Metadata-Version: 2.4
Name: ucon
Version: 1.6.2
Summary: A tool for dimensional analysis: a 'Unit CONverter'
Author-email: "Emmanuel I. Obi" <withtwoemms@gmail.com>
Maintainer-email: "Emmanuel I. Obi" <withtwoemms@gmail.com>
License: Apache-2.0
Project-URL: Homepage, https://docs.ucon.dev/
Project-URL: Repository, https://github.com/withtwoemms/ucon
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Software Development :: Build Tools
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: typing_extensions>=3.7.4; python_version < "3.9"
Requires-Dist: tomli>=2.0; python_version < "3.11"
Provides-Extra: test
Requires-Dist: coverage[toml]>=5.5; extra == "test"
Requires-Dist: pytest>=7.0; extra == "test"
Requires-Dist: numpy>=1.20; extra == "test"
Requires-Dist: pandas>=1.3; python_version >= "3.8" and extra == "test"
Requires-Dist: polars>=0.15; python_version >= "3.8" and extra == "test"
Provides-Extra: pydantic
Requires-Dist: pydantic>=2.0; extra == "pydantic"
Provides-Extra: serialization
Requires-Dist: tomli_w>=1.0; extra == "serialization"
Provides-Extra: docs
Requires-Dist: mkdocs-material; extra == "docs"
Requires-Dist: mkdocstrings[python]; extra == "docs"
Provides-Extra: numpy
Requires-Dist: numpy>=1.20; extra == "numpy"
Provides-Extra: pandas
Requires-Dist: pandas>=1.3; python_version >= "3.8" and extra == "pandas"
Provides-Extra: polars
Requires-Dist: polars>=0.15; python_version >= "3.8" and extra == "polars"
Provides-Extra: dataframe
Requires-Dist: ucon[pandas,polars]; python_version >= "3.8" and extra == "dataframe"
Provides-Extra: scientific
Requires-Dist: ucon[numpy]; extra == "scientific"
Requires-Dist: ucon[pandas,polars]; python_version >= "3.8" and extra == "scientific"
Provides-Extra: all
Requires-Dist: ucon[numpy,pydantic]; extra == "all"
Requires-Dist: ucon[pandas,polars]; python_version >= "3.8" and extra == "all"
Dynamic: license-file

<table>
  <tr>
    <td width="200">
      <img src="https://gist.githubusercontent.com/withtwoemms/0cb9e6bc8df08f326771a89eeb790f8e/raw/221c60e85ac8361c7d202896b52c1a279081b54c/ucon-logo.png" align="left" width="200" />
    </td>
    <td>

# ucon

> Pronounced: _yoo · cahn_

[![tests](https://github.com/withtwoemms/ucon/workflows/tests/badge.svg)](https://github.com/withtwoemms/ucon/actions?query=workflow%3Atests)
[![codecov](https://codecov.io/gh/withtwoemms/ucon/graph/badge.svg?token=BNONQTRJWG)](https://codecov.io/gh/withtwoemms/ucon)
[![publish](https://github.com/withtwoemms/ucon/workflows/publish/badge.svg)](https://github.com/withtwoemms/ucon/actions?query=workflow%3Apublish)

   </td>
  </tr>
</table>

> A lightweight, **unit-aware computation library** for Python — built on first-principles.

**[Documentation](https://docs.ucon.dev)** · [Quickstart](https://docs.ucon.dev/getting-started/quickstart) · [API Reference](https://docs.ucon.dev/reference/api)

---

## What is ucon?

`ucon` helps Python understand the *physical meaning* of your numbers. It treats units, dimensions, and scales as first-class objects — enforcing physics, not just labels.

```python
from ucon import units

length = units.meter(5)
time = units.second(2)

speed = length / time      # <2.5 m/s>
invalid = length + time    # raises: incompatible dimensions
```

---

## Installation

```bash
pip install ucon
```

With extras:

```bash
pip install ucon[numpy]     # NumPy array support
pip install ucon[pandas]    # Pandas DataFrame integration
pip install ucon[polars]    # Polars DataFrame integration
pip install ucon[pydantic]  # Pydantic v2 integration
pip install ucon-tools[mcp] # MCP server for AI agents (separate package)
```

---

## Quick Examples

### Parse Quantities

```python
from ucon import parse

velocity = parse("9.81 m/s^2")       # <9.81 m/s²>
measurement = parse("1.234 ± 0.005 m")  # <1.234 ± 0.005 m>
```

### Unit Conversion

```python
from ucon import units, Scale

km = Scale.kilo * units.meter
distance = km(5)

print(distance.to(units.mile))  # <3.107... mi>
```

### Dimensional Safety

```python
from ucon import Number, Dimension, enforce_dimensions

@enforce_dimensions
def speed(
    distance: Number[Dimension.length],
    time: Number[Dimension.time],
) -> Number:
    return distance / time

speed(units.meter(100), units.second(10))   # <10.0 m/s>
speed(units.second(100), units.second(10))  # raises ValueError
```

### NumPy Arrays

```python
from ucon import units

# Vectorized operations on arrays
heights = units.meter([1.7, 1.8, 1.9, 2.0])
heights_ft = heights.to(units.foot)  # <[5.577, 5.906, 6.234, 6.562] ft>

# Arithmetic with unit tracking
areas = heights * units.meter([2, 2, 2, 2])  # m^2

# Statistical reductions preserve units
avg = heights.mean()  # <1.85 m>
```

### Pydantic Integration

```python
from pydantic import BaseModel
from ucon.integrations.pydantic import Number

class Measurement(BaseModel):
    value: Number

m = Measurement(value={"quantity": 9.8, "unit": "m/s^2"})
print(m.model_dump_json())
# {"value": {"quantity": 9.8, "unit": "m/s^2", "uncertainty": null}}
```

### MCP Server for AI Agents

Install `ucon-tools` and configure in Claude Desktop:

```bash
pip install ucon-tools[mcp]
```

```json
{
  "mcpServers": {
    "ucon": {
      "command": "uvx",
      "args": ["--from", "ucon-tools[mcp]", "ucon-mcp"]
    }
  }
}
```

AI agents can then convert units, check dimensions, and perform factor-label calculations with dimensional validation at each step.

---

## Features

- **NumPy arrays** — Vectorized operations with `NumberArray` for batch computations
- **Pandas/Polars** — Unit-aware DataFrames with `NumberSeries` and `NumberColumn`
- **Physical constants** — CODATA 2022 values with uncertainty propagation (`E = m * c**2`)
- **Custom constants** — Define domain-specific constants with uncertainty propagation
- **String parsing** — `parse("9.81 m/s^2")` with uncertainty support (`1.234 ± 0.005 m`)
- **Dimensional algebra** — Units combine through multiplication/division with automatic dimension tracking
- **Scale prefixes** — Full SI (kilo, milli, micro, etc.) and binary (kibi, mebi) prefix support
- **Uncertainty propagation** — Measurement errors propagate through arithmetic and conversions; conversion factor uncertainty from measured constants (Planck, atomic) propagates on opt-in
- **Pseudo-dimensions** — Semantically isolated handling of angles, ratios, and counts
- **Natural units** — Custom dimensional bases where c=ℏ=k_B=1 for particle physics
- **Logarithmic units** — dB, pH, and neper conversions with uncertainty propagation
- **Pydantic v2** — Type-safe API validation and JSON serialization
- **MCP server** — AI agent integration with Claude, Cursor, and other MCP clients
- **ConversionGraph** — Extensible conversion registry with custom unit support

---

## Roadmap Highlights

| Version | Theme | Status |
|---------|-------|--------|
| **0.3.x** | Dimensional Algebra | Complete |
| **0.4.x** | Conversion System | Complete |
| **0.5.x** | Dimensionless Units + Uncertainty | Complete |
| **0.6.x** | Pydantic + MCP Server | Complete |
| **0.7.x** | Compute Tool + Extension API | Complete |
| **0.8.x** | Basis Abstraction + String Parsing | Complete |
| **0.9.x** | Constants + Natural Units | Complete |
| **0.10.x** | NumPy/Pandas/Polars Integration | Complete |
| **0.11.x** | Module Reorganization | Complete |
| **1.0.0** | API Stability + Units Expansion | Complete |
| **1.1.0** | Package Format Enhancements | Current |
| **1.2.0** | ConversionGraph Serialization | Planned |

See full roadmap: [ROADMAP.md](https://github.com/withtwoemms/ucon/blob/main/ROADMAP.md)

---

## Documentation

| Section | Description |
|---------|-------------|
| [Getting Started](https://docs.ucon.dev/getting-started/) | Why ucon, quickstart, installation |
| [Guides](https://docs.ucon.dev/guides/) | NumPy/Pandas/Polars, MCP server, Pydantic, custom units |
| [Reference](https://docs.ucon.dev/reference/) | API docs, unit tables, MCP tool schemas |
| [Architecture](https://docs.ucon.dev/architecture/) | Design principles, ConversionGraph, comparison with Pint |

---

## Contributing

```bash
make venv                        # Create virtual environment
source .ucon-3.12/bin/activate   # Activate
make test                        # Run tests
make test-all                    # Run tests across all Python versions
```

When modifying `ucon/dimension.py` (adding/removing dimensions), regenerate the type stubs:

```bash
make stubs                       # Regenerate ucon/dimension.pyi
make stubs-check                 # Verify stubs are current (used in CI)
```

All pull requests must include a [CHANGELOG.md](https://github.com/withtwoemms/ucon/blob/main/CHANGELOG.md) entry under the `[Unreleased]` section:

```markdown
## [Unreleased]

### Added

- Your new feature description (#PR_NUMBER)
```

Use the appropriate category: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, or `Security`.

---

## Policies

- **[Security](./SECURITY.md)** — Vulnerability reporting and dependency policy
- **[Support](./SUPPORT.md)** — Versioning, LTS, and backward-compatibility guarantees

## License

Apache 2.0. See [LICENSE](./LICENSE).
