forked from h5py/h5py
/
ipy_completer.py
195 lines (150 loc) · 4.81 KB
/
ipy_completer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#+
#
# This file is part of h5py, a low-level Python interface to the HDF5 library.
#
# Contributed by Darren Dale
#
# Copyright (C) 2009 Darren Dale
#
# http://h5py.alfven.org
# License: BSD (See LICENSE.txt for full license)
#
#-
# pylint: disable=eval-used,protected-access
"""
This is the h5py completer extension for ipython. It is loaded by
calling the function h5py.enable_ipython_completer() from within an
interactive IPython session.
It will let you do things like::
f=File('foo.h5')
f['<tab>
# or:
f['ite<tab>
which will do tab completion based on the subgroups of `f`. Also::
f['item1'].at<tab>
will perform tab completion for the attributes in the usual way. This should
also work::
a = b = f['item1'].attrs.<tab>
as should::
f['item1/item2/it<tab>
"""
from __future__ import absolute_import
import posixpath
import re
import readline
from ._hl.attrs import AttributeManager
from ._hl.base import HLObject
try:
# >=ipython-1.0
from IPython import get_ipython
except ImportError:
try:
# support >=ipython-0.11, <ipython-1.0
from IPython.core.ipapi import get as get_ipython
except ImportError:
# support <ipython-0.11
from IPython.ipapi import get as get_ipython
try:
# support >=ipython-0.11
from IPython.utils import generics
except ImportError:
# support <ipython-0.11
from IPython import generics
try:
from IPython.core.error import TryNext
except ImportError:
try:
from IPython import TryNext
except ImportError:
from IPython.ipapi import TryNext
re_attr_match = re.compile(r"(?:.*\=)?(.+\[.*\].*)\.(\w*)$")
re_item_match = re.compile(r"""(?:.*\=)?(.*)\[(?P<s>['|"])(?!.*(?P=s))(.*)$""")
re_object_match = re.compile(r"(?:.*\=)?(.+?)(?:\[)")
def _retrieve_obj(name, context):
""" Filter function for completion. """
# we don't want to call any functions, but I couldn't find a robust regex
# that filtered them without unintended side effects. So keys containing
# "(" will not complete.
if '(' in name:
raise ValueError()
try:
# older versions of IPython:
obj = eval(name, context.shell.user_ns)
except AttributeError:
# as of IPython-1.0:
obj = eval(name, context.user_ns)
return obj
def h5py_item_completer(context, command):
"""Compute possible item matches for dict-like objects"""
base, item = re_item_match.split(command)[1:4:2]
try:
obj = _retrieve_obj(base, context)
except Exception:
return []
path, _ = posixpath.split(item)
try:
if path:
items = (posixpath.join(path, name) for name in obj[path].keys())
else:
items = obj.keys()
except AttributeError:
return []
items = list(items)
readline.set_completer_delims(' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?')
return [i for i in items if i[:len(item)] == item]
def h5py_attr_completer(context, command):
"""Compute possible attr matches for nested dict-like objects"""
base, attr = re_attr_match.split(command)[1:3]
base = base.strip()
try:
obj = _retrieve_obj(base, context)
except Exception:
return []
attrs = dir(obj)
try:
attrs = generics.complete_object(obj, attrs)
except TryNext:
pass
omit__names = None
try:
# support >=ipython-0.12
omit__names = get_ipython().Completer.omit__names
except AttributeError:
pass
if omit__names is None:
try:
# support ipython-0.11
omit__names = get_ipython().readline_omit__names
except AttributeError:
pass
if omit__names is None:
try:
# support <ipython-0.11
omit__names = get_ipython().options.readline_omit__names
except AttributeError:
omit__names = 0
if omit__names == 1:
attrs = [a for a in attrs if not a.startswith('__')]
elif omit__names == 2:
attrs = [a for a in attrs if not a.startswith('_')]
readline.set_completer_delims(' =')
return ["%s.%s" % (base, a) for a in attrs if a[:len(attr)] == attr]
def h5py_completer(self, event):
""" Completer function to be loaded into IPython """
base = re_object_match.split(event.line)[1]
if not isinstance(self._ofind(base)['obj'], (AttributeManager, HLObject)):
raise TryNext
try:
return h5py_attr_completer(self, event.line)
except ValueError:
pass
try:
return h5py_item_completer(self, event.line)
except ValueError:
pass
return []
def load_ipython_extension(ip=None):
""" Load completer function into IPython """
if ip is None:
ip = get_ipython()
ip.set_hook('complete_command', h5py_completer, re_key=r"(?:.*\=)?(.+?)\[")