Skip to content
Snippets Groups Projects
Commit 9e4cdbb9 authored by Olivier BICHLER's avatar Olivier BICHLER
Browse files

Corrected attributes binding

parent 09a9da2f
No related branches found
No related tags found
1 merge request!16Unified interface for attributes
Pipeline #32388 passed with warnings
...@@ -31,7 +31,13 @@ class test_operator_binding(unittest.TestCase): ...@@ -31,7 +31,13 @@ class test_operator_binding(unittest.TestCase):
def test_param_bool(self): def test_param_bool(self):
self.generic_operator.add_attr("bool", True) self.generic_operator.add_attr("bool", True)
self.assertEqual(self.generic_operator.has_attr("bool"), True)
self.assertEqual(self.generic_operator.get_attr("bool"), True) self.assertEqual(self.generic_operator.get_attr("bool"), True)
self.assertEqual(self.generic_operator.get_attr_type("bool"), "bool")
self.assertEqual(self.generic_operator.get_attrs_name(), {"bool"})
self.generic_operator.del_attr("bool")
self.assertEqual(self.generic_operator.has_attr("bool"), False)
self.assertEqual(len(self.generic_operator.get_attrs_name()), 0)
def test_param_int(self): def test_param_int(self):
self.generic_operator.add_attr("int", 1) self.generic_operator.add_attr("int", 1)
......
...@@ -58,9 +58,9 @@ public: ...@@ -58,9 +58,9 @@ public:
/** /**
* @brief Get the attribute's name list. * @brief Get the attribute's name list.
* @return std::vector<std::string> Vector of names of the attributes. * @return std::set<std::string> Vector of names of the attributes.
*/ */
virtual std::vector<std::string> getAttrsName() const = 0; virtual std::set<std::string> getAttrsName() const = 0;
#ifdef PYBIND #ifdef PYBIND
/* Bindable get function, does not recquire any templating. /* Bindable get function, does not recquire any templating.
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#ifdef PYBIND #ifdef PYBIND
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/embed.h>
namespace py = pybind11; namespace py = pybind11;
#endif #endif
...@@ -89,8 +90,11 @@ public: ...@@ -89,8 +90,11 @@ public:
assert(res.second && "attribute already exists"); assert(res.second && "attribute already exists");
#ifdef PYBIND #ifdef PYBIND
// Keep a copy of the attribute in py::object that is updated everytime // We cannot handle Python object if the Python interpreter is not running
mAttrsPy.emplace(std::make_pair(name, py::cast(value))); if (Py_IsInitialized()) {
// Keep a copy of the attribute in py::object that is updated everytime
mAttrsPy.emplace(std::make_pair(name, py::cast(std::forward<T>(value))));
}
#endif #endif
} }
...@@ -105,10 +109,20 @@ public: ...@@ -105,10 +109,20 @@ public:
res.first->second = std::move(libany::any(std::forward<T>(value))); res.first->second = std::move(libany::any(std::forward<T>(value)));
#ifdef PYBIND #ifdef PYBIND
// Keep a copy of the attribute in py::object that is updated everytime // We cannot handle Python object if the Python interpreter is not running
auto resPy = mAttrsPy.emplace(std::make_pair(name, py::cast(value))); if (Py_IsInitialized()) {
if (!resPy.second) // Keep a copy of the attribute in py::object that is updated everytime
resPy.first->second = std::move(py::cast(value)); auto resPy = mAttrsPy.emplace(std::make_pair(name, py::cast(std::forward<T>(value))));
if (!resPy.second)
resPy.first->second = std::move(py::cast(std::forward<T>(value)));
}
#endif
}
void delAttr(const std::string& name) {
mAttrs.erase(name);
#ifdef PYBIND
mAttrsPy.erase(name);
#endif #endif
} }
...@@ -131,7 +145,8 @@ public: ...@@ -131,7 +145,8 @@ public:
////////////////////////////////////// //////////////////////////////////////
bool hasAttr(const std::string& name) const override final { bool hasAttr(const std::string& name) const override final {
#ifdef PYBIND #ifdef PYBIND
return (mAttrsPy.find(name) != mAttrsPy.end()); // Attributes might have been created in Python, the second condition is necessary.
return (mAttrs.find(name) != mAttrs.end() || mAttrsPy.find(name) != mAttrsPy.end());
#else #else
return (mAttrs.find(name) != mAttrs.end()); return (mAttrs.find(name) != mAttrs.end());
#endif #endif
...@@ -155,14 +170,14 @@ public: ...@@ -155,14 +170,14 @@ public:
return mAttrs.at(name).type().name(); return mAttrs.at(name).type().name();
} }
std::vector<std::string> getAttrsName() const override final { std::set<std::string> getAttrsName() const override final {
std::vector<std::string> attrsName; std::set<std::string> attrsName;
for(auto const& it: mAttrs)
attrsName.insert(it.first);
#ifdef PYBIND #ifdef PYBIND
// Attributes might have been created in Python
for(auto const& it: mAttrsPy) for(auto const& it: mAttrsPy)
attrsName.push_back(it.first); attrsName.insert(it.first);
#else
for(auto const& it: mAttrs)
attrsName.push_back(it.first);
#endif #endif
return attrsName; return attrsName;
} }
...@@ -185,6 +200,7 @@ private: ...@@ -185,6 +200,7 @@ private:
// See https://pybind11.readthedocs.io/en/stable/faq.html: // 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]” // field ‘SomeClass::member’ [-Wattributes]”
// This map will only be populated if Python interpreter is running
std::map<std::string, py::object> mAttrsPy; std::map<std::string, py::object> mAttrsPy;
// Stores C++ attributes only // Stores C++ attributes only
// mutable because it may be updated in getAttr() from Python // mutable because it may be updated in getAttr() from Python
......
...@@ -162,10 +162,10 @@ public: ...@@ -162,10 +162,10 @@ public:
assert(false && "attribute not found"); assert(false && "attribute not found");
} }
std::vector<std::string> getAttrsName() const override final { std::set<std::string> getAttrsName() const override final {
std::vector<std::string> attrsName; std::set<std::string> attrsName;
for (std::size_t i = 0; i < size(EnumStrings<ATTRS_ENUM>::data); ++i) { for (std::size_t i = 0; i < size(EnumStrings<ATTRS_ENUM>::data); ++i) {
attrsName.push_back(EnumStrings<ATTRS_ENUM>::data[i]); attrsName.insert(EnumStrings<ATTRS_ENUM>::data[i]);
} }
return attrsName; return attrsName;
} }
......
...@@ -13,7 +13,8 @@ void init_Attributes(py::module& m){ ...@@ -13,7 +13,8 @@ void init_Attributes(py::module& m){
py::class_<DynamicAttributes, std::shared_ptr<DynamicAttributes>, Attributes>(m, "DynamicAttributes") py::class_<DynamicAttributes, std::shared_ptr<DynamicAttributes>, Attributes>(m, "DynamicAttributes")
.def("add_attr", &DynamicAttributes::addAttrPy, py::arg("name"), py::arg("value")) .def("add_attr", &DynamicAttributes::addAttrPy, py::arg("name"), py::arg("value"))
.def("set_attr", &DynamicAttributes::setAttrPy, py::arg("name"), py::arg("value")); .def("set_attr", &DynamicAttributes::setAttrPy, py::arg("name"), py::arg("value"))
.def("del_attr", &DynamicAttributes::delAttr, py::arg("name"));
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment