BIM: Prevent crash when removing a wall's base component (#24633)

* BIM: Prevent crash when removing a wall's base component

When a user selected a wall's base object in the Tree View and used the
`Arch_Remove` command, a traceback occurred due to an `AttributeError`.

The `removeComponents` function was incorrectly checking for the `.Base`
attribute on a list of subtractions (`s.Base`) instead of on the parent
host object (`h.Base`).

This commit corrects the reference to check against the parent object,
resolving the crash and allowing the component to be removed.

Fixes: https://github.com/FreeCAD/FreeCAD/issues/24532

Authored-by:  furgo16 <148809153+furgo16@users.noreply.github.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: Furgo <148809153+furgo16@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
marcuspollio
2025-10-14 11:19:43 +02:00
committed by GitHub
parent 9fad915d0e
commit d0c7b427ff
2 changed files with 27 additions and 3 deletions

View File

@@ -263,9 +263,10 @@ def removeComponents(objectsList, host=None):
s.remove(o)
h.Subtractions = s
o.ViewObject.show()
elif o == s.Base:
s.Base = None
o.ViewObject.show()
elif o == h.Base:
h.Base = None
if FreeCAD.GuiUp:
o.ViewObject.show()
elif tp in ["SectionPlane"]:
a = h.Objects
if o in a:

View File

@@ -115,3 +115,26 @@ class TestArchWall(TestArchBase.TestArchBase):
wall2 = Arch.makeWall(base_line2, width=200, height=3000)
joined_wall = Arch.joinWalls([wall1, wall2])
self.assertIsNotNone(joined_wall, "joinWalls failed to join walls.")
def test_remove_base_from_wall_without_host(self):
"""
Tests that removing a wall's base using removeComponents(host=None)
does not crash and successfully unlinks the base.
This is the non-regression test for the 'list' has no attribute 'Base' bug.
https://github.com/FreeCAD/FreeCAD/issues/24532
"""
self.printTestMessage("Testing removal of a wall's base component...")
# 1. Arrange: Create a wall with a base
line = Draft.makeLine(App.Vector(0, 0, 0), App.Vector(2000, 0, 0))
wall = Arch.makeWall(line)
self.assertIsNotNone(wall.Base, "Pre-condition failed: Wall should have a base.")
# 2. Act: Call removeComponents on the base, simulating the failing workflow
# Before the fix, this will raise an AttributeError.
# After the fix, it should complete without error.
Arch.removeComponents([wall.Base])
self.document.recompute()
# 3. Assert: The base should now be None
self.assertIsNone(wall.Base, "The wall's Base property was not cleared after removal.")