Skip to content

Commit 4d26621

Browse files
committed
Move attr_{matches,lookup} to AttrCompleter
Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
1 parent e83fb4a commit 4d26621

File tree

1 file changed

+49
-51
lines changed

1 file changed

+49
-51
lines changed

bpython/autocomplete.py

Lines changed: 49 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ def format(self, filename):
199199
return filename
200200

201201

202+
attr_matches_re = LazyReCompile(r"(\w+(\.\w+)*)\.(\w*)")
203+
204+
202205
class AttrCompletion(BaseCompletionType):
203206

204207
def matches(self, cursor_offset, line, **kwargs):
@@ -222,7 +225,7 @@ def matches(self, cursor_offset, line, **kwargs):
222225
break
223226
methodtext = text[-i:]
224227
matches = set(''.join([text[:-i], m])
225-
for m in attr_matches(methodtext, locals_))
228+
for m in self.attr_matches(methodtext, locals_))
226229

227230
# TODO add open paren for methods via _callable_prefix (or decide not
228231
# to) unless the first character is a _ filter out all attributes
@@ -238,6 +241,51 @@ def locate(self, current_offset, line):
238241
def format(self, word):
239242
return after_last_dot(word)
240243

244+
def attr_matches(self, text, namespace):
245+
"""Taken from rlcompleter.py and bent to my will.
246+
"""
247+
248+
# Gna, Py 2.6's rlcompleter searches for __call__ inside the
249+
# instance instead of the type, so we monkeypatch to prevent
250+
# side-effects (__getattr__/__getattribute__)
251+
m = attr_matches_re.match(text)
252+
if not m:
253+
return []
254+
255+
expr, attr = m.group(1, 3)
256+
if expr.isdigit():
257+
# Special case: float literal, using attrs here will result in
258+
# a SyntaxError
259+
return []
260+
try:
261+
obj = safe_eval(expr, namespace)
262+
except EvaluationError:
263+
return []
264+
with inspection.AttrCleaner(obj):
265+
matches = self.attr_lookup(obj, expr, attr)
266+
return matches
267+
268+
def attr_lookup(self, obj, expr, attr):
269+
"""Second half of original attr_matches method factored out so it can
270+
be wrapped in a safe try/finally block in case anything bad happens to
271+
restore the original __getattribute__ method."""
272+
words = dir(obj)
273+
if hasattr(obj, '__class__'):
274+
words.append('__class__')
275+
words = words + rlcompleter.get_class_members(obj.__class__)
276+
if not isinstance(obj.__class__, abc.ABCMeta):
277+
try:
278+
words.remove('__abstractmethods__')
279+
except ValueError:
280+
pass
281+
282+
matches = []
283+
n = len(attr)
284+
for word in words:
285+
if method_match(word, n, attr) and word != "__builtins__":
286+
matches.append("%s.%s" % (expr, word))
287+
return matches
288+
241289

242290
class DictKeyCompletion(BaseCompletionType):
243291

@@ -498,56 +546,6 @@ def safe_eval(expr, namespace):
498546
raise EvaluationError
499547

500548

501-
attr_matches_re = LazyReCompile(r"(\w+(\.\w+)*)\.(\w*)")
502-
503-
504-
def attr_matches(text, namespace):
505-
"""Taken from rlcompleter.py and bent to my will.
506-
"""
507-
508-
# Gna, Py 2.6's rlcompleter searches for __call__ inside the
509-
# instance instead of the type, so we monkeypatch to prevent
510-
# side-effects (__getattr__/__getattribute__)
511-
m = attr_matches_re.match(text)
512-
if not m:
513-
return []
514-
515-
expr, attr = m.group(1, 3)
516-
if expr.isdigit():
517-
# Special case: float literal, using attrs here will result in
518-
# a SyntaxError
519-
return []
520-
try:
521-
obj = safe_eval(expr, namespace)
522-
except EvaluationError:
523-
return []
524-
with inspection.AttrCleaner(obj):
525-
matches = attr_lookup(obj, expr, attr)
526-
return matches
527-
528-
529-
def attr_lookup(obj, expr, attr):
530-
"""Second half of original attr_matches method factored out so it can
531-
be wrapped in a safe try/finally block in case anything bad happens to
532-
restore the original __getattribute__ method."""
533-
words = dir(obj)
534-
if hasattr(obj, '__class__'):
535-
words.append('__class__')
536-
words = words + rlcompleter.get_class_members(obj.__class__)
537-
if not isinstance(obj.__class__, abc.ABCMeta):
538-
try:
539-
words.remove('__abstractmethods__')
540-
except ValueError:
541-
pass
542-
543-
matches = []
544-
n = len(attr)
545-
for word in words:
546-
if method_match(word, n, attr) and word != "__builtins__":
547-
matches.append("%s.%s" % (expr, word))
548-
return matches
549-
550-
551549
def _callable_postfix(value, word):
552550
"""rlcompleter's _callable_postfix done right."""
553551
with inspection.AttrCleaner(value):

0 commit comments

Comments
 (0)