From 3bdf82aea7a4820163b415861e1997928d10151d Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Tue, 11 Feb 2025 12:14:13 -0500 Subject: [PATCH] Python: switch to arg arrays for launch Fixes Python when there are spaces in interpreter path --- common/api/api_plugin_manager.cpp | 45 ++++++++++++++++-------- common/dialogs/panel_plugin_settings.cpp | 2 +- scripting/python_manager.cpp | 17 ++++++--- scripting/python_manager.h | 2 +- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/common/api/api_plugin_manager.cpp b/common/api/api_plugin_manager.cpp index bbbf00418e..80301794b6 100644 --- a/common/api/api_plugin_manager.cpp +++ b/common/api/api_plugin_manager.cpp @@ -284,7 +284,7 @@ void API_PLUGIN_MANAGER::InvokeAction( const wxString& aIdentifier ) if( pythonHome ) env.env[wxS( "VIRTUAL_ENV" )] = *pythonHome; - long pid = manager.Execute( pluginFile.GetFullPath(), + long pid = manager.Execute( { pluginFile.GetFullPath() }, []( int aRetVal, const wxString& aOutput, const wxString& aError ) { wxLogTrace( traceApi, @@ -495,10 +495,14 @@ void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent ) env.env.erase( "PYTHONPATH" ); } #endif + std::vector args = { + "-m", + "venv", + "--system-site-packages", + job.env_path + }; - manager.Execute( - wxString::Format( wxS( "-m venv --system-site-packages \"%s\"" ), - job.env_path ), + manager.Execute( args, [this]( int aRetVal, const wxString& aOutput, const wxString& aError ) { wxLogTrace( traceApi, @@ -553,10 +557,15 @@ void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent ) } #endif - wxString cmd = wxS( "-m pip install --upgrade pip" ); - wxLogTrace( traceApi, "Manager: calling python %s", cmd ); + std::vector args = { + "-m", + "pip", + "install", + "--upgrade", + "pip" + }; - manager.Execute( cmd, + manager.Execute( args, [this]( int aRetVal, const wxString& aOutput, const wxString& aError ) { wxLogTrace( traceApi, wxString::Format( "Manager: upgrade pip returned %d", @@ -618,14 +627,22 @@ void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent ) if( pythonHome ) env.env[wxS( "VIRTUAL_ENV" )] = *pythonHome; - wxString cmd = wxString::Format( - wxS( "-m pip install --no-input --isolated --only-binary :all: --require-virtualenv " - "--exists-action i -r \"%s\"" ), - reqs.GetFullPath() ); + std::vector args = { + "-m", + "pip", + "install", + "--no-input", + "--isolated", + "--only-binary", + ":all:", + "--require-virtualenv", + "--exists-action", + "i", + "-r", + reqs.GetFullPath() + }; - wxLogTrace( traceApi, "Manager: calling python %s", cmd ); - - manager.Execute( cmd, + manager.Execute( args, [this, job]( int aRetVal, const wxString& aOutput, const wxString& aError ) { if( !aError.IsEmpty() ) diff --git a/common/dialogs/panel_plugin_settings.cpp b/common/dialogs/panel_plugin_settings.cpp index 372a227d33..64e494c2cb 100644 --- a/common/dialogs/panel_plugin_settings.cpp +++ b/common/dialogs/panel_plugin_settings.cpp @@ -136,7 +136,7 @@ void PANEL_PLUGIN_SETTINGS::validatePythonInterpreter() PYTHON_MANAGER manager( pythonExe.GetFullPath() ); - manager.Execute( wxS( "--version" ), + manager.Execute( { wxS( "--version" ) }, [&]( int aRetCode, const wxString& aStdOut, const wxString& aStdErr ) { wxString msg; diff --git a/scripting/python_manager.cpp b/scripting/python_manager.cpp index 467a3995bb..dd35a8f417 100644 --- a/scripting/python_manager.cpp +++ b/scripting/python_manager.cpp @@ -90,7 +90,7 @@ PYTHON_MANAGER::PYTHON_MANAGER( const wxString& aInterpreterPath ) } -long PYTHON_MANAGER::Execute( const wxString& aArgs, +long PYTHON_MANAGER::Execute( const std::vector& aArgs, const std::function& aCallback, const wxExecuteEnv* aEnv, bool aSaveOutput ) { @@ -115,10 +115,19 @@ long PYTHON_MANAGER::Execute( const wxString& aArgs, } }; - wxString cmd = wxString::Format( wxS( "%s %s" ), m_interpreterPath, aArgs ); + wxString argsStr; + std::vector args = { m_interpreterPath.wc_str() }; - wxLogTrace( traceApi, wxString::Format( "Execute: %s", cmd ) ); - long pid = wxExecute( cmd, wxEXEC_ASYNC, process, aEnv ); + for( const wxString& arg : aArgs ) + { + args.emplace_back( arg.wc_str() ); + argsStr << arg << " "; + } + + args.emplace_back( nullptr ); + + wxLogTrace( traceApi, wxString::Format( "Execute: %s %s", m_interpreterPath, argsStr ) ); + long pid = wxExecute( args.data(), wxEXEC_ASYNC, process, aEnv ); if( pid == 0 ) { diff --git a/scripting/python_manager.h b/scripting/python_manager.h index ea29275876..ce9bcb18f8 100644 --- a/scripting/python_manager.h +++ b/scripting/python_manager.h @@ -42,7 +42,7 @@ public: * @param aSaveOutput * @return the process ID of the created process, or 0 if one was not created */ - long Execute( const wxString& aArgs, + long Execute( const std::vector& aArgs, const std::function& aCallback, const wxExecuteEnv* aEnv = nullptr, bool aSaveOutput = false );