From 73cd1063a5ad208b1a4b7d1633d4ebf7512e83f1 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Tue, 14 Jun 2022 15:09:32 +0200 Subject: [PATCH 1/5] [SceneLoaderPY3] Add the setting ot the instanciation point. --- Plugin/src/SofaPython3/SceneLoaderPY3.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Plugin/src/SofaPython3/SceneLoaderPY3.cpp b/Plugin/src/SofaPython3/SceneLoaderPY3.cpp index b20e80480..5ac365d50 100644 --- a/Plugin/src/SofaPython3/SceneLoaderPY3.cpp +++ b/Plugin/src/SofaPython3/SceneLoaderPY3.cpp @@ -106,6 +106,9 @@ void SceneLoaderPY3::loadSceneWithArguments(const char *filename, py::object createScene = module.attr("createScene"); createScene( PythonFactory::toPython(root_out.get()) ); + + root_out->setInstanciationSourceFileName(filename); + root_out->setInstanciationSourceFilePos(0); }catch(py::error_already_set& e) { msg_error() << "Unable to completely load the scene from file '"<< filename << "'." << msgendl From c49833379ef088dc790c3406b0f496532bb19fff Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Tue, 14 Jun 2022 15:10:08 +0200 Subject: [PATCH 2/5] [Sofa.Core] Add setting of instanciation point for object & child. --- .../SofaPython3/Sofa/Core/Binding_Node.cpp | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp index 137dca3e4..529a2f1f0 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp @@ -195,15 +195,15 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs if (sofapython3::isProtectedKeyword(name)) throw py::value_error("Cannot call addObject with name " + name + ": Protected keyword"); } - /// Prepare the description to hold the different python attributes as data field's - /// arguments then create the object. + // Prepare the description to hold the different python attributes as data field's + // arguments then create the object. BaseObjectDescription desc {nullptr, type.c_str()}; fillBaseObjectdescription(desc, kwargs); auto object = ObjectFactory::getInstance()->createObject(self, &desc); - /// After calling createObject the returned value can be either a nullptr - /// or non-null but with error message or non-null. - /// Let's first handle the case when the returned pointer is null. + // After calling createObject the returned value can be either a nullptr + // or non-null but with error message or non-null. + // Let's first handle the case when the returned pointer is null. if(!object) { std::stringstream tmp ; @@ -212,6 +212,11 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs throw py::value_error(tmp.str()); } + // Associates the emission location to the created object. + auto finfo = PythonEnvironment::getPythonCallingPointAsFileInfo(); + object->setInstanciationSourceFileName(finfo->filename); + object->setInstanciationSourceFilePos(finfo->line); + if (name.empty()) { 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 checkParamUsage(desc); - /// Convert the logged messages in the object's internal logging into python exception. - /// this is not a very fast way to do that...but well...python is slow anyway. And serious - /// error management has a very high priority. If performance becomes an issue we will fix it - /// when needed. + // Convert the logged messages in the object's internal logging into python exception. + // this is not a very fast way to do that...but well...python is slow anyway. And serious + // error management has a very high priority. If performance becomes an issue we will fix it + // when needed. if(object->countLoggedMessages({Message::Error})) { 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 if(py::isinstance(callable)) { BaseObject* obj = py::cast(callable); - self->addObject(obj); return py::cast(obj); } @@ -255,6 +259,7 @@ py::object addKwargs(Node* self, const py::object& callable, const py::kwargs& k self->addChild(node); return py::cast(node); } + if(py::isinstance(callable)) { py::str type = callable; @@ -265,11 +270,21 @@ py::object addKwargs(Node* self, const py::object& callable, const py::kwargs& k { std::string name = py::str(kwargs["name"]); if (sofapython3::isProtectedKeyword(name)) - throw py::value_error("addObject: Cannot call addObject with name " + name + ": Protected keyword"); + throw py::value_error("add: Cannot call addObject with name " + name + ": Protected keyword"); } auto c = callable(self, **kwargs); Base* base = py::cast(c); + if(!py::isinstance(c)) + { + throw py::value_error("add: the function passed as first argument can only return a Sofa.BaseObject or Sofa.Node object"); + } + + // Set the creation point + auto finfo = PythonEnvironment::getPythonCallingPointAsFileInfo(); + base->setInstanciationSourceFileName(finfo->filename); + base->setInstanciationSourceFilePos(finfo->line); + for(auto a : kwargs) { BaseData* d = base->findData(py::cast(a.first)); @@ -299,6 +314,10 @@ py::object addChildKwargs(Node* self, const std::string& name, const py::kwargs& BaseObjectDescription desc (name.c_str()); fillBaseObjectdescription(desc,kwargs); auto node=simpleapi::createChild(self, desc); + auto finfo = PythonEnvironment::getPythonCallingPointAsFileInfo(); + node->setInstanciationSourceFileName(finfo->filename); + node->setInstanciationSourceFilePos(finfo->line); + checkParamUsage(desc); for(auto a : kwargs) From 040e394e46886db3524e4f03d2b19149163f8239 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Tue, 21 Jun 2022 23:31:47 +0200 Subject: [PATCH 3/5] [SofaPython3] Use the pybindapi instead of cpython's one for getCallpoint --- Plugin/src/SofaPython3/PythonEnvironment.cpp | 23 ++++++++------------ 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Plugin/src/SofaPython3/PythonEnvironment.cpp b/Plugin/src/SofaPython3/PythonEnvironment.cpp index c47c943d9..28121ce67 100644 --- a/Plugin/src/SofaPython3/PythonEnvironment.cpp +++ b/Plugin/src/SofaPython3/PythonEnvironment.cpp @@ -103,7 +103,8 @@ class PythonEnvironmentData std::set addedPath; - py::module m_sofamodule ; + py::module m_sofaModule ; + py::module m_sofaRuntimeModule ; private: std::vector m_argv; }; @@ -237,7 +238,8 @@ void PythonEnvironment::Init() // Lastly, we (try to) add modules from the root of SOFA addPythonModulePathsFromDirectory( Utils::getSofaPathPrefix() ); - getStaticData()->m_sofamodule = py::module::import("Sofa"); + getStaticData()->m_sofaModule = py::module::import("Sofa"); + getStaticData()->m_sofaRuntimeModule = py::module::import("SofaRuntime"); PyRun_SimpleString("import SofaRuntime"); // python livecoding related @@ -508,22 +510,15 @@ std::string PythonEnvironment::getStackAsString() std::string PythonEnvironment::getPythonCallingPointString() { - return py::cast(getStaticData()->m_sofamodule.attr("getPythonCallingPointAsString")()); + gil lock; + return py::cast(getStaticData()->m_sofaModule.attr("getPythonCallingPointAsString")()); } sofa::helper::logging::FileInfo::SPtr PythonEnvironment::getPythonCallingPointAsFileInfo() { - PyObject* pDict = PyModule_GetDict(PyImport_AddModule("SofaRuntime")); - PyObject* res = PyDict_GetItemString(pDict, "getPythonCallingPoint"); - if(res && PySequence_Check(res) ){ - PyObject* filename = PySequence_GetItem(res, 0) ; - PyObject* number = PySequence_GetItem(res, 1) ; - std::string tmp=PyBytes_AsString(filename); - auto lineno = PyLong_AsLong(number); - Py_DECREF(res) ; - return SOFA_FILE_INFO_COPIED_FROM(tmp, lineno); - } - return SOFA_FILE_INFO_COPIED_FROM("undefined", -1); + gil lock; + py::tuple cp = getStaticData()->m_sofaRuntimeModule.attr("getPythonCallingPoint")(); + return SOFA_FILE_INFO_COPIED_FROM(py::cast(cp[0]), py::cast(cp[1])); } void PythonEnvironment::setArguments(const std::string& filename, const std::vector& arguments) From 86802cfc7e402ab565471764c277b636a4d7b5f1 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Wed, 22 Jun 2022 14:31:56 +0200 Subject: [PATCH 4/5] =?UTF-8?q?[SofaPython3]=C2=A0Fix=20Merge=20conflict?= =?UTF-8?q?=20in=20PythonEnvironment.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Plugin/src/SofaPython3/PythonEnvironment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugin/src/SofaPython3/PythonEnvironment.cpp b/Plugin/src/SofaPython3/PythonEnvironment.cpp index d4789c504..08aeec878 100644 --- a/Plugin/src/SofaPython3/PythonEnvironment.cpp +++ b/Plugin/src/SofaPython3/PythonEnvironment.cpp @@ -237,7 +237,7 @@ void PythonEnvironment::Init() // Lastly, we (try to) add modules from the root of SOFA addPythonModulePathsFromDirectory( Utils::getSofaPathPrefix() ); - executePython([]{ getStaticData()->m_sofamodule = py::module::import("Sofa"); }); + executePython([]{ getStaticData()->m_sofaModule = py::module::import("Sofa"); }); executePython([]{ getStaticData()->m_sofaRuntimeModule = py::module::import("SofaRuntime"); }); executePython([]{ PyRun_SimpleString("import SofaRuntime");}); From 93e0ecfdd88c3fbd2e3853f63f260b9e41ce004c Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Wed, 22 Jun 2022 23:59:46 +0200 Subject: [PATCH 5/5] [Bindings] Fix callpoint in Sofa.Prefab. In python3 the path are not absolute so it is needed to ask for. --- bindings/Sofa/package/prefab.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bindings/Sofa/package/prefab.py b/bindings/Sofa/package/prefab.py index 2daadb903..82e97bb38 100644 --- a/bindings/Sofa/package/prefab.py +++ b/bindings/Sofa/package/prefab.py @@ -1,5 +1,6 @@ import Sofa.Core import inspect +import os class Prefab(Sofa.Core.RawPrefab): """ @@ -34,7 +35,7 @@ def __init__(self, *args, **kwargs): Sofa.Core.RawPrefab.__init__(self, *args, **kwargs) frame = inspect.currentframe().f_back frameinfo = inspect.getframeinfo(frame) - definedloc = (frameinfo.filename, frameinfo.lineno) + definedloc = (os.path.abspath(frameinfo.filename), frameinfo.lineno) self.setDefinitionSourceFileName(definedloc[0]) self.setDefinitionSourceFilePos(definedloc[1]) @@ -43,7 +44,7 @@ def __init__(self, *args, **kwargs): frame = frame.f_back if frame is not None: frameinfo = inspect.getframeinfo(frame) - definedloc = (frameinfo.filename, frameinfo.lineno) + definedloc = (os.path.abspath(frameinfo.filename), frameinfo.lineno) self.setInstanciationSourceFileName(definedloc[0]) self.setInstanciationSourceFilePos(definedloc[1])