polspec 0.1.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- polspec-0.1.5/.github/workflows/docs.yml +63 -0
- polspec-0.1.5/.github/workflows/release.yml +126 -0
- polspec-0.1.5/.github/workflows/test.yml +126 -0
- polspec-0.1.5/.gitignore +167 -0
- polspec-0.1.5/.pre-commit-config.yaml +27 -0
- polspec-0.1.5/.python-version +1 -0
- polspec-0.1.5/CHANGELOG.md +113 -0
- polspec-0.1.5/CONTRIBUTING.md +85 -0
- polspec-0.1.5/Cargo.lock +3853 -0
- polspec-0.1.5/Cargo.toml +43 -0
- polspec-0.1.5/LICENSE +21 -0
- polspec-0.1.5/PKG-INFO +195 -0
- polspec-0.1.5/README.md +165 -0
- polspec-0.1.5/benchmarks/bench_generate.py +192 -0
- polspec-0.1.5/docs/comparison.md +179 -0
- polspec-0.1.5/docs/getting-started.md +118 -0
- polspec-0.1.5/docs/guide/categories.md +169 -0
- polspec-0.1.5/docs/guide/cli.md +176 -0
- polspec-0.1.5/docs/guide/columns.md +256 -0
- polspec-0.1.5/docs/guide/constraints.md +185 -0
- polspec-0.1.5/docs/guide/documenting.md +93 -0
- polspec-0.1.5/docs/guide/generating.md +100 -0
- polspec-0.1.5/docs/guide/testing.md +203 -0
- polspec-0.1.5/docs/guide/validating.md +124 -0
- polspec-0.1.5/docs/guide/yaml.md +150 -0
- polspec-0.1.5/docs/index.md +102 -0
- polspec-0.1.5/docs/reference/architecture.md +108 -0
- polspec-0.1.5/docs/reference/limitations.md +128 -0
- polspec-0.1.5/docs/reference/roadmap.md +180 -0
- polspec-0.1.5/examples/categories.yaml +8 -0
- polspec-0.1.5/examples/products.yaml +43 -0
- polspec-0.1.5/examples/related_specs.py +212 -0
- polspec-0.1.5/pyproject.toml +105 -0
- polspec-0.1.5/python/polspec/__init__.py +24 -0
- polspec-0.1.5/python/polspec/__main__.py +6 -0
- polspec-0.1.5/python/polspec/bound.py +47 -0
- polspec-0.1.5/python/polspec/catspec.py +788 -0
- polspec-0.1.5/python/polspec/check.py +60 -0
- polspec-0.1.5/python/polspec/cli.py +567 -0
- polspec-0.1.5/python/polspec/constants.py +33 -0
- polspec-0.1.5/python/polspec/distributions.py +101 -0
- polspec-0.1.5/python/polspec/dtypes.py +134 -0
- polspec-0.1.5/python/polspec/engine.py +408 -0
- polspec-0.1.5/python/polspec/foreign_key.py +176 -0
- polspec-0.1.5/python/polspec/framespec.py +1507 -0
- polspec-0.1.5/python/polspec/profiler.py +196 -0
- polspec-0.1.5/python/polspec/py.typed +0 -0
- polspec-0.1.5/python/polspec/report.py +414 -0
- polspec-0.1.5/python/polspec/rules.py +241 -0
- polspec-0.1.5/python/polspec/serialization.py +388 -0
- polspec-0.1.5/python/polspec/spec.py +375 -0
- polspec-0.1.5/python/polspec/validation.py +707 -0
- polspec-0.1.5/src/lib.rs +717 -0
- polspec-0.1.5/tests/test_catspec.py +648 -0
- polspec-0.1.5/tests/test_cli.py +348 -0
- polspec-0.1.5/tests/test_declaration.py +377 -0
- polspec-0.1.5/tests/test_foreign_key.py +390 -0
- polspec-0.1.5/tests/test_framespec.py +314 -0
- polspec-0.1.5/tests/test_generation.py +479 -0
- polspec-0.1.5/tests/test_profiler.py +234 -0
- polspec-0.1.5/tests/test_report.py +131 -0
- polspec-0.1.5/tests/test_roundtrip.py +647 -0
- polspec-0.1.5/tests/test_rules.py +232 -0
- polspec-0.1.5/tests/test_serialization.py +399 -0
- polspec-0.1.5/tests/test_streaming.py +199 -0
- polspec-0.1.5/tests/test_validation.py +923 -0
- polspec-0.1.5/uv.lock +531 -0
- polspec-0.1.5/zensical.toml +102 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- "docs/**"
|
|
9
|
+
- "zensical.toml"
|
|
10
|
+
- "README.md"
|
|
11
|
+
- ".github/workflows/docs.yml"
|
|
12
|
+
pull_request:
|
|
13
|
+
paths:
|
|
14
|
+
- "docs/**"
|
|
15
|
+
- "zensical.toml"
|
|
16
|
+
- "README.md"
|
|
17
|
+
- ".github/workflows/docs.yml"
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build:
|
|
24
|
+
# Runs on pull requests too, so a broken link fails before merge rather
|
|
25
|
+
# than after. Only the push to main deploys.
|
|
26
|
+
name: Build (strict)
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7
|
|
30
|
+
|
|
31
|
+
- name: Install uv
|
|
32
|
+
uses: astral-sh/setup-uv@v7
|
|
33
|
+
with:
|
|
34
|
+
python-version: "3.13"
|
|
35
|
+
|
|
36
|
+
# zensical is pinned by uv.lock through the docs group.
|
|
37
|
+
- name: Install docs tooling
|
|
38
|
+
run: uv sync --only-group docs --no-install-project
|
|
39
|
+
|
|
40
|
+
- name: Build site
|
|
41
|
+
run: uv run --no-sync zensical build --clean --strict
|
|
42
|
+
|
|
43
|
+
- name: Upload site
|
|
44
|
+
if: github.event_name == 'push'
|
|
45
|
+
uses: actions/upload-pages-artifact@v5
|
|
46
|
+
with:
|
|
47
|
+
path: site
|
|
48
|
+
|
|
49
|
+
deploy:
|
|
50
|
+
name: Deploy to GitHub Pages
|
|
51
|
+
if: github.event_name == 'push'
|
|
52
|
+
needs: build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
permissions:
|
|
55
|
+
pages: write
|
|
56
|
+
id-token: write
|
|
57
|
+
environment:
|
|
58
|
+
name: github-pages
|
|
59
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/configure-pages@v6
|
|
62
|
+
- uses: actions/deploy-pages@v5
|
|
63
|
+
id: deployment
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
check-version:
|
|
10
|
+
name: Tag matches pyproject.toml version
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v7
|
|
14
|
+
- name: Compare tag to pyproject.toml
|
|
15
|
+
run: |
|
|
16
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
17
|
+
declared="$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')"
|
|
18
|
+
if [ "$tag" != "$declared" ]; then
|
|
19
|
+
echo "Tag v$tag does not match pyproject.toml version $declared" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# A tag publishes nothing unless the full test workflow is green.
|
|
24
|
+
test:
|
|
25
|
+
name: Test
|
|
26
|
+
needs: check-version
|
|
27
|
+
uses: ./.github/workflows/test.yml
|
|
28
|
+
|
|
29
|
+
build:
|
|
30
|
+
name: Build wheel (${{ matrix.os }}, ${{ matrix.target }})
|
|
31
|
+
needs: [check-version, test]
|
|
32
|
+
runs-on: ${{ matrix.os }}
|
|
33
|
+
strategy:
|
|
34
|
+
fail-fast: false
|
|
35
|
+
matrix:
|
|
36
|
+
include:
|
|
37
|
+
- os: ubuntu-latest
|
|
38
|
+
target: x86_64
|
|
39
|
+
- os: ubuntu-24.04-arm
|
|
40
|
+
target: aarch64
|
|
41
|
+
- os: macos-latest
|
|
42
|
+
target: aarch64
|
|
43
|
+
- os: macos-latest
|
|
44
|
+
target: x86_64
|
|
45
|
+
- os: windows-latest
|
|
46
|
+
target: x86_64
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v7
|
|
50
|
+
|
|
51
|
+
# One abi3 wheel per platform covers every supported CPython version.
|
|
52
|
+
- name: Build wheel
|
|
53
|
+
uses: PyO3/maturin-action@v1
|
|
54
|
+
with:
|
|
55
|
+
command: build
|
|
56
|
+
target: ${{ matrix.target }}
|
|
57
|
+
manylinux: auto
|
|
58
|
+
args: --release --out dist
|
|
59
|
+
sccache: "true"
|
|
60
|
+
|
|
61
|
+
- name: Upload wheel artifact
|
|
62
|
+
uses: actions/upload-artifact@v7
|
|
63
|
+
with:
|
|
64
|
+
name: wheels-${{ matrix.os }}-${{ matrix.target }}
|
|
65
|
+
path: dist/*.whl
|
|
66
|
+
|
|
67
|
+
sdist:
|
|
68
|
+
name: Build sdist
|
|
69
|
+
needs: [check-version, test]
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v7
|
|
73
|
+
|
|
74
|
+
- name: Build sdist
|
|
75
|
+
uses: PyO3/maturin-action@v1
|
|
76
|
+
with:
|
|
77
|
+
command: sdist
|
|
78
|
+
args: --out dist
|
|
79
|
+
|
|
80
|
+
- name: Upload sdist artifact
|
|
81
|
+
uses: actions/upload-artifact@v7
|
|
82
|
+
with:
|
|
83
|
+
name: wheels-sdist
|
|
84
|
+
path: dist/*.tar.gz
|
|
85
|
+
|
|
86
|
+
publish-pypi:
|
|
87
|
+
name: Publish to PyPI
|
|
88
|
+
needs: [build, sdist]
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
environment: pypi
|
|
91
|
+
permissions:
|
|
92
|
+
id-token: write
|
|
93
|
+
steps:
|
|
94
|
+
- name: Download all artifacts
|
|
95
|
+
uses: actions/download-artifact@v8
|
|
96
|
+
with:
|
|
97
|
+
pattern: wheels-*
|
|
98
|
+
path: dist
|
|
99
|
+
merge-multiple: true
|
|
100
|
+
|
|
101
|
+
- name: Publish to PyPI
|
|
102
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
103
|
+
with:
|
|
104
|
+
packages-dir: dist
|
|
105
|
+
skip-existing: true
|
|
106
|
+
|
|
107
|
+
release:
|
|
108
|
+
name: Attach artifacts to GitHub Release
|
|
109
|
+
needs: [build, sdist]
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
permissions:
|
|
112
|
+
contents: write
|
|
113
|
+
steps:
|
|
114
|
+
- name: Download all artifacts
|
|
115
|
+
uses: actions/download-artifact@v8
|
|
116
|
+
with:
|
|
117
|
+
pattern: wheels-*
|
|
118
|
+
path: dist
|
|
119
|
+
merge-multiple: true
|
|
120
|
+
|
|
121
|
+
- name: Upload to GitHub Release
|
|
122
|
+
uses: softprops/action-gh-release@v3
|
|
123
|
+
with:
|
|
124
|
+
files: |
|
|
125
|
+
dist/*.whl
|
|
126
|
+
dist/*.tar.gz
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_call:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
name: Lint (ruff)
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v7
|
|
15
|
+
|
|
16
|
+
- name: Install uv
|
|
17
|
+
uses: astral-sh/setup-uv@v7
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.13"
|
|
20
|
+
|
|
21
|
+
# The project itself is not installed: linting needs no Rust build.
|
|
22
|
+
- name: Sync dev dependencies
|
|
23
|
+
run: uv sync --no-install-project
|
|
24
|
+
|
|
25
|
+
- name: ruff check
|
|
26
|
+
run: uv run --no-sync ruff check .
|
|
27
|
+
|
|
28
|
+
- name: ruff format
|
|
29
|
+
run: uv run --no-sync ruff format --check .
|
|
30
|
+
|
|
31
|
+
rust:
|
|
32
|
+
name: Rust (fmt, clippy, test)
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v7
|
|
36
|
+
|
|
37
|
+
- name: Install Rust
|
|
38
|
+
uses: dtolnay/rust-toolchain@stable
|
|
39
|
+
with:
|
|
40
|
+
components: rustfmt, clippy
|
|
41
|
+
|
|
42
|
+
- name: Cache Rust build
|
|
43
|
+
uses: Swatinem/rust-cache@v2
|
|
44
|
+
|
|
45
|
+
- name: Install Python (the pyo3 build script needs an interpreter)
|
|
46
|
+
uses: actions/setup-python@v7
|
|
47
|
+
with:
|
|
48
|
+
python-version: "3.13"
|
|
49
|
+
|
|
50
|
+
- name: cargo fmt
|
|
51
|
+
run: cargo fmt --check
|
|
52
|
+
|
|
53
|
+
- name: cargo clippy
|
|
54
|
+
run: cargo clippy --release -- -D warnings
|
|
55
|
+
|
|
56
|
+
- name: cargo test
|
|
57
|
+
run: cargo test --release
|
|
58
|
+
|
|
59
|
+
test:
|
|
60
|
+
name: Test (${{ matrix.os }}, py${{ matrix.python-version }})
|
|
61
|
+
runs-on: ${{ matrix.os }}
|
|
62
|
+
strategy:
|
|
63
|
+
fail-fast: false
|
|
64
|
+
matrix:
|
|
65
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
66
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
67
|
+
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v7
|
|
70
|
+
|
|
71
|
+
- name: Install Rust
|
|
72
|
+
uses: dtolnay/rust-toolchain@stable
|
|
73
|
+
|
|
74
|
+
- name: Cache Rust build
|
|
75
|
+
uses: Swatinem/rust-cache@v2
|
|
76
|
+
|
|
77
|
+
- name: Install uv
|
|
78
|
+
uses: astral-sh/setup-uv@v7
|
|
79
|
+
with:
|
|
80
|
+
python-version: ${{ matrix.python-version }}
|
|
81
|
+
|
|
82
|
+
- name: Sync dependencies
|
|
83
|
+
run: uv sync --all-extras
|
|
84
|
+
|
|
85
|
+
- name: Build extension (maturin develop)
|
|
86
|
+
run: uv run maturin develop --release
|
|
87
|
+
|
|
88
|
+
- name: Run tests
|
|
89
|
+
run: uv run pytest
|
|
90
|
+
|
|
91
|
+
- name: Run the worked example as a smoke test
|
|
92
|
+
run: uv run python examples/related_specs.py
|
|
93
|
+
|
|
94
|
+
polars-latest:
|
|
95
|
+
# uv.lock pins one Polars release; this job catches a break in the newest
|
|
96
|
+
# release that still satisfies the bound declared in pyproject.toml.
|
|
97
|
+
name: Test (ubuntu, py3.13, newest polars)
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
steps:
|
|
100
|
+
- uses: actions/checkout@v7
|
|
101
|
+
|
|
102
|
+
- name: Install Rust
|
|
103
|
+
uses: dtolnay/rust-toolchain@stable
|
|
104
|
+
|
|
105
|
+
- name: Cache Rust build
|
|
106
|
+
uses: Swatinem/rust-cache@v2
|
|
107
|
+
|
|
108
|
+
- name: Install uv
|
|
109
|
+
uses: astral-sh/setup-uv@v7
|
|
110
|
+
with:
|
|
111
|
+
python-version: "3.13"
|
|
112
|
+
|
|
113
|
+
- name: Upgrade polars within the declared bound
|
|
114
|
+
run: uv lock --upgrade-package polars
|
|
115
|
+
|
|
116
|
+
- name: Sync dependencies
|
|
117
|
+
run: uv sync --all-extras
|
|
118
|
+
|
|
119
|
+
- name: Report polars version
|
|
120
|
+
run: uv run python -c "import polars; print(polars.__version__)"
|
|
121
|
+
|
|
122
|
+
- name: Build extension (maturin develop)
|
|
123
|
+
run: uv run maturin develop --release
|
|
124
|
+
|
|
125
|
+
- name: Run tests
|
|
126
|
+
run: uv run pytest
|
polspec-0.1.5/.gitignore
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
### Python template
|
|
2
|
+
# Byte-compiled / optimized / DLL files
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.py[cod]
|
|
5
|
+
*$py.class
|
|
6
|
+
|
|
7
|
+
# C extensions
|
|
8
|
+
*.so
|
|
9
|
+
|
|
10
|
+
# Distribution / packaging
|
|
11
|
+
.Python
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
*.py,cover
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
#Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# poetry
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
103
|
+
#poetry.lock
|
|
104
|
+
|
|
105
|
+
# pdm
|
|
106
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
107
|
+
#pdm.lock
|
|
108
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
109
|
+
# in version control.
|
|
110
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
111
|
+
.pdm.toml
|
|
112
|
+
.pdm-python
|
|
113
|
+
.pdm-build/
|
|
114
|
+
|
|
115
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
116
|
+
__pypackages__/
|
|
117
|
+
|
|
118
|
+
# Celery stuff
|
|
119
|
+
celerybeat-schedule
|
|
120
|
+
celerybeat.pid
|
|
121
|
+
|
|
122
|
+
# SageMath parsed files
|
|
123
|
+
*.sage.py
|
|
124
|
+
|
|
125
|
+
# Environments
|
|
126
|
+
.env
|
|
127
|
+
.venv
|
|
128
|
+
env/
|
|
129
|
+
venv/
|
|
130
|
+
ENV/
|
|
131
|
+
env.bak/
|
|
132
|
+
venv.bak/
|
|
133
|
+
|
|
134
|
+
# Spyder project settings
|
|
135
|
+
.spyderproject
|
|
136
|
+
.spyproject
|
|
137
|
+
|
|
138
|
+
# Rope project settings
|
|
139
|
+
.ropeproject
|
|
140
|
+
|
|
141
|
+
# mkdocs documentation
|
|
142
|
+
/site
|
|
143
|
+
|
|
144
|
+
# mypy
|
|
145
|
+
.mypy_cache/
|
|
146
|
+
.dmypy.json
|
|
147
|
+
dmypy.json
|
|
148
|
+
|
|
149
|
+
# Pyre type checker
|
|
150
|
+
.pyre/
|
|
151
|
+
|
|
152
|
+
# pytype static type analyzer
|
|
153
|
+
.pytype/
|
|
154
|
+
|
|
155
|
+
# Cython debug symbols
|
|
156
|
+
cython_debug/
|
|
157
|
+
|
|
158
|
+
# PyCharm
|
|
159
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
160
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
161
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
162
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
163
|
+
.idea/
|
|
164
|
+
*.pdb
|
|
165
|
+
*.pyd
|
|
166
|
+
|
|
167
|
+
*sandbox*
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Optional local hooks. Enable with:
|
|
2
|
+
# uv run --with pre-commit pre-commit install
|
|
3
|
+
# CI runs the same ruff and cargo checks whether or not these are installed.
|
|
4
|
+
repos:
|
|
5
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
6
|
+
rev: v5.0.0
|
|
7
|
+
hooks:
|
|
8
|
+
- id: end-of-file-fixer
|
|
9
|
+
- id: trailing-whitespace
|
|
10
|
+
- id: check-yaml
|
|
11
|
+
- id: check-toml
|
|
12
|
+
|
|
13
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
14
|
+
rev: v0.16.5
|
|
15
|
+
hooks:
|
|
16
|
+
- id: ruff-check
|
|
17
|
+
args: [--fix]
|
|
18
|
+
- id: ruff-format
|
|
19
|
+
|
|
20
|
+
- repo: local
|
|
21
|
+
hooks:
|
|
22
|
+
- id: cargo-fmt
|
|
23
|
+
name: cargo fmt
|
|
24
|
+
entry: cargo fmt --
|
|
25
|
+
language: system
|
|
26
|
+
types: [rust]
|
|
27
|
+
pass_filenames: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to polspec are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Until 1.0, minor
|
|
5
|
+
versions may break the Python API, the YAML format, and the values a given
|
|
6
|
+
seed produces; see
|
|
7
|
+
[Roadmap and stability](https://maxwellb13.github.io/polspec/reference/roadmap/).
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
## [0.1.5] - 2026-09-03
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `python/polspec/py.typed`, so type checkers use the package's annotations.
|
|
16
|
+
- `CONTRIBUTING.md`, this changelog, and a `.python-version` file.
|
|
17
|
+
- `examples/related_specs.py`: a worked example of four related specs
|
|
18
|
+
(foreign keys, shared categories, rules, checks, a YAML-declared spec). It
|
|
19
|
+
runs in CI as a smoke test.
|
|
20
|
+
- A release-workflow job that refuses a `vX.Y.Z` tag whose version does not
|
|
21
|
+
match `pyproject.toml`.
|
|
22
|
+
- CI now runs `ruff check` with a wider rule set, `ruff format --check`, `cargo fmt --check`,
|
|
23
|
+
`cargo clippy -D warnings` and `cargo test`, tests on macOS as well as
|
|
24
|
+
Linux and Windows, and tests against the newest Polars release inside the
|
|
25
|
+
declared bound. The docs build runs strictly on pull requests.
|
|
26
|
+
- Release builds now produce wheels for Linux aarch64 and macOS (x86_64 and
|
|
27
|
+
arm64) alongside Linux and Windows x86_64, plus an sdist, and only publish
|
|
28
|
+
when the test workflow is green.
|
|
29
|
+
- An optional `.pre-commit-config.yaml` with ruff and cargo fmt hooks.
|
|
30
|
+
- `tests/test_colspec.py` (2,000 lines, unsectioned) is split into
|
|
31
|
+
`test_generation.py`, `test_rules.py`, `test_serialization.py`,
|
|
32
|
+
`test_profiler.py`, `test_framespec.py`, `test_report.py` and
|
|
33
|
+
`test_foreign_key.py`, each with a docstring saying what it covers.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- The crate version in `Cargo.toml` is a placeholder; `pyproject.toml` is the
|
|
38
|
+
only place the version is set, so `uv version --bump` works.
|
|
39
|
+
- The `parquet`, `ipc` and `all` extras (all identical) are replaced by a
|
|
40
|
+
single `arrow` extra. Install with `polspec[arrow]` for the Parquet and
|
|
41
|
+
Arrow IPC sinks.
|
|
42
|
+
- `polars` is bounded to `<2`; the Rust extension is coupled to a Polars
|
|
43
|
+
release line.
|
|
44
|
+
- The abi3 floor is now Python 3.12, matching `requires-python`.
|
|
45
|
+
- `cargo test` links again (`extension-module` is no longer an unconditional
|
|
46
|
+
crate feature; maturin enables it).
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- Repository URL in package metadata pointed at the repository's old name.
|
|
51
|
+
- README claimed the license was unspecified; it is MIT.
|
|
52
|
+
- Documentation: `ColSpec(col_name=...)` is now described in *Declaring
|
|
53
|
+
columns*, `FrameSpec.to_python()` in *YAML specs*, the getting-started
|
|
54
|
+
example imports `date`, and the architecture page lists the `cli` module
|
|
55
|
+
and its tests.
|
|
56
|
+
|
|
57
|
+
## [0.1.4] - 2026-09-02
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
|
|
61
|
+
- `polspec schema infer --output spec.py` and `FrameSpec.to_python()`, which
|
|
62
|
+
write a spec as an editable Python module rather than YAML.
|
|
63
|
+
|
|
64
|
+
## [0.1.3] - 2026-09-01
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- `ColSpec(col_name=...)`, so a column's name in data may differ from the
|
|
69
|
+
attribute name used to declare it.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
- Roadmap expanded with detailed plans for a spec registry, structured
|
|
74
|
+
validation results, and generation guardrails.
|
|
75
|
+
|
|
76
|
+
## [0.1.2] - 2026-08-31
|
|
77
|
+
|
|
78
|
+
Version bump only; no user-facing change.
|
|
79
|
+
|
|
80
|
+
## [0.1.1] - 2026-08-31
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
|
|
84
|
+
- Test workflow on GitHub Actions (Linux and Windows, Python 3.12 to 3.14).
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
|
|
88
|
+
- `ColSpec.dtype` accepts a dtype class as well as an instance.
|
|
89
|
+
|
|
90
|
+
## [0.1.0] - 2026-08-31
|
|
91
|
+
|
|
92
|
+
First tagged release.
|
|
93
|
+
|
|
94
|
+
- `ColSpec` and `FrameSpec`: declare a Polars schema with nullability,
|
|
95
|
+
bounds, string lengths, choices and weights, distributions, tags, and
|
|
96
|
+
conditional `ColRule`s.
|
|
97
|
+
- `generate()` backed by a parallel Rust extension, `method="cartesian"` for
|
|
98
|
+
coverage sets, batched generation and Parquet/CSV/IPC/NDJSON sinks.
|
|
99
|
+
- `validate()` collecting every violation in one Polars aggregation, with
|
|
100
|
+
column validators, multi-column `Check`s, composite uniqueness and
|
|
101
|
+
`ForeignKey`s.
|
|
102
|
+
- `CatSpec` registries for shared `Enum`/`Categorical` domains.
|
|
103
|
+
- YAML round-trip, `from_dataframe()` profiling, Markdown and Mermaid output.
|
|
104
|
+
- CLI: `polspec schema infer`, `polspec schema new`, `polspec test`.
|
|
105
|
+
- Documentation site, comparison guide, and release automation.
|
|
106
|
+
|
|
107
|
+
[Unreleased]: https://github.com/MaxwellB13/polspec/compare/v0.1.5...HEAD
|
|
108
|
+
[0.1.5]: https://github.com/MaxwellB13/polspec/compare/v0.1.4...v0.1.5
|
|
109
|
+
[0.1.4]: https://github.com/MaxwellB13/polspec/compare/v0.1.3...v0.1.4
|
|
110
|
+
[0.1.3]: https://github.com/MaxwellB13/polspec/compare/v0.1.2...v0.1.3
|
|
111
|
+
[0.1.2]: https://github.com/MaxwellB13/polspec/compare/v0.1.1...v0.1.2
|
|
112
|
+
[0.1.1]: https://github.com/MaxwellB13/polspec/compare/v0.1.0...v0.1.1
|
|
113
|
+
[0.1.0]: https://github.com/MaxwellB13/polspec/releases/tag/v0.1.0
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
polspec is a Python package over a Rust extension. The Python side owns the
|
|
4
|
+
vocabulary (what a column can declare and what it means); the Rust side owns
|
|
5
|
+
the inner loop that fills arrays with values. See
|
|
6
|
+
[Architecture](https://maxwellb13.github.io/polspec/reference/architecture/)
|
|
7
|
+
for the module map.
|
|
8
|
+
|
|
9
|
+
## Set up
|
|
10
|
+
|
|
11
|
+
You need Python 3.12+, [uv](https://docs.astral.sh/uv/), and a Rust toolchain
|
|
12
|
+
(`rustup`).
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
git clone https://github.com/MaxwellB13/polspec.git
|
|
16
|
+
cd polspec
|
|
17
|
+
uv sync --group dev # Python deps, including maturin and pyarrow
|
|
18
|
+
uv run maturin develop --release
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`maturin develop` compiles the extension and installs the package into the
|
|
22
|
+
project's virtual environment as editable. Re-run it whenever `src/` changes;
|
|
23
|
+
Python-only edits are picked up immediately.
|
|
24
|
+
|
|
25
|
+
## Check your change
|
|
26
|
+
|
|
27
|
+
Run everything CI runs before opening a pull request:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uv run pytest # Python test suite
|
|
31
|
+
uv run ruff check . && uv run ruff format --check .
|
|
32
|
+
cargo test --release # Rust unit tests
|
|
33
|
+
cargo clippy --release
|
|
34
|
+
uv run python examples/related_specs.py # worked example, doubles as a smoke test
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Optionally, install the pre-commit hooks so ruff and `cargo fmt` run on
|
|
38
|
+
every commit:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv run --with pre-commit pre-commit install
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The docs build with [zensical](https://pypi.org/project/zensical/):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uv run --group docs zensical serve # live preview
|
|
48
|
+
uv run --group docs zensical build --strict # what the docs workflow runs
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Conventions
|
|
52
|
+
|
|
53
|
+
- **Generate and validate must agree.** Anything `generate()` produces,
|
|
54
|
+
`validate()` must accept. `tests/test_roundtrip.py` pins that property. A
|
|
55
|
+
known gap is recorded once in
|
|
56
|
+
[`docs/reference/limitations.md`](docs/reference/limitations.md) and once as
|
|
57
|
+
an `xfail(strict=True)` test, so fixing it forces the docs to be updated.
|
|
58
|
+
- **Error messages name the fix.** Say what was declared, what was expected,
|
|
59
|
+
and what to change. Look at the existing `ValueError`s in
|
|
60
|
+
`python/polspec/spec.py` for the register.
|
|
61
|
+
- **Two tables must match.** The distribution parameter aliases live in both
|
|
62
|
+
`python/polspec/distributions.py` and `DistKind::from_spec` in
|
|
63
|
+
`src/lib.rs`. Change them together.
|
|
64
|
+
- **Docs are part of the change.** A new field, option or CLI flag lands with
|
|
65
|
+
its guide page and a `CHANGELOG.md` entry under *Unreleased*.
|
|
66
|
+
- Commit messages follow the existing `type: summary` style
|
|
67
|
+
(`feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `ci:`, `chore:`).
|
|
68
|
+
|
|
69
|
+
## Releasing
|
|
70
|
+
|
|
71
|
+
The version lives in exactly one place: `project.version` in
|
|
72
|
+
`pyproject.toml`. maturin prefers it over the crate version in `Cargo.toml`,
|
|
73
|
+
which is a placeholder.
|
|
74
|
+
|
|
75
|
+
1. Bump it and refresh the lock file:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv version --bump patch # or minor / major
|
|
79
|
+
uv lock
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Then move the *Unreleased* section of `CHANGELOG.md` under the new version.
|
|
83
|
+
2. Commit, then tag `vX.Y.Z` and push the tag.
|
|
84
|
+
3. The release workflow checks the tag matches `pyproject.toml`, builds wheels,
|
|
85
|
+
publishes to PyPI, and attaches the wheels to a GitHub release.
|