-
Notifications
You must be signed in to change notification settings - Fork 128
Expand file tree
/
Copy pathargparse_example.py
More file actions
executable file
·176 lines (136 loc) · 7.61 KB
/
argparse_example.py
File metadata and controls
executable file
·176 lines (136 loc) · 7.61 KB
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
#!/usr/bin/env python3
"""A comprehensive example demonstrating various aspects of using `argparse` for command argument processing.
Demonstrates basic usage of the `cmd2.with_argparser` decorator for passing a `cmd2.Cmd2ArgumentParser` to a `do_*` command
method. The `fsize` and `pow` commands demonstrate various different types of arguments, actions, choices, and completers that
can be used.
The `print_args` and `print_unknown` commands display how argparse arguments are passed to commands in the cases that unknown
arguments are not captured and are captured, respectively.
The `base` and `alternate` commands show an easy way for a single command to have many subcommands, each of which take
different arguments and provides separate contextual help.
Lastly, this example shows how you can also use `argparse` to parse command-line arguments when launching a cmd2 application.
"""
import argparse
import os
import cmd2
from cmd2.string_utils import stylize
# Command categories
ARGPARSE_USAGE = 'Argparse Basic Usage'
ARGPARSE_PRINTING = 'Argparse Printing'
ARGPARSE_SUBCOMMANDS = 'Argparse Subcommands'
class ArgparsingApp(cmd2.Cmd):
def __init__(self, color: str) -> None:
"""Cmd2 application for demonstrating the use of argparse for command argument parsing."""
super().__init__(include_ipy=True)
self.intro = stylize(
'cmd2 has awesome decorators to make it easy to use Argparse to parse command arguments', style=color
)
## ------ Basic examples of using argparse for command argument parsing -----
# do_fsize parser
fsize_parser = cmd2.Cmd2ArgumentParser(description='Obtain the size of a file')
fsize_parser.add_argument('-c', '--comma', action='store_true', help='add comma for thousands separator')
fsize_parser.add_argument('-u', '--unit', choices=['MB', 'KB'], help='unit to display size in')
fsize_parser.add_argument('file_path', help='path of file', completer=cmd2.Cmd.path_complete)
@cmd2.with_argparser(fsize_parser)
@cmd2.with_category(ARGPARSE_USAGE)
def do_fsize(self, args: argparse.Namespace) -> None:
"""Obtain the size of a file."""
expanded_path = os.path.expanduser(args.file_path)
try:
size = os.path.getsize(expanded_path)
except OSError as ex:
self.perror(f"Error retrieving size: {ex}")
return
if args.unit == 'KB':
size //= 1024
elif args.unit == 'MB':
size //= 1024 * 1024
else:
args.unit = 'bytes'
size = round(size, 2)
size_str = f'{size:,}' if args.comma else f'{size}'
self.poutput(f'{size_str} {args.unit}')
# do_pow parser
pow_parser = cmd2.Cmd2ArgumentParser()
pow_parser.add_argument('base', type=int)
pow_parser.add_argument('exponent', type=int, choices=range(-5, 6))
@cmd2.with_argparser(pow_parser)
@cmd2.with_category(ARGPARSE_USAGE)
def do_pow(self, args: argparse.Namespace) -> None:
"""Raise an integer to a small integer exponent, either positive or negative.
:param args: argparse arguments
"""
self.poutput(f'{args.base} ** {args.exponent} == {args.base**args.exponent}')
## ------ Examples displaying how argparse arguments are passed to commands by printing them out -----
argprint_parser = cmd2.Cmd2ArgumentParser()
argprint_parser.add_argument('-p', '--piglatin', action='store_true', help='atinLay')
argprint_parser.add_argument('-s', '--shout', action='store_true', help='N00B EMULATION MODE')
argprint_parser.add_argument('-r', '--repeat', type=int, help='output [n] times')
argprint_parser.add_argument('words', nargs='+', help='words to print')
@cmd2.with_argparser(argprint_parser)
@cmd2.with_category(ARGPARSE_PRINTING)
def do_print_args(self, args: argparse.Namespace) -> None:
"""Print the arpgarse argument list this command was called with."""
self.poutput(f'print_args was called with the following\n\targuments: {args!r}')
unknownprint_parser = cmd2.Cmd2ArgumentParser()
unknownprint_parser.add_argument('-p', '--piglatin', action='store_true', help='atinLay')
unknownprint_parser.add_argument('-s', '--shout', action='store_true', help='N00B EMULATION MODE')
unknownprint_parser.add_argument('-r', '--repeat', type=int, help='output [n] times')
@cmd2.with_argparser(unknownprint_parser, with_unknown_args=True)
@cmd2.with_category(ARGPARSE_PRINTING)
def do_print_unknown(self, args: argparse.Namespace, unknown: list[str]) -> None:
"""Print the arpgarse argument list this command was called with, including unknown arguments."""
self.poutput(f'print_unknown was called with the following arguments\n\tknown: {args!r}\n\tunknown: {unknown}')
## ------ Examples demonstrating how to use argparse subcommands -----
# create the top-level parser for the base command
calculate_parser = cmd2.Cmd2ArgumentParser(description="Perform simple mathematical calculations.")
calculate_subparsers = calculate_parser.add_subparsers(title='operation', help='Available operations', required=True)
# create the parser for the "add" subcommand
add_description = "Add two numbers"
add_parser = cmd2.Cmd2ArgumentParser("add", description=add_description)
add_parser.add_argument('num1', type=int, help='The first number')
add_parser.add_argument('num2', type=int, help='The second number')
# create the parser for the "add" subcommand
subtract_description = "Subtract two numbers"
subtract_parser = cmd2.Cmd2ArgumentParser("subtract", description=subtract_description)
subtract_parser.add_argument('num1', type=int, help='The first number')
subtract_parser.add_argument('num2', type=int, help='The second number')
# subcommand functions for the calculate command
@cmd2.as_subcommand_to('calculate', 'add', add_parser, help=add_description.lower())
def add(self, args: argparse.Namespace) -> None:
"""add subcommand of calculate command."""
result = args.num1 + args.num2
self.poutput(f"{args.num1} + {args.num2} = {result}")
@cmd2.as_subcommand_to('calculate', 'subtract', subtract_parser, help=subtract_description.lower())
def subtract(self, args: argparse.Namespace) -> None:
"""subtract subcommand of calculate command."""
result = args.num1 - args.num2
self.poutput(f"{args.num1} - {args.num2} = {result}")
@cmd2.with_argparser(calculate_parser)
@cmd2.with_category(ARGPARSE_SUBCOMMANDS)
def do_calculate(self, args: argparse.Namespace) -> None:
"""Calculate a simple mathematical operation on two integers."""
handler = args.cmd2_handler.get()
handler(args)
if __name__ == '__main__':
import sys
from cmd2.colors import Color
# You can do your custom Argparse parsing here to meet your application's needs
parser = cmd2.Cmd2ArgumentParser(description='Process the arguments however you like.')
# Add an argument which we will pass to the app to change some behavior
parser.add_argument(
'-c',
'--color',
choices=[Color.RED, Color.ORANGE1, Color.YELLOW, Color.GREEN, Color.BLUE, Color.PURPLE, Color.VIOLET, Color.WHITE],
help='Color of intro text',
)
# Parse the arguments
args, unknown_args = parser.parse_known_args()
color = Color.WHITE
if args.color:
color = args.color
# Perform surgery on sys.argv to remove the arguments which have already been processed by argparse
sys.argv = sys.argv[:1] + unknown_args
# Instantiate your cmd2 application
app = ArgparsingApp(color)
# And run your cmd2 application
sys.exit(app.cmdloop())