From a38c5bb0850a0a28cb1371a8caa0dfa7f6505a32 Mon Sep 17 00:00:00 2001 From: jan Date: Mon, 9 Mar 2026 01:15:42 -0700 Subject: [PATCH] [ports2data] deal with cycles better --- masque/utils/ports2data.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/masque/utils/ports2data.py b/masque/utils/ports2data.py index b97b41e..889425e 100644 --- a/masque/utils/ports2data.py +++ b/masque/utils/ports2data.py @@ -57,11 +57,9 @@ def data_to_ports( name: str | None = None, # Note: name optional, but arg order different from read(postprocess=) max_depth: int = 0, skip_subcells: bool = True, - # TODO missing ok? + visited: set[int] | None = None, ) -> Pattern: """ - # TODO fixup documentation in ports2data - # TODO move to utils.file? Examine `pattern` for labels specifying port info, and use that info to fill out its `ports` attribute. @@ -70,18 +68,28 @@ def data_to_ports( Args: layers: Search for labels on all the given layers. + library: Mapping from pattern names to patterns. pattern: Pattern object to scan for labels. - max_depth: Maximum hierarcy depth to search. Default 999_999. + name: Name of the pattern object. + max_depth: Maximum hierarcy depth to search. Default 0. Reduce this to 0 to avoid ever searching subcells. skip_subcells: If port labels are found at a given hierarcy level, do not continue searching at deeper levels. This allows subcells to contain their own port info without interfering with supercells' port data. Default True. + visited: Set of object IDs which have already been processed. Returns: The updated `pattern`. Port labels are not removed. """ + if visited is None: + visited = set() + + if id(pattern) in visited: + return pattern + visited.add(id(pattern)) + if pattern.ports: logger.warning(f'Pattern {name if name else pattern} already had ports, skipping data_to_ports') return pattern @@ -99,12 +107,13 @@ def data_to_ports( if target is None: continue pp = data_to_ports( - layers=layers, - library=library, - pattern=library[target], - name=target, - max_depth=max_depth - 1, - skip_subcells=skip_subcells, + layers = layers, + library = library, + pattern = library[target], + name = target, + max_depth = max_depth - 1, + skip_subcells = skip_subcells, + visited = visited, ) found_ports |= bool(pp.ports)