From 24885305331c3b777e41b80226524f2d06d76544 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 21 Aug 2022 09:44:01 -0700 Subject: [PATCH 1/2] embed.h Python 3.11 `config.use_environment=1` + `PYTHONPATH` test (#4119) * Add debug fprintf to test_interpreter.cpp * Update `sys.path` from `PYTHONPATH` in Python >= 3.11 branch of `initialize_interpreter()` * Use `config.isolated = 0; config.use_environment = 1;` As suggsted by @vstinner here: https://github.com/pybind/pybind11/pull/4119#issuecomment-1219442853 * Add `TEST_CASE("PYTHONPATH is used to update sys.path")` * Fix clang-tidy error. * Use `_putenv_s()` under Windows. * Fix clang-tidy error: argument name ... in comment does not match parameter name * Remove slash from PYTHONPATH addition, to work around Windows slash-vs-backslash issue. * Use `py::str(...)` instead of `.attr("__str__")` as suggested by @skylion007 Co-authored-by: Aaron Gokaslan Co-authored-by: Aaron Gokaslan --- include/pybind11/embed.h | 2 ++ tests/test_embed/catch.cpp | 18 ++++++++++++++++++ tests/test_embed/test_interpreter.cpp | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/include/pybind11/embed.h b/include/pybind11/embed.h index d6999cd779..0ac609e0f1 100644 --- a/include/pybind11/embed.h +++ b/include/pybind11/embed.h @@ -150,6 +150,8 @@ inline void initialize_interpreter(bool init_signal_handlers = true, #else PyConfig config; PyConfig_InitIsolatedConfig(&config); + config.isolated = 0; + config.use_environment = 1; config.install_signal_handlers = init_signal_handlers ? 1 : 0; PyStatus status = PyConfig_SetBytesArgv(&config, argc, const_cast(argv)); diff --git a/tests/test_embed/catch.cpp b/tests/test_embed/catch.cpp index 96d2e3f92a..a03a8b37c4 100644 --- a/tests/test_embed/catch.cpp +++ b/tests/test_embed/catch.cpp @@ -20,7 +20,25 @@ namespace py = pybind11; int main(int argc, char *argv[]) { + // Setup for TEST_CASE in test_interpreter.cpp, tagging on a large random number: + std::string updated_pythonpath("pybind11_test_embed_PYTHONPATH_2099743835476552"); + const char *preexisting_pythonpath = getenv("PYTHONPATH"); + if (preexisting_pythonpath != nullptr) { +#if defined(_WIN32) + updated_pythonpath += ';'; +#else + updated_pythonpath += ':'; +#endif + updated_pythonpath += preexisting_pythonpath; + } +#if defined(_WIN32) + _putenv_s("PYTHONPATH", updated_pythonpath.c_str()); +#else + setenv("PYTHONPATH", updated_pythonpath.c_str(), /*replace=*/1); +#endif + py::scoped_interpreter guard{}; + auto result = Catch::Session().run(argc, argv); return result < 0xff ? result : 0xff; diff --git a/tests/test_embed/test_interpreter.cpp b/tests/test_embed/test_interpreter.cpp index 1c45457a05..6299293b91 100644 --- a/tests/test_embed/test_interpreter.cpp +++ b/tests/test_embed/test_interpreter.cpp @@ -75,6 +75,13 @@ PYBIND11_EMBEDDED_MODULE(throw_error_already_set, ) { d["missing"].cast(); } +TEST_CASE("PYTHONPATH is used to update sys.path") { + // The setup for this TEST_CASE is in catch.cpp! + auto sys_path = py::str(py::module_::import("sys").attr("path")).cast(); + REQUIRE_THAT(sys_path, + Catch::Matchers::Contains("pybind11_test_embed_PYTHONPATH_2099743835476552")); +} + TEST_CASE("Pass classes and data between modules defined in C++ and Python") { auto module_ = py::module_::import("test_interpreter"); REQUIRE(py::hasattr(module_, "DerivedWidget")); From 549223ae81acc4d54d4f12bd8544f1636caa32bf Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 21 Oct 2022 13:33:50 -0700 Subject: [PATCH 2/2] Revert "embed.h Python 3.11 `config.use_environment=1` + `PYTHONPATH` test (#4119)" This reverts commit 24885305331c3b777e41b80226524f2d06d76544. --- include/pybind11/embed.h | 2 -- tests/test_embed/catch.cpp | 18 ------------------ tests/test_embed/test_interpreter.cpp | 7 ------- 3 files changed, 27 deletions(-) diff --git a/include/pybind11/embed.h b/include/pybind11/embed.h index 0ac609e0f1..d6999cd779 100644 --- a/include/pybind11/embed.h +++ b/include/pybind11/embed.h @@ -150,8 +150,6 @@ inline void initialize_interpreter(bool init_signal_handlers = true, #else PyConfig config; PyConfig_InitIsolatedConfig(&config); - config.isolated = 0; - config.use_environment = 1; config.install_signal_handlers = init_signal_handlers ? 1 : 0; PyStatus status = PyConfig_SetBytesArgv(&config, argc, const_cast(argv)); diff --git a/tests/test_embed/catch.cpp b/tests/test_embed/catch.cpp index a03a8b37c4..96d2e3f92a 100644 --- a/tests/test_embed/catch.cpp +++ b/tests/test_embed/catch.cpp @@ -20,25 +20,7 @@ namespace py = pybind11; int main(int argc, char *argv[]) { - // Setup for TEST_CASE in test_interpreter.cpp, tagging on a large random number: - std::string updated_pythonpath("pybind11_test_embed_PYTHONPATH_2099743835476552"); - const char *preexisting_pythonpath = getenv("PYTHONPATH"); - if (preexisting_pythonpath != nullptr) { -#if defined(_WIN32) - updated_pythonpath += ';'; -#else - updated_pythonpath += ':'; -#endif - updated_pythonpath += preexisting_pythonpath; - } -#if defined(_WIN32) - _putenv_s("PYTHONPATH", updated_pythonpath.c_str()); -#else - setenv("PYTHONPATH", updated_pythonpath.c_str(), /*replace=*/1); -#endif - py::scoped_interpreter guard{}; - auto result = Catch::Session().run(argc, argv); return result < 0xff ? result : 0xff; diff --git a/tests/test_embed/test_interpreter.cpp b/tests/test_embed/test_interpreter.cpp index 6299293b91..1c45457a05 100644 --- a/tests/test_embed/test_interpreter.cpp +++ b/tests/test_embed/test_interpreter.cpp @@ -75,13 +75,6 @@ PYBIND11_EMBEDDED_MODULE(throw_error_already_set, ) { d["missing"].cast(); } -TEST_CASE("PYTHONPATH is used to update sys.path") { - // The setup for this TEST_CASE is in catch.cpp! - auto sys_path = py::str(py::module_::import("sys").attr("path")).cast(); - REQUIRE_THAT(sys_path, - Catch::Matchers::Contains("pybind11_test_embed_PYTHONPATH_2099743835476552")); -} - TEST_CASE("Pass classes and data between modules defined in C++ and Python") { auto module_ = py::module_::import("test_interpreter"); REQUIRE(py::hasattr(module_, "DerivedWidget"));