Extract py::AppendToSysPath function

Reviewers: mferencevic, ipaljak, llugovic

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2714
This commit is contained in:
Teon Banek 2020-03-09 10:42:07 +01:00
parent d0411510fa
commit c4a1a6c0b4
2 changed files with 23 additions and 15 deletions

View File

@ -190,7 +190,7 @@ inline std::ostream &operator<<(std::ostream &os, const Object &py_object) {
/// Stores information on a raised Python exception.
/// @sa FetchError
struct ExceptionInfo final {
struct [[nodiscard]] ExceptionInfo final {
/// Type of the exception, if nullptr there is no exception.
Object type;
/// Optional value of the exception.
@ -222,7 +222,7 @@ inline std::ostream &operator<<(std::ostream &os,
/// Get the current exception info and clear the current exception indicator.
///
/// This is normally used to catch and handle exceptions via C API.
inline std::optional<ExceptionInfo> FetchError() {
[[nodiscard]] inline std::optional<ExceptionInfo> FetchError() {
PyObject *exc_type, *exc_value, *traceback;
PyErr_Fetch(&exc_type, &exc_value, &traceback);
if (!exc_type) return std::nullopt;
@ -230,4 +230,22 @@ inline std::optional<ExceptionInfo> FetchError() {
return ExceptionInfo{Object(exc_type), Object(exc_value), Object(traceback)};
}
/// Append `dir` to Python's `sys.path`.
///
/// The function does not check whether the directory exists, or is readable.
/// ExceptionInfo is returned if an error occurred.
[[nodiscard]] inline std::optional<ExceptionInfo> AppendToSysPath(
const char *dir) {
CHECK(dir);
auto *py_path = PySys_GetObject("path");
CHECK(py_path);
py::Object import_dir(PyUnicode_FromString(dir));
if (!import_dir) return py::FetchError();
int import_dir_in_path = PySequence_Contains(py_path, import_dir);
if (import_dir_in_path == -1) return py::FetchError();
if (import_dir_in_path == 1) return std::nullopt;
if (PyList_Append(py_path, import_dir) == -1) return py::FetchError();
return std::nullopt;
}
} // namespace py

View File

@ -345,21 +345,11 @@ bool PythonModule::Load(std::filesystem::path file_path) {
CHECK(!py_module_) << "Attempting to load an already loaded module...";
LOG(INFO) << "Loading module " << file_path << " ...";
auto gil = py::EnsureGIL();
auto *py_path = PySys_GetObject("path");
CHECK(py_path);
py::Object import_dir(PyUnicode_FromString(file_path.parent_path().c_str()));
int import_dir_in_path = PySequence_Contains(py_path, import_dir);
if (import_dir_in_path == -1) {
LOG(ERROR) << "Unexpected error when loading module " << file_path;
auto maybe_exc = py::AppendToSysPath(file_path.parent_path().c_str());
if (maybe_exc) {
LOG(ERROR) << "Unable to load module " << file_path << "; " << *maybe_exc;
return false;
}
if (import_dir_in_path == 0) {
if (PyList_Append(py_path, import_dir) != 0) {
auto exc_info = py::FetchError().value();
LOG(ERROR) << "Unable to load module " << file_path << "; " << exc_info;
return false;
}
}
py_module_ =
WithModuleRegistration(&procedures_, [&](auto *module_def, auto *memory) {
return ImportPyModule(file_path.stem().c_str(), module_def);