Editing ModtoolArchitecture

Jump to: navigation, search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 4: Line 4:
 
This article explains the current architecture of gr_modtool in the python3 branch.<br>
 
This article explains the current architecture of gr_modtool in the python3 branch.<br>
  
For this tutorial, one must have the dependencies <code>click</code>, <code>click-plugins</code> installed.<br>
+
For this tutorial, we must have the dependencies <code>click</code>, <code>click-plugins</code> installed.<br>
 
<code>pip3 install click</code><br>
 
<code>pip3 install click</code><br>
 
<code>pip3 install click-plugins</code>
 
<code>pip3 install click-plugins</code>
Line 10: Line 10:
 
= What is gr_modtool? =
 
= What is gr_modtool? =
  
While developing an [[OutOfTreeModules|Out Of Tree module]], there's a lot of boring, monotonous work involved: boilerplate code, makefile editing, etc. gr_modtool is a script which aims to help with all these things by automatically editing makefiles, using templates, and doing as much work as possible for the developer such that one can jump straight into the DSP coding.
+
While developing an [[OutOfTreeModules|Out Of Tree module]], there's a lot of boring, monotonous work involved: boilerplate code, makefile editing, etc. gr_modtool is a script which aims to help with all these things by automatically editing makefiles, using templates, and doing as much work as possible for the developer such that you can jump straight into the DSP coding.
  
Note that gr_modtool makes a lot of assumptions on how the code looks like. The more the module is custom and has specific changes, the less useful gr_modtool will be, but it is probably the best place to start with any new module or block. One can go through the [[BlocksCodingGuide|block coding guide]] for getting an insight of coding the block.
+
Note that gr_modtool makes a lot of assumptions on what the code looks like. The more your module is custom and has specific changes, the less useful gr_modtool will be, but it is probably the best place to start with any new module or block. You can go through the [[BlocksCodingGuide|block coding guide]] for getting an insight of coding the block.
  
 
gr_modtool is available in the GNU Radio source tree and is installed by default.
 
gr_modtool is available in the GNU Radio source tree and is installed by default.
Line 20: Line 20:
 
gr-modtool uses the [http://click.pocoo.org/6/ Click] Python package for its command line interface. Some of the advantages of using Click for CLI are:-
 
gr-modtool uses the [http://click.pocoo.org/6/ Click] Python package for its command line interface. Some of the advantages of using Click for CLI are:-
 
* Click is fully nestable and composable.
 
* Click is fully nestable and composable.
* Click supports prompting of custom values.
+
* Click supports for prompting of custom values.
* Click works the same in Python 2 as well as in Pythonn3.
+
* Click works the same in Python 2 and 3.
* Click comes with useful helpers like ANSI colors.
+
* Click comes with useful common helpers like ANSI colors.
 
* Click is very simple to code and visualize.
 
* Click is very simple to code and visualize.
  
Line 33: Line 33:
 
== CLI functions in Modtool ==
 
== CLI functions in Modtool ==
  
Initially all commands with <code>gr_modtool</code> in the command-line interface entered by the user pass through the <code>cli()</code> function of <code>modtool_base.py</code>. If no further command is provided in the command-line, the help page is displayed with all the in-tree plug-ins commands as well as the commands from the external plug-ins, if any. <br>
+
Initially all commands with <code>gr_modtool</code> in the command-line interface entered by the user pass through the <code>cli()</code> function of <code>modtool_base.py</code>. If no further command is provided in the command-line, the help page is displayed with all the in-tree plug-ins commands as well as commands from the external plug-ins, if any. <br>
  
If a command (after gr_modtool) is provided in the interface which has a corresponding module <code>modtool_command.py</code>, where the command is the user input command, the <code>cli()</code> function of the corresponding module is invoked with the context of the group instance in the base module.<br>
+
If a command (after gr_modtool) is provided in the interface which has a corresponding module <code>modtool_command.py</code> (where the command is the user input command) the <code>cli()</code> function of the corresponding module is invoked with the context of the group instance in the base module.<br>
  
The function is decorated by the decorator, <code>@click.command()</code>, which adds the functionalities of the class <code>[http://click.pocoo.org/5/api/#click.command click.Command]</code> and automatically attaches the decorated <code>[http://click.pocoo.org/5/options/ options]</code> and <code>[http://click.pocoo.org/5/arguments/ arguments]</code> to it. The user input values of all these parameters are then passed to the <code>run()</code> function of the respective module defined in its core class.<br>
+
The function is decorated by the decorator <code>@click.command()</code> which add the functionalities of the class <code>[http://click.pocoo.org/5/api/#click.command click.Command]</code> and automatically attach the decorated <code>[http://click.pocoo.org/5/options/ options]</code> and <code>[http://click.pocoo.org/5/arguments/ arguments]</code> to it. The user input values of all these parameters are then passed to the <code>run()</code> function of the respective module defined in its core class.<br>
  
Note: The basic difference between arguments and options is that arguments are positional and mandatory by default unlike options, although arguments can also be made optional as in the case with the modtool scripts. Moreover, <code>documentation</code> of the argument is not generated by click and it has to be done manually.
+
Note: The basic difference between arguments and options is that arguments are mandatory (by default, can be made optional as in the case with the modtool scripts) and positional. Moreover, <code>documentation</code> of the argument is not generated by click and it has to be done manually.
  
 
== Key Notes ==
 
== Key Notes ==
  
* A decorator function <code>common_params</code> is present in the base module to remove the redundancy of adding the same options in every module. These options are not provided as the options to the base command group '''intentionally''' because they actually make sense with the command itself, otherwise the command <code>gr_modtool add -t general --skip-lib</code> will look like <code>gr_modtool add --skip-lib -t general</code> which is not user-friendly. Therefore, these parameters will show up in the help page of the respective command rather than the command group.
+
* A decorator function <code>common_params</code> is present in the base module to remove the redundancy of adding the same options in every module. These options haven't been provided as the options to the base command group '''intentionally''' because they actually make sense with the command itself and otherwise the command <code>gr_modtool add -t general --skip-lib</code> will look like <code>gr_modtool add --skip-lib -t general</code> which won't be user-friendly. Therefore, these parameters will show up in the help page of the respective command rather than the command group.
* A decorator <code>block_name</code> is present in the base module which adds an argument (non-mandatory) '''block_name''' to the particular command that uses it.
+
* A decorator <code>block_name</code> is present in the base module which adds an argument (non-mandatory) '''block_name''' to the particular command which uses it.
 
* The help page for a particular command can be shown with <code>--help</code> in the CLI. For eg:- <code>gr_modtool add --help</code>.
 
* The help page for a particular command can be shown with <code>--help</code> in the CLI. For eg:- <code>gr_modtool add --help</code>.
* For commands, a short help snippet is generated. By default, it is the first sentence of the help message of the command, unless it is too long. This can also be overridden by <code>short_help</code> provided with command. For example, <code>@click.command('newmod', short_help=ModToolNewModule().description)</code> shows the help of the command <code>newmod</code> generated in the help page (<code>gr_modtool --help</code> or simply <code>gr_modtool</code>) as the '''description''' variable of the class <code>ModToolNewModule</code>. The main '''help-text''' ,when you request the command's help page with commands like <code>gr_modtool makexml --help</code>, is the '''document string''' of the function attached to the decorator <code>@click.command</code>.
+
* For commands, a short help snippet is generated. By default, it’s the first sentence of the help message of the command, unless it’s too long. This can also be overridden by <code>short_help</code> provided with command. For example, <code>@click.command('newmod', short_help=ModToolNewModule().description)</code> shows the help of the command <code>newmod</code> generated in the help page (<code>gr_modtool --help</code> or simply <code>gr_modtool</code>) as the '''description''' variable of the class <code>ModToolNewModule</code>. The main '''help-text''' when you run the command's help page, eg:- <code>gr_modtool makexml --help</code> is the '''document string''' of the function attached to the decorator <code>@click.command</code>.
 
* For options, the help documentation can be added by <code>help</code> parameter in the decorator <code>@click.option()</code>. For example, <code>@click.option('--copyright', help="Name of the copyright holder (you or your company) MUST be a quoted string.")</code>.
 
* For options, the help documentation can be added by <code>help</code> parameter in the decorator <code>@click.option()</code>. For example, <code>@click.option('--copyright', help="Name of the copyright holder (you or your company) MUST be a quoted string.")</code>.
 
<br>
 
<br>
Line 134: Line 134:
 
         exit(1)
 
         exit(1)
 
</pre>
 
</pre>
Here, the available '''options''' with the command are <code>srcdir</code> and all the options that the function of the class <code>ModTool</code>, <code>common_params</code>, adds to it. <br><br>
+
Here the available '''options''' with the command are <code>srcdir</code> and all the options that the function of the class <code>ModTool</code>, <code>common_params</code>, adds to it. <br><br>
 
+
So, to add a module in-tree, all you have to do is create module as <code>module_command.py</code> with a function <code>cli()</code> in the '''modtool''' directory, add options and arguments to it with <code>@click.option()</code> and <code>@click.argument()</code> decorators and specify the functional details with the obtained value of parameters.<br>
So, to add a module in-tree, all that one has to do is to create module as <code>module_command.py</code> with a function <code>cli()</code> in the '''modtool''' directory, add options and arguments to it with <code>@click.option()</code> and <code>@click.argument()</code> decorators and specify the functional details with the obtained value of parameters.<br>
+
Note: Instead of <code>**kwargs</code>, we can specify the particular options.
Note: Instead of <code>**kwargs</code>, one can specify the particular options.
 
  
 
= External Plug-ins =
 
= External Plug-ins =
  
<code>gr_modtool</code> supports the addition of external plug-ins, if required by the user. To achieve this functionality, it uses <code>pkg_resources.iter_entry_points</code> to load an external plug-in and a python package <code>click-plugins</code> to register commands to the base group and show <code>Broken Plug-in</code> if the plug-in is not be loaded properly.
+
<code>gr_modtool</code> supports the addition of external plug-ins, if required by the user. To achieve this functionality, it uses <code>pkg_resources.iter_entry_points</code> to load an external plug-in and a python package <code>click-plugins</code> to register commands to the base group and show <code>Broken Plug-in</code> if the plug-in could not be loaded properly.
  
== Adding a plug-in ==
+
== Adding a plugin ==
  
To add an external plug-in to the modtool, all that one has to do is to create a package directory with a file <code>setup.py</code> and specify the <code>entry_point</code> as <code>gnuradio.modtool.plugins</code> through the functional definition of our choice.<br>
+
To add an external plug-in to the modtool, all we need to do is create a package directory with a file <code>setup.py</code> and specify the <code>entry_point</code> as <code>gnuradio.modtool.plugins</code> through the functional definition of our choice.<br>
 
For example:-<br>
 
For example:-<br>
 
If package directory <code>ext_plug</code> looks like
 
If package directory <code>ext_plug</code> looks like
Line 171: Line 170:
 
== Writing a plug-in ==
 
== Writing a plug-in ==
  
Writing an external plug-in is quite simple. All that one has to do is create a function with the name specified in the <code>entry_point</code> and decorate it with <code>@click.command()</code>, if just an external command is to be added, or  <code>@click.group()</code>, if a command group is to be added.<br>
+
Writing an external plug-in is quite simple. All we have to do create a function with the name specified in the <code>entry_point</code> and decorate it with <code>@click.command()</code>, if you just wish to add a command, or  <code>@click.group()</code>, if you wish to add a command group.<br>
 
For eg:- For the previous package, <code>core.py</code> can be like
 
For eg:- For the previous package, <code>core.py</code> can be like
 
<pre>
 
<pre>
Line 184: Line 183:
 
     pass
 
     pass
 
</pre>
 
</pre>
Now, one just needs to install this package by running <code>pip3 install ext_plug/</code> and the external plugin is ready to use.<br>
+
Now, all we need to do install this package by running <code>pip3 install ext_plug/</code> and the external plugin is ready to use.<br>
 
Now, on running <code>gr_modtool --help</code>, we get
 
Now, on running <code>gr_modtool --help</code>, we get
 
<pre>
 
<pre>
Line 208: Line 207:
 
   options to run specified command interactively
 
   options to run specified command interactively
 
</pre>
 
</pre>
If the plug-in is not loaded due to reasons like an incorrect entry_point setup, the help page will duly indicate that.<br>
+
If the plug-in could not be loaded, due to reasons like an incorrect entry_point setup, the help page will duly indicate that.<br>
 
For example:-<br>
 
For example:-<br>
If the <code>setup.py</code> file for the above-mentioned package looks like
+
If the <code>setup.py</code> file for the above mentioned package looks like
 
<pre>
 
<pre>
 
from setuptools import setup
 
from setuptools import setup
Line 223: Line 222:
 
)
 
)
 
</pre>
 
</pre>
the plug-in will not load to incorrect functional definition in the <code>entry_points</code>.<br>
+
the plug-in won't be loaded due to incorrect functional definition in the <code>entry_points</code>.<br>
 
Now, on running <code>gr_modtool --help</code>, we get
 
Now, on running <code>gr_modtool --help</code>, we get
 
<pre>
 
<pre>
Line 247: Line 246:
 
   options to run specified command interactively
 
   options to run specified command interactively
 
</pre>
 
</pre>
So, <code>gr_modtool</code> makes even the adding an external plug-in highly interactive.<br><br>
+
So, <code>gr_modtool</code> even makes adding an external plug-in highly interactive.<br><br>
  
 
Information regarding creating an out of tree module and in-tree commands is available [[OutOfTreeModules|here]].
 
Information regarding creating an out of tree module and in-tree commands is available [[OutOfTreeModules|here]].

Please note that all contributions to GNU Radio are considered to be released under the Creative Commons Attribution-ShareAlike (see GNU Radio:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To edit this page, please answer the question that appears below (more info):

Cancel | Editing help (opens in new window)