diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0dc2f1a2..ff1e43e2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -36,7 +36,7 @@ jobs: # only. Keeping the environment small is what makes this job fast # enough to run on every push. - name: Install test dependencies - run: pip install pytest gdstk numpy pandas pydantic docopt + run: pip install pytest gdstk numpy pandas pydantic docopt 'prettyprinttree>=1.36.4,<2' 'cmd2<3' # The heavier DRC/LVS workflows run the gdsfactory backend (Python # 3.10, gdsfactory 7.7), so gdstk currently has no CI coverage at all. diff --git a/setup.py b/setup.py index c927da31..caf211cb 100644 --- a/setup.py +++ b/setup.py @@ -31,8 +31,14 @@ # `ModuleNotFoundError: No module named 'docopt'` and the deck # never runs. "docopt", - "prettyprint", - "prettyprinttree", + # `PortTree.print()` passes `default_orientation`, which PrettyPrintTree + # removed in 2.0, so an unconstrained install raises TypeError. 1.36.x + # keeps the argument but does not constrain its own `cmd2` dependency, + # and cmd2 4.x moved `cmd2.ansi`, which makes `PrettyPrint` unimportable + # — `port_utils` then silently falls back to its no-op shim. Both bounds + # are needed for the printer to actually produce output. + "prettyprinttree>=1.36.4,<2", + "cmd2<3", "gdstk", "svgutils", "nltk", diff --git a/tests/test_port_tree.py b/tests/test_port_tree.py new file mode 100644 index 00000000..73c56ce4 --- /dev/null +++ b/tests/test_port_tree.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import unittest +from pathlib import Path +from tempfile import TemporaryDirectory + + +class PortTreeTests(unittest.TestCase): + def test_print_writes_the_port_hierarchy(self) -> None: + from glayout.backend import Component + from glayout.util.port_utils import PortTree + + component = Component("demo") + component.add_port( + name="device_gate_N", + center=(0, 0), + width=1, + orientation=90, + layer=(1, 0), + ) + + with TemporaryDirectory() as directory: + output = Path(directory) / "ports.txt" + PortTree(component).print(savetofile=True, outfile_name=str(output)) + + self.assertTrue(output.is_file()) + text = output.read_text() + self.assertIn("demo", text) + self.assertIn("device", text) + self.assertIn("gate", text) + self.assertIn("N", text) + + +if __name__ == "__main__": + unittest.main()