From 589951eaead868625154efdbe875888321c80bd5 Mon Sep 17 00:00:00 2001 From: Ian McInerney Date: Sun, 9 Aug 2020 20:31:16 +0100 Subject: [PATCH] Ensure the environment variables are synced between Pcbnew and Python This ensures that when the project or an environment variable is changed in pcbnew, the Python interpreter is updated to reflect that. This is a backport version of the master-branch commit, and will not synchronize any changes to the environment variables if they are made from frames other tna Pcbnew. Fixes https://gitlab.com/kicad/code/kicad/issues/5071 --- pcbnew/files.cpp | 2 ++ pcbnew/pcb_edit_frame.cpp | 31 +++++++++++++++++++++++++++++++ pcbnew/pcb_edit_frame.h | 12 ++++++++++++ pcbnew/swig/python_scripting.cpp | 26 +++++++++++++++++++++++++- pcbnew/swig/python_scripting.h | 8 ++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 2173b8c01e..179517c169 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -315,6 +315,7 @@ bool PCB_EDIT_FRAME::Files_io_from_id( int id ) ProjectFileExtension ); Prj().SetProjectFullName( fn.GetFullPath() ); + PythonSyncProjectName(); fn.SetExt( PcbFileExtension ); @@ -461,6 +462,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in // it knows what consequences that will have on other KIFACEs running and using // this same PROJECT. It can be very harmful if that calling code is stupid. Prj().SetProjectFullName( pro.GetFullPath() ); + PythonSyncProjectName(); // load project settings before BOARD LoadProjectSettings(); diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index 0eae92cded..bcd26ed01f 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -454,6 +454,10 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : enableGALSpecificMenus(); + // Ensure the Python interpreter is up to date with its environment variables + PythonSyncEnvironmentVariables(); + PythonSyncProjectName(); + // disable Export STEP item if kicad2step does not exist wxString strK2S = Pgm().GetExecutablePath(); @@ -1138,6 +1142,10 @@ void PCB_EDIT_FRAME::OnConfigurePaths( wxCommandEvent& aEvent ) { DIALOG_CONFIGURE_PATHS dlg( this, Prj().Get3DCacheManager()->GetResolver() ); dlg.ShowModal(); + + // Ensure the Python interpreter is up to date with its environment variables + PythonSyncEnvironmentVariables(); + PythonSyncProjectName(); } @@ -1270,6 +1278,29 @@ void PCB_EDIT_FRAME::PythonPluginsReload() } +void PCB_EDIT_FRAME::PythonSyncEnvironmentVariables() +{ +#if defined( KICAD_SCRIPTING ) + const ENV_VAR_MAP& varMap = Pgm().GetLocalEnvVariables(); + + for( ENV_VAR_MAP_CITER it = varMap.begin(); it != varMap.end(); ++it ) + { + pcbnewUpdatePythonEnvVar( it->first, it->second.GetValue() ); + } +#endif +} + + +void PCB_EDIT_FRAME::PythonSyncProjectName() +{ +#if defined( KICAD_SCRIPTING ) + wxString evValue; + wxGetEnv( PROJECT_VAR_NAME, &evValue ); + pcbnewUpdatePythonEnvVar( wxString( PROJECT_VAR_NAME ).ToStdString(), evValue ); +#endif +} + + void PCB_EDIT_FRAME::InstallFootprintPropertiesDialog( MODULE* Module, wxDC* DC ) { if( Module == NULL ) diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h index d27551cb00..604b9a3c3b 100644 --- a/pcbnew/pcb_edit_frame.h +++ b/pcbnew/pcb_edit_frame.h @@ -312,6 +312,18 @@ public: */ void PythonPluginsReload(); + /** + * Synchronize the environment variables from KiCad's environment into the Python interpreter. + * Do nothing if KICAD_SCRIPTING is not defined. + */ + void PythonSyncEnvironmentVariables(); + + /** + * Synchronize the project name from KiCad's environment into the Python interpreter. + * Do nothing if KICAD_SCRIPTING is not defined. + */ + void PythonSyncProjectName(); + /** * Update the layer manager and other widgets from the board setup * (layer and items visibility, colors ...) diff --git a/pcbnew/swig/python_scripting.cpp b/pcbnew/swig/python_scripting.cpp index 3cbb342f0a..484cb55ed5 100644 --- a/pcbnew/swig/python_scripting.cpp +++ b/pcbnew/swig/python_scripting.cpp @@ -210,7 +210,8 @@ bool pcbnewInitPythonScripting( const char * aUserScriptingPath ) { PyLOCK lock; - snprintf( cmd, sizeof( cmd ), "import sys, traceback\n" + // Load os so that we can modify the environment variables through python + snprintf( cmd, sizeof( cmd ), "import sys, os, traceback\n" "sys.path.append(\".\")\n" "import pcbnew\n" "pcbnew.LoadPlugins(\"%s\")", aUserScriptingPath ); @@ -318,6 +319,29 @@ void pcbnewFinishPythonScripting() } +void pcbnewUpdatePythonEnvVar( const wxString& aVar, const wxString& aValue ) +{ + char cmd[1024]; + + // Ensure the interpreter is initalized before we try to interact with it + if( !Py_IsInitialized() ) + return; + + snprintf( cmd, sizeof( cmd ), + "# coding=utf-8\n" // The values could potentially be UTF8 + "os.environ[\"%s\"]=\"%s\"\n", + TO_UTF8( aVar ), + TO_UTF8( aValue ) ); + + PyLOCK lock; + + int retv = PyRun_SimpleString( cmd ); + + if( retv != 0 ) + wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd ); +} + + #if defined( KICAD_SCRIPTING_WXPYTHON ) void RedirectStdio() { diff --git a/pcbnew/swig/python_scripting.h b/pcbnew/swig/python_scripting.h index 369d50c8d4..d210c671c3 100644 --- a/pcbnew/swig/python_scripting.h +++ b/pcbnew/swig/python_scripting.h @@ -78,6 +78,14 @@ void pcbnewGetScriptsSearchPaths( wxString& aNames ); */ void pcbnewGetWizardsBackTrace( wxString& aNames ); +/** + * Set an environment variable in the current Python interpreter. + * + * @param aVar is the variable to set + * @param aValue is the value to give it + */ +void pcbnewUpdatePythonEnvVar( const wxString& aVar, const wxString& aValue ); + #ifdef KICAD_SCRIPTING_WXPYTHON void RedirectStdio(); wxWindow* CreatePythonShellWindow( wxWindow* parent, const wxString& aFramenameId );