This release is a pre-release and may not be stable for production use.
Nyctea
Polars-based data validation library with an extensible OOP validator architecture.
Features
Validator system
- Extensible: create custom parsers and checks by inheriting from base classes
- Type-safe: generic validator classes with runtime validation
- Discoverable: tag-based validator discovery and registration
Customizable pipeline
- Flexible: add, remove, or reorder validation phases
- Validated: strict dependency enforcement prevents invalid configurations
- Observable: built-in logging and metrics collection
Schema-centric API
- Intuitive:
schema.validate(df, registry), the schema owns validation - Pythonic: clean, object-oriented design
- Out-of-core: built on Polars
LazyFrame, designed for larger-than-RAM data
Installation
pip install nyctea
# or with uv
uv add nyctea
Quick start
import polars as pl
from nyctea import Registry, SchemaModel, register_builtins
# Define schema
schema = SchemaModel.from_dict({
"columns": {
"name": {
"dtype": "Utf8",
"parsers": [{"name": "strip"}, {"name": "lower"}],
"nullable": False,
},
"age": {
"dtype": "Int64",
"parsers": [{"name": "to_int"}],
"checks": [{"name": "min_value", "args": {"min": 0}}],
"nullable": False,
},
}
})
# Register built-in validators
registry = Registry()
register_builtins(registry)
# Load and validate data
df = pl.scan_csv("data.csv")
result = schema.validate(df, registry)
# Inspect results
print(result.report.summary())
print(result.data.collect())
Creating custom validators
Custom parser (OOP)
import polars as pl
from nyctea.validators.base import ValidatorMetadata
from nyctea.validators.column import ColumnParser
class TrimParser(ColumnParser):
def __init__(self):
super().__init__(ValidatorMetadata(
name="trim",
description="Remove whitespace",
tags=["string", "cleaning"],
))
def execute(self, column: pl.Expr, **kwargs) -> pl.Expr:
return column.str.strip_chars()
def validate_args(self, **kwargs) -> None:
pass # No arguments
registry.register_column_parser(TrimParser())
Custom check (functional)
import polars as pl
from nyctea.validators.decorators import ValidatorDecorator
decorators = ValidatorDecorator(registry)
@decorators.column_check(name="positive", tags=["numeric"])
def is_positive(column: pl.Expr) -> pl.Expr:
return column > 0
Architecture
Validator[TInput, TOutput]
├── ColumnValidator[pl.Expr, pl.Expr]
│ ├── ColumnParser (transformations)
│ └── ColumnCheck (validations)
└── FrameValidator[pl.LazyFrame, pl.LazyFrame]
├── FrameParser (transformations)
└── FrameCheck (validations)
Registry
├── column_parsers: ValidatorRegistry[ColumnParser]
├── column_checks: ValidatorRegistry[ColumnCheck]
├── frame_parsers: ValidatorRegistry[FrameParser]
└── frame_checks: ValidatorRegistry[FrameCheck]
ValidationPipeline
├── ColumnResolutionPhase (synonyms)
├── ColumnParsingPhase (transformations)
├── CoercionPhase (dtype coercion)
└── ColumnCheckPhase (checks, nullable enforcement)
Testing
uv run pytest tests/ -v
uv run pytest tests/ --cov=src/nyctea --cov-report=term --cov-report=html
uv run ruff check src/ tests/
uv run ty check src/nyctea
CI runs linting, type checking, and the test suite on Python 3.11 through 3.14 for every pull request.
Documentation
- Quickstart: getting started guide
- Features: schema syntax and validator capabilities
- Registry guide: registering and discovering validators
- API reference: full public API
- Breaking changes: migrating between versions
Contributing
Contributions are welcome. Open an issue before starting anything beyond a trivial fix; see docs/development/contributing.md for the full workflow (issue-first, branch and PR conventions, CI overview) and DEVELOPMENT.md for local setup.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nyctea-0.2.0b1.tar.gz.
File metadata
- Download URL: nyctea-0.2.0b1.tar.gz
- Upload date:
- Size: 46.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92201ab87e11a11d558966f26db7d53170c5e27851663a57798b00d6db2e1b48
|
|
| MD5 |
fa58ebf7c52cd36403e361ab64ac71b7
|
|
| BLAKE2b-256 |
d8b3df0c3e55b78a7e16f7e7c672a2a339f252b801f2fd07c0b537f0f11b4d5c
|
Provenance
The following attestation bundles were made for nyctea-0.2.0b1.tar.gz:
Publisher:
pypi-publish.yaml on yannick-vinkesteijn/nyctea
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nyctea-0.2.0b1.tar.gz -
Subject digest:
92201ab87e11a11d558966f26db7d53170c5e27851663a57798b00d6db2e1b48 - Sigstore transparency entry: 2581446274
- Sigstore integration time:
-
Permalink:
yannick-vinkesteijn/nyctea@210d617b1e8f3909e8ff3fad103c12802e47b103 -
Branch / Tag:
refs/tags/v0.2.0b1 - Owner: https://github.com/yannick-vinkesteijn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yaml@210d617b1e8f3909e8ff3fad103c12802e47b103 -
Trigger Event:
release
-
Statement type:
File details
Details for the file nyctea-0.2.0b1-py3-none-any.whl.
File metadata
- Download URL: nyctea-0.2.0b1-py3-none-any.whl
- Upload date:
- Size: 60.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a1157fa4635b6da650e89d0193077030fd5f3afa56d48012812f2774edcf3ca
|
|
| MD5 |
24bbc2a65140145c9ce9f6691241410c
|
|
| BLAKE2b-256 |
656a0b16909faf2281ab5b77b89caaea0df7aa35de37c2f8dd909d3b5fc4317d
|
Provenance
The following attestation bundles were made for nyctea-0.2.0b1-py3-none-any.whl:
Publisher:
pypi-publish.yaml on yannick-vinkesteijn/nyctea
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nyctea-0.2.0b1-py3-none-any.whl -
Subject digest:
7a1157fa4635b6da650e89d0193077030fd5f3afa56d48012812f2774edcf3ca - Sigstore transparency entry: 2581446278
- Sigstore integration time:
-
Permalink:
yannick-vinkesteijn/nyctea@210d617b1e8f3909e8ff3fad103c12802e47b103 -
Branch / Tag:
refs/tags/v0.2.0b1 - Owner: https://github.com/yannick-vinkesteijn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yaml@210d617b1e8f3909e8ff3fad103c12802e47b103 -
Trigger Event:
release
-
Statement type: