2121# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2222# THE SOFTWARE.
2323
24+ # To gradually migrate to mypy we aren't setting these globally yet
25+ # mypy: disallow_untyped_defs=True
2426
2527import __main__
2628import abc
3537from enum import Enum
3638from typing import (
3739Any ,
40+ cast ,
3841Dict ,
3942Iterator ,
4043List ,
4144Match ,
45+ Optional ,
4246Set ,
4347Union ,
4448Tuple ,
5054from .line import LinePart
5155from .lazyre import LazyReCompile
5256from .simpleeval import safe_eval ,evaluate_current_expression ,EvaluationError
57+ from .importcompletion import ModuleGatherer
5358
5459
5560# Autocomplete modes
@@ -60,7 +65,7 @@ class AutocompleteModes(Enum):
6065FUZZY = "fuzzy"
6166
6267@classmethod
63- def from_string (cls ,value )-> Union [Any ,None ]:
68+ def from_string (cls ,value : str )-> Union [Any ,None ]:
6469if value .upper ()in cls .__members__ :
6570return cls .__members__ [value .upper ()]
6671return None
@@ -177,7 +182,7 @@ def after_last_dot(name: str) -> str:
177182return name .rstrip ("." ).rsplit ("." )[- 1 ]
178183
179184
180- def few_enough_underscores (current ,match )-> bool :
185+ def few_enough_underscores (current : str ,match : str )-> bool :
181186"""Returns whether match should be shown based on current
182187
183188 if current is _, True if match starts with 0 or 1 underscore
@@ -203,7 +208,7 @@ def method_match_substring(word: str, size: int, text: str) -> bool:
203208return text in word
204209
205210
206- def method_match_fuzzy (word ,size ,text )-> Union [Match ,None ]:
211+ def method_match_fuzzy (word : str ,size : int ,text : str )-> Union [Match ,None ]:
207212s = r".*%s.*" % ".*" .join (list (text ))
208213return re .search (s ,word )
209214
@@ -220,14 +225,16 @@ class BaseCompletionType:
220225"""Describes different completion types"""
221226
222227def __init__ (
223- self ,shown_before_tab :bool = True ,mode = AutocompleteModes .SIMPLE
228+ self ,
229+ shown_before_tab :bool = True ,
230+ mode :AutocompleteModes = AutocompleteModes .SIMPLE ,
224231 )-> None :
225232self ._shown_before_tab = shown_before_tab
226233self .method_match = MODES_MAP [mode ]
227234
228235@abc .abstractmethod
229236def matches (
230- self ,cursor_offset :int ,line :str ,** kwargs
237+ self ,cursor_offset :int ,line :str ,** kwargs : Any
231238 )-> Union [Set [str ],None ]:
232239"""Returns a list of possible matches given a line and cursor, or None
233240 if this completion type isn't applicable.
@@ -255,10 +262,12 @@ def locate(self, cursor_offset: int, line: str) -> Union[LinePart, None]:
255262 the cursor."""
256263raise NotImplementedError
257264
258- def format (self ,word ) :
265+ def format (self ,word : str ) -> str :
259266return word
260267
261- def substitute (self ,cursor_offset ,line ,match )-> Tuple [int ,str ]:
268+ def substitute (
269+ self ,cursor_offset :int ,line :str ,match :str
270+ )-> Tuple [int ,str ]:
262271"""Returns a cursor offset and line with match swapped in"""
263272lpart = self .locate (cursor_offset ,line )
264273assert lpart
@@ -289,18 +298,18 @@ def __init__(
289298
290299super ().__init__ (True ,mode )
291300
292- def locate (self ,current_offset ,line ) :
301+ def locate (self ,cursor_offset : int ,line : str ) -> Union [ LinePart , None ] :
293302for completer in self ._completers :
294- return_value = completer .locate (current_offset ,line )
303+ return_value = completer .locate (cursor_offset ,line )
295304if return_value is not None :
296305return return_value
297306return None
298307
299- def format (self ,word ) :
308+ def format (self ,word : str ) -> str :
300309return self ._completers [0 ].format (word )
301310
302311def matches (
303- self ,cursor_offset :int ,line :str ,** kwargs
312+ self ,cursor_offset :int ,line :str ,** kwargs : Any
304313 )-> Union [None ,Set ]:
305314return_value = None
306315all_matches = set ()
@@ -316,28 +325,36 @@ def matches(
316325
317326
318327class ImportCompletion (BaseCompletionType ):
319- def __init__ (self ,module_gatherer ,mode = AutocompleteModes .SIMPLE ):
328+ def __init__ (
329+ self ,
330+ module_gatherer :ModuleGatherer ,
331+ mode :AutocompleteModes = AutocompleteModes .SIMPLE ,
332+ ):
320333super ().__init__ (False ,mode )
321334self .module_gatherer = module_gatherer
322335
323- def matches (self ,cursor_offset ,line ,** kwargs ):
336+ def matches (
337+ self ,cursor_offset :int ,line :str ,** kwargs :Any
338+ )-> Union [None ,Set ]:
324339return self .module_gatherer .complete (cursor_offset ,line )
325340
326- def locate (self ,current_offset ,line ) :
327- return lineparts .current_word (current_offset ,line )
341+ def locate (self ,cursor_offset : int ,line : str ) -> Union [ LinePart , None ] :
342+ return lineparts .current_word (cursor_offset ,line )
328343
329- def format (self ,word ) :
344+ def format (self ,word : str ) -> str :
330345return after_last_dot (word )
331346
332347
333348class FilenameCompletion (BaseCompletionType ):
334- def __init__ (self ,mode = AutocompleteModes .SIMPLE ):
349+ def __init__ (self ,mode : AutocompleteModes = AutocompleteModes .SIMPLE ):
335350super ().__init__ (False ,mode )
336351
337- def safe_glob (self ,pathname )-> Iterator :
352+ def safe_glob (self ,pathname : str )-> Iterator [ str ] :
338353return glob .iglob (glob .escape (pathname )+ "*" )
339354
340- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,set ]:
355+ def matches (
356+ self ,cursor_offset :int ,line :str ,** kwargs :Any
357+ )-> Union [None ,Set ]:
341358cs = lineparts .current_string (cursor_offset ,line )
342359if cs is None :
343360return None
@@ -352,10 +369,10 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, set]:
352369matches .add (filename )
353370return matches
354371
355- def locate (self ,current_offset ,line ) :
356- return lineparts .current_string (current_offset ,line )
372+ def locate (self ,cursor_offset : int ,line : str ) -> Union [ LinePart , None ] :
373+ return lineparts .current_string (cursor_offset ,line )
357374
358- def format (self ,filename ) :
375+ def format (self ,filename : str ) -> str :
359376filename .rstrip (os .sep ).rsplit (os .sep )[- 1 ]
360377if os .sep in filename [:- 1 ]:
361378return filename [filename .rindex (os .sep ,0 ,- 1 )+ 1 :]
@@ -367,10 +384,12 @@ class AttrCompletion(BaseCompletionType):
367384
368385attr_matches_re = LazyReCompile (r"(\w+(\.\w+)*)\.(\w*)" )
369386
370- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Set ]:
387+ def matches (
388+ self ,cursor_offset :int ,line :str ,** kwargs :Any
389+ )-> Union [None ,Set ]:
371390if "locals_" not in kwargs :
372391return None
373- locals_ = kwargs ["locals_" ]
392+ locals_ = cast ( Dict [ str , Any ], kwargs ["locals_" ])
374393
375394r = self .locate (cursor_offset ,line )
376395if r is None :
@@ -397,13 +416,13 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
397416if few_enough_underscores (r .word .split ("." )[- 1 ],m .split ("." )[- 1 ])
398417 }
399418
400- def locate (self ,current_offset ,line ) :
401- return lineparts .current_dotted_attribute (current_offset ,line )
419+ def locate (self ,cursor_offset : int ,line : str ) -> Union [ LinePart , None ] :
420+ return lineparts .current_dotted_attribute (cursor_offset ,line )
402421
403- def format (self ,word ) :
422+ def format (self ,word : str ) -> str :
404423return after_last_dot (word )
405424
406- def attr_matches (self ,text ,namespace )-> List :
425+ def attr_matches (self ,text : str ,namespace : Dict [ str , Any ] )-> List :
407426"""Taken from rlcompleter.py and bent to my will."""
408427
409428m = self .attr_matches_re .match (text )
@@ -422,7 +441,7 @@ def attr_matches(self, text, namespace) -> List:
422441matches = self .attr_lookup (obj ,expr ,attr )
423442return matches
424443
425- def attr_lookup (self ,obj ,expr ,attr )-> List :
444+ def attr_lookup (self ,obj : Any ,expr : str ,attr : str )-> List :
426445"""Second half of attr_matches."""
427446words = self .list_attributes (obj )
428447if inspection .hasattr_safe (obj ,"__class__" ):
@@ -442,15 +461,17 @@ def attr_lookup(self, obj, expr, attr) -> List:
442461matches .append (f"{ expr } .{ word } " )
443462return matches
444463
445- def list_attributes (self ,obj )-> List [str ]:
464+ def list_attributes (self ,obj : Any )-> List [str ]:
446465# TODO: re-implement dir using getattr_static to avoid using
447466# AttrCleaner here?
448467with inspection .AttrCleaner (obj ):
449468return dir (obj )
450469
451470
452471class DictKeyCompletion (BaseCompletionType ):
453- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Set ]:
472+ def matches (
473+ self ,cursor_offset :int ,line :str ,** kwargs :Any
474+ )-> Union [None ,Set ]:
454475if "locals_" not in kwargs :
455476return None
456477locals_ = kwargs ["locals_" ]
@@ -473,15 +494,17 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
473494else :
474495return None
475496
476- def locate (self ,current_offset ,line )-> Union [LinePart ,None ]:
477- return lineparts .current_dict_key (current_offset ,line )
497+ def locate (self ,cursor_offset : int ,line : str )-> Union [LinePart ,None ]:
498+ return lineparts .current_dict_key (cursor_offset ,line )
478499
479- def format (self ,match ) :
500+ def format (self ,match : str ) -> str :
480501return match [:- 1 ]
481502
482503
483504class MagicMethodCompletion (BaseCompletionType ):
484- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Set ]:
505+ def matches (
506+ self ,cursor_offset :int ,line :str ,** kwargs :Any
507+ )-> Union [None ,Set ]:
485508if "current_block" not in kwargs :
486509return None
487510current_block = kwargs ["current_block" ]
@@ -493,12 +516,14 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
493516return None
494517return {name for name in MAGIC_METHODS if name .startswith (r .word )}
495518
496- def locate (self ,current_offset ,line )-> Union [LinePart ,None ]:
497- return lineparts .current_method_definition_name (current_offset ,line )
519+ def locate (self ,cursor_offset : int ,line : str )-> Union [LinePart ,None ]:
520+ return lineparts .current_method_definition_name (cursor_offset ,line )
498521
499522
500523class GlobalCompletion (BaseCompletionType ):
501- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [Set ,None ]:
524+ def matches (
525+ self ,cursor_offset :int ,line :str ,** kwargs :Any
526+ )-> Union [None ,Set ]:
502527"""Compute matches when text is a simple name.
503528 Return a list of all keywords, built-in functions and names currently
504529 defined in self.namespace that match.
@@ -528,12 +553,14 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
528553matches .add (_callable_postfix (val ,word ))
529554return matches if matches else None
530555
531- def locate (self ,current_offset ,line )-> Union [LinePart ,None ]:
532- return lineparts .current_single_word (current_offset ,line )
556+ def locate (self ,cursor_offset : int ,line : str )-> Union [LinePart ,None ]:
557+ return lineparts .current_single_word (cursor_offset ,line )
533558
534559
535560class ParameterNameCompletion (BaseCompletionType ):
536- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Set ]:
561+ def matches (
562+ self ,cursor_offset :int ,line :str ,** kwargs :Any
563+ )-> Union [None ,Set ]:
537564if "argspec" not in kwargs :
538565return None
539566argspec = kwargs ["argspec" ]
@@ -554,16 +581,18 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
554581 )
555582return matches if matches else None
556583
557- def locate (self ,current_offset ,line )-> Union [LinePart ,None ]:
558- return lineparts .current_word (current_offset ,line )
584+ def locate (self ,cursor_offset : int ,line : str )-> Union [LinePart ,None ]:
585+ return lineparts .current_word (cursor_offset ,line )
559586
560587
561588class ExpressionAttributeCompletion (AttrCompletion ):
562589# could replace attr completion as a more general case with some work
563- def locate (self ,current_offset ,line )-> Union [LinePart ,None ]:
564- return lineparts .current_expression_attribute (current_offset ,line )
590+ def locate (self ,cursor_offset : int ,line : str )-> Union [LinePart ,None ]:
591+ return lineparts .current_expression_attribute (cursor_offset ,line )
565592
566- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [Set ,None ]:
593+ def matches (
594+ self ,cursor_offset :int ,line :str ,** kwargs :Any
595+ )-> Union [None ,Set ]:
567596if "locals_" not in kwargs :
568597return None
569598locals_ = kwargs ["locals_" ]
@@ -589,7 +618,14 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
589618except ImportError :
590619
591620class MultilineJediCompletion (BaseCompletionType ):# type: ignore [no-redef]
592- def matches (self ,cursor_offset ,line ,** kwargs )-> None :
621+ def matches (
622+ self ,cursor_offset :int ,line :str ,** kwargs :Any
623+ )-> Union [None ,Set ]:
624+ return None
625+
626+ def locate (
627+ self ,cursor_offset :int ,line :str
628+ )-> Union [LinePart ,None ]:
593629return None
594630
595631
@@ -598,7 +634,9 @@ def matches(self, cursor_offset, line, **kwargs) -> None:
598634class JediCompletion (BaseCompletionType ):
599635_orig_start :Union [int ,None ]
600636
601- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [None ,Set ]:
637+ def matches (
638+ self ,cursor_offset :int ,line :str ,** kwargs :Any
639+ )-> Union [None ,Set ]:
602640if "history" not in kwargs :
603641return None
604642history = kwargs ["history" ]
@@ -646,7 +684,9 @@ def locate(self, cursor_offset: int, line: str) -> LinePart:
646684return LinePart (start ,end ,line [start :end ])
647685
648686class MultilineJediCompletion (JediCompletion ):# type: ignore [no-redef]
649- def matches (self ,cursor_offset ,line ,** kwargs )-> Union [Set ,None ]:
687+ def matches (
688+ self ,cursor_offset :int ,line :str ,** kwargs :Any
689+ )-> Union [None ,Set ]:
650690if "current_block" not in kwargs or "history" not in kwargs :
651691return None
652692current_block = kwargs ["current_block" ]
@@ -663,7 +703,12 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
663703return None
664704
665705
666- def get_completer (completers ,cursor_offset ,line ,** kwargs ):
706+ def get_completer (
707+ completers :Sequence [BaseCompletionType ],
708+ cursor_offset :int ,
709+ line :str ,
710+ ** kwargs :Any ,
711+ )-> Tuple [List [str ],Optional [BaseCompletionType ]]:
667712"""Returns a list of matches and an applicable completer
668713
669714 If no matches available, returns a tuple of an empty list and None
@@ -698,7 +743,9 @@ def get_completer(completers, cursor_offset, line, **kwargs):
698743return [],None
699744
700745
701- def get_default_completer (mode = AutocompleteModes .SIMPLE ,module_gatherer = None ):
746+ def get_default_completer (
747+ mode :AutocompleteModes ,module_gatherer :ModuleGatherer
748+ )-> Tuple [BaseCompletionType , ...]:
702749return (
703750 (
704751DictKeyCompletion (mode = mode ),
@@ -721,7 +768,7 @@ def get_default_completer(mode=AutocompleteModes.SIMPLE, module_gatherer=None):
721768 )
722769
723770
724- def _callable_postfix (value ,word ) :
771+ def _callable_postfix (value : Any ,word : str ) -> str :
725772"""rlcompleter's _callable_postfix done right."""
726773if callable (value ):
727774word += "("