Metadata-Version: 2.4
Name: polspec
Version: 0.4.1
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Rust
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Dist: polars>=1.44.1,<2
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: pyarrow>=14.0.0 ; extra == 'arrow'
Provides-Extra: arrow
License-File: LICENSE
Summary: Declare a Polars schema once, then generate data from it and validate data against it.
Keywords: polars,schema,validation,data-generation,testing
Author-email: Maxwell Brown <maxbrown130@gmail.com>
License-Expression: MIT
Requires-Python: >=3.12
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/MaxwellB13/polspec/blob/main/CHANGELOG.md
Project-URL: Documentation, https://maxwellb13.github.io/polspec/
Project-URL: Homepage, https://maxwellb13.github.io/polspec/
Project-URL: Issues, https://github.com/MaxwellB13/polspec/issues
Project-URL: Repository, https://github.com/MaxwellB13/polspec

# polspec

Declare a [Polars](https://pola.rs) schema once. Generate data that matches
it, and validate data against it — from the same declaration.

> **Early alpha.** The API, the YAML format, and the exact values a given
> seed produces are all still moving. See
> [Roadmap and stability](https://maxwellb13.github.io/polspec/explanation/roadmap/)
> before depending on any of it.

```python
import polars as pl
from polspec import ColSpec, FrameSpec

class Orders(FrameSpec):
    order_id = ColSpec(pl.Int64, bounds=(1, None), unique=True)
    status   = ColSpec(pl.Enum(["NEW", "PAID", "SHIPPED"]))
    total    = ColSpec(pl.Float64, bounds=(0.0, None))
    placed   = ColSpec(pl.Date, nullable=True)

df = Orders.generate(1_000_000, seed=42)   # a million rows in well under a second
Orders.validate(df)                        # raises ValidationError on any breach
```

A validation library tells you when production data drifted. A fixture
library gives you something to test against. Keeping both behind one
declaration means the fixtures and the contract cannot quietly disagree — and
where they still can, it is written down in
[Known limitations](https://maxwellb13.github.io/polspec/explanation/limitations/),
each backed by a test that fails the moment it stops being true.

The generator is a Rust extension that fills columns in parallel; `validate()`
compiles every check across every column into a single Polars aggregation, so
validating a wide table costs about the same as a narrow one. Numbers, and
comparisons to NumPy and hand-written fixtures, are in
[Comparison](https://maxwellb13.github.io/polspec/explanation/comparison/).

## Install

```bash
uv add polspec           # preferred
pip install polspec      # alternative
uv add "polspec[arrow]"  # extra: PyArrow for the Parquet/IPC sinks
```

Wheels are published for Linux (x86_64, aarch64), macOS (Intel and Apple
silicon) and Windows (x86_64), so using polspec needs no Rust toolchain.
Building from a checkout is covered in [CONTRIBUTING.md](CONTRIBUTING.md).

## Documentation

Full docs: **[maxwellb13.github.io/polspec](https://maxwellb13.github.io/polspec/)**

- **Tutorial** — [Getting started](https://maxwellb13.github.io/polspec/tutorial/getting-started/) ·
  [Related tables](https://maxwellb13.github.io/polspec/tutorial/related-tables/)
- **How-to** — [Declare columns](https://maxwellb13.github.io/polspec/how-to/columns/) ·
  [Constraints](https://maxwellb13.github.io/polspec/how-to/constraints/) ·
  [Generate](https://maxwellb13.github.io/polspec/how-to/generating/) ·
  [Validate](https://maxwellb13.github.io/polspec/how-to/validating/) ·
  [Specs as files](https://maxwellb13.github.io/polspec/how-to/files/) ·
  [Command line](https://maxwellb13.github.io/polspec/how-to/cli/)
- **Reference** — [API](https://maxwellb13.github.io/polspec/reference/api/) ·
  [Errors and findings](https://maxwellb13.github.io/polspec/reference/errors/)
- **Explanation** — [Architecture](https://maxwellb13.github.io/polspec/explanation/architecture/) ·
  [Generation and validation](https://maxwellb13.github.io/polspec/explanation/two-sides/) ·
  [Known limitations](https://maxwellb13.github.io/polspec/explanation/limitations/) ·
  [Roadmap](https://maxwellb13.github.io/polspec/explanation/roadmap/)

## Development

```bash
uv run pytest
uv run ruff check . && uv run ruff format --check .
cargo test && cargo clippy --all-targets -- -D warnings
uv run --group docs zensical build --strict
uv run python examples/related_specs.py
```

`uv run --group bench python benchmarks/bench.py compare` runs the generator
benchmark; `record` then `check` guard a change against a local baseline. See [CONTRIBUTING.md](CONTRIBUTING.md) for conventions and the
release process, and [CHANGELOG.md](CHANGELOG.md) for what changed.

## License

[MIT](LICENSE).

