scoped_interpreter. overloaded constructor: PyConfig param (#4330)

* scoped_interpreter overloaded ctor: PyConfig param

* style: pre-commit fixes

* refact: some logics extracted into funcs (precheck_interpreter, _initialize_interpreter); config_guard

* style: pre-commit fixes

* refact: scoped_config, some funcs hidden in detail ns

* refact: macro PYBIND11_PYCONFIG_SUPPORT_PY_VERSION + undef

* feat: PYBIND11_PYCONFIG_SUPPORT_PY_VERSION set to 3.8

* tests: Custom PyConfig

* ci: python 3.6 -> 3.8

* ci: reverted py 38 back  to 36; refact: initialize_interpreter overloads

* style: pre-commit fixes

* fix: readability-implicit-bool-conversion

* refact: each initialize_interpreter overloads in pybind11 ns

* Move `initialize_interpreter_pre_pyconfig()` into the `detail` namespace.

Move the `PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX` define down to where it is used for the first time, and check if it is defined already, so that it is possible to customize from the compilation command line, just in case there is some unforeseen issue for Python 3.8, 3.9, 3.10.

* tests: Add program dir to path, Custom PyConfig with argv

* refact: clang-formatted

* tests: Add-program-dir-to-path covers both scoped_interpreter overloads

* tests: Add-program-dir-to-path fixed

* tests: Add-program-dir-to-path py_version dependant validation

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Ralf W. Grosse-Kunstleve <rwgk@google.com>
This commit is contained in:
Arman
2022-12-01 07:17:59 +02:00
committed by GitHub
parent 06003e82b3
commit 8869984926
2 changed files with 143 additions and 42 deletions

View File

@@ -166,6 +166,72 @@ TEST_CASE("There can be only one interpreter") {
py::initialize_interpreter();
}
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
TEST_CASE("Custom PyConfig") {
py::finalize_interpreter();
PyConfig config;
PyConfig_InitPythonConfig(&config);
REQUIRE_NOTHROW(py::scoped_interpreter{&config});
{
py::scoped_interpreter p{&config};
REQUIRE(py::module_::import("widget_module").attr("add")(1, 41).cast<int>() == 42);
}
py::initialize_interpreter();
}
TEST_CASE("Custom PyConfig with argv") {
py::finalize_interpreter();
{
PyConfig config;
PyConfig_InitIsolatedConfig(&config);
char *argv[] = {strdup("a.out")};
py::scoped_interpreter argv_scope{&config, 1, argv};
std::free(argv[0]);
auto module = py::module::import("test_interpreter");
auto py_widget = module.attr("DerivedWidget")("The question");
const auto &cpp_widget = py_widget.cast<const Widget &>();
REQUIRE(cpp_widget.argv0() == "a.out");
}
py::initialize_interpreter();
}
#endif
TEST_CASE("Add program dir to path") {
static auto get_sys_path_size = []() -> size_t {
auto sys_path = py::module::import("sys").attr("path");
return py::len(sys_path);
};
static auto validate_path_len = [](size_t default_len) {
#if PY_VERSION_HEX < 0x030A0000
// It seems a value remains in sys.path
// left by the previous call of scoped_interpreter ctor.
REQUIRE(get_sys_path_size() > default_len);
#else
REQUIRE(get_sys_path_size() == default_len + 1);
#endif
};
py::finalize_interpreter();
size_t sys_path_default_size = 0;
{
py::scoped_interpreter scoped_interp{true, 0, nullptr, false};
sys_path_default_size = get_sys_path_size();
}
{
py::scoped_interpreter scoped_interp{}; // expected to append some to sys.path
validate_path_len(sys_path_default_size);
}
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
{
PyConfig config;
PyConfig_InitPythonConfig(&config);
py::scoped_interpreter scoped_interp{&config}; // expected to append some to sys.path
validate_path_len(sys_path_default_size);
}
#endif
py::initialize_interpreter();
}
bool has_pybind11_internals_builtin() {
auto builtins = py::handle(PyEval_GetBuiltins());
return builtins.contains(PYBIND11_INTERNALS_ID);