Skip to content

Commit cfe07ec

Browse files
committed
Merge pull request #7 with some additional changes.
2 parents 14da675 + 543ae39 commit cfe07ec

File tree

10 files changed

+561
-131
lines changed

10 files changed

+561
-131
lines changed

.hgignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ tags
55
_trial_temp
66
.mo
77
build/*
8+
env
9+
.DS_Store
810
.idea/

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Other contributors are (in alphabetical order):
1010
* Martha Girdler <martha at cheezburger dot com>
1111
* Eike Hein <sho at eikehein dot com>
1212
* Allison Kaptur <allison dot kaptur at gmail dot com>
13+
* Jason Laster <jason dot laster dot 11 at gmail dot com>
1314
* Brandon Navra <brandon dot navra at gmail dot com>
1415
* Michele Orrù <maker dot py at gmail dot com>
1516
* Pavel Panchekha <pavpanchekha at gmail dot com>

bpython/autocomplete.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# The MIT License
2+
#
3+
# Copyright (c) 2009-2012 the bpython authors.
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
#
23+
24+
import __builtin__
25+
import __main__
26+
import rlcompleter
27+
import re
28+
from bpython import inspection
29+
30+
# Needed for special handling of __abstractmethods__
31+
# abc only exists since 2.6, so check both that it exists and that it's
32+
# the one we're expecting
33+
try:
34+
import abc
35+
abc.ABCMeta
36+
has_abc = True
37+
except (ImportError, AttributeError):
38+
has_abc = False
39+
40+
# Autocomplete modes
41+
SIMPLE = 'simple'
42+
SUBSTRING = 'substring'
43+
FUZZY = 'fuzzy'
44+
45+
class Autocomplete(rlcompleter.Completer):
46+
"""
47+
"""
48+
49+
def __init__(self, namespace = None, config = None):
50+
rlcompleter.Completer.__init__(self, namespace)
51+
self.locals = namespace
52+
if hasattr(config, 'autocomplete_mode'):
53+
self.autocomplete_mode = config.autocomplete_mode
54+
else:
55+
self.autocomplete_mode = SUBSTRING
56+
57+
def attr_matches(self, text):
58+
"""Taken from rlcompleter.py and bent to my will.
59+
"""
60+
61+
# Gna, Py 2.6's rlcompleter searches for __call__ inside the
62+
# instance instead of the type, so we monkeypatch to prevent
63+
# side-effects (__getattr__/__getattribute__)
64+
m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
65+
if not m:
66+
return []
67+
68+
expr, attr = m.group(1, 3)
69+
if expr.isdigit():
70+
# Special case: float literal, using attrs here will result in
71+
# a SyntaxError
72+
return []
73+
obj = eval(expr, self.locals)
74+
with inspection.AttrCleaner(obj):
75+
matches = self.attr_lookup(obj, expr, attr)
76+
return matches
77+
78+
def attr_lookup(self, obj, expr, attr):
79+
"""Second half of original attr_matches method factored out so it can
80+
be wrapped in a safe try/finally block in case anything bad happens to
81+
restore the original __getattribute__ method."""
82+
words = dir(obj)
83+
if hasattr(obj, '__class__'):
84+
words.append('__class__')
85+
words = words + rlcompleter.get_class_members(obj.__class__)
86+
if has_abc and not isinstance(obj.__class__, abc.ABCMeta):
87+
try:
88+
words.remove('__abstractmethods__')
89+
except ValueError:
90+
pass
91+
92+
matches = []
93+
n = len(attr)
94+
for word in words:
95+
if self.method_match(word, n, attr) and word != "__builtins__":
96+
matches.append("%s.%s" % (expr, word))
97+
return matches
98+
99+
def _callable_postfix(self, value, word):
100+
"""rlcompleter's _callable_postfix done right."""
101+
with inspection.AttrCleaner(value):
102+
if inspection.is_callable(value):
103+
word += '('
104+
return word
105+
106+
def global_matches(self, text):
107+
"""Compute matches when text is a simple name.
108+
Return a list of all keywords, built-in functions and names currently
109+
defined in self.namespace that match.
110+
"""
111+
112+
hash = {}
113+
n = len(text)
114+
import keyword
115+
for word in keyword.kwlist:
116+
if self.method_match(word, n, text):
117+
hash[word] = 1
118+
for nspace in [__builtin__.__dict__, self.namespace]:
119+
for word, val in nspace.items():
120+
if self.method_match(word, len(text), text) and word != "__builtins__":
121+
hash[self._callable_postfix(val, word)] = 1
122+
matches = hash.keys()
123+
matches.sort()
124+
return matches
125+
126+
def method_match(self, word, size, text):
127+
if self.autocomplete_mode == SIMPLE:
128+
return word[:size] == text
129+
elif self.autocomplete_mode == SUBSTRING:
130+
s = r'.*%s.*' % text
131+
return re.search(s, word)
132+
else:
133+
s = r'.*%s.*' % '.*'.join(list(text))
134+
return re.search(s, word)
135+

0 commit comments

Comments
 (0)