From 67ea7deb005964fe8ea1687697d85dc4832bddf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 18 Apr 2022 22:40:36 +0200 Subject: [PATCH] Clean stuff. Bindings for IFileTree. --- src/runner-pybind11/converters_qt.h | 8 +- src/runner-pybind11/converters_qt_sip.cpp | 91 ++ src/runner-pybind11/converters_qt_sip.h | 34 +- src/runner-pybind11/pyfiletree.cpp | 248 ++++++ src/runner-pybind11/pyfiletree.h | 36 + src/runner-pybind11/pylogger.cpp | 74 -- src/runner-pybind11/pylogger.h | 13 - src/runner-pybind11/pythonrunner.cpp | 827 ++++++++----------- src/runner-pybind11/pythonutils.cpp | 93 ++- src/runner-pybind11/pythonutils.h | 253 +----- src/runner-pybind11/pythonwrapperutilities.h | 4 +- src/runner-pybind11/sipapiaccess.cpp | 86 -- src/runner-pybind11/sipapiaccess.h | 12 - src/runner-pybind11/tuple_helper.h | 99 --- src/runner-pybind11/variant_helper.h | 104 --- src/runner-pybind11/widgets.cpp | 4 +- 16 files changed, 825 insertions(+), 1161 deletions(-) create mode 100644 src/runner-pybind11/converters_qt_sip.cpp create mode 100644 src/runner-pybind11/pyfiletree.cpp create mode 100644 src/runner-pybind11/pyfiletree.h delete mode 100644 src/runner-pybind11/pylogger.cpp delete mode 100644 src/runner-pybind11/pylogger.h delete mode 100644 src/runner-pybind11/sipapiaccess.cpp delete mode 100644 src/runner-pybind11/sipapiaccess.h delete mode 100644 src/runner-pybind11/tuple_helper.h delete mode 100644 src/runner-pybind11/variant_helper.h diff --git a/src/runner-pybind11/converters_qt.h b/src/runner-pybind11/converters_qt.h index 7948c69..9a50fae 100644 --- a/src/runner-pybind11/converters_qt.h +++ b/src/runner-pybind11/converters_qt.h @@ -96,7 +96,7 @@ namespace pybind11::detail { * instance or return false upon failure. The second argument * indicates whether implicit conversions should be applied. */ - bool load(handle src, bool) { + inline bool load(handle src, bool) { PyObject *objPtr = src.ptr(); @@ -125,7 +125,7 @@ namespace pybind11::detail { * ``return_value_policy::reference_internal``) and are generally * ignored by implicit casters. */ - static handle cast(QString src, return_value_policy /* policy */, handle /* parent */) { + inline static handle cast(QString src, return_value_policy /* policy */, handle /* parent */) { static_assert(sizeof(QChar) == 2); return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, src.constData(), src.length()); } @@ -143,7 +143,7 @@ namespace pybind11::detail { * instance or return false upon failure. The second argument * indicates whether implicit conversions should be applied. */ - bool load(handle src, bool); + inline bool load(handle src, bool); /** * Conversion part 2 (C++ -> Python): convert an QString instance into @@ -152,7 +152,7 @@ namespace pybind11::detail { * ``return_value_policy::reference_internal``) and are generally * ignored by implicit casters. */ - static handle cast(QVariant var, return_value_policy policy, handle parent); + inline static handle cast(QVariant var, return_value_policy policy, handle parent); }; // QList diff --git a/src/runner-pybind11/converters_qt_sip.cpp b/src/runner-pybind11/converters_qt_sip.cpp new file mode 100644 index 0000000..9fc9e9d --- /dev/null +++ b/src/runner-pybind11/converters_qt_sip.cpp @@ -0,0 +1,91 @@ +#include "converters_qt_sip.h" + +#include + +#include + +namespace py = pybind11; + +namespace mo2::details { + + const sipAPIDef* sipAPI() + { + QString exception; + static const sipAPIDef* sipApi = nullptr; + if (sipApi == nullptr) { + #if defined(SIP_USE_PYCAPSULE) + PyImport_ImportModule("PyQt5.sip"); + + auto errorObj = PyErr_Occurred(); + if (errorObj != NULL) { + PyObject* type, * value, * traceback; + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + if (traceback != NULL) { + py::handle h_type(type); + py::handle h_val(value); + py::handle h_tb(traceback); + py::module_ tb = py::module_::import("traceback"); + py::object fmt_exp(tb.attr("format_exception")); + py::object exp_list(fmt_exp(h_type, h_val, h_tb)); + py::object exp_str(py::str("\n").attr("join")(exp_list)); + exception = QString::fromStdString(exp_str.cast()); + } + PyErr_Restore(type, value, traceback); + throw MOBase::Exception(QString("Failed to load PyQt5: %1").arg(exception)); + } + + sipApi = (const sipAPIDef*)PyCapsule_Import("PyQt5.sip._C_API", 0); + if (sipApi == NULL) { + auto errorObj = PyErr_Occurred(); + if (errorObj != NULL) { + PyObject* type, * value, * traceback; + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + if (traceback != NULL) { + py::handle h_type(type); + py::handle h_val(value); + py::handle h_tb(traceback); + py::module_ tb = py::module_::import("traceback"); + py::object fmt_exp(tb.attr("format_exception")); + py::object exp_list(fmt_exp(h_type, h_val, h_tb)); + py::object exp_str(py::str("\n").attr("join")(exp_list)); + exception = QString::fromStdString(exp_str.cast()); + } + PyErr_Restore(type, value, traceback); + } + throw MOBase::Exception(QString("Failed to load SIP API: %1").arg(exception)); + } + #else + PyObject* sip_module; + PyObject* sip_module_dict; + PyObject* c_api; + + /* Import the SIP module. */ + sip_module = PyImport_ImportModule("PyQt5.sip"); + + if (sip_module == NULL) + return NULL; + + /* Get the module's dictionary. */ + sip_module_dict = PyModule_GetDict(sip_module); + + /* Get the "_C_API" attribute. */ + c_api = PyDict_GetItemString(sip_module_dict, "_C_API"); + + if (c_api == NULL) + return NULL; + + /* Sanity check that it is the right type. */ + if (!PyCObject_Check(c_api)) + return NULL; + + /* Get the actual pointer from the object. */ + sipApi = (const sipAPIDef*)PyCObject_AsVoidPtr(c_api); + #endif + } + + return sipApi; + } + +} diff --git a/src/runner-pybind11/converters_qt_sip.h b/src/runner-pybind11/converters_qt_sip.h index f123616..410dced 100644 --- a/src/runner-pybind11/converters_qt_sip.h +++ b/src/runner-pybind11/converters_qt_sip.h @@ -1,10 +1,30 @@ #ifndef PYTHON_CONVERTERS_QT_SIP_HPP #define PYTHON_CONVERTERS_QT_SIP_HPP -#include "sipapiaccess.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include namespace mo2::details { + /** + * @brief Retrieve the SIP api. + * + * @return const sipAPIDef* + */ + const sipAPIDef* sipAPI(); + template struct MetaData; template @@ -43,10 +63,10 @@ namespace mo2::details { // sipAPI()->api_transfer_to(objPtr, Py_None); // void* data = nullptr; - if (PyObject_TypeCheck(src.ptr(), sipAPIAccess::sipAPI()->api_simplewrapper_type)) { + if (PyObject_TypeCheck(src.ptr(), mo2::details::sipAPI()->api_simplewrapper_type)) { data = reinterpret_cast(src.ptr())->data; } - else if (PyObject_TypeCheck(src.ptr(), sipAPIAccess::sipAPI()->api_wrapper_type)) { + else if (PyObject_TypeCheck(src.ptr(), mo2::details::sipAPI()->api_wrapper_type)) { data = reinterpret_cast(src.ptr())->super.data; } @@ -68,7 +88,7 @@ namespace mo2::details { QtType src, pybind11::return_value_policy /* policy */, pybind11::handle /* parent */) { const sipTypeDef* type = - sipAPIAccess::sipAPI()->api_find_type(MetaData::name); + mo2::details::sipAPI()->api_find_type(MetaData::name); if (type == nullptr) { return Py_None; } @@ -87,10 +107,10 @@ namespace mo2::details { } if constexpr (std::is_pointer_v) { - sipObj = sipAPIAccess::sipAPI()->api_convert_from_type(sipData, type, 0); + sipObj = mo2::details::sipAPI()->api_convert_from_type(sipData, type, 0); } else { - sipObj = sipAPIAccess::sipAPI()->api_convert_from_type(sipData, type, 0); + sipObj = mo2::details::sipAPI()->api_convert_from_type(sipData, type, 0); } if (sipObj == nullptr) { @@ -99,7 +119,7 @@ namespace mo2::details { if constexpr (!std::is_pointer_v && std::is_copy_constructible_v) { // ensure Python deletes the C++ component - sipAPIAccess::sipAPI()->api_transfer_back(sipObj); + mo2::details::sipAPI()->api_transfer_back(sipObj); } return sipObj; diff --git a/src/runner-pybind11/pyfiletree.cpp b/src/runner-pybind11/pyfiletree.cpp new file mode 100644 index 0000000..ee46ceb --- /dev/null +++ b/src/runner-pybind11/pyfiletree.cpp @@ -0,0 +1,248 @@ +#include "pyfiletree.h" + +#include +#include + +#include +#include +#include + +#include +#include + +#include "converters_qt.h" + +namespace py = pybind11; +using namespace MOBase; + +namespace mo2::details { + + // filetree implementation for testing purpose + // + class PyFileTree : public IFileTree { + public: + + using callback_t = std::function; + + PyFileTree(std::shared_ptr parent, QString name, callback_t callback) : + FileTreeEntry(parent, name), IFileTree(), m_Callback(callback){ } + + std::shared_ptr addFile(QString name, bool) override { + if (m_Callback && !m_Callback(name, false)) { + throw UnsupportedOperationException("File rejected by callback."); + } + return IFileTree::addFile(name); + } + + std::shared_ptr addDirectory(QString name) override { + if (m_Callback && !m_Callback(name, true)) { + throw UnsupportedOperationException("Directory rejected by callback."); + } + return IFileTree::addDirectory(name); + } + + protected: + + std::shared_ptr makeDirectory(std::shared_ptr parent, QString name) const override { + return std::make_shared(parent, name, m_Callback); + } + + bool doPopulate(std::shared_ptr parent, std::vector>& entries) const override { return true; } + std::shared_ptr doClone() const override { return std::make_shared(nullptr, name(), m_Callback); } + + private: + callback_t m_Callback; + }; + +} + +#pragma optimize("", off) + +namespace pybind11 { + const void *polymorphic_type_hook::get(const FileTreeEntry *src, const std::type_info *&type) { + if (auto p = dynamic_cast(src)) { + type = &typeid(IFileTree); + return p; + } + return src; + } +} // namespace pybind11 + +namespace mo2::python { + + void add_ifiletree_bindings(pybind11::module_ &m) { + + // FileTreeEntry Scope: + auto fileTreeEntryClass = py::class_>(m, "FileTreeEntry"); + + // we do not use the enum directly, we will mostly bind the FileTypes (with an S) + py::enum_(fileTreeEntryClass, "FileType", py::arithmetic{}); + py::class_(fileTreeEntryClass, "FileTypes") + .def_property_readonly_static("FILE", [](py::object) { return FileTreeEntry::FILE; }) + .def_property_readonly_static("DIRECTORY", [](py::object) { return FileTreeEntry::DIRECTORY; }) + .def_property_readonly_static("FILE_OR_DIRECTORY", [](py::object) { return FileTreeEntry::FILE_OR_DIRECTORY; }) + + .def(py::self == py::self) + .def(py::self != py::self) + .def(py::self | py::self) + ; + py::implicitly_convertible(); + + fileTreeEntryClass + .def_property_readonly_static("FILE", [](py::object) { return FileTreeEntry::FILE; }) + .def_property_readonly_static("DIRECTORY", [](py::object) { return FileTreeEntry::DIRECTORY; }) + .def_property_readonly_static("FILE_OR_DIRECTORY", [](py::object) { return FileTreeEntry::FILE_OR_DIRECTORY; }); + + fileTreeEntryClass + + .def("isFile", &FileTreeEntry::isFile) + .def("isDir", &FileTreeEntry::isDir) + // Forcing the conversion to FileTypeS to avoid having to expose FileType in python: + .def("fileType", &FileTreeEntry::fileType) + // This should probably not be exposed in python since we provide automatic downcast: + // .def("getTree", static_cast(FileTreeEntry::*)()>(&FileTreeEntry::astree)) + .def("name", &FileTreeEntry::name) + .def("suffix", &FileTreeEntry::suffix) + .def("hasSuffix", [](FileTreeEntry* entry, QStringList suffixes) { return entry->hasSuffix(suffixes); }, py::arg("suffixes")) + .def("hasSuffix", [](FileTreeEntry* entry, QString suffix) { return entry->hasSuffix(suffix); }, py::arg("suffix")) + .def("parent", py::overload_cast<>(&FileTreeEntry::parent), "[optional]") + .def("path", &FileTreeEntry::path, py::arg("sep") = "\\") + .def("pathFrom", &FileTreeEntry::pathFrom, py::arg("tree"), py::arg("sep") = "\\") + + // Mutable operation: + .def("detach", &FileTreeEntry::detach) + .def("moveTo", &FileTreeEntry::moveTo, py::arg("tree")) + + // Special methods: + .def("__eq__", [](const FileTreeEntry* entry, QString other) { + return entry->compare(other) == 0; + }) + .def("__eq__", [](const FileTreeEntry* entry, std::shared_ptr other) { + return entry == other.get(); + }) + + // Special methods for debug: + .def("__repr__", [](const FileTreeEntry* entry) { return "FileTreeEntry(\"" + entry->name() + "\")"; }) + ; + + // IFileTree scope: + auto iFileTreeClass = py::class_>( + m, "IFileTree", py::multiple_inheritance()); + + py::enum_(iFileTreeClass, "InsertPolicy") + .value("FAIL_IF_EXISTS", IFileTree::InsertPolicy::FAIL_IF_EXISTS) + .value("REPLACE", IFileTree::InsertPolicy::REPLACE) + .value("MERGE", IFileTree::InsertPolicy::MERGE) + .export_values() + ; + + py::enum_(iFileTreeClass, "WalkReturn") + .value("CONTINUE", IFileTree::WalkReturn::CONTINUE) + .value("STOP", IFileTree::WalkReturn::STOP) + .value("SKIP", IFileTree::WalkReturn::SKIP) + .export_values() + ; + + // Non-mutable operations: + iFileTreeClass.def("exists", + py::overload_cast(&IFileTree::exists, py::const_), + py::arg("path"), py::arg("type") = IFileTree::FILE_OR_DIRECTORY); + iFileTreeClass.def("find", py::overload_cast(&IFileTree::find), + py::arg("path"), py::arg("type") = IFileTree::FILE_OR_DIRECTORY, "[optional]"); + iFileTreeClass.def("pathTo", + &IFileTree::pathTo, py::arg("entry"), py::arg("sep") = "\\"); + + // Note: walk() would probably be better as a generator in python, but it is likely impossible to construct + // from the C++ walk() method. + iFileTreeClass.def("walk", + &IFileTree::walk, py::arg("callback"), py::arg("sep") = "\\"); + + // Kind-of-static operations: + iFileTreeClass.def("createOrphanTree", + &IFileTree::createOrphanTree, py::arg("name") = ""); + + // addFile() and addDirectory throws exception instead of returning null pointer in order + // to have better traces. + iFileTreeClass.def("addFile", [](IFileTree* w, QString path, bool replaceIfExists) { + auto result = w->addFile(path, replaceIfExists); + if (result == nullptr) { + throw std::logic_error("addFile failed"); + } + return result; + }, py::arg("path"), py::arg("replace_if_exists") = false); + iFileTreeClass.def("addDirectory", [](IFileTree* w, QString path) { + auto result = w->addDirectory(path); + if (result == nullptr) { + throw std::logic_error("addDirectory failed"); + } + MOBase::log::warn("{}", result->fileType()); + return result; + }, py::arg("path")); + + // Merge needs custom return types depending if the user wants overrides or not. A failure is translated + // into an exception for easier tracing and handling. + iFileTreeClass.def("merge", + [](IFileTree* p, std::shared_ptr other, bool returnOverwrites) + -> std::variant { + IFileTree::OverwritesType overwrites; + auto result = p->merge(other, returnOverwrites ? &overwrites : nullptr); + if (result == IFileTree::MERGE_FAILED) { + throw std::logic_error("merge failed"); + } + if (returnOverwrites) { + return { overwrites }; + } + return { result }; + }, py::arg("other"), py::arg("overwrites") = false); + + // Insert and erase returns an iterator, which makes no sense in python, so we convert it to bool. Erase is also + // renamed "remove" since "erase" is very C++. + iFileTreeClass.def("insert", + [](IFileTree* p, std::shared_ptr entry, IFileTree::InsertPolicy insertPolicy) { + return p->insert(entry, insertPolicy) == p->end(); + }, py::arg("entry"), py::arg("policy") = IFileTree::InsertPolicy::FAIL_IF_EXISTS); + + iFileTreeClass.def("remove", [](IFileTree* p, QString name) { + return p->erase(name).first != p->end(); }, py::arg("name")); + iFileTreeClass.def("remove", [](IFileTree* p, std::shared_ptr entry) { + return p->erase(entry) != p->end(); }, py::arg("entry")); + + iFileTreeClass.def("move", + &IFileTree::move, py::arg("entry"), py::arg("path"), + py::arg("policy") = IFileTree::InsertPolicy::FAIL_IF_EXISTS); + iFileTreeClass.def("copy", + [](IFileTree* w, std::shared_ptr entry, QString path, IFileTree::InsertPolicy insertPolicy) { + auto result = w->copy(entry, path, insertPolicy); + if (result == nullptr) { + throw std::logic_error("copy failed"); + } + return result; + }, py::arg("entry"), py::arg("path") = "", + py::arg("insert_policy") = IFileTree::InsertPolicy::FAIL_IF_EXISTS); + + iFileTreeClass.def("clear", &IFileTree::clear); + iFileTreeClass.def("removeAll", &IFileTree::removeAll, py::arg("names")); + iFileTreeClass.def("removeIf", &IFileTree::removeIf, py::arg("filter")); + + // Special methods: + iFileTreeClass.def("__getitem__", py::overload_cast(&IFileTree::at)); + // , py::return_value_policy>() + + iFileTreeClass.def("__iter__", [](IFileTree *tree) { + return py::make_iterator(*tree); }); + iFileTreeClass.def("__len__", &IFileTree::size); + iFileTreeClass.def("__bool__", +[](const IFileTree* tree) { + return !tree->empty(); }); + iFileTreeClass.def("__repr__", +[](const IFileTree* entry) { + return "IFileTree(\"" + entry->name() + "\")"; }); + } + + void add_make_tree_function(pybind11::module_ &m) { + m.def("makeTree", [](mo2::details::PyFileTree::callback_t callback) -> std::shared_ptr { + return std::make_shared(nullptr, "", callback); + }, py::arg("callback") = mo2::details::PyFileTree::callback_t{}); + } + +} + +#pragma optimize("", on) diff --git a/src/runner-pybind11/pyfiletree.h b/src/runner-pybind11/pyfiletree.h new file mode 100644 index 0000000..7a31039 --- /dev/null +++ b/src/runner-pybind11/pyfiletree.h @@ -0,0 +1,36 @@ +#ifndef MO2_PYTHON_FILETREE_H +#define MO2_PYTHON_FILETREE_H + +#include + +#include + +namespace pybind11 +{ + template <> + struct polymorphic_type_hook + { + static const void *get(const MOBase::FileTreeEntry *src, const std::type_info *&type); + }; +} // namespace pybind11 + + +namespace mo2::python { + + /** + * @brief Add bindings for FileTreeEntry andIFileTree to the given module. + * + * @param mobase Module to add the bindings to. + */ + void add_ifiletree_bindings(pybind11::module_ &m); + + /** + * @brief Add makeTree() function to the given module, useful for debugging. + * + * @param mobase Module to add the function to. + */ + void add_make_tree_function(pybind11::module_ &m); + +} + +#endif diff --git a/src/runner-pybind11/pylogger.cpp b/src/runner-pybind11/pylogger.cpp deleted file mode 100644 index f0793e3..0000000 --- a/src/runner-pybind11/pylogger.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "pylogger.h" - -#include "log.h" - -namespace py = pybind11; - -// Small structure to hold the levels - There are copy paste from -// my Python version and I assume these will not change soon: -struct PyLogLevel { - static constexpr int CRITICAL = 50; - static constexpr int ERROR = 40; - static constexpr int WARNING = 30; - static constexpr int INFO = 20; - static constexpr int DEBUG = 10; -}; - -// This is the function we are going to use as our Handler .emit -// method. -void emit_function(py::object self, py::object record) { - - // There are other parameters that could be used, but this is minimal for - // now (filename, line number, etc.). - const int level = record.attr("levelno").cast(); - const std::wstring msg = py::str(record.attr("msg")).cast(); - - switch (level) { - case PyLogLevel::CRITICAL: - case PyLogLevel::ERROR: - MOBase::log::error("{}", msg); - break; - case PyLogLevel::WARNING: - MOBase::log::warn("{}", msg); - break; - case PyLogLevel::INFO: - MOBase::log::info("{}", msg); - break; - case PyLogLevel::DEBUG: - default: // There is a "NOTSET" level in theory: - MOBase::log::debug("{}", msg); - break; - } -}; - -void configure_python_logging(py::module_ mobase) -{ - // most of this is dealing with actual Python objects since it is not possible - // to derive from logging.Handler in C++ using Boost.Python, and since a lot of - // this would require extra register only for this. - - // see also https://github.com/pybind/pybind11/issues/1193#issuecomment-429451094 - - // retrieve the logging module and the Handler class. - auto logging = py::module_::import("logging"); - auto Handler = logging.attr("Handler"); - - // this is ugly but that's how it's done in C Python - auto type = py::reinterpret_borrow((PyObject*)&PyType_Type); - - // Create the "MO2Handler" python class: - auto methods = py::dict(); - methods["emit"] = py::cpp_function(emit_function); - auto MO2Handler = type("LogHandler", py::make_tuple(Handler), methods); - - // Create the default logger: - auto handler = MO2Handler(); - handler.attr("setLevel")(PyLogLevel::DEBUG); - auto logger = logging.attr("getLogger")(py::object(mobase.attr("__name__"))); - logger.attr("setLevel")(PyLogLevel::DEBUG); - logger.attr("addHandler")(handler); - - // Set mobase attributes: - mobase.attr("LogHandler") = MO2Handler; - mobase.attr("logger") = logger; -} diff --git a/src/runner-pybind11/pylogger.h b/src/runner-pybind11/pylogger.h deleted file mode 100644 index 5d0804b..0000000 --- a/src/runner-pybind11/pylogger.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef MO2_PYTHON_LOGGER_H -#define MO2_PYTHON_LOGGER_H - -#include - -/** - * @brief Configure logging for MO2 python plugin. - * - * @param mobase The mobase module. - */ -void configure_python_logging(pybind11::module_ mobase); - -#endif diff --git a/src/runner-pybind11/pythonrunner.cpp b/src/runner-pybind11/pythonrunner.cpp index 1d01701..6906f5c 100644 --- a/src/runner-pybind11/pythonrunner.cpp +++ b/src/runner-pybind11/pythonrunner.cpp @@ -39,7 +39,8 @@ #include "error.h" // #include "gamefeatureswrappers.h" // #include "proxypluginwrappers.h" -#include "pylogger.h" +#include "pyfiletree.h" +#include "pythonutils.h" // #include "shared_ptr_converter.h" // #include "sipApiAccess.h" // #include "tuple_helper.h" @@ -54,7 +55,7 @@ using namespace MOBase; namespace py = pybind11; /** - * This macro should be used within a bpy::class_ declaration and will define two + * This macro should be used within a py::class_ declaration and will define two * methods: __getattr__ and Name, where Name will simply return the object as a QClass* * object, while __getattr__ will delegate to the underlying QClass object when required. * @@ -62,9 +63,9 @@ namespace py = pybind11; * methods from QObject or QWidget, etc.). */ #define Q_DELEGATE(Class, QClass, Name) \ - .def(Name, +[](Class* w) -> QClass* { return w; }, bpy::return_value_policy()) \ - .def("__getattr__", +[](Class* w, bpy::str str) -> bpy::object { \ - return bpy::object{ (QClass*)w }.attr(str); \ + .def(Name, +[](Class* w) -> QClass* { return w; }, py::return_value_policy()) \ + .def("__getattr__", +[](Class* w, py::str str) -> py::object { \ + return py::object{ (QClass*)w }.attr(str); \ }) PYBIND11_MODULE(mobase, m) @@ -130,18 +131,18 @@ PYBIND11_MODULE(mobase, m) // utils::register_enum_converter(); // // Pointers: - // bpy::register_ptr_to_python>(); - // bpy::register_ptr_to_python>(); - // bpy::implicitly_convertible, std::shared_ptr>(); - // bpy::register_ptr_to_python>(); - // bpy::register_ptr_to_python>(); - // bpy::implicitly_convertible, std::shared_ptr>(); + // py::register_ptr_to_python>(); + // py::register_ptr_to_python>(); + // py::implicitly_convertible, std::shared_ptr>(); + // py::register_ptr_to_python>(); + // py::register_ptr_to_python>(); + // py::implicitly_convertible, std::shared_ptr>(); // utils::shared_ptr_from_python>(); - // bpy::register_ptr_to_python>(); + // py::register_ptr_to_python>(); // utils::shared_ptr_from_python>(); - // bpy::register_ptr_to_python>(); + // py::register_ptr_to_python>(); // // Containers: // utils::register_sequence_container>(); @@ -174,21 +175,21 @@ PYBIND11_MODULE(mobase, m) // utils::register_optional>(); // // Tuple: - // bpy::register_tuple>(); // IOrganizer::waitForApplication - // bpy::register_tuple>(); // IProfile::invalidationActive - // bpy::register_tuple>(); - // bpy::register_tuple, QString, int>>(); - // bpy::register_tuple>(); + // py::register_tuple>(); // IOrganizer::waitForApplication + // py::register_tuple>(); // IProfile::invalidationActive + // py::register_tuple>(); + // py::register_tuple, QString, int>>(); + // py::register_tuple>(); // // Variants: - // bpy::register_variant, // std::tuple, QString, int>>>(); - // bpy::register_variant>(); - // bpy::register_variant>(); - // bpy::register_variant>>(); - // bpy::register_variant>>(); + // py::register_variant>(); + // py::register_variant>(); + // py::register_variant>>(); + // py::register_variant>>(); // // Functions: // utils::register_functor_converter(); // converter for the onRefreshed-callback @@ -200,17 +201,17 @@ PYBIND11_MODULE(mobase, m) // utils::register_functor_converter&)>(); // converter for the onPluginStateChanged-callback (IPluginList) // utils::register_functor_converter(); // utils::register_functor_converter(); - // utils::register_functor_converter>(); - // utils::register_functor_converter>(); - // utils::register_functor_converter>(); + // utils::register_functor_converter>(); + // utils::register_functor_converter>(); + // utils::register_functor_converter>(); // utils::register_functor_converter(); // utils::register_functor_converter)>(); // utils::register_functor_converter>(); // utils::register_functor_converter const&)>(); // utils::register_functor_converter(QString const&)>(); - // utils::register_functor_converter>(); - // utils::register_functor_converter>(); - // utils::register_functor_converter>(); + // utils::register_functor_converter>(); + // utils::register_functor_converter>(); + // utils::register_functor_converter>(); // // This one is kept for backward-compatibility while we deprecate onModStateChanged for singl mod. // utils::register_functor_converter(); // converter for the onModStateChanged-callback (IModList). @@ -220,7 +221,7 @@ PYBIND11_MODULE(mobase, m) // // Class declarations: // // - // bpy::enum_("ReleaseType") + // py::enum_("ReleaseType") // .value("final", MOBase::VersionInfo::RELEASE_FINAL) // .value("candidate", MOBase::VersionInfo::RELEASE_CANDIDATE) // .value("beta", MOBase::VersionInfo::RELEASE_BETA) @@ -234,7 +235,7 @@ PYBIND11_MODULE(mobase, m) // .value("PRE_ALPHA", MOBase::VersionInfo::RELEASE_PREALPHA) // ; - // bpy::enum_("VersionScheme") + // py::enum_("VersionScheme") // .value("discover", MOBase::VersionInfo::SCHEME_DISCOVER) // .value("regular", MOBase::VersionInfo::SCHEME_REGULAR) // .value("decimalmark", MOBase::VersionInfo::SCHEME_DECIMALMARK) @@ -250,44 +251,44 @@ PYBIND11_MODULE(mobase, m) // .value("LITERAL", MOBase::VersionInfo::SCHEME_LITERAL) // ; - // bpy::class_("VersionInfo") - // .def(bpy::init( - // (bpy::arg("value"), bpy::arg("scheme") = VersionInfo::SCHEME_DISCOVER))) + // py::class_("VersionInfo") + // .def(py::init( + // (py::arg("value"), py::arg("scheme") = VersionInfo::SCHEME_DISCOVER))) // // Note: Order of the two init<> below is important because ReleaseType is a simple enum with an // // implicit int conversion. - // .def(bpy::init( - // (bpy::arg("major"), "minor", "subminor", "subsubminor", bpy::arg("release_type") = VersionInfo::RELEASE_FINAL))) - // .def(bpy::init( - // (bpy::arg("major"), "minor", "subminor", bpy::arg("release_type") = VersionInfo::RELEASE_FINAL))) + // .def(py::init( + // (py::arg("major"), "minor", "subminor", "subsubminor", py::arg("release_type") = VersionInfo::RELEASE_FINAL))) + // .def(py::init( + // (py::arg("major"), "minor", "subminor", py::arg("release_type") = VersionInfo::RELEASE_FINAL))) // .def("clear", &VersionInfo::clear) // .def("parse", &VersionInfo::parse, - // (bpy::arg("value"), bpy::arg("scheme") = VersionInfo::SCHEME_DISCOVER, bpy::arg("is_manual") = false)) + // (py::arg("value"), py::arg("scheme") = VersionInfo::SCHEME_DISCOVER, py::arg("is_manual") = false)) // .def("canonicalString", &VersionInfo::canonicalString) - // .def("displayString", &VersionInfo::displayString, bpy::arg("forced_segments") = 2) + // .def("displayString", &VersionInfo::displayString, py::arg("forced_segments") = 2) // .def("isValid", &VersionInfo::isValid) // .def("scheme", &VersionInfo::scheme) // .def("__str__", &VersionInfo::canonicalString) - // .def(bpy::self < bpy::self) - // .def(bpy::self > bpy::self) - // .def(bpy::self <= bpy::self) - // .def(bpy::self >= bpy::self) - // .def(bpy::self != bpy::self) - // .def(bpy::self == bpy::self) + // .def(py::self < py::self) + // .def(py::self > py::self) + // .def(py::self <= py::self) + // .def(py::self >= py::self) + // .def(py::self != py::self) + // .def(py::self == py::self) // ; - // bpy::class_( - // "PluginSetting", bpy::init( - // (bpy::arg("key"), "description", "default_value"))) + // py::class_( + // "PluginSetting", py::init( + // (py::arg("key"), "description", "default_value"))) // .def_readwrite("key", &PluginSetting::key) // .def_readwrite("description", &PluginSetting::description) // .def_readwrite("default_value", &PluginSetting::defaultValue); - // bpy::class_("ExecutableInfo", - // bpy::init((bpy::arg("title"), "binary"))) - // .def("withArgument", &ExecutableInfo::withArgument, bpy::return_self<>(), bpy::arg("argument")) - // .def("withWorkingDirectory", &ExecutableInfo::withWorkingDirectory, bpy::return_self<>(), bpy::arg("directory")) - // .def("withSteamAppId", &ExecutableInfo::withSteamAppId, bpy::return_self<>(), bpy::arg("app_id")) - // .def("asCustom", &ExecutableInfo::asCustom, bpy::return_self<>()) + // py::class_("ExecutableInfo", + // py::init((py::arg("title"), "binary"))) + // .def("withArgument", &ExecutableInfo::withArgument, py::return_self<>(), py::arg("argument")) + // .def("withWorkingDirectory", &ExecutableInfo::withWorkingDirectory, py::return_self<>(), py::arg("directory")) + // .def("withSteamAppId", &ExecutableInfo::withSteamAppId, py::return_self<>(), py::arg("app_id")) + // .def("asCustom", &ExecutableInfo::asCustom, py::return_self<>()) // .def("isValid", &ExecutableInfo::isValid) // .def("title", &ExecutableInfo::title) // .def("binary", &ExecutableInfo::binary) @@ -297,73 +298,73 @@ PYBIND11_MODULE(mobase, m) // .def("isCustom", &ExecutableInfo::isCustom) // ; - // bpy::class_("ExecutableForcedLoadSetting", - // bpy::init((bpy::arg("process"), "library"))) - // .def("withForced", &ExecutableForcedLoadSetting::withForced, bpy::return_self<>(), bpy::arg("forced")) - // .def("withEnabled", &ExecutableForcedLoadSetting::withEnabled, bpy::return_self<>(), bpy::arg("enabled")) + // py::class_("ExecutableForcedLoadSetting", + // py::init((py::arg("process"), "library"))) + // .def("withForced", &ExecutableForcedLoadSetting::withForced, py::return_self<>(), py::arg("forced")) + // .def("withEnabled", &ExecutableForcedLoadSetting::withEnabled, py::return_self<>(), py::arg("enabled")) // .def("enabled", &ExecutableForcedLoadSetting::enabled) // .def("forced", &ExecutableForcedLoadSetting::forced) // .def("library", &ExecutableForcedLoadSetting::library) // .def("process", &ExecutableForcedLoadSetting::process) // ; - // bpy::class_, boost::noncopyable>("ISaveGame") - // .def("getFilepath", bpy::pure_virtual(&ISaveGame::getFilepath)) - // .def("getCreationTime", bpy::pure_virtual(&ISaveGame::getCreationTime)) - // .def("getName", bpy::pure_virtual(&ISaveGame::getName)) - // .def("getSaveGroupIdentifier", bpy::pure_virtual(&ISaveGame::getSaveGroupIdentifier)) - // .def("allFiles", bpy::pure_virtual(&ISaveGame::allFiles)) + // py::class_, boost::noncopyable>("ISaveGame") + // .def("getFilepath", py::pure_virtual(&ISaveGame::getFilepath)) + // .def("getCreationTime", py::pure_virtual(&ISaveGame::getCreationTime)) + // .def("getName", py::pure_virtual(&ISaveGame::getName)) + // .def("getSaveGroupIdentifier", py::pure_virtual(&ISaveGame::getSaveGroupIdentifier)) + // .def("allFiles", py::pure_virtual(&ISaveGame::allFiles)) // ; // // See Q_DELEGATE for more details. - // bpy::class_, ISaveGameInfoWidgetWrapper*, boost::noncopyable>( - // "ISaveGameInfoWidget", bpy::init>(bpy::arg("parent"))) - // .def("setSave", bpy::pure_virtual(&ISaveGameInfoWidget::setSave), bpy::arg("save")) + // py::class_, ISaveGameInfoWidgetWrapper*, boost::noncopyable>( + // "ISaveGameInfoWidget", py::init>(py::arg("parent"))) + // .def("setSave", py::pure_virtual(&ISaveGameInfoWidget::setSave), py::arg("save")) // Q_DELEGATE(ISaveGameInfoWidget, QWidget, "_widget") // ; // // Plugin requirements: - // auto iPluginRequirementClass = bpy::class_< - // IPluginRequirementWrapper, bpy::bases<>, boost::noncopyable>("IPluginRequirement"); + // auto iPluginRequirementClass = py::class_< + // IPluginRequirementWrapper, py::bases<>, boost::noncopyable>("IPluginRequirement"); // { - // bpy::scope scope = iPluginRequirementClass; + // py::scope scope = iPluginRequirementClass; - // bpy::class_("Problem", - // bpy::init((bpy::arg("short_description"), bpy::arg("long_description") = ""))) + // py::class_("Problem", + // py::init((py::arg("short_description"), py::arg("long_description") = ""))) // .def("shortDescription", &IPluginRequirement::Problem::shortDescription) // .def("longDescription", &IPluginRequirement::Problem::longDescription); // iPluginRequirementClass - // .def("check", bpy::pure_virtual(&IPluginRequirement::check), bpy::arg("organizer")) + // .def("check", py::pure_virtual(&IPluginRequirement::check), py::arg("organizer")) // ; // } - // bpy::class_("PluginRequirementFactory") + // py::class_("PluginRequirementFactory") // // pluginDependency // .def("pluginDependency", +[](QStringList const& pluginNames) { // return PluginRequirementFactory::pluginDependency(pluginNames); - // }, bpy::arg("plugins")) + // }, py::arg("plugins")) // .def("pluginDependency", +[](QString const& pluginName) { // return PluginRequirementFactory::pluginDependency(pluginName); - // }, bpy::arg("plugin")) + // }, py::arg("plugin")) // .staticmethod("pluginDependency") // // gameDependency // .def("gameDependency", +[](QStringList const& gameNames) { // return PluginRequirementFactory::gameDependency(gameNames); - // }, bpy::arg("games")) + // }, py::arg("games")) // .def("gameDependency", +[](QString const& gameNames) { // return PluginRequirementFactory::gameDependency(gameNames); - // }, bpy::arg("game")) + // }, py::arg("game")) // .staticmethod("gameDependency") // // diagnose - // .def("diagnose", &PluginRequirementFactory::diagnose, bpy::arg("diagnose")) + // .def("diagnose", &PluginRequirementFactory::diagnose, py::arg("diagnose")) // .staticmethod("diagnose") // // basic - // .def("basic", &PluginRequirementFactory::basic, (bpy::arg("checker"), "description")) + // .def("basic", &PluginRequirementFactory::basic, (py::arg("checker"), "description")) // .staticmethod("basic"); - // bpy::class_("FileInfo", bpy::init<>()) + // py::class_("FileInfo", py::init<>()) // .add_property("filePath", // +[](const IOrganizer::FileInfo& info) { return info.filePath; }, // +[](IOrganizer::FileInfo& info, QString value) { info.filePath = value; }) @@ -375,8 +376,8 @@ PYBIND11_MODULE(mobase, m) // +[](IOrganizer::FileInfo& info, QStringList value) { info.origins = value; }) // ; - // bpy::class_("IOrganizer", bpy::no_init) - // .def("createNexusBridge", &IOrganizer::createNexusBridge, bpy::return_value_policy()) + // py::class_("IOrganizer", py::no_init) + // .def("createNexusBridge", &IOrganizer::createNexusBridge, py::return_value_policy()) // .def("profileName", &IOrganizer::profileName) // .def("profilePath", &IOrganizer::profilePath) // .def("downloadsPath", &IOrganizer::downloadsPath) @@ -384,23 +385,23 @@ PYBIND11_MODULE(mobase, m) // .def("basePath", &IOrganizer::basePath) // .def("modsPath", &IOrganizer::modsPath) // .def("appVersion", &IOrganizer::appVersion) - // .def("createMod", &IOrganizer::createMod, bpy::return_value_policy(), bpy::arg("name")) - // .def("getGame", &IOrganizer::getGame, bpy::return_value_policy(), bpy::arg("name")) - // .def("modDataChanged", &IOrganizer::modDataChanged, bpy::arg("mod")) - // .def("isPluginEnabled", +[](IOrganizer* o, IPlugin* plugin) { return o->isPluginEnabled(plugin); }, bpy::arg("plugin")) - // .def("isPluginEnabled", +[](IOrganizer* o, QString const& plugin) { return o->isPluginEnabled(plugin); }, bpy::arg("plugin")) - // .def("pluginSetting", &IOrganizer::pluginSetting, (bpy::arg("plugin_name"), "key")) - // .def("setPluginSetting", &IOrganizer::setPluginSetting, (bpy::arg("plugin_name"), "key", "value")) - // .def("persistent", &IOrganizer::persistent, (bpy::arg("plugin_name"), "key", bpy::arg("default") = QVariant())) - // .def("setPersistent", &IOrganizer::setPersistent, (bpy::arg("plugin_name"), "key", "value", bpy::arg("sync") = true)) + // .def("createMod", &IOrganizer::createMod, py::return_value_policy(), py::arg("name")) + // .def("getGame", &IOrganizer::getGame, py::return_value_policy(), py::arg("name")) + // .def("modDataChanged", &IOrganizer::modDataChanged, py::arg("mod")) + // .def("isPluginEnabled", +[](IOrganizer* o, IPlugin* plugin) { return o->isPluginEnabled(plugin); }, py::arg("plugin")) + // .def("isPluginEnabled", +[](IOrganizer* o, QString const& plugin) { return o->isPluginEnabled(plugin); }, py::arg("plugin")) + // .def("pluginSetting", &IOrganizer::pluginSetting, (py::arg("plugin_name"), "key")) + // .def("setPluginSetting", &IOrganizer::setPluginSetting, (py::arg("plugin_name"), "key", "value")) + // .def("persistent", &IOrganizer::persistent, (py::arg("plugin_name"), "key", py::arg("default") = QVariant())) + // .def("setPersistent", &IOrganizer::setPersistent, (py::arg("plugin_name"), "key", "value", py::arg("sync") = true)) // .def("pluginDataPath", &IOrganizer::pluginDataPath) - // .def("installMod", &IOrganizer::installMod, bpy::return_value_policy(), (bpy::arg("filename"), bpy::arg("name_suggestion") = "")) - // .def("resolvePath", &IOrganizer::resolvePath, bpy::arg("filename")) - // .def("listDirectories", &IOrganizer::listDirectories, bpy::arg("directory")) + // .def("installMod", &IOrganizer::installMod, py::return_value_policy(), (py::arg("filename"), py::arg("name_suggestion") = "")) + // .def("resolvePath", &IOrganizer::resolvePath, py::arg("filename")) + // .def("listDirectories", &IOrganizer::listDirectories, py::arg("directory")) // // Provide multiple overloads of findFiles: // .def("findFiles", +[](const IOrganizer* o, QString const& p, std::function f) { return o->findFiles(p, f); }, - // (bpy::arg("path"), "filter")) + // (py::arg("path"), "filter")) // // In C++, it is possible to create a QStringList implicitly from a single QString. This is not possible with the current // // converters in python (and I do not think it is a good idea to have it everywhere), but here it is nice to be able to @@ -408,19 +409,19 @@ PYBIND11_MODULE(mobase, m) // // Important: the order matters, because a Python string can be converted to a QStringList since it is a sequence of // // single-character strings: // .def("findFiles", +[](const IOrganizer* o, QString const& p, const QStringList& gf) { return o->findFiles(p, gf); }, - // (bpy::arg("path"), "patterns")) + // (py::arg("path"), "patterns")) // .def("findFiles", +[](const IOrganizer* o, QString const& p, const QString& f) { return o->findFiles(p, QStringList{ f }); }, - // (bpy::arg("path"), "pattern")) + // (py::arg("path"), "pattern")) - // .def("getFileOrigins", &IOrganizer::getFileOrigins, bpy::arg("filename")) - // .def("findFileInfos", &IOrganizer::findFileInfos, (bpy::arg("path"), "filter")) + // .def("getFileOrigins", &IOrganizer::getFileOrigins, py::arg("filename")) + // .def("findFileInfos", &IOrganizer::findFileInfos, (py::arg("path"), "filter")) // .def("virtualFileTree", &IOrganizer::virtualFileTree) - // .def("downloadManager", &IOrganizer::downloadManager, bpy::return_value_policy()) - // .def("pluginList", &IOrganizer::pluginList, bpy::return_value_policy()) - // .def("modList", &IOrganizer::modList, bpy::return_value_policy()) - // .def("profile", &IOrganizer::profile, bpy::return_value_policy()) + // .def("downloadManager", &IOrganizer::downloadManager, py::return_value_policy()) + // .def("pluginList", &IOrganizer::pluginList, py::return_value_policy()) + // .def("modList", &IOrganizer::modList, py::return_value_policy()) + // .def("profile", &IOrganizer::profile, py::return_value_policy()) // // Custom implementation for startApplication and waitForApplication because 1) HANDLE (= void*) is not properly // // converted from/to python, and 2) we need to convert the by-ptr argument to a return-tuple for waitForApplication: @@ -428,49 +429,49 @@ PYBIND11_MODULE(mobase, m) // +[](IOrganizer* o, const QString& executable, const QStringList& args, const QString& cwd, const QString& profile, // const QString& forcedCustomOverwrite, bool ignoreCustomOverwrite) { // return (std::uintptr_t) o->startApplication(executable, args, cwd, profile, forcedCustomOverwrite, ignoreCustomOverwrite); - // }, (bpy::arg("executable"), (bpy::arg("args") = QStringList()), (bpy::arg("cwd") = ""), (bpy::arg("profile") = ""), - // (bpy::arg("forcedCustomOverwrite") = ""), (bpy::arg("ignoreCustomOverwrite") = false)), bpy::return_value_policy()) + // }, (py::arg("executable"), (py::arg("args") = QStringList()), (py::arg("cwd") = ""), (py::arg("profile") = ""), + // (py::arg("forcedCustomOverwrite") = ""), (py::arg("ignoreCustomOverwrite") = false)), py::return_value_policy()) // .def("waitForApplication", +[](IOrganizer *o, std::uintptr_t handle, bool refresh) { // DWORD returnCode; // bool result = o->waitForApplication((HANDLE)handle, refresh, &returnCode); // return std::make_tuple(result, returnCode); - // }, (bpy::arg("handle"), bpy::arg("refresh") = true)) - // .def("refresh", &IOrganizer::refresh, (bpy::arg("save_changes") = true)) - // .def("managedGame", &IOrganizer::managedGame, bpy::return_value_policy()) + // }, (py::arg("handle"), py::arg("refresh") = true)) + // .def("refresh", &IOrganizer::refresh, (py::arg("save_changes") = true)) + // .def("managedGame", &IOrganizer::managedGame, py::return_value_policy()) - // .def("onAboutToRun", &IOrganizer::onAboutToRun, bpy::arg("callback")) - // .def("onFinishedRun", &IOrganizer::onFinishedRun, bpy::arg("callback")) - // .def("onUserInterfaceInitialized", &IOrganizer::onUserInterfaceInitialized, bpy::arg("callback")) - // .def("onProfileCreated", &IOrganizer::onProfileCreated, bpy::arg("callback")) - // .def("onProfileRenamed", &IOrganizer::onProfileRenamed, bpy::arg("callback")) - // .def("onProfileRemoved", &IOrganizer::onProfileRemoved, bpy::arg("callback")) - // .def("onProfileChanged", &IOrganizer::onProfileChanged, bpy::arg("callback")) + // .def("onAboutToRun", &IOrganizer::onAboutToRun, py::arg("callback")) + // .def("onFinishedRun", &IOrganizer::onFinishedRun, py::arg("callback")) + // .def("onUserInterfaceInitialized", &IOrganizer::onUserInterfaceInitialized, py::arg("callback")) + // .def("onProfileCreated", &IOrganizer::onProfileCreated, py::arg("callback")) + // .def("onProfileRenamed", &IOrganizer::onProfileRenamed, py::arg("callback")) + // .def("onProfileRemoved", &IOrganizer::onProfileRemoved, py::arg("callback")) + // .def("onProfileChanged", &IOrganizer::onProfileChanged, py::arg("callback")) - // .def("onPluginSettingChanged", &IOrganizer::onPluginSettingChanged, bpy::arg("callback")) + // .def("onPluginSettingChanged", &IOrganizer::onPluginSettingChanged, py::arg("callback")) // .def("onPluginEnabled", +[](IOrganizer* o, std::function const& func) { // o->onPluginEnabled(func); - // }, bpy::arg("callback")) + // }, py::arg("callback")) // .def("onPluginEnabled", +[](IOrganizer* o, QString const& name, std::function const& func) { // o->onPluginEnabled(name, func); - // }, (bpy::arg("name"), bpy::arg("callback"))) + // }, (py::arg("name"), py::arg("callback"))) // .def("onPluginDisabled", +[](IOrganizer* o, std::function const& func) { // o->onPluginDisabled(func); - // }, bpy::arg("callback")) + // }, py::arg("callback")) // .def("onPluginDisabled", +[](IOrganizer* o, QString const& name, std::function const& func) { // o->onPluginDisabled(name, func); - // }, (bpy::arg("name"), bpy::arg("callback"))) + // }, (py::arg("name"), py::arg("callback"))) // // DEPRECATED: // .def("getMod", +[](IOrganizer* o, QString const& name) { // utils::show_deprecation_warning("getMod", // "IOrganizer::getMod(str) is deprecated, use IModList::getMod(str) instead."); // return o->modList()->getMod(name); - // }, bpy::return_value_policy(), bpy::arg("name")) + // }, py::return_value_policy(), py::arg("name")) // .def("removeMod", +[](IOrganizer* o, IModInterface *mod) { // utils::show_deprecation_warning("removeMod", // "IOrganizer::removeMod(IModInterface) is deprecated, use IModList::removeMod(IModInterface) instead."); // return o->modList()->removeMod(mod); - // }, bpy::arg("mod")) + // }, py::arg("mod")) // .def("modsSortedByProfilePriority", +[](IOrganizer* o) { // utils::show_deprecation_warning("modsSortedByProfilePriority", // "IOrganizer::modsSortedByProfilePriority() is deprecated, use IModList::allModsByProfilePriority() instead."); @@ -480,167 +481,22 @@ PYBIND11_MODULE(mobase, m) // utils::show_deprecation_warning("refreshModList", // "IOrganizer::refreshModList(bool) is deprecated, use IOrganizer::refresh(bool) instead."); // o->refresh(s); - // }, (bpy::arg("save_changes") = true)) + // }, (py::arg("save_changes") = true)) // .def("onModInstalled", +[](IOrganizer* organizer, const std::function& func) { // utils::show_deprecation_warning("onModInstalled", // "IOrganizer::onModInstalled(Callable[[str], None]) is deprecated, " // "use IModList::onModInstalled(Callable[[IModInterface], None]) instead."); // return organizer->modList()->onModInstalled([func](MOBase::IModInterface* m) { func(m->name()); });; - // }, bpy::arg("callback")) + // }, py::arg("callback")) // .def("getPluginDataPath", &IOrganizer::getPluginDataPath) // .staticmethod("getPluginDataPath") // ; - // // FileTreeEntry Scope: - // auto fileTreeEntryClass = bpy::class_("FileTreeEntry", bpy::no_init); - // { + mo2::python::add_ifiletree_bindings(m); - // bpy::scope scope = fileTreeEntryClass; - - // bpy::enum_("FileTypes") - // .value("FILE_OR_DIRECTORY", FileTreeEntry::FILE_OR_DIRECTORY) - // .value("FILE", FileTreeEntry::FILE) - // .value("DIRECTORY", FileTreeEntry::DIRECTORY) - // .export_values() - // ; - - // fileTreeEntryClass - - // .def("isFile", &FileTreeEntry::isFile) - // .def("isDir", &FileTreeEntry::isDir) - // // Forcing the conversion to FileTypeS to avoid having to expose FileType in python: - // .def("fileType", +[](FileTreeEntry* p) { return FileTreeEntry::FileTypes{ p->fileType() }; }) - // // This should probably not be exposed in python since we provide automatic downcast: - // // .def("getTree", static_cast(FileTreeEntry::*)()>(&FileTreeEntry::astree)) - // .def("name", &FileTreeEntry::name) - // .def("suffix", &FileTreeEntry::suffix) - // .def("hasSuffix", +[](FileTreeEntry* entry, QStringList suffixes) { return entry->hasSuffix(suffixes); }, bpy::arg("suffixes")) - // .def("hasSuffix", +[](FileTreeEntry* entry, QString suffix) { return entry->hasSuffix(suffix); }, bpy::arg("suffix")) - // .def("parent", static_cast(FileTreeEntry::*)()>(&FileTreeEntry::parent), "[optional]") - // .def("path", &FileTreeEntry::path, bpy::arg("sep") = "\\") - // .def("pathFrom", &FileTreeEntry::pathFrom, (bpy::arg("tree"), bpy::arg("sep") = "\\")) - - // // Mutable operation: - // .def("detach", &FileTreeEntry::detach) - // .def("moveTo", &FileTreeEntry::moveTo, bpy::arg("tree")) - - // // Special methods: - // .def("__eq__", +[](const FileTreeEntry* entry, QString other) { - // return entry->compare(other) == 0; - // }) - // .def("__eq__", +[](const FileTreeEntry* entry, std::shared_ptr other) { - // return entry == other.get(); - // }) - - // // Special methods for debug: - // .def("__repr__", +[](const FileTreeEntry* entry) { return "FileTreeEntry(\"" + entry->name() + "\")"; }) - // ; - // } - - // // IFileTree scope: - // auto iFileTreeClass = bpy::class_, boost::noncopyable>("IFileTree", bpy::no_init); - // { - - // bpy::scope scope = iFileTreeClass; - - // bpy::enum_("InsertPolicy") - // .value("FAIL_IF_EXISTS", IFileTree::InsertPolicy::FAIL_IF_EXISTS) - // .value("REPLACE", IFileTree::InsertPolicy::REPLACE) - // .value("MERGE", IFileTree::InsertPolicy::MERGE) - // .export_values() - // ; - - // bpy::enum_("WalkReturn") - // .value("CONTINUE", IFileTree::WalkReturn::CONTINUE) - // .value("STOP", IFileTree::WalkReturn::STOP) - // .value("SKIP", IFileTree::WalkReturn::SKIP) - // .export_values() - // ; - - // iFileTreeClass - - // // Non-mutable operations: - // .def("exists", static_cast(&IFileTree::exists), - // (bpy::arg("path"), bpy::arg("type") = IFileTree::FILE_OR_DIRECTORY)) - // .def("find", static_cast(IFileTree::*)(QString, IFileTree::FileTypes)>(&IFileTree::find), - // bpy::return_value_policy>(), (bpy::arg("path"), bpy::arg("type") = IFileTree::FILE_OR_DIRECTORY), "[optional]") - // .def("pathTo", &IFileTree::pathTo, (bpy::arg("entry"), bpy::arg("sep") = "\\")) - - // // Note: walk() would probably be better as a generator in python, but it is likely impossible to construct - // // from the C++ walk() method. - // .def("walk", &IFileTree::walk, (bpy::arg("callback"), bpy::arg("sep") = "\\")) - - // // Kind-of-static operations: - // .def("createOrphanTree", &IFileTree::createOrphanTree, bpy::arg("name") = "") - - // // addFile() and addDirectory throws exception instead of returning null pointer in order - // // to have better traces. - // .def("addFile", +[](IFileTree* w, QString path, bool replaceIfExists) { - // auto result = w->addFile(path, replaceIfExists); - // if (result == nullptr) { - // throw std::logic_error("addFile failed"); - // } - // return result; - // }, (bpy::arg("path"), bpy::arg("replace_if_exists") = false)) - // .def("addDirectory", +[](IFileTree* w, QString path) { - // auto result = w->addDirectory(path); - // if (result == nullptr) { - // throw std::logic_error("addDirectory failed"); - // } - // return result; - // }, bpy::arg("path")) - - // // Merge needs custom return types depending if the user wants overrides or not. A failure is translated - // // into an exception for easier tracing and handling. - // .def("merge", +[](IFileTree* p, std::shared_ptr other, bool returnOverwrites) -> std::variant { - // IFileTree::OverwritesType overwrites; - // auto result = p->merge(other, returnOverwrites ? &overwrites : nullptr); - // if (result == IFileTree::MERGE_FAILED) { - // throw std::logic_error("merge failed"); - // } - // if (returnOverwrites) { - // return { overwrites }; - // } - // return { result }; - // }, (bpy::arg("other"), bpy::arg("overwrites") = false)) - - // // Insert and erase returns an iterator, which makes no sense in python, so we convert it to bool. Erase is also - // // renamed "remove" since "erase" is very C++. - // .def("insert", +[](IFileTree* p, std::shared_ptr entry, IFileTree::InsertPolicy insertPolicy) { - // return p->insert(entry, insertPolicy) == p->end(); - // }, (bpy::arg("entry"), bpy::arg("policy") = IFileTree::InsertPolicy::FAIL_IF_EXISTS)) - - // .def("remove", +[](IFileTree* p, QString name) { return p->erase(name).first != p->end(); }, bpy::arg("name")) - // .def("remove", +[](IFileTree* p, std::shared_ptr entry) { return p->erase(entry) != p->end(); }, bpy::arg("entry")) - - // .def("move", &IFileTree::move, (bpy::arg("entry"), "path", bpy::arg("policy") = IFileTree::InsertPolicy::FAIL_IF_EXISTS)) - // .def("copy", +[](IFileTree* w, std::shared_ptr entry, QString path, IFileTree::InsertPolicy insertPolicy) { - // auto result = w->copy(entry, path, insertPolicy); - // if (result == nullptr) { - // throw std::logic_error("copy failed"); - // } - // return result; - // }, (bpy::arg("entry"), bpy::arg("path") = "", bpy::arg("insert_policy") = IFileTree::InsertPolicy::FAIL_IF_EXISTS)) - - // .def("clear", &IFileTree::clear) - // .def("removeAll", &IFileTree::removeAll, bpy::arg("names")) - // .def("removeIf", &IFileTree::removeIf, bpy::arg("filter")) - - // // Special methods: - // .def("__getitem__", static_cast(IFileTree::*)(std::size_t)>(&IFileTree::at), - // bpy::return_value_policy>()) - // .def("__iter__", bpy::range>>( - // static_cast(&IFileTree::begin), - // static_cast(&IFileTree::end))) - // .def("__len__", &IFileTree::size) - // .def("__bool__", +[](const IFileTree* tree) { return !tree->empty(); }) - // .def("__repr__", +[](const IFileTree* entry) { return "IFileTree(\"" + entry->name() + "\")"; }) - // ; - // } - - py::class_("IProfile") + py::class_(m, "IProfile") .def("name", &IProfile::name) .def("absolutePath", &IProfile::absolutePath) .def("localSavesEnabled", &IProfile::localSavesEnabled) @@ -653,21 +509,21 @@ PYBIND11_MODULE(mobase, m) .def("absoluteIniFilePath", &IProfile::absoluteIniFilePath, py::arg("inifile")) ; - // bpy::class_("IModRepositoryBridge", bpy::no_init) - // .def("requestDescription", &IModRepositoryBridge::requestDescription, (bpy::arg("game_name"), "mod_id", "user_data")) - // .def("requestFiles", &IModRepositoryBridge::requestFiles, (bpy::arg("game_name"), "mod_id", "user_data")) - // .def("requestFileInfo", &IModRepositoryBridge::requestFileInfo, (bpy::arg("game_name"), "mod_id", "file_id", "user_data")) - // .def("requestDownloadURL", &IModRepositoryBridge::requestDownloadURL, (bpy::arg("game_name"), "mod_id", "file_id", "user_data")) - // .def("requestToggleEndorsement", &IModRepositoryBridge::requestToggleEndorsement, (bpy::arg("game_name"), "mod_id", "mod_version", "endorse", "user_data")) + // py::class_("IModRepositoryBridge", py::no_init) + // .def("requestDescription", &IModRepositoryBridge::requestDescription, (py::arg("game_name"), "mod_id", "user_data")) + // .def("requestFiles", &IModRepositoryBridge::requestFiles, (py::arg("game_name"), "mod_id", "user_data")) + // .def("requestFileInfo", &IModRepositoryBridge::requestFileInfo, (py::arg("game_name"), "mod_id", "file_id", "user_data")) + // .def("requestDownloadURL", &IModRepositoryBridge::requestDownloadURL, (py::arg("game_name"), "mod_id", "file_id", "user_data")) + // .def("requestToggleEndorsement", &IModRepositoryBridge::requestToggleEndorsement, (py::arg("game_name"), "mod_id", "mod_version", "endorse", "user_data")) // Q_DELEGATE(IModRepositoryBridge, QObject, "_object") // ; - // bpy::class_("ModRepositoryFileInfo", bpy::no_init) - // .def(bpy::init(bpy::arg("other"))) - // .def(bpy::init>((bpy::arg("game_name"), "mod_id", "file_id"))) + // py::class_("ModRepositoryFileInfo", py::no_init) + // .def(py::init(py::arg("other"))) + // .def(py::init>((py::arg("game_name"), "mod_id", "file_id"))) // .def("__str__", &ModRepositoryFileInfo::toString) - // .def("createFromJson", &ModRepositoryFileInfo::createFromJson, bpy::arg("data")).staticmethod("createFromJson") + // .def("createFromJson", &ModRepositoryFileInfo::createFromJson, py::arg("data")).staticmethod("createFromJson") // .def_readwrite("name", &ModRepositoryFileInfo::name) // .def_readwrite("uri", &ModRepositoryFileInfo::uri) // .def_readwrite("description", &ModRepositoryFileInfo::description) @@ -686,23 +542,23 @@ PYBIND11_MODULE(mobase, m) // .def_readwrite("userData", &ModRepositoryFileInfo::userData) // ; - // bpy::class_("IDownloadManager", bpy::no_init) - // .def("startDownloadURLs", &IDownloadManager::startDownloadURLs, bpy::arg("urls")) - // .def("startDownloadNexusFile", &IDownloadManager::startDownloadNexusFile, (bpy::arg("mod_id"), "file_id")) - // .def("downloadPath", &IDownloadManager::downloadPath, bpy::arg("id")) - // .def("onDownloadComplete", &IDownloadManager::onDownloadComplete, bpy::arg("callback")) - // .def("onDownloadPaused", &IDownloadManager::onDownloadPaused, bpy::arg("callback")) - // .def("onDownloadFailed", &IDownloadManager::onDownloadFailed, bpy::arg("callback")) - // .def("onDownloadRemoved", &IDownloadManager::onDownloadRemoved, bpy::arg("callback")) + // py::class_("IDownloadManager", py::no_init) + // .def("startDownloadURLs", &IDownloadManager::startDownloadURLs, py::arg("urls")) + // .def("startDownloadNexusFile", &IDownloadManager::startDownloadNexusFile, (py::arg("mod_id"), "file_id")) + // .def("downloadPath", &IDownloadManager::downloadPath, py::arg("id")) + // .def("onDownloadComplete", &IDownloadManager::onDownloadComplete, py::arg("callback")) + // .def("onDownloadPaused", &IDownloadManager::onDownloadPaused, py::arg("callback")) + // .def("onDownloadFailed", &IDownloadManager::onDownloadFailed, py::arg("callback")) + // .def("onDownloadRemoved", &IDownloadManager::onDownloadRemoved, py::arg("callback")) // ; - // bpy::class_("IInstallationManager", bpy::no_init) + // py::class_("IInstallationManager", py::no_init) // .def("getSupportedExtensions", &IInstallationManager::getSupportedExtensions) - // .def("extractFile", &IInstallationManager::extractFile, (bpy::arg("entry"), bpy::arg("silent") = false)) - // .def("extractFiles", &IInstallationManager::extractFiles, (bpy::arg("entries"), bpy::arg("silent") = false)) + // .def("extractFile", &IInstallationManager::extractFile, (py::arg("entry"), py::arg("silent") = false)) + // .def("extractFiles", &IInstallationManager::extractFiles, (py::arg("entries"), py::arg("silent") = false)) // .def("createFile", +[](IInstallationManager* m, std::shared_ptr entry) { // return m->createFile(utils::clean_shared_ptr(entry)); - // }, bpy::arg("entry")) + // }, py::arg("entry")) // // accept both QString and GuessedValue since the conversion is not automatic in Python, and // // return a tuple to get back the mod name and the mod ID @@ -716,23 +572,23 @@ PYBIND11_MODULE(mobase, m) // } // auto result = m->installArchive(tmp, archive, modId); // return std::make_tuple(result, static_cast(tmp), modId); - // }, (bpy::arg("mod_name"), "archive", bpy::arg("mod_id") = 0)) + // }, (py::arg("mod_name"), "archive", py::arg("mod_id") = 0)) // ; - py::enum_("EndorsedState") + py::enum_(m, "EndorsedState") .value("ENDORSED_FALSE", EndorsedState::ENDORSED_FALSE) .value("ENDORSED_TRUE", EndorsedState::ENDORSED_TRUE) .value("ENDORSED_UNKNOWN", EndorsedState::ENDORSED_UNKNOWN) .value("ENDORSED_NEVER", EndorsedState::ENDORSED_NEVER) ; - py::enum_("TrackedState") + py::enum_(m, "TrackedState") .value("TRACKED_FALSE", TrackedState::TRACKED_FALSE) .value("TRACKED_TRUE", TrackedState::TRACKED_TRUE) .value("TRACKED_UNKNOWN", TrackedState::TRACKED_UNKNOWN) ; - // bpy::class_("IModInterface", bpy::no_init) + // py::class_("IModInterface", py::no_init) // .def("name", &IModInterface::name) // .def("absolutePath", &IModInterface::absolutePath) @@ -759,19 +615,19 @@ PYBIND11_MODULE(mobase, m) // .def("isSeparator", &IModInterface::isSeparator) // .def("isForeign", &IModInterface::isForeign) - // .def("setVersion", &IModInterface::setVersion, bpy::arg("version")) - // .def("setNewestVersion", &IModInterface::setNewestVersion, bpy::arg("version")) - // .def("setIsEndorsed", &IModInterface::setIsEndorsed, bpy::arg("endorsed")) - // .def("setNexusID", &IModInterface::setNexusID, bpy::arg("nexus_id")) - // .def("addNexusCategory", &IModInterface::addNexusCategory, bpy::arg("category_id")) - // .def("addCategory", &IModInterface::addCategory, bpy::arg("name")) - // .def("removeCategory", &IModInterface::removeCategory, bpy::arg("name")) - // .def("setGameName", &IModInterface::setGameName, bpy::arg("name")) - // .def("setUrl", &IModInterface::setUrl, bpy::arg("url")) - // .def("pluginSetting", &IModInterface::pluginSetting, (bpy::arg("plugin_name"), "key", bpy::arg("default") = QVariant())) - // .def("pluginSettings", &IModInterface::pluginSettings, bpy::arg("plugin_name")) - // .def("setPluginSetting", &IModInterface::setPluginSetting, (bpy::arg("plugin_name"), "key", bpy::arg("value"))) - // .def("clearPluginSettings", &IModInterface::clearPluginSettings, bpy::arg("plugin_name")) + // .def("setVersion", &IModInterface::setVersion, py::arg("version")) + // .def("setNewestVersion", &IModInterface::setNewestVersion, py::arg("version")) + // .def("setIsEndorsed", &IModInterface::setIsEndorsed, py::arg("endorsed")) + // .def("setNexusID", &IModInterface::setNexusID, py::arg("nexus_id")) + // .def("addNexusCategory", &IModInterface::addNexusCategory, py::arg("category_id")) + // .def("addCategory", &IModInterface::addCategory, py::arg("name")) + // .def("removeCategory", &IModInterface::removeCategory, py::arg("name")) + // .def("setGameName", &IModInterface::setGameName, py::arg("name")) + // .def("setUrl", &IModInterface::setUrl, py::arg("url")) + // .def("pluginSetting", &IModInterface::pluginSetting, (py::arg("plugin_name"), "key", py::arg("default") = QVariant())) + // .def("pluginSettings", &IModInterface::pluginSettings, py::arg("plugin_name")) + // .def("setPluginSetting", &IModInterface::setPluginSetting, (py::arg("plugin_name"), "key", py::arg("value"))) + // .def("clearPluginSettings", &IModInterface::clearPluginSettings, py::arg("plugin_name")) // ; @@ -784,23 +640,23 @@ PYBIND11_MODULE(mobase, m) .value("USER", MOBase::GUESS_USER) ; - // bpy::class_, boost::noncopyable>("GuessedString") - // .def(bpy::init<>()) - // .def(bpy::init((bpy::arg("value"), bpy::arg("quality") = EGuessQuality::GUESS_USER))) + // py::class_, boost::noncopyable>("GuessedString") + // .def(py::init<>()) + // .def(py::init((py::arg("value"), py::arg("quality") = EGuessQuality::GUESS_USER))) // .def("update", // static_cast& (GuessedValue::*)(const QString&)>(&GuessedValue::update), - // bpy::return_self<>(), bpy::arg("value")) + // py::return_self<>(), py::arg("value")) // .def("update", // static_cast& (GuessedValue::*)(const QString&, EGuessQuality)>(&GuessedValue::update), - // bpy::return_self<>(), (bpy::arg("value"), "quality")) + // py::return_self<>(), (py::arg("value"), "quality")) // // Methods to simulate the assignment operator: // .def("reset", +[](GuessedValue* gv) { - // *gv = GuessedValue(); }, bpy::return_self<>()) + // *gv = GuessedValue(); }, py::return_self<>()) // .def("reset", +[](GuessedValue* gv, const QString& value, EGuessQuality eq) { - // *gv = GuessedValue(value, eq); }, bpy::return_self<>(), (bpy::arg("value"), "quality")) + // *gv = GuessedValue(value, eq); }, py::return_self<>(), (py::arg("value"), "quality")) // .def("reset", +[](GuessedValue* gv, const GuessedValue& other) { - // *gv = other; }, bpy::return_self<>(), bpy::arg("other")) + // *gv = other; }, py::return_self<>(), py::arg("other")) // // Use an intermediate lambda to avoid having to register the std::function conversion: // .def("setFilter", +[](GuessedValue* gv, std::function(QString const&)> fn) { @@ -816,11 +672,11 @@ PYBIND11_MODULE(mobase, m) // } // }, ret); // }); - // }, bpy::arg("filter")) + // }, py::arg("filter")) // // This makes a copy in python but it more practical than exposing an iterator: - // .def("variants", &GuessedValue::variants, bpy::return_value_policy()) - // .def("__str__", &MOBase::GuessedValue::operator const QString&, bpy::return_value_policy()) + // .def("variants", &GuessedValue::variants, py::return_value_policy()) + // .def("__str__", &MOBase::GuessedValue::operator const QString&, py::return_value_policy()) // ; py::enum_(m, "PluginState") @@ -861,16 +717,16 @@ PYBIND11_MODULE(mobase, m) return res; }); - // bpy::class_("IPluginList", bpy::no_init) - // .def("state", &MOBase::IPluginList::state, bpy::arg("name")) - // .def("priority", &MOBase::IPluginList::priority, bpy::arg("name")) - // .def("setPriority", &MOBase::IPluginList::setPriority, (bpy::arg("name"), "priority")) - // .def("loadOrder", &MOBase::IPluginList::loadOrder, bpy::arg("name")) - // .def("isMaster", &MOBase::IPluginList::isMaster, bpy::arg("name")) - // .def("masters", &MOBase::IPluginList::masters, bpy::arg("name")) - // .def("origin", &MOBase::IPluginList::origin, bpy::arg("name")) - // .def("onRefreshed", &MOBase::IPluginList::onRefreshed, bpy::arg("callback")) - // .def("onPluginMoved", &MOBase::IPluginList::onPluginMoved, bpy::arg("callback")) + // py::class_("IPluginList", py::no_init) + // .def("state", &MOBase::IPluginList::state, py::arg("name")) + // .def("priority", &MOBase::IPluginList::priority, py::arg("name")) + // .def("setPriority", &MOBase::IPluginList::setPriority, (py::arg("name"), "priority")) + // .def("loadOrder", &MOBase::IPluginList::loadOrder, py::arg("name")) + // .def("isMaster", &MOBase::IPluginList::isMaster, py::arg("name")) + // .def("masters", &MOBase::IPluginList::masters, py::arg("name")) + // .def("origin", &MOBase::IPluginList::origin, py::arg("name")) + // .def("onRefreshed", &MOBase::IPluginList::onRefreshed, py::arg("callback")) + // .def("onPluginMoved", &MOBase::IPluginList::onPluginMoved, py::arg("callback")) // // Kept but deprecated for backward compatibility: // .def("onPluginStateChanged", +[](IPluginList* modList, const std::function& fn) { @@ -882,14 +738,14 @@ PYBIND11_MODULE(mobase, m) // fn(entry.first, entry.second); // } // }); - // }, bpy::arg("callback")) - // .def("onPluginStateChanged", &MOBase::IPluginList::onPluginStateChanged, bpy::arg("callback")) + // }, py::arg("callback")) + // .def("onPluginStateChanged", &MOBase::IPluginList::onPluginStateChanged, py::arg("callback")) // .def("pluginNames", &MOBase::IPluginList::pluginNames) - // .def("setState", &MOBase::IPluginList::setState, (bpy::arg("name"), "state")) - // .def("setLoadOrder", &MOBase::IPluginList::setLoadOrder, bpy::arg("loadorder")) + // .def("setState", &MOBase::IPluginList::setState, (py::arg("name"), "state")) + // .def("setLoadOrder", &MOBase::IPluginList::setLoadOrder, py::arg("loadorder")) // ; - // bpy::enum_("ModState") + // py::enum_("ModState") // .value("exists", IModList::STATE_EXISTS) // .value("active", IModList::STATE_ACTIVE) // .value("essential", IModList::STATE_ESSENTIAL) @@ -907,22 +763,22 @@ PYBIND11_MODULE(mobase, m) // .value("ALTERNATE", IModList::STATE_ALTERNATE) // ; - // bpy::class_("IModList", bpy::no_init) - // .def("displayName", &MOBase::IModList::displayName, bpy::arg("name")) + // py::class_("IModList", py::no_init) + // .def("displayName", &MOBase::IModList::displayName, py::arg("name")) // .def("allMods", &MOBase::IModList::allMods) - // .def("allModsByProfilePriority", &MOBase::IModList::allModsByProfilePriority, bpy::arg("profile") = bpy::ptr((IProfile*)nullptr)) + // .def("allModsByProfilePriority", &MOBase::IModList::allModsByProfilePriority, py::arg("profile") = py::ptr((IProfile*)nullptr)) - // .def("getMod", &MOBase::IModList::getMod, bpy::return_value_policy(), bpy::arg("name")) - // .def("removeMod", &MOBase::IModList::removeMod, bpy::arg("mod")) - // .def("renameMod", &MOBase::IModList::renameMod, bpy::return_value_policy(), (bpy::arg("mod"), bpy::arg("name"))) + // .def("getMod", &MOBase::IModList::getMod, py::return_value_policy(), py::arg("name")) + // .def("removeMod", &MOBase::IModList::removeMod, py::arg("mod")) + // .def("renameMod", &MOBase::IModList::renameMod, py::return_value_policy(), (py::arg("mod"), py::arg("name"))) - // .def("state", &MOBase::IModList::state, bpy::arg("name")) + // .def("state", &MOBase::IModList::state, py::arg("name")) // .def("setActive", - // static_cast(&MOBase::IModList::setActive), (bpy::arg("names"), "active")) + // static_cast(&MOBase::IModList::setActive), (py::arg("names"), "active")) // .def("setActive", - // static_cast(&MOBase::IModList::setActive), (bpy::arg("name"), "active")) - // .def("priority", &MOBase::IModList::priority, bpy::arg("name")) - // .def("setPriority", &MOBase::IModList::setPriority, (bpy::arg("name"), "priority")) + // static_cast(&MOBase::IModList::setActive), (py::arg("name"), "active")) + // .def("priority", &MOBase::IModList::priority, py::arg("name")) + // .def("setPriority", &MOBase::IModList::setPriority, (py::arg("name"), "priority")) // // Kept but deprecated for backward compatibility: // .def("onModStateChanged", +[](IModList* modList, const std::function& fn) { @@ -934,49 +790,49 @@ PYBIND11_MODULE(mobase, m) // fn(entry.first, entry.second); // } // }); - // }, bpy::arg("callback")) + // }, py::arg("callback")) - // .def("onModInstalled", &MOBase::IModList::onModInstalled, bpy::arg("callback")) - // .def("onModRemoved", &MOBase::IModList::onModRemoved, bpy::arg("callback")) - // .def("onModStateChanged", &MOBase::IModList::onModStateChanged, bpy::arg("callback")) - // .def("onModMoved", &MOBase::IModList::onModMoved, bpy::arg("callback")) + // .def("onModInstalled", &MOBase::IModList::onModInstalled, py::arg("callback")) + // .def("onModRemoved", &MOBase::IModList::onModRemoved, py::arg("callback")) + // .def("onModStateChanged", &MOBase::IModList::onModStateChanged, py::arg("callback")) + // .def("onModMoved", &MOBase::IModList::onModMoved, py::arg("callback")) // ; // // Note: localizedName, master, requirements and enabledByDefault have to go in all the plugin wrappers declaration, // // since the default functions are specific to each wrapper, otherwise in turns into an // // infinite recursion mess. - // bpy::class_("IPlugin") - // .def("init", bpy::pure_virtual(&MOBase::IPlugin::init), bpy::arg("organizer")) - // .def("name", bpy::pure_virtual(&MOBase::IPlugin::name)) + // py::class_("IPlugin") + // .def("init", py::pure_virtual(&MOBase::IPlugin::init), py::arg("organizer")) + // .def("name", py::pure_virtual(&MOBase::IPlugin::name)) // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginWrapper::master_Default) - // .def("author", bpy::pure_virtual(&MOBase::IPlugin::author)) - // .def("description", bpy::pure_virtual(&MOBase::IPlugin::description)) - // .def("version", bpy::pure_virtual(&MOBase::IPlugin::version)) + // .def("author", py::pure_virtual(&MOBase::IPlugin::author)) + // .def("description", py::pure_virtual(&MOBase::IPlugin::description)) + // .def("version", py::pure_virtual(&MOBase::IPlugin::version)) // .def("requirements", &MOBase::IPlugin::requirements, &IPluginWrapper::requirements_Default) - // .def("settings", bpy::pure_virtual(&MOBase::IPlugin::settings)) + // .def("settings", py::pure_virtual(&MOBase::IPlugin::settings)) // .def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginWrapper::enabledByDefault_Default) // ; - // bpy::class_, boost::noncopyable>("IPluginDiagnose") + // py::class_, boost::noncopyable>("IPluginDiagnose") // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginDiagnoseWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginDiagnoseWrapper::master_Default) // .def("requirements", &MOBase::IPlugin::requirements, &IPluginDiagnoseWrapper::requirements_Default) // .def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginDiagnoseWrapper::enabledByDefault_Default) - // .def("activeProblems", bpy::pure_virtual(&MOBase::IPluginDiagnose::activeProblems)) - // .def("shortDescription", bpy::pure_virtual(&MOBase::IPluginDiagnose::shortDescription), bpy::arg("key")) - // .def("fullDescription", bpy::pure_virtual(&MOBase::IPluginDiagnose::fullDescription), bpy::arg("key")) - // .def("hasGuidedFix", bpy::pure_virtual(&MOBase::IPluginDiagnose::hasGuidedFix), bpy::arg("key")) - // .def("startGuidedFix", bpy::pure_virtual(&MOBase::IPluginDiagnose::startGuidedFix), bpy::arg("key")) + // .def("activeProblems", py::pure_virtual(&MOBase::IPluginDiagnose::activeProblems)) + // .def("shortDescription", py::pure_virtual(&MOBase::IPluginDiagnose::shortDescription), py::arg("key")) + // .def("fullDescription", py::pure_virtual(&MOBase::IPluginDiagnose::fullDescription), py::arg("key")) + // .def("hasGuidedFix", py::pure_virtual(&MOBase::IPluginDiagnose::hasGuidedFix), py::arg("key")) + // .def("startGuidedFix", py::pure_virtual(&MOBase::IPluginDiagnose::startGuidedFix), py::arg("key")) // .def("_invalidate", &IPluginDiagnoseWrapper::invalidate) // ; - // bpy::class_("Mapping", bpy::init<>()) - // .def("__init__", bpy::make_constructor(+[](QString src, QString dst, bool dir, bool crt) -> Mapping* { + // py::class_("Mapping", py::init<>()) + // .def("__init__", py::make_constructor(+[](QString src, QString dst, bool dir, bool crt) -> Mapping* { // return new Mapping{ src, dst, dir, crt }; - // }, bpy::default_call_policies(), - // (bpy::arg("source"), bpy::arg("destination"), bpy::arg("is_directory"), bpy::arg("create_target") = false))) + // }, py::default_call_policies(), + // (py::arg("source"), py::arg("destination"), py::arg("is_directory"), py::arg("create_target") = false))) // .def_readwrite("source", &Mapping::source) // .def_readwrite("destination", &Mapping::destination) // .def_readwrite("isDirectory", &Mapping::isDirectory) @@ -986,16 +842,16 @@ PYBIND11_MODULE(mobase, m) // }) // ; - // bpy::class_, boost::noncopyable>("IPluginFileMapper") + // py::class_, boost::noncopyable>("IPluginFileMapper") // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginFileMapperWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginFileMapperWrapper::master_Default) // .def("requirements", &MOBase::IPlugin::requirements, &IPluginFileMapperWrapper::requirements_Default) // .def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginFileMapperWrapper::enabledByDefault_Default) - // .def("mappings", bpy::pure_virtual(&MOBase::IPluginFileMapper::mappings)) + // .def("mappings", py::pure_virtual(&MOBase::IPluginFileMapper::mappings)) // ; - // bpy::enum_("LoadOrderMechanism") + // py::enum_("LoadOrderMechanism") // .value("FileTime", MOBase::IPluginGame::LoadOrderMechanism::FileTime) // .value("PluginsTxt", MOBase::IPluginGame::LoadOrderMechanism::PluginsTxt) @@ -1003,7 +859,7 @@ PYBIND11_MODULE(mobase, m) // .value("PLUGINS_TXT", MOBase::IPluginGame::LoadOrderMechanism::PluginsTxt) // ; - // bpy::enum_("SortMechanism") + // py::enum_("SortMechanism") // .value("NONE", MOBase::IPluginGame::SortMechanism::NONE) // .value("MLOX", MOBase::IPluginGame::SortMechanism::MLOX) // .value("BOSS", MOBase::IPluginGame::SortMechanism::BOSS) @@ -1011,7 +867,7 @@ PYBIND11_MODULE(mobase, m) // ; // // This doesn't actually do the conversion, but might be convenient for accessing the names for enum bits - // bpy::enum_("ProfileSetting") + // py::enum_("ProfileSetting") // .value("mods", MOBase::IPluginGame::MODS) // .value("configuration", MOBase::IPluginGame::CONFIGURATION) // .value("savegames", MOBase::IPluginGame::SAVEGAMES) @@ -1023,84 +879,84 @@ PYBIND11_MODULE(mobase, m) // .value("PREFER_DEFAULTS", MOBase::IPluginGame::PREFER_DEFAULTS) // ; - // bpy::class_, boost::noncopyable>("IPluginGame") + // py::class_, boost::noncopyable>("IPluginGame") // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginGameWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginGameWrapper::master_Default) - // .def("detectGame", bpy::pure_virtual(&MOBase::IPluginGame::detectGame)) - // .def("gameName", bpy::pure_virtual(&MOBase::IPluginGame::gameName)) - // .def("initializeProfile", bpy::pure_virtual(&MOBase::IPluginGame::initializeProfile), (bpy::arg("directory"), "settings")) - // .def("listSaves", bpy::pure_virtual(&MOBase::IPluginGame::listSaves), bpy::arg("folder")) - // .def("isInstalled", bpy::pure_virtual(&MOBase::IPluginGame::isInstalled)) - // .def("gameIcon", bpy::pure_virtual(&MOBase::IPluginGame::gameIcon)) - // .def("gameDirectory", bpy::pure_virtual(&MOBase::IPluginGame::gameDirectory)) - // .def("dataDirectory", bpy::pure_virtual(&MOBase::IPluginGame::dataDirectory)) - // .def("setGamePath", bpy::pure_virtual(&MOBase::IPluginGame::setGamePath), bpy::arg("path")) - // .def("documentsDirectory", bpy::pure_virtual(&MOBase::IPluginGame::documentsDirectory)) - // .def("savesDirectory", bpy::pure_virtual(&MOBase::IPluginGame::savesDirectory)) - // .def("executables", bpy::pure_virtual(&MOBase::IPluginGame::executables)) - // .def("executableForcedLoads", bpy::pure_virtual(&MOBase::IPluginGame::executableForcedLoads)) - // .def("steamAPPId", bpy::pure_virtual(&MOBase::IPluginGame::steamAPPId)) - // .def("primaryPlugins", bpy::pure_virtual(&MOBase::IPluginGame::primaryPlugins)) - // .def("gameVariants", bpy::pure_virtual(&MOBase::IPluginGame::gameVariants)) - // .def("setGameVariant", bpy::pure_virtual(&MOBase::IPluginGame::setGameVariant), bpy::arg("variant")) - // .def("binaryName", bpy::pure_virtual(&MOBase::IPluginGame::binaryName)) - // .def("gameShortName", bpy::pure_virtual(&MOBase::IPluginGame::gameShortName)) - // .def("primarySources", bpy::pure_virtual(&MOBase::IPluginGame::primarySources)) - // .def("validShortNames", bpy::pure_virtual(&MOBase::IPluginGame::validShortNames)) - // .def("gameNexusName", bpy::pure_virtual(&MOBase::IPluginGame::gameNexusName)) - // .def("iniFiles", bpy::pure_virtual(&MOBase::IPluginGame::iniFiles)) - // .def("DLCPlugins", bpy::pure_virtual(&MOBase::IPluginGame::DLCPlugins)) - // .def("CCPlugins", bpy::pure_virtual(&MOBase::IPluginGame::CCPlugins)) - // .def("loadOrderMechanism", bpy::pure_virtual(&MOBase::IPluginGame::loadOrderMechanism)) - // .def("sortMechanism", bpy::pure_virtual(&MOBase::IPluginGame::sortMechanism)) - // .def("nexusModOrganizerID", bpy::pure_virtual(&MOBase::IPluginGame::nexusModOrganizerID)) - // .def("nexusGameID", bpy::pure_virtual(&MOBase::IPluginGame::nexusGameID)) - // .def("looksValid", bpy::pure_virtual(&MOBase::IPluginGame::looksValid), bpy::arg("directory")) - // .def("gameVersion", bpy::pure_virtual(&MOBase::IPluginGame::gameVersion)) - // .def("getLauncherName", bpy::pure_virtual(&MOBase::IPluginGame::getLauncherName)) + // .def("detectGame", py::pure_virtual(&MOBase::IPluginGame::detectGame)) + // .def("gameName", py::pure_virtual(&MOBase::IPluginGame::gameName)) + // .def("initializeProfile", py::pure_virtual(&MOBase::IPluginGame::initializeProfile), (py::arg("directory"), "settings")) + // .def("listSaves", py::pure_virtual(&MOBase::IPluginGame::listSaves), py::arg("folder")) + // .def("isInstalled", py::pure_virtual(&MOBase::IPluginGame::isInstalled)) + // .def("gameIcon", py::pure_virtual(&MOBase::IPluginGame::gameIcon)) + // .def("gameDirectory", py::pure_virtual(&MOBase::IPluginGame::gameDirectory)) + // .def("dataDirectory", py::pure_virtual(&MOBase::IPluginGame::dataDirectory)) + // .def("setGamePath", py::pure_virtual(&MOBase::IPluginGame::setGamePath), py::arg("path")) + // .def("documentsDirectory", py::pure_virtual(&MOBase::IPluginGame::documentsDirectory)) + // .def("savesDirectory", py::pure_virtual(&MOBase::IPluginGame::savesDirectory)) + // .def("executables", py::pure_virtual(&MOBase::IPluginGame::executables)) + // .def("executableForcedLoads", py::pure_virtual(&MOBase::IPluginGame::executableForcedLoads)) + // .def("steamAPPId", py::pure_virtual(&MOBase::IPluginGame::steamAPPId)) + // .def("primaryPlugins", py::pure_virtual(&MOBase::IPluginGame::primaryPlugins)) + // .def("gameVariants", py::pure_virtual(&MOBase::IPluginGame::gameVariants)) + // .def("setGameVariant", py::pure_virtual(&MOBase::IPluginGame::setGameVariant), py::arg("variant")) + // .def("binaryName", py::pure_virtual(&MOBase::IPluginGame::binaryName)) + // .def("gameShortName", py::pure_virtual(&MOBase::IPluginGame::gameShortName)) + // .def("primarySources", py::pure_virtual(&MOBase::IPluginGame::primarySources)) + // .def("validShortNames", py::pure_virtual(&MOBase::IPluginGame::validShortNames)) + // .def("gameNexusName", py::pure_virtual(&MOBase::IPluginGame::gameNexusName)) + // .def("iniFiles", py::pure_virtual(&MOBase::IPluginGame::iniFiles)) + // .def("DLCPlugins", py::pure_virtual(&MOBase::IPluginGame::DLCPlugins)) + // .def("CCPlugins", py::pure_virtual(&MOBase::IPluginGame::CCPlugins)) + // .def("loadOrderMechanism", py::pure_virtual(&MOBase::IPluginGame::loadOrderMechanism)) + // .def("sortMechanism", py::pure_virtual(&MOBase::IPluginGame::sortMechanism)) + // .def("nexusModOrganizerID", py::pure_virtual(&MOBase::IPluginGame::nexusModOrganizerID)) + // .def("nexusGameID", py::pure_virtual(&MOBase::IPluginGame::nexusGameID)) + // .def("looksValid", py::pure_virtual(&MOBase::IPluginGame::looksValid), py::arg("directory")) + // .def("gameVersion", py::pure_virtual(&MOBase::IPluginGame::gameVersion)) + // .def("getLauncherName", py::pure_virtual(&MOBase::IPluginGame::getLauncherName)) // .def("featureList", +[](MOBase::IPluginGame* p) { // // Constructing a dict from class name to actual object: - // bpy::dict dict; + // py::dict dict; // mp11::mp_for_each< // // Must user pointers because mp_for_each construct object: // mp11::mp_transform // >([&](auto* pt) { // using T = std::remove_pointer_t; - // typename bpy::reference_existing_object::apply::type converter; + // typename py::reference_existing_object::apply::type converter; // // Retrieve the python class object: - // const bpy::converter::registration* registration = bpy::converter::registry::query(bpy::type_id()); - // bpy::object key = bpy::object(bpy::handle<>(bpy::borrowed(registration->get_class_object()))); + // const py::converter::registration* registration = py::converter::registry::query(py::type_id()); + // py::object key = py::object(py::handle<>(py::borrowed(registration->get_class_object()))); // // Set the object: - // dict[key] = bpy::handle<>(converter(p->feature())); + // dict[key] = py::handle<>(converter(p->feature())); // }); // return dict; // }) - // .def("feature", +[](MOBase::IPluginGame* p, bpy::object clsObj) { - // bpy::object feature; + // .def("feature", +[](MOBase::IPluginGame* p, py::object clsObj) { + // py::object feature; // mp11::mp_for_each< // // Must user pointers because mp_for_each construct object: // mp11::mp_transform // >([&](auto* pt) { // using T = std::remove_pointer_t; - // typename bpy::reference_existing_object::apply::type converter; + // typename py::reference_existing_object::apply::type converter; // // Retrieve the python class object: - // const bpy::converter::registration* registration = bpy::converter::registry::query(bpy::type_id()); + // const py::converter::registration* registration = py::converter::registry::query(py::type_id()); // if (clsObj.ptr() == (PyObject*) registration->get_class_object()) { - // feature = bpy::object(bpy::handle<>(converter(p->feature()))); + // feature = py::object(py::handle<>(converter(p->feature()))); // } // }); // return feature; - // }, bpy::arg("feature_type")) + // }, py::arg("feature_type")) // ; - // bpy::enum_("InstallResult") + // py::enum_("InstallResult") // .value("SUCCESS", MOBase::IPluginInstaller::RESULT_SUCCESS) // .value("FAILED", MOBase::IPluginInstaller::RESULT_FAILED) // .value("CANCELED", MOBase::IPluginInstaller::RESULT_CANCELED) @@ -1108,19 +964,19 @@ PYBIND11_MODULE(mobase, m) // .value("NOT_ATTEMPTED", MOBase::IPluginInstaller::RESULT_NOTATTEMPTED) // ; - // bpy::class_, boost::noncopyable>("IPluginInstaller", bpy::no_init) - // .def("isArchiveSupported", &IPluginInstaller::isArchiveSupported, bpy::arg("tree")) + // py::class_, boost::noncopyable>("IPluginInstaller", py::no_init) + // .def("isArchiveSupported", &IPluginInstaller::isArchiveSupported, py::arg("tree")) // .def("priority", &IPluginInstaller::priority) - // .def("onInstallationStart", &IPluginInstaller::onInstallationStart, (bpy::arg("archive"), bpy::arg("reinstallation"), bpy::arg("current_mod"))) - // .def("onInstallationEnd", &IPluginInstaller::onInstallationEnd, (bpy::arg("result"), bpy::arg("new_mod"))) + // .def("onInstallationStart", &IPluginInstaller::onInstallationStart, (py::arg("archive"), py::arg("reinstallation"), py::arg("current_mod"))) + // .def("onInstallationEnd", &IPluginInstaller::onInstallationEnd, (py::arg("result"), py::arg("new_mod"))) // .def("isManualInstaller", &IPluginInstaller::isManualInstaller) - // .def("setParentWidget", &IPluginInstaller::setParentWidget, bpy::arg("parent")) - // .def("setInstallationManager", &IPluginInstaller::setInstallationManager, bpy::arg("manager")) + // .def("setParentWidget", &IPluginInstaller::setParentWidget, py::arg("parent")) + // .def("setInstallationManager", &IPluginInstaller::setInstallationManager, py::arg("manager")) // ; - // bpy::class_, boost::noncopyable>("IPluginInstallerSimple") - // .def("onInstallationStart", &IPluginInstaller::onInstallationStart, (bpy::arg("archive"), bpy::arg("reinstallation"), bpy::arg("current_mod"))) - // .def("onInstallationEnd", &IPluginInstaller::onInstallationEnd, (bpy::arg("result"), bpy::arg("new_mod"))) + // py::class_, boost::noncopyable>("IPluginInstallerSimple") + // .def("onInstallationStart", &IPluginInstaller::onInstallationStart, (py::arg("archive"), py::arg("reinstallation"), py::arg("current_mod"))) + // .def("onInstallationEnd", &IPluginInstaller::onInstallationEnd, (py::arg("result"), py::arg("new_mod"))) // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginInstallerSimpleWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginInstallerSimpleWrapper::master_Default) // .def("requirements", &MOBase::IPlugin::requirements, &IPluginInstallerSimpleWrapper::requirements_Default) @@ -1132,66 +988,66 @@ PYBIND11_MODULE(mobase, m) // -> std::variant, std::tuple, QString, int>> { // auto result = p->install(modName, tree, version, nexusID); // return std::make_tuple(result, tree, version, nexusID); - // }, (bpy::arg("name"), "tree", "version", "nexus_id")) - // .def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy()) - // .def("_manager", &IPluginInstallerSimpleWrapper::manager, bpy::return_value_policy()) + // }, (py::arg("name"), "tree", "version", "nexus_id")) + // .def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, py::return_value_policy()) + // .def("_manager", &IPluginInstallerSimpleWrapper::manager, py::return_value_policy()) // ; - // bpy::class_, boost::noncopyable>("IPluginInstallerCustom") - // .def("onInstallationStart", &IPluginInstaller::onInstallationStart, (bpy::arg("archive"), bpy::arg("reinstallation"), bpy::arg("current_mod"))) - // .def("onInstallationEnd", &IPluginInstaller::onInstallationEnd, (bpy::arg("result"), bpy::arg("new_mod"))) + // py::class_, boost::noncopyable>("IPluginInstallerCustom") + // .def("onInstallationStart", &IPluginInstaller::onInstallationStart, (py::arg("archive"), py::arg("reinstallation"), py::arg("current_mod"))) + // .def("onInstallationEnd", &IPluginInstaller::onInstallationEnd, (py::arg("result"), py::arg("new_mod"))) // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginInstallerCustomWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginInstallerCustomWrapper::master_Default) // .def("requirements", &MOBase::IPlugin::requirements, &IPluginInstallerCustomWrapper::requirements_Default) // .def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginInstallerCustomWrapper::enabledByDefault_Default) // // Needs to add both otherwize boost does not understand: - // .def("isArchiveSupported", &IPluginInstaller::isArchiveSupported, bpy::arg("tree")) - // .def("isArchiveSupported", &IPluginInstallerCustom::isArchiveSupported, bpy::arg("archive_name")) + // .def("isArchiveSupported", &IPluginInstaller::isArchiveSupported, py::arg("tree")) + // .def("isArchiveSupported", &IPluginInstallerCustom::isArchiveSupported, py::arg("archive_name")) // .def("supportedExtensions", &IPluginInstallerCustom::supportedExtensions) - // .def("install", &IPluginInstallerCustom::install, (bpy::arg("mod_name"), "game_name", "archive_name", "version", "nexus_id")) - // .def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy()) - // .def("_manager", &IPluginInstallerCustomWrapper::manager, bpy::return_value_policy()) + // .def("install", &IPluginInstallerCustom::install, (py::arg("mod_name"), "game_name", "archive_name", "version", "nexus_id")) + // .def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, py::return_value_policy()) + // .def("_manager", &IPluginInstallerCustomWrapper::manager, py::return_value_policy()) // ; - // bpy::class_, boost::noncopyable>("IPluginModPage") + // py::class_, boost::noncopyable>("IPluginModPage") // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginModPageWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginModPageWrapper::master_Default) // .def("requirements", &MOBase::IPlugin::requirements, &IPluginModPageWrapper::requirements_Default) // .def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginModPageWrapper::enabledByDefault_Default) - // .def("displayName", bpy::pure_virtual(&IPluginModPage::displayName)) - // .def("icon", bpy::pure_virtual(&IPluginModPage::icon)) - // .def("pageURL", bpy::pure_virtual(&IPluginModPage::pageURL)) - // .def("useIntegratedBrowser", bpy::pure_virtual(&IPluginModPage::useIntegratedBrowser)) - // .def("handlesDownload", bpy::pure_virtual(&IPluginModPage::handlesDownload), (bpy::arg("page_url"), "download_url", "fileinfo")) - // .def("setParentWidget", &IPluginModPage::setParentWidget, &IPluginModPageWrapper::setParentWidget_Default, bpy::arg("parent")) - // .def("_parentWidget", &IPluginModPageWrapper::parentWidget, bpy::return_value_policy()) + // .def("displayName", py::pure_virtual(&IPluginModPage::displayName)) + // .def("icon", py::pure_virtual(&IPluginModPage::icon)) + // .def("pageURL", py::pure_virtual(&IPluginModPage::pageURL)) + // .def("useIntegratedBrowser", py::pure_virtual(&IPluginModPage::useIntegratedBrowser)) + // .def("handlesDownload", py::pure_virtual(&IPluginModPage::handlesDownload), (py::arg("page_url"), "download_url", "fileinfo")) + // .def("setParentWidget", &IPluginModPage::setParentWidget, &IPluginModPageWrapper::setParentWidget_Default, py::arg("parent")) + // .def("_parentWidget", &IPluginModPageWrapper::parentWidget, py::return_value_policy()) // ; - // bpy::class_, boost::noncopyable>("IPluginPreview") + // py::class_, boost::noncopyable>("IPluginPreview") // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginPreviewWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginPreviewWrapper::master_Default) // .def("requirements", &MOBase::IPlugin::requirements, &IPluginPreviewWrapper::requirements_Default) // .def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginPreviewWrapper::enabledByDefault_Default) - // .def("supportedExtensions", bpy::pure_virtual(&IPluginPreview::supportedExtensions)) - // .def("genFilePreview", bpy::pure_virtual(&IPluginPreview::genFilePreview), bpy::return_value_policy(), - // (bpy::arg("filename"), "max_size")) + // .def("supportedExtensions", py::pure_virtual(&IPluginPreview::supportedExtensions)) + // .def("genFilePreview", py::pure_virtual(&IPluginPreview::genFilePreview), py::return_value_policy(), + // (py::arg("filename"), "max_size")) // ; - // bpy::class_, boost::noncopyable>("IPluginTool") + // py::class_, boost::noncopyable>("IPluginTool") // .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginToolWrapper::localizedName_Default) // .def("master", &MOBase::IPlugin::master, &IPluginToolWrapper::master_Default) // .def("requirements", &MOBase::IPlugin::requirements, &IPluginToolWrapper::requirements_Default) // .def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginToolWrapper::enabledByDefault_Default) - // .def("displayName", bpy::pure_virtual(&IPluginTool::displayName)) - // .def("tooltip", bpy::pure_virtual(&IPluginTool::tooltip)) - // .def("icon", bpy::pure_virtual(&IPluginTool::icon)) - // .def("display", bpy::pure_virtual(&IPluginTool::display)) - // .def("setParentWidget", &IPluginTool::setParentWidget, &IPluginToolWrapper::setParentWidget_Default, bpy::arg("parent")) - // .def("_parentWidget", &IPluginToolWrapper::parentWidget, bpy::return_value_policy()) + // .def("displayName", py::pure_virtual(&IPluginTool::displayName)) + // .def("tooltip", py::pure_virtual(&IPluginTool::tooltip)) + // .def("icon", py::pure_virtual(&IPluginTool::icon)) + // .def("display", py::pure_virtual(&IPluginTool::display)) + // .def("setParentWidget", &IPluginTool::setParentWidget, &IPluginToolWrapper::setParentWidget_Default, py::arg("parent")) + // .def("_parentWidget", &IPluginToolWrapper::parentWidget, py::return_value_policy()) // ; // registerGameFeaturesPythonConverters(); @@ -1200,10 +1056,10 @@ PYBIND11_MODULE(mobase, m) m.def("getProductVersion", &MOBase::getProductVersion, py::arg("executable")); m.def("getIconForExecutable", &MOBase::iconForExecutable, py::arg("executable")); - // bpy::object widgets(bpy::borrowed(PyImport_AddModule("mobase.widgets"))); - // bpy::scope().attr("widgets") = widgets; + // py::object widgets(py::borrowed(PyImport_AddModule("mobase.widgets"))); + // py::scope().attr("widgets") = widgets; // { - // bpy::scope w_ = widgets; + // py::scope w_ = widgets; // register_widgets(); // } @@ -1324,45 +1180,10 @@ PYBIND11_MODULE(moprivate, m) .def("stopRecordingExceptionMessage", &ErrWrapper::stopRecordingExceptionMessage) .def("getLastExceptionMessage", &ErrWrapper::getLastExceptionMessage); - // utils::register_functor_converter(); + // expose a function to create a particular tree, only for debugging purpose, not + // in mobase. + mo2::python::add_make_tree_function(m); - // Expose a function to create a particular tree, only for debugging purpose, not in mobase. - // m.def("makeTree", [](std::function callback) -> std::shared_ptr { - // struct FileTree : IFileTree { - - // using callback_t = std::function; - - // FileTree(std::shared_ptr parent, QString name, callback_t callback) : - // FileTreeEntry(parent, name), IFileTree(), m_Callback(callback){ } - - // std::shared_ptr addFile(QString name, bool) override { - // if (m_Callback && !m_Callback(name, false)) { - // throw UnsupportedOperationException("File rejected by callback."); - // } - // return IFileTree::addFile(name); - // } - - // std::shared_ptr addDirectory(QString name) override { - // if (m_Callback && !m_Callback(name, true)) { - // throw UnsupportedOperationException("Directory rejected by callback."); - // } - // return IFileTree::addDirectory(name); - // } - - // protected: - - // std::shared_ptr makeDirectory(std::shared_ptr parent, QString name) const override { - // return std::make_shared(parent, name, m_Callback); - // } - - // bool doPopulate(std::shared_ptr parent, std::vector>& entries) const override { return true; } - // std::shared_ptr doClone() const override { return std::make_shared(nullptr, name(), m_Callback); } - - // private: - // callback_t m_Callback; - // }; - // return std::make_shared(nullptr, "", callback); - // }, py::arg("callback") = py::object{}); } bool PythonRunner::initPython() @@ -1402,7 +1223,7 @@ bool PythonRunner::initPython() mainNamespace); mainNamespace["mobase"] = py::module_::import("mobase"); - configure_python_logging(mainNamespace["mobase"]); + mo2::details::configure_python_logging(mainNamespace["mobase"]); return true; } catch (const py::error_already_set&) { @@ -1450,7 +1271,7 @@ QList PythonRunner::load(const QString& identifier) // `pluginName` can either be a python file (single-file plugin or a folder (whole module). // // For whole module, we simply add the parent folder to path, then we load the module with a simple - // bpy::import, and we retrieve the associated __dict__ from which we extract either createPlugin or + // py::import, and we retrieve the associated __dict__ from which we extract either createPlugin or // createPlugins. // // For single file, we need to use py::eval_file, and we will use the context (global variables) diff --git a/src/runner-pybind11/pythonutils.cpp b/src/runner-pybind11/pythonutils.cpp index 37445c5..142eb7d 100644 --- a/src/runner-pybind11/pythonutils.cpp +++ b/src/runner-pybind11/pythonutils.cpp @@ -3,24 +3,99 @@ #include #include +#include + #include #include "log.h" -namespace utils { +namespace py = pybind11; - void show_deprecation_warning(std::string_view name, std::string_view message, bool show_once) { +namespace mo2::python { + + // Small structure to hold the levels - There are copy paste from + // my Python version and I assume these will not change soon: + struct PyLogLevel { + static constexpr int CRITICAL = 50; + static constexpr int ERROR = 40; + static constexpr int WARNING = 30; + static constexpr int INFO = 20; + static constexpr int DEBUG = 10; + }; + + // This is the function we are going to use as our Handler .emit + // method. + void emit_function(py::object self, py::object record) + { + + // There are other parameters that could be used, but this is minimal for + // now (filename, line number, etc.). + const int level = record.attr("levelno").cast(); + const std::wstring msg = py::str(record.attr("msg")).cast(); + + switch (level) { + case PyLogLevel::CRITICAL: + case PyLogLevel::ERROR: + MOBase::log::error("{}", msg); + break; + case PyLogLevel::WARNING: + MOBase::log::warn("{}", msg); + break; + case PyLogLevel::INFO: + MOBase::log::info("{}", msg); + break; + case PyLogLevel::DEBUG: + default: // There is a "NOTSET" level in theory: + MOBase::log::debug("{}", msg); + break; + } + }; + + void configure_python_logging(py::module_ mobase) + { + // most of this is dealing with actual Python objects since it is not possible + // to derive from logging.Handler in C++ using Boost.Python, and since a lot of + // this would require extra register only for this. + + // see also https://github.com/pybind/pybind11/issues/1193#issuecomment-429451094 + + // retrieve the logging module and the Handler class. + auto logging = py::module_::import("logging"); + auto Handler = logging.attr("Handler"); + + // this is ugly but that's how it's done in C Python + auto type = py::reinterpret_borrow((PyObject*)&PyType_Type); + + // Create the "MO2Handler" python class: + auto methods = py::dict(); + methods["emit"] = py::cpp_function(emit_function); + auto MO2Handler = type("LogHandler", py::make_tuple(Handler), methods); + + // Create the default logger: + auto handler = MO2Handler(); + handler.attr("setLevel")(PyLogLevel::DEBUG); + auto logger = logging.attr("getLogger")(py::object(mobase.attr("__name__"))); + logger.attr("setLevel")(PyLogLevel::DEBUG); + logger.attr("addHandler")(handler); + + // Set mobase attributes: + mobase.attr("LogHandler") = MO2Handler; + mobase.attr("logger") = logger; + } + + void show_deprecation_warning(std::string_view name, std::string_view message, bool show_once) + { // Contains the list of filename / line number for which a deprecation warning has already been shown. static std::set> DeprecatedLines; - + // Find the caller: - auto inspect = bpy::import("inspect"); + auto inspect = py::module_::import("inspect"); auto current_frame = inspect.attr("currentframe")(); - auto callable_frame = inspect.attr("getouterframes")(current_frame, 2); - auto filename = bpy::extract(callable_frame[-1].attr("filename"))(); - auto function = bpy::extract(callable_frame[-1].attr("function"))(); - auto lineno = bpy::extract(callable_frame[-1].attr("lineno")); + py::sequence callable_frame = inspect.attr("getouterframes")(current_frame, 2); + auto filename = callable_frame[-1].attr("filename").cast(); + auto function = callable_frame[-1].attr("function").cast(); + auto lineno = callable_frame[-1].attr("lineno").cast(); // Only show once if requested: if (show_once && DeprecatedLines.contains({ filename, lineno })) { @@ -43,4 +118,4 @@ namespace utils { } } -} \ No newline at end of file +} diff --git a/src/runner-pybind11/pythonutils.h b/src/runner-pybind11/pythonutils.h index 6703557..59f936c 100644 --- a/src/runner-pybind11/pythonutils.h +++ b/src/runner-pybind11/pythonutils.h @@ -1,257 +1,18 @@ #ifndef PYTHONRUNNER_UTILS_H #define PYTHONRUNNER_UTILS_H -#include +#include -#include "error.h" - -namespace utils { - - namespace bpy = boost::python; - - namespace details { - - template - struct is_stdmap_iterator : std::false_type {}; - - template - struct is_stdmap_iterator()->first)>> : std::true_type {}; - - // Note: QMap and standard maps do not have the same type of iterators: - template {}, int> = 0> - inline auto set_dict_entry(bpy::dict& result, It const& it) { - result[bpy::object{ it->first }] = bpy::object{ it->second }; - } - - template {}, int > = 0> - inline auto set_dict_entry(bpy::dict& result, It const& it) { - result[bpy::object{ it.key() }] = bpy::object{ it.value() }; - } - - } - - template - struct map_to_python { - static PyObject* convert(const Map& map) { - bpy::dict result; - for (auto it = map.begin(); it != map.end(); ++it) { - details::set_dict_entry(result, it); - } - return bpy::incref(result.ptr()); - } - }; - - template - struct map_from_python { - - using key_type = typename Map::key_type; - using value_type = typename Map::mapped_type; - - static void* convertible(PyObject* objPtr) { - return PyDict_Check(objPtr) ? objPtr : nullptr; - } - - static void construct(PyObject* objPtr, bpy::converter::rvalue_from_python_stage1_data* data) { - void* storage = ((bpy::converter::rvalue_from_python_storage*)data)->storage.bytes; - Map* result = new (storage) Map(); - bpy::dict source(bpy::handle<>(bpy::borrowed(objPtr))); - bpy::list keys = source.keys(); - int len = bpy::len(keys); - for (int i = 0; i < len; ++i) { - bpy::object pyKey = keys[i]; - (*result)[bpy::extract(pyKey)] = bpy::extract(source[pyKey]); - } - - data->convertible = storage; - } - }; - - template - struct container_to_python_list { - static PyObject* convert(const Container& container) { - bpy::list pyList; - - try { - for (auto& item : container) { - pyList.append(item); - } - } - catch (const bpy::error_already_set&) { - throw pyexcept::PythonError(); - } - - return bpy::incref(pyList.ptr()); - } - }; - - - template - struct container_from_python_list { - - using value_type = typename Container::value_type; - - static void* convertible(PyObject* objPtr) { - // Check that the object can be iterated or is a sequence. There is no "clean" - // way checking that an object is iterable apparently (PyIter_Check checks that - // an object is an iterator, which is very different). - if (objPtr->ob_type->tp_iter != 0 || PySequence_Check(objPtr)) return objPtr; - return nullptr; - } - - static void construct(PyObject* objPtr, bpy::converter::rvalue_from_python_stage1_data* data) { - void* storage = ((bpy::converter::rvalue_from_python_storage*)data)->storage.bytes; - Container* result = new (storage) Container(); - bpy::object source(bpy::handle<>(bpy::borrowed(objPtr))); - bpy::stl_input_iterator begin(source), end; - std::copy(begin, end, std::back_inserter(*result)); - data->convertible = storage; - } - }; - - template - struct set_to_python { - static PyObject* convert(const Container& container) { - bpy::list pyList; - - try { - for (auto& item : container) - pyList.append(item); - } - catch (const bpy::error_already_set&) { - throw pyexcept::PythonError(); - } - - return bpy::incref(pyList.ptr()); - } - }; - - - template - struct set_from_python { - - using value_type = typename Container::value_type; - - static void* convertible(PyObject* objPtr) { - // See container_from_python. - if (objPtr->ob_type->tp_iter != 0 && PySequence_Check(objPtr)) return objPtr; - return nullptr; - } - - static void construct(PyObject* objPtr, bpy::converter::rvalue_from_python_stage1_data* data) { - void* storage = ((bpy::converter::rvalue_from_python_storage*)data)->storage.bytes; - Container* result = new (storage) Container(); - bpy::list source(bpy::handle<>(bpy::borrowed(objPtr))); - bpy::stl_input_iterator begin(source), end; - std::copy(begin, end, std::inserter(*result, result->begin())); - data->convertible = storage; - } - }; - - - template - struct optional_to_python { - static PyObject* convert(const Optional& optional) { - if (optional) { - return bpy::incref(bpy::object(*optional).ptr()); - } - else { - return bpy::incref(Py_None); - } - } - }; - - - template - struct optional_from_python { - - using value_type = typename Optional::value_type; - - static void* convertible(PyObject* objPtr) { - - if (objPtr == Py_None) { - return objPtr; - } - - bpy::object source(bpy::handle<>(bpy::borrowed(objPtr))); - return bpy::extract(source).check() ? objPtr : nullptr; - } - - static void construct(PyObject* objPtr, bpy::converter::rvalue_from_python_stage1_data* data) { - void* storage = ((bpy::converter::rvalue_from_python_storage*)data)->storage.bytes; - Optional* result = new (storage) Optional(); - - bpy::object source(bpy::handle<>(bpy::borrowed(objPtr))); - if (!source.is_none()) { - *result = bpy::extract(source)(); - } - - data->convertible = storage; - } - }; +#include +namespace mo2::python { /** - * @brief Register from and to python converters for (at least) map, unordered_map and QMap. + * @brief Configure logging for MO2 python plugin. * - * Any standard compliant associative container with key/value should work here. - * - * @tparam Map The container type to register. + * @param mobase The mobase module. */ - template - void register_associative_container() { - bpy::to_python_converter>(); - bpy::converter::registry::push_back( - &map_from_python::convertible - , &map_from_python::construct - , bpy::type_id()); - }; - - /** - * @brief Register from and to python converters for (at least) set, unordered_set and QSet. - * - * Any standard compliant associative container with key should work here. - * - * @tparam Map The container type to register. - */ - template - void register_set_container() { - bpy::to_python_converter>(); - bpy::converter::registry::push_back( - &set_from_python::convertible - , &set_from_python::construct - , bpy::type_id()); - }; - - /** - * @brief Register from and to python converters for sequence container. - * - * Any standard compliant container should work here. - * - * @tparam Map The container type to register. - */ - template - void register_sequence_container() { - bpy::to_python_converter>(); - bpy::converter::registry::push_back( - &container_from_python_list::convertible - , &container_from_python_list::construct - , bpy::type_id()); - }; - - /** - * @brief Register from and to python converters for optional. - * - * @tparam T The optional type (std::optional or boost::optional). - */ - template - void register_optional() { - bpy::to_python_converter>(); - bpy::converter::registry::push_back( - &optional_from_python::convertible - , &optional_from_python::construct - , bpy::type_id()); - }; - + void configure_python_logging(pybind11::module_ mobase); /** * @brief Show a deprecation warning. @@ -268,4 +29,4 @@ namespace utils { } -#endif \ No newline at end of file +#endif diff --git a/src/runner-pybind11/pythonwrapperutilities.h b/src/runner-pybind11/pythonwrapperutilities.h index a55025c..213eaff 100644 --- a/src/runner-pybind11/pythonwrapperutilities.h +++ b/src/runner-pybind11/pythonwrapperutilities.h @@ -8,7 +8,7 @@ #include #include -#include "sipApiAccess.h" +#include "converters_qt_sip.h" #include "error.h" #include "gilock.h" @@ -39,7 +39,7 @@ namespace details { *objPtr = result; } else if (apiTransfer) { - sipAPIAccess::sipAPI()->api_transfer_to(result.ptr(), Py_None); + mo2::details::sipAPI()->api_transfer_to(result.ptr(), Py_None); } if constexpr (!std::is_same_v) { return boost::python::extract(result)(); diff --git a/src/runner-pybind11/sipapiaccess.cpp b/src/runner-pybind11/sipapiaccess.cpp deleted file mode 100644 index b93d6f3..0000000 --- a/src/runner-pybind11/sipapiaccess.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "sipapiaccess.h" -#include -#include -#include - -const sipAPIDef* sipAPIAccess::sipAPI() -{ - QString exception; - static const sipAPIDef* sipApi = nullptr; - if (sipApi == nullptr) { - #if defined(SIP_USE_PYCAPSULE) - PyImport_ImportModule("PyQt5.sip"); - - auto errorObj = PyErr_Occurred(); - if (errorObj != NULL) { - PyObject* type, * value, * traceback; - PyErr_Fetch(&type, &value, &traceback); - PyErr_NormalizeException(&type, &value, &traceback); - if (traceback != NULL) { - boost::python::handle<> h_type(type); - boost::python::handle<> h_val(value); - boost::python::handle<> h_tb(traceback); - boost::python::object tb(boost::python::import("traceback")); - boost::python::object fmt_exp(tb.attr("format_exception")); - boost::python::object exp_list(fmt_exp(h_type, h_val, h_tb)); - boost::python::object exp_str(boost::python::str("\n").join(exp_list)); - boost::python::extract returned(exp_str); - exception = QString::fromStdString(returned()); - } - PyErr_Restore(type, value, traceback); - throw MOBase::Exception(QString("Failed to load PyQt5: %1").arg(exception)); - } - - sipApi = (const sipAPIDef*)PyCapsule_Import("PyQt5.sip._C_API", 0); - if (sipApi == NULL) { - auto errorObj = PyErr_Occurred(); - if (errorObj != NULL) { - PyObject* type, * value, * traceback; - PyErr_Fetch(&type, &value, &traceback); - PyErr_NormalizeException(&type, &value, &traceback); - if (traceback != NULL) { - boost::python::handle<> h_type(type); - boost::python::handle<> h_val(value); - boost::python::handle<> h_tb(traceback); - boost::python::object tb(boost::python::import("traceback")); - boost::python::object fmt_exp(tb.attr("format_exception")); - boost::python::object exp_list(fmt_exp(h_type, h_val, h_tb)); - boost::python::object exp_str(boost::python::str("\n").join(exp_list)); - boost::python::extract returned(exp_str); - exception = QString::fromStdString(returned()); - } - PyErr_Restore(type, value, traceback); - } - throw MOBase::Exception(QString("Failed to load SIP API: %1").arg(exception)); - } - #else - PyObject* sip_module; - PyObject* sip_module_dict; - PyObject* c_api; - - /* Import the SIP module. */ - sip_module = PyImport_ImportModule("PyQt5.sip"); - - if (sip_module == NULL) - return NULL; - - /* Get the module's dictionary. */ - sip_module_dict = PyModule_GetDict(sip_module); - - /* Get the "_C_API" attribute. */ - c_api = PyDict_GetItemString(sip_module_dict, "_C_API"); - - if (c_api == NULL) - return NULL; - - /* Sanity check that it is the right type. */ - if (!PyCObject_Check(c_api)) - return NULL; - - /* Get the actual pointer from the object. */ - sipApi = (const sipAPIDef*)PyCObject_AsVoidPtr(c_api); - #endif - } - - return sipApi; -} \ No newline at end of file diff --git a/src/runner-pybind11/sipapiaccess.h b/src/runner-pybind11/sipapiaccess.h deleted file mode 100644 index 2706dda..0000000 --- a/src/runner-pybind11/sipapiaccess.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef SIPAPIACCESS_H -#define SIPAPIACCESS_H - -#include - -class sipAPIAccess -{ -public: - static const sipAPIDef* sipAPI(); -}; - -#endif // SIPAPIACCESS_H diff --git a/src/runner-pybind11/tuple_helper.h b/src/runner-pybind11/tuple_helper.h deleted file mode 100644 index 1d7b8b5..0000000 --- a/src/runner-pybind11/tuple_helper.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef TUPLE_HELPER_H -#define TUPLE_HELPER_H - -#include -#include //len function - -namespace boost { - namespace python { - - template - struct to_py_tuple { - - static PyObject* convert(const TTuple& c_tuple) { - list values; - //add all c_tuple items to "values" list - convert_impl(c_tuple, values, std::make_index_sequence>{}); - //create Python tuple from the list - return incref(python::tuple(values).ptr()); - } - - private: - - template - static void convert_impl(const TTuple& c_tuple, list& values, std::index_sequence) { - (values.append(std::get(c_tuple)), ...); - } - - }; - - - template - struct from_py_sequence { - - using tuple_type = TTuple; - using index_sequence = std::make_index_sequence>; - - static void* convertible(PyObject* py_obj) { - - if (!PySequence_Check(py_obj)) { - return 0; - } - - if (!PyObject_HasAttrString(py_obj, "__len__")) { - return 0; - } - - python::object py_sequence(handle<>(borrowed(py_obj))); - - if (std::tuple_size_v != len(py_sequence)) { - return 0; - } - - if (convertible_impl(py_sequence, index_sequence{})) { - return py_obj; - } - else { - return 0; - } - } - - static void construct(PyObject* py_obj, converter::rvalue_from_python_stage1_data* data) { - typedef converter::rvalue_from_python_storage storage_t; - storage_t* the_storage = reinterpret_cast(data); - void* memory_chunk = the_storage->storage.bytes; - TTuple* c_tuple = new (memory_chunk) TTuple(); - data->convertible = memory_chunk; - - python::object py_sequence(handle<>(borrowed(py_obj))); - construct_impl(py_sequence, *c_tuple, index_sequence{}); - } - - private: - - template - static bool convertible_impl(const python::object& py_sequence, std::index_sequence) { - return (... && extract>(py_sequence[Is]).check()); - } - - template - static void construct_impl(const python::object& py_sequence, TTuple& c_tuple, std::index_sequence) { - c_tuple = tuple_type{ extract>(py_sequence[Is])... }; - } - - }; - - template< class TTuple> - void register_tuple() { - - to_python_converter< TTuple, to_py_tuple >(); - - converter::registry::push_back(&from_py_sequence::convertible - , &from_py_sequence::construct - , type_id()); - }; - - } -} //boost::python - -#endif \ No newline at end of file diff --git a/src/runner-pybind11/variant_helper.h b/src/runner-pybind11/variant_helper.h deleted file mode 100644 index 08fa27d..0000000 --- a/src/runner-pybind11/variant_helper.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef VARIANT_HELPER_H -#define VARIANT_HELPER_H - -#include - -/** - * Register variant(s) from and to python object. Greatly inspired by register_tuple<>. - */ - -namespace boost { - namespace python { - - template - struct to_py_variant { - - static PyObject* convert(const TVariant& c_variant) { - object value = std::visit([](auto const& value) { - return object{ value }; - }, c_variant); - //create Python object from the list - return incref(value.ptr()); - } - - }; - - template - struct variant_from_python; - - template