X Tutup
Skip to content

Commit 64dd9de

Browse files
committed
Use sets everywhere
… and make sure autocompletion results are sorted Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
1 parent 6a29a44 commit 64dd9de

File tree

2 files changed

+28
-25
lines changed

2 files changed

+28
-25
lines changed

bpython/autocomplete.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,15 @@ def matches(self, cursor_offset, line, **kwargs):
152152
if cs is None:
153153
return None
154154
start, end, text = cs
155-
matches = []
155+
matches = set()
156156
username = text.split(os.path.sep, 1)[0]
157157
user_dir = os.path.expanduser(username)
158158
for filename in glob(os.path.expanduser(text + '*')):
159159
if os.path.isdir(filename):
160160
filename += os.path.sep
161161
if text.startswith('~'):
162162
filename = username + filename[len(user_dir):]
163-
matches.append(filename)
163+
matches.add(filename)
164164
return matches
165165

166166
def locate(self, current_offset, line):
@@ -191,14 +191,14 @@ def matches(self, cursor_offset, line, locals_, **kwargs):
191191
i -= 1
192192
break
193193
methodtext = text[-i:]
194-
matches = [''.join([text[:-i], m]) for m in
195-
attr_matches(methodtext, locals_)]
194+
matches = set(''.join([text[:-i], m])
195+
for m in attr_matches(methodtext, locals_))
196196

197197
#TODO add open paren for methods via _callable_prefix (or decide not to)
198198
# unless the first character is a _ filter out all attributes starting with a _
199199
if not text.split('.')[-1].startswith('_'):
200-
matches = [match for match in matches
201-
if not match.split('.')[-1].startswith('_')]
200+
matches = set(match for match in matches
201+
if not match.split('.')[-1].startswith('_'))
202202
return matches
203203

204204
def locate(self, current_offset, line):
@@ -218,11 +218,12 @@ def matches(self, cursor_offset, line, locals_, **kwargs):
218218
try:
219219
obj = safe_eval(dexpr, locals_)
220220
except EvaluationError:
221-
return []
221+
return set()
222222
if obj and isinstance(obj, type({})) and obj.keys():
223-
return ["{!r}]".format(k) for k in obj.keys() if repr(k).startswith(orig)]
223+
return set("{!r}".format(k) for k in obj.keys()
224+
if repr(k).startswith(orig))
224225
else:
225-
return []
226+
return set()
226227

227228
def locate(self, current_offset, line):
228229
return lineparts.current_dict_key(current_offset, line)
@@ -239,7 +240,7 @@ def matches(self, cursor_offset, line, current_block, **kwargs):
239240
if 'class' not in current_block:
240241
return None
241242
start, end, word = r
242-
return [name for name in MAGIC_METHODS if name.startswith(word)]
243+
return set(name for name in MAGIC_METHODS if name.startswith(word))
243244

244245
def locate(self, current_offset, line):
245246
return lineparts.current_method_definition_name(current_offset, line)
@@ -256,17 +257,15 @@ def matches(self, cursor_offset, line, locals_, **kwargs):
256257
return None
257258
start, end, text = r
258259

259-
hash = {}
260+
matches = set()
260261
n = len(text)
261262
for word in keyword.kwlist:
262263
if method_match(word, n, text):
263-
hash[word] = 1
264+
matches.add(word)
264265
for nspace in [__builtin__.__dict__, locals_]:
265266
for word, val in nspace.items():
266267
if method_match(word, len(text), text) and word != "__builtins__":
267-
hash[_callable_postfix(val, word)] = 1
268-
matches = hash.keys()
269-
matches.sort()
268+
matches.add(_callable_postfix(val, word))
270269
return matches
271270

272271
def locate(self, current_offset, line):
@@ -282,10 +281,11 @@ def matches(self, cursor_offset, line, argspec, **kwargs):
282281
return None
283282
start, end, word = r
284283
if argspec:
285-
matches = [name + '=' for name in argspec[1][0]
286-
if isinstance(name, basestring) and name.startswith(word)]
284+
matches = set(name + '=' for name in argspec[1][0]
285+
if isinstance(name, basestring) and
286+
name.startswith(word))
287287
if py3:
288-
matches.extend(name + '=' for name in argspec[1][4]
288+
matches.update(name + '=' for name in argspec[1][4]
289289
if name.startswith(word))
290290
return matches
291291

@@ -300,9 +300,9 @@ def matches(self, cursor_offset, line, **kwargs):
300300
return None
301301
start, end, word = r
302302
attrs = dir('')
303-
matches = [att for att in attrs if att.startswith(word)]
303+
matches = set(att for att in attrs if att.startswith(word))
304304
if not word.startswith('_'):
305-
return [match for match in matches if not match.startswith('_')]
305+
return set(match for match in matches if not match.startswith('_'))
306306
return matches
307307

308308
def locate(self, current_offset, line):
@@ -329,7 +329,7 @@ def get_completer(completers, cursor_offset, line, **kwargs):
329329
for completer in completers:
330330
matches = completer.matches(cursor_offset, line, **kwargs)
331331
if matches is not None:
332-
return matches, (completer if matches else None)
332+
return sorted(matches), (completer if matches else None)
333333
return [], None
334334

335335
BPYTHON_COMPLETER = (

bpython/test/test_autocomplete.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,28 +114,31 @@ def test_match_returns_none_if_not_in_string(self):
114114

115115
@mock.patch('bpython.autocomplete.glob', new=lambda text: [])
116116
def test_match_returns_empty_list_when_no_files(self):
117-
self.assertEqual(self.completer.matches(2, '"a'), [])
117+
self.assertEqual(self.completer.matches(2, '"a'), set())
118118

119119
@mock.patch('bpython.autocomplete.glob', new=lambda text: ['abcde', 'aaaaa'])
120120
@mock.patch('os.path.expanduser', new=lambda text: text)
121121
@mock.patch('os.path.isdir', new=lambda text: False)
122122
@mock.patch('os.path.sep', new='/')
123123
def test_match_returns_files_when_files_exist(self):
124-
self.assertEqual(self.completer.matches(2, '"x'), ['abcde', 'aaaaa'])
124+
self.assertEqual(sorted(self.completer.matches(2, '"x')),
125+
['aaaaa', 'abcde'])
125126

126127
@mock.patch('bpython.autocomplete.glob', new=lambda text: ['abcde', 'aaaaa'])
127128
@mock.patch('os.path.expanduser', new=lambda text: text)
128129
@mock.patch('os.path.isdir', new=lambda text: True)
129130
@mock.patch('os.path.sep', new='/')
130131
def test_match_returns_dirs_when_dirs_exist(self):
131-
self.assertEqual(self.completer.matches(2, '"x'), ['abcde/', 'aaaaa/'])
132+
self.assertEqual(sorted(self.completer.matches(2, '"x')),
133+
['aaaaa/', 'abcde/'])
132134

133135
@mock.patch('bpython.autocomplete.glob', new=lambda text: ['/expand/ed/abcde', '/expand/ed/aaaaa'])
134136
@mock.patch('os.path.expanduser', new=lambda text: text.replace('~', '/expand/ed'))
135137
@mock.patch('os.path.isdir', new=lambda text: False)
136138
@mock.patch('os.path.sep', new='/')
137139
def test_tilde_stays_pretty(self):
138-
self.assertEqual(self.completer.matches(4, '"~/a'), ['~/abcde', '~/aaaaa'])
140+
self.assertEqual(sorted(self.completer.matches(4, '"~/a')),
141+
['~/aaaaa', '~/abcde'])
139142

140143
@mock.patch('os.path.sep', new='/')
141144
def test_formatting_takes_just_last_part(self):

0 commit comments

Comments
 (0)
X Tutup