Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions Plugin/src/SofaPython3/PythonEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ class PythonEnvironmentData

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

py::module m_sofamodule ;
py::module m_sofaModule ;
py::module m_sofaRuntimeModule ;
private:
std::vector<wchar_t*> m_argv;
};
Expand Down Expand Up @@ -236,7 +237,8 @@ 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");});

// python livecoding related
Expand Down Expand Up @@ -505,22 +507,15 @@ std::string PythonEnvironment::getStackAsString()

std::string PythonEnvironment::getPythonCallingPointString()
{
return py::cast<std::string>(getStaticData()->m_sofamodule.attr("getPythonCallingPointAsString")());
gil lock;
return py::cast<std::string>(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<std::string>(cp[0]), py::cast<int>(cp[1]));
}

void PythonEnvironment::setArguments(const std::string& filename, const std::vector<std::string>& arguments)
Expand Down
3 changes: 3 additions & 0 deletions Plugin/src/SofaPython3/SceneLoaderPY3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions bindings/Sofa/package/prefab.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Sofa.Core
import inspect
import os

class Prefab(Sofa.Core.RawPrefab):
"""
Expand Down Expand Up @@ -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])
Expand All @@ -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])

Expand Down
41 changes: 30 additions & 11 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ;
Expand All @@ -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);
Expand All @@ -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}));
Expand All @@ -244,7 +249,6 @@ py::object addKwargs(Node* self, const py::object& callable, const py::kwargs& k
if(py::isinstance<BaseObject*>(callable))
{
BaseObject* obj = py::cast<BaseObject*>(callable);

self->addObject(obj);
return py::cast(obj);
}
Expand All @@ -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<py::str>(callable))
{
py::str type = callable;
Expand All @@ -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<Base*>(c);
if(!py::isinstance<Base*>(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<std::string>(a.first));
Expand Down Expand Up @@ -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)
Expand Down