Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import argparse
2import sys
3import textwrap
4from importlib import import_module
6from ase import __version__
9class CLIError(Exception):
10 """Error for CLI commands.
12 A subcommand may raise this. The message will be forwarded to
13 the error() method of the argument parser."""
16# Important: Following any change to command-line parameters, use
17# python3 -m ase.cli.completion to update autocompletion.
18commands = [
19 ('info', 'ase.cli.info'),
20 # ('show', 'ase.cli.show'),
21 ('test', 'ase.test'),
22 ('gui', 'ase.gui.ag'),
23 ('db', 'ase.db.cli'),
24 ('run', 'ase.cli.run'),
25 ('band-structure', 'ase.cli.band_structure'),
26 ('build', 'ase.cli.build'),
27 ('dimensionality', 'ase.cli.dimensionality'),
28 ('eos', 'ase.eos'),
29 ('ulm', 'ase.io.ulm'),
30 ('find', 'ase.cli.find'),
31 ('nebplot', 'ase.cli.nebplot'),
32 ('nomad-upload', 'ase.cli.nomad'),
33 ('nomad-get', 'ase.cli.nomadget'),
34 ('convert', 'ase.cli.convert'),
35 ('reciprocal', 'ase.cli.reciprocal'),
36 ('completion', 'ase.cli.completion'),
37 ('diff', 'ase.cli.diff'),
38 ('exec', 'ase.cli.exec')
39]
42def main(prog='ase', description='ASE command line tool.',
43 version=__version__, commands=commands, hook=None, args=None):
44 parser = argparse.ArgumentParser(prog=prog,
45 description=description,
46 formatter_class=Formatter)
47 parser.add_argument('--version', action='version',
48 version='%(prog)s-{}'.format(version))
49 parser.add_argument('-T', '--traceback', action='store_true')
50 subparsers = parser.add_subparsers(title='Sub-commands',
51 dest='command')
53 subparser = subparsers.add_parser('help',
54 description='Help',
55 help='Help for sub-command.')
56 subparser.add_argument('helpcommand',
57 nargs='?',
58 metavar='sub-command',
59 help='Provide help for sub-command.')
61 functions = {}
62 parsers = {}
63 for command, module_name in commands:
64 cmd = import_module(module_name).CLICommand
65 docstring = cmd.__doc__
66 if docstring is None:
67 # Backwards compatibility with GPAW
68 short = cmd.short_description
69 long = getattr(cmd, 'description', short)
70 else:
71 parts = docstring.split('\n', 1)
72 if len(parts) == 1:
73 short = docstring
74 long = docstring
75 else:
76 short, body = parts
77 long = short + '\n' + textwrap.dedent(body)
78 subparser = subparsers.add_parser(
79 command,
80 formatter_class=Formatter,
81 help=short,
82 description=long)
83 cmd.add_arguments(subparser)
84 functions[command] = cmd.run
85 parsers[command] = subparser
87 if hook:
88 args = hook(parser, args)
89 else:
90 args = parser.parse_args(args)
92 if args.command == 'help':
93 if args.helpcommand is None:
94 parser.print_help()
95 else:
96 parsers[args.helpcommand].print_help()
97 elif args.command is None:
98 parser.print_usage()
99 else:
100 f = functions[args.command]
101 try:
102 if f.__code__.co_argcount == 1:
103 f(args)
104 else:
105 f(args, parsers[args.command])
106 except KeyboardInterrupt:
107 pass
108 except CLIError as x:
109 parser.error(x)
110 except Exception as x:
111 if args.traceback:
112 raise
113 else:
114 l1 = '{}: {}\n'.format(x.__class__.__name__, x)
115 l2 = ('To get a full traceback, use: {} -T {} ...'
116 .format(prog, args.command))
117 parser.error(l1 + l2)
120class Formatter(argparse.HelpFormatter):
121 """Improved help formatter."""
123 def _fill_text(self, text, width, indent):
124 assert indent == ''
125 out = ''
126 blocks = text.split('\n\n')
127 for block in blocks:
128 if block[0] == '*':
129 # List items:
130 for item in block[2:].split('\n* '):
131 out += textwrap.fill(item,
132 width=width - 2,
133 initial_indent='* ',
134 subsequent_indent=' ') + '\n'
135 elif block[0] == ' ':
136 # Indented literal block:
137 out += block + '\n'
138 else:
139 # Block of text:
140 out += textwrap.fill(block, width=width) + '\n'
141 out += '\n'
142 return out[:-1]
145def old():
146 cmd = sys.argv[0].split('-')[-1]
147 print('Please use "ase {cmd}" instead of "ase-{cmd}"'.format(cmd=cmd))
148 sys.argv[:1] = ['ase', cmd]
149 main()