From bbef4fee1754ded04930abde96d996ca1ca130c5 Mon Sep 17 00:00:00 2001 From: Simon Kueppers Date: Tue, 27 Jun 2017 23:10:36 +0200 Subject: [PATCH] Added documentation about pcbnew plugin development --- Documentation/development/pcbnew-plugins.md | 111 ++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 Documentation/development/pcbnew-plugins.md diff --git a/Documentation/development/pcbnew-plugins.md b/Documentation/development/pcbnew-plugins.md new file mode 100644 index 0000000000..1066f528bc --- /dev/null +++ b/Documentation/development/pcbnew-plugins.md @@ -0,0 +1,111 @@ +# Python Plugin Development for Pcbnew # + +## Introduction ## +KiCad implements a Python plugin interface so that external Python plugins can be run from within Pcbnew. +The interface is generated using the `Simplified Wrapper and Interface Generator` or [SWIG](http://www.swig.org). +SWIG is instructed to translate specific C/C++ header files into other languages using `interface` files. +These files ultimately decide what C/C++ functions, classes and other declarations are exported and can be found in `pcbnew/swig/`. + +During build-time the SWIG interface files are used to generate the corresponding .py files. +These files are installed into Python's system-wide `dist-packages` repository, thus they can be imported by any Python 2 interpreter installed on the system. + +## Existing Pcbnew Python API documentation ## +The Pcbnew Python API can be used stand-alone, i.e. no instance of Pcbnew is running and the board project to be manipulated is loaded and saved from and to file. +This approach is shown with some examples in the [user's documentation](http://docs.kicad-pcb.org/stable/en/pcbnew.html#_kicad_scripting_reference). + +Another documentation source is the auto-generated doxygen reference of the API. It can be found [here](http://docs.kicad-pcb.org/doxygen-python/namespacepcbnew.html). + +## `Action Plugin` Support ## +Besides the stand-alone usage of the generated Python plugin interface, additional support regarding online manipulation of board projects is available for Pcbnew. +Plugins using this feature are called `Action Plugins` and they are accessible using a Pcbnew menu entry that can be found under `Tools->External Plugins`. +KiCad plugins that follow the `Action Plugin` conventions can be made to show up as external plugins in that menu. +The user can run the plugin resulting in calling a defined entry function in the Python plugin's code. +This function can then be used to access and manipulate the currently loaded board from the Python script environment. + +### Typical Plugin Structure ### +The `Action Plugin` support is implemented in Pcbnew by discovering Python packages and Python script files in specific directories on startup. +In order for the discovery process to work, the following requirements must be met. + +* The plugin must be installed in the KiCad plugins search paths as documented in `scripting/kicadplugins.i`. + (Currently on a Linux Mint Installation this is /usr/share/kicad/scripting/plugins/ and ~/.kicad_plugins/) +* Alternatively a symbolic link can be created in the KiCad plugin path link to the plugin file/folder in another location of the filesystem. This can be useful for development. +* The plugin must be written as a simple Python script (*.py) located in the plugin search path. + Note that this method is preferred for small plugins consisting of a single .py file. +* Alternatively the plugin must be implemented as a Python package conforming to the Python package standard definitions (See [6.4. Packages](https://docs.python.org/2/tutorial/modules.html#packages)). + Note that this method is preferred for larger plugin projects consisting of multiple .py files and resource files such as dialogs or images. +* The Python plugin must contain a class derived from `pcbnew.ActionPlugin` and it's `register()` method must be called within the plugin. + +The following examples demonstrate the plugin requirements. + +### Simple Plugin Example ### +The folder structure of the simple plugin is fairly straight forward. +A single Python script file is placed into a directory that is present in the KiCad plugin path. + + + ~/.kicad_plugins/ # A folder in the KiCad plugin path + - simple_plugin.py + +The file `simple_plugin.py` contains the following. + + import pcbnew + + class SimplePlugin(pcbnew.ActionPlugin): + def defaults(self): + self.name = "Plugin Name as shown in Pcbnew: Tools->External Plugins" + self.category = "A descriptive category name" + self.description = "A description of the plugin and what it does" + + def Run(self): + # The entry function of the plugin that is executed on user action + print("Hello World") + + SimplePlugin().register() # Instantiate and register to Pcbnew + +### Complex Plugin Example ### +The complex plugin example represents a single Python package that is imported on Pcbnew startup. +When the Python package is imported, the `__init__.py` file is executed and is thus a perfect place to instantiate and register the plugin to Pcbnew. +The big advantage here is, that you can modularize your plugin much better and include other files without cluttering the KiCad plugin directory. +Additionally, the same plugin can be executed standalone using `python -m` e.g. to perform tests on the Python code. +The following folder structure shows how complex plugins are implemented: + + + ~/.kicad_plugins/ # this directory has to be in the plugin path + + complex_plugin/ # The plugin directory (A Python package) + - __init__.py # This file is executed when the package is imported (on Pcbnew startup) + - __main__.py # This file is optional. See below + - complex_plugin_action.py # The ActionPlugin derived class lives here + - complex_plugin_utils.py # Other Python parts of the plugin + + otherstuff/ + - otherfile.png + - misc.txt + +It is recommended to name the file containing the ActionPlugin derived class as `_action.py`. +In this case the file is named `complex_plugin_action.py` with the following contents: + + import pcbnew + + class ComplexPluginAction(pcbnew.ActionPlugin) + def defaults(self): + self.name = "A complex action plugin" + self.category = "A descriptive category name" + self.description "A description of the plugin" + + def Run(self): + # The entry function of the plugin that is executed on user action + print("Hello World") + +The `__init__.py` file is then used to instantiate and register the plugin to Pcbnew as follows. + + from .complex_plugin_action import ComplexPluginAction # Note the relative import! + ComplexPluginAction().register() # Instantiate and register to Pcbnew + +As described in [PEP 338](https://www.python.org/dev/peps/pep-0338/) Python can execute packages (or modules) as scripts. +This can be useful to implement a command-line stand-alone version of your KiCad plugin with minimum effort. +In order to implement this feature, a `__main__.py` file is created in the package directory. +This file can be executed by running the following command. + + python -m + +Make sure that your current directory is the parent directory of the package directory when running the command. +In these examples, this would be `~/.kicad_plugins`. +When running the command the Python interpreter runs `/complex_plugin/__init__.py` followed by `/complex_plugin/__main__.py`. + +