diff --git a/Plugin/src/SofaPython3/PythonFactory.cpp b/Plugin/src/SofaPython3/PythonFactory.cpp index bb200c73..c20da562 100644 --- a/Plugin/src/SofaPython3/PythonFactory.cpp +++ b/Plugin/src/SofaPython3/PythonFactory.cpp @@ -291,16 +291,27 @@ void copyFromListOf(BaseData& d, const AbstractTypeInfo& nfo, const void PythonFactory::fromPython(BaseData* d, const py::object& o) { - const AbstractTypeInfo& nfo{ *(d->getValueTypeInfo()) }; + // Is this data field a container ? + // If no we fill it with direct access. if(!nfo.Container()) { scoped_writeonly_access guard(d); if(nfo.Integer()) { nfo.setIntegerValue(guard.ptr, 0, py::cast(o)); } else if(nfo.Text()) { - nfo.setTextValue(guard.ptr, 0, py::cast(o)); + if(py::isinstance(o)) + { + nfo.setTextValue(guard.ptr, 0, py::cast(o)); + } + else + { + std::stringstream s; + s<< "trying to set value for '" + << d->getName() << "' from a python object of type " << py::cast(py::str(o.get_type())) ; + throw std::runtime_error(s.str()); + } } else if(nfo.Scalar()) { nfo.setScalarValue(guard.ptr, 0, py::cast(o)); } else { @@ -328,6 +339,18 @@ void PythonFactory::fromPython(BaseData* d, const py::object& o) return ; } + // The data field is a container, and we want to sets its value from a python string. + // This is the old sofa-behavior that we want to avoid. + // To smooth the deprecation process we are still allowing it ...but prints a warning. + if( !nfo.Text() && py::isinstance(o) ) + { + msg_deprecated(d->getOwner()) << "Data field '" << d->getName() << "' is initialized from a string." + << " This behavior was allowed with SofaPython2 but have very poor performance so it is now " + << "deprecated with SofaPython3. Please fix your scene (as this behavior will be removed)."; + d->read( py::cast(o) ); + return; + } + if(nfo.Integer()) return copyFromListOf(*d, nfo, o); @@ -341,7 +364,7 @@ void PythonFactory::fromPython(BaseData* d, const py::object& o) std::stringstream s; s<< "binding problem, trying to set value for " - << d->getName() << ", " << py::cast(py::str(o)); + << d->getName() << ", from " << py::cast(py::str(o.get_type())); throw std::runtime_error(s.str()); } diff --git a/bindings/Sofa/tests/Core/BaseData.py b/bindings/Sofa/tests/Core/BaseData.py index b0cf3e47..34d99d9a 100644 --- a/bindings/Sofa/tests/Core/BaseData.py +++ b/bindings/Sofa/tests/Core/BaseData.py @@ -292,6 +292,13 @@ def t(c): self.assertEqual(wa[2, 2], 8.0) numpy.testing.assert_array_equal(wa, v*4.0) + def test_set_value_from_string(self): + n = create_scene("rootNode") + n.gravity.value = [1.0,2.0,3.0] + self.assertEqual(list(n.gravity.value), [1.0,2.0,3.0]) + n.gravity.value = "4.0 5.0 6.0" + self.assertEqual(list(n.gravity.value), [4.0,5.0,6.0]) + def test_DataString(self): n = create_scene("rootNode") self.assertTrue(isinstance(n.name, Sofa.Core.DataString))