From 82a043a0be212b105f98847cb56559496b222db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Urba=C5=84czyk?= Date: Fri, 18 Dec 2020 08:40:24 +0100 Subject: [PATCH] Assembly hierarchy - 2nd take (#545) * Reworked nested assy querying * Support subclassing * Added docstring --- cadquery/assembly.py | 39 ++++++++++++++++++++++++++++++++++----- tests/test_assembly.py | 16 +++++++++++----- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/cadquery/assembly.py b/cadquery/assembly.py index daf6063c5..715f9d43c 100644 --- a/cadquery/assembly.py +++ b/cadquery/assembly.py @@ -21,15 +21,26 @@ ConstraintKinds = Literal["Plane", "Point", "Axis"] ExportLiterals = Literal["STEP", "XML"] +PATH_DELIM = "/" + # enitity selector grammar definiiton def _define_grammar(): - from pyparsing import Literal as Literal, Word, Optional, alphas, alphanums + from pyparsing import ( + Literal as Literal, + Word, + Optional, + alphas, + alphanums, + delimitedList, + ) Separator = Literal("@").suppress() TagSeparator = Literal("?").suppress() - Name = Word(alphas, alphanums + "_").setResultsName("name") + Name = delimitedList( + Word(alphas, alphanums + "_"), PATH_DELIM, combine=True + ).setResultsName("name") Tag = Word(alphas, alphanums + "_").setResultsName("tag") Selector = _selector_grammar.setResultsName("selector") @@ -234,6 +245,11 @@ def add(self, arg, **kwargs): if isinstance(arg, Assembly): + # enforce unique names + name = kwargs["name"] if kwargs.get("name") else arg.name + if name in self.objects: + raise ValueError("Unique name is required") + subassy = arg._copy() subassy.loc = kwargs["loc"] if kwargs.get("loc") else arg.loc @@ -242,11 +258,10 @@ def add(self, arg, **kwargs): subassy.parent = self self.children.append(subassy) - self.objects[subassy.name] = subassy - self.objects.update(subassy.objects) + self.objects.update(subassy._flatten()) else: - assy = Assembly(arg, **kwargs) + assy = self.__class__(arg, **kwargs) assy.parent = self self.add(assy) @@ -454,3 +469,17 @@ def traverse(self) -> Iterator[Tuple[str, "Assembly"]]: yield el yield (self.name, self) + + def _flatten(self, parents=[]): + """ + Generate a dict with all ancestors with keys indicating parent-child relations. + """ + + rv = {} + + for ch in self.children: + rv.update(ch._flatten(parents=parents + [self.name])) + + rv[PATH_DELIM.join(parents + [self.name])] = self + + return rv diff --git a/tests/test_assembly.py b/tests/test_assembly.py index 0a3eebecc..7addc8870 100644 --- a/tests/test_assembly.py +++ b/tests/test_assembly.py @@ -153,8 +153,8 @@ def test_constrain(simple_assy, nested_assy): assert len(simple_assy.constraints) == 3 - nested_assy.constrain("TOP@faces@>Z", "BOTTOM@faces@X", "BOTTOM@faces@Z", "SECOND/BOTTOM@faces@X", "SECOND/BOTTOM@faces@