1717*******************************************************************************
1818* Contact information: contact@sofa-framework.org *
1919******************************************************************************/
20+
21+
2022// / Neede to have automatic conversion from pybind types to stl container.
2123#include < pybind11/stl.h>
22- #include < pybind11/numpy .h>
24+ #include < pybind11/eval .h>
2325
2426#include < sofa/simulation/Simulation.h>
2527#include < sofa/core/ComponentNameHelper.h>
@@ -33,9 +35,6 @@ namespace simpleapi = sofa::simpleapi;
3335#include < sofa/helper/logging/Messaging.h>
3436using sofa::helper::logging::Message;
3537
36- #include < sofa/helper/DiffLib.h>
37- using sofa::helper::getClosestMatch;
38-
3938#include < sofa/simulation/graph/DAGNode.h>
4039using sofa::core::ExecParams;
4140
@@ -60,67 +59,41 @@ using sofapython3::PythonEnvironment;
6059#include < SofaPython3/Sofa/Core/Binding_NodeIterator.h>
6160#include < SofaPython3/Sofa/Core/Binding_PythonScriptEvent.h>
6261
63- #include < SofaPython3/SpellingSuggestionHelper.h>
64-
6562using sofa::core::objectmodel::BaseObjectDescription;
6663
6764#include < queue>
6865#include < sofa/core/objectmodel/Link.h>
6966
70- // These two lines are there to handle deprecated version of pybind.
71- SOFAPYTHON3_BIND_ATTRIBUTE_ERROR ()
72- SOFAPYTHON3_ADD_PYBIND_TYPE_FOR_OLD_VERSION()
73-
7467// / Makes an alias for the pybind11 namespace to increase readability.
7568namespace py { using namespace pybind11 ; }
7669
7770using sofa::simulation::Node;
7871
79- namespace sofapython3
80- {
72+ namespace sofapython3 {
8173
82- namespace
83- {
84- bool checkParamUsage (BaseObjectDescription& desc, const Base* base)
74+ bool checkParamUsage (BaseObjectDescription& desc)
8575{
86- std::vector<std::tuple<std::string, std::string>> paramErrors;
76+ bool hasFailure = false ;
77+ std::stringstream tmp;
78+ tmp <<" Unknown Attribute(s): " << msgendl;
8779 for ( auto & it : desc.getAttributeMap () )
8880 {
8981 if (!it.second .isAccessed ())
9082 {
91- paramErrors.emplace_back (std::make_tuple (it.first , it.second ));
83+ hasFailure = true ;
84+ tmp << " - \" " <<it.first <<" \" with value: \" " <<std::string (it.second ) << msgendl;
9285 }
9386 }
94-
95- if (!paramErrors.empty () || !desc.getErrors ().empty ())
87+ if (!desc.getErrors ().empty ())
88+ {
89+ hasFailure = true ;
90+ tmp << desc.getErrors ()[0 ];
91+ }
92+ if (hasFailure)
9693 {
97- std::stringstream tmp;
98- tmp << " Unknown Attribute(s): " << msgendl;
99-
100- std::vector<std::string> possibleNames;
101- if (base)
102- {
103- fillVectorOfStringFrom (base->getDataFields (), std::back_inserter (possibleNames), [](const BaseData* d){return d->getName ();});
104- fillVectorOfStringFrom (base->getLinks (), std::back_inserter (possibleNames), [](const BaseLink* l){return l->getName ();});
105- }
106-
107- for (auto & [name, value] : paramErrors)
108- {
109- tmp << " - Unable to set attribute '" << name <<" ' with value: " << value;
110- const auto & v = getClosestMatch (name, possibleNames);
111- if (!v.empty ())
112- tmp << " . Possible misspelling of attribute '" << std::get<0 >(v[0 ]) << " ' ?" ;
113- else
114- tmp << " ." ;
115- tmp << msgendl;
116- }
117-
118- if (!desc.getErrors ().empty ())
119- tmp << desc.getErrors ()[0 ];
12094 throw py::type_error (tmp.str ());
12195 }
122-
123- return false ;
96+ return hasFailure;
12497}
12598
12699py::object getItem (Node& self, std::list<std::string>& path)
@@ -206,7 +179,7 @@ py::object getObject(Node &n, const std::string &name, const py::kwargs& kwargs)
206179 msg_deprecated (&n) << " Calling the method getObject() with extra arguments is not supported anymore."
207180 << " To remove this message please refer to the documentation of the getObject method"
208181 << msgendl
209- << PythonEnvironment::getPythonCallingPointString () ;
182+ << PythonEnvironment::getPythonCallingPointString () ;
210183 }
211184
212185 BaseObject *object = n.getObject (name);
@@ -274,7 +247,7 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
274247
275248 setFieldsFromPythonValues (object.get (), kwargs);
276249
277- checkParamUsage (desc, object. get () );
250+ checkParamUsage (desc);
278251
279252 // Convert the logged messages in the object's internal logging into python exception.
280253 // this is not a very fast way to do that...but well...python is slow anyway. And serious
@@ -369,7 +342,7 @@ py::object addChildKwargs(Node* self, const std::string& name, const py::kwargs&
369342 node->setInstanciationSourceFileName (finfo->filename );
370343 node->setInstanciationSourceFilePos (finfo->line );
371344
372- checkParamUsage (desc, node. get () );
345+ checkParamUsage (desc);
373346
374347 for (auto a : kwargs)
375348 {
@@ -425,79 +398,56 @@ py::object removeChildByName(Node& n, const std::string name)
425398std::unique_ptr<NodeIterator> property_children (Node* node)
426399{
427400 return std::make_unique<NodeIterator>(node,
428- [](Node* n) -> size_t { return n->child .size (); },
429- [](Node* n, unsigned int index) -> Base::SPtr { return n->child [index]; },
430- [](const Node* n, const std::string& name) { return n->getChild (name); },
431- [](Node* n, unsigned int index) { n->removeChild (n->child [index]); }
432- );
401+ [](Node* n) -> size_t { return n->child .size (); },
402+ [](Node* n, unsigned int index) -> Base::SPtr { return n->child [index]; },
403+ [](const Node* n, const std::string& name) { return n->getChild (name); },
404+ [](Node* n, unsigned int index) { n->removeChild (n->child [index]); }
405+ );
433406}
434407
435408std::unique_ptr<NodeIterator> property_parents (Node* node)
436409{
437410 return std::make_unique<NodeIterator>(node,
438- [](Node* n) -> size_t { return n->getNbParents (); },
439- [](Node* n, unsigned int index) -> Node::SPtr {
440- auto p = n->getParents ();
441- return static_cast <Node*>(p[index]);
442- },
443- [](const Node* n, const std::string& name) -> sofa::core::Base* {
444- const auto & parents = n->getParents ();
445- return *std::find_if (parents.begin (),
446- parents.end (),
447- [name](BaseNode* child){ return child->getName () == name; });
448- },
449- [](Node*, unsigned int ) {
450- throw std::runtime_error (" Removing a parent is not a supported operation. Please detach the node from the corresponding graph node." );
451- });
411+ [](Node* n) -> size_t { return n->getNbParents (); },
412+ [](Node* n, unsigned int index) -> Node::SPtr {
413+ auto p = n->getParents ();
414+ return static_cast <Node*>(p[index]);
415+ },
416+ [](const Node* n, const std::string& name) -> sofa::core::Base* {
417+ const auto & parents = n->getParents ();
418+ return *std::find_if (parents.begin (),
419+ parents.end (),
420+ [name](BaseNode* child){ return child->getName () == name; });
421+ },
422+ [](Node*, unsigned int ) {
423+ throw std::runtime_error (" Removing a parent is not a supported operation. Please detach the node from the corresponding graph node." );
424+ });
452425}
453426
454427std::unique_ptr<NodeIterator> property_objects (Node* node)
455428{
456429 return std::make_unique<NodeIterator>(node,
457- [](Node* n) -> size_t { return n->object .size (); },
458- [](Node* n, unsigned int index) -> Base::SPtr { return (n->object [index]);},
459- [](const Node* n, const std::string& name) { return n->getObject (name); },
460- [](Node* n, unsigned int index) { n->removeObject (n->object [index]);}
461- );
430+ [](Node* n) -> size_t { return n->object .size (); },
431+ [](Node* n, unsigned int index) -> Base::SPtr { return (n->object [index]);},
432+ [](const Node* n, const std::string& name) { return n->getObject (name); },
433+ [](Node* n, unsigned int index) { n->removeObject (n->object [index]);}
434+ );
462435}
463436
464- py::object __getattr__ (py::object pyself , const std::string& name)
437+ py::object __getattr__ (Node& self , const std::string& name)
465438{
466- Node* selfnode = py::cast<Node*>(pyself);
467439 // / Search in the object lists
468- BaseObject *object = selfnode-> getObject (name);
440+ BaseObject *object = self. getObject (name);
469441 if (object)
470442 return PythonFactory::toPython (object);
471443
472444 // / Search in the child lists
473- Node *child = selfnode-> getChild (name);
445+ Node *child = self. getChild (name);
474446 if (child)
475447 return PythonFactory::toPython (child);
476448
477449 // / Search in the data & link lists
478- py::object result = BindingBase::GetAttr (selfnode, name, false );
479- if (!result.is_none ())
480- return result;
481-
482- std::stringstream tmp;
483- emitSpellingMessage (tmp, " - The data field named " , selfnode->getDataFields (), name, 2 , 0.8 );
484- emitSpellingMessage (tmp, " - The link named " , selfnode->getDataFields (), name, 2 , 0.8 );
485- emitSpellingMessage (tmp, " - The object named " , selfnode->getNodeObjects (), name, 2 , 0.8 );
486- emitSpellingMessage (tmp, " - The child node named " , selfnode->getChildren (), name, 2 , 0.8 );
487-
488- // Also provide spelling hints on python functions.
489- emitSpellingMessage (tmp, " - The python attribute named " , py::cast<py::dict>(py::type::of (pyself).attr (" __dict__" )), name, 5 , 0.8 ,
490- [](const std::pair<py::handle, py::handle>& kv) { return py::cast<std::string>(std::get<0 >(kv)); });
491-
492- std::stringstream message;
493- message << " Unable to find attribute: " +name;
494- if (!tmp.str ().empty ())
495- {
496- message << msgendl;
497- message << " You possibly wanted to access: " << msgendl;
498- message << tmp.rdbuf ();
499- }
500- throw pybind11::attribute_error (message.str ());
450+ return BindingBase::GetAttr (&self, name, true );
501451}
502452
503453// / gets an item using its path (path is dot-separated, relative to the object
@@ -599,8 +549,6 @@ void sendEvent(Node* self, py::object pyUserData, char* eventName)
599549 self->propagateEvent (sofa::core::execparams::defaultInstance (), &event);
600550}
601551
602- }
603-
604552void moduleAddNode (py::module &m) {
605553 // / Register the complete parent-child relationship between Base and Node to the pybind11
606554 // / typing system.
0 commit comments