Skip to content

Commit 575be3f

Browse files
committed
Test that Python virtual environments are treated correctly
1 parent dfe9bcd commit 575be3f

File tree

4 files changed

+76
-8
lines changed

4 files changed

+76
-8
lines changed

plugins/python/src/pymodule.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,12 @@ static bool initialize()
124124
PyConfig_InitPythonConfig(&config);
125125
PyConfig_SetString(&config, &config.program_name, L"phlex");
126126

127-
// Ensure Python finds site-packages from a virtual environment if it exists
128-
if (char const* python_home = std::getenv("VIRTUAL_ENV")) {
129-
PyConfig_SetBytesString(&config, &config.home, python_home);
127+
PyStatus status = Py_InitializeFromConfig(&config);
128+
PyConfig_Clear(&config);
129+
if (PyStatus_Exception(status)) {
130+
throw std::runtime_error("Python initialization failed");
130131
}
131132

132-
Py_InitializeFromConfig(&config);
133-
134133
// try again to see if the interpreter is now initialized
135134
if (!Py_IsInitialized())
136135
throw std::runtime_error("Python can not be initialized");

test/python/CMakeLists.txt

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
find_package(Python 3.12 COMPONENTS Interpreter REQUIRED)
2+
13
# Verify installation of necessary python modules for specific tests
24

35
function(check_python_module_version MODULE_NAME MIN_VERSION OUT_VAR)
@@ -92,11 +94,26 @@ set_tests_properties(
9294
)
9395
list(APPEND ACTIVE_PY_CPHLEX_TESTS py:failure)
9496

97+
# Environment variables required:
9598
set(TEST_PYTHONPATH ${CMAKE_CURRENT_SOURCE_DIR}:$ENV{PYTHONPATH})
99+
set(
100+
PYTHON_TEST_ENVIRONMENT
101+
"SPDLOG_LEVEL=debug;PHLEX_PLUGIN_PATH=${PROJECT_BINARY_DIR};PYTHONPATH=${TEST_PYTHONPATH};PHLEX_INSTALL=${PYTHON_TEST_PHLEX_INSTALL}"
102+
)
103+
104+
set_tests_properties(${ACTIVE_PY_CPHLEX_TESTS} PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
105+
106+
# phlex-based test to ensure that sys.path is sanely set for virtual environment
107+
set(PY_VIRTUAL_ENV_DIR ${CMAKE_CURRENT_BINARY_DIR}/py_virtual_env)
108+
execute_process(COMMAND python -m venv ${PY_VIRTUAL_ENV_DIR})
109+
configure_file(pysyspath.jsonnet.in pysyspath.jsonnet @ONLY)
110+
add_test(NAME py:syspath COMMAND phlex -c ${CMAKE_CURRENT_BINARY_DIR}/pysyspath.jsonnet)
96111

112+
# Activate the Python virtual environment "by hand". Requires setting the VIRTUAL_ENV
113+
# environment variable and prepending to the PATH environment variable.
97114
set_tests_properties(
98-
${ACTIVE_PY_CPHLEX_TESTS}
115+
py:syspath
99116
PROPERTIES
100-
ENVIRONMENT
101-
"SPDLOG_LEVEL=debug;PHLEX_PLUGIN_PATH=${PROJECT_BINARY_DIR};PYTHONPATH=${TEST_PYTHONPATH};PHLEX_INSTALL=${PYTHON_TEST_PHLEX_INSTALL}"
117+
ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT};VIRTUAL_ENV=${PY_VIRTUAL_ENV_DIR}"
118+
ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:${PY_VIRTUAL_ENV_DIR}/bin"
102119
)

test/python/check_sys_path.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""An observer to check for output in tests.
2+
3+
Test algorithms produce outputs. To ensure that a test is run correctly,
4+
this observer verifies its result against the expected value.
5+
"""
6+
7+
import sys
8+
9+
class Checker:
10+
11+
__name__ = 'checker'
12+
13+
def __init__(self, venv_path: str):
14+
self._venv_path = venv_path
15+
16+
def __call__(self, i: int) -> None:
17+
assert len(sys.path) > 0
18+
venv_site_packages = f"{sys.prefix}/lib/python{sys.version_info.major}.{sys.version_info.minor}/site-packages"
19+
assert any(p == venv_site_packages for p in sys.path)
20+
21+
22+
def PHLEX_REGISTER_ALGORITHMS(m, config):
23+
"""Register check_sys_path for checking sys.path.
24+
25+
Args:
26+
m (internal): Phlex registrar representation.
27+
config (internal): Phlex configuration representation.
28+
29+
Returns:
30+
None
31+
"""
32+
m.observe(Checker(config["venv"]), input_family = config["input"])

test/python/pysyspath.jsonnet.in

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
driver: {
3+
cpp: 'generate_layers',
4+
layers: {
5+
event: { parent: 'job', total: 10, starting_number: 1 }
6+
}
7+
},
8+
sources: {
9+
provider: {
10+
cpp: 'cppsource4py',
11+
}
12+
},
13+
modules: {
14+
pysyspath: {
15+
py: 'check_sys_path',
16+
input: ['i'],
17+
venv: '@PY_VIRTUAL_ENV_DIR@',
18+
},
19+
},
20+
}

0 commit comments

Comments
 (0)