Architecture Docs → ABIO infra
IO¶
Entity I/O: prefix bindings, formatting, lookup, and persistence.
Overview¶
IO handles all external representation concerns for entities: prefix bindings for short names, formatting to strings, lookup by reference, and persistence via DAT. It is accessed through Context and provides the implementation for top-level load, save, lookup, and create_root functions.
| Property | Type | Description |
|---|---|---|
_prefixes |
Dict[str, Entity | str] | Prefix -> target entity or path |
_dat_entity_cache |
Dict[str, Entity] | Cache for loaded DAT entities |
prefixes |
Dict[str, Entity | str] | Current prefix bindings (read-only copy) |
orphan_root |
Entity | Root entity for orphaned entities (lazy-init) |
| Method | Returns | Description |
|---|---|---|
bind_prefix(prefix, target) |
None | Bind prefix to entity or path |
unbind_prefix(prefix) |
Entity | str | None | Remove prefix binding |
resolve_prefix(prefix) |
Entity | Get entity bound to prefix |
ref(entity, prefer_short, absolute) |
str | Get reference string for entity |
lookup(string) |
Entity | Find entity by reference string |
resolve_refs(obj) |
Any | Replace <PREFIX:path> with entities |
insert_refs(obj) |
Any | Replace entities with <PREFIX:path> |
load(path) |
Dat | Load Dat from data path |
save(obj, path) |
Dat | Save object as Dat |
Discussion¶
Prefix Conventions¶
Single-letter prefixes for common entity types:
| Prefix | Binds To | Example |
|---|---|---|
| D | Data root (always available) | D:runs/exp1.world |
| R | Current run DAT | R:world.compartment |
| W | Current world | W:compartment.glucose |
| E | Current experiment | E:run1.world |
| ORPHAN | Orphan root (auto-bound) | ORPHAN:detached_entity |
Reference Formats¶
Prefix-Relative Format: PREFIX:path
io.bind_prefix("W", world)
io.ref(glucose) # "W:cytoplasm.glucose"
io.lookup("W:cytoplasm") # -> cytoplasm entity
Absolute Format: </dat/path.entity.path>
io.ref(glucose, absolute=True) # "</runs/exp1.cytoplasm.glucose>"
io.lookup("</runs/exp1.cytoplasm>") # -> cytoplasm entity
Ref / Lookup Roundtrip¶
ref and lookup are inverses:
io.bind_prefix("W", world)
ref_str = io.ref(glucose) # "W:cytoplasm.glucose"
found = io.lookup(ref_str) # glucose entity
assert found is glucose
# Shortest prefix is used
io.bind_prefix("C", cytoplasm)
io.ref(glucose) # "C:glucose" (shorter than "W:cytoplasm.glucose")
Entity Loading with Type Dispatch¶
When loading entities from entities.yaml, IO uses the type registry:
YAML Serialization¶
Entity references use <PREFIX:path> format:
Use resolve_refs and insert_refs to convert between YAML and in-memory.
Creating Entity Trees¶
Use create_root to create a new DAT with its root entity:
from alienbio import create_root
world = create_root("runs/exp1", World, description="My experiment")
cytoplasm = Compartment("cytoplasm", parent=world, volume=1.5)
world.save() # Creates runs/exp1/entities.yaml
Method Details¶
bind_prefix(prefix: str, target: Entity | str) -> None¶
Bind a prefix to a target entity or path string.
Args:
- prefix: Short prefix string (e.g., "W", "R")
- target: Entity or path string to bind
ref(entity: Entity, prefer_short: bool = True, absolute: bool = False) -> str¶
Get reference string for entity.
Args:
- entity: Entity to get reference for
- prefer_short: If True, uses shortest matching prefix
- absolute: If True, returns </dat/path.entity.path> format
Returns: Reference string
lookup(string: str) -> Entity¶
Look up entity by reference string.
Args:
- string: Either PREFIX:path or </dat/path.entity.path>
Returns: The entity
Raises:
- KeyError: If prefix not bound or entity not found
orphan_root -> Entity (property)¶
Lazy-initialized root entity for orphaned entities. When entities are detached from their parent, they are re-parented here instead of becoming invalid. The ORPHAN: prefix is automatically bound to this root.
child.detach()
print(child) # "ORPHAN:child"
child.dat() # Returns orphan DAT (valid but can't be saved)
resolve_refs(obj: Any) -> Any¶
Recursively replace <PREFIX:path> strings with Entity objects.
Args:
- obj: Data structure to process (dict, list, or scalar)
Returns: New structure with entity references resolved
insert_refs(obj: Any) -> Any¶
Recursively replace Entity objects with <PREFIX:path> strings.
Args:
- obj: Data structure to process (dict, list, or scalar)
Returns: New structure with entities replaced by reference strings
load(path: str | Path) -> Dat¶
Load a Dat from data path.
Args:
- path: Path relative to data root, or absolute path
Returns: The loaded Dat
save(obj: Any, path: str | Path) -> Dat¶
Save object as Dat to data path.
Args:
- obj: Object to save. If dict, uses as spec. If Dat, saves in place. Otherwise wraps in {"value": obj}.
- path: Path relative to Dat.manager.sync_folder
Returns: The created or saved Dat
Protocol¶
from typing import Dict, Any, Optional, Protocol
class IO(Protocol):
"""Entity I/O: naming, formatting, lookup, persistence."""
_prefixes: Dict[str, "Entity" | str]
_dat_entity_cache: Dict[str, "Entity"]
@property
def prefixes(self) -> Dict[str, "Entity" | str]:
"""Current prefix bindings (read-only copy)."""
...
@property
def orphan_root(self) -> "Entity":
"""Root entity for orphaned entities."""
...
def bind_prefix(self, prefix: str, target: "Entity" | str) -> None:
"""Bind a prefix to a target entity or path string."""
...
def unbind_prefix(self, prefix: str) -> Optional["Entity" | str]:
"""Remove a prefix binding."""
...
def resolve_prefix(self, prefix: str) -> "Entity":
"""Get the entity bound to a prefix."""
...
def ref(
self, entity: "Entity", prefer_short: bool = True, absolute: bool = False
) -> str:
"""Get reference string for entity."""
...
def lookup(self, string: str) -> "Entity":
"""Look up entity by reference string."""
...
def resolve_refs(self, obj: Any) -> Any:
"""Replace <PREFIX:path> strings with Entity objects."""
...
def insert_refs(self, obj: Any) -> Any:
"""Replace Entity objects with <PREFIX:path> strings."""
...
def load(self, path: str) -> "Dat":
"""Load a Dat from data path."""
...
def save(self, obj: Any, path: str) -> "Dat":
"""Save object as Dat to data path."""
...