ipy_completer.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #+
  2. #
  3. # This file is part of h5py, a low-level Python interface to the HDF5 library.
  4. #
  5. # Contributed by Darren Dale
  6. #
  7. # Copyright (C) 2009 Darren Dale
  8. #
  9. # http://h5py.org
  10. # License: BSD (See LICENSE.txt for full license)
  11. #
  12. #-
  13. # pylint: disable=eval-used,protected-access
  14. """
  15. This is the h5py completer extension for ipython. It is loaded by
  16. calling the function h5py.enable_ipython_completer() from within an
  17. interactive IPython session.
  18. It will let you do things like::
  19. f=File('foo.h5')
  20. f['<tab>
  21. # or:
  22. f['ite<tab>
  23. which will do tab completion based on the subgroups of `f`. Also::
  24. f['item1'].at<tab>
  25. will perform tab completion for the attributes in the usual way. This should
  26. also work::
  27. a = b = f['item1'].attrs.<tab>
  28. as should::
  29. f['item1/item2/it<tab>
  30. """
  31. import posixpath
  32. import re
  33. from ._hl.attrs import AttributeManager
  34. from ._hl.base import HLObject
  35. from IPython import get_ipython
  36. from IPython.core.error import TryNext
  37. from IPython.utils import generics
  38. re_attr_match = re.compile(r"(?:.*\=)?(.+\[.*\].*)\.(\w*)$")
  39. re_item_match = re.compile(r"""(?:.*\=)?(.*)\[(?P<s>['|"])(?!.*(?P=s))(.*)$""")
  40. re_object_match = re.compile(r"(?:.*\=)?(.+?)(?:\[)")
  41. def _retrieve_obj(name, context):
  42. """ Filter function for completion. """
  43. # we don't want to call any functions, but I couldn't find a robust regex
  44. # that filtered them without unintended side effects. So keys containing
  45. # "(" will not complete.
  46. if '(' in name:
  47. raise ValueError()
  48. return eval(name, context.user_ns)
  49. def h5py_item_completer(context, command):
  50. """Compute possible item matches for dict-like objects"""
  51. base, item = re_item_match.split(command)[1:4:2]
  52. try:
  53. obj = _retrieve_obj(base, context)
  54. except Exception:
  55. return []
  56. path, _ = posixpath.split(item)
  57. try:
  58. if path:
  59. items = (posixpath.join(path, name) for name in obj[path].keys())
  60. else:
  61. items = obj.keys()
  62. except AttributeError:
  63. return []
  64. items = list(items)
  65. return [i for i in items if i[:len(item)] == item]
  66. def h5py_attr_completer(context, command):
  67. """Compute possible attr matches for nested dict-like objects"""
  68. base, attr = re_attr_match.split(command)[1:3]
  69. base = base.strip()
  70. try:
  71. obj = _retrieve_obj(base, context)
  72. except Exception:
  73. return []
  74. attrs = dir(obj)
  75. try:
  76. attrs = generics.complete_object(obj, attrs)
  77. except TryNext:
  78. pass
  79. try:
  80. # support >=ipython-0.12
  81. omit__names = get_ipython().Completer.omit__names
  82. except AttributeError:
  83. omit__names = 0
  84. if omit__names == 1:
  85. attrs = [a for a in attrs if not a.startswith('__')]
  86. elif omit__names == 2:
  87. attrs = [a for a in attrs if not a.startswith('_')]
  88. return ["%s.%s" % (base, a) for a in attrs if a[:len(attr)] == attr]
  89. def h5py_completer(self, event):
  90. """ Completer function to be loaded into IPython """
  91. base = re_object_match.split(event.line)[1]
  92. try:
  93. obj = self._ofind(base).obj
  94. except AttributeError:
  95. obj = self._ofind(base).get('obj')
  96. if not isinstance(obj, (AttributeManager, HLObject)):
  97. raise TryNext
  98. try:
  99. return h5py_attr_completer(self, event.line)
  100. except ValueError:
  101. pass
  102. try:
  103. return h5py_item_completer(self, event.line)
  104. except ValueError:
  105. pass
  106. return []
  107. def load_ipython_extension(ip=None):
  108. """ Load completer function into IPython """
  109. if ip is None:
  110. ip = get_ipython()
  111. ip.set_hook('complete_command', h5py_completer, re_key=r"(?:.*\=)?(.+?)\[")