Skip to content

Commit e51194f

Browse files
committed
Add compatibility layer
1 parent cb5e0b0 commit e51194f

1 file changed

Lines changed: 86 additions & 8 deletions

File tree

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

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)