← Back to team overview

kicad-developers team mailing list archive

Re: Fwd: Python plugin for pcbnew

 

Hi Jean-Samuel,

I am assuming that you would like this work to be committed as part kicad source?  If not
please let me know.  With my assumption in place, we'll have to achieve a minimum amount
of general usability, and that may extend beyond what you need it for.

Please be aware of this.


> Hi,
> 
> For starting I had implement your b) option. For that I start from a copy of guthub
> plugin. So I add options in all
> needed files (CMakeLists.txt..), I had create a directory on pcbnew and put the code
> inside and an example.
> 
> Out of this directory I had done some small changes:
> scripting/python_scripting.h
> => Adding global value g_PythonMainTState as extern (needed for python locks)
> pcbnew/plugin.cpp
> => move python_footprint_plugin option to my plugin (as comment suggest). I hope it's ok.
> pcbnew/io_mgr.h
> pcbnew/io_mgr.cpp
> => Declare my plugin on lists
> 
> On the new directory:
> 
> pcbnew/fppython/fppython_example.py
> A plugin example.
> It's a really basic:
>  - 2 statics foot prints
>  - footprint himself are hardcoded on the example
>  - fake save/delete
> 
> pcbnew/fppython/fppython_plugin.(cpp|h)
> The plugin himself
> 
> To use is:
> - add a new footprint lib entry,
> - specify the directory where the plugin is as library path


The Footprint*() library path argument should always only be used as a pointer to the
library, not as a pointer to the plugin.


A normal python environment variable should know where a python module is.  That should be
the fallback in any case, with possible augmentation as described below, which is only an
*optional* override for module loading.

Additionally, you can look for an optional fp_lib_table property, one spelled identically
to a standard python environment variable name, which if present, can trump the
environment variable.



> - specify python_footprint_plugin option as the plugin name (without .py, for example
> fppython_example)

good.


> Some limitations I found inside the core to allow more feature for plugins:
> - IsFootprintLibWritable don't have a PROPERTY parameter. So since the plugin module name
> is inside this, I'm unable to load
> the right python module to let it handle this method

Your python module loading should happen less frequently.

1) The the association between the C++ adapter instance and the python module can and
should be retentative up until
it cannot be.

2) The association between the module and the library can and should be retentative up
until it cannot be.


The easiest way to manage this is to have two member helpers in your adaptor:

bool PYTHON_ADAPTOR::changedLibPath( const wxString& aCurrentLibPath )
{
    if( aCurrentLibPath != m_lib_path )
    {
	m_lib_path = aCurrentLibPath;
	return true;
    }
    return false;
}

PLUS, a similar function for python module name.

Then only change libraries, when changedLibPath() returns true.  Only change modules when
changedModule() returns true.

This way your module and library can both be cached in the PYTHON_ADAPTER.  User's will
instantiate a new PYTHON_ADAPTER for any number of libraries.

But 99% of the time, your python interpreter (or sub-interpreter) instantiation should
survive multiple calls to the adaptor, and the module should be left loaded, and the
library should be left open.

We can add PROPERTIES argument to IsFootprintLibWritable() but if you follow my design
suggestions, you can survive without this additional argument for now.  You will have a
record of the m_module's last value already.


> - FootprintLibOptions: Same issue. So the plugin can't provide a list of parameters needed
> for his own usage. 

In the C++ why don't you refer people to the pydocs for the module.  I don't want to have
to load the python module in the OptionsEditor, where the plugin may instantiated just to
get the supported parameters.  Let's refer people to external documentation in the help
text for the certainly present python_footprint_plugin option.

That way each python module can later query for the options it might expect.  The user can
supply additional options, even though they are not initially part of the supplied
choices, in the options editor.



> To work arround this
> I hard code 4 parameters (fppython_parameter[1-4]) but it is not beautiful...

Those could be removed, if the user can add his own in the OptionEditor with more
meaningful names.

I think we have to prove viability of this entire python plugin module first before we tip
the boat over.


Also, remember that its going to be impossible to have more than one running python
interpreter in a single process.  Python simply does not support that.  It does however
support "sub-interpreters".  As the top level Kicad GUI transforms into wxPython, you will
not be able to instantiate a brand new python interpreter in your PYTHON_ADAPTOR, for two
reasons:

a) only one interpreter per process, and the main one is way above you.

b) you should not assume that the user only has one PYTHON_ADAPTOR in the fp_lib_table,
and you are limited to only one interpreter per process.

So if you are not already an expert on python "sub-interpreters", you need to make that
your highest priority, because your work will never get committed if you cannot conform to
the overall design constraints of the single python interpreter constraint.


Dick


> 
> I hope it can help... After this, I plan to create a more advanced python plugin
> 
> 
> Tell me...
> 
> Regards
> 
> 
> 2014-03-08 17:08 GMT+01:00 Dick Hollenbeck <dick@xxxxxxxxxxx <mailto:dick@xxxxxxxxxxx>>:
> 
>     RE: FootprintLoad()
> 
>     There are two ways you could go:
> 
>     a) use swig functions on class MODULE and add features that way, one by one in python.
>     Return the MODULE when you are done "loading" the footprint.
> 
> 
>     b) construct a pretty string, return that to C++ land but still within your adapter, i.e.
>     still inside ADAPTER::FootprintLoad(), before returning from that C++ function.  Then
>     while in there PCB_IO::Parse() the pretty string and return the constructed MODULE coming
>     back from the Parse() function.
> 
> 
>     This latter path, b) was what I was thinking for the SWEET support, and you can see that
>     its API is different from PLUGIN.  It returned SWEET strings on part loading.  That was to
>     support SWEET's inheritance model.
> 
> 
>     Dick
> 
> 
>     _______________________________________________
>     Mailing list: https://launchpad.net/~kicad-developers
>     Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
>     <mailto:kicad-developers@xxxxxxxxxxxxxxxxxxx>
>     Unsubscribe : https://launchpad.net/~kicad-developers
>     More help   : https://help.launchpad.net/ListHelp
> 
> 
> 
> 
> _______________________________________________
> Mailing list: https://launchpad.net/~kicad-developers
> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~kicad-developers
> More help   : https://help.launchpad.net/ListHelp
> 



Follow ups

References