diff --git a/hugr-py/src/hugr/__init__.py b/hugr-py/src/hugr/__init__.py index 1b0b25aea..a1f36b133 100644 --- a/hugr-py/src/hugr/__init__.py +++ b/hugr-py/src/hugr/__init__.py @@ -2,10 +2,8 @@ representation. """ -from .hugr import Hugr -from .node_port import Direction, InPort, Node, OutPort, Wire -from .ops import Op -from .tys import Kind, Type +from .hugr.base import Hugr +from .hugr.node_port import Direction, InPort, Node, OutPort, Wire __all__ = [ "Hugr", @@ -13,9 +11,6 @@ "OutPort", "InPort", "Direction", - "Op", - "Kind", - "Type", "Wire", ] diff --git a/hugr-py/src/hugr/_serialization/ops.py b/hugr-py/src/hugr/_serialization/ops.py index b2a899dc2..95b01beed 100644 --- a/hugr-py/src/hugr/_serialization/ops.py +++ b/hugr-py/src/hugr/_serialization/ops.py @@ -7,7 +7,9 @@ from pydantic import ConfigDict, Field, RootModel -from hugr.node_port import NodeIdx # noqa: TCH001 # pydantic needs this alias in scope +from hugr.hugr.node_port import ( + NodeIdx, # noqa: TCH001 # pydantic needs this alias in scope +) from hugr.utils import deser_it from . import tys as stys diff --git a/hugr-py/src/hugr/_serialization/serial_hugr.py b/hugr-py/src/hugr/_serialization/serial_hugr.py index 8ccb58f85..264a84268 100644 --- a/hugr-py/src/hugr/_serialization/serial_hugr.py +++ b/hugr-py/src/hugr/_serialization/serial_hugr.py @@ -2,7 +2,7 @@ from pydantic import ConfigDict, Field -from hugr.node_port import NodeIdx, PortOffset +from hugr.hugr.node_port import NodeIdx, PortOffset from .ops import OpType from .ops import classes as ops_classes diff --git a/hugr-py/src/hugr/build/__init__.py b/hugr-py/src/hugr/build/__init__.py new file mode 100644 index 000000000..def20437f --- /dev/null +++ b/hugr-py/src/hugr/build/__init__.py @@ -0,0 +1,24 @@ +"""Classes for building HUGRs.""" + +from .base import ParentBuilder +from .cfg import Block, Cfg +from .cond_loop import Case, Conditional, If, TailLoop +from .dfg import DefinitionBuilder, DfBase, Dfg, Function +from .function import Module +from .tracked_dfg import TrackedDfg + +__all__ = [ + "ParentBuilder", + "Cfg", + "Block", + "Case", + "If", + "Conditional", + "TailLoop", + "Function", + "Module", + "TrackedDfg", + "Dfg", + "DefinitionBuilder", + "DfBase", +] diff --git a/hugr-py/src/hugr/build/base.py b/hugr-py/src/hugr/build/base.py new file mode 100644 index 000000000..65ec280bd --- /dev/null +++ b/hugr-py/src/hugr/build/base.py @@ -0,0 +1,31 @@ +"""Base classes for HUGR builders.""" + +from __future__ import annotations + +from typing import ( + Protocol, + cast, +) + +from hugr.hugr.base import Hugr, OpVar +from hugr.hugr.node_port import ( + Node, + ToNode, +) + + +class ParentBuilder(ToNode, Protocol[OpVar]): + """Abstract interface implemented by builders of nodes that contain child HUGRs.""" + + #: The child HUGR. + hugr: Hugr[OpVar] + # Unique parent node. + parent_node: Node + + def to_node(self) -> Node: + return self.parent_node + + @property + def parent_op(self) -> OpVar: + """The parent node's operation.""" + return cast(OpVar, self.hugr[self.parent_node].op) diff --git a/hugr-py/src/hugr/cfg.py b/hugr-py/src/hugr/build/cfg.py similarity index 96% rename from hugr-py/src/hugr/cfg.py rename to hugr-py/src/hugr/build/cfg.py index 9ee06d49a..f6b9c277d 100644 --- a/hugr-py/src/hugr/cfg.py +++ b/hugr-py/src/hugr/build/cfg.py @@ -9,14 +9,14 @@ from typing_extensions import Self from hugr import ops, tys, val - -from .dfg import DfBase -from .exceptions import MismatchedExit, NoSiblingAncestor, NotInSameCfg -from .hugr import Hugr, ParentBuilder +from hugr.build.base import ParentBuilder +from hugr.build.dfg import DfBase +from hugr.exceptions import MismatchedExit, NoSiblingAncestor, NotInSameCfg +from hugr.hugr import Hugr if TYPE_CHECKING: - from .node_port import Node, PortOffset, ToNode, Wire - from .tys import Type, TypeRow + from hugr.hugr.node_port import Node, PortOffset, ToNode, Wire + from hugr.tys import Type, TypeRow class Block(DfBase[ops.DataflowBlock]): diff --git a/hugr-py/src/hugr/cond_loop.py b/hugr-py/src/hugr/build/cond_loop.py similarity index 97% rename from hugr-py/src/hugr/cond_loop.py rename to hugr-py/src/hugr/build/cond_loop.py index ca286fcc4..02b046251 100644 --- a/hugr-py/src/hugr/cond_loop.py +++ b/hugr-py/src/hugr/build/cond_loop.py @@ -11,14 +11,14 @@ from typing_extensions import Self from hugr import ops +from hugr.build.base import ParentBuilder +from hugr.build.dfg import DfBase +from hugr.hugr.base import Hugr from hugr.tys import Sum -from .dfg import DfBase -from .hugr import Hugr, ParentBuilder - if TYPE_CHECKING: - from .node_port import Node, ToNode, Wire - from .tys import TypeRow + from hugr.hugr.node_port import Node, ToNode, Wire + from hugr.tys import TypeRow class Case(DfBase[ops.Case]): diff --git a/hugr-py/src/hugr/dfg.py b/hugr-py/src/hugr/build/dfg.py similarity index 99% rename from hugr-py/src/hugr/dfg.py rename to hugr-py/src/hugr/build/dfg.py index a2b4dbb0e..8c0fb95c6 100644 --- a/hugr-py/src/hugr/dfg.py +++ b/hugr-py/src/hugr/build/dfg.py @@ -14,17 +14,18 @@ from typing_extensions import Self from hugr import ops, tys, val - -from .exceptions import NoSiblingAncestor -from .hugr import Hugr, ParentBuilder +from hugr.build.base import ParentBuilder +from hugr.exceptions import NoSiblingAncestor +from hugr.hugr import Hugr if TYPE_CHECKING: from collections.abc import Iterable, Sequence + from hugr.hugr.node_port import Node, OutPort, PortOffset, ToNode, Wire + from hugr.tys import Type, TypeParam, TypeRow + from .cfg import Cfg from .cond_loop import Conditional, If, TailLoop - from .node_port import Node, OutPort, PortOffset, ToNode, Wire - from .tys import Type, TypeParam, TypeRow OpVar = TypeVar("OpVar", bound=ops.Op) diff --git a/hugr-py/src/hugr/function.py b/hugr-py/src/hugr/build/function.py similarity index 89% rename from hugr-py/src/hugr/function.py rename to hugr-py/src/hugr/build/function.py index 8e31b50b8..97ff17d9c 100644 --- a/hugr-py/src/hugr/function.py +++ b/hugr-py/src/hugr/build/function.py @@ -5,13 +5,13 @@ from dataclasses import dataclass from typing import TYPE_CHECKING -from . import ops -from .dfg import DefinitionBuilder, Function -from .hugr import Hugr +from hugr import ops +from hugr.build.dfg import DefinitionBuilder, Function +from hugr.hugr import Hugr if TYPE_CHECKING: - from .node_port import Node - from .tys import PolyFuncType, TypeBound, TypeRow + from hugr.hugr.node_port import Node + from hugr.tys import PolyFuncType, TypeBound, TypeRow __all__ = ["Function", "Module"] diff --git a/hugr-py/src/hugr/tracked_dfg.py b/hugr-py/src/hugr/build/tracked_dfg.py similarity index 98% rename from hugr-py/src/hugr/tracked_dfg.py rename to hugr-py/src/hugr/build/tracked_dfg.py index aa8d768bd..439d5680c 100644 --- a/hugr-py/src/hugr/tracked_dfg.py +++ b/hugr-py/src/hugr/build/tracked_dfg.py @@ -4,8 +4,8 @@ from typing import Any from hugr import tys -from hugr.dfg import Dfg -from hugr.node_port import Node, Wire +from hugr.build.dfg import Dfg +from hugr.hugr.node_port import Node, Wire from hugr.ops import Command, ComWire diff --git a/hugr-py/src/hugr/conftest.py b/hugr-py/src/hugr/conftest.py index 2289f8128..daf1b82f1 100644 --- a/hugr-py/src/hugr/conftest.py +++ b/hugr-py/src/hugr/conftest.py @@ -2,7 +2,10 @@ import pytest -from hugr import dfg, hugr, node_port, ops, tys, val +from hugr import ops, tys, val +from hugr.build import dfg +from hugr.hugr import base as hugr +from hugr.hugr import node_port @pytest.fixture(autouse=True) diff --git a/hugr-py/src/hugr/exceptions.py b/hugr-py/src/hugr/exceptions.py index aa2767178..8568b3e99 100644 --- a/hugr-py/src/hugr/exceptions.py +++ b/hugr-py/src/hugr/exceptions.py @@ -2,7 +2,7 @@ from dataclasses import dataclass -from .node_port import NodeIdx +from .hugr.node_port import NodeIdx @dataclass diff --git a/hugr-py/src/hugr/hugr/__init__.py b/hugr-py/src/hugr/hugr/__init__.py new file mode 100644 index 000000000..3cbc426d7 --- /dev/null +++ b/hugr-py/src/hugr/hugr/__init__.py @@ -0,0 +1,20 @@ +"""The main HUGR structure.""" + +from .base import Hugr, NodeData +from .node_port import ( + Direction, + InPort, + Node, + OutPort, + Wire, +) + +__all__ = [ + "Hugr", + "NodeData", + "Direction", + "InPort", + "Wire", + "OutPort", + "Node", +] diff --git a/hugr-py/src/hugr/hugr.py b/hugr-py/src/hugr/hugr/base.py similarity index 97% rename from hugr-py/src/hugr/hugr.py rename to hugr-py/src/hugr/hugr/base.py index bb2926a4a..3a73a4a7e 100644 --- a/hugr-py/src/hugr/hugr.py +++ b/hugr-py/src/hugr/hugr/base.py @@ -9,7 +9,6 @@ TYPE_CHECKING, Any, Generic, - Protocol, TypeVar, cast, overload, @@ -17,7 +16,13 @@ from hugr._serialization.ops import OpType as SerialOp from hugr._serialization.serial_hugr import SerialHugr -from hugr.node_port import ( +from hugr.exceptions import ParentBeforeChild +from hugr.ops import Call, Const, Custom, DataflowOp, Module, Op +from hugr.tys import Kind, Type, ValueKind +from hugr.utils import BiMap +from hugr.val import Value + +from .node_port import ( Direction, InPort, Node, @@ -27,12 +32,6 @@ ToNode, _SubPort, ) -from hugr.ops import Call, Const, Custom, DataflowOp, Module, Op -from hugr.tys import Kind, Type, ValueKind -from hugr.utils import BiMap -from hugr.val import Value - -from .exceptions import ParentBeforeChild if TYPE_CHECKING: import graphviz as gv # type: ignore[import-untyped] @@ -69,23 +68,6 @@ def _to_serial(self, node: Node) -> SerialOp: OpVarCov = TypeVar("OpVarCov", bound=Op, covariant=True) -class ParentBuilder(ToNode, Protocol[OpVar]): - """Abstract interface implemented by builders of nodes that contain child HUGRs.""" - - #: The child HUGR. - hugr: Hugr[OpVar] - # Unique parent node. - parent_node: Node - - def to_node(self) -> Node: - return self.parent_node - - @property - def parent_op(self) -> OpVar: - """The parent node's operation.""" - return cast(OpVar, self.hugr[self.parent_node].op) - - @dataclass() class Hugr(Mapping[Node, NodeData], Generic[OpVarCov]): """The core HUGR datastructure. diff --git a/hugr-py/src/hugr/node_port.py b/hugr-py/src/hugr/hugr/node_port.py similarity index 100% rename from hugr-py/src/hugr/node_port.py rename to hugr-py/src/hugr/hugr/node_port.py diff --git a/hugr-py/src/hugr/render.py b/hugr-py/src/hugr/hugr/render.py similarity index 100% rename from hugr-py/src/hugr/render.py rename to hugr-py/src/hugr/hugr/render.py diff --git a/hugr-py/src/hugr/ops.py b/hugr-py/src/hugr/ops.py index 015385c00..65ad1623c 100644 --- a/hugr-py/src/hugr/ops.py +++ b/hugr-py/src/hugr/ops.py @@ -10,7 +10,7 @@ import hugr._serialization.ops as sops from hugr import tys, val -from hugr.node_port import Direction, InPort, Node, OutPort, PortOffset, Wire +from hugr.hugr.node_port import Direction, InPort, Node, OutPort, PortOffset, Wire from hugr.utils import ser_it if TYPE_CHECKING: diff --git a/hugr-py/tests/serialization/test_basic.py b/hugr-py/tests/serialization/test_basic.py index 57d30af73..fd9dd099c 100644 --- a/hugr-py/tests/serialization/test_basic.py +++ b/hugr-py/tests/serialization/test_basic.py @@ -1,6 +1,6 @@ from hugr import Hugr, tys from hugr._serialization.serial_hugr import SerialHugr, serialization_version -from hugr.function import Module +from hugr.build.function import Module def test_empty(): diff --git a/hugr-py/tests/test_cfg.py b/hugr-py/tests/test_cfg.py index 7bf24ab2b..14753e2f4 100644 --- a/hugr-py/tests/test_cfg.py +++ b/hugr-py/tests/test_cfg.py @@ -1,6 +1,5 @@ from hugr import ops, tys, val -from hugr.cfg import Cfg -from hugr.dfg import Dfg +from hugr.build import Cfg, Dfg from hugr.std.int import INT_T, DivMod, IntVal from .conftest import validate diff --git a/hugr-py/tests/test_cond_loop.py b/hugr-py/tests/test_cond_loop.py index 5e6a2e46c..b49ea69c6 100644 --- a/hugr-py/tests/test_cond_loop.py +++ b/hugr-py/tests/test_cond_loop.py @@ -1,8 +1,8 @@ import pytest from hugr import ops, tys, val -from hugr.cond_loop import Conditional, ConditionalError, TailLoop -from hugr.dfg import Dfg +from hugr.build.cond_loop import Conditional, ConditionalError, TailLoop +from hugr.build.dfg import Dfg from hugr.ext import Package from hugr.std.int import INT_T, IntVal diff --git a/hugr-py/tests/test_custom.py b/hugr-py/tests/test_custom.py index 7d91066c4..73ef5eea3 100644 --- a/hugr-py/tests/test_custom.py +++ b/hugr-py/tests/test_custom.py @@ -3,9 +3,8 @@ import pytest from hugr import ext, ops, tys -from hugr.dfg import Dfg -from hugr.hugr import Hugr -from hugr.node_port import Node +from hugr.build.dfg import Dfg +from hugr.hugr import Hugr, Node from hugr.ops import AsExtOp, Custom, ExtOp from hugr.std.float import EXTENSION as FLOAT_EXT from hugr.std.float import FLOAT_T diff --git a/hugr-py/tests/test_hugr_build.py b/hugr-py/tests/test_hugr_build.py index ae5b060ff..3f7145a87 100644 --- a/hugr-py/tests/test_hugr_build.py +++ b/hugr-py/tests/test_hugr_build.py @@ -5,10 +5,10 @@ import hugr.ops as ops import hugr.tys as tys import hugr.val as val -from hugr.dfg import Dfg, _ancestral_sibling -from hugr.function import Module +from hugr.build.dfg import Dfg, _ancestral_sibling +from hugr.build.function import Module from hugr.hugr import Hugr -from hugr.node_port import Node, _SubPort +from hugr.hugr.node_port import Node, _SubPort from hugr.ops import NoConcreteFunc from hugr.std.int import INT_T, DivMod, IntVal from hugr.std.logic import Not diff --git a/hugr-py/tests/test_nodes.py b/hugr-py/tests/test_nodes.py index 7fc1d30db..16c3b259a 100644 --- a/hugr-py/tests/test_nodes.py +++ b/hugr-py/tests/test_nodes.py @@ -1,6 +1,6 @@ import pytest -from hugr.node_port import Node, OutPort +from hugr.hugr import Node, OutPort def test_index(): diff --git a/hugr-py/tests/test_tracked_dfg.py b/hugr-py/tests/test_tracked_dfg.py index b558bf1c9..cac9ec0ee 100644 --- a/hugr-py/tests/test_tracked_dfg.py +++ b/hugr-py/tests/test_tracked_dfg.py @@ -1,10 +1,10 @@ import pytest from hugr import tys +from hugr.build.tracked_dfg import TrackedDfg from hugr.ext import Package from hugr.std.float import FLOAT_T, FloatVal from hugr.std.logic import Not -from hugr.tracked_dfg import TrackedDfg from .conftest import CX, QUANTUM_EXT, H, Measure, Rz, validate