Skip to content

Commit d9305d7

Browse files
Mypy types for completion (#928)
* Mypy types for completion We're not checking these in CI nor are we providing a config file yet. I used mypy 0.910 in Python 3.6 run directly on bpython/autocomplete.py and still had 3 errors after these changes.
1 parent 2308a61 commit d9305d7

File tree

1 file changed

+31
-16
lines changed

1 file changed

+31
-16
lines changed

bpython/autocomplete.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import builtins
3434

3535
from enum import Enum
36-
from typing import Any, Dict, Iterator, List, Match, NoReturn, Set, Union
36+
from typing import Any, Dict, Iterator, List, Match, NoReturn, Set, Union, Tuple
3737
from . import inspection
3838
from . import line as lineparts
3939
from .line import LinePart
@@ -180,7 +180,7 @@ def few_enough_underscores(current, match) -> bool:
180180
return not match.startswith("_")
181181

182182

183-
def method_match_none(word, size, text) -> False:
183+
def method_match_none(word, size, text) -> bool:
184184
return False
185185

186186

@@ -214,7 +214,10 @@ def __init__(
214214
self._shown_before_tab = shown_before_tab
215215
self.method_match = MODES_MAP[mode]
216216

217-
def matches(self, cursor_offset, line, **kwargs) -> NoReturn:
217+
@abc.abstractmethod
218+
def matches(
219+
self, cursor_offset: int, line: str, **kwargs
220+
) -> Union[Set[str], None]:
218221
"""Returns a list of possible matches given a line and cursor, or None
219222
if this completion type isn't applicable.
220223
@@ -232,7 +235,8 @@ def matches(self, cursor_offset, line, **kwargs) -> NoReturn:
232235
"""
233236
raise NotImplementedError
234237

235-
def locate(self, cursor_offset, line) -> NoReturn:
238+
@abc.abstractmethod
239+
def locate(self, cursor_offset: int, line: str) -> Union[LinePart, None]:
236240
"""Returns a Linepart namedtuple instance or None given cursor and line
237241
238242
A Linepart namedtuple contains a start, stop, and word. None is
@@ -243,9 +247,10 @@ def locate(self, cursor_offset, line) -> NoReturn:
243247
def format(self, word):
244248
return word
245249

246-
def substitute(self, cursor_offset, line, match) -> NoReturn:
250+
def substitute(self, cursor_offset, line, match) -> Tuple[int, str]:
247251
"""Returns a cursor offset and line with match swapped in"""
248252
lpart = self.locate(cursor_offset, line)
253+
assert lpart
249254
offset = lpart.start + len(match)
250255
changed_line = line[: lpart.start] + match + line[lpart.stop :]
251256
return offset, changed_line
@@ -269,16 +274,19 @@ def __init__(self, completers, mode=AutocompleteModes.SIMPLE) -> None:
269274

270275
super().__init__(True, mode)
271276

272-
def locate(self, current_offset, line) -> Union[None, NoReturn]:
277+
def locate(self, current_offset: int, line: str) -> Union[None, NoReturn]:
273278
for completer in self._completers:
274279
return_value = completer.locate(current_offset, line)
275280
if return_value is not None:
276281
return return_value
282+
return None
277283

278284
def format(self, word):
279285
return self._completers[0].format(word)
280286

281-
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
287+
def matches(
288+
self, cursor_offset: int, line: str, **kwargs
289+
) -> Union[None, Set]:
282290
return_value = None
283291
all_matches = set()
284292
for completer in self._completers:
@@ -344,7 +352,7 @@ class AttrCompletion(BaseCompletionType):
344352

345353
attr_matches_re = LazyReCompile(r"(\w+(\.\w+)*)\.(\w*)")
346354

347-
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Dict]:
355+
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
348356
if "locals_" not in kwargs:
349357
return None
350358
locals_ = kwargs["locals_"]
@@ -427,15 +435,17 @@ def list_attributes(self, obj) -> List[str]:
427435

428436

429437
class DictKeyCompletion(BaseCompletionType):
430-
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Dict]:
438+
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
431439
if "locals_" not in kwargs:
432440
return None
433441
locals_ = kwargs["locals_"]
434442

435443
r = self.locate(cursor_offset, line)
436444
if r is None:
437445
return None
438-
_, _, dexpr = lineparts.current_dict(cursor_offset, line)
446+
curDictParts = lineparts.current_dict(cursor_offset, line)
447+
assert curDictParts, "current_dict when .locate() truthy"
448+
_, _, dexpr = curDictParts
439449
try:
440450
obj = safe_eval(dexpr, locals_)
441451
except EvaluationError:
@@ -456,7 +466,7 @@ def format(self, match):
456466

457467

458468
class MagicMethodCompletion(BaseCompletionType):
459-
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Dict]:
469+
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
460470
if "current_block" not in kwargs:
461471
return None
462472
current_block = kwargs["current_block"]
@@ -508,7 +518,7 @@ def locate(self, current_offset, line) -> Union[LinePart, None]:
508518

509519

510520
class ParameterNameCompletion(BaseCompletionType):
511-
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Dict]:
521+
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
512522
if "argspec" not in kwargs:
513523
return None
514524
argspec = kwargs["argspec"]
@@ -538,7 +548,7 @@ class ExpressionAttributeCompletion(AttrCompletion):
538548
def locate(self, current_offset, line) -> Union[LinePart, None]:
539549
return lineparts.current_expression_attribute(current_offset, line)
540550

541-
def matches(self, cursor_offset, line, **kwargs) -> Union[Set, Dict, None]:
551+
def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
542552
if "locals_" not in kwargs:
543553
return None
544554
locals_ = kwargs["locals_"]
@@ -547,6 +557,7 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, Dict, None]:
547557
locals_ = __main__.__dict__
548558

549559
attr = self.locate(cursor_offset, line)
560+
assert attr, "locate was already truthy for the same call"
550561

551562
try:
552563
obj = evaluate_current_expression(cursor_offset, line, locals_)
@@ -570,7 +581,9 @@ def matches(self, cursor_offset, line, **kwargs) -> None:
570581
else:
571582

572583
class JediCompletion(BaseCompletionType):
573-
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Dict]:
584+
_orig_start: Union[int, None]
585+
586+
def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
574587
if "history" not in kwargs:
575588
return None
576589
history = kwargs["history"]
@@ -596,6 +609,7 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Dict]:
596609
else:
597610
self._orig_start = None
598611
return None
612+
assert isinstance(self._orig_start, int)
599613

600614
first_letter = line[self._orig_start : self._orig_start + 1]
601615

@@ -610,13 +624,14 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Dict]:
610624
# case-sensitive matches only
611625
return {m for m in matches if m.startswith(first_letter)}
612626

613-
def locate(self, cursor_offset, line) -> LinePart:
627+
def locate(self, cursor_offset: int, line: str) -> LinePart:
628+
assert isinstance(self._orig_start, int)
614629
start = self._orig_start
615630
end = cursor_offset
616631
return LinePart(start, end, line[start:end])
617632

618633
class MultilineJediCompletion(JediCompletion):
619-
def matches(self, cursor_offset, line, **kwargs) -> Union[Dict, None]:
634+
def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
620635
if "current_block" not in kwargs or "history" not in kwargs:
621636
return None
622637
current_block = kwargs["current_block"]

0 commit comments

Comments
 (0)