KiCad PCB EDA Suite
python_scripting.cpp File Reference

methods to add scripting capabilities inside pcbnew More...

#include <python_scripting.h>
#include <stdlib.h>
#include <string.h>
#include <fctsys.h>
#include <wxstruct.h>
#include <common.h>
#include <gal/color4d.h>
#include <macros.h>
#include <pgm_base.h>

Go to the source code of this file.

Macros

#define EXTRA_PYTHON_MODULES   10
 

Functions

void init_kicad (void)
 
void init_pcbnew (void)
 
bool IsWxPythonLoaded ()
 
static void swigAddModule (const char *name, void(*initfunc)())
 
static void swigAddBuiltin ()
 
static void swigAddModules ()
 
static void swigSwitchPythonBuiltin ()
 
bool pcbnewInitPythonScripting (const char *aUserScriptingPath)
 Function pcbnewInitPythonScripting Initializes the Python engine inside pcbnew. More...
 
static void pcbnewRunPythonMethodWithReturnedString (const char *aMethodName, wxString &aNames)
 this function runs a python method from pcbnew module, which returns a string More...
 
void pcbnewGetUnloadableScriptNames (wxString &aNames)
 Function pcbnewGetUnloadableScriptNames collects the list of python scripts which could not be loaded because some error (synthax error) happened. More...
 
void pcbnewGetScriptsSearchPaths (wxString &aNames)
 Function pcbnewGetScriptsSearchPaths collects the list of paths where python scripts are searched. More...
 
void pcbnewGetWizardsBackTrace (wxString &aNames)
 Function pcbnewGetWizardsBackTrace returns the backtrace of errors (if any) when wizard python scripts are loaded. More...
 
void pcbnewFinishPythonScripting ()
 
wxArrayString PyArrayStringToWx (PyObject *aArrayString)
 
wxString PyErrStringWithTraceback ()
 
wxString PyScriptingPath ()
 Find the Python scripting path. More...
 
wxString PyPluginsPath ()
 

Variables

struct _inittab * SwigImportInittab
 
static int SwigNumModules = 0
 
static bool wxPythonLoaded = false
 
PyThreadState * g_PythonMainTState
 

Detailed Description

methods to add scripting capabilities inside pcbnew

Definition in file python_scripting.cpp.

Macro Definition Documentation

#define EXTRA_PYTHON_MODULES   10

Definition at line 48 of file python_scripting.cpp.

Referenced by swigAddBuiltin().

Function Documentation

void init_kicad ( void  )
void init_pcbnew ( void  )

Referenced by swigAddModules().

bool IsWxPythonLoaded ( )

Definition at line 62 of file python_scripting.cpp.

References wxPythonLoaded.

Referenced by PCB_EDIT_FRAME::ReCreateHToolbar().

63 {
64  return wxPythonLoaded;
65 }
static bool wxPythonLoaded
void pcbnewFinishPythonScripting ( )

Definition at line 267 of file python_scripting.cpp.

268 {
269 #ifdef KICAD_SCRIPTING_WXPYTHON
270  wxPyEndAllowThreads( g_PythonMainTState );
271 #endif
272  Py_Finalize();
273 }
PyThreadState * g_PythonMainTState
void pcbnewGetScriptsSearchPaths ( wxString &  aNames)

Function pcbnewGetScriptsSearchPaths collects the list of paths where python scripts are searched.

Parameters
aNamesis a wxString which will contain the paths (separated by '
')

Definition at line 256 of file python_scripting.cpp.

References pcbnewRunPythonMethodWithReturnedString().

257 {
258  pcbnewRunPythonMethodWithReturnedString( "pcbnew.GetWizardsSearchPaths", aNames );
259 }
static void pcbnewRunPythonMethodWithReturnedString(const char *aMethodName, wxString &aNames)
this function runs a python method from pcbnew module, which returns a string
void pcbnewGetUnloadableScriptNames ( wxString &  aNames)

Function pcbnewGetUnloadableScriptNames collects the list of python scripts which could not be loaded because some error (synthax error) happened.

Parameters
aNamesis a wxString which will contain the filenames (separated by '
')

Definition at line 250 of file python_scripting.cpp.

References pcbnewRunPythonMethodWithReturnedString().

251 {
252  pcbnewRunPythonMethodWithReturnedString( "pcbnew.GetUnLoadableWizards", aNames );
253 }
static void pcbnewRunPythonMethodWithReturnedString(const char *aMethodName, wxString &aNames)
this function runs a python method from pcbnew module, which returns a string
void pcbnewGetWizardsBackTrace ( wxString &  aNames)

Function pcbnewGetWizardsBackTrace returns the backtrace of errors (if any) when wizard python scripts are loaded.

Parameters
aNamesis a wxString which will contain the trace

Definition at line 261 of file python_scripting.cpp.

References pcbnewRunPythonMethodWithReturnedString().

262 {
263  pcbnewRunPythonMethodWithReturnedString( "pcbnew.GetWizardsBackTrace", aNames );
264 }
static void pcbnewRunPythonMethodWithReturnedString(const char *aMethodName, wxString &aNames)
this function runs a python method from pcbnew module, which returns a string
bool pcbnewInitPythonScripting ( const char *  aUserScriptingPath)

Function pcbnewInitPythonScripting Initializes the Python engine inside pcbnew.

Definition at line 141 of file python_scripting.cpp.

References swigAddBuiltin(), swigAddModules(), swigSwitchPythonBuiltin(), and wxPythonLoaded.

142 {
143  swigAddBuiltin(); // add builtin functions
144  swigAddModules(); // add our own modules
145  swigSwitchPythonBuiltin(); // switch the python builtin modules to our new list
146 
147  Py_Initialize();
148 
149 #ifdef KICAD_SCRIPTING_WXPYTHON
150  PyEval_InitThreads();
151 
152 #ifndef __WINDOWS__ // import wxversion.py currently not working under winbuilder, and not useful.
153  char cmd[1024];
154  // Make sure that that the correct version of wxPython is loaded. In systems where there
155  // are different versions of wxPython installed this can lead to select wrong wxPython
156  // version being selected.
157  snprintf( cmd, sizeof(cmd), "import wxversion; wxversion.select('%s')", WXPYTHON_VERSION );
158 
159  int retv = PyRun_SimpleString( cmd );
160 
161  if( retv != 0 )
162  {
163  wxLogError( wxT( "Python error %d occurred running string `%s`" ), retv, cmd );
164  PyErr_Print();
165  Py_Finalize();
166  return false;
167  }
168 #endif // ifndef __WINDOWS__
169 
170  // Load the wxPython core API. Imports the wx._core_ module and sets a
171  // local pointer to a function table located there. The pointer is used
172  // internally by the rest of the API functions.
173  if( !wxPyCoreAPI_IMPORT() )
174  {
175  wxLogError( wxT( "***** Error importing the wxPython API! *****" ) );
176  PyErr_Print();
177  Py_Finalize();
178  return false;
179  }
180 
181  wxPythonLoaded = true;
182 
183  // Save the current Python thread state and release the
184  // Global Interpreter Lock.
185 
186  g_PythonMainTState = wxPyBeginAllowThreads();
187 #endif // ifdef KICAD_SCRIPTING_WXPYTHON
188 
189  // load pcbnew inside python, and load all the user plugins, TODO: add system wide plugins
190  {
191  char loadCmd[1024];
192  PyLOCK lock;
193  snprintf( loadCmd, sizeof(loadCmd), "import sys, traceback\n"
194  "sys.path.append(\".\")\n"
195  "import pcbnew\n"
196  "pcbnew.LoadPlugins(\"%s\")", aUserScriptingPath );
197  PyRun_SimpleString( loadCmd );
198  }
199 
200  return true;
201 }
static void swigAddBuiltin()
static void swigAddModules()
static void swigSwitchPythonBuiltin()
static bool wxPythonLoaded
PyThreadState * g_PythonMainTState
static void pcbnewRunPythonMethodWithReturnedString ( const char *  aMethodName,
wxString &  aNames 
)
static

this function runs a python method from pcbnew module, which returns a string

Parameters
aMethodNameis the name of the method (like "pcbnew.myfunction" )
aNameswill contains the returned string

Definition at line 209 of file python_scripting.cpp.

References FROM_UTF8(), and PyErrStringWithTraceback().

Referenced by pcbnewGetScriptsSearchPaths(), pcbnewGetUnloadableScriptNames(), and pcbnewGetWizardsBackTrace().

210 {
211  aNames.Clear();
212 
213  PyLOCK lock;
214  PyErr_Clear();
215 
216  PyObject* builtins = PyImport_ImportModule( "pcbnew" );
217  wxASSERT( builtins );
218 
219  if( !builtins ) // Something is wrong in pcbnew.py module (incorrect version?)
220  return;
221 
222  PyObject* globals = PyDict_New();
223  PyDict_SetItemString( globals, "pcbnew", builtins );
224  Py_DECREF( builtins );
225 
226  // Build the python code
227  char cmd[1024];
228  snprintf( cmd, sizeof(cmd), "result = %s()", aMethodName );
229 
230  // Execute the python code and get the returned data
231  PyObject* localDict = PyDict_New();
232  PyObject* pobj = PyRun_String( cmd, Py_file_input, globals, localDict);
233  Py_DECREF( globals );
234 
235  if( pobj )
236  {
237  PyObject* str = PyDict_GetItemString(localDict, "result" );
238  const char* str_res = str ? PyString_AsString( str ) : 0;
239  aNames = FROM_UTF8( str_res );
240  Py_DECREF( pobj );
241  }
242 
243  Py_DECREF( localDict );
244 
245  if( PyErr_Occurred() )
246  wxLogMessage(PyErrStringWithTraceback());
247 }
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
wxString PyErrStringWithTraceback()
wxArrayString PyArrayStringToWx ( PyObject *  aArrayString)

Definition at line 374 of file python_scripting.cpp.

References FROM_UTF8().

Referenced by PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod(), and PyErrStringWithTraceback().

375 {
376  wxArrayString ret;
377 
378  if( !aArrayString )
379  return ret;
380 
381  int list_size = PyList_Size( aArrayString );
382 
383  for( int n = 0; n < list_size; n++ )
384  {
385  PyObject* element = PyList_GetItem( aArrayString, n );
386 
387  if( element )
388  ret.Add( FROM_UTF8( PyString_AsString( element ) ), 1 );
389  }
390 
391  return ret;
392 }
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
wxString PyErrStringWithTraceback ( )

Definition at line 395 of file python_scripting.cpp.

References PyArrayStringToWx().

Referenced by PYTHON_ACTION_PLUGIN::CallMethod(), PYTHON_FOOTPRINT_WIZARD::CallMethod(), and pcbnewRunPythonMethodWithReturnedString().

396 {
397  wxString err;
398 
399  if( !PyErr_Occurred() )
400  return err;
401 
402  PyObject* type;
403  PyObject* value;
404  PyObject* traceback;
405 
406  PyErr_Fetch( &type, &value, &traceback );
407 
408  PyObject* tracebackModuleString = PyString_FromString( "traceback" );
409  PyObject* tracebackModule = PyImport_Import( tracebackModuleString );
410  Py_DECREF( tracebackModuleString );
411 
412  PyObject* formatException = PyObject_GetAttrString( tracebackModule,
413  "format_exception" );
414  Py_DECREF( tracebackModule );
415 
416  PyObject* args = Py_BuildValue( "(O,O,O)", type, value, traceback );
417  PyObject* result = PyObject_CallObject( formatException, args );
418  Py_XDECREF( formatException );
419  Py_XDECREF( args );
420  Py_XDECREF( type );
421  Py_XDECREF( value );
422  Py_XDECREF( traceback );
423 
424  wxArrayString res = PyArrayStringToWx( result );
425 
426  for( unsigned i = 0; i<res.Count(); i++ )
427  {
428  err += res[i] + wxT( "\n" );
429  }
430 
431  PyErr_Clear();
432 
433  return err;
434 }
wxArrayString PyArrayStringToWx(PyObject *aArrayString)
wxString PyPluginsPath ( )

Definition at line 456 of file python_scripting.cpp.

References PyScriptingPath().

457 {
458  return PyScriptingPath() + wxFileName::GetPathSeparator() + "plugins";
459 }
wxString PyScriptingPath()
Find the Python scripting path.
wxString PyScriptingPath ( )

Find the Python scripting path.

Definition at line 439 of file python_scripting.cpp.

References PGM_BASE::GetExecutablePath(), and Pgm().

Referenced by PyPluginsPath(), and PythonPluginsReloadBase().

440 {
441  wxString path;
442 
443  //TODO should this be a user configurable variable eg KISCRIPT ?
444 #if defined( __WXMAC__ )
445  path = GetOSXKicadDataDir() + wxT( "/scripting" );
446 #else
447  path = Pgm().GetExecutablePath() + wxT( "../share/kicad/scripting" );
448 #endif
449 
450  wxFileName scriptPath( path );
451  scriptPath.MakeAbsolute();
452 
453  return scriptPath.GetFullPath();
454 }
VTBL_ENTRY const wxString & GetExecutablePath() const
Definition: pgm_base.h:173
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:63
static void swigAddBuiltin ( )
static

Definition at line 82 of file python_scripting.cpp.

References EXTRA_PYTHON_MODULES, swigAddModule(), and SwigImportInittab.

Referenced by pcbnewInitPythonScripting().

83 {
84  int i = 0;
85 
86  /* discover the length of the pyimport inittab */
87  while( PyImport_Inittab[i].name )
88  i++;
89 
90  /* allocate memory for the python module table */
91  SwigImportInittab = (struct _inittab*) malloc(
92  sizeof(struct _inittab) * (i + EXTRA_PYTHON_MODULES) );
93 
94  /* copy all pre-existing python modules into our newly created table */
95  i = 0;
96 
97  while( PyImport_Inittab[i].name )
98  {
99  swigAddModule( PyImport_Inittab[i].name, PyImport_Inittab[i].initfunc );
100  i++;
101  }
102 }
#define EXTRA_PYTHON_MODULES
static void swigAddModule(const char *name, void(*initfunc)())
struct _inittab * SwigImportInittab
static void swigAddModule ( const char *  name,
void(*)()  initfunc 
)
static

Definition at line 70 of file python_scripting.cpp.

References SwigImportInittab, and SwigNumModules.

Referenced by swigAddBuiltin(), and swigAddModules().

71 {
72  SwigImportInittab[SwigNumModules].name = (char*) name;
73  SwigImportInittab[SwigNumModules].initfunc = initfunc;
75  SwigImportInittab[SwigNumModules].name = (char*) 0;
76  SwigImportInittab[SwigNumModules].initfunc = 0;
77 }
struct _inittab * SwigImportInittab
static int SwigNumModules
static void swigAddModules ( )
static

Definition at line 111 of file python_scripting.cpp.

References init_pcbnew(), and swigAddModule().

Referenced by pcbnewInitPythonScripting().

112 {
113  swigAddModule( "_pcbnew", init_pcbnew );
114 
115  // finally it seems better to include all in just one module
116  // but in case we needed to include any other modules,
117  // it must be done like this:
118  // swigAddModule( "_kicad", init_kicad );
119 }
static void swigAddModule(const char *name, void(*initfunc)())
void init_pcbnew(void)
static void swigSwitchPythonBuiltin ( )
static

Definition at line 127 of file python_scripting.cpp.

References SwigImportInittab.

Referenced by pcbnewInitPythonScripting().

128 {
129  PyImport_Inittab = SwigImportInittab;
130 }
struct _inittab * SwigImportInittab

Variable Documentation

PyThreadState* g_PythonMainTState

Definition at line 139 of file python_scripting.cpp.

struct _inittab* SwigImportInittab

Definition at line 57 of file python_scripting.cpp.

Referenced by swigAddBuiltin(), swigAddModule(), and swigSwitchPythonBuiltin().

int SwigNumModules = 0
static

Definition at line 58 of file python_scripting.cpp.

Referenced by swigAddModule().

bool wxPythonLoaded = false
static

Definition at line 60 of file python_scripting.cpp.

Referenced by IsWxPythonLoaded(), and pcbnewInitPythonScripting().