Skip to content

Commit 66d7b52

Browse files
committed
Refactoring with named tuples
1 parent bd2002a commit 66d7b52

File tree

2 files changed

+37
-43
lines changed

2 files changed

+37
-43
lines changed

bpython/autocomplete.py

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
# The MIT License
44
#
5-
# Copyright (c) 2009-2015 the bpython authors.
65
#
76
# Permission is hereby granted, free of charge, to any person obtaining a copy
87
# of this software and associated documentation files (the "Software"), to deal
@@ -39,6 +38,7 @@
3938
from bpython import inspection
4039
from bpython import importcompletion
4140
from bpython import line as lineparts
41+
from bpython.line import LinePart
4242
from bpython._py3compat import py3, try_decode
4343
from bpython.lazyre import LazyReCompile
4444

@@ -126,8 +126,8 @@ def format(self, word):
126126

127127
def substitute(self, cursor_offset, line, match):
128128
"""Returns a cursor offset and line with match swapped in"""
129-
start, end, word = self.locate(cursor_offset, line)
130-
result = start + len(match), line[:start] + match + line[end:]
129+
lpart = self.locate(cursor_offset, line)
130+
result = lpart.start + len(match), line[:lpart.start] + match + line[lpart.end:]
131131
return result
132132

133133
@property
@@ -200,14 +200,13 @@ def matches(self, cursor_offset, line, **kwargs):
200200
cs = lineparts.current_string(cursor_offset, line)
201201
if cs is None:
202202
return None
203-
start, end, text = cs
204203
matches = set()
205-
username = text.split(os.path.sep, 1)[0]
204+
username = cs.word.split(os.path.sep, 1)[0]
206205
user_dir = os.path.expanduser(username)
207-
for filename in self.safe_glob(os.path.expanduser(text)):
206+
for filename in self.safe_glob(os.path.expanduser(cs.word)):
208207
if os.path.isdir(filename):
209208
filename += os.path.sep
210-
if text.startswith('~'):
209+
if cs.word.startswith('~'):
211210
filename = username + filename[len(user_dir):]
212211
matches.add(filename)
213212
return matches
@@ -235,25 +234,24 @@ def matches(self, cursor_offset, line, **kwargs):
235234
r = self.locate(cursor_offset, line)
236235
if r is None:
237236
return None
238-
text = r[2]
239237

240238
if locals_ is None:
241239
locals_ = __main__.__dict__
242240

243-
assert '.' in text
241+
assert '.' in r.word
244242

245-
for i in range(1, len(text) + 1):
246-
if text[-i] == '[':
243+
for i in range(1, len(r.word) + 1):
244+
if r.word[-i] == '[':
247245
i -= 1
248246
break
249-
methodtext = text[-i:]
250-
matches = set(''.join([text[:-i], m])
247+
methodtext = r.word[-i:]
248+
matches = set(''.join([r.word[:-i], m])
251249
for m in self.attr_matches(methodtext, locals_))
252250

253251
# TODO add open paren for methods via _callable_prefix (or decide not
254252
# to) unless the first character is a _ filter out all attributes
255253
# starting with a _
256-
if not text.split('.')[-1].startswith('_'):
254+
if not r.word.split('.')[-1].startswith('_'):
257255
matches = set(match for match in matches
258256
if not match.split('.')[-1].startswith('_'))
259257
return matches
@@ -340,15 +338,14 @@ def matches(self, cursor_offset, line, **kwargs):
340338
r = self.locate(cursor_offset, line)
341339
if r is None:
342340
return None
343-
start, end, orig = r
344341
_, _, dexpr = lineparts.current_dict(cursor_offset, line)
345342
try:
346343
obj = safe_eval(dexpr, locals_)
347344
except EvaluationError:
348345
return set()
349346
if isinstance(obj, dict) and obj.keys():
350347
return set("{0!r}]".format(k) for k in obj.keys()
351-
if repr(k).startswith(orig))
348+
if repr(k).startswith(r.word))
352349
else:
353350
return set()
354351

@@ -371,8 +368,7 @@ def matches(self, cursor_offset, line, **kwargs):
371368
return None
372369
if 'class' not in current_block:
373370
return None
374-
start, end, word = r
375-
return set(name for name in MAGIC_METHODS if name.startswith(word))
371+
return set(name for name in MAGIC_METHODS if name.startswith(r.word))
376372

377373
def locate(self, current_offset, line):
378374
return lineparts.current_method_definition_name(current_offset, line)
@@ -392,20 +388,19 @@ def matches(self, cursor_offset, line, **kwargs):
392388
r = self.locate(cursor_offset, line)
393389
if r is None:
394390
return None
395-
start, end, text = r
396391

397392
matches = set()
398-
n = len(text)
393+
n = len(r.word)
399394
for word in KEYWORDS:
400-
if self.method_match(word, n, text):
395+
if self.method_match(word, n, r.word):
401396
matches.add(word)
402397
for nspace in (builtins.__dict__, locals_):
403398
for word, val in iteritems(nspace):
404399
word = try_decode(word, 'ascii')
405400
# if identifier isn't ascii, don't complete (syntax error)
406401
if word is None:
407402
continue
408-
if self.method_match(word, n, text) and word != "__builtins__":
403+
if self.method_match(word, n, r.word) and word != "__builtins__":
409404
matches.add(_callable_postfix(val, word))
410405
return matches
411406

@@ -425,14 +420,13 @@ def matches(self, cursor_offset, line, **kwargs):
425420
r = self.locate(cursor_offset, line)
426421
if r is None:
427422
return None
428-
start, end, word = r
429423
if argspec:
430424
matches = set(name + '=' for name in argspec[1][0]
431425
if isinstance(name, string_types) and
432-
name.startswith(word))
426+
name.startswith(r.word))
433427
if py3:
434428
matches.update(name + '=' for name in argspec[1][4]
435-
if name.startswith(word))
429+
if name.startswith(r.word))
436430
return matches
437431

438432
def locate(self, current_offset, line):
@@ -446,14 +440,13 @@ def matches(self, cursor_offset, line, **kwargs):
446440
if r is None:
447441
return None
448442

449-
start, end, word = r
450443
attrs = dir('')
451444
if not py3:
452445
# decode attributes
453446
attrs = (att.decode('ascii') for att in attrs)
454447

455-
matches = set(att for att in attrs if att.startswith(word))
456-
if not word.startswith('_'):
448+
matches = set(att for att in attrs if att.startswith(r.word))
449+
if not r.word.startswith('_'):
457450
return set(match for match in matches if not match.startswith('_'))
458451
return matches
459452

@@ -513,7 +506,7 @@ def matches(self, cursor_offset, line, **kwargs):
513506
def locate(self, cursor_offset, line):
514507
start = self._orig_start
515508
end = cursor_offset
516-
return start, end, line[start:end]
509+
return LinePart(start, end, line[start:end])
517510

518511
class MultilineJediCompletion(JediCompletion):
519512
def matches(self, cursor_offset, line, **kwargs):

bpython/line.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
word."""
66

77
from itertools import chain
8+
from collections import namedtuple
89
from bpython.lazyre import LazyReCompile
910

10-
1111
current_word_re = LazyReCompile(r'[\w_][\w0-9._]*[(]?')
12+
LinePart = namedtuple('LinePart', ['start', 'stop', 'word'])
1213

1314

1415
def current_word(cursor_offset, line):
@@ -25,7 +26,7 @@ def current_word(cursor_offset, line):
2526
word = m.group()
2627
if word is None:
2728
return None
28-
return (start, end, word)
29+
return LinePart(start, end, word)
2930

3031

3132
current_dict_key_re = LazyReCompile(r'''[\w_][\w0-9._]*\[([\w0-9._(), '"]*)''')
@@ -36,7 +37,7 @@ def current_dict_key(cursor_offset, line):
3637
matches = current_dict_key_re.finditer(line)
3738
for m in matches:
3839
if m.start(1) <= cursor_offset and m.end(1) >= cursor_offset:
39-
return (m.start(1), m.end(1), m.group(1))
40+
return LinePart(m.start(1), m.end(1), m.group(1))
4041
return None
4142

4243

@@ -48,7 +49,7 @@ def current_dict(cursor_offset, line):
4849
matches = current_dict_re.finditer(line)
4950
for m in matches:
5051
if m.start(2) <= cursor_offset and m.end(2) >= cursor_offset:
51-
return (m.start(1), m.end(1), m.group(1))
52+
return LinePart(m.start(1), m.end(1), m.group(1))
5253
return None
5354

5455

@@ -66,7 +67,7 @@ def current_string(cursor_offset, line):
6667
for m in current_string_re.finditer(line):
6768
i = 3 if m.group(3) else 4
6869
if m.start(i) <= cursor_offset and m.end(i) >= cursor_offset:
69-
return m.start(i), m.end(i), m.group(i)
70+
return LinePart(m.start(i), m.end(i), m.group(i))
7071
return None
7172

7273

@@ -89,7 +90,7 @@ def current_object(cursor_offset, line):
8990
s += m.group(1)
9091
if not s:
9192
return None
92-
return start, start+len(s), s
93+
return LinePart(start, start+len(s), s)
9394

9495

9596
current_object_attribute_re = LazyReCompile(r'([\w_][\w0-9_]*)[.]?')
@@ -106,7 +107,7 @@ def current_object_attribute(cursor_offset, line):
106107
for m in matches:
107108
if (m.start(1) + start <= cursor_offset and
108109
m.end(1) + start >= cursor_offset):
109-
return m.start(1) + start, m.end(1) + start, m.group(1)
110+
return LinePart(m.start(1) + start, m.end(1) + start, m.group(1))
110111
return None
111112

112113

@@ -128,7 +129,7 @@ def current_from_import_from(cursor_offset, line):
128129
for m in matches:
129130
if ((m.start(1) < cursor_offset and m.end(1) >= cursor_offset) or
130131
(m.start(2) < cursor_offset and m.end(2) >= cursor_offset)):
131-
return m.start(1), m.end(1), m.group(1)
132+
return LinePart(m.start(1), m.end(1), m.group(1))
132133
return None
133134

134135

@@ -153,7 +154,7 @@ def current_from_import_import(cursor_offset, line):
153154
start = baseline.end() + m.start(1)
154155
end = baseline.end() + m.end(1)
155156
if start < cursor_offset and end >= cursor_offset:
156-
return start, end, m.group(1)
157+
return LinePart(start, end, m.group(1))
157158
return None
158159

159160

@@ -175,7 +176,7 @@ def current_import(cursor_offset, line):
175176
start = baseline.end() + m.start(1)
176177
end = baseline.end() + m.end(1)
177178
if start < cursor_offset and end >= cursor_offset:
178-
return start, end, m.group(1)
179+
return LinePart(start, end, m.group(1))
179180

180181

181182
current_method_definition_name_re = LazyReCompile("def\s+([a-zA-Z_][\w]*)")
@@ -186,7 +187,7 @@ def current_method_definition_name(cursor_offset, line):
186187
matches = current_method_definition_name_re.finditer(line)
187188
for m in matches:
188189
if (m.start(1) <= cursor_offset and m.end(1) >= cursor_offset):
189-
return m.start(1), m.end(1), m.group(1)
190+
return LinePart(m.start(1), m.end(1), m.group(1))
190191
return None
191192

192193

@@ -198,7 +199,7 @@ def current_single_word(cursor_offset, line):
198199
matches = current_single_word_re.finditer(line)
199200
for m in matches:
200201
if m.start(1) <= cursor_offset and m.end(1) >= cursor_offset:
201-
return m.start(1), m.end(1), m.group(1)
202+
return LinePart(m.start(1), m.end(1), m.group(1))
202203
return None
203204

204205

@@ -209,7 +210,7 @@ def current_dotted_attribute(cursor_offset, line):
209210
return None
210211
start, end, word = match
211212
if '.' in word[1:]:
212-
return start, end, word
213+
return LinePart(start, end, word)
213214

214215

215216
current_string_literal_attr_re = LazyReCompile(
@@ -223,5 +224,5 @@ def current_string_literal_attr(cursor_offset, line):
223224
matches = current_string_literal_attr_re.finditer(line)
224225
for m in matches:
225226
if m.start(4) <= cursor_offset and m.end(4) >= cursor_offset:
226-
return m.start(4), m.end(4), m.group(4)
227+
return LinePart(m.start(4), m.end(4), m.group(4))
227228
return None

0 commit comments

Comments
 (0)