Skip to content

Commit

Permalink
Fix finding Numpy packages in Pypp
Browse files Browse the repository at this point in the history
  • Loading branch information
nilsvu committed Feb 13, 2023
1 parent 10bb97a commit 8ac6309
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 28 deletions.
12 changes: 12 additions & 0 deletions tests/Unit/Framework/CMakeLists.txt
Expand Up @@ -31,3 +31,15 @@ target_link_libraries(
Python::Python
Utilities
)

# Give SetupLocalPythonEnvironment access to installed Python packages.
# The Python interpreter usually takes care of adding this directory to the path
# at launch, but in SetupLocalPythonEnvironment we just link in Python. The
# linked Python libs may reside in a different place than the Python interpreter
# (in particular when the Python interpreter was symlinked to a venv). Thefore,
# SetupLocalPythonEnvironment needs to add this directory to the path as well.
target_compile_definitions(
${LIBRARY}
PRIVATE
PYTHON_SITELIB="${Python_SITELIB}"
)
63 changes: 35 additions & 28 deletions tests/Unit/Framework/SetupLocalPythonEnvironment.cpp
@@ -1,6 +1,7 @@
// Distributed under the MIT License.
// See LICENSE.txt for details.

#include <boost/preprocessor.hpp>
#include <codecvt> // IWYU pragma: keep
#include <locale> // IWYU pragma: keep
#include <string>
Expand Down Expand Up @@ -33,41 +34,47 @@ SetupLocalPythonEnvironment::SetupLocalPythonEnvironment(
// tree. The overhead of not having the compile files is <= 0.01s
Py_DontWriteBytecodeFlag = 1;
Py_Initialize();

// clang-tidy: Do not use const-cast
PyObject* pyob_old_paths =
PySys_GetObject(const_cast<char*>("path")); // NOLINT
const auto old_paths =
pypp::from_py_object<std::vector<std::string>>(pyob_old_paths);
std::string new_path =
unit_test_src_path() + cur_dir_relative_to_unit_test_path;
if (not file_system::check_if_dir_exists(new_path)) {
ERROR_NO_TRACE("Trying to add path '"
<< new_path
<< "' to the python environment during setup "
"but this directory does not exist. Maybe "
"you have a typo in your path?");
}

// Add directory for installed packages (see CMakeLists.txt for details)
new_path += ":";
new_path += PYTHON_SITELIB;

for (const auto& p : old_paths) {
new_path += ":";
new_path += p;
}

#if PY_MAJOR_VERSION == 3
PySys_SetPath(std::wstring_convert<std::codecvt_utf8<wchar_t>>()
.from_bytes(new_path)
.c_str());
#else
// clang-tidy: Do not use const-cast
PySys_SetPath(const_cast<char*>(new_path.c_str())); // NOLINT
#endif

// On some python versions init_numpy() can throw an FPE, this occurred at
// least with python 3.6, numpy 1.14.2.
disable_floating_point_exceptions();
init_numpy();
enable_floating_point_exceptions();
}
initialized = true;
// clang-tidy: Do not use const-cast
PyObject *pyob_old_paths =
PySys_GetObject(const_cast<char *>("path")); // NOLINT
const auto old_paths =
pypp::from_py_object<std::vector<std::string>>(pyob_old_paths);
std::string new_path =
unit_test_src_path()+cur_dir_relative_to_unit_test_path;
if (not file_system::check_if_dir_exists(new_path)) {
ERROR_NO_TRACE("Trying to add path '"
<< new_path
<< "' to the python environment during setup "
"but this directory does not exist. Maybe "
"you have a typo in your path?");
}

for (const auto &p : old_paths) {
new_path += ":";
new_path += p;
}

#if PY_MAJOR_VERSION == 3
PySys_SetPath(std::wstring_convert<std::codecvt_utf8<wchar_t>>()
.from_bytes(new_path)
.c_str());
#else
// clang-tidy: Do not use const-cast
PySys_SetPath(const_cast<char*>(new_path.c_str())); // NOLINT
#endif
}

#if PY_MAJOR_VERSION == 3
Expand Down

0 comments on commit 8ac6309

Please sign in to comment.