KiCad PCB EDA Suite
python_scripting.h File Reference
#include <Python.h>
#include <wx/string.h>
#include <wx/arrstr.h>

Go to the source code of this file.

Classes

class  PyLOCK
 

Functions

bool pcbnewInitPythonScripting (const char *aUserScriptingPath)
 Initialize the Python engine inside pcbnew. More...
 
void pcbnewFinishPythonScripting ()
 
void pcbnewGetUnloadableScriptNames (wxString &aNames)
 Collect the list of python scripts which could not be loaded. More...
 
void pcbnewGetScriptsSearchPaths (wxString &aNames)
 Collect the list of paths where python scripts are searched. More...
 
void pcbnewGetWizardsBackTrace (wxString &aNames)
 Return the backtrace of errors (if any) when wizard python scripts are loaded. More...
 
wxString PyStringToWx (PyObject *str)
 
wxArrayString PyArrayStringToWx (PyObject *arr)
 
wxString PyErrStringWithTraceback ()
 
wxString PyScriptingPath ()
 Find the Python scripting path. More...
 
wxString PyPluginsPath ()
 

Function Documentation

◆ pcbnewFinishPythonScripting()

void pcbnewFinishPythonScripting ( )

Definition at line 312 of file python_scripting.cpp.

313 {
314 #ifdef KICAD_SCRIPTING_WXPYTHON
315  PyEval_RestoreThread( g_PythonMainTState );
316 #endif
317  Py_Finalize();
318 }
PyThreadState * g_PythonMainTState

References g_PythonMainTState.

◆ pcbnewGetScriptsSearchPaths()

void pcbnewGetScriptsSearchPaths ( wxString &  aNames)

Collect the list of paths where python scripts are searched.

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

Definition at line 300 of file python_scripting.cpp.

301 {
302  pcbnewRunPythonMethodWithReturnedString( "pcbnew.GetWizardsSearchPaths", aNames );
303 }
static void pcbnewRunPythonMethodWithReturnedString(const char *aMethodName, wxString &aNames)
Run a python method from the pcbnew module.

References pcbnewRunPythonMethodWithReturnedString().

◆ pcbnewGetUnloadableScriptNames()

void pcbnewGetUnloadableScriptNames ( wxString &  aNames)

Collect the list of python scripts which could not be loaded.

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

Definition at line 294 of file python_scripting.cpp.

295 {
296  pcbnewRunPythonMethodWithReturnedString( "pcbnew.GetUnLoadableWizards", aNames );
297 }
static void pcbnewRunPythonMethodWithReturnedString(const char *aMethodName, wxString &aNames)
Run a python method from the pcbnew module.

References pcbnewRunPythonMethodWithReturnedString().

◆ pcbnewGetWizardsBackTrace()

void pcbnewGetWizardsBackTrace ( wxString &  aNames)

Return the backtrace of errors (if any) when wizard python scripts are loaded.

Parameters
aNamesis a wxString which will contain the trace

Definition at line 306 of file python_scripting.cpp.

307 {
308  pcbnewRunPythonMethodWithReturnedString( "pcbnew.GetWizardsBackTrace", aNames );
309 }
static void pcbnewRunPythonMethodWithReturnedString(const char *aMethodName, wxString &aNames)
Run a python method from the pcbnew module.

References pcbnewRunPythonMethodWithReturnedString().

◆ pcbnewInitPythonScripting()

bool pcbnewInitPythonScripting ( const char *  aUserScriptingPath)

Initialize the Python engine inside pcbnew.

Initialize the Python engine inside pcbnew.

This initializes all the wxPython interface and returns the python thread control structure

Definition at line 154 of file python_scripting.cpp.

155 {
156  int retv;
157  char cmd[1024];
158 
159  swigAddBuiltin(); // add builtin functions
160  swigAddModules(); // add our own modules
161  swigSwitchPythonBuiltin(); // switch the python builtin modules to our new list
162 
163  Py_Initialize();
164  PySys_SetArgv( Pgm().App().argc, Pgm().App().argv );
165 
166 #ifdef KICAD_SCRIPTING_WXPYTHON
167  PyEval_InitThreads();
168 
169 #ifndef KICAD_SCRIPTING_WXPYTHON_PHOENIX
170 #ifndef __WINDOWS__ // import wxversion.py currently not working under winbuilder, and not useful.
171  // Make sure that that the correct version of wxPython is loaded. In systems where there
172  // are different versions of wxPython installed this can lead to select wrong wxPython
173  // version being selected.
174  snprintf( cmd, sizeof( cmd ), "import wxversion; wxversion.select( '%s' )", WXPYTHON_VERSION );
175 
176  retv = PyRun_SimpleString( cmd );
177 
178  if( retv != 0 )
179  {
180  wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd );
181  return false;
182  }
183 #endif // ifndef __WINDOWS__
184 
185  // Load the wxPython core API. Imports the wx._core_ module and sets a
186  // local pointer to a function table located there. The pointer is used
187  // internally by the rest of the API functions.
188  if( !wxPyCoreAPI_IMPORT() )
189  {
190  wxLogError( "***** Error importing the wxPython API! *****" );
191  PyErr_Print();
192  Py_Finalize();
193  return false;
194  }
195 #endif
196 
197 #if defined( DEBUG )
198  RedirectStdio();
199 #endif
200 
201  wxPythonLoaded = true;
202 
203  // Save the current Python thread state and release the
204  // Global Interpreter Lock.
205  g_PythonMainTState = PyEval_SaveThread();
206 
207 #endif // ifdef KICAD_SCRIPTING_WXPYTHON
208 
209  // Load pcbnew inside Python and load all the user plugins, TODO: add system wide plugins
210  {
211  PyLOCK lock;
212 
213  snprintf( cmd, sizeof( cmd ), "import sys, traceback\n"
214  "sys.path.append(\".\")\n"
215  "import pcbnew\n"
216  "pcbnew.LoadPlugins(\"%s\")", aUserScriptingPath );
217  retv = PyRun_SimpleString( cmd );
218 
219  if( retv != 0 )
220  wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd );
221  }
222 
223  return true;
224 }
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
static void swigAddBuiltin()
Add the builtin python modules.
static void swigAddModules()
Add the internal modules to the python scripting so they will be available to the scripts.
static void swigSwitchPythonBuiltin()
Switch the python module table to the Pcbnew built one.
static bool wxPythonLoaded
True if the wxPython scripting layer was successfully loaded.
PyThreadState * g_PythonMainTState

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

◆ PyArrayStringToWx()

wxArrayString PyArrayStringToWx ( PyObject *  arr)

Definition at line 470 of file python_scripting.cpp.

471 {
472  wxArrayString ret;
473 
474  if( !aArrayString )
475  return ret;
476 
477  int list_size = PyList_Size( aArrayString );
478 
479  for( int n = 0; n < list_size; n++ )
480  {
481  PyObject* element = PyList_GetItem( aArrayString, n );
482 
483  if( element )
484  {
485 #if PY_MAJOR_VERSION >= 3
486  const char* str_res = NULL;
487  PyObject* temp_bytes = PyUnicode_AsEncodedString( element, "UTF-8", "strict" );
488 
489  if( temp_bytes != NULL )
490  {
491  str_res = PyBytes_AS_STRING( temp_bytes );
492  ret.Add( FROM_UTF8( str_res ), 1 );
493  Py_DECREF( temp_bytes );
494  }
495  else
496  {
497  wxLogMessage( "cannot encode unicode python string" );
498  }
499 #else
500  ret.Add( FROM_UTF8( PyString_AsString( element ) ), 1 );
501 #endif
502  }
503  }
504 
505  return ret;
506 }
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:62

References FROM_UTF8().

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

◆ PyErrStringWithTraceback()

wxString PyErrStringWithTraceback ( )

Definition at line 509 of file python_scripting.cpp.

510 {
511  wxString err;
512 
513  if( !PyErr_Occurred() )
514  return err;
515 
516  PyObject* type;
517  PyObject* value;
518  PyObject* traceback;
519 
520  PyErr_Fetch( &type, &value, &traceback );
521 
522  PyErr_NormalizeException( &type, &value, &traceback );
523 
524  if( traceback == NULL )
525  {
526  traceback = Py_None;
527  Py_INCREF( traceback );
528  }
529 
530 #if PY_MAJOR_VERSION >= 3
531  PyException_SetTraceback( value, traceback );
532 
533  PyObject* tracebackModuleString = PyUnicode_FromString( "traceback" );
534 #else
535  PyObject* tracebackModuleString = PyString_FromString( "traceback" );
536 #endif
537  PyObject* tracebackModule = PyImport_Import( tracebackModuleString );
538  Py_DECREF( tracebackModuleString );
539 
540  PyObject* formatException = PyObject_GetAttrString( tracebackModule,
541  "format_exception" );
542  Py_DECREF( tracebackModule );
543 
544  PyObject* args = Py_BuildValue( "(O,O,O)", type, value, traceback );
545  PyObject* result = PyObject_CallObject( formatException, args );
546  Py_XDECREF( formatException );
547  Py_XDECREF( args );
548  Py_XDECREF( type );
549  Py_XDECREF( value );
550  Py_XDECREF( traceback );
551 
552  wxArrayString res = PyArrayStringToWx( result );
553 
554  for( unsigned i = 0; i<res.Count(); i++ )
555  {
556  err += res[i] + wxT( "\n" );
557  }
558 
559  PyErr_Clear();
560 
561  return err;
562 }
wxArrayString PyArrayStringToWx(PyObject *aArrayString)
string & err
Definition: json11.cpp:598
size_t i
Definition: json11.cpp:597

References err, i, and PyArrayStringToWx().

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

◆ PyPluginsPath()

wxString PyPluginsPath ( )

Definition at line 592 of file python_scripting.cpp.

593 {
594  // Note we are using unix path separator, because window separator sometimes
595  // creates issues when passing a command string to a python method by PyRun_SimpleString
596  return PyScriptingPath() + '/' + "plugins";
597 }
wxString PyScriptingPath()
Find the Python scripting path.

References PyScriptingPath().

◆ PyScriptingPath()

wxString PyScriptingPath ( )

Find the Python scripting path.

Definition at line 568 of file python_scripting.cpp.

569 {
570  wxString path;
571 
572  //@todo This should this be a user configurable variable eg KISCRIPT?
573 #if defined( __WXMAC__ )
574  path = GetOSXKicadDataDir() + wxT( "/scripting" );
575 #else
576  path = Pgm().GetExecutablePath() + wxT( "../share/kicad/scripting" );
577 #endif
578 
579  wxFileName scriptPath( path );
580  scriptPath.MakeAbsolute();
581 
582  // Convert '\' to '/' in path, because later python script read \n or \r
583  // as escaped sequence, and create issues, when calling it by PyRun_SimpleString() method.
584  // It can happen on Windows.
585  path = scriptPath.GetFullPath();
586  path.Replace( '\\', '/' );
587 
588  return path;
589 }
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
VTBL_ENTRY const wxString & GetExecutablePath() const
Definition: pgm_base.h:232

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

Referenced by PyPluginsPath(), and PythonPluginsReloadBase().

◆ PyStringToWx()

wxString PyStringToWx ( PyObject *  str)

Definition at line 440 of file python_scripting.cpp.

441 {
442  wxString ret;
443 
444  if( !aString )
445  return ret;
446 
447 #if PY_MAJOR_VERSION >= 3
448  const char* str_res = NULL;
449  PyObject* temp_bytes = PyUnicode_AsEncodedString( aString, "UTF-8", "strict" );
450 
451  if( temp_bytes != NULL )
452  {
453  str_res = PyBytes_AS_STRING( temp_bytes );
454  ret = FROM_UTF8( str_res );
455  Py_DECREF( temp_bytes );
456  }
457  else
458  {
459  wxLogMessage( "cannot encode unicode python string" );
460  }
461 #else
462  const char* str_res = PyString_AsString( aString );
463  ret = FROM_UTF8( str_res );
464 #endif
465 
466  return ret;
467 }
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:62

References FROM_UTF8().

Referenced by PYTHON_ACTION_PLUGIN::CallRetStrMethod(), PYTHON_FOOTPRINT_WIZARD::CallRetStrMethod(), and PYTHON_FOOTPRINT_WIZARD::GetParameterPageName().