From 2896afa0146869d227a36d0882b91cc49244a51a Mon Sep 17 00:00:00 2001 From: Hanif Koh Date: Tue, 29 Sep 2026 14:14:18 +0800 Subject: [PATCH] Keep the Plugin Tests' Python Packages Out of the Working Directory The plugin test fixtures start the interpreter before the test points data_dir at its temporary directory, so PythonInterpreter creates {data_dir}/python/packages and {data_dir}/log with an empty data_dir: a python/ and log/ folder in whatever directory the tests run from. When that is the test binary's folder, the next run's embedded-interpreter tests took the stray python/ as their home and failed to start Python. Give each fixture that initializes the plugin manager its own temporary data directory, set up before initialize(), and only use the python/ folder next to the test binary as the interpreter's home when it holds a standard library. --- tests/slic3rutils/python_test_support.hpp | 10 +++++++++- tests/slic3rutils/test_plugin_capability_config.cpp | 3 +++ tests/slic3rutils/test_plugin_cloud_metadata.cpp | 3 +++ tests/slic3rutils/test_plugin_lifecycle.cpp | 3 +++ tests/slic3rutils/test_plugin_printer_agent.cpp | 5 +++++ tests/slic3rutils/test_slicing_pipeline_config.cpp | 3 +++ 6 files changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/slic3rutils/python_test_support.hpp b/tests/slic3rutils/python_test_support.hpp index ab66f05887..29747a88c4 100644 --- a/tests/slic3rutils/python_test_support.hpp +++ b/tests/slic3rutils/python_test_support.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -25,8 +26,15 @@ void ensure_python_initialized() config.parse_argv = 0; const auto python_home = boost::dll::program_location().parent_path() / "python"; +#ifdef _WIN32 + const auto stdlib = python_home / "Lib"; +#else + const auto stdlib = python_home / "lib" / + ("python" + std::to_string(PY_MAJOR_VERSION) + "." + std::to_string(PY_MINOR_VERSION)); +#endif - if (boost::filesystem::exists(python_home)) { + // Only a real runtime: a stray python/ folder (packages a test left behind) is not a home. + if (boost::filesystem::exists(stdlib / "encodings")) { const std::string home = python_home.string(); const PyStatus status = PyConfig_SetBytesString(&config, &config.home, home.c_str()); diff --git a/tests/slic3rutils/test_plugin_capability_config.cpp b/tests/slic3rutils/test_plugin_capability_config.cpp index f224f92308..39ecd1002d 100644 --- a/tests/slic3rutils/test_plugin_capability_config.cpp +++ b/tests/slic3rutils/test_plugin_capability_config.cpp @@ -38,6 +38,9 @@ namespace { // before this destructor's shutdown() runs. struct ScopedPluginManager { + // Before initialize(): the interpreter creates {data_dir}/python/packages and {data_dir}/log, + // which would otherwise land in the working directory. + ScopedDataDir python_data_dir{"plugin-python"}; bool initialized = PluginManager::instance().initialize(); ~ScopedPluginManager() diff --git a/tests/slic3rutils/test_plugin_cloud_metadata.cpp b/tests/slic3rutils/test_plugin_cloud_metadata.cpp index c34b596ee0..241ef3ed90 100644 --- a/tests/slic3rutils/test_plugin_cloud_metadata.cpp +++ b/tests/slic3rutils/test_plugin_cloud_metadata.cpp @@ -31,6 +31,9 @@ namespace { // same as any other plugin. struct ScopedManagerShutdown { + // Before initialize(): the interpreter creates {data_dir}/python/packages and {data_dir}/log, + // which would otherwise land in the working directory. + ScopedDataDir python_data_dir{"plugin-python"}; bool initialized = PluginManager::instance().initialize(); ~ScopedManagerShutdown() diff --git a/tests/slic3rutils/test_plugin_lifecycle.cpp b/tests/slic3rutils/test_plugin_lifecycle.cpp index bac3a19ea9..c57e12fb43 100644 --- a/tests/slic3rutils/test_plugin_lifecycle.cpp +++ b/tests/slic3rutils/test_plugin_lifecycle.cpp @@ -41,6 +41,9 @@ namespace { // Declare this FIRST in a test so it is destroyed last. struct ScopedPluginManager { + // Before initialize(): the interpreter creates {data_dir}/python/packages and {data_dir}/log, + // which would otherwise land in the working directory. + ScopedDataDir python_data_dir{"plugin-python"}; bool initialized = false; ScopedPluginManager() { initialized = PluginManager::instance().initialize(); } diff --git a/tests/slic3rutils/test_plugin_printer_agent.cpp b/tests/slic3rutils/test_plugin_printer_agent.cpp index 2065360080..29c11c7fec 100644 --- a/tests/slic3rutils/test_plugin_printer_agent.cpp +++ b/tests/slic3rutils/test_plugin_printer_agent.cpp @@ -12,6 +12,8 @@ #include #include +#include "plugin_test_utils.hpp" + namespace py = pybind11; using namespace Slic3r; @@ -21,6 +23,9 @@ namespace { // into Python unless PythonInterpreter::instance() reports initialized. struct ScopedPluginManager { + // Before initialize(): the interpreter creates {data_dir}/python/packages and {data_dir}/log, + // which would otherwise land in the working directory. + ScopedDataDir python_data_dir{"plugin-python"}; bool initialized = PluginManager::instance().initialize(); ~ScopedPluginManager() diff --git a/tests/slic3rutils/test_slicing_pipeline_config.cpp b/tests/slic3rutils/test_slicing_pipeline_config.cpp index ff8cddcba6..37984cff34 100644 --- a/tests/slic3rutils/test_slicing_pipeline_config.cpp +++ b/tests/slic3rutils/test_slicing_pipeline_config.cpp @@ -35,6 +35,9 @@ namespace { struct ScopedPluginManager { + // Before initialize(): the interpreter creates {data_dir}/python/packages and {data_dir}/log, + // which would otherwise land in the working directory. + ScopedDataDir python_data_dir{"plugin-python"}; bool initialized = false; ScopedPluginManager() { initialized = PluginManager::instance().initialize(); }