Skip to content

ucon.graph

ConversionGraph implementation, ContextVar-based scoping, and conversion exceptions.

ucon.graph

Implements the ConversionGraph — the registry of unit conversion morphisms that enables Number.to() conversions.

Classes

  • :class:ConversionGraph — Stores and composes conversion Maps between units.

Functions

  • :func:get_default_graph — Get the current default graph.
  • :func:set_default_graph — Replace the default graph.
  • :func:reset_default_graph — Reset to standard graph on next access.
  • :func:using_graph — Context manager for scoped graph override.
  • :func:ucon.core._get_parsing_graph — Get the graph for name resolution during parsing.

DimensionMismatch

Bases: Exception

Raised when attempting to convert between incompatible dimensions.

ConversionNotFound

Bases: Exception

Raised when no conversion path exists between units.

CyclicInconsistency

Bases: Exception

Raised when adding an edge creates an inconsistent cycle.

ConversionGraph dataclass

Registry of conversion morphisms between units.

Stores edges between Unit nodes (partitioned by Dimension) and between UnitProduct nodes (for composite unit conversions like joule → watt_hour).

Supports: - Direct edge lookup - BFS path composition for multi-hop conversions - Factorwise decomposition for UnitProduct conversions - Graph-local unit name resolution (v0.7.3+) - Optional BasisGraph for cross-basis validation (v0.8.3+)

package_constants property

Constants materialized from loaded packages.

Returns

tuple[Constant, ...] All constants from loaded packages, in load order.

add_edge(*, src, dst, map, basis_transform=None)

Register a conversion edge. Also registers the inverse.

Parameters

src : Unit or UnitProduct Source unit expression. dst : Unit or UnitProduct Destination unit expression. map : Map The conversion morphism (src → dst). basis_transform : BasisTransform or ConstantBoundBasisTransform, optional If provided, creates a cross-basis edge. The src unit is rebased to the dst's dimension and the edge connects the rebased unit to dst.

Raises

DimensionMismatch If src and dst have different dimensions (and no basis_transform). CyclicInconsistency If the reverse edge exists and round-trip is not identity. NoTransformPath If basis_graph is set and no path exists between src/dst bases.

connect_systems(*, basis_transform, edges)

Bulk-add edges between systems.

Parameters

basis_transform : BasisTransform or ConstantBoundBasisTransform The transform bridging the two systems. edges : dict Mapping from (src_unit, dst_unit) to Map.

list_rebased_units()

Return all rebased units in the graph.

Returns

dict[Unit, list[RebasedUnit]] Mapping from original unit to its RebasedUnit(s).

list_transforms()

Return all BasisTransforms active in the graph.

Returns

list[BasisTransform] Unique transforms used by rebased units.

edges_for_transform(transform)

Return all edges that use a specific BasisTransform.

Parameters

transform : BasisTransform The transform to filter by.

Returns

list[tuple[Unit, Unit]] List of (original_unit, destination_unit) pairs.

register_unit(unit)

Register a unit for name resolution within this graph.

Populates both case-insensitive and case-sensitive registries with the unit's name, shorthand, and aliases.

Parameters

unit : Unit The unit to register.

resolve_unit(name)

Resolve a unit string in graph-local registry.

Checks case-sensitive registry first (for shorthands like 'm', 'L'), then falls back to case-insensitive lookup.

Parameters

name : str The unit name or alias to resolve.

Returns

tuple[Unit, Scale] | None (unit, Scale.one) if found, None otherwise. Caller should fall back to global registry if None.

copy()

Return a deep copy suitable for extension.

Creates independent copies of edge dictionaries and name registries. The returned graph can be modified without affecting the original.

Returns

ConversionGraph A new graph with copied state.

with_package(package)

Return a new graph with this package's units and edges added.

Creates a copy of this graph and applies the package contents. The original graph is not modified.

Parameters

package : UnitPackage Package containing unit and edge definitions.

Returns

ConversionGraph New graph with package contents added.

Example

from ucon.packages import load_package aero = load_package("aerospace.ucon.toml") graph = get_default_graph().with_package(aero)

convert(*, src, dst)

Find or compose a conversion Map from src to dst.

Parameters

src : Unit or UnitProduct Source unit expression. dst : Unit or UnitProduct Destination unit expression.

Returns

Map The conversion morphism.

Raises

DimensionMismatch If src and dst have different dimensions. ConversionNotFound If no conversion path exists.

get_default_graph()

Get the current conversion graph.

Priority: 1. Context-local graph (from using_graph) 2. Module-level default graph (lazily built)

set_default_graph(graph)

Replace the module-level default graph.

Parameters

graph : ConversionGraph The new default conversion graph.

reset_default_graph()

Reset to the standard graph on next access.

The standard graph (with all built-in unit conversions) is lazily rebuilt when :func:get_default_graph is next called.

using_graph(graph)

Context manager for scoped graph override.

Sets both the conversion graph and parsing graph contexts, so that name resolution and conversions both use the same graph.

Usage::

with using_graph(custom_graph):
    result = value.to(target)  # uses custom_graph
    unit = get_unit_by_name("custom_unit")  # resolves in custom_graph

Parameters

graph : ConversionGraph The graph to use within this context.

Yields

ConversionGraph The same graph passed in.