From c38cd45cbe8765ca204ef1dc2cd68a14d1a1813e Mon Sep 17 00:00:00 2001 From: Jonathan Wagenet Date: Wed, 17 Dec 2025 23:35:29 -0500 Subject: [PATCH] Add __format__ to Axis, Plane, Location, TOL_DIGIT for precision both str and repr --- src/build123d/geometry.py | 43 +++++++++++++++++++------- tests/test_direct_api/test_axis.py | 13 +++++--- tests/test_direct_api/test_location.py | 9 +++++- tests/test_direct_api/test_plane.py | 12 +++++++ 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/build123d/geometry.py b/src/build123d/geometry.py index adcc016..6ebc6a5 100644 --- a/src/build123d/geometry.py +++ b/src/build123d/geometry.py @@ -453,7 +453,7 @@ class Vector: if "." in spec: precision = int(spec[:-1].split(".")[-1]) else: - precision = 6 if last_char == "f" else 6 + precision = 6 if last_char == "f" else 12 x = trim_float(self.X, precision) y = trim_float(self.Y, precision) @@ -758,15 +758,23 @@ class Axis(metaclass=AxisMeta): ) ) + def __format__(self, spec) -> str: + """Format Axis""" + last_char = spec[-1] if spec else None + if last_char in ("f", "g"): + return f"({self.position:{spec}}, {self.direction:{spec}})" + + return f"({tuple(self.position)}, {tuple(self.direction)})" + def __repr__(self) -> str: """Represent Axis""" - return f"{type(self).__name__}({self.position:.13g}, {self.direction:.13g})" + return f"{type(self).__name__}{self:.{TOL_DIGITS}g}" def __str__(self) -> str: """Display Axis""" return ( f"{type(self).__name__}: " - f"(position={self.position:.6g}, direction={self.direction:.6g})" + f"(position={self.position:.{TOL_DIGITS}g}, direction={self.direction:.{TOL_DIGITS}g})" ) def __eq__(self, other: object) -> bool: @@ -1931,17 +1939,23 @@ class Location: return rv_trans, rv_rot + def __format__(self, spec) -> str: + """Format Location""" + last_char = spec[-1] if spec else None + if last_char in ("f", "g"): + return f"({self.position:{spec}}, {self.orientation:{spec}})" + + return f"({tuple(self.position)}, {tuple(self.orientation)})" + def __repr__(self) -> str: """Represent Location""" - return ( - f"{type(self).__name__}" f"({self.position:.13g}, {self.orientation:.13g})" - ) + return f"{type(self).__name__}{self:.{TOL_DIGITS}g}" def __str__(self) -> str: """Display Location""" return ( f"{type(self).__name__}: " - f"(position={self.position:.6g}, orientation={self.orientation:.6g})" + f"(position={self.position:.{TOL_DIGITS}g}, orientation={self.orientation:.{TOL_DIGITS}g})" ) @overload @@ -2863,18 +2877,23 @@ class Plane(metaclass=PlaneMeta): """intersect plane with other &""" return self.intersect(other) + def __format__(self, spec) -> str: + """Format Plane""" + last_char = spec[-1] if spec else None + if last_char in ("f", "g"): + return f"({self.origin:{spec}}, {self.x_dir:{spec}}, {self.z_dir:{spec}})" + + return f"({tuple(self.origin)}, {tuple(self.x_dir)}, {tuple(self.z_dir)})" + def __repr__(self) -> str: """Represent Plane""" - return ( - f"{type(self).__name__}" - f"({self.origin:.13g}, {self.x_dir:.13g}, {self.z_dir:.13g})" - ) + return f"{type(self).__name__}{self:.{TOL_DIGITS}g}" def __str__(self) -> str: """Display Plane""" return ( f"{type(self).__name__}: " - f"(origin={self.origin:.6g}, x_dir={self.x_dir:.6g}, z_dir={self.z_dir:.6g})" + f"(origin={self.origin:.{TOL_DIGITS}g}, x_dir={self.x_dir:.{TOL_DIGITS}g}, z_dir={self.z_dir:.{TOL_DIGITS}g})" ) def reverse(self) -> Plane: diff --git a/tests/test_direct_api/test_axis.py b/tests/test_direct_api/test_axis.py index b1c792a..ff5d06b 100644 --- a/tests/test_direct_api/test_axis.py +++ b/tests/test_direct_api/test_axis.py @@ -85,6 +85,15 @@ class TestAxis(unittest.TestCase): self.assertAlmostEqual(test_axis.direction, (0, 1, 0), 5) def test_axis_repr_and_str(self): + self.assertEqual( + f"{Axis((1, 2, 3), (4, 5, 6)):.2f}", + "((1.00, 2.00, 3.00), (0.46, 0.57, 0.68))", + ) + self.assertEqual( + f"{Axis((1, 2, 3), (4, 5, 6)):.2g}", "((1, 2, 3), (0.46, 0.57, 0.68))" + ) + self.assertIn("((1.0, 2.0, 3.0), ", f"{Axis((1, 2, 3), (4, 5, 6)):.2t}") + self.assertEqual(repr(Axis.X), "Axis((0, 0, 0), (1, 0, 0))") self.assertEqual(str(Axis.Y), "Axis: (position=(0, 0, 0), direction=(0, 1, 0))") @@ -136,10 +145,6 @@ class TestAxis(unittest.TestCase): self.assertTrue(Axis.X.is_parallel(Axis((1, 1, 1), (1, 0, 0)))) self.assertFalse(Axis.X.is_parallel(Axis.Y)) - def test_axis_is_skew(self): - self.assertTrue(Axis.X.is_skew(Axis((0, 1, 1), (0, 0, 1)))) - self.assertFalse(Axis.X.is_skew(Axis.Y)) - def test_axis_is_skew(self): # Skew Axes self.assertTrue(Axis.X.is_skew(Axis((0, 1, 1), (0, 0, 1)))) diff --git a/tests/test_direct_api/test_location.py b/tests/test_direct_api/test_location.py index 4887fd6..ecb88bf 100644 --- a/tests/test_direct_api/test_location.py +++ b/tests/test_direct_api/test_location.py @@ -228,8 +228,15 @@ class TestLocation(unittest.TestCase): def test_location_repr_and_str(self): self.assertEqual( - repr(Location()), "Location((0, 0, 0), (0, 0, 0))" + f"{Location((1, 2, 3), (4, 5, 6)):.2f}", + "((1.00, 2.00, 3.00), (4.00, 5.00, 6.00))", ) + self.assertEqual( + f"{Location((1, 2, 3), (4, 5, 6)):.2g}", "((1, 2, 3), (4, 5, 6))" + ) + self.assertIn("((1.0, 2.0, 3.0), ", f"{Location((1, 2, 3), (4, 5, 6)):.2t}") + + self.assertEqual(repr(Location()), "Location((0, 0, 0), (0, 0, 0))") self.assertEqual( str(Location()), "Location: (position=(0, 0, 0), orientation=(0, 0, 0))", diff --git a/tests/test_direct_api/test_plane.py b/tests/test_direct_api/test_plane.py index 9711c0f..474d05a 100644 --- a/tests/test_direct_api/test_plane.py +++ b/tests/test_direct_api/test_plane.py @@ -333,6 +333,18 @@ class TestPlane(unittest.TestCase): ) def test_repr(self): + self.assertEqual( + f"{Plane((1, 2, 3), (4, 5, 6), (7, 8, 9)):.2f}", + "((1.00, 2.00, 3.00), (0.46, 0.57, 0.68), (0.50, 0.57, 0.65))", + ) + self.assertEqual( + f"{Plane((1, 2, 3), (4, 5, 6), (7, 8, 9)):.2g}", + "((1, 2, 3), (0.46, 0.57, 0.68), (0.5, 0.57, 0.65))", + ) + self.assertIn( + "((1.0, 2.0, 3.0), ", f"{Plane((1, 2, 3), (4, 5, 6), (7, 8, 9)):.2t}" + ) + self.assertEqual( repr(Plane.XY), "Plane((0, 0, 0), (1, 0, 0), (0, 0, 1))",