diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index 6c77808ba4..451066fd73 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -1725,8 +1725,6 @@ Py::Object ObjectIdentifier::access(const ResolveResults &result, else if(lastObj) { const char *attr = components[idx].getName().c_str(); auto prop = lastObj->getPropertyByName(attr); - if(!prop && !pyobj.hasAttr(attr)) - attr = nullptr; setPropDep(lastObj,prop,attr); lastObj = nullptr; } diff --git a/src/Mod/Part/parttests/regression_tests.py b/src/Mod/Part/parttests/regression_tests.py index f58d48f890..b383b01508 100644 --- a/src/Mod/Part/parttests/regression_tests.py +++ b/src/Mod/Part/parttests/regression_tests.py @@ -1,4 +1,4 @@ -from FreeCAD import Vector +from FreeCAD import Vector, newDocument, closeDocument import Part import unittest @@ -23,3 +23,27 @@ class RegressionTests(unittest.TestCase): def test_OptimalBox(self): box = Part.makeBox(1, 1, 1) self.assertTrue(box.optimalBoundingBox(True, False).isValid()) + + def test_CircularReference(self): + # put me in def setup(self): ? + self.Doc = newDocument("TestSketchExpr") + + cube = self.Doc.addObject("Part::Box","Cube") + cube.setExpression('Length', 'Width + 10mm') + with self.assertRaises(RuntimeError) as context: + cube.setExpression('Width', 'Length + 10mm') + assert "Width reference creates a cyclic dependency." in str(context.exception) + + cube.setExpression('.Placement.Base.x', '.Placement.Base.y + 10mm') + with self.assertRaises(RuntimeError) as context: + cube.setExpression('.Placement.Base.y', '.Placement.Base.x + 10mm') + assert ".Placement.Base.y reference creates a cyclic dependency." in str(context.exception) + + cube.recompute() + v1 = cube.Placement.Base + cube.recompute() + assert cube.Placement.Base.isEqual(v1,1e-6) + + # Put me in def tearDown(self): ? + closeDocument(self.Doc.Name) + diff --git a/src/Mod/Sketcher/SketcherTests/TestSketchExpression.py b/src/Mod/Sketcher/SketcherTests/TestSketchExpression.py index 4aba472f28..8853bd4907 100644 --- a/src/Mod/Sketcher/SketcherTests/TestSketchExpression.py +++ b/src/Mod/Sketcher/SketcherTests/TestSketchExpression.py @@ -57,12 +57,26 @@ class TestSketchExpression(unittest.TestCase): sketch.addConstraint(conList) del geoList, conList + # Check that circular references get detected length = sketch.addConstraint(Sketcher.Constraint("Distance", 0, 6.0)) height = sketch.addConstraint(Sketcher.Constraint("Distance", 3, 5.0)) - sketch.renameConstraint(length, "Length") + sketch.renameConstraint(height, "Height") + sketch.setExpression("Constraints[{}]".format(height), ".Constraints.Length") + with self.assertRaises(RuntimeError) as context: + sketch.setExpression("Constraints.Length", ".Constraints.Length * 2") + assert ".Constraints.Length reference creates a cyclic dependency." in str( + context.exception + ) + + with self.assertRaises(RuntimeError) as context: + sketch.setExpression("Constraints.Length", ".Constraints.Height * 2") + assert ".Constraints.Length reference creates a cyclic dependency." in str( + context.exception + ) + def tearDown(self): # comment out to omit closing document for debugging FreeCAD.closeDocument(self.Doc.Name)