Skip to content

ucon.kinds

Kind-of-Quantity (KOQ) sortal lattice. Records refinement relationships within a single dimension (e.g. kinetic_energy ≤ energy, equivalent_dose ≤ absorbed_dose).

See Kind-of-Quantity Problem for the conceptual framing and API › Kinds for usage.

Kind lattice: dimensional refinements for :class:~ucon.quantity.Number.

A kind refines a dimension. Energy is a dimension; kinetic energy, potential energy, and enthalpy are kinds within that dimension. Kinds form rooted trees, partitioned by dimensional equivalence class, and arithmetic that crosses the partition is governed by the kind's join_policy.

This subpackage provides storage and structural reasoning only. It is not wired into :class:~ucon.quantity.Number in v1.9.x; users build lattices, query LCAs, and test load-time validation in isolation. In v2.0.0 the lattice becomes a member of UnitSystem.

AliasCollision

Bases: KindError

An alias collides with another name or alias.

Aliases share the flat name/alias namespace with primary names. The conflict_with attribute names the existing entry.

CrossDimensionParent

Bases: KindError

A kind's declared parent has a different dimension.

The kind tree partitions by dimensional equivalence class. A parent edge across dimensions is structurally invalid.

DisjointKinds

Bases: KindError, ValueError

Two kinds belong to disjoint trees — no common ancestor exists.

Raised by :meth:KindLattice.lca when the operands' ancestor chains never intersect. Distinct roots cannot be joined; this is a verdict ("independent kinds, no conversion"), not a programming error, so it joins the :class:KindError taxonomy with left/right attributes for diagnostics. It also subclasses :class:ValueError so existing except ValueError handlers continue to work.

JoinRefused

Bases: KindError

Two sibling kinds share a parent with join_policy = REFUSE.

Raised by :meth:KindLattice.lca when the lowest common ancestor's join_policy forbids the join. The left, right, and parent attributes carry the involved kinds; the caller can use them to produce a domain-appropriate diagnostic.

KindCycle

Bases: KindError

A parent chain forms a cycle.

The cycle attribute lists the kind names that participate in the cycle, in walk order.

KindError

Bases: Exception

Base class for kind lattice errors.

KindNotFound

Bases: KindError

A kind lookup by name or alias failed.

NameCollision

Bases: KindError

Two kinds share the same primary name.

When the colliding kinds live in different fibers (their dimensions differ), the message says so and points at qualification: the flat name index refuses cross-fiber same-names in 2.x because name-only Kind.__eq__ would make lattice walks silently conflate them if they coexisted. Extending equality is a breaking change reserved for a major release; pkg:name qualification is the supported resolution today.

OrphanParent

Bases: KindError

A kind references a parent name that is not declared.

KindLattice

A collection of :class:Kind nodes with parent edges.

Parameters

kinds Initial kinds to load. Validated on construction.

Notes

The lattice owns canonical Kind instances and a flat name/alias index. Lookups by alias return the kind those aliases resolve to.

get(name)

Resolve a primary name or alias to its canonical :class:Kind.

Raises

KindNotFound If no kind or alias matches name.

names()

All registered primary names.

ancestors(kind)

Return the chain [kind, parent, grandparent, ..., root].

is_descendant(child, ancestor)

True if child is ancestor or any descendant of it.

lca(a, b)

Lowest common ancestor of a and b.

Returns the ancestor kind and the join_policy declared at that ancestor. The caller decides whether to honor the policy; a convenience :meth:join consults it directly and raises :class:JoinRefused when blocked.

Raises

KindNotFound If a or b refer to unregistered kinds. DisjointKinds If a and b belong to disjoint trees (no common ancestor). Distinct roots cannot be joined. Subclasses both :class:KindError and :class:ValueError, so pre-2.1.x except ValueError handlers keep working.

join(a, b)

LCA-based join that honors join_policy.

Equivalent kinds short-circuit to a. Otherwise consults :meth:lca; raises :class:JoinRefused when the ancestor's policy blocks the join.

register(kind)

Add a kind to an existing lattice.

Re-runs the same load-time validation. Provided primarily as a building block for parsers; users typically construct a lattice in one shot.

kinds_for_dimension(dimension)

Return all kinds registered for the given dimension.

Returns an empty list if no kinds refine the dimension.

Parameters

dimension : Dimension The dimension to query.

Returns

list[Kind] Kinds whose :attr:~Kind.dimension equals dimension.

copy()

Return an independent copy of this lattice.

The new lattice contains the same :class:Kind objects (which are frozen dataclasses) but its index dicts are independent — mutations via :meth:register on the copy do not affect the original.

JoinPolicy

Bases: Enum

Policy applied when joining sibling kinds at a parent node.

LCA lifts the result to the lowest common ancestor. REFUSE blocks the join; the operation must be expressed via a named formula instead.

Kind dataclass

A refinement within a dimensional equivalence class.

Parameters

name Primary identifier. Must be unique across the lattice's flat name/alias namespace. dimension The dimension this kind refines. All ancestors in the kind tree must share this dimension. parent The parent kind, or None for a root. join_policy Policy applied to additions of distinct descendants of this kind. Defaults to :attr:JoinPolicy.LCA. aliases Legacy or alternate names that resolve to this kind. Share the flat name/alias namespace with primary names; collisions refuse at load time.

Notes

Kind is intentionally storage-only. All structural reasoning (parent walks, LCA, validation) lives on :class:~ucon.kinds.lattice.KindLattice.

Equality and hashing key off name only. Two Kind instances with the same name are treated as the same kind, regardless of parent or join policy. This permits constructing a kind reference by name during parse before the parent is resolvable.

lca(a, b, *, lattice)

Module-level convenience for :meth:KindLattice.lca.

Takes an explicit lattice; there is no implicit global. In v2.0.0 this is the same shape as the bound method on UnitSystem.