Coverage for ase / cli / completion.py: 77.55%
49 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-30 08:22 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-30 08:22 +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
13# Path of the complete.py script:
14path = Path(__file__).with_name('complete.py')
17class CLICommand:
18 """Add tab-completion for Bash.
20 Will show the command that needs to be added to your '~/.bashrc file.
21 """
22 cmd = f'complete -o default -C "{sys.executable} {path}" ase'
24 @staticmethod
25 def add_arguments(parser):
26 pass
28 @staticmethod
29 def run(args):
30 cmd = CLICommand.cmd
31 print(cmd)
34def update(path: Path,
35 subcommands: list[tuple[str, str]],
36 test: bool = False) -> None:
37 """Update commands dict in complete.py.
39 Use test=True to test that no changes are needed.
41 Refactor with care! This function is also used by GPAW.
42 """
44 import textwrap
45 from importlib import import_module
47 dct: dict[str, list[str]] = {}
49 class Subparser:
50 def __init__(self, command):
51 self.command = command
52 dct[command] = []
54 def add_argument(self, *args, **kwargs):
55 dct[command].extend(arg for arg in args
56 if arg.startswith('-'))
58 def add_argument_group(self, name):
59 return self
61 def add_mutually_exclusive_group(self, required=False):
62 return self
64 for command, module_name in subcommands:
65 module = import_module(module_name)
66 module.CLICommand.add_arguments(Subparser(command))
68 txt = 'commands = {'
69 for command, opts in sorted(dct.items()):
70 txt += "\n '" + command + "':\n ["
71 if opts:
72 txt += '\n'.join(textwrap.wrap("'" + "', '".join(opts) + "'],",
73 width=65,
74 break_on_hyphens=False,
75 subsequent_indent=' '))
76 else:
77 txt += '],'
78 txt = txt[:-1] + '}\n'
80 with path.open() as fd:
81 lines = fd.readlines()
83 a = lines.index('# Beginning of computer generated data:\n')
84 b = lines.index('# End of computer generated data\n')
86 if test:
87 if ''.join(lines[a + 1:b]) != txt:
88 raise ValueError(
89 'Please update ase/cli/complete.py using '
90 '"python3 -m ase.cli.completion".')
91 else:
92 lines[a + 1:b] = [txt]
93 new = path.with_name('complete.py.new')
94 with new.open('w') as fd:
95 print(''.join(lines), end='', file=fd)
96 new.rename(path)
97 path.chmod(0o775)
100if __name__ == '__main__':
101 from ase.cli.main import commands
102 update(path, commands)