21
21
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
22
# THE SOFTWARE.
23
23
24
+ # To gradually migrate to mypy we aren't setting these globally yet
25
+ # mypy: disallow_untyped_defs=True
24
26
25
27
import __main__
26
28
import abc
35
37
from enum import Enum
36
38
from typing import (
37
39
Any ,
40
+ cast ,
38
41
Dict ,
39
42
Iterator ,
40
43
List ,
41
44
Match ,
45
+ Optional ,
42
46
Set ,
43
47
Union ,
44
48
Tuple ,
50
54
from .line import LinePart
51
55
from .lazyre import LazyReCompile
52
56
from .simpleeval import safe_eval , evaluate_current_expression , EvaluationError
57
+ from .importcompletion import ModuleGatherer
53
58
54
59
55
60
# Autocomplete modes
@@ -60,7 +65,7 @@ class AutocompleteModes(Enum):
60
65
FUZZY = "fuzzy"
61
66
62
67
@classmethod
63
- def from_string (cls , value ) -> Union [Any , None ]:
68
+ def from_string (cls , value : str ) -> Union [Any , None ]:
64
69
if value .upper () in cls .__members__ :
65
70
return cls .__members__ [value .upper ()]
66
71
return None
@@ -177,7 +182,7 @@ def after_last_dot(name: str) -> str:
177
182
return name .rstrip ("." ).rsplit ("." )[- 1 ]
178
183
179
184
180
- def few_enough_underscores (current , match ) -> bool :
185
+ def few_enough_underscores (current : str , match : str ) -> bool :
181
186
"""Returns whether match should be shown based on current
182
187
183
188
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:
203
208
return text in word
204
209
205
210
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 ]:
207
212
s = r".*%s.*" % ".*" .join (list (text ))
208
213
return re .search (s , word )
209
214
@@ -220,14 +225,16 @@ class BaseCompletionType:
220
225
"""Describes different completion types"""
221
226
222
227
def __init__ (
223
- self , shown_before_tab : bool = True , mode = AutocompleteModes .SIMPLE
228
+ self ,
229
+ shown_before_tab : bool = True ,
230
+ mode : AutocompleteModes = AutocompleteModes .SIMPLE ,
224
231
) -> None :
225
232
self ._shown_before_tab = shown_before_tab
226
233
self .method_match = MODES_MAP [mode ]
227
234
228
235
@abc .abstractmethod
229
236
def matches (
230
- self , cursor_offset : int , line : str , ** kwargs
237
+ self , cursor_offset : int , line : str , ** kwargs : Any
231
238
) -> Union [Set [str ], None ]:
232
239
"""Returns a list of possible matches given a line and cursor, or None
233
240
if this completion type isn't applicable.
@@ -255,10 +262,12 @@ def locate(self, cursor_offset: int, line: str) -> Union[LinePart, None]:
255
262
the cursor."""
256
263
raise NotImplementedError
257
264
258
- def format (self , word ) :
265
+ def format (self , word : str ) -> str :
259
266
return word
260
267
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 ]:
262
271
"""Returns a cursor offset and line with match swapped in"""
263
272
lpart = self .locate (cursor_offset , line )
264
273
assert lpart
@@ -289,18 +298,18 @@ def __init__(
289
298
290
299
super ().__init__ (True , mode )
291
300
292
- def locate (self , current_offset , line ) :
301
+ def locate (self , cursor_offset : int , line : str ) -> Union [ LinePart , None ] :
293
302
for completer in self ._completers :
294
- return_value = completer .locate (current_offset , line )
303
+ return_value = completer .locate (cursor_offset , line )
295
304
if return_value is not None :
296
305
return return_value
297
306
return None
298
307
299
- def format (self , word ) :
308
+ def format (self , word : str ) -> str :
300
309
return self ._completers [0 ].format (word )
301
310
302
311
def matches (
303
- self , cursor_offset : int , line : str , ** kwargs
312
+ self , cursor_offset : int , line : str , ** kwargs : Any
304
313
) -> Union [None , Set ]:
305
314
return_value = None
306
315
all_matches = set ()
@@ -316,28 +325,36 @@ def matches(
316
325
317
326
318
327
class 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
+ ):
320
333
super ().__init__ (False , mode )
321
334
self .module_gatherer = module_gatherer
322
335
323
- def matches (self , cursor_offset , line , ** kwargs ):
336
+ def matches (
337
+ self , cursor_offset : int , line : str , ** kwargs : Any
338
+ ) -> Union [None , Set ]:
324
339
return self .module_gatherer .complete (cursor_offset , line )
325
340
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 )
328
343
329
- def format (self , word ) :
344
+ def format (self , word : str ) -> str :
330
345
return after_last_dot (word )
331
346
332
347
333
348
class FilenameCompletion (BaseCompletionType ):
334
- def __init__ (self , mode = AutocompleteModes .SIMPLE ):
349
+ def __init__ (self , mode : AutocompleteModes = AutocompleteModes .SIMPLE ):
335
350
super ().__init__ (False , mode )
336
351
337
- def safe_glob (self , pathname ) -> Iterator :
352
+ def safe_glob (self , pathname : str ) -> Iterator [ str ] :
338
353
return glob .iglob (glob .escape (pathname ) + "*" )
339
354
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 ]:
341
358
cs = lineparts .current_string (cursor_offset , line )
342
359
if cs is None :
343
360
return None
@@ -352,10 +369,10 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, set]:
352
369
matches .add (filename )
353
370
return matches
354
371
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 )
357
374
358
- def format (self , filename ) :
375
+ def format (self , filename : str ) -> str :
359
376
filename .rstrip (os .sep ).rsplit (os .sep )[- 1 ]
360
377
if os .sep in filename [:- 1 ]:
361
378
return filename [filename .rindex (os .sep , 0 , - 1 ) + 1 :]
@@ -367,10 +384,12 @@ class AttrCompletion(BaseCompletionType):
367
384
368
385
attr_matches_re = LazyReCompile (r"(\w+(\.\w+)*)\.(\w*)" )
369
386
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 ]:
371
390
if "locals_" not in kwargs :
372
391
return None
373
- locals_ = kwargs ["locals_" ]
392
+ locals_ = cast ( Dict [ str , Any ], kwargs ["locals_" ])
374
393
375
394
r = self .locate (cursor_offset , line )
376
395
if r is None :
@@ -397,13 +416,13 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
397
416
if few_enough_underscores (r .word .split ("." )[- 1 ], m .split ("." )[- 1 ])
398
417
}
399
418
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 )
402
421
403
- def format (self , word ) :
422
+ def format (self , word : str ) -> str :
404
423
return after_last_dot (word )
405
424
406
- def attr_matches (self , text , namespace ) -> List :
425
+ def attr_matches (self , text : str , namespace : Dict [ str , Any ] ) -> List :
407
426
"""Taken from rlcompleter.py and bent to my will."""
408
427
409
428
m = self .attr_matches_re .match (text )
@@ -422,7 +441,7 @@ def attr_matches(self, text, namespace) -> List:
422
441
matches = self .attr_lookup (obj , expr , attr )
423
442
return matches
424
443
425
- def attr_lookup (self , obj , expr , attr ) -> List :
444
+ def attr_lookup (self , obj : Any , expr : str , attr : str ) -> List :
426
445
"""Second half of attr_matches."""
427
446
words = self .list_attributes (obj )
428
447
if inspection .hasattr_safe (obj , "__class__" ):
@@ -442,15 +461,17 @@ def attr_lookup(self, obj, expr, attr) -> List:
442
461
matches .append (f"{ expr } .{ word } " )
443
462
return matches
444
463
445
- def list_attributes (self , obj ) -> List [str ]:
464
+ def list_attributes (self , obj : Any ) -> List [str ]:
446
465
# TODO: re-implement dir using getattr_static to avoid using
447
466
# AttrCleaner here?
448
467
with inspection .AttrCleaner (obj ):
449
468
return dir (obj )
450
469
451
470
452
471
class 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 ]:
454
475
if "locals_" not in kwargs :
455
476
return None
456
477
locals_ = kwargs ["locals_" ]
@@ -473,15 +494,17 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
473
494
else :
474
495
return None
475
496
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 )
478
499
479
- def format (self , match ) :
500
+ def format (self , match : str ) -> str :
480
501
return match [:- 1 ]
481
502
482
503
483
504
class 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 ]:
485
508
if "current_block" not in kwargs :
486
509
return None
487
510
current_block = kwargs ["current_block" ]
@@ -493,12 +516,14 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
493
516
return None
494
517
return {name for name in MAGIC_METHODS if name .startswith (r .word )}
495
518
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 )
498
521
499
522
500
523
class 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 ]:
502
527
"""Compute matches when text is a simple name.
503
528
Return a list of all keywords, built-in functions and names currently
504
529
defined in self.namespace that match.
@@ -528,12 +553,14 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
528
553
matches .add (_callable_postfix (val , word ))
529
554
return matches if matches else None
530
555
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 )
533
558
534
559
535
560
class 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 ]:
537
564
if "argspec" not in kwargs :
538
565
return None
539
566
argspec = kwargs ["argspec" ]
@@ -554,16 +581,18 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[None, Set]:
554
581
)
555
582
return matches if matches else None
556
583
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 )
559
586
560
587
561
588
class ExpressionAttributeCompletion (AttrCompletion ):
562
589
# 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 )
565
592
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 ]:
567
596
if "locals_" not in kwargs :
568
597
return None
569
598
locals_ = kwargs ["locals_" ]
@@ -589,7 +618,14 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
589
618
except ImportError :
590
619
591
620
class 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 ]:
593
629
return None
594
630
595
631
@@ -598,7 +634,9 @@ def matches(self, cursor_offset, line, **kwargs) -> None:
598
634
class JediCompletion (BaseCompletionType ):
599
635
_orig_start : Union [int , None ]
600
636
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 ]:
602
640
if "history" not in kwargs :
603
641
return None
604
642
history = kwargs ["history" ]
@@ -646,7 +684,9 @@ def locate(self, cursor_offset: int, line: str) -> LinePart:
646
684
return LinePart (start , end , line [start :end ])
647
685
648
686
class 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 ]:
650
690
if "current_block" not in kwargs or "history" not in kwargs :
651
691
return None
652
692
current_block = kwargs ["current_block" ]
@@ -663,7 +703,12 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
663
703
return None
664
704
665
705
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 ]]:
667
712
"""Returns a list of matches and an applicable completer
668
713
669
714
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):
698
743
return [], None
699
744
700
745
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 , ...]:
702
749
return (
703
750
(
704
751
DictKeyCompletion (mode = mode ),
@@ -721,7 +768,7 @@ def get_default_completer(mode=AutocompleteModes.SIMPLE, module_gatherer=None):
721
768
)
722
769
723
770
724
- def _callable_postfix (value , word ) :
771
+ def _callable_postfix (value : Any , word : str ) -> str :
725
772
"""rlcompleter's _callable_postfix done right."""
726
773
if callable (value ):
727
774
word += "("
0 commit comments