@@ -236,7 +236,7 @@ void setFieldsFromPythonValues(Base* self, const py::kwargs& dict)
236236}
237237
238238// / Implement the addObject function.
239- py::object addObjectKwargs (Node* self, const std::string& type, const py::kwargs& kwargs)
239+ py::object addObjectKwargsToStrings (Node* self, const std::string& type, const py::kwargs& kwargs)
240240{
241241 std::string name {};
242242 if (kwargs.contains (" name" ))
@@ -248,10 +248,8 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
248248 // / Prepare the description to hold the different python attributes as data field's
249249 // / arguments then create the object.
250250 BaseObjectDescription desc {nullptr , type.c_str ()};
251- py::list parametersToCopy;
252- py::list parametersToLink;
253251
254- processKwargsForObjectCreation (kwargs, parametersToLink, parametersToCopy, desc);
252+ fillBaseObjectdescription ( desc,kwargs );
255253 auto object = ObjectFactory::getInstance ()->createObject (self, &desc);
256254
257255 // After calling createObject the returned value can be either a nullptr
@@ -295,13 +293,93 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
295293 BaseData * d = object->findData (dataName);
296294 if (d)
297295 {
298- if (parametersToLink.contains (a.first ))
299- d->setParent (a.second .cast <BaseData*>());
300- else if (parametersToCopy.contains (a.first ))
301- PythonFactory::fromPython (d, py::cast<py::object>(a.second ));
302296 d->setPersistent (true );
303297 }
304298 }
299+
300+ return PythonFactory::toPython (object.get ());
301+ }
302+
303+ // / Implement the addObject function.
304+ py::object addObjectKwargs (Node* self, const std::string& type, const py::kwargs& kwargs)
305+ {
306+ std::string name {};
307+ if (kwargs.contains (" name" ))
308+ {
309+ name = py::str (kwargs[" name" ]);
310+ if (sofapython3::isProtectedKeyword (name))
311+ throw py::value_error (" Cannot call addObject with name " + name + " : Protected keyword" );
312+ }
313+ // / Prepare the description to hold the different python attributes as data field's
314+ // / arguments then create the object.
315+ BaseObjectDescription desc {nullptr , type.c_str ()};
316+ py::list parametersToCopy;
317+ py::list parametersToLink;
318+
319+ processKwargsForObjectCreation (kwargs, parametersToLink, parametersToCopy, desc);
320+ auto object = ObjectFactory::getInstance ()->createObject (self, &desc);
321+
322+ // After calling createObject the returned value can be either a nullptr
323+ // or non-null but with error message or non-null.
324+ // Let's first handle the case when the returned pointer is null.
325+ if (!object)
326+ {
327+ std::stringstream tmp ;
328+ for (auto & s : desc.getErrors ())
329+ tmp << s << msgendl ;
330+ throw py::value_error (tmp.str ());
331+ }
332+
333+ // Associates the emission location to the created object.
334+ auto finfo = PythonEnvironment::getPythonCallingPointAsFileInfo ();
335+ object->setInstanciationSourceFileName (finfo->filename );
336+ object->setInstanciationSourceFilePos (finfo->line );
337+
338+ if (name.empty ())
339+ {
340+ const auto resolvedName = self->getNameHelper ().resolveName (object->getClassName (), name, sofa::core::ComponentNameHelper::Convention::python);
341+ object->setName (resolvedName);
342+ }
343+
344+ setFieldsFromPythonValues (object.get (), kwargs);
345+
346+ checkParamUsage (desc, object.get ());
347+
348+ // Convert the logged messages in the object's internal logging into python exception.
349+ // this is not a very fast way to do that...but well...python is slow anyway. And serious
350+ // error management has a very high priority. If performance becomes an issue we will fix it
351+ // when needed.
352+ if (object->countLoggedMessages ({Message::Error}))
353+ {
354+ throw py::value_error (object->getLoggedMessagesAsString ({Message::Error}));
355+ }
356+
357+
358+ for (auto a : kwargs)
359+ {
360+ const std::string dataName = py::cast<std::string>(a.first );
361+ BaseData * d = object->findData (dataName);
362+
363+ if (d)
364+ {
365+ if (parametersToLink.contains (a.first ))
366+ d->setParent (a.second .cast <BaseData*>());
367+ else if (parametersToCopy.contains (a.first ))
368+ {
369+ try
370+ {
371+ PythonFactory::fromPython (d, py::cast<py::object>(a.second ));
372+ }
373+ catch (std::exception& e)
374+ {
375+ msg_warning (self)<<" Creating " << type << " named " << name <<" . An exception of type \" " <<e.what ()<<" \" was received while copying value input for data " << dataName << " . To fix this please reshape the list you are providing to fit the real intended data structure. \n The compatibility layer will try to create the data by converting the input to string." ;
376+
377+ d->read (toSofaParsableString (a.second ));
378+ }
379+ }
380+ d->setPersistent (true );
381+ }
382+ }
305383 return PythonFactory::toPython (object.get ());
306384}
307385
0 commit comments