{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"hexa","text":""},{"location":"#hexa","title":"hexa","text":""},{"location":"#hexa--summary","title":"Summary","text":"
Type-declared dependency injection for Python.
Hexa is a pattern and utility library for structuring complex hierarchical pipelines. It rests on one core idea: a concrete class's annotated slot type is the dependency decision. Variation is expressed entirely as class annotations \u2014 never as imperative wiring, never as __init__ parameters, never as a composition root that assembles objects by hand.
All utilities serialize through a single shared model (PortNode):
parse_yaml / generate_yaml \u2014 between YAML specs and the modelparse_abc / generate_abc \u2014 between ABC Python modules and the modelcheck_matches \u2014 verify two representations describe the same treebuild \u2014 recursively instantiate a wired pipeline from annotationsInstall using pip:
pip install hexa\n"},{"location":"#hexa--quick-start","title":"Quick start","text":"Define contracts, pin concrete types on the slots, and let build wire the tree from annotations:
from hexa import build\n\nclass NumberPort(ABC):\n @abstractmethod\n def extract(self, line: str) -> float: ...\n\nclass ParserPort(ABC):\n number: NumberPort\n\n @abstractmethod\n def parse(self, text: str) -> dict: ...\n\nclass RegexNumberPort(NumberPort):\n def extract(self, line: str) -> float:\n ...\n\nclass StandardParserPort(ParserPort):\n number: RegexNumberPort # <-- the dependency decision\n\n def parse(self, text: str) -> dict:\n return {\"value\": self.number.extract(text)}\n\npipeline = build(StandardParserPort)\nprint(pipeline.parse(\"Value: 42\"))\n"},{"location":"#hexa--cli-usage","title":"CLI usage","text":"Convert between YAML and ABC representations:
hexa parse-yaml spec.yaml\nhexa generate-abc spec.yaml --out spec_abc.py\nhexa parse-abc spec_abc.py\nhexa generate-yaml spec_abc.py --out spec.yaml\nhexa check spec.yaml spec_abc.py\n"},{"location":"#hexa--core-concepts","title":"Core concepts","text":""},{"location":"#hexa--shared-model","title":"Shared model","text":"PortNode \u2014 the neutral tree every parser and generator serializes through.
Parsers and generators that translate between YAML specs and ABC Python modules via the shared model.
"},{"location":"#hexa--verification","title":"Verification","text":"check_matches \u2014 machine-check that two representations agree.
build \u2014 recursively instantiate a full pipeline from class annotations.
dataclass","text":"MethodSpec(\n name: str,\n args: list[str] = list(),\n kwargs: dict[str, str] = dict(),\n)\n Specification of a single abstract method.
Attributes:
Name Type Descriptionname str Name of the method.
args list[str] Positional parameter names.
kwargs dict[str, str] Keyword-only parameter names mapped to their type expressions.
"},{"location":"#hexa.PortNode","title":"PortNodedataclass","text":"PortNode(\n name: str,\n port_cls: str,\n kind: str = \"leaf\",\n attributes: dict[str, ConfigValue] = dict(),\n children: list[PortNode] = list(),\n methods: dict[str, MethodSpec] = dict(),\n)\n A node in the hexa port tree.
Each node is a leaf (no children), a port (has nested port slots), or the parent root of the tree. Every node carries a concrete typed shape derived from an ABC class name.
Attributes:
Name Type Descriptionname str Slot name, e.g. \"parser\", \"amount_balance\".
port_cls str ABC class name that gives this port its shape, e.g. \"TransactionParserPort\". Every port has a concrete typed shape.
kind str One of \"leaf\", \"port\", or \"parent\". - \"leaf\": no children (e.g. NumberPort) - \"port\": has children (e.g. TransactionParserPort) - \"parent\": the root of the tree (e.g. ExtractionPipeline)
attributes dict[str, ConfigValue] Annotated attributes: name -> type_expr for scalars, or a nested dict of sub-attributes (a struct) for grouped values.
children list[PortNode] Nested port slots.
methods dict[str, MethodSpec] Abstract methods keyed by method name.
"},{"location":"#hexa.PortNode-functions","title":"Functions","text":""},{"location":"#hexa.PortNode.diff","title":"diff","text":"diff(other: PortNode, path: str = '') -> list[str]\n Return a list of human-readable difference strings.
An empty list means the trees are equal.
Parameters:
Name Type Description Defaultother PortNode Tree to compare against.
requiredpath str Path prefix used when recursing into nested nodes; defaults to the root path.
'' Returns:
Type Descriptionlist[str] list[str]: Human-readable difference strings, one per discrepancy.
"},{"location":"#hexa.PortNode.find","title":"find","text":"find(name: str) -> PortNode | None\n Find a direct child by slot name.
Parameters:
Name Type Description Defaultname str Slot name of the child to look up.
requiredReturns:
Type DescriptionPortNode | None PortNode | None: The matching child node, or None if no child has that name.
walk() -> list[PortNode]\n Return all nodes in depth-first order (self first).
Returns:
Type Descriptionlist[PortNode] list[PortNode]: All nodes of the tree, self first, depth-first.
"},{"location":"#hexa-functions","title":"Functions","text":""},{"location":"#hexa.build","title":"build","text":"build(\n cls: type[T],\n *,\n instances: dict[str, Any] | None = None,\n config: dict[str, Any] | None = None\n) -> T\n Recursively instantiate the port tree from annotations.
Parameters:
Name Type Description Defaultcls type[T] The root class to build (e.g. AxisExtractionPipeline).
instances dict[str, Any] | None {slot_name: object} injected verbatim into every node whose annotations contain that name (runtime values \u2014 repos, handlers, clients \u2014 that must not be re-constructed). Applied to the whole tree by name.
None config dict[str, Any] | None {field_name: value} propagated by name to every node's annotated config fields (non-port attributes), replacing the default None.
None Returns:
Name Type DescriptionT T A fully wired instance of cls and all its nested ports.
Verify that two hexa representations agree.
check_matches parses two representations \u2014 one YAML spec and/or ABC Python module each \u2014 and reports whether they describe the same port tree.
PortNode.diff to produce human-readable difference strings.check_matches(\n path_a: str | Path, path_b: str | Path\n) -> bool | list[str]\n Verify two representations agree.
Parameters:
Name Type Description Defaultpath_a str | Path Path to a .yaml or .py file.
path_b str | Path Path to a .yaml or .py file.
Returns:
Type Descriptionbool | list[str] bool | list[str]: True if they match exactly, otherwise a list of difference strings.
Command-line interface for hexa utilities.
"},{"location":"cli/#hexa.cli--usage","title":"Usage","text":"hexa parse-yaml PATH\nhexa generate-abc PATH [--out FILE]\nhexa parse-abc PATH\nhexa generate-yaml PATH [--out FILE]\nhexa check PATH_A PATH_B\n"},{"location":"cli/#hexa.cli-functions","title":"Functions","text":""},{"location":"container/","title":"Container","text":""},{"location":"container/#hexa.container","title":"hexa.container","text":""},{"location":"container/#hexa.container--summary","title":"Summary","text":"Container to build a wired hexa pipeline from annotations.
build recursively instantiates the port tree implied by a root class's annotations, injecting provided runtime instances and config values by name.
build(\n cls: type[T],\n *,\n instances: dict[str, Any] | None = None,\n config: dict[str, Any] | None = None\n) -> T\n Recursively instantiate the port tree from annotations.
Parameters:
Name Type Description Defaultcls type[T] The root class to build (e.g. AxisExtractionPipeline).
instances dict[str, Any] | None {slot_name: object} injected verbatim into every node whose annotations contain that name (runtime values \u2014 repos, handlers, clients \u2014 that must not be re-constructed). Applied to the whole tree by name.
None config dict[str, Any] | None {field_name: value} propagated by name to every node's annotated config fields (non-port attributes), replacing the default None.
None Returns:
Name Type DescriptionT T A fully wired instance of cls and all its nested ports.
Generate _abc.py source from a hexa PortNode tree.
generate_abc(\n node: PortNode, out_path: str | Path | None = None\n) -> str\n Generate ABC Python source from a :class:PortNode tree.
Parameters:
Name Type Description Defaultnode PortNode The root of the parsed YAML (or generated) tree.
requiredout_path str | Path | None Optional file path to write the generated source to.
None Returns:
Name Type Descriptionstr str The generated Python source code.
"},{"location":"generate_yaml/","title":"Generate Yaml","text":""},{"location":"generate_yaml/#hexa.generate_yaml","title":"hexa.generate_yaml","text":""},{"location":"generate_yaml/#hexa.generate_yaml--summary","title":"Summary","text":"Generate YAML spec (nested mapping form) from a hexa PortNode tree.
"},{"location":"generate_yaml/#hexa.generate_yaml-classes","title":"Classes","text":""},{"location":"generate_yaml/#hexa.generate_yaml-functions","title":"Functions","text":""},{"location":"generate_yaml/#hexa.generate_yaml.generate_yaml","title":"generate_yaml","text":"generate_yaml(\n node: PortNode, out_path: str | Path | None = None\n) -> str\n Generate YAML source from a :class:PortNode tree.
Parameters:
Name Type Description Defaultnode PortNode The root of the tree.
requiredout_path str | Path | None Optional file path to write the generated source to.
None Returns:
Name Type Descriptionstr str The generated YAML source.
"},{"location":"model/","title":"Model","text":""},{"location":"model/#hexa.model","title":"hexa.model","text":""},{"location":"model/#hexa.model--summary","title":"Summary","text":"Shared neutral model for hexa port trees.
All utilities (parse_yaml, generate_abc, parse_abc, generate_yaml, check_matches) serialize through this single model.
dataclass","text":"MethodSpec(\n name: str,\n args: list[str] = list(),\n kwargs: dict[str, str] = dict(),\n)\n Specification of a single abstract method.
Attributes:
Name Type Descriptionname str Name of the method.
args list[str] Positional parameter names.
kwargs dict[str, str] Keyword-only parameter names mapped to their type expressions.
"},{"location":"model/#hexa.model.PortNode","title":"PortNodedataclass","text":"PortNode(\n name: str,\n port_cls: str,\n kind: str = \"leaf\",\n attributes: dict[str, ConfigValue] = dict(),\n children: list[PortNode] = list(),\n methods: dict[str, MethodSpec] = dict(),\n)\n A node in the hexa port tree.
Each node is a leaf (no children), a port (has nested port slots), or the parent root of the tree. Every node carries a concrete typed shape derived from an ABC class name.
Attributes:
Name Type Descriptionname str Slot name, e.g. \"parser\", \"amount_balance\".
port_cls str ABC class name that gives this port its shape, e.g. \"TransactionParserPort\". Every port has a concrete typed shape.
kind str One of \"leaf\", \"port\", or \"parent\". - \"leaf\": no children (e.g. NumberPort) - \"port\": has children (e.g. TransactionParserPort) - \"parent\": the root of the tree (e.g. ExtractionPipeline)
attributes dict[str, ConfigValue] Annotated attributes: name -> type_expr for scalars, or a nested dict of sub-attributes (a struct) for grouped values.
children list[PortNode] Nested port slots.
methods dict[str, MethodSpec] Abstract methods keyed by method name.
"},{"location":"model/#hexa.model.PortNode-functions","title":"Functions","text":""},{"location":"model/#hexa.model.PortNode.diff","title":"diff","text":"diff(other: PortNode, path: str = '') -> list[str]\n Return a list of human-readable difference strings.
An empty list means the trees are equal.
Parameters:
Name Type Description Defaultother PortNode Tree to compare against.
requiredpath str Path prefix used when recursing into nested nodes; defaults to the root path.
'' Returns:
Type Descriptionlist[str] list[str]: Human-readable difference strings, one per discrepancy.
"},{"location":"model/#hexa.model.PortNode.find","title":"find","text":"find(name: str) -> PortNode | None\n Find a direct child by slot name.
Parameters:
Name Type Description Defaultname str Slot name of the child to look up.
requiredReturns:
Type DescriptionPortNode | None PortNode | None: The matching child node, or None if no child has that name.
walk() -> list[PortNode]\n Return all nodes in depth-first order (self first).
Returns:
Type Descriptionlist[PortNode] list[PortNode]: All nodes of the tree, self first, depth-first.
"},{"location":"parse_abc/","title":"Parse Abc","text":""},{"location":"parse_abc/#hexa.parse_abc","title":"hexa.parse_abc","text":""},{"location":"parse_abc/#hexa.parse_abc--summary","title":"Summary","text":"Parse an ABC Python module into a hexa PortNode tree.
ABC classes become port nodes. A nested-struct attribute is expressed as a @dataclass annotation on an ABC port (e.g. source: ExtractionSource where ExtractionSource is a @dataclass); the dataclass's fields are expanded into a nested attributes entry.
parse_abc(module_or_path: str | Path | Any) -> PortNode\n Parse an ABC Python module into a :class:PortNode tree.
ABC classes become port nodes. A nested-struct attribute is expressed as a @dataclass annotation on an ABC port (e.g. source: ExtractionSource where ExtractionSource is a @dataclass); the dataclass's fields are expanded into a nested attributes entry.
Parameters:
Name Type Description Defaultmodule_or_path str | Path | Any A file path to a .py file, a module import string, or a loaded module.
Returns:
Name Type DescriptionPortNode PortNode The root node of the tree.
"},{"location":"parse_yaml/","title":"Parse Yaml","text":""},{"location":"parse_yaml/#hexa.parse_yaml","title":"hexa.parse_yaml","text":""},{"location":"parse_yaml/#hexa.parse_yaml--summary","title":"Summary","text":"Parse a hexa YAML spec into a :class:PortNode tree.
The YAML grammar uses a nested mapping format built from three member kinds:
name: type scalar (e.g. source_type: str)name: mapping of sub-attributes (e.g. source:)name: mapping whose single key is a class whose value is a body, or a class key with a ... body. A port carries a class shape.A mapping with exactly one key whose value is a non-scalar body (a mapping, ..., or a list) is a port. Any other mapping (multiple keys, or all scalar-typed values) is a nested struct of attributes.
Parse a spec into a port tree:
```python\nfrom hexa import parse_yaml\n\nnode = parse_yaml(\"samples/minimal/sample.yaml\")\nprint(node)\n```\n The YAML grammar:
```yaml\nRootClassName:\n attr: type # scalar attribute\n source: # nested struct (all scalar sub-attributes)\n source_type: str\n bank: str\n methods: # reserved block of functions\n run:\n args: [a, b]\n ingest: # port (single non-scalar class key)\n IngestPort:\n source_type: str\n methods: {Method: ...}\n```\n"},{"location":"parse_yaml/#hexa.parse_yaml--notes","title":"Notes","text":"samples/minimal/sample.yaml and samples/extraction_pipeline/extraction_pipeline.yaml for worked examples.parse_yaml(path: str | Path) -> PortNode\n Parse a hexa YAML spec file into a :class:PortNode tree.
Parameters:
Name Type Description Defaultpath str | Path Path to the .yaml file.
Returns:
Name Type DescriptionPortNode PortNode The root node of the parsed tree.
Raises:
Type DescriptionValueError On structural errors in the YAML.
"}]}