diff --git a/src/build123d/topology/shape_core.py b/src/build123d/topology/shape_core.py index c506b86c..46310cab 100644 --- a/src/build123d/topology/shape_core.py +++ b/src/build123d/topology/shape_core.py @@ -2635,7 +2635,7 @@ def solids(self) -> ShapeList[Solid]: def sort_by( self, - sort_by: Axis | Callable[[T], K] | Edge | Wire | SortBy = Axis.Z, + sort_by: Axis | Callable[[T], K] | Edge | Wire | SortBy | property = Axis.Z, reverse: bool = False, ) -> ShapeList[T]: """sort by @@ -2661,6 +2661,9 @@ def sort_by( # If a callable is provided, use it directly as the key objects = sorted(self, key=sort_by, reverse=reverse) + elif isinstance(sort_by, property): + objects = sorted(self, key=sort_by.__get__, reverse=reverse) + elif isinstance(sort_by, Axis): if sort_by.wrapped is None: raise ValueError("Cannot sort by an empty axis") diff --git a/tests/test_direct_api/test_shape_list.py b/tests/test_direct_api/test_shape_list.py index 4892e5e8..c1c967ff 100644 --- a/tests/test_direct_api/test_shape_list.py +++ b/tests/test_direct_api/test_shape_list.py @@ -90,10 +90,12 @@ def test_sort_by_lambda(self): self.assertAlmostEqual(largest.area, math.pi * 2**2, 5) def test_sort_by_property(self): - box1 = Box(2, 2, 2) - box2 = Box(2, 2, 2).translate((1, 1, 1)) - assert len((box1 + box2).edges().filter_by(Edge.is_interior)) == 6 - assert len((box1 - box2).edges().filter_by(Edge.is_interior)) == 3 + box1 = Box(1, 1, 1) + box2 = Box(2, 2, 2) + box3 = Box(3, 3, 3) + unsorted_boxes = ShapeList([box2, box3, box1]) + assert unsorted_boxes.sort_by(Solid.volume) == [box1, box2, box3] + assert unsorted_boxes.sort_by(Solid.volume, reverse=True) == [box3, box2, box1] def test_sort_by_invalid(self): with self.assertRaises(ValueError): @@ -125,6 +127,12 @@ def test_filter_by_callable_predicate(self): self.assertEqual(len(shapelist.filter_by(lambda s: s.label == "A")), 2) self.assertEqual(len(shapelist.filter_by(lambda s: s.label == "B")), 1) + def test_filter_by_property(self): + box1 = Box(2, 2, 2) + box2 = Box(2, 2, 2).translate((1, 1, 1)) + assert len((box1 + box2).edges().filter_by(Edge.is_interior)) == 6 + assert len((box1 - box2).edges().filter_by(Edge.is_interior)) == 3 + def test_first_last(self): vertices = ( Solid.make_box(1, 1, 1).vertices().sort_by(Axis((0, 0, 0), (1, 1, 1)))