From ae314cce9301afb47646fe59a957fe602205a1b4 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Wed, 1 Apr 2026 19:59:59 -0700 Subject: [PATCH] [ILibraryView] child_order shouldn't leak graphlib.CycleErrror --- masque/library.py | 10 ++++++++-- masque/test/test_library.py | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/masque/library.py b/masque/library.py index db9dda5..88799ec 100644 --- a/masque/library.py +++ b/masque/library.py @@ -22,7 +22,7 @@ import copy from pprint import pformat from collections import defaultdict from abc import ABCMeta, abstractmethod -from graphlib import TopologicalSorter +from graphlib import TopologicalSorter, CycleError import numpy from numpy.typing import ArrayLike, NDArray @@ -618,7 +618,13 @@ class ILibraryView(Mapping[str, 'Pattern'], metaclass=ABCMeta): Return: Topologically sorted list of pattern names. """ - return cast('list[str]', list(TopologicalSorter(self.child_graph(dangling=dangling)).static_order())) + try: + return cast('list[str]', list(TopologicalSorter(self.child_graph(dangling=dangling)).static_order())) + except CycleError as exc: + cycle = exc.args[1] if len(exc.args) > 1 else None + if cycle is None: + raise LibraryError('Cycle found while building child order') from exc + raise LibraryError(f'Cycle found while building child order: {cycle}') from exc def find_refs_local( self, diff --git a/masque/test/test_library.py b/masque/test/test_library.py index 56ee3d7..e66b7cc 100644 --- a/masque/test/test_library.py +++ b/masque/test/test_library.py @@ -293,6 +293,26 @@ def test_library_subtree() -> None: assert "c" not in sub +def test_library_child_order_cycle_raises_library_error() -> None: + lib = Library() + lib["a"] = Pattern() + lib["a"].ref("b") + lib["b"] = Pattern() + lib["b"].ref("a") + + with pytest.raises(LibraryError, match="Cycle found while building child order"): + lib.child_order() + + +def test_library_find_refs_global_cycle_raises_library_error() -> None: + lib = Library() + lib["a"] = Pattern() + lib["a"].ref("a") + + with pytest.raises(LibraryError, match="Cycle found while building child order"): + lib.find_refs_global("a") + + def test_library_get_name() -> None: lib = Library() lib["cell"] = Pattern()