forked from python-cmd2/cmd2
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmodular_subcommands.py
118 lines (91 loc) · 3.91 KB
/
modular_subcommands.py
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
#!/usr/bin/env python3
# coding=utf-8
"""A simple example demonstrating modular subcommand loading through CommandSets
In this example, there are loadable CommandSets defined. Each CommandSet has 1 subcommand defined that will be
attached to the 'cut' command.
The cut command is implemented with the `do_cut` function that has been tagged as an argparse command.
The `load` and `unload` command will load and unload the CommandSets. The available top level commands as well as
subcommands to the `cut` command will change depending on which CommandSets are loaded.
"""
import argparse
import cmd2
from cmd2 import (
CommandSet,
with_argparser,
with_category,
with_default_category,
)
@with_default_category('Fruits')
class LoadableFruits(CommandSet):
def __init__(self):
super().__init__()
def do_apple(self, _: cmd2.Statement):
self._cmd.poutput('Apple')
banana_description = "Cut a banana"
banana_parser = cmd2.Cmd2ArgumentParser(description=banana_description)
banana_parser.add_argument('direction', choices=['discs', 'lengthwise'])
@cmd2.as_subcommand_to('cut', 'banana', banana_parser, help=banana_description.lower())
def cut_banana(self, ns: argparse.Namespace):
"""Cut banana"""
self._cmd.poutput('cutting banana: ' + ns.direction)
@with_default_category('Vegetables')
class LoadableVegetables(CommandSet):
def __init__(self):
super().__init__()
def do_arugula(self, _: cmd2.Statement):
self._cmd.poutput('Arugula')
bokchoy_description = "Cut some bokchoy"
bokchoy_parser = cmd2.Cmd2ArgumentParser(description=bokchoy_description)
bokchoy_parser.add_argument('style', choices=['quartered', 'diced'])
@cmd2.as_subcommand_to('cut', 'bokchoy', bokchoy_parser, help=bokchoy_description.lower())
def cut_bokchoy(self, _: argparse.Namespace):
self._cmd.poutput('Bok Choy')
class ExampleApp(cmd2.Cmd):
"""
CommandSets are automatically loaded. Nothing needs to be done.
"""
def __init__(self, *args, **kwargs):
# gotta have this or neither the plugin or cmd2 will initialize
super().__init__(*args, auto_load_commands=False, **kwargs)
self._fruits = LoadableFruits()
self._vegetables = LoadableVegetables()
load_parser = cmd2.Cmd2ArgumentParser()
load_parser.add_argument('cmds', choices=['fruits', 'vegetables'])
@with_argparser(load_parser)
@with_category('Command Loading')
def do_load(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
try:
self.register_command_set(self._fruits)
self.poutput('Fruits loaded')
except ValueError:
self.poutput('Fruits already loaded')
if ns.cmds == 'vegetables':
try:
self.register_command_set(self._vegetables)
self.poutput('Vegetables loaded')
except ValueError:
self.poutput('Vegetables already loaded')
@with_argparser(load_parser)
def do_unload(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
self.unregister_command_set(self._fruits)
self.poutput('Fruits unloaded')
if ns.cmds == 'vegetables':
self.unregister_command_set(self._vegetables)
self.poutput('Vegetables unloaded')
cut_parser = cmd2.Cmd2ArgumentParser()
cut_subparsers = cut_parser.add_subparsers(title='item', help='item to cut')
@with_argparser(cut_parser)
def do_cut(self, ns: argparse.Namespace):
# Call handler for whatever subcommand was selected
handler = ns.cmd2_handler.get()
if handler is not None:
handler(ns)
else:
# No subcommand was provided, so call help
self.poutput('This command does nothing without sub-parsers registered')
self.do_help('cut')
if __name__ == '__main__':
app = ExampleApp()
app.cmdloop()