Coverage for /builds/ase/ase/ase/cli/completion.py: 75.47%
53 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3"""TAB-completion sub-command and update helper funtion.
5Run this when ever options are changed::
7 python3 -m ase.cli.completion
8"""
10import sys
11from pathlib import Path
12from typing import Dict, List, Tuple
14# Path of the complete.py script:
15path = Path(__file__).with_name('complete.py')
18class CLICommand:
19 """Add tab-completion for Bash.
21 Will show the command that needs to be added to your '~/.bashrc file.
22 """
23 cmd = f'complete -o default -C "{sys.executable} {path}" ase'
25 @staticmethod
26 def add_arguments(parser):
27 pass
29 @staticmethod
30 def run(args):
31 cmd = CLICommand.cmd
32 print(cmd)
35def update(path: Path,
36 subcommands: List[Tuple[str, str]],
37 test: bool = False) -> None:
38 """Update commands dict in complete.py.
40 Use test=True to test that no changes are needed.
42 Refactor with care! This function is also used by GPAW.
43 """
45 import textwrap
46 from importlib import import_module
48 dct: Dict[str, List[str]] = {}
50 class Subparser:
51 def __init__(self, command):
52 self.command = command
53 dct[command] = []
55 def add_argument(self, *args, **kwargs):
56 dct[command].extend(arg for arg in args
57 if arg.startswith('-'))
59 def add_argument_group(self, name):
60 return self
62 def add_mutually_exclusive_group(self, required=False):
63 return self
65 for command, module_name in subcommands:
66 module = import_module(module_name)
67 module.CLICommand.add_arguments(Subparser(command))
69 txt = 'commands = {'
70 for command, opts in sorted(dct.items()):
71 txt += "\n '" + command + "':\n ["
72 if opts:
73 txt += '\n'.join(textwrap.wrap("'" + "', '".join(opts) + "'],",
74 width=65,
75 break_on_hyphens=False,
76 subsequent_indent=' '))
77 else:
78 txt += '],'
79 txt = txt[:-1] + '}\n'
81 with path.open() as fd:
82 lines = fd.readlines()
84 a = lines.index('# Beginning of computer generated data:\n')
85 b = lines.index('# End of computer generated data\n')
87 if test:
88 if ''.join(lines[a + 1:b]) != txt:
89 raise ValueError(
90 'Please update ase/cli/complete.py using '
91 '"python3 -m ase.cli.completion".')
92 else:
93 lines[a + 1:b] = [txt]
94 new = path.with_name('complete.py.new')
95 with new.open('w') as fd:
96 print(''.join(lines), end='', file=fd)
97 new.rename(path)
98 path.chmod(0o775)
101if __name__ == '__main__':
102 from ase.cli.main import commands
103 update(path, commands)