Statistics
| Branch: | Tag: | Revision:

root / docs / developers / adding-commands.rst @ 16d7b9ff

History | View | Annotate | Download (12.8 kB)

1 9e4508df Stavros Sachtouris
Adding Commands
2 9e4508df Stavros Sachtouris
===============
3 9e4508df Stavros Sachtouris
4 fa382f9e Stavros Sachtouris
Kamaki commands are implemented as python classes, decorated with a special
5 16d7b9ff Stavros Sachtouris
decorator called *command*. This decorator is a method of *kamaki.cli* that
6 16d7b9ff Stavros Sachtouris
adds a new command in a *CommandTree* structure. A *CommandTree* (package
7 16d7b9ff Stavros Sachtouris
*kamaki.cli.commant_tree*) is a data structure used by kamaki to manage command
8 16d7b9ff Stavros Sachtouris
namespaces.
9 9e4508df Stavros Sachtouris
10 16d7b9ff Stavros Sachtouris
For demonstration purposes, the following set of kamaki commands will be
11 16d7b9ff Stavros Sachtouris
implemented in this document::
12 9e4508df Stavros Sachtouris
13 9e4508df Stavros Sachtouris
    mygrp1 list all                         //show a list
14 9e4508df Stavros Sachtouris
    mygrp1 list details [--match=<>]        //show list of details
15 9e4508df Stavros Sachtouris
    mygrp2 list all [regular expression] [-l]       //list all subjects
16 9e4508df Stavros Sachtouris
    mygrp2 info <id> [name]      //get information for subject with id
17 9e4508df Stavros Sachtouris
18 16d7b9ff Stavros Sachtouris
There are two command groups to implement i.e., *mygrp1* and *mygrp2*,
19 16d7b9ff Stavros Sachtouris
containing two commands each (*list_all*, *list_details* and *list_all*, *info*
20 16d7b9ff Stavros Sachtouris
respectively). To avoid ambiguities, command names are prefixed with the
21 16d7b9ff Stavros Sachtouris
command group they belong to, e.g., *mygrp1_list_all* and *mygrp2_list_all*.
22 16d7b9ff Stavros Sachtouris
The underscore is used to separate command namespaces.
23 9e4508df Stavros Sachtouris
24 16d7b9ff Stavros Sachtouris
The first command (*mygrp1_list_all*) has the simplest possible syntax: no
25 16d7b9ff Stavros Sachtouris
parameters, no runtime arguments. The second accepts an optional runtime argument with a value. The third features an optional parameter and an optional
26 16d7b9ff Stavros Sachtouris
runtime flag argument. The last is an example of a command with an obligatory
27 16d7b9ff Stavros Sachtouris
and an optional parameter.
28 9e4508df Stavros Sachtouris
29 16d7b9ff Stavros Sachtouris
Examples of the expected behavior in one-command mode:
30 9e4508df Stavros Sachtouris
31 9e4508df Stavros Sachtouris
.. code-block:: console
32 9e4508df Stavros Sachtouris
33 9e4508df Stavros Sachtouris
    $kamaki mygrp1
34 9e4508df Stavros Sachtouris
        mygrp1 description
35 9e4508df Stavros Sachtouris
36 9e4508df Stavros Sachtouris
        Options
37 9e4508df Stavros Sachtouris
         - - - -
38 9e4508df Stavros Sachtouris
        list
39 9e4508df Stavros Sachtouris
    $ kamaki mygrp1 list
40 9e4508df Stavros Sachtouris
41 9e4508df Stavros Sachtouris
        Options
42 9e4508df Stavros Sachtouris
         - - - -
43 9e4508df Stavros Sachtouris
        all        show a list
44 9e4508df Stavros Sachtouris
        details     show a list of details
45 9e4508df Stavros Sachtouris
    $ kamaki mygrp1 list all
46 16d7b9ff Stavros Sachtouris
        ... (a mygrp1_list_all instance runs) ...
47 9e4508df Stavros Sachtouris
    $ kamaki mygrp2 list all 'Z[.]' -l
48 16d7b9ff Stavros Sachtouris
        ... (a mygrp2_list_all instance runs) ...
49 9e4508df Stavros Sachtouris
    $
50 9e4508df Stavros Sachtouris
51 9e4508df Stavros Sachtouris
The CommandTree structure
52 9e4508df Stavros Sachtouris
-------------------------
53 9e4508df Stavros Sachtouris
54 16d7b9ff Stavros Sachtouris
CommandTree manages a command by its namespace. Each command is stored in
55 16d7b9ff Stavros Sachtouris
a tree path, where each node is a name. A leaf is the end term of a namespace and contains a pointer to the command class to be executed.
56 16d7b9ff Stavros Sachtouris
57 16d7b9ff Stavros Sachtouris
Here is an example from the actual kamaki command structure, where the commands
58 16d7b9ff Stavros Sachtouris
*file upload*, *file list* and *file info* are represented as shown bellow::
59 9e4508df Stavros Sachtouris
60 0ea31480 Stavros Sachtouris
    - file
61 9e4508df Stavros Sachtouris
    ''''''''|- info
62 9e4508df Stavros Sachtouris
            |- list
63 9e4508df Stavros Sachtouris
            |- upload
64 9e4508df Stavros Sachtouris
65 16d7b9ff Stavros Sachtouris
Now, let's load the showcase example on CommandTrees::
66 9e4508df Stavros Sachtouris
67 9e4508df Stavros Sachtouris
    - mygrp1
68 9e4508df Stavros Sachtouris
    ''''''''|- list
69 9e4508df Stavros Sachtouris
            '''''''|- all
70 9e4508df Stavros Sachtouris
                   |- details
71 9e4508df Stavros Sachtouris
72 9e4508df Stavros Sachtouris
    - mygrp2
73 9e4508df Stavros Sachtouris
    ''''''''|- list
74 9e4508df Stavros Sachtouris
            '''''''|- all
75 9e4508df Stavros Sachtouris
            |- info
76 9e4508df Stavros Sachtouris
77 16d7b9ff Stavros Sachtouris
Each command group should be stored on a different CommandTree.
78 16d7b9ff Stavros Sachtouris
79 16d7b9ff Stavros Sachtouris
For that reason, command specification modules should contain a list of CommandTree objects, named *_commands*. This mechanism allows any interface
80 16d7b9ff Stavros Sachtouris
application to load the list of commands from the *_commands* array.
81 9e4508df Stavros Sachtouris
82 16d7b9ff Stavros Sachtouris
The first name of the command path and a description (name, description) are needed to initializeg a CommandTree:
83 9e4508df Stavros Sachtouris
84 9e4508df Stavros Sachtouris
.. code-block:: python
85 9e4508df Stavros Sachtouris
86 9e4508df Stavros Sachtouris
    _mygrp1_commands = CommandTree('mygrp', 'mygrp1 description')
87 9e4508df Stavros Sachtouris
    _mygrp2_commands = CommandTree('mygrp', 'mygrp2 description')
88 9e4508df Stavros Sachtouris
89 9e4508df Stavros Sachtouris
    _commands = [_mygrp1_commands, _mygrp2_commands]
90 9e4508df Stavros Sachtouris
91 16d7b9ff Stavros Sachtouris
92 9e4508df Stavros Sachtouris
The command decorator
93 9e4508df Stavros Sachtouris
---------------------
94 9e4508df Stavros Sachtouris
95 16d7b9ff Stavros Sachtouris
All commands are specified by subclasses of *kamaki.cli.commands._command_init*
96 16d7b9ff Stavros Sachtouris
These classes are called "command specifications".
97 16d7b9ff Stavros Sachtouris
98 16d7b9ff Stavros Sachtouris
The *command* decorator mines all the information needed to build a namespace
99 16d7b9ff Stavros Sachtouris
from a command specification::
100 9e4508df Stavros Sachtouris
101 9e4508df Stavros Sachtouris
    class code  --->  command()  -->  updated CommandTree structure
102 9e4508df Stavros Sachtouris
103 16d7b9ff Stavros Sachtouris
Kamaki interfaces make use of the CommandTree structure. Optimizations are
104 fa382f9e Stavros Sachtouris
possible by using special parameters on the command decorator method.
105 9e4508df Stavros Sachtouris
106 9e4508df Stavros Sachtouris
.. code-block:: python
107 9e4508df Stavros Sachtouris
108 9e4508df Stavros Sachtouris
    def command(cmd_tree, prefix='', descedants_depth=None):
109 9e4508df Stavros Sachtouris
    """Load a class as a command
110 fa382f9e Stavros Sachtouris
111 59cadffb Stavros Sachtouris
        :param cmd_tree: is the CommandTree to be updated with a new command
112 fa382f9e Stavros Sachtouris
113 59cadffb Stavros Sachtouris
        :param prefix: of the commands allowed to be inserted ('' for all)
114 fa382f9e Stavros Sachtouris
115 16d7b9ff Stavros Sachtouris
        :param descedants_depth: is the depth of the tree descendants of the
116 9e4508df Stavros Sachtouris
            prefix command.
117 9e4508df Stavros Sachtouris
    """
118 9e4508df Stavros Sachtouris
119 9e4508df Stavros Sachtouris
Creating a new command specification set
120 9e4508df Stavros Sachtouris
----------------------------------------
121 9e4508df Stavros Sachtouris
122 16d7b9ff Stavros Sachtouris
A command specification developer should create a new module (python file) with
123 16d7b9ff Stavros Sachtouris
one command specification class per command. Each class should be decorated
124 16d7b9ff Stavros Sachtouris
with *command*.
125 9e4508df Stavros Sachtouris
126 9e4508df Stavros Sachtouris
.. code-block:: python
127 9e4508df Stavros Sachtouris
128 9e4508df Stavros Sachtouris
    ...
129 9e4508df Stavros Sachtouris
    _commands = [_mygrp1_commands, _mygrp2_commands]
130 9e4508df Stavros Sachtouris
131 9e4508df Stavros Sachtouris
    @command(_mygrp1_commands)
132 9e4508df Stavros Sachtouris
    class mygrp1_list_all():
133 9e4508df Stavros Sachtouris
        ...
134 9e4508df Stavros Sachtouris
135 9e4508df Stavros Sachtouris
    ...
136 9e4508df Stavros Sachtouris
137 fa382f9e Stavros Sachtouris
A list of CommandTree structures must exist in the module scope, with the name
138 16d7b9ff Stavros Sachtouris
*_commands*. Different CommandTree objects correspond to different command
139 16d7b9ff Stavros Sachtouris
groups.
140 9e4508df Stavros Sachtouris
141 16d7b9ff Stavros Sachtouris
Set command description
142 9e4508df Stavros Sachtouris
-----------------------
143 9e4508df Stavros Sachtouris
144 fa382f9e Stavros Sachtouris
The description of each command is the first line of the class commend. The
145 fa382f9e Stavros Sachtouris
following declaration of *mygrp2-info* command has a "*get information for
146 fa382f9e Stavros Sachtouris
subject with id*" description.
147 9e4508df Stavros Sachtouris
148 9e4508df Stavros Sachtouris
.. code-block:: python
149 9e4508df Stavros Sachtouris
150 9e4508df Stavros Sachtouris
    ...
151 9e4508df Stavros Sachtouris
    @command(_mygrp2_commands)
152 16d7b9ff Stavros Sachtouris
    class mygrp2_info():
153 16d7b9ff Stavros Sachtouris
        """get information for subject with id
154 16d7b9ff Stavros Sachtouris
        Anything from this point and bellow constitutes the long description
155 16d7b9ff Stavros Sachtouris
        Please, mind the indentation, pep8 is not forgiving.
156 16d7b9ff Stavros Sachtouris
        """
157 9e4508df Stavros Sachtouris
        ...
158 9e4508df Stavros Sachtouris
159 16d7b9ff Stavros Sachtouris
Description placeholders
160 16d7b9ff Stavros Sachtouris
------------------------
161 16d7b9ff Stavros Sachtouris
162 16d7b9ff Stavros Sachtouris
There is possible to create an empty command, that can act as a description
163 16d7b9ff Stavros Sachtouris
placeholder. For example, the *mygrp1_list* namespace does not correspond to an
164 16d7b9ff Stavros Sachtouris
executable command, but it can have a helpful description. In that case, create
165 16d7b9ff Stavros Sachtouris
a command specification class with a command and no code:
166 16d7b9ff Stavros Sachtouris
167 16d7b9ff Stavros Sachtouris
.. code-block:: python
168 16d7b9ff Stavros Sachtouris
169 16d7b9ff Stavros Sachtouris
    @command(_mygrp1_commands)
170 16d7b9ff Stavros Sachtouris
    class mygrp1_list():
171 16d7b9ff Stavros Sachtouris
        """List mygrp1 objects.
172 16d7b9ff Stavros Sachtouris
        There are two versions: short and detailed
173 16d7b9ff Stavros Sachtouris
        """
174 16d7b9ff Stavros Sachtouris
175 16d7b9ff Stavros Sachtouris
.. warning:: A command specification class with no description is invalid and
176 16d7b9ff Stavros Sachtouris
    will cause an error.
177 16d7b9ff Stavros Sachtouris
178 9e4508df Stavros Sachtouris
Declare run-time argument
179 9e4508df Stavros Sachtouris
-------------------------
180 9e4508df Stavros Sachtouris
181 16d7b9ff Stavros Sachtouris
A special argument mechanism allows the definition of run-time arguments. This
182 16d7b9ff Stavros Sachtouris
mechanism is based on argparse and is designed to simplify argument definitions
183 16d7b9ff Stavros Sachtouris
when specifying commands.
184 16d7b9ff Stavros Sachtouris
185 16d7b9ff Stavros Sachtouris
Some basic argument types are defined at the
186 fa382f9e Stavros Sachtouris
`argument module <code.html#module-kamaki.cli.argument>`_, but it is not
187 16d7b9ff Stavros Sachtouris
a bad idea to extent these classes in order to achieve specialized type
188 16d7b9ff Stavros Sachtouris
checking and syntax control. Still, in most cases, the argument types of the
189 16d7b9ff Stavros Sachtouris
argument package are enough for most cases.
190 9e4508df Stavros Sachtouris
191 16d7b9ff Stavros Sachtouris
To declare a run-time argument on a specific command, the specification class
192 16d7b9ff Stavros Sachtouris
should contain a dict called *arguments* , where Argument objects are stored.
193 16d7b9ff Stavros Sachtouris
Each argument object is a run-time argument. Syntax checking happens at client
194 16d7b9ff Stavros Sachtouris
level, while the type checking is implemented in the Argument code (e.g.,
195 16d7b9ff Stavros Sachtouris
IntArgument checks if the value is an int).
196 9e4508df Stavros Sachtouris
197 9e4508df Stavros Sachtouris
.. code-block:: python
198 9e4508df Stavros Sachtouris
199 9e4508df Stavros Sachtouris
    from kamaki.cli.argument import ValueArgument
200 9e4508df Stavros Sachtouris
    ...
201 9e4508df Stavros Sachtouris
202 9e4508df Stavros Sachtouris
    @command(_mygrp1_commands)
203 9e4508df Stavros Sachtouris
    class mygrp1_list_details():
204 9e4508df Stavros Sachtouris
        """list of details"""
205 9e4508df Stavros Sachtouris
206 59cadffb Stavros Sachtouris
        def __init__(self, global_args={}):
207 9e4508df Stavros Sachtouris
            global_args['match'] = ValueArgument(
208 9e4508df Stavros Sachtouris
                'Filter results to match string',
209 fa382f9e Stavros Sachtouris
                ('-m', '--match'))
210 9e4508df Stavros Sachtouris
            self.arguments = global_args
211 9e4508df Stavros Sachtouris
212 fa382f9e Stavros Sachtouris
or more usually and elegantly:
213 fa382f9e Stavros Sachtouris
214 fa382f9e Stavros Sachtouris
.. code-block:: python
215 fa382f9e Stavros Sachtouris
216 fa382f9e Stavros Sachtouris
    from kamaki.cli.argument import ValueArgument
217 fa382f9e Stavros Sachtouris
    
218 fa382f9e Stavros Sachtouris
    @command(_mygrp1_commands)
219 fa382f9e Stavros Sachtouris
    class mygrp1_list_details():
220 fa382f9e Stavros Sachtouris
    """List of details"""
221 fa382f9e Stavros Sachtouris
222 fa382f9e Stavros Sachtouris
        arguments = dict(
223 fa382f9e Stavros Sachtouris
            match=ValueArgument(
224 16d7b9ff Stavros Sachtouris
                'Filter output to match string', ('-m', --match'))
225 fa382f9e Stavros Sachtouris
        )
226 fa382f9e Stavros Sachtouris
227 fa382f9e Stavros Sachtouris
Accessing run-time arguments
228 fa382f9e Stavros Sachtouris
----------------------------
229 fa382f9e Stavros Sachtouris
230 16d7b9ff Stavros Sachtouris
To access run-time arguments, users can use the *_command_init* interface,
231 16d7b9ff Stavros Sachtouris
which implements *__item__* accessors to handle run-time argument values. In
232 16d7b9ff Stavros Sachtouris
other words, one may get the value of an argument with *self[<argument>]*.
233 fa382f9e Stavros Sachtouris
234 fa382f9e Stavros Sachtouris
.. code-block:: python
235 fa382f9e Stavros Sachtouris
236 fa382f9e Stavros Sachtouris
    from kamaki.cli.argument import ValueArgument
237 fa382f9e Stavros Sachtouris
    from kamaki.cli.commands import _command_init
238 fa382f9e Stavros Sachtouris
    
239 fa382f9e Stavros Sachtouris
    @command(_mygrp1_commands)
240 fa382f9e Stavros Sachtouris
    class mygrp1_list_details(_command_init):
241 fa382f9e Stavros Sachtouris
        """List of details"""
242 fa382f9e Stavros Sachtouris
243 fa382f9e Stavros Sachtouris
        arguments = dict(
244 fa382f9e Stavros Sachtouris
            match=ValueArgument(
245 fa382f9e Stavros Sachtouris
                'Filter output to match string', ('-m', --match'))
246 fa382f9e Stavros Sachtouris
        )
247 fa382f9e Stavros Sachtouris
248 fa382f9e Stavros Sachtouris
        def check_runtime_arguments(self):
249 fa382f9e Stavros Sachtouris
            ...
250 fa382f9e Stavros Sachtouris
            assert self['match'] == self.arguments['match'].value
251 fa382f9e Stavros Sachtouris
            ...
252 fa382f9e Stavros Sachtouris
253 9e4508df Stavros Sachtouris
The main method and command parameters
254 9e4508df Stavros Sachtouris
--------------------------------------
255 9e4508df Stavros Sachtouris
256 16d7b9ff Stavros Sachtouris
The command behavior for each command class is coded in *main*. The
257 16d7b9ff Stavros Sachtouris
parameters of *main* method affect the syntax of the command. In specific::
258 9e4508df Stavros Sachtouris
259 59cadffb Stavros Sachtouris
    main(self, param)                   - obligatory parameter <param>
260 59cadffb Stavros Sachtouris
    main(self, param=None)              - optional parameter [param]
261 9e4508df Stavros Sachtouris
    main(self, param1, param2=42)       - <param1> [param2]
262 9e4508df Stavros Sachtouris
    main(self, param1____param2)        - <param1:param2>
263 9e4508df Stavros Sachtouris
    main(self, param1____param2=[])     - [param1:param2]
264 9e4508df Stavros Sachtouris
    main(self, param1____param2__)      - <param1[:param2]>
265 9e4508df Stavros Sachtouris
    main(self, param1____param2__='')   - [param1[:param2]]
266 9e4508df Stavros Sachtouris
    main(self, *args)                   - arbitary number of params [...]
267 9e4508df Stavros Sachtouris
    main(self, param1____param2, *args) - <param1:param2> [...]
268 9e4508df Stavros Sachtouris
269 16d7b9ff Stavros Sachtouris
Let's have a look at the command specification class again, and highlight the
270 16d7b9ff Stavros Sachtouris
parts that affect the command syntax:
271 9e4508df Stavros Sachtouris
272 9e4508df Stavros Sachtouris
.. code-block:: python
273 9e4508df Stavros Sachtouris
    :linenos:
274 9e4508df Stavros Sachtouris
275 9e4508df Stavros Sachtouris
    from kamaki.cli.argument import FlagArgument
276 9e4508df Stavros Sachtouris
    ...
277 9e4508df Stavros Sachtouris
278 16d7b9ff Stavros Sachtouris
    _commands = [_mygrp1_commands, _mygrp2_commands]
279 9e4508df Stavros Sachtouris
    ...
280 9e4508df Stavros Sachtouris
281 9e4508df Stavros Sachtouris
    @command(_mygrp2_commands)
282 fa382f9e Stavros Sachtouris
    class mygrp2_list_all():
283 16d7b9ff Stavros Sachtouris
        """List all subjects
284 16d7b9ff Stavros Sachtouris
        Refers to the subject accessible by current user
285 16d7b9ff Stavros Sachtouris
        """
286 9e4508df Stavros Sachtouris
287 fa382f9e Stavros Sachtouris
        arguments = dict(FlagArgument('detailed list', '-l'))
288 9e4508df Stavros Sachtouris
289 9e4508df Stavros Sachtouris
        def main(self, reg_exp=None):
290 9e4508df Stavros Sachtouris
            ...
291 9e4508df Stavros Sachtouris
292 16d7b9ff Stavros Sachtouris
The above lines contain the following information:
293 16d7b9ff Stavros Sachtouris
294 16d7b9ff Stavros Sachtouris
* Namespace and name (line 8): mygrp2 list all
295 16d7b9ff Stavros Sachtouris
* Short (line 9) and long (line 10) description
296 16d7b9ff Stavros Sachtouris
* Parameters (line 15): [reg exp]
297 16d7b9ff Stavros Sachtouris
* Runtime arguments (line 13): [-l]
298 16d7b9ff Stavros Sachtouris
* Runtime arguments help (line 13): detailed list
299 9e4508df Stavros Sachtouris
300 16d7b9ff Stavros Sachtouris
.. tip:: It is suggested to code the main functionality in a member method
301 16d7b9ff Stavros Sachtouris
    called *_run*. This allows the separation between syntax and logic. For
302 16d7b9ff Stavros Sachtouris
    example, an external library may need to call a command without caring
303 16d7b9ff Stavros Sachtouris
    about its command line behavior.
304 9e4508df Stavros Sachtouris
305 9e4508df Stavros Sachtouris
Letting kamaki know
306 9e4508df Stavros Sachtouris
-------------------
307 9e4508df Stavros Sachtouris
308 fa382f9e Stavros Sachtouris
Kamaki will load a command specification *only* if it is set as a configurable
309 fa382f9e Stavros Sachtouris
option. To demonstrate this, let the command specifications coded above be
310 fa382f9e Stavros Sachtouris
stored in a file named *grps.py*.
311 9e4508df Stavros Sachtouris
312 16d7b9ff Stavros Sachtouris
The developer should move the file *grps.py* to *kamaki/cli/commands*, the
313 16d7b9ff Stavros Sachtouris
default place for command specifications
314 9e4508df Stavros Sachtouris
315 16d7b9ff Stavros Sachtouris
These lines should be contained in the kamaki configuration file for a new
316 16d7b9ff Stavros Sachtouris
command specification module to work:
317 9e4508df Stavros Sachtouris
::
318 9e4508df Stavros Sachtouris
319 fa382f9e Stavros Sachtouris
    [global]
320 fa382f9e Stavros Sachtouris
    mygrp1_cli = grps
321 fa382f9e Stavros Sachtouris
    mygrp2_cli = grps
322 9e4508df Stavros Sachtouris
323 fa382f9e Stavros Sachtouris
or equivalently:
324 9e4508df Stavros Sachtouris
325 9e4508df Stavros Sachtouris
.. code-block:: console
326 9e4508df Stavros Sachtouris
327 fa382f9e Stavros Sachtouris
    $ kamaki config set mygrp1_cli grps
328 fa382f9e Stavros Sachtouris
    $ kamaki config set mygrp2_cli grps
329 9e4508df Stavros Sachtouris
330 16d7b9ff Stavros Sachtouris
.. note:: running a command specification from a different path is supported.
331 16d7b9ff Stavros Sachtouris
    To achieve this, add a *<group>_cli = </path/to/module>* line in the
332 16d7b9ff Stavros Sachtouris
    configure file under the *global* section.
333 16d7b9ff Stavros Sachtouris
::
334 9e4508df Stavros Sachtouris
335 fa382f9e Stavros Sachtouris
    [global]
336 fa382f9e Stavros Sachtouris
    mygrp_cli = /another/path/grps.py
337 9e4508df Stavros Sachtouris
338 9e4508df Stavros Sachtouris
Summary: create a command set
339 9e4508df Stavros Sachtouris
-----------------------------
340 9e4508df Stavros Sachtouris
341 9e4508df Stavros Sachtouris
.. code-block:: python
342 9e4508df Stavros Sachtouris
343 9e4508df Stavros Sachtouris
    #  File: grps.py
344 9e4508df Stavros Sachtouris
345 fa382f9e Stavros Sachtouris
    from kamaki.cli.commands import _command_init
346 9e4508df Stavros Sachtouris
    from kamaki.cli.command_tree import CommandTree
347 9e4508df Stavros Sachtouris
    from kamaki.cli.argument import ValueArgument, FlagArgument
348 9e4508df Stavros Sachtouris
    ...
349 9e4508df Stavros Sachtouris
350 9e4508df Stavros Sachtouris
351 9e4508df Stavros Sachtouris
    #  Initiallize command trees
352 9e4508df Stavros Sachtouris
353 9e4508df Stavros Sachtouris
    _mygrp1_commands = CommandTree('mygrp', 'mygrp1 description')
354 9e4508df Stavros Sachtouris
    _mygrp2_commands = CommandTree('mygrp', 'mygrp2 description')
355 9e4508df Stavros Sachtouris
356 9e4508df Stavros Sachtouris
    _commands = [_mygrp1_commands, _mygrp2_commands]
357 9e4508df Stavros Sachtouris
358 9e4508df Stavros Sachtouris
359 9e4508df Stavros Sachtouris
    #  Define command specifications
360 9e4508df Stavros Sachtouris
361 9e4508df Stavros Sachtouris
362 9e4508df Stavros Sachtouris
    @command(_mygrp1_commands)
363 16d7b9ff Stavros Sachtouris
    class mygrp1_list(_command_init):
364 16d7b9ff Stavros Sachtouris
        """List mygrp1 objects.
365 16d7b9ff Stavros Sachtouris
        There are two versions: short and detailed
366 16d7b9ff Stavros Sachtouris
        """
367 16d7b9ff Stavros Sachtouris
368 16d7b9ff Stavros Sachtouris
369 16d7b9ff Stavros Sachtouris
    @command(_mygrp1_commands)
370 fa382f9e Stavros Sachtouris
    class mygrp1_list_all(_command_init):
371 9e4508df Stavros Sachtouris
        """show a list"""
372 9e4508df Stavros Sachtouris
373 16d7b9ff Stavros Sachtouris
        def _run():
374 9e4508df Stavros Sachtouris
            ...
375 9e4508df Stavros Sachtouris
376 16d7b9ff Stavros Sachtouris
        def main(self):
377 16d7b9ff Stavros Sachtouris
            self._run()
378 16d7b9ff Stavros Sachtouris
379 9e4508df Stavros Sachtouris
380 9e4508df Stavros Sachtouris
    @command(_mygrp1_commands)
381 fa382f9e Stavros Sachtouris
    class mygrp1_list_details(_command_init):
382 9e4508df Stavros Sachtouris
        """show list of details"""
383 9e4508df Stavros Sachtouris
384 fa382f9e Stavros Sachtouris
        arguments = dict(
385 fa382f9e Stavros Sachtouris
            match=ValueArgument(
386 fa382f9e Stavros Sachtouris
                'Filter output to match string', ('-m', --match'))
387 fa382f9e Stavros Sachtouris
        )
388 9e4508df Stavros Sachtouris
389 16d7b9ff Stavros Sachtouris
        def _run(self):
390 fa382f9e Stavros Sachtouris
            match_value = self['match']
391 9e4508df Stavros Sachtouris
            ...
392 9e4508df Stavros Sachtouris
393 16d7b9ff Stavros Sachtouris
        def main(self):
394 16d7b9ff Stavros Sachtouris
        self._run()
395 16d7b9ff Stavros Sachtouris
396 16d7b9ff Stavros Sachtouris
397 16d7b9ff Stavros Sachtouris
    #The following will also create a mygrp2_list command with no description
398 16d7b9ff Stavros Sachtouris
399 9e4508df Stavros Sachtouris
400 9e4508df Stavros Sachtouris
    @command(_mygrp2_commands)
401 fa382f9e Stavros Sachtouris
    class mygrp2_list_all(_command_init):
402 9e4508df Stavros Sachtouris
        """list all subjects"""
403 9e4508df Stavros Sachtouris
404 fa382f9e Stavros Sachtouris
        arguments = dict(
405 fa382f9e Stavros Sachtouris
            list=FlagArgument('detailed listing', '-l')
406 fa382f9e Stavros Sachtouris
        )
407 9e4508df Stavros Sachtouris
408 16d7b9ff Stavros Sachtouris
        def _run(self, regexp):
409 9e4508df Stavros Sachtouris
            ...
410 16d7b9ff Stavros Sachtouris
            if self['list']:
411 9e4508df Stavros Sachtouris
                ...
412 16d7b9ff Stavros Sachtouris
            else:
413 9e4508df Stavros Sachtouris
                ...
414 16d7b9ff Stavros Sachtouris
415 16d7b9ff Stavros Sachtouris
        def main(self, regular_expression=None):
416 16d7b9ff Stavros Sachtouris
            self._run(regular_expression)
417 9e4508df Stavros Sachtouris
418 9e4508df Stavros Sachtouris
419 9e4508df Stavros Sachtouris
    @command(_mygrp2_commands)
420 fa382f9e Stavros Sachtouris
    class mygrp2_info(_command_init):
421 9e4508df Stavros Sachtouris
        """get information for subject with id"""
422 9e4508df Stavros Sachtouris
423 16d7b9ff Stavros Sachtouris
        def _run(self, grp_id, grp_name):
424 9e4508df Stavros Sachtouris
            ...
425 16d7b9ff Stavros Sachtouris
426 16d7b9ff Stavros Sachtouris
        def main(self, id, name=''):
427 16d7b9ff Stavros Sachtouris
            self._run(id, name)