diff --git a/src/build123d/build_common.py b/src/build123d/build_common.py index c5c4f87f..0c7dfbd4 100644 --- a/src/build123d/build_common.py +++ b/src/build123d/build_common.py @@ -49,7 +49,7 @@ from abc import ABC, abstractmethod from itertools import product from math import sqrt -from typing import Callable, Iterable, Optional, Union, TypeVar +from typing import Any, Callable, Iterable, Optional, Union, TypeVar from typing_extensions import Self, ParamSpec, Concatenate from build123d.build_enums import Align, Mode, Select @@ -103,24 +103,26 @@ KG = 1000 * G LB = 453.59237 * G -T = TypeVar("T") +def _is_point(obj): + """Identify points as tuples of numbers""" + return isinstance(obj, tuple) and all( + isinstance(item, (int, float)) for item in obj + ) -def flatten_sequence(*obj: T) -> list[T]: - """Convert a sequence of object potentially containing iterables into a flat list""" - def is_point(obj): - """Identify points as tuples of numbers""" - return isinstance(obj, tuple) and all( - isinstance(item, (int, float)) for item in obj - ) +T = TypeVar("T", Any, list[Any]) + + +def flatten_sequence(*obj: T) -> list[Any]: + """Convert a sequence of object potentially containing iterables into a flat list""" flat_list = [] for item in obj: # Note: an Iterable can't be used here as it will match with Vector & Vertex # and break them into a list of floats. - if isinstance(item, (list, tuple, filter, set)) and not is_point(item): - flat_list.extend(item) + if isinstance(item, (list, tuple, filter, set)) and not _is_point(item): + flat_list.extend(flatten_sequence(*item)) else: flat_list.append(item) diff --git a/tests/test_build_common.py b/tests/test_build_common.py index 668fef1c..ef3eb331 100644 --- a/tests/test_build_common.py +++ b/tests/test_build_common.py @@ -71,6 +71,24 @@ def test_points(self): flatten_sequence("a", (1.0, 2.0, 3.0), "e"), ["a", (1.0, 2.0, 3.0), "e"] ) + def test_group_slice(self): + with BuildSketch() as s3: + Circle(55 / 2 + 3) + Rectangle(23 + 6, 42, align=(Align.CENTER, Align.MIN)) + Circle(55 / 2, mode=Mode.SUBTRACT) + Rectangle(23, 42, mode=Mode.SUBTRACT, align=(Align.CENTER, Align.MIN)) + vertex_groups = s3.vertices().group_by(Axis.Y)[0:2] + + self.assertListEqual( + flatten_sequence(vertex_groups), + [ + vertex_groups[0][0], + vertex_groups[0][1], + vertex_groups[1][0], + vertex_groups[1][1], + ], + ) + class TestBuilder(unittest.TestCase): """Test the Builder base class"""