Added Builder error handling to guide new users

This commit is contained in:
gumyr 2024-01-31 10:42:19 -05:00
parent 6e127877c2
commit 338954580e
2 changed files with 53 additions and 6 deletions

View file

@ -725,6 +725,33 @@ class Builder(ABC):
f" did you intend <keyword>={obj}?" f" did you intend <keyword>={obj}?"
) )
def _invalid_combine(self):
"""Raise an error for invalid boolean combine operations"""
raise RuntimeError(
f"{self.__class__.__name__} is a builder of Shapes and can't be "
f"combined. The object being constructed is accessible via the "
f"'{self._obj_name}' attribute."
)
def __add__(self, _other) -> Self:
"""Invalid add"""
self._invalid_combine()
def __sub__(self, _other) -> Self:
"""Invalid sub"""
self._invalid_combine()
def __and__(self, _other) -> Self:
"""Invalid and"""
self._invalid_combine()
def __getattr__(self, name):
"""The user is likely trying to reference the builder's object"""
raise AttributeError(
f"'{self.__class__.__name__}' has no attribute '{name}'. "
f"Did you intend '<{self.__class__.__name__}>.{self._obj_name}.{name}'?"
)
def validate_inputs( def validate_inputs(
context: Builder, validating_class, objects: Iterable[Shape] = None context: Builder, validating_class, objects: Iterable[Shape] = None

View file

@ -185,6 +185,29 @@ class TestBuilder(unittest.TestCase):
with BuildLine([Plane.XY, Plane.XZ]): with BuildLine([Plane.XY, Plane.XZ]):
Line((0, 0), (1, 1)) Line((0, 0), (1, 1))
def test_invalid_boolean_operations(self):
with BuildPart() as a:
Box(1, 1, 1)
with BuildPart() as b:
Cylinder(1, 1)
with self.assertRaises(RuntimeError):
c = a + b
with self.assertRaises(RuntimeError):
c = a - b
with self.assertRaises(RuntimeError):
c = a & b
def test_invalid_methods(self):
with BuildPart() as a:
Box(1, 1, 1)
with self.assertRaises(AttributeError):
a.export_stl("invalid.stl")
class TestBuilderExit(unittest.TestCase): class TestBuilderExit(unittest.TestCase):
def test_multiple(self): def test_multiple(self):
@ -223,12 +246,9 @@ class TestCommonOperations(unittest.TestCase):
def test_xor(self): def test_xor(self):
helix_loc = Edge.make_helix(2 * pi, 1, 1) ^ 0 helix_loc = Edge.make_helix(2 * pi, 1, 1) ^ 0
self.assertTupleAlmostEquals( self.assertTupleAlmostEquals(helix_loc.position.to_tuple(), (1, 0, 0), 5)
helix_loc.position.to_tuple(), (1, 0, 0), 5 self.assertTupleAlmostEquals(helix_loc.orientation.to_tuple(), (-45, 0, 180), 5)
)
self.assertTupleAlmostEquals(
helix_loc.orientation.to_tuple(), (-45, 0, 180), 5
)
class TestLocations(unittest.TestCase): class TestLocations(unittest.TestCase):
def test_polar_locations(self): def test_polar_locations(self):