Merge pull request #15669 from marioalexis84/fem-link_scope_python_objects
Fem: Fix link scope for Python objects
This commit is contained in:
@@ -423,6 +423,10 @@ void Application::setupPythonException(PyObject* module)
|
||||
Base::PyExc_FC_CADKernelError = PyErr_NewException("Base.CADKernelError", Base::PyExc_FC_GeneralError, nullptr);
|
||||
Py_INCREF(Base::PyExc_FC_CADKernelError);
|
||||
PyModule_AddObject(module, "CADKernelError", Base::PyExc_FC_CADKernelError);
|
||||
|
||||
Base::PyExc_FC_PropertyError = PyErr_NewException("Base.PropertyError", PyExc_AttributeError, nullptr);
|
||||
Py_INCREF(Base::PyExc_FC_PropertyError);
|
||||
PyModule_AddObject(module, "PropertyError", Base::PyExc_FC_PropertyError);
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -2184,6 +2188,7 @@ void Application::initTypes()
|
||||
new Base::ExceptionProducer<Base::UnitsMismatchError>;
|
||||
new Base::ExceptionProducer<Base::CADKernelError>;
|
||||
new Base::ExceptionProducer<Base::RestoreError>;
|
||||
new Base::ExceptionProducer<Base::PropertyError>;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -63,7 +63,7 @@ PyObject* PropertyContainerPy::getPropertyByName(PyObject *args)
|
||||
|
||||
App::Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
|
||||
if (!prop) {
|
||||
PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr);
|
||||
PyErr_Format(Base::PyExc_FC_PropertyError, "Property container has no property '%s'", pstr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -612,6 +612,23 @@ PyObject* AttributeError::getPyExceptionType() const
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
PropertyError::PropertyError() = default;
|
||||
|
||||
PropertyError::PropertyError(const char* sMessage)
|
||||
: AttributeError(sMessage)
|
||||
{}
|
||||
|
||||
PropertyError::PropertyError(const std::string& sMessage)
|
||||
: AttributeError(sMessage)
|
||||
{}
|
||||
|
||||
PyObject* PropertyError::getPyExceptionType() const
|
||||
{
|
||||
return PyExc_FC_PropertyError;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
RuntimeError::RuntimeError() = default;
|
||||
|
||||
RuntimeError::RuntimeError(const char* sMessage)
|
||||
|
||||
@@ -670,6 +670,26 @@ public:
|
||||
PyObject* getPyExceptionType() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* The PropertyError can be used to indicate the usage of a wrong property name or value.
|
||||
* @author Mario Passaglia
|
||||
*/
|
||||
class BaseExport PropertyError: public AttributeError
|
||||
{
|
||||
public:
|
||||
/// Construction
|
||||
PropertyError();
|
||||
explicit PropertyError(const char* sMessage);
|
||||
explicit PropertyError(const std::string& sMessage);
|
||||
PropertyError(const PropertyError&) = default;
|
||||
PropertyError(PropertyError&&) = default;
|
||||
/// Destruction
|
||||
~PropertyError() noexcept override = default;
|
||||
PropertyError& operator=(const PropertyError&) = default;
|
||||
PropertyError& operator=(PropertyError&&) = default;
|
||||
PyObject* getPyExceptionType() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* The RuntimeError can be used to indicate an unknown exception at runtime.
|
||||
* @author Werner Mayer
|
||||
|
||||
@@ -48,6 +48,7 @@ PyObject* Base::PyExc_FC_BadGraphError = nullptr;
|
||||
PyObject* Base::PyExc_FC_ExpressionError = nullptr;
|
||||
PyObject* Base::PyExc_FC_ParserError = nullptr;
|
||||
PyObject* Base::PyExc_FC_CADKernelError = nullptr;
|
||||
PyObject* Base::PyExc_FC_PropertyError = nullptr;
|
||||
|
||||
typedef struct { //NOLINT
|
||||
PyObject_HEAD
|
||||
|
||||
@@ -430,6 +430,7 @@ BaseExport extern PyObject* PyExc_FC_BadGraphError;
|
||||
BaseExport extern PyObject* PyExc_FC_ExpressionError;
|
||||
BaseExport extern PyObject* PyExc_FC_ParserError;
|
||||
BaseExport extern PyObject* PyExc_FC_CADKernelError;
|
||||
BaseExport extern PyObject* PyExc_FC_PropertyError;
|
||||
|
||||
/** Exception handling for python callback functions
|
||||
* Is a convenience macro to manage the exception handling of python callback
|
||||
|
||||
@@ -29,7 +29,7 @@ __url__ = "https://www.freecad.org"
|
||||
# \ingroup FEM
|
||||
# \brief base object for FEM Element Features
|
||||
|
||||
|
||||
from FreeCAD import Base
|
||||
from . import base_fempythonobject
|
||||
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
@@ -50,7 +50,7 @@ class BaseFemElement(base_fempythonobject.BaseFemPythonObject):
|
||||
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyLinkSubList",
|
||||
type="App::PropertyLinkSubListGlobal",
|
||||
name="References",
|
||||
group="Element",
|
||||
doc="List of element shapes",
|
||||
@@ -59,3 +59,15 @@ class BaseFemElement(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
|
||||
return prop
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
# update old project with new properties
|
||||
for prop in self._get_properties():
|
||||
try:
|
||||
obj.getPropertyByName(prop.name)
|
||||
except Base.PropertyError:
|
||||
prop.add_to_object(obj)
|
||||
|
||||
if prop.name == "References":
|
||||
# change References to App::PropertyLinkSubListGlobal
|
||||
prop.handle_change_type(obj, old_type="App::PropertyLinkSubList")
|
||||
|
||||
@@ -30,6 +30,7 @@ __url__ = "https://www.freecad.org"
|
||||
# \brief base object for FEM Mesh Element Features
|
||||
|
||||
|
||||
from FreeCAD import Base
|
||||
from . import base_fempythonobject
|
||||
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
@@ -50,7 +51,7 @@ class BaseFemMeshElement(base_fempythonobject.BaseFemPythonObject):
|
||||
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyLinkSubList",
|
||||
type="App::PropertyLinkSubListGlobal",
|
||||
name="References",
|
||||
group="Mesh Element",
|
||||
doc="List of reference shapes",
|
||||
@@ -59,3 +60,15 @@ class BaseFemMeshElement(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
|
||||
return prop
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
# update old project with new properties
|
||||
for prop in self._get_properties():
|
||||
try:
|
||||
obj.getPropertyByName(prop.name)
|
||||
except Base.PropertyError:
|
||||
prop.add_to_object(obj)
|
||||
|
||||
if prop.name == "References":
|
||||
# change References to App::PropertyLinkSubListGlobal
|
||||
prop.handle_change_type(obj, old_type="App::PropertyLinkSubList")
|
||||
|
||||
@@ -65,3 +65,10 @@ class _PropHelper:
|
||||
obj.addProperty(**self.info)
|
||||
obj.setPropertyStatus(self.name, "LockDynamic")
|
||||
setattr(obj, self.name, self.value)
|
||||
|
||||
def handle_change_type(self, obj, old_type, convert_old_value=lambda x: x):
|
||||
if obj.getTypeIdOfProperty(self.name) == old_type:
|
||||
self.value = convert_old_value(obj.getPropertyByName(self.name))
|
||||
obj.setPropertyStatus(self.name, "-LockDynamic")
|
||||
obj.removeProperty(self.name)
|
||||
self.add_to_object(obj)
|
||||
|
||||
@@ -86,7 +86,7 @@ class ConstraintBodyHeatSource(base_fempythonobject.BaseFemPythonObject):
|
||||
for prop in self._get_properties():
|
||||
try:
|
||||
obj.getPropertyByName(prop.name)
|
||||
except:
|
||||
except FreeCAD.Base.PropertyError:
|
||||
prop.add_to_object(obj)
|
||||
|
||||
# migrate old HeatSource property
|
||||
@@ -96,5 +96,5 @@ class ConstraintBodyHeatSource(base_fempythonobject.BaseFemPythonObject):
|
||||
obj.Mode = "Dissipation Rate"
|
||||
obj.setPropertyStatus("HeatSource", "-LockDynamic")
|
||||
obj.removeProperty("HeatSource")
|
||||
except:
|
||||
except FreeCAD.Base.PropertyError:
|
||||
pass
|
||||
|
||||
@@ -29,6 +29,7 @@ __url__ = "https://www.freecad.org"
|
||||
# \ingroup FEM
|
||||
# \brief constraint section print object
|
||||
|
||||
from FreeCAD import Base
|
||||
from . import base_fempythonobject
|
||||
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
@@ -67,5 +68,5 @@ class ConstraintSectionPrint(base_fempythonobject.BaseFemPythonObject):
|
||||
for prop in self._get_properties():
|
||||
try:
|
||||
obj.getPropertyByName(prop.name)
|
||||
except:
|
||||
except Base.PropertyError:
|
||||
prop.add_to_object(obj)
|
||||
|
||||
@@ -114,5 +114,5 @@ class ConstraintTie(base_fempythonobject.BaseFemPythonObject):
|
||||
for prop in self._get_properties():
|
||||
try:
|
||||
obj.getPropertyByName(prop.name)
|
||||
except:
|
||||
except FreeCAD.Base.PropertyError:
|
||||
prop.add_to_object(obj)
|
||||
|
||||
@@ -30,8 +30,11 @@ __url__ = "https://www.freecad.org"
|
||||
# \ingroup FEM
|
||||
# \brief material common object
|
||||
|
||||
from FreeCAD import Base
|
||||
from . import base_fempythonobject
|
||||
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
|
||||
|
||||
class MaterialCommon(base_fempythonobject.BaseFemPythonObject):
|
||||
"""
|
||||
@@ -42,27 +45,46 @@ class MaterialCommon(base_fempythonobject.BaseFemPythonObject):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
self.add_properties(obj)
|
||||
|
||||
for prop in self._get_properties():
|
||||
prop.add_to_object(obj)
|
||||
|
||||
def _get_properties(self):
|
||||
prop = []
|
||||
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyLinkSubListGlobal",
|
||||
name="References",
|
||||
group="Material",
|
||||
doc="List of material shapes",
|
||||
value=[],
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyEnumeration",
|
||||
name="Category",
|
||||
group="Material",
|
||||
doc="Material type: fluid or solid",
|
||||
value=["Solid", "Fluid"],
|
||||
)
|
||||
)
|
||||
|
||||
return prop
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
self.add_properties(obj)
|
||||
# update old project with new properties
|
||||
for prop in self._get_properties():
|
||||
try:
|
||||
obj.getPropertyByName(prop.name)
|
||||
except Base.PropertyError:
|
||||
prop.add_to_object(obj)
|
||||
|
||||
if prop.name == "References":
|
||||
# change References to App::PropertyLinkSubListGlobal
|
||||
prop.handle_change_type(obj, old_type="App::PropertyLinkSubList")
|
||||
|
||||
def add_properties(self, obj):
|
||||
# References
|
||||
if not hasattr(obj, "References"):
|
||||
obj.addProperty(
|
||||
"App::PropertyLinkSubList", "References", "Material", "List of material shapes"
|
||||
)
|
||||
obj.setPropertyStatus("References", "LockDynamic")
|
||||
# Category
|
||||
# attribute Category was added in commit 61fb3d429a
|
||||
if not hasattr(obj, "Category"):
|
||||
obj.addProperty(
|
||||
"App::PropertyEnumeration", "Category", "Material", "Material type: fluid or solid"
|
||||
)
|
||||
obj.setPropertyStatus("Category", "LockDynamic")
|
||||
obj.Category = ["Solid", "Fluid"] # used in TaskPanel
|
||||
obj.Category = "Solid"
|
||||
"""
|
||||
Some remarks to the category. Not finished, thus to be continued.
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@ __url__ = "https://www.freecad.org"
|
||||
# \ingroup FEM
|
||||
# \brief reinforced object
|
||||
|
||||
from . import base_fempythonobject
|
||||
from . import material_common
|
||||
|
||||
|
||||
class MaterialReinforced(base_fempythonobject.BaseFemPythonObject):
|
||||
class MaterialReinforced(material_common.MaterialCommon):
|
||||
"""
|
||||
The MaterialReinforced object
|
||||
"""
|
||||
@@ -42,20 +42,10 @@ class MaterialReinforced(base_fempythonobject.BaseFemPythonObject):
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertyLinkSubList", "References", "Material", "List of material shapes"
|
||||
)
|
||||
obj.setPropertyStatus("References", "LockDynamic")
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertyMap", "Reinforcement", "Composites", "Reinforcement material properties"
|
||||
)
|
||||
obj.setPropertyStatus("Reinforcement", "LockDynamic")
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertyEnumeration", "Category", "Material", "Matrix material properties"
|
||||
)
|
||||
obj.setPropertyStatus("Category", "LockDynamic")
|
||||
|
||||
# overwrite Category enumeration
|
||||
obj.Category = ["Solid"]
|
||||
obj.Category = "Solid"
|
||||
|
||||
@@ -29,6 +29,7 @@ __url__ = "https://www.freecad.org"
|
||||
# \ingroup FEM
|
||||
# \brief mesh gmsh object
|
||||
|
||||
from FreeCAD import Base
|
||||
from . import base_fempythonobject
|
||||
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
@@ -41,8 +42,6 @@ class MeshGmsh(base_fempythonobject.BaseFemPythonObject):
|
||||
|
||||
Type = "Fem::FemMeshGmsh"
|
||||
|
||||
# they will be used from the task panel too, thus they need to be outside of the __init__
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
@@ -277,23 +276,21 @@ class MeshGmsh(base_fempythonobject.BaseFemPythonObject):
|
||||
for prop in self._get_properties():
|
||||
try:
|
||||
obj.getPropertyByName(prop.name)
|
||||
if prop.name == "Algorithm2D":
|
||||
# refresh the list of known 2D algorithms
|
||||
obj.Algorithm2D = prop.value
|
||||
elif prop.name == "Algorithm3D":
|
||||
# refresh the list of known 3D algorithms
|
||||
obj.Algorithm3D = prop.value
|
||||
elif prop.name == "HighOrderOptimize":
|
||||
# HighOrderOptimize was once App::PropertyBool, so check this
|
||||
if type(obj.HighOrderOptimize) is bool:
|
||||
value = obj.HighOrderOptimize
|
||||
obj.setPropertyStatus("HighOrderOptimize", "-LockDynamic")
|
||||
obj.removeProperty("HighOrderOptimize")
|
||||
prop.add_to_object(obj)
|
||||
obj.HighOrderOptimize = "Optimization" if value else "None"
|
||||
except:
|
||||
except Base.PropertyError:
|
||||
prop.add_to_object(obj)
|
||||
|
||||
if prop.name == "Algorithm2D":
|
||||
# refresh the list of known 2D algorithms for old projects
|
||||
obj.Algorithm2D = prop.value
|
||||
elif prop.name == "Algorithm3D":
|
||||
# refresh the list of known 3D algorithms for old projects
|
||||
obj.Algorithm3D = prop.value
|
||||
elif prop.name == "HighOrderOptimize":
|
||||
# HighOrderOptimize was once App::PropertyBool, so check this
|
||||
prop.handle_change_type(
|
||||
obj, "App::PropertyBool", lambda x: "Optimization" if x else "None"
|
||||
)
|
||||
|
||||
# migrate old Part property to Shape property
|
||||
try:
|
||||
value_part = obj.getPropertyByName("Part")
|
||||
@@ -304,9 +301,9 @@ class MeshGmsh(base_fempythonobject.BaseFemPythonObject):
|
||||
type="App::PropertyLinkGlobal",
|
||||
name="Shape",
|
||||
group="FEM Mesh",
|
||||
doc="Geometry object, the mesh is made from. The geometry object has to have a Shape",
|
||||
doc="Geometry object, the mesh is made from. The geometry object has to have a Shape.",
|
||||
value=value_part,
|
||||
)
|
||||
prop.add_to_object(obj)
|
||||
except:
|
||||
except Base.PropertyError:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user