Coverage for /builds/kinetik161/ase/ase/cli/completion.py: 76.47%

51 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-12-10 11:04 +0000

1"""TAB-completion sub-command and update helper funtion. 

2 

3Run this when ever options are changed:: 

4 

5 python3 -m ase.cli.completion 

6""" 

7 

8import sys 

9from pathlib import Path 

10from typing import Dict, List, Tuple 

11 

12# Path of the complete.py script: 

13path = Path(__file__).with_name('complete.py') 

14 

15 

16class CLICommand: 

17 """Add tab-completion for Bash. 

18 

19 Will show the command that needs to be added to your '~/.bashrc file. 

20 """ 

21 cmd = f'complete -o default -C "{sys.executable} {path}" ase' 

22 

23 @staticmethod 

24 def add_arguments(parser): 

25 pass 

26 

27 @staticmethod 

28 def run(args): 

29 cmd = CLICommand.cmd 

30 print(cmd) 

31 

32 

33def update(path: Path, 

34 subcommands: List[Tuple[str, str]], 

35 test: bool = False) -> None: 

36 """Update commands dict in complete.py. 

37 

38 Use test=True to test that no changes are needed. 

39 

40 Refactor with care! This function is also used by GPAW. 

41 """ 

42 

43 import textwrap 

44 from importlib import import_module 

45 

46 dct: Dict[str, List[str]] = {} 

47 

48 class Subparser: 

49 def __init__(self, command): 

50 self.command = command 

51 dct[command] = [] 

52 

53 def add_argument(self, *args, **kwargs): 

54 dct[command].extend(arg for arg in args 

55 if arg.startswith('-')) 

56 

57 def add_mutually_exclusive_group(self, required=False): 

58 return self 

59 

60 for command, module_name in subcommands: 

61 module = import_module(module_name) 

62 module.CLICommand.add_arguments(Subparser(command)) 

63 

64 txt = 'commands = {' 

65 for command, opts in sorted(dct.items()): 

66 txt += "\n '" + command + "':\n [" 

67 if opts: 

68 txt += '\n'.join(textwrap.wrap("'" + "', '".join(opts) + "'],", 

69 width=65, 

70 break_on_hyphens=False, 

71 subsequent_indent=' ')) 

72 else: 

73 txt += '],' 

74 txt = txt[:-1] + '}\n' 

75 

76 with path.open() as fd: 

77 lines = fd.readlines() 

78 

79 a = lines.index('# Beginning of computer generated data:\n') 

80 b = lines.index('# End of computer generated data\n') 

81 

82 if test: 

83 if ''.join(lines[a + 1:b]) != txt: 

84 raise ValueError( 

85 'Please update ase/cli/complete.py using ' 

86 '"python3 -m ase.cli.completion".') 

87 else: 

88 lines[a + 1:b] = [txt] 

89 new = path.with_name('complete.py.new') 

90 with new.open('w') as fd: 

91 print(''.join(lines), end='', file=fd) 

92 new.rename(path) 

93 path.chmod(0o775) 

94 

95 

96if __name__ == '__main__': 

97 from ase.cli.main import commands 

98 update(path, commands)