From b08714116cbd9bd8269306c162db9b8024c810f8 Mon Sep 17 00:00:00 2001 From: shai Date: Thu, 4 Jul 2024 11:48:44 +0300 Subject: [PATCH 1/2] Fix python shape setElement function. Partially fixes #15095 --- src/Mod/Part/App/TopoShapePy.xml | 8 +++-- src/Mod/Part/App/TopoShapePyImp.cpp | 33 +++++-------------- .../TestTopologicalNamingProblem.py | 21 ++++++++++++ 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/Mod/Part/App/TopoShapePy.xml b/src/Mod/Part/App/TopoShapePy.xml index 357a7be4cf..435db55ef8 100644 --- a/src/Mod/Part/App/TopoShapePy.xml +++ b/src/Mod/Part/App/TopoShapePy.xml @@ -813,8 +813,12 @@ infos contains additional info on the solutions. It is a list of tuples: - Returns a SubElement -getElement(elementName) -> Face | Edge | Vertex + +Returns a SubElement +getElement(elementName, [silent = False]) -> Face | Edge | Vertex +elementName: SubElement name - i.e. 'Edge1', 'Face3' etc. + Accepts TNP names as well +silent: True to suppress the exception throw if the shape isn't found. diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index a556600cf5..a6678b9d6a 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -2602,35 +2602,18 @@ PyObject* TopoShapePy::removeSplitter(PyObject *args) PyObject* TopoShapePy::getElement(PyObject *args) { char* input; - if (!PyArg_ParseTuple(args, "s", &input)) + PyObject* silent = Py_False; + if (!PyArg_ParseTuple(args, "s|O", &input, &silent)) { return nullptr; - - boost::regex ex("^(Face|Edge|Vertex)[1-9][0-9]*$"); - + } try { - if (boost::regex_match(input, ex)) { - std::unique_ptr s(static_cast - (getTopoShapePtr()->getSubElementByName(input))); - TopoDS_Shape shape = s->Shape; - switch (shape.ShapeType()) { - case TopAbs_FACE: - return new TopoShapeFacePy(new TopoShape(shape)); - case TopAbs_EDGE: - return new TopoShapeEdgePy(new TopoShape(shape)); - case TopAbs_VERTEX: - return new TopoShapeVertexPy(new TopoShape(shape)); - default: - break; - } + PyObject* res = getTopoShapePtr()->getPySubShape(input, PyObject_IsTrue(silent)); + if (!res) { + Py_Return; } - - PyErr_SetString(PyExc_ValueError, "Invalid subelement name"); - return nullptr; - } - catch (Standard_Failure& e) { - PyErr_SetString(PartExceptionOCCError, e.GetMessageString()); - return nullptr; + return res; } + PY_CATCH_OCC } PyObject* TopoShapePy::countElement(PyObject *args) diff --git a/src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py b/src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py index 6b6c73db8b..3f9fa99f02 100644 --- a/src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py +++ b/src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py @@ -1455,6 +1455,27 @@ class TestTopologicalNamingProblem(unittest.TestCase): else: self.assertEqual(App.Gui.Selection.getSelectionEx("", 0)[0].SubElementNames[0][-8:],",F.Face2") + def testGetElementFunctionality(self): + # Arrange + body = self.Doc.addObject('PartDesign::Body', 'Body') + padSketch = self.Doc.addObject('Sketcher::SketchObject', 'SketchPad') + pad = self.Doc.addObject("PartDesign::Pad", "Pad") + body.addObject(padSketch) + body.addObject(pad) + TestSketcherApp.CreateRectangleSketch(padSketch, (0, 0), (1, 1)) + pad.Profile = padSketch + pad.Length = 1 + # Act + self.Doc.recompute() + if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023. + return + map = pad.Shape.ElementMap + # Assert + for tnpName in map.keys(): + element1 = body.Shape.getElement(tnpName) + element2 = body.Shape.getElement(map[tnpName]) + self.assertTrue(element1.isSame(element2)) + def testFileSaveRestore(self): # Arrange self.Body = self.Doc.addObject('PartDesign::Body', 'Body') From 2d1edacaa9249dfd8826a27a6b2ed9dd23e843aa Mon Sep 17 00:00:00 2001 From: shai Date: Thu, 4 Jul 2024 19:53:09 +0300 Subject: [PATCH 2/2] Add fixes suggested by @bgbsww --- src/Mod/Part/App/TopoShapePy.xml | 2 +- .../PartDesignTests/TestTopologicalNamingProblem.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Mod/Part/App/TopoShapePy.xml b/src/Mod/Part/App/TopoShapePy.xml index 435db55ef8..96c9ef7aa0 100644 --- a/src/Mod/Part/App/TopoShapePy.xml +++ b/src/Mod/Part/App/TopoShapePy.xml @@ -817,7 +817,7 @@ infos contains additional info on the solutions. It is a list of tuples: Returns a SubElement getElement(elementName, [silent = False]) -> Face | Edge | Vertex elementName: SubElement name - i.e. 'Edge1', 'Face3' etc. - Accepts TNP names as well + Accepts TNP mitigation mapped names as well silent: True to suppress the exception throw if the shape isn't found. diff --git a/src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py b/src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py index 3f9fa99f02..599985b10a 100644 --- a/src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py +++ b/src/Mod/PartDesign/PartDesignTests/TestTopologicalNamingProblem.py @@ -1467,13 +1467,14 @@ class TestTopologicalNamingProblem(unittest.TestCase): pad.Length = 1 # Act self.Doc.recompute() - if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023. + if pad.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023. return map = pad.Shape.ElementMap # Assert + self.assertGreater(pad.Shape.ElementMapSize,0) for tnpName in map.keys(): - element1 = body.Shape.getElement(tnpName) - element2 = body.Shape.getElement(map[tnpName]) + element1 = pad.Shape.getElement(tnpName) + element2 = pad.Shape.getElement(map[tnpName]) self.assertTrue(element1.isSame(element2)) def testFileSaveRestore(self):