Skip to content

Commit cb97cab

Browse files
Merge pull request #271 from CRIStAL-PADR/pr-fix-callpoint-api
[FIX] The callpoint api is broken since SofaPython3.
2 parents d993fcf + 93e0ecf commit cb97cab

4 files changed

Lines changed: 45 additions & 27 deletions

File tree

Plugin/src/SofaPython3/PythonEnvironment.cpp

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ class PythonEnvironmentData
103103

104104
std::set<std::string> addedPath;
105105

106-
py::module m_sofamodule ;
106+
py::module m_sofaModule ;
107+
py::module m_sofaRuntimeModule ;
107108
private:
108109
std::vector<wchar_t*> m_argv;
109110
};
@@ -236,7 +237,8 @@ void PythonEnvironment::Init()
236237
// Lastly, we (try to) add modules from the root of SOFA
237238
addPythonModulePathsFromDirectory( Utils::getSofaPathPrefix() );
238239

239-
executePython([]{ getStaticData()->m_sofamodule = py::module::import("Sofa"); });
240+
executePython([]{ getStaticData()->m_sofaModule = py::module::import("Sofa"); });
241+
executePython([]{ getStaticData()->m_sofaRuntimeModule = py::module::import("SofaRuntime"); });
240242
executePython([]{ PyRun_SimpleString("import SofaRuntime");});
241243

242244
// python livecoding related
@@ -505,22 +507,15 @@ std::string PythonEnvironment::getStackAsString()
505507

506508
std::string PythonEnvironment::getPythonCallingPointString()
507509
{
508-
return py::cast<std::string>(getStaticData()->m_sofamodule.attr("getPythonCallingPointAsString")());
510+
gil lock;
511+
return py::cast<std::string>(getStaticData()->m_sofaModule.attr("getPythonCallingPointAsString")());
509512
}
510513

511514
sofa::helper::logging::FileInfo::SPtr PythonEnvironment::getPythonCallingPointAsFileInfo()
512515
{
513-
PyObject* pDict = PyModule_GetDict(PyImport_AddModule("SofaRuntime"));
514-
PyObject* res = PyDict_GetItemString(pDict, "getPythonCallingPoint");
515-
if(res && PySequence_Check(res) ){
516-
PyObject* filename = PySequence_GetItem(res, 0) ;
517-
PyObject* number = PySequence_GetItem(res, 1) ;
518-
std::string tmp=PyBytes_AsString(filename);
519-
auto lineno = PyLong_AsLong(number);
520-
Py_DECREF(res) ;
521-
return SOFA_FILE_INFO_COPIED_FROM(tmp, lineno);
522-
}
523-
return SOFA_FILE_INFO_COPIED_FROM("undefined", -1);
516+
gil lock;
517+
py::tuple cp = getStaticData()->m_sofaRuntimeModule.attr("getPythonCallingPoint")();
518+
return SOFA_FILE_INFO_COPIED_FROM(py::cast<std::string>(cp[0]), py::cast<int>(cp[1]));
524519
}
525520

526521
void PythonEnvironment::setArguments(const std::string& filename, const std::vector<std::string>& arguments)

Plugin/src/SofaPython3/SceneLoaderPY3.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ void SceneLoaderPY3::loadSceneWithArguments(const char *filename,
106106

107107
py::object createScene = module.attr("createScene");
108108
createScene( PythonFactory::toPython(root_out.get()) );
109+
110+
root_out->setInstanciationSourceFileName(filename);
111+
root_out->setInstanciationSourceFilePos(0);
109112
}catch(py::error_already_set& e)
110113
{
111114
msg_error() << "Unable to completely load the scene from file '"<< filename << "'." << msgendl

bindings/Sofa/package/prefab.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Sofa.Core
22
import inspect
3+
import os
34

45

56
class Prefab(Sofa.Core.RawPrefab):
@@ -50,7 +51,7 @@ def __init__(self, *args, **kwargs):
5051
Sofa.Core.RawPrefab.__init__(self, *args, **kwargs)
5152
frame = inspect.currentframe().f_back
5253
frameinfo = inspect.getframeinfo(frame)
53-
definedloc = (frameinfo.filename, frameinfo.lineno)
54+
definedloc = (os.path.abspath(frameinfo.filename), frameinfo.lineno)
5455

5556
self.setDefinitionSourceFileName(definedloc[0])
5657
self.setDefinitionSourceFilePos(definedloc[1])
@@ -59,7 +60,7 @@ def __init__(self, *args, **kwargs):
5960
frame = frame.f_back
6061
if frame is not None:
6162
frameinfo = inspect.getframeinfo(frame)
62-
definedloc = (frameinfo.filename, frameinfo.lineno)
63+
definedloc = (os.path.abspath(frameinfo.filename), frameinfo.lineno)
6364
self.setInstanciationSourceFileName(definedloc[0])
6465
self.setInstanciationSourceFilePos(definedloc[1])
6566

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

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

Comments
 (0)