1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
.. _decorators:
===================
Argument Processing
===================
``cmd2`` makes it easy to add sophisticated argument processing to your commands using the ``argparse`` python module.
``cmd2`` handles the following for you:
1. Parsing input and quoted strings like the Unix shell
2. Parse the resulting argument list using an instance of ``argparse.ArgumentParser`` that you provide
3. Passes the resulting ``argparse.Namespace`` object to your command function
4. Adds the usage message from the argument parser to your command.
5. Checks if the ``-h/--help`` option is present, and if so, display the help message for the command
These features are all provided by the ``@with_argument_parser`` decorator.
Using the argument parser decorator
===================================
For each command in the ``cmd2`` subclass which requires argument parsing,
create an instance of ``argparse.ArgumentParser()`` which can parse the
input appropriately for the command. Then decorate the command method with
the ``@with_argument_parser`` decorator, passing the argument parser as the
first parameter to the decorator. This changes the second argumen to the command method, which will contain the results
of ``ArgumentParser.parse_args()``.
Here's what it looks like::
argparser = argparse.ArgumentParser()
argparser.add_argument('-p', '--piglatin', action='store_true', help='atinLay')
argparser.add_argument('-s', '--shout', action='store_true', help='N00B EMULATION MODE')
argparser.add_argument('-r', '--repeat', type=int, help='output [n] times')
argparser.add_argument('word', nargs='?', help='word to say')
@with_argument_parser(argparser)
def do_speak(self, opts)
"""Repeats what you tell me to."""
arg = opts.word
if opts.piglatin:
arg = '%s%say' % (arg[1:], arg[0])
if opts.shout:
arg = arg.upper()
repetitions = opts.repeat or 1
for i in range(min(repetitions, self.maxrepeats)):
self.poutput(arg)
.. note::
The ``@with_argument_parser`` decorator sets the ``prog`` variable in
the argument parser based on the name of the method it is decorating.
This will override anything you specify in ``prog`` variable when
creating the argument parser.
Help Messages
=============
By default, cmd2 uses the docstring of the command method when a user asks
for help on the command. When you use the ``@with_argument_parser``
decorator, the docstring for the ``do_*`` method is used to set the description for the ``argparse.ArgumentParser`` is
With this code::
argparser = argparse.ArgumentParser()
argparser.add_argument('tag', help='tag')
argparser.add_argument('content', nargs='+', help='content to surround with tag')
@with_argument_parser(argparser)
def do_tag(self, args):
"""create a html tag"""
self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content)))
self.stdout.write('\n')
The ``help tag`` command displays:
.. code-block:: none
usage: tag [-h] tag content [content ...]
create a html tag
positional arguments:
tag tag
content content to surround with tag
optional arguments:
-h, --help show this help message and exit
If you would prefer you can set the ``description`` while instantiating the ``argparse.ArgumentParser`` and leave the
docstring on your method empty::
argparser = argparse.ArgumentParser(description='create an html tag')
argparser.add_argument('tag', help='tag')
argparser.add_argument('content', nargs='+', help='content to surround with tag')
@with_argument_parser(argparser)
def do_tag(self, args):
self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content)))
self.stdout.write('\n')
Now when the user enters ``help tag`` they see:
.. code-block:: none
usage: tag [-h] tag content [content ...]
create an html tag
positional arguments:
tag tag
content content to surround with tag
optional arguments:
-h, --help show this help message and exit
To add additional text to the end of the generated help message, use the ``epilog`` variable::
argparser = argparse.ArgumentParser(
description='create an html tag',
epilog='This command can not generate tags with no content, like <br/>.'
)
argparser.add_argument('tag', help='tag')
argparser.add_argument('content', nargs='+', help='content to surround with tag')
@with_argument_parser(argparser)
def do_tag(self, args):
self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content)))
self.stdout.write('\n')
Which yields:
.. code-block:: none
usage: tag [-h] tag content [content ...]
create an html tag
positional arguments:
tag tag
content content to surround with tag
optional arguments:
-h, --help show this help message and exit
This command can not generate tags with no content, like <br/>
Receiving an argument list
==========================
The default behavior of ``cmd2`` is to pass the user input directly to your
``do_*`` methods as a string. If you don't want to use the full argument parser support outlined above, you can still have ``cmd2`` apply shell parsing rules to the user input and pass you a list of arguments instead of a string. Apply the ``@with_argument_list`` decorator to those methods that should receive an argument list instead of a string::
class CmdLineApp(cmd2.Cmd):
""" Example cmd2 application. """
def do_say(self, cmdline):
# cmdline contains a string
pass
@with_argument_list
def do_speak(self, arglist):
# arglist contains a list of arguments
pass
Using the argument parser decorator and also receiving a a list of unknown positional arguments
===============================================================================================
If you want all unknown arguments to be passed to your command as a list of strings, then
decorate the command method with the ``@with_argparser_and_list`` decorator.
Here's what it looks like::
dir_parser = argparse.ArgumentParser()
dir_parser.add_argument('-l', '--long', action='store_true', help="display in long format with one item per line")
@with_argparser_and_list(dir_parser)
def do_dir(self, args, unknown):
"""List contents of current directory."""
# No arguments for this command
if unknown:
self.perror("dir does not take any positional arguments:", traceback_war=False)
self.do_help('dir')
self._last_result = CmdResult('', 'Bad arguments')
return
# Get the contents as a list
contents = os.listdir(self.cwd)
...
Deprecated optparse support
===========================
The ``optparse`` library has been deprecated since Python 2.7 (released on July
3rd 2010) and Python 3.2 (released on February 20th, 2011). ``optparse`` is
still included in the python standard library, but the documentation
recommends using ``argparse`` instead.
``cmd2`` includes a decorator which can parse arguments using ``optparse``. This decorator is deprecated just like the ``optparse`` library.
Here's an example::
opts = [make_option('-p', '--piglatin', action="store_true", help="atinLay"),
make_option('-s', '--shout', action="store_true", help="N00B EMULATION MODE"),
make_option('-r', '--repeat', type="int", help="output [n] times")]
@options(opts, arg_desc='(text to say)')
def do_speak(self, arg, opts=None):
"""Repeats what you tell me to."""
arg = ''.join(arg)
if opts.piglatin:
arg = '%s%say' % (arg[1:], arg[0])
if opts.shout:
arg = arg.upper()
repetitions = opts.repeat or 1
for i in range(min(repetitions, self.maxrepeats)):
self.poutput(arg)
The optparse decorator performs the following key functions for you:
1. Use `shlex` to split the arguments entered by the user.
2. Parse the arguments using the given optparse options.
3. Replace the `__doc__` string of the decorated function (i.e. do_speak) with the help string generated by optparse.
4. Call the decorated function (i.e. do_speak) passing an additional parameter which contains the parsed options.
|