From 37d0d5f11801b4bf2b043ee97ed6dc50740bd7b7 Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Sat, 11 Jan 2025 11:46:56 -0500 Subject: [PATCH] Use PYTHON_MANAGER to launch actions and capture trace output --- common/api/api_plugin_manager.cpp | 95 +++++++++++++++++++++---------- scripting/python_manager.cpp | 7 +-- 2 files changed, 67 insertions(+), 35 deletions(-) diff --git a/common/api/api_plugin_manager.cpp b/common/api/api_plugin_manager.cpp index 90e7593042..cbccc6b867 100644 --- a/common/api/api_plugin_manager.cpp +++ b/common/api/api_plugin_manager.cpp @@ -246,8 +246,6 @@ void API_PLUGIN_MANAGER::InvokeAction( const wxString& aIdentifier ) return; } - args.push_back( py->wc_str() ); - if( !pluginFile.IsFileReadable() ) { wxLogTrace( traceApi, wxString::Format( "Manager: Python entrypoint %s is not readable", @@ -255,6 +253,27 @@ void API_PLUGIN_MANAGER::InvokeAction( const wxString& aIdentifier ) return; } + PYTHON_MANAGER manager( *py ); + wxExecuteEnv env; + + wxString systemRoot; + wxGetEnv( wxS( "SYSTEMROOT" ), &systemRoot ); + env.env[wxS( "SYSTEMROOT" )] = systemRoot; + + env.env.erase( "PYTHONHOME" ); + env.env.erase( "PYTHONPATH" ); + + manager.Execute( pluginFile.GetFullPath(), + []( int aRetVal, const wxString& aOutput, const wxString& aError ) + { + wxLogTrace( traceApi, + wxString::Format( "Manager: action exited with code %d", aRetVal ) ); + + if( !aError.IsEmpty() ) + wxLogTrace( traceApi, wxString::Format( "Manager: action stderr: %s", aError ) ); + }, + &env ); + break; } @@ -267,41 +286,40 @@ void API_PLUGIN_MANAGER::InvokeAction( const wxString& aIdentifier ) return; } + args.emplace_back( pluginPath.wc_str() ); + + for( const wxString& arg : action->args ) + args.emplace_back( arg.wc_str() ); + + args.emplace_back( nullptr ); + + wxExecuteEnv env; + wxGetEnvMap( &env.env ); + env.env[wxS( "KICAD_API_SOCKET" )] = Pgm().GetApiServer().SocketPath(); + env.env[wxS( "KICAD_API_TOKEN" )] = Pgm().GetApiServer().Token(); + env.cwd = pluginFile.GetPath(); + + long p = wxExecute( const_cast( args.data() ), + wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE, nullptr, &env ); + + if( !p ) + { + wxLogTrace( traceApi, wxString::Format( "Manager: launching action %s failed", + action->identifier ) ); + } + else + { + wxLogTrace( traceApi, wxString::Format( "Manager: launching action %s -> pid %ld", + action->identifier, p ) ); + } break; - }; + } default: wxLogTrace( traceApi, wxString::Format( "Manager: unhandled runtime for action %s", action->identifier ) ); return; } - - args.emplace_back( pluginPath.wc_str() ); - - for( const wxString& arg : action->args ) - args.emplace_back( arg.wc_str() ); - - args.emplace_back( nullptr ); - - wxExecuteEnv env; - wxGetEnvMap( &env.env ); - env.env[ wxS( "KICAD_API_SOCKET" ) ] = Pgm().GetApiServer().SocketPath(); - env.env[ wxS( "KICAD_API_TOKEN" ) ] = Pgm().GetApiServer().Token(); - env.cwd = pluginFile.GetPath(); - - long p = wxExecute( const_cast( args.data() ), wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE, - nullptr, &env ); - - if( !p ) - { - wxLogTrace( traceApi, wxString::Format( "Manager: launching action %s failed", - action->identifier ) ); - } - else - { - wxLogTrace( traceApi, wxString::Format( "Manager: launching action %s -> pid %ld", - action->identifier, p ) ); - } } @@ -411,6 +429,14 @@ void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent ) wxLogTrace( traceApi, wxString::Format( "Manager: creating Python env at %s", job.env_path ) ); PYTHON_MANAGER manager( Pgm().GetCommonSettings()->m_Api.python_interpreter ); + wxExecuteEnv env; + + wxString systemRoot; + wxGetEnv( wxS( "SYSTEMROOT" ), &systemRoot ); + env.env[wxS( "SYSTEMROOT" )] = systemRoot; + + env.env.erase( "PYTHONHOME" ); + env.env.erase( "PYTHONPATH" ); manager.Execute( wxString::Format( wxS( "-m venv --system-site-packages \"%s\"" ), @@ -426,7 +452,7 @@ void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent ) wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_PLUGIN_MANAGER_JOB_FINISHED, wxID_ANY ); QueueEvent( evt ); - } ); + }, &env ); JOB nextJob( job ); nextJob.type = JOB_TYPE::SETUP_ENV; @@ -457,6 +483,9 @@ void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent ) wxString systemRoot; wxGetEnv( wxS( "SYSTEMROOT" ), &systemRoot ); env.env[wxS( "SYSTEMROOT" )] = systemRoot; + + env.env.erase( "PYTHONHOME" ); + env.env.erase( "PYTHONPATH" ); #endif wxString cmd = wxS( "-m pip install --upgrade pip" ); @@ -515,6 +544,10 @@ void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent ) wxString systemRoot; wxGetEnv( wxS( "SYSTEMROOT" ), &systemRoot ); env.env[wxS( "SYSTEMROOT" )] = systemRoot; + + // If we are using the KiCad-shipped Python interpreter we have to do hacks + env.env.erase( "PYTHONHOME" ); + env.env.erase( "PYTHONPATH" ); #endif if( pythonHome ) diff --git a/scripting/python_manager.cpp b/scripting/python_manager.cpp index 70526e87a3..306d3dec0a 100644 --- a/scripting/python_manager.cpp +++ b/scripting/python_manager.cpp @@ -91,9 +91,8 @@ PYTHON_MANAGER::PYTHON_MANAGER( const wxString& aInterpreterPath ) void PYTHON_MANAGER::Execute( const wxString& aArgs, - const std::function& aCallback, - const wxExecuteEnv* aEnv, bool aSaveOutput ) + const std::function& aCallback, + const wxExecuteEnv* aEnv, bool aSaveOutput ) { PYTHON_PROCESS* process = new PYTHON_PROCESS( aCallback ); process->Redirect(); @@ -227,7 +226,7 @@ std::optional PYTHON_MANAGER::GetVirtualPython( const wxString& aNames #ifdef _WIN32 python.AppendDir( "Scripts" ); - python.SetFullName( "python.exe" ); + python.SetFullName( "pythonw.exe" ); #else python.AppendDir( "bin" ); python.SetFullName( "python" );