From f28a09ed54f3f665779a6efda0471d26ab506f99 Mon Sep 17 00:00:00 2001 From: cmoineau <cyril.moineau@cea.fr> Date: Wed, 24 Jan 2024 16:11:15 +0000 Subject: [PATCH] [PyBind] Add support for setAttrPy for Dynamic and Static Attributes. --- include/aidge/utils/Attributes.hpp | 5 +++++ include/aidge/utils/DynamicAttributes.hpp | 4 ++-- include/aidge/utils/StaticAttributes.hpp | 17 ++++++++++++++++- python_binding/utils/pybind_Parameter.cpp | 3 ++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/aidge/utils/Attributes.hpp b/include/aidge/utils/Attributes.hpp index d34440001..927686cfd 100644 --- a/include/aidge/utils/Attributes.hpp +++ b/include/aidge/utils/Attributes.hpp @@ -69,6 +69,11 @@ public: * be agnostic from its return type. */ virtual py::object getAttrPy(const std::string& name) const = 0; + /* Bindable set function, does not recquire any templating. + * This is thanks to py::object which allow the function to + * be agnostic from ``value`` type. + */ + virtual void setAttrPy(const std::string& name, py::object&& value) = 0; #endif virtual ~Attributes() {} }; diff --git a/include/aidge/utils/DynamicAttributes.hpp b/include/aidge/utils/DynamicAttributes.hpp index 2af8f47e9..44c3b1f5e 100644 --- a/include/aidge/utils/DynamicAttributes.hpp +++ b/include/aidge/utils/DynamicAttributes.hpp @@ -135,7 +135,7 @@ public: assert(res.second && "attribute already exists"); } - void setAttrPy(const std::string& name, py::object&& value) + void setAttrPy(const std::string& name, py::object&& value) override final { auto resPy = mAttrsPy.emplace(std::make_pair(name, value)); if (!resPy.second) @@ -204,7 +204,7 @@ private: // Stores C++ attributes (copy) and Python-only attributes // Code should be compiled with -fvisibility=hidden // See https://pybind11.readthedocs.io/en/stable/faq.html: - // “‘SomeClass’ declared with greater visibility than the type of its + // “‘SomeClass’ declared with greater visibility than the type of its // field ‘SomeClass::member’ [-Wattributes]†// This map will only be populated if Python interpreter is running std::map<std::string, py::object> mAttrsPy; diff --git a/include/aidge/utils/StaticAttributes.hpp b/include/aidge/utils/StaticAttributes.hpp index a90a08b01..fa450769f 100644 --- a/include/aidge/utils/StaticAttributes.hpp +++ b/include/aidge/utils/StaticAttributes.hpp @@ -212,7 +212,22 @@ public: } AIDGE_THROW_OR_ABORT(py::value_error, "attribute \"%s\" not found", name.c_str()); - }; + } + + + void setAttrPy(const std::string& name, py::object&& value) override final{ + for (std::size_t i = 0; i < size(EnumStrings<ATTRS_ENUM>::data); ++i) { + if (name == EnumStrings<ATTRS_ENUM>::data[i]) { + // Cannot update attribute using reference has it would require templating + // Use a dirty + auto tmpAttr = py::cast(mAttrs); + py::detail::accessor_policies::tuple_item::set(tmpAttr, static_cast<py::size_t>(i), value); + mAttrs = py::cast<std::tuple<T...>>(tmpAttr); + return; + } + } + AIDGE_THROW_OR_ABORT(py::value_error, "attribute \"%s\" not found", name.c_str()); + } #endif private: diff --git a/python_binding/utils/pybind_Parameter.cpp b/python_binding/utils/pybind_Parameter.cpp index 2957876f3..056cbf16b 100644 --- a/python_binding/utils/pybind_Parameter.cpp +++ b/python_binding/utils/pybind_Parameter.cpp @@ -21,7 +21,8 @@ void init_Attributes(py::module& m){ .def("has_attr", &Attributes::hasAttr, py::arg("name")) .def("get_attr_type", &Attributes::getAttrType, py::arg("name")) .def("get_attrs_name", &Attributes::getAttrsName) - .def("get_attr", &Attributes::getAttrPy, py::arg("name")); + .def("get_attr", &Attributes::getAttrPy, py::arg("name")) + .def("set_attr", &Attributes::setAttrPy, py::arg("name"), py::arg("value")); py::class_<DynamicAttributes, std::shared_ptr<DynamicAttributes>, Attributes>(m, "DynamicAttributes") .def("add_attr", &DynamicAttributes::addAttrPy, py::arg("name"), py::arg("value")) -- GitLab