Statistics
| Branch: | Tag: | Revision:

root / docs / developers / adding-commands.rst @ ef04bdeb

History | View | Annotate | Download (11 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 fa382f9e Stavros Sachtouris
decorator called *command*. This decorator is a method of kamaki.cli that adds
6 fa382f9e Stavros Sachtouris
a new command in a CommandTree structure (kamaki.cli.commant_tree). The later
7 fa382f9e Stavros Sachtouris
is used by interfaces to manage kamaki commands.
8 9e4508df Stavros Sachtouris
9 9e4508df Stavros Sachtouris
In the following, a set of kamaki commands will be implemented::
10 9e4508df Stavros Sachtouris
11 9e4508df Stavros Sachtouris
    mygrp1 list all                         //show a list
12 9e4508df Stavros Sachtouris
    mygrp1 list details [--match=<>]        //show list of details
13 9e4508df Stavros Sachtouris
    mygrp2 list all [regular expression] [-l]       //list all subjects
14 9e4508df Stavros Sachtouris
    mygrp2 info <id> [name]      //get information for subject with id
15 9e4508df Stavros Sachtouris
16 fa382f9e Stavros Sachtouris
There are two command sets to implement, namely mygrp1 and mygrp2. The first
17 fa382f9e Stavros Sachtouris
will contain two commands, namely list-all and list-details. The second one
18 fa382f9e Stavros Sachtouris
will also contain two commands, list-all and info. To avoid ambiguities,
19 fa382f9e Stavros Sachtouris
command names should rather be prefixed with the group they belong to, e.g.
20 fa382f9e Stavros Sachtouris
mygrp1-list-all and mygrp2-list-all.
21 9e4508df Stavros Sachtouris
22 fa382f9e Stavros Sachtouris
The first command has the simplest possible syntax: no parameters, no runtime
23 fa382f9e Stavros Sachtouris
arguments. The second accepts an optional runtime argument with a value. The
24 fa382f9e Stavros Sachtouris
third features an optional argument and an optional runtime flag argument. The
25 fa382f9e Stavros Sachtouris
last is an example of a command with an obligatory and an optional argument.
26 9e4508df Stavros Sachtouris
27 9e4508df Stavros Sachtouris
Samples of the expected behavior in one-command mode are following:
28 9e4508df Stavros Sachtouris
29 9e4508df Stavros Sachtouris
.. code-block:: console
30 9e4508df Stavros Sachtouris
31 9e4508df Stavros Sachtouris
    $kamaki mygrp1
32 9e4508df Stavros Sachtouris
        mygrp1 description
33 9e4508df Stavros Sachtouris
34 9e4508df Stavros Sachtouris
        Options
35 9e4508df Stavros Sachtouris
         - - - -
36 9e4508df Stavros Sachtouris
        list
37 9e4508df Stavros Sachtouris
    $ kamaki mygrp1 list
38 9e4508df Stavros Sachtouris
        Syntax Error
39 9e4508df Stavros Sachtouris
40 9e4508df Stavros Sachtouris
        Options
41 9e4508df Stavros Sachtouris
         - - - -
42 9e4508df Stavros Sachtouris
        all        show a list
43 9e4508df Stavros Sachtouris
        details     show a list of details
44 9e4508df Stavros Sachtouris
    $ kamaki mygrp1 list all
45 9e4508df Stavros Sachtouris
        ... (mygrp1 client method is called) ...
46 9e4508df Stavros Sachtouris
    $ kamaki mygrp2 list all 'Z[.]' -l
47 9e4508df Stavros Sachtouris
        ... (mygrp2 client method is called) ...
48 9e4508df Stavros Sachtouris
    $
49 9e4508df Stavros Sachtouris
50 fa382f9e Stavros Sachtouris
The above example will be used throughout the present guide.
51 9e4508df Stavros Sachtouris
52 9e4508df Stavros Sachtouris
The CommandTree structure
53 9e4508df Stavros Sachtouris
-------------------------
54 9e4508df Stavros Sachtouris
55 fa382f9e Stavros Sachtouris
CommandTree manages a command by its path. Each command is stored in multiple
56 fa382f9e Stavros Sachtouris
nodes on the tree, so that the last term is a leaf and the route from root to
57 fa382f9e Stavros Sachtouris
that leaf represents the command path. For example the commands *file upload*,
58 fa382f9e Stavros Sachtouris
*file list* and *file info* are stored together 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 9e4508df Stavros Sachtouris
The example used in the present, should result to the creation of two trees::
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 fa382f9e Stavros Sachtouris
Each command group should be stored on a different CommandTree. For that
78 fa382f9e Stavros Sachtouris
reason, command specification modules should contain a list of CommandTree
79 fa382f9e Stavros Sachtouris
objects, named *_commands*
80 9e4508df Stavros Sachtouris
81 fa382f9e Stavros Sachtouris
A command group information (name, description) is provided at CommandTree
82 fa382f9e Stavros Sachtouris
structure initialization:
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 9e4508df Stavros Sachtouris
The command decorator
92 9e4508df Stavros Sachtouris
---------------------
93 9e4508df Stavros Sachtouris
94 fa382f9e Stavros Sachtouris
The *command* decorator mines all the information necessary to build a command
95 fa382f9e Stavros Sachtouris
specification which is then inserted in a CommanTree instance::
96 9e4508df Stavros Sachtouris
97 9e4508df Stavros Sachtouris
    class code  --->  command()  -->  updated CommandTree structure
98 9e4508df Stavros Sachtouris
99 fa382f9e Stavros Sachtouris
Kamaki interfaces make use of this CommandTree structure. Optimizations are
100 fa382f9e Stavros Sachtouris
possible by using special parameters on the command decorator method.
101 9e4508df Stavros Sachtouris
102 9e4508df Stavros Sachtouris
.. code-block:: python
103 9e4508df Stavros Sachtouris
104 9e4508df Stavros Sachtouris
    def command(cmd_tree, prefix='', descedants_depth=None):
105 9e4508df Stavros Sachtouris
    """Load a class as a command
106 fa382f9e Stavros Sachtouris
107 59cadffb Stavros Sachtouris
        :param cmd_tree: is the CommandTree to be updated with a new command
108 fa382f9e Stavros Sachtouris
109 59cadffb Stavros Sachtouris
        :param prefix: of the commands allowed to be inserted ('' for all)
110 fa382f9e Stavros Sachtouris
111 59cadffb Stavros Sachtouris
        :param descedants_depth: is the depth of the tree descedants of the
112 9e4508df Stavros Sachtouris
            prefix command.
113 9e4508df Stavros Sachtouris
    """
114 9e4508df Stavros Sachtouris
115 9e4508df Stavros Sachtouris
Creating a new command specification set
116 9e4508df Stavros Sachtouris
----------------------------------------
117 9e4508df Stavros Sachtouris
118 9e4508df Stavros Sachtouris
A command specification developer should create a new module (python file) with as many classes as the command specifications to be offered. Each class should be decorated with *command*.
119 9e4508df Stavros Sachtouris
120 9e4508df Stavros Sachtouris
.. code-block:: python
121 9e4508df Stavros Sachtouris
122 9e4508df Stavros Sachtouris
    ...
123 9e4508df Stavros Sachtouris
    _commands = [_mygrp1_commands, _mygrp2_commands]
124 9e4508df Stavros Sachtouris
125 9e4508df Stavros Sachtouris
    @command(_mygrp1_commands)
126 9e4508df Stavros Sachtouris
    class mygrp1_list_all():
127 9e4508df Stavros Sachtouris
        ...
128 9e4508df Stavros Sachtouris
129 9e4508df Stavros Sachtouris
    ...
130 9e4508df Stavros Sachtouris
131 fa382f9e Stavros Sachtouris
A list of CommandTree structures must exist in the module scope, with the name
132 fa382f9e Stavros Sachtouris
_commands, as shown above. Different CommandTree objects correspond to
133 fa382f9e Stavros Sachtouris
different command groups.
134 9e4508df Stavros Sachtouris
135 9e4508df Stavros Sachtouris
Get command description
136 9e4508df Stavros Sachtouris
-----------------------
137 9e4508df Stavros Sachtouris
138 fa382f9e Stavros Sachtouris
The description of each command is the first line of the class commend. The
139 fa382f9e Stavros Sachtouris
following declaration of *mygrp2-info* command has a "*get information for
140 fa382f9e Stavros Sachtouris
subject with id*" description.
141 9e4508df Stavros Sachtouris
142 9e4508df Stavros Sachtouris
.. code-block:: python
143 9e4508df Stavros Sachtouris
144 9e4508df Stavros Sachtouris
    ...
145 9e4508df Stavros Sachtouris
    @command(_mygrp2_commands)
146 9e4508df Stavros Sachtouris
    class mygrp2_info()
147 9e4508df Stavros Sachtouris
        """get information for subject with id"""
148 9e4508df Stavros Sachtouris
        ...
149 9e4508df Stavros Sachtouris
150 9e4508df Stavros Sachtouris
Declare run-time argument
151 9e4508df Stavros Sachtouris
-------------------------
152 9e4508df Stavros Sachtouris
153 fa382f9e Stavros Sachtouris
The argument mechanism allows the definition of run-time arguments. Some basic
154 fa382f9e Stavros Sachtouris
argument types are defined at the
155 fa382f9e Stavros Sachtouris
`argument module <code.html#module-kamaki.cli.argument>`_, but it is not
156 fa382f9e Stavros Sachtouris
uncommon to extent these classes in order to achieve specialized type checking
157 fa382f9e Stavros Sachtouris
and syntax control (e.g. at
158 fa382f9e Stavros Sachtouris
`pithos cli module <code.html#module-kamaki.cli.commands.pithos>`_).
159 9e4508df Stavros Sachtouris
160 fa382f9e Stavros Sachtouris
To declare a run-time argument on a specific command, the object class should
161 fa382f9e Stavros Sachtouris
initialize a dict called *arguments* , where Argument objects are stored. Each
162 fa382f9e Stavros Sachtouris
argument object is a possible run-time argument. Syntax checking happens at
163 fa382f9e Stavros Sachtouris
client level, while the type checking is implemented in the Argument code
164 fa382f9e Stavros Sachtouris
(thus, many different Argument types might be needed).`
165 9e4508df Stavros Sachtouris
166 9e4508df Stavros Sachtouris
.. code-block:: python
167 9e4508df Stavros Sachtouris
168 9e4508df Stavros Sachtouris
    from kamaki.cli.argument import ValueArgument
169 9e4508df Stavros Sachtouris
    ...
170 9e4508df Stavros Sachtouris
171 9e4508df Stavros Sachtouris
    @command(_mygrp1_commands)
172 9e4508df Stavros Sachtouris
    class mygrp1_list_details():
173 9e4508df Stavros Sachtouris
        """list of details"""
174 9e4508df Stavros Sachtouris
175 59cadffb Stavros Sachtouris
        def __init__(self, global_args={}):
176 9e4508df Stavros Sachtouris
            global_args['match'] = ValueArgument(
177 9e4508df Stavros Sachtouris
                'Filter results to match string',
178 fa382f9e Stavros Sachtouris
                ('-m', '--match'))
179 9e4508df Stavros Sachtouris
            self.arguments = global_args
180 9e4508df Stavros Sachtouris
181 fa382f9e Stavros Sachtouris
or more usually and elegantly:
182 fa382f9e Stavros Sachtouris
183 fa382f9e Stavros Sachtouris
.. code-block:: python
184 fa382f9e Stavros Sachtouris
185 fa382f9e Stavros Sachtouris
    from kamaki.cli.argument import ValueArgument
186 fa382f9e Stavros Sachtouris
    
187 fa382f9e Stavros Sachtouris
    @command(_mygrp1_commands)
188 fa382f9e Stavros Sachtouris
    class mygrp1_list_details():
189 fa382f9e Stavros Sachtouris
    """List of details"""
190 fa382f9e Stavros Sachtouris
191 fa382f9e Stavros Sachtouris
        arguments = dict(
192 fa382f9e Stavros Sachtouris
            match=ValueArgument(
193 fa382f9e Stavros Sachtouris
            'Filter output to match string', ('-m', --match'))
194 fa382f9e Stavros Sachtouris
        )
195 fa382f9e Stavros Sachtouris
196 fa382f9e Stavros Sachtouris
Accessing run-time arguments
197 fa382f9e Stavros Sachtouris
----------------------------
198 fa382f9e Stavros Sachtouris
199 fa382f9e Stavros Sachtouris
To access run-time arguments, users can use the _command_init interface, which
200 fa382f9e Stavros Sachtouris
implements __item__ accessors to handle run-time argument values. In specific,
201 fa382f9e Stavros Sachtouris
an instance of _command_init can use brackets to set or read <argument>.value .
202 fa382f9e Stavros Sachtouris
203 fa382f9e Stavros Sachtouris
.. code-block:: python
204 fa382f9e Stavros Sachtouris
205 fa382f9e Stavros Sachtouris
    from kamaki.cli.argument import ValueArgument
206 fa382f9e Stavros Sachtouris
    from kamaki.cli.commands import _command_init
207 fa382f9e Stavros Sachtouris
    
208 fa382f9e Stavros Sachtouris
    @command(_mygrp1_commands)
209 fa382f9e Stavros Sachtouris
    class mygrp1_list_details(_command_init):
210 fa382f9e Stavros Sachtouris
        """List of details"""
211 fa382f9e Stavros Sachtouris
212 fa382f9e Stavros Sachtouris
        arguments = dict(
213 fa382f9e Stavros Sachtouris
            match=ValueArgument(
214 fa382f9e Stavros Sachtouris
                'Filter output to match string', ('-m', --match'))
215 fa382f9e Stavros Sachtouris
        )
216 fa382f9e Stavros Sachtouris
217 fa382f9e Stavros Sachtouris
        def check_runtime_arguments(self):
218 fa382f9e Stavros Sachtouris
            ...
219 fa382f9e Stavros Sachtouris
            assert self['match'] == self.arguments['match'].value
220 fa382f9e Stavros Sachtouris
            ...
221 fa382f9e Stavros Sachtouris
222 9e4508df Stavros Sachtouris
The main method and command parameters
223 9e4508df Stavros Sachtouris
--------------------------------------
224 9e4508df Stavros Sachtouris
225 fa382f9e Stavros Sachtouris
The command behavior for each command / class is coded in *main*. The
226 fa382f9e Stavros Sachtouris
parameters of *main* method defines the command parameters part of the syntax.
227 fa382f9e Stavros Sachtouris
In specific::
228 9e4508df Stavros Sachtouris
229 59cadffb Stavros Sachtouris
    main(self, param)                   - obligatory parameter <param>
230 59cadffb Stavros Sachtouris
    main(self, param=None)              - optional parameter [param]
231 9e4508df Stavros Sachtouris
    main(self, param1, param2=42)       - <param1> [param2]
232 9e4508df Stavros Sachtouris
    main(self, param1____param2)        - <param1:param2>
233 9e4508df Stavros Sachtouris
    main(self, param1____param2=[])     - [param1:param2]
234 9e4508df Stavros Sachtouris
    main(self, param1____param2__)      - <param1[:param2]>
235 9e4508df Stavros Sachtouris
    main(self, param1____param2__='')   - [param1[:param2]]
236 9e4508df Stavros Sachtouris
    main(self, *args)                   - arbitary number of params [...]
237 9e4508df Stavros Sachtouris
    main(self, param1____param2, *args) - <param1:param2> [...]
238 9e4508df Stavros Sachtouris
239 fa382f9e Stavros Sachtouris
The information that can be mined by *command* for each individual command is
240 fa382f9e Stavros Sachtouris
presented in the following:
241 9e4508df Stavros Sachtouris
242 9e4508df Stavros Sachtouris
.. code-block:: python
243 9e4508df Stavros Sachtouris
    :linenos:
244 9e4508df Stavros Sachtouris
245 9e4508df Stavros Sachtouris
    from kamaki.cli.argument import FlagArgument
246 9e4508df Stavros Sachtouris
    ...
247 9e4508df Stavros Sachtouris
248 9e4508df Stavros Sachtouris
    _commands = [_mygrp1_commands, _mygrp2=commands]
249 9e4508df Stavros Sachtouris
    ...
250 9e4508df Stavros Sachtouris
251 9e4508df Stavros Sachtouris
    @command(_mygrp2_commands)
252 fa382f9e Stavros Sachtouris
    class mygrp2_list_all():
253 9e4508df Stavros Sachtouris
        """List all subjects"""
254 9e4508df Stavros Sachtouris
255 fa382f9e Stavros Sachtouris
        arguments = dict(FlagArgument('detailed list', '-l'))
256 9e4508df Stavros Sachtouris
257 9e4508df Stavros Sachtouris
        def main(self, reg_exp=None):
258 9e4508df Stavros Sachtouris
            ...
259 9e4508df Stavros Sachtouris
260 9e4508df Stavros Sachtouris
This will load the following information on the CommandTree:
261 9e4508df Stavros Sachtouris
262 9e4508df Stavros Sachtouris
* Syntax (from lines 8,12,19): mygrp list all [reg exp] [-l]
263 9e4508df Stavros Sachtouris
* Description (form line 9): List all subjects
264 9e4508df Stavros Sachtouris
* Arguments help (from line 13,14): -l: detailed list
265 9e4508df Stavros Sachtouris
266 9e4508df Stavros Sachtouris
Letting kamaki know
267 9e4508df Stavros Sachtouris
-------------------
268 9e4508df Stavros Sachtouris
269 fa382f9e Stavros Sachtouris
Kamaki will load a command specification *only* if it is set as a configurable
270 fa382f9e Stavros Sachtouris
option. To demonstrate this, let the command specifications coded above be
271 fa382f9e Stavros Sachtouris
stored in a file named *grps.py*.
272 9e4508df Stavros Sachtouris
273 fa382f9e Stavros Sachtouris
The developer should move file *grps.py* to kamaki/cli/commands, the default
274 fa382f9e Stavros Sachtouris
place for command specifications, although running a command specification from
275 fa382f9e Stavros Sachtouris
a different path is also a kamaki feature.
276 9e4508df Stavros Sachtouris
277 9e4508df Stavros Sachtouris
The user has to use a configuration file where the following is added:
278 9e4508df Stavros Sachtouris
::
279 9e4508df Stavros Sachtouris
280 fa382f9e Stavros Sachtouris
    [global]
281 fa382f9e Stavros Sachtouris
    mygrp1_cli = grps
282 fa382f9e Stavros Sachtouris
    mygrp2_cli = grps
283 9e4508df Stavros Sachtouris
284 fa382f9e Stavros Sachtouris
or equivalently:
285 9e4508df Stavros Sachtouris
286 9e4508df Stavros Sachtouris
.. code-block:: console
287 9e4508df Stavros Sachtouris
288 fa382f9e Stavros Sachtouris
    $ kamaki config set mygrp1_cli grps
289 fa382f9e Stavros Sachtouris
    $ kamaki config set mygrp2_cli grps
290 9e4508df Stavros Sachtouris
291 fa382f9e Stavros Sachtouris
Command specification modules don't need to live in kamaki/cli/commands,
292 fa382f9e Stavros Sachtouris
although this is suggested for uniformity. If a command module exist in another
293 fa382f9e Stavros Sachtouris
path::
294 9e4508df Stavros Sachtouris
295 fa382f9e Stavros Sachtouris
    [global]
296 fa382f9e Stavros Sachtouris
    mygrp_cli = /another/path/grps.py
297 9e4508df Stavros Sachtouris
298 9e4508df Stavros Sachtouris
Summary: create a command set
299 9e4508df Stavros Sachtouris
-----------------------------
300 9e4508df Stavros Sachtouris
301 9e4508df Stavros Sachtouris
.. code-block:: python
302 9e4508df Stavros Sachtouris
303 9e4508df Stavros Sachtouris
    #  File: grps.py
304 9e4508df Stavros Sachtouris
305 fa382f9e Stavros Sachtouris
    from kamaki.cli.commands import _command_init
306 9e4508df Stavros Sachtouris
    from kamaki.cli.command_tree import CommandTree
307 9e4508df Stavros Sachtouris
    from kamaki.cli.argument import ValueArgument, FlagArgument
308 9e4508df Stavros Sachtouris
    ...
309 9e4508df Stavros Sachtouris
310 9e4508df Stavros Sachtouris
311 9e4508df Stavros Sachtouris
    #  Initiallize command trees
312 9e4508df Stavros Sachtouris
313 9e4508df Stavros Sachtouris
    _mygrp1_commands = CommandTree('mygrp', 'mygrp1 description')
314 9e4508df Stavros Sachtouris
    _mygrp2_commands = CommandTree('mygrp', 'mygrp2 description')
315 9e4508df Stavros Sachtouris
316 9e4508df Stavros Sachtouris
    _commands = [_mygrp1_commands, _mygrp2_commands]
317 9e4508df Stavros Sachtouris
318 9e4508df Stavros Sachtouris
319 9e4508df Stavros Sachtouris
    #  Define command specifications
320 9e4508df Stavros Sachtouris
321 9e4508df Stavros Sachtouris
322 9e4508df Stavros Sachtouris
    @command(_mygrp1_commands)
323 fa382f9e Stavros Sachtouris
    class mygrp1_list_all(_command_init):
324 9e4508df Stavros Sachtouris
        """show a list"""
325 9e4508df Stavros Sachtouris
326 9e4508df Stavros Sachtouris
        def main(self):
327 9e4508df Stavros Sachtouris
            ...
328 9e4508df Stavros Sachtouris
329 9e4508df Stavros Sachtouris
330 9e4508df Stavros Sachtouris
    @command(_mygrp1_commands)
331 fa382f9e Stavros Sachtouris
    class mygrp1_list_details(_command_init):
332 9e4508df Stavros Sachtouris
        """show list of details"""
333 9e4508df Stavros Sachtouris
334 fa382f9e Stavros Sachtouris
        arguments = dict(
335 fa382f9e Stavros Sachtouris
            match=ValueArgument(
336 fa382f9e Stavros Sachtouris
                'Filter output to match string', ('-m', --match'))
337 fa382f9e Stavros Sachtouris
        )
338 9e4508df Stavros Sachtouris
339 9e4508df Stavros Sachtouris
        def main(self):
340 9e4508df Stavros Sachtouris
            ...
341 fa382f9e Stavros Sachtouris
            match_value = self['match']
342 9e4508df Stavros Sachtouris
            ...
343 9e4508df Stavros Sachtouris
344 9e4508df Stavros Sachtouris
345 9e4508df Stavros Sachtouris
    @command(_mygrp2_commands)
346 fa382f9e Stavros Sachtouris
    class mygrp2_list_all(_command_init):
347 9e4508df Stavros Sachtouris
        """list all subjects"""
348 9e4508df Stavros Sachtouris
349 fa382f9e Stavros Sachtouris
        arguments = dict(
350 fa382f9e Stavros Sachtouris
            list=FlagArgument('detailed listing', '-l')
351 fa382f9e Stavros Sachtouris
        )
352 9e4508df Stavros Sachtouris
353 9e4508df Stavros Sachtouris
        def main(self, regular_expression=None):
354 9e4508df Stavros Sachtouris
            ...
355 fa382f9e Stavros Sachtouris
            detail_flag = self['list']
356 9e4508df Stavros Sachtouris
            ...
357 9e4508df Stavros Sachtouris
            if detail_flag:
358 9e4508df Stavros Sachtouris
                ...
359 9e4508df Stavros Sachtouris
            ...
360 9e4508df Stavros Sachtouris
            if regular_expression:
361 9e4508df Stavros Sachtouris
                ...
362 9e4508df Stavros Sachtouris
            ...
363 9e4508df Stavros Sachtouris
364 9e4508df Stavros Sachtouris
365 9e4508df Stavros Sachtouris
    @command(_mygrp2_commands)
366 fa382f9e Stavros Sachtouris
    class mygrp2_info(_command_init):
367 9e4508df Stavros Sachtouris
        """get information for subject with id"""
368 9e4508df Stavros Sachtouris
369 9e4508df Stavros Sachtouris
        def main(self, id, name=''):
370 9e4508df Stavros Sachtouris
            ...