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:
parent
d0411510fa
commit
c4a1a6c0b4
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user