Merge branch 'gumyr:dev' into mypy_ocp_stubs

This commit is contained in:
jdegenstein 2025-01-23 10:04:45 -06:00 committed by GitHub
commit 6c7e6988be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 34 additions and 3 deletions

View file

@ -8,6 +8,9 @@ ignore_missing_imports = True
[mypy-build123d.topology.jupyter_tools.*]
ignore_missing_imports = True
[mypy-cadquery-ocp-stubs.*]
ignore_missing_imports = True
[mypy-IPython.*]
ignore_missing_imports = True

View file

@ -2624,7 +2624,9 @@ class ShapeList(list[T]):
return ShapeList([s for shape in self for s in shape.solids()]) # type: ignore
def sort_by(
self, sort_by: Axis | Edge | Wire | SortBy = Axis.Z, reverse: bool = False
self,
sort_by: Axis | Callable[[T], K] | Edge | Wire | SortBy = Axis.Z,
reverse: bool = False,
) -> ShapeList[T]:
"""sort by
@ -2632,14 +2634,24 @@ class ShapeList(list[T]):
objects.
Args:
sort_by (SortBy, optional): sort criteria. Defaults to SortBy.Z.
sort_by (Axis | Callable[[T], K] | Edge | Wire | SortBy, optional): sort criteria.
Defaults to Axis.Z.
reverse (bool, optional): flip order of sort. Defaults to False.
Raises:
ValueError: Cannot sort by an empty axis
ValueError: Cannot sort by an empty object
ValueError: Invalid sort_by criteria provided
Returns:
ShapeList: sorted list of objects
"""
if isinstance(sort_by, Axis):
if callable(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, Axis):
if sort_by.wrapped is None:
raise ValueError("Cannot sort by an empty axis")
assert sort_by.location is not None
@ -2702,6 +2714,8 @@ class ShapeList(list[T]):
key=lambda obj: obj.volume, # type: ignore
reverse=reverse,
)
else:
raise ValueError("Invalid sort_by criteria provided")
return ShapeList(objects)

View file

@ -79,6 +79,20 @@ class TestShapeList(unittest.TestCase):
faces = Solid.make_box(1, 2, 3).faces() < SortBy.AREA
self.assertAlmostEqual(faces[-1].area, 2, 5)
def test_sort_by_lambda(self):
c = Solid.make_cone(2, 1, 2)
flat_faces = c.faces().filter_by(GeomType.PLANE)
sorted_flat_faces = flat_faces.sort_by(lambda f: f.area)
smallest = sorted_flat_faces[0]
largest = sorted_flat_faces[-1]
self.assertAlmostEqual(smallest.area, math.pi * 1**2, 5)
self.assertAlmostEqual(largest.area, math.pi * 2**2, 5)
def test_sort_by_invalid(self):
with self.assertRaises(ValueError):
Solid.make_box(1, 1, 1).faces().sort_by(">Z")
def test_filter_by_geomtype(self):
non_planar_faces = (
Solid.make_cylinder(1, 1).faces().filter_by(GeomType.PLANE, reverse=True)