Skip to content

Commit f1140e9

Browse files
Merge pull request #208 from CRIStAL-PADR/pr-add-baselink-attribute-forwarding
[Sofa.Core] Add BaseLink forwarding accessor.
2 parents cfd8709 + 9fde3ec commit f1140e9

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseLink.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ using sofa::core::objectmodel::BaseObject;
2626

2727
#include <sofa/core/objectmodel/BaseNode.h>
2828

29+
#include <SofaPython3/Sofa/Core/Binding_Base.h>
2930
#include <SofaPython3/Sofa/Core/Binding_BaseLink.h>
3031
#include <SofaPython3/Sofa/Core/Binding_BaseLink_doc.h>
3132
#include <SofaPython3/PythonFactory.h>
@@ -67,6 +68,29 @@ std::string getPathName(BaseLink& self)
6768
return (n ? n->getPathName() : o->getPathName()) + "." + self.getName();
6869
}
6970

71+
namespace {
72+
py::object __getattr__(py::object self, const std::string& s)
73+
{
74+
py::object base = getLinkedBase(py::cast<BaseLink&>(self), 0);
75+
if(!base.is_none())
76+
{
77+
return BindingBase::__getattr__(base, s);
78+
}
79+
throw std::runtime_error("Unable to find attribute on an empty link.");
80+
}
81+
82+
void __setattr__(py::object self, const std::string& s, py::object value)
83+
{
84+
py::object base = getLinkedBase(py::cast<BaseLink&>(self), 0);
85+
if(!base.is_none())
86+
{
87+
BindingBase::__setattr__(base, s, value);
88+
return;
89+
}
90+
throw std::runtime_error("Unable to find and set an attribute on an empty link.");
91+
}
92+
}
93+
7094
void moduleAddBaseLink(py::module& m)
7195
{
7296
py::class_<BaseLink> link(m, "Link", sofapython3::doc::baseLink::baseLinkClass);
@@ -89,11 +113,12 @@ void moduleAddBaseLink(py::module& m)
89113
link.def("getLinkedBase", getLinkedBase, "index"_a = 0, sofapython3::doc::baseLink::getLinkedBase);
90114
link.def("setLinkedBase", &BaseLink::setLinkedBase, sofapython3::doc::baseLink::getLinkedBase);
91115

92-
93116
link.def("getLinkedPath", &BaseLink::getLinkedPath, "index"_a = 0, sofapython3::doc::baseLink::getLinkedPath);
94117
link.def("getPathName", getPathName, sofapython3::doc::baseLink::getLinkedPath);
95118
link.def("read", &BaseLink::read, sofapython3::doc::baseLink::read);
96119

120+
link.def("__getattr__", &__getattr__);
121+
link.def("__setattr__", &__setattr__);
97122
}
98123

99124
} /// namespace sofapython3

bindings/Sofa/tests/Core/BaseLink.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
def create_scene(rootName="root"):
88
root = Sofa.Core.Node(rootName)
99
root.addObject("RequiredPlugin", name="SofaBaseMechanics")
10+
root.addObject("RequiredPlugin", name="SofaDeformable")
1011
return root
1112

1213
class Test(unittest.TestCase):
@@ -95,6 +96,14 @@ def test_getLinked_and_Owner(self):
9596
self.assertEqual(link_input.getOwnerBase().getName(), "BarycentricMapping")
9697
self.assertEqual(link_output.getOwnerBase().getName(), "BarycentricMapping")
9798

99+
def test_baselink_attributes_forwarding(self):
100+
root = create_scene("root")
101+
c1 = root.addObject("MechanicalObject", name="t1", position=[[-1,-2,-3],[-4,-5,-6]])
102+
f1 = root.addObject("RestShapeSpringsForceField", name="forcefield", mstate="@t1")
103+
self.assertEqual(len(f1.mstate.position), 2)
104+
f1.mstate.position = [[1.0,2.0,3.0]]
105+
self.assertEqual(len(f1.mstate.position), 1)
106+
98107
@unittest.skip # Segmentation fault on MacOS
99108
def test_read(self):
100109
root = create_scene("root")

0 commit comments

Comments
 (0)