3333import builtins
3434
3535from 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
3737from .import inspection
3838from .import line as lineparts
3939from .line import LinePart
@@ -180,7 +180,7 @@ def few_enough_underscores(current, match) -> bool:
180180return not match .startswith ("_" )
181181
182182
183- def method_match_none (word ,size ,text )-> False :
183+ def method_match_none (word ,size ,text )-> bool :
184184return False
185185
186186
@@ -214,7 +214,10 @@ def __init__(
214214self ._shown_before_tab = shown_before_tab
215215self .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 """
233236raise 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:
243247def format (self ,word ):
244248return 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"""
248252lpart = self .locate (cursor_offset ,line )
253+ assert lpart
249254offset = lpart .start + len (match )
250255changed_line = line [:lpart .start ]+ match + line [lpart .stop :]
251256return offset ,changed_line
@@ -269,16 +274,19 @@ def __init__(self, completers, mode=AutocompleteModes.SIMPLE) -> None:
269274
270275super ().__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 ]:
273278for completer in self ._completers :
274279return_value = completer .locate (current_offset ,line )
275280if return_value is not None :
276281return return_value
282+ return None
277283
278284def format (self ,word ):
279285return 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 ]:
282290return_value = None
283291all_matches = set ()
284292for completer in self ._completers :
@@ -344,7 +352,7 @@ class AttrCompletion(BaseCompletionType):
344352
345353attr_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 ]:
348356if "locals_" not in kwargs :
349357return None
350358locals_ = kwargs ["locals_" ]
@@ -427,15 +435,17 @@ def list_attributes(self, obj) -> List[str]:
427435
428436
429437class DictKeyCompletion (BaseCompletionType ):
430- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Dict ]:
438+ def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Set ]:
431439if "locals_" not in kwargs :
432440return None
433441locals_ = kwargs ["locals_" ]
434442
435443r = self .locate (cursor_offset ,line )
436444if r is None :
437445return 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
439449try :
440450obj = safe_eval (dexpr ,locals_ )
441451except EvaluationError :
@@ -456,7 +466,7 @@ def format(self, match):
456466
457467
458468class MagicMethodCompletion (BaseCompletionType ):
459- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Dict ]:
469+ def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Set ]:
460470if "current_block" not in kwargs :
461471return None
462472current_block = kwargs ["current_block" ]
@@ -508,7 +518,7 @@ def locate(self, current_offset, line) -> Union[LinePart, None]:
508518
509519
510520class ParameterNameCompletion (BaseCompletionType ):
511- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Dict ]:
521+ def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Set ]:
512522if "argspec" not in kwargs :
513523return None
514524argspec = kwargs ["argspec" ]
@@ -538,7 +548,7 @@ class ExpressionAttributeCompletion(AttrCompletion):
538548def locate (self ,current_offset ,line )-> Union [LinePart ,None ]:
539549return 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 ]:
542552if "locals_" not in kwargs :
543553return None
544554locals_ = kwargs ["locals_" ]
@@ -547,6 +557,7 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, Dict, None]:
547557locals_ = __main__ .__dict__
548558
549559attr = self .locate (cursor_offset ,line )
560+ assert attr ,"locate was already truthy for the same call"
550561
551562try :
552563obj = evaluate_current_expression (cursor_offset ,line ,locals_ )
@@ -570,7 +581,9 @@ def matches(self, cursor_offset, line, **kwargs) -> None:
570581else :
571582
572583class 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 ]:
574587if "history" not in kwargs :
575588return None
576589history = kwargs ["history" ]
@@ -596,6 +609,7 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Dict]:
596609else :
597610self ._orig_start = None
598611return None
612+ assert isinstance (self ._orig_start ,int )
599613
600614first_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
611625return {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 )
614629start = self ._orig_start
615630end = cursor_offset
616631return LinePart (start ,end ,line [start :end ])
617632
618633class MultilineJediCompletion (JediCompletion ):
619- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [Dict ,None ]:
634+ def matches (self ,cursor_offset ,line ,** kwargs )-> Union [Set ,None ]:
620635if "current_block" not in kwargs or "history" not in kwargs :
621636return None
622637current_block = kwargs ["current_block" ]