Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/argcomplete/completers.py: 38%

68 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 06:31 +0000

1# Copyright 2012-2023, Andrey Kislyuk and argcomplete contributors. 

2# Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info. 

3 

4import argparse 

5import os 

6import subprocess 

7 

8 

9def _call(*args, **kwargs): 

10 # TODO: replace "universal_newlines" with "text" once 3.6 support is dropped 

11 kwargs["universal_newlines"] = True 

12 try: 

13 return subprocess.check_output(*args, **kwargs).splitlines() 

14 except subprocess.CalledProcessError: 

15 return [] 

16 

17 

18class BaseCompleter: 

19 """ 

20 This is the base class that all argcomplete completers should subclass. 

21 """ 

22 

23 def __call__( 

24 self, *, prefix: str, action: argparse.Action, parser: argparse.ArgumentParser, parsed_args: argparse.Namespace 

25 ): 

26 raise NotImplementedError("This method should be implemented by a subclass.") 

27 

28 

29class ChoicesCompleter(BaseCompleter): 

30 def __init__(self, choices): 

31 self.choices = choices 

32 

33 def _convert(self, choice): 

34 if not isinstance(choice, str): 

35 choice = str(choice) 

36 return choice 

37 

38 def __call__(self, **kwargs): 

39 return (self._convert(c) for c in self.choices) 

40 

41 

42EnvironCompleter = ChoicesCompleter(os.environ) 

43 

44 

45class FilesCompleter(BaseCompleter): 

46 """ 

47 File completer class, optionally takes a list of allowed extensions 

48 """ 

49 

50 def __init__(self, allowednames=(), directories=True): 

51 # Fix if someone passes in a string instead of a list 

52 if isinstance(allowednames, (str, bytes)): 

53 allowednames = [allowednames] 

54 

55 self.allowednames = [x.lstrip("*").lstrip(".") for x in allowednames] 

56 self.directories = directories 

57 

58 def __call__(self, prefix, **kwargs): 

59 completion = [] 

60 if self.allowednames: 

61 if self.directories: 

62 files = _call(["bash", "-c", "compgen -A directory -- '{p}'".format(p=prefix)]) 

63 completion += [f + "/" for f in files] 

64 for x in self.allowednames: 

65 completion += _call(["bash", "-c", "compgen -A file -X '!*.{0}' -- '{p}'".format(x, p=prefix)]) 

66 else: 

67 completion += _call(["bash", "-c", "compgen -A file -- '{p}'".format(p=prefix)]) 

68 anticomp = _call(["bash", "-c", "compgen -A directory -- '{p}'".format(p=prefix)]) 

69 completion = list(set(completion) - set(anticomp)) 

70 

71 if self.directories: 

72 completion += [f + "/" for f in anticomp] 

73 return completion 

74 

75 

76class _FilteredFilesCompleter(BaseCompleter): 

77 def __init__(self, predicate): 

78 """ 

79 Create the completer 

80 

81 A predicate accepts as its only argument a candidate path and either 

82 accepts it or rejects it. 

83 """ 

84 assert predicate, "Expected a callable predicate" 

85 self.predicate = predicate 

86 

87 def __call__(self, prefix, **kwargs): 

88 """ 

89 Provide completions on prefix 

90 """ 

91 target_dir = os.path.dirname(prefix) 

92 try: 

93 names = os.listdir(target_dir or ".") 

94 except Exception: 

95 return # empty iterator 

96 incomplete_part = os.path.basename(prefix) 

97 # Iterate on target_dir entries and filter on given predicate 

98 for name in names: 

99 if not name.startswith(incomplete_part): 

100 continue 

101 candidate = os.path.join(target_dir, name) 

102 if not self.predicate(candidate): 

103 continue 

104 yield candidate + "/" if os.path.isdir(candidate) else candidate 

105 

106 

107class DirectoriesCompleter(_FilteredFilesCompleter): 

108 def __init__(self): 

109 _FilteredFilesCompleter.__init__(self, predicate=os.path.isdir) 

110 

111 

112class SuppressCompleter(BaseCompleter): 

113 """ 

114 A completer used to suppress the completion of specific arguments 

115 """ 

116 

117 def __init__(self): 

118 pass 

119 

120 def suppress(self): 

121 """ 

122 Decide if the completion should be suppressed 

123 """ 

124 return True