Use Case 2: ABC-First Contract Authoring¶
Scenario: you prefer to author contracts as Python ABC modules, then emit โ and verify โ a YAML spec for them.
๐ฆ What's New?¶
| Component | Description |
|---|---|
parse_abc |
Reflects an ABC module into the neutral PortNode tree. |
generate_yaml |
Emits a YAML spec from the tree. |
check_matches |
Verifies the two representations agree (reverse direction). |
๐ Example¶
Author the contract in Python (see samples/minimal/abc.py). A nested-struct attribute is expressed as a @dataclass annotation on an ABC port; the dataclass fields expand into a nested attributes entry when parsed:
Python
from abc import ABC, abstractmethod
class NonHexaPort1(ABC):
config_var11: str
config_var12: int
@abstractmethod
def method1(self, arg1, arg2, *, kwarg1: int = 0, kwarg2: str = "") -> str: ...
class ParentClass(ABC):
config_var1: str
config_var2: int
port1: NonHexaChildClass1
port2: HexaChildClass2
port3: HexaChildClass3
@abstractmethod
def run(self, arg1, arg2, *, kwarg1: int = 0, kwarg2: str = "") -> dict: ...
Emit the YAML spec from the module:
Inspect the parsed tree to make sure the root was detected correctly:
Bash
hexa parse-abc samples/minimal/abc.py
# PortNode(name='ParentClass', port_cls='ParentClass', kind='parent', ...)
And verify the spec against the module:
๐ก Tips¶
- Root detection:
parse_abcpicks the class that is not referenced as any other slot; on ties it prefers names containingPipeline,Root, orParent. parse_abcaccepts a.pypath, an import string (e.g.samples.minimal.abc), or an already-loaded module, so it composes well in scripts.- A
@dataclassreferenced from a port becomes a nested struct; a dataclass field that references an ABC becomes a nested port slot keyed under the struct. - YAML generated this way is exactly the grammar
parse_yamlunderstands โ the two directions round-trip (node1.diff(node3) == []in the repo's roundtrip tests).