@@ -195,15 +195,15 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
195195 if (sofapython3::isProtectedKeyword (name))
196196 throw py::value_error (" Cannot call addObject with name " + name + " : Protected keyword" );
197197 }
198- // / Prepare the description to hold the different python attributes as data field's
199- // / arguments then create the object.
198+ // Prepare the description to hold the different python attributes as data field's
199+ // arguments then create the object.
200200 BaseObjectDescription desc {nullptr , type.c_str ()};
201201 fillBaseObjectdescription (desc, kwargs);
202202 auto object = ObjectFactory::getInstance ()->createObject (self, &desc);
203203
204- // / After calling createObject the returned value can be either a nullptr
205- // / or non-null but with error message or non-null.
206- // / Let's first handle the case when the returned pointer is null.
204+ // After calling createObject the returned value can be either a nullptr
205+ // or non-null but with error message or non-null.
206+ // Let's first handle the case when the returned pointer is null.
207207 if (!object)
208208 {
209209 std::stringstream tmp ;
@@ -212,6 +212,11 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
212212 throw py::value_error (tmp.str ());
213213 }
214214
215+ // Associates the emission location to the created object.
216+ auto finfo = PythonEnvironment::getPythonCallingPointAsFileInfo ();
217+ object->setInstanciationSourceFileName (finfo->filename );
218+ object->setInstanciationSourceFilePos (finfo->line );
219+
215220 if (name.empty ())
216221 {
217222 const auto resolvedName = self->getNameHelper ().resolveName (object->getClassName (), name, sofa::core::ComponentNameHelper::Convention::python);
@@ -220,10 +225,10 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
220225
221226 checkParamUsage (desc);
222227
223- // / Convert the logged messages in the object's internal logging into python exception.
224- // / this is not a very fast way to do that...but well...python is slow anyway. And serious
225- // / error management has a very high priority. If performance becomes an issue we will fix it
226- // / when needed.
228+ // Convert the logged messages in the object's internal logging into python exception.
229+ // this is not a very fast way to do that...but well...python is slow anyway. And serious
230+ // error management has a very high priority. If performance becomes an issue we will fix it
231+ // when needed.
227232 if (object->countLoggedMessages ({Message::Error}))
228233 {
229234 throw py::value_error (object->getLoggedMessagesAsString ({Message::Error}));
@@ -244,7 +249,6 @@ py::object addKwargs(Node* self, const py::object& callable, const py::kwargs& k
244249 if (py::isinstance<BaseObject*>(callable))
245250 {
246251 BaseObject* obj = py::cast<BaseObject*>(callable);
247-
248252 self->addObject (obj);
249253 return py::cast (obj);
250254 }
@@ -255,6 +259,7 @@ py::object addKwargs(Node* self, const py::object& callable, const py::kwargs& k
255259 self->addChild (node);
256260 return py::cast (node);
257261 }
262+
258263 if (py::isinstance<py::str>(callable))
259264 {
260265 py::str type = callable;
@@ -265,11 +270,21 @@ py::object addKwargs(Node* self, const py::object& callable, const py::kwargs& k
265270 {
266271 std::string name = py::str (kwargs[" name" ]);
267272 if (sofapython3::isProtectedKeyword (name))
268- throw py::value_error (" addObject : Cannot call addObject with name " + name + " : Protected keyword" );
273+ throw py::value_error (" add : Cannot call addObject with name " + name + " : Protected keyword" );
269274 }
270275
271276 auto c = callable (self, **kwargs);
272277 Base* base = py::cast<Base*>(c);
278+ if (!py::isinstance<Base*>(c))
279+ {
280+ throw py::value_error (" add: the function passed as first argument can only return a Sofa.BaseObject or Sofa.Node object" );
281+ }
282+
283+ // Set the creation point
284+ auto finfo = PythonEnvironment::getPythonCallingPointAsFileInfo ();
285+ base->setInstanciationSourceFileName (finfo->filename );
286+ base->setInstanciationSourceFilePos (finfo->line );
287+
273288 for (auto a : kwargs)
274289 {
275290 BaseData* d = base->findData (py::cast<std::string>(a.first ));
@@ -299,6 +314,10 @@ py::object addChildKwargs(Node* self, const std::string& name, const py::kwargs&
299314 BaseObjectDescription desc (name.c_str ());
300315 fillBaseObjectdescription (desc,kwargs);
301316 auto node=simpleapi::createChild (self, desc);
317+ auto finfo = PythonEnvironment::getPythonCallingPointAsFileInfo ();
318+ node->setInstanciationSourceFileName (finfo->filename );
319+ node->setInstanciationSourceFilePos (finfo->line );
320+
302321 checkParamUsage (desc);
303322
304323 for (auto a : kwargs)
0 commit comments