Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

ucon

Pronounced: yoo · cahn A lightweight, unit-aware computation library for Python — built on first-principles.

tests codecov publish


Overview

ucon helps Python understand the physical meaning of your numbers. It combines units, scales, and dimensions into a composable algebra that supports:

  • Dimensional analysis through Number and Ratio
  • Scale-aware arithmetic and conversions
  • Metric and binary prefixes (kilo, kibi, micro, mebi, ect.)
  • A clean foundation for physics, chemistry, data modeling, and beyond

Think of it as decimal.Decimal for the physical world — precise, predictable, and type-safe.

Introduction

The crux of this tiny library is to provide abstractions that simplify the answering of questions like:

"If given two milliliters of bromine (liquid Br2), how many grams of bromine does one have?"

To best answer this question, we turn to an age-old technique (dimensional analysis) which essentially allows for the solution to be written as a product of ratios. ucon comes equipped with some useful primitives:

Type Defined In Purpose Typical Use Cases
Vector ucon.dimension Represents the exponent tuple of a physical quantity’s base dimensions (e.g., T, L, M, I, Θ, J, N). Internal representation of dimensional algebra; building derived quantities (e.g., area, velocity, force).
Dimension ucon.dimension Encapsulates physical dimensions (e.g., length, time, mass) as algebraic combinations of vectors. Enforcing dimensional consistency; defining relationships between quantities (e.g., length / time = velocity).
Unit ucon.unit Represents a named, dimensioned measurement unit (e.g., meter, second, joule). Attaching human-readable units to quantities; defining or composing new units (newton = kilogram * meter / second²).
Scale ucon.core Encodes powers of base magnitudes (binary or decimal prefixes like kilo-, milli-, mebi-). Adjusting numeric scale without changing dimension (e.g., kilometer ↔ meter, byte ↔ kibibyte).
Exponent ucon.core Represents base-power pairs (e.g., 10³, 2¹⁰) used by Scale. Performing arithmetic on powers and bases; normalizing scales across conversions.
Number ucon.core Combines a numeric quantity with a unit and scale; the primary measurable type. Performing arithmetic with units; converting between compatible units; representing physical quantities like 5 m/s.
Ratio ucon.core Represents the division of two Number objects; captures relationships between quantities. Expressing rates, densities, efficiencies (e.g., energy / time = power, length / time = velocity).
units module ucon.units Defines canonical unit instances (SI and common derived units). Quick access to standard physical units (units.meter, units.second, units.newton, etc.).

Under the Hood

ucon models unit math through a hierarchy where each layer builds on the last:

---
config:
  layout: elk
  elk:
    mergeEdges: true  # Combines parallel edges
    nodePlacementStrategy: SIMPLE # Other options: SIMPLE, NETWORK_SIMPLEX, BRANDES_KOEPF (default)
---
flowchart LR
%% --- Algebraic substrate ---
subgraph "Algebraic Substrate"
  A[Exponent] --> B[Scale]
end
%% --- Physical ontology ---
subgraph "Physical Ontology"
  D[Dimension] --> E[Unit]
end
%% --- Value layer ---
subgraph "Value Layer"
  F[Number]
  G[Ratio]
end
%% --- Cross-layer relationships ---
E --> F
B --> F
%% Ratio composes Numbers and also evaluates to a Number
F --> G
G --> F

Why ucon?

Python already has mature libraries for handling units and physical quantities — Pint, SymPy, and Unum — each solving part of the same problem from different angles:

Library Focus Limitation
Pint Runtime unit conversion and compatibility checking Treats quantities as decorated numbers — conversions work, but the algebra behind them isn’t inspectable or type-safe.
SymPy Symbolic algebra and simplification of unit expressions Excellent for symbolic reasoning, but not designed for runtime validation, conversion, or serialization.
Unum Unit-aware arithmetic and unit propagation Tracks units through arithmetic but lacks explicit dimensional algebra, conversion taxonomy, or runtime introspection.

Together, these tools can use units, but none can explicitly represent and verify the relationships between units and dimensions.

That’s the gap ucon fills.

It treats units, dimensions, and scales as first-class objects and builds a composable algebra around them. This allows you to:

  • Represent dimensional meaning explicitly (Dimension, Vector);
  • Compose and compute with type-safe, introspectable quantities (Unit, Number);
  • Perform reversible, declarative conversions (standard, linear, affine, nonlinear);
  • Serialize and validate measurements with Pydantic integration;
  • Extend the system with custom unit registries and conversion families.

Where Pint, Unum, and SymPy focus on how to compute with units, ucon focuses on why those computations make sense. Every operation checks the dimensional structure, not just the unit labels. This means ucon doesn’t just track names: it enforces physics:

from ucon import Number, units

length = Number(quantity=5, unit=units.meter)
time = Number(quantity=2, unit=units.second)

speed = length / time     # ✅ valid: L / T = velocity
invalid = length + time   # ❌ raises: incompatible dimensions

Setup

Simple:

pip install ucon

Usage

This sort of dimensional analysis:

 2 mL bromine | 3.119 g bromine
--------------x-----------------  #=> 6.238 g bromine
      1       |  1 mL bromine

becomes straightforward when you define a measurement:

from ucon import Number, Scale, Units, Ratio

# Two milliliters of bromine
two_mL_bromine = Number(unit=Units.liter, scale=Scale.milli, quantity=2)

# Density of bromine: 3.119 g/mL
bromine_density = Ratio(
    numerator=Number(unit=Units.gram, quantity=3.119),
    denominator=Number(unit=Units.liter, scale=Scale.milli),
)

# Multiply to find mass
grams_bromine = two_mL_bromine * bromine_density
print(grams_bromine)  # <6.238 gram>

Scale conversion is automatic and precise:

grams_bromine.to(Scale.milli)  # <6238.0 milligram>
grams_bromine.to(Scale.kibi)   # <0.006091796875 kibigram>

Roadmap Highlights

Version Theme Focus
0.3.x Primitive Type Refinement Unified algebraic foundation
0.4.x Conversion System Linear & affine conversions
0.6.x Nonlinear / Specialized Units Decibel, Percent, pH
0.8.x Pydantic Integration Type-safe quantity validation

See full roadmap: ROADMAP.md


Contributing

Contributions, issues, and pull requests are welcome! Ensure nox is installed.

pip install -r requirements.txt

Then run the full test suite (agains all supported python versions) before committing:

nox -s test

“If it can be measured, it can be represented. If it can be represented, it can be validated. If it can be validated, it can be trusted.”

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ucon-0.3.2rc6.tar.gz (33.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ucon-0.3.2rc6-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file ucon-0.3.2rc6.tar.gz.

File metadata

  • Download URL: ucon-0.3.2rc6.tar.gz
  • Upload date:
  • Size: 33.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ucon-0.3.2rc6.tar.gz
Algorithm Hash digest
SHA256 bfd78a7cdd67923ee5e960c97f026e926ef8bc3da4213400f74ca9cf4e21510d
MD5 725cc7dfca8eb9483f484fba7fd4aa32
BLAKE2b-256 82553a28659f61672ffa8f7deab307637014d1dd8b01d2dcb4a2fc80422b53e0

See more details on using hashes here.

File details

Details for the file ucon-0.3.2rc6-py3-none-any.whl.

File metadata

  • Download URL: ucon-0.3.2rc6-py3-none-any.whl
  • Upload date:
  • Size: 23.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ucon-0.3.2rc6-py3-none-any.whl
Algorithm Hash digest
SHA256 9bbf23c40026010d8fc9ba9074d8d02fe214834f25d68486497af8d643013937
MD5 dec318de7ee381d2e7749dc6c81d19df
BLAKE2b-256 97eb27b312b49295ac426c2754c19c4492a9e67e0e845ef2b2a6a799597a2b04

See more details on using hashes here.

Release history Release notifications | RSS feed

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page