upxo.material.registry module
registry.py
Extensible, typed, provenance-tracking container for material data.
Replaces upxo._sup.ODDict.ObjectDataDictionary, which flattened
every appended dataclass to a plain dict via dataclasses.asdict() the
instant it was stored, discarding all type information immediately and
offering no validation. MaterialRegistry keeps typed instances and
lets new data categories be declared via register_category() rather
than requiring a central build() function to be edited (import + append)
every time a category is added.
Validation is deliberately soft: unrecognized field values warn but never block, so the registry stays usable for exploratory work and materials/ processing routes not yet on any curated list – the point is catching likely typos, not gatekeeping legitimate but unanticipated input.
Usage
>>> from dataclasses import dataclass
>>> from upxo.material.registry import MaterialRegistry
>>>
>>> @dataclass
... class MaterialIdentity:
... name: str = "cu"
... alloy: str = "value"
>>>
>>> registry = MaterialRegistry()
>>> registry.register_category(
... "MaterialIdentity", MaterialIdentity,
... known_values={"name": {"OFHC-Cu", "CuCrZr"}})
>>> registry.ingest(
... "MaterialIdentity", MaterialIdentity(name="OFHC-Cu"),
... source="user input")
>>> registry.get("MaterialIdentity").name
'OFHC-Cu'
>>> registry.get_provenance("MaterialIdentity").source
'user input'
- class upxo.material.registry.MaterialRegistry[source]
Bases:
objectTyped, extensible container for material data categories.
Register dataclass types with
register_category(), store instances withingest()(soft-validates known field values), and retrieve data / provenance viaget()/get_provenance(). Built byupxo.material.Material.build()with default category set.Validation is soft: unknown values warn but never block, so exploratory materials and processing routes remain usable.
- register_category(name: str, dataclass_type: Type, known_values: Dict[str, Set[Any]] | None = None) None[source]
Declare that
namemaps todataclass_type.- Parameters:
name (str) – Category name (e.g.
"MaterialIdentity"). Conventionally the dataclass’s own class name, but not required to be – multiple categories of the same underlying type can be registered under different names if ever needed.dataclass_type (type) – The dataclass every instance ingested under this category must be an instance of.
known_values (dict, optional) – Maps field name -> a set of recognized values for that field. Used only for soft-validation warnings on
ingest()(unknown values warn, never block).
Notes
Calling this again for an already-registered
namereplaces its type/known_values – it does not merge with a prior registration.
- ingest(category: str, instance: Any, *, source: str | None = None, method: str | None = None, params: dict | None = None) None[source]
Store
instanceundercategory, with provenance.- Parameters:
category (str) – Must already be registered via
register_category().instance (Any) – Must be an instance of that category’s registered dataclass type.
source – Forwarded into a new
Provenancerecord attached to this ingestion – see that class for what each means.method – Forwarded into a new
Provenancerecord attached to this ingestion – see that class for what each means.params – Forwarded into a new
Provenancerecord attached to this ingestion – see that class for what each means.
- Raises:
- Warns:
UserWarning – For every field named in this category’s
known_values(from registration) whose current value oninstanceisn’t in the recognized set. The value is still stored – this is soft validation, not a block.
- get(category: str) Any[source]
Return the stored instance for
category.- Raises:
KeyError – If nothing has been ingested yet for
category.
- get_provenance(category: str) Provenance | None[source]
Return the
Provenancerecord forcategory, orNoneif nothing has been ingested yet for it.