ucon.aspects¶
Aspects: the discriminator that gates combination below the kind layer. An aspect qualifies a quantity on terms its kind cannot express — the weighting standard behind a dose equivalent, the dry/wet basis of a mass fraction. Aspects are tree nodes grouped by family (the tree's root); resolution is family-wise.
See API › Aspects for usage and the Kind-of-Quantity Problem for the conceptual framing.
Aspects: the discriminator that gates combination below the kind layer.
An aspect qualifies a quantity on terms the kind cannot express: two dose equivalents — same dimension, same unit, same kind — may still be weighted per different standards, and their sum conforms to neither. Aspects are tree nodes grouped by family (the tree's root); resolution is family-wise, and the flat-set model this package shipped through v2.1.x (which could not distinguish conflict from absence) is gone.
Design record: docs/internal/decisions/008-aspect-stratum.md.
AspectError
¶
Bases: Exception
Base class for aspect stratum errors.
AspectNotApplicable
¶
Bases: AspectError
An aspect family does not apply to the quantity's kind.
Raised at attachment time — Number(...) construction or formula
load — never during resolution. The family attribute is the
family root; kind is the offending kind (or None when the
family requires a kind and none was given).
AspectRefused
¶
Bases: AspectError
An operation's operands cannot be reconciled within one family.
Two categories share this type:
- Family conflict — both operands carry positions in the family
and the lowest common ancestor's policy refuses the join
(
leftandrightare both :class:Aspect\ s). - Partial under strict — one operand carries the family and the
other is silent (the silent side is
None).
The family attribute is the family's root aspect; policy is
the join policy consulted. The payload is deliberately
warrant-shaped so a future unified refusal can wrap it losslessly.
AspectForest
¶
A collection of aspect trees, one lattice engine per family.
Construction closes over parents (passing leaves is enough),
validates root-only fields, and loads each family into its own
mirrored :class:KindLattice. All structural failures surface as
:class:AspectError.
get(name)
¶
Resolve a name to its aspect; :class:AspectError if absent.
families()
¶
The family roots, one per tree.
family_of(aspect)
¶
The family root governing aspect (registered instance).
lca(a, b)
¶
Lowest common ancestor within one family, with its policy.
Operands from different families are a caller error — resolution
groups by family before consulting the engine — and raise
:class:AspectError.
join(a, b)
¶
LCA-based join honoring the ancestor's policy.
Equal aspects short-circuit. A refuse ancestor raises
:class:AspectRefused carrying the family, both operands, and
the policy consulted.
Aspect
dataclass
¶
One node in an aspect tree.
Attributes¶
name : str
Node name. Package-declared aspects are fully qualified
("radsafe:icrp103"); root builtins are unprefixed.
parent : Aspect | None
Parent node; None marks a family root.
join_policy : JoinPolicy
Policy consulted when two positions in this family meet at this
node as their lowest common ancestor. Defaults to REFUSE —
strict matching is the zero-configuration behavior; LCA
degradation is opt-in per node.
applies_to : frozenset[str]
Root-only. Kind names this family may attach to, or {"*"}
for kind-independent families (coverage factor, calibration
status). Checked at attachment, never during resolution.
multiplication_policy : MultPolicy
Root-only. Behavior under ×/÷; see :class:MultPolicy.
MultPolicy
¶
Bases: Enum
How a family's aspects behave under multiplicative operations.
CARRY Aspects propagate onto the product/quotient whenever either operand carries them — provenance survives multiplication, so refusals outlive kind degradation. The default, and the reason the stratum is load-bearing.
resolve_add_aspects(left, right, *, strict, warn=True, op='Adding')
¶
Resolve result aspects for addition or subtraction.
Family-wise: equal carries, differing joins at LCA under the
ancestor's policy, partial refuses under strict and inherits
(with a warning, unless warn is false) otherwise.
resolve_mul_aspects(left, right, *, op='Multiplying')
¶
Resolve result aspects for multiplication or division.
Family-wise: equal carries, differing joins at LCA under the
ancestor's policy, partial follows the family root's
multiplication_policy (carry threads the present positions
onto the product). op names the operation in any refusal
message; the rules themselves are symmetric.