typedframes 0.2.2__tar.gz → 0.3.0__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.
- {typedframes-0.2.2 → typedframes-0.3.0}/PKG-INFO +51 -20
- {typedframes-0.2.2 → typedframes-0.3.0}/README.md +50 -19
- {typedframes-0.2.2 → typedframes-0.3.0}/pyproject.toml +1 -1
- {typedframes-0.2.2 → typedframes-0.3.0}/rust/Cargo.lock +3 -3
- {typedframes-0.2.2 → typedframes-0.3.0}/rust/Cargo.toml +1 -1
- {typedframes-0.2.2 → typedframes-0.3.0}/rust/src/lib.rs +1461 -101
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/__init__.py +1 -1
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/pandas.py +2 -2
- {typedframes-0.2.2 → typedframes-0.3.0}/rust/README.md +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/rust/benches/parser_bench.rs +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/rust/src/main.rs +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/rust/tests/integration_test.rs +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/base_schema.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/cli.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/column.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/column_group.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/column_group_error.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/column_set.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/missing_dependency_error.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/mypy.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/pandera.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/polars.py +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/py.typed +0 -0
- {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/schema_algebra.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: typedframes
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -42,7 +42,7 @@ Project-URL: Repository, https://github.com/w-martin/typedframes
|
|
|
42
42
|
|
|
43
43
|
> ⚠️ **Project Status: Proof of Concept**
|
|
44
44
|
>
|
|
45
|
-
> `typedframes` (v0.
|
|
45
|
+
> `typedframes` (v0.3.0) is currently an experimental proof-of-concept. The core static analysis and mypy/Rust
|
|
46
46
|
> integrations work, but expect rough edges. The codebase prioritizes demonstrating the viability of static DataFrame
|
|
47
47
|
> schema validation over production-grade stability.
|
|
48
48
|
>
|
|
@@ -140,7 +140,7 @@ print(orders["revenue"]) # ✗ unknown-column — 'revenue' not in inferred set
|
|
|
140
140
|
|
|
141
141
|
```shell
|
|
142
142
|
typedframes check src/
|
|
143
|
-
# src/pipeline.py:7:8: error[unknown-column] Column 'revenue' not in inferred set
|
|
143
|
+
# src/pipeline.py:7:8: error[unknown-column] Column 'revenue' does not exist in inferred column set (defined at line 6)
|
|
144
144
|
# ✗ Found 1 error in 12 files (0.0s)
|
|
145
145
|
```
|
|
146
146
|
|
|
@@ -297,12 +297,39 @@ trimmed = df.drop(columns=["nonexistent"])
|
|
|
297
297
|
# ⚠ dropped-unknown-column: Dropped column 'nonexistent' does not exist in UserData
|
|
298
298
|
```
|
|
299
299
|
|
|
300
|
+
### Function Parameter Contracts
|
|
301
|
+
|
|
302
|
+
Beyond validating access at the point it happens, the checker infers a *contract* for any function's
|
|
303
|
+
first parameter: every column the function needs, drawn from what its body accesses or — taking priority —
|
|
304
|
+
from a schema annotation on the parameter itself. Calling that function with a DataFrame that doesn't
|
|
305
|
+
satisfy the contract is caught at the **call site**, across files:
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
# transforms.py
|
|
309
|
+
def contact_label(customers):
|
|
310
|
+
return customers["name"] + customers["email"]
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
# pipeline.py
|
|
315
|
+
customers = load_customers(path) # inferred columns: {customer_id, name, region}
|
|
316
|
+
contact_label(customers)
|
|
317
|
+
# ✗ missing-column: 'customers' passed to contact_label (transforms.py:2) is missing
|
|
318
|
+
# column(s) {email} — available: {customer_id, name, region}, required: {email, name}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
The contract is resolved *transitively*: if a function only forwards its parameter to other functions
|
|
322
|
+
(`step1 = preprocess(df); step2 = enrich(step1)`), the checker follows the chain and unions their
|
|
323
|
+
requirements, catching a missing column even when no single function in the chain touches it directly.
|
|
324
|
+
Column-list slices (`df[["a", "b"]]`) contribute to the contract too.
|
|
325
|
+
|
|
300
326
|
### See Also
|
|
301
327
|
|
|
302
328
|
- [`examples/inference_example.py`](examples/inference_example.py) — single-file walkthrough of all four inference
|
|
303
329
|
scenarios with annotated ✓/✗ comments.
|
|
304
330
|
- [`examples/multi_file_inference/`](examples/multi_file_inference/) — multi-file project checked with
|
|
305
|
-
`typedframes check examples/multi_file_inference/`; no `BaseSchema` anywhere.
|
|
331
|
+
`typedframes check examples/multi_file_inference/`; no `BaseSchema` anywhere. Includes a function
|
|
332
|
+
parameter contract violation caught at the call site (`missing-column`).
|
|
306
333
|
- [`examples/multi_file_with_schema/`](examples/multi_file_with_schema/) — same scenario with `BaseSchema`
|
|
307
334
|
classes; the checker follows schemas across module boundaries via the project index.
|
|
308
335
|
|
|
@@ -327,6 +354,8 @@ typedframes check src/
|
|
|
327
354
|
**Features:**
|
|
328
355
|
- Catches column name errors
|
|
329
356
|
- Validates schema mismatches between functions
|
|
357
|
+
- Validates function parameter contracts across files, including transitively through chains of
|
|
358
|
+
helper functions (`missing-column`)
|
|
330
359
|
- Checks both pandas and polars code
|
|
331
360
|
- Significantly faster than mypy (see benchmarks below)
|
|
332
361
|
|
|
@@ -409,15 +438,15 @@ Fast feedback reduces development time. The typedframes Rust binary provides nea
|
|
|
409
438
|
|
|
410
439
|
**Benchmark results** (10 runs, 3 warmup, caches cleared between runs):
|
|
411
440
|
|
|
412
|
-
| Tool | Version | What it does | typedframes (13 files) | great_expectations (
|
|
441
|
+
| Tool | Version | What it does | typedframes (13 files) | great_expectations (485 files) |
|
|
413
442
|
|------|---------|--------------|------------------------|--------------------------------|
|
|
414
|
-
| typedframes | 0.
|
|
415
|
-
| ruff | 0.15.
|
|
416
|
-
| ty | 0.0.
|
|
417
|
-
| pyrefly |
|
|
418
|
-
| mypy |
|
|
419
|
-
| mypy + typedframes |
|
|
420
|
-
| pyright | 1.1.
|
|
443
|
+
| typedframes | 0.3.0 | DataFrame column checker | 81ms ±6ms | 3.64s ±9ms |
|
|
444
|
+
| ruff | 0.15.21 | Linter (no type checking) | 48ms ±13ms | 237ms ±31ms |
|
|
445
|
+
| ty | 0.0.58 | Type checker | 119ms ±14ms | 287ms ±33ms |
|
|
446
|
+
| pyrefly | 1.1.1 | Type checker | 162ms ±18ms | 390ms ±21ms |
|
|
447
|
+
| mypy | 2.2.0 | Type checker (no plugin) | 4.56s ±22ms | 7.31s ±35ms |
|
|
448
|
+
| mypy + typedframes | 2.2.0 | Type checker + column checker | 4.69s ±61ms | 10.89s ±356ms |
|
|
449
|
+
| pyright | 1.1.411 | Type checker | 1.39s ±17ms | 8.06s ±193ms |
|
|
421
450
|
|
|
422
451
|
*Run `uv run python benchmarks/benchmark_checkers.py` to reproduce.*
|
|
423
452
|
|
|
@@ -630,7 +659,7 @@ Comprehensive comparison of pandas/DataFrame typing and validation tools. **type
|
|
|
630
659
|
|
|
631
660
|
| Feature | typedframes | Pandera | Great Expectations | strictly_typed_pandas | pandas-stubs | dataenforce | pandas-type-checks | StaticFrame | narwhals | dataframely | patito |
|
|
632
661
|
|---------------------------------|------------------------|-------------|--------------------|-----------------------|--------------|-------------|--------------------|------------------|----------|------------------|------------------|
|
|
633
|
-
| **Version tested** | 0.
|
|
662
|
+
| **Version tested** | 0.3.0 | 0.32.1 | 1.18.2 | 0.3.7 | 3.0.3 | 0.1.2 | 1.1.3 | 5.0.0 | 2.23.0 | 2.13.0 | 0.8.6 |
|
|
634
663
|
| **Analysis Type** |
|
|
635
664
|
| When errors are caught | **Static (lint-time)** | Runtime | Runtime | Runtime | Static | Runtime | Runtime | Runtime | Runtime | Runtime | Runtime |
|
|
636
665
|
| **Static Analysis (our focus)** |
|
|
@@ -656,7 +685,7 @@ Comprehensive comparison of pandas/DataFrame typing and validation tools. **type
|
|
|
656
685
|
|
|
657
686
|
### Tool Descriptions
|
|
658
687
|
|
|
659
|
-
- **[Pandera](https://pandera.readthedocs.io/)** (v0.
|
|
688
|
+
- **[Pandera](https://pandera.readthedocs.io/)** (v0.32.1): Excellent runtime validation. Static analysis support exists
|
|
660
689
|
but has limitations—column access via `df["column"]` is not validated, and schema mismatches between functions may not
|
|
661
690
|
be caught.
|
|
662
691
|
|
|
@@ -664,30 +693,30 @@ Comprehensive comparison of pandas/DataFrame typing and validation tools. **type
|
|
|
664
693
|
hints for runtime validation via typeguard. Despite documentation implying mypy support, there is no mypy plugin —
|
|
665
694
|
column access errors are not caught statically. No standalone checker. No polars support.
|
|
666
695
|
|
|
667
|
-
- **[pandas-stubs](https://github.com/pandas-dev/pandas-stubs)** (v3.0.
|
|
696
|
+
- **[pandas-stubs](https://github.com/pandas-dev/pandas-stubs)** (v3.0.3): Official pandas type stubs. Provides
|
|
668
697
|
API-level types but no column-level checking.
|
|
669
698
|
|
|
670
699
|
- **[dataenforce](https://github.com/CedricFR/dataenforce)** (v0.1.2): Runtime validation via decorator. Marked as
|
|
671
|
-
experimental/not production-ready. Appears inactive.
|
|
700
|
+
experimental/not production-ready. Appears inactive. Broken on Python 3.13+ due to removal of internal typing APIs.
|
|
672
701
|
|
|
673
702
|
- **[pandas-type-checks](https://pypi.org/project/pandas-type-checks/)** (v1.1.3): Runtime validation decorator. No
|
|
674
703
|
static analysis.
|
|
675
704
|
|
|
676
|
-
- **[StaticFrame](https://github.com/static-frame/static-frame)** (
|
|
705
|
+
- **[StaticFrame](https://github.com/static-frame/static-frame)** (v5.0.0): Alternative immutable DataFrame library.
|
|
677
706
|
Not compatible with pandas/polars — requires a full rewrite to StaticFrame's own API. Column access is still
|
|
678
707
|
string-based; mypy does not catch column name typos. Type safety comes from immutability guarantees, not schema checking.
|
|
679
708
|
|
|
680
|
-
- **[narwhals](https://narwhals-dev.github.io/narwhals/)** (v2.
|
|
709
|
+
- **[narwhals](https://narwhals-dev.github.io/narwhals/)** (v2.23.0): Compatibility layer that provides a unified API
|
|
681
710
|
across pandas, polars, DuckDB, cuDF, and more. Solves a different problem—write-once-run-anywhere portability, not
|
|
682
711
|
type safety. See [Why Abstraction Layers Don't Solve Type Safety](#why-abstraction-layers-dont-solve-type-safety)
|
|
683
712
|
below.
|
|
684
713
|
|
|
685
|
-
- **[Great Expectations](https://greatexpectations.io/)** (v1.18.
|
|
714
|
+
- **[Great Expectations](https://greatexpectations.io/)** (v1.18.2): Comprehensive data quality framework. Defines
|
|
686
715
|
"expectations" (assertions) about data values, distributions, and schema properties. Excellent for runtime
|
|
687
716
|
validation, data documentation, and data quality monitoring. No static analysis or column-level type checking in
|
|
688
717
|
code. Supports pandas, Spark, and SQL backends.
|
|
689
718
|
|
|
690
|
-
- **[dataframely](https://github.com/Quantco/dataframely)** (v2.
|
|
719
|
+
- **[dataframely](https://github.com/Quantco/dataframely)** (v2.13.0): Polars-only runtime validation library from Quantco.
|
|
691
720
|
Schemas are defined as classes inheriting `dy.Schema` with typed descriptor fields (`dy.String()`, `dy.Float64()`)
|
|
692
721
|
and `@dy.rule()` decorators for cross-column and group-level constraints. Returns `dy.DataFrame[Schema]` generic
|
|
693
722
|
types that give call-site narrowing to type checkers, but does not validate column subscript access inside function
|
|
@@ -992,6 +1021,8 @@ MIT License - see [LICENSE](LICENSE)
|
|
|
992
1021
|
- [x] Pandera integration (`to_pandera_schema()`)
|
|
993
1022
|
- [x] Cross-file schema inference (project-level index, `--no-index` flag)
|
|
994
1023
|
- [x] Aggressive column inference (untracked-dataframe/dropped-unknown-column warnings, method chain propagation)
|
|
1024
|
+
- [x] Function parameter contracts (`missing-column`), resolved transitively across chains of helper
|
|
1025
|
+
functions and cross-file calls; schema-annotated parameters take priority over body-scanning
|
|
995
1026
|
|
|
996
1027
|
**Planned:**
|
|
997
1028
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
> ⚠️ **Project Status: Proof of Concept**
|
|
10
10
|
>
|
|
11
|
-
> `typedframes` (v0.
|
|
11
|
+
> `typedframes` (v0.3.0) is currently an experimental proof-of-concept. The core static analysis and mypy/Rust
|
|
12
12
|
> integrations work, but expect rough edges. The codebase prioritizes demonstrating the viability of static DataFrame
|
|
13
13
|
> schema validation over production-grade stability.
|
|
14
14
|
>
|
|
@@ -106,7 +106,7 @@ print(orders["revenue"]) # ✗ unknown-column — 'revenue' not in inferred set
|
|
|
106
106
|
|
|
107
107
|
```shell
|
|
108
108
|
typedframes check src/
|
|
109
|
-
# src/pipeline.py:7:8: error[unknown-column] Column 'revenue' not in inferred set
|
|
109
|
+
# src/pipeline.py:7:8: error[unknown-column] Column 'revenue' does not exist in inferred column set (defined at line 6)
|
|
110
110
|
# ✗ Found 1 error in 12 files (0.0s)
|
|
111
111
|
```
|
|
112
112
|
|
|
@@ -263,12 +263,39 @@ trimmed = df.drop(columns=["nonexistent"])
|
|
|
263
263
|
# ⚠ dropped-unknown-column: Dropped column 'nonexistent' does not exist in UserData
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
+
### Function Parameter Contracts
|
|
267
|
+
|
|
268
|
+
Beyond validating access at the point it happens, the checker infers a *contract* for any function's
|
|
269
|
+
first parameter: every column the function needs, drawn from what its body accesses or — taking priority —
|
|
270
|
+
from a schema annotation on the parameter itself. Calling that function with a DataFrame that doesn't
|
|
271
|
+
satisfy the contract is caught at the **call site**, across files:
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
# transforms.py
|
|
275
|
+
def contact_label(customers):
|
|
276
|
+
return customers["name"] + customers["email"]
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
# pipeline.py
|
|
281
|
+
customers = load_customers(path) # inferred columns: {customer_id, name, region}
|
|
282
|
+
contact_label(customers)
|
|
283
|
+
# ✗ missing-column: 'customers' passed to contact_label (transforms.py:2) is missing
|
|
284
|
+
# column(s) {email} — available: {customer_id, name, region}, required: {email, name}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
The contract is resolved *transitively*: if a function only forwards its parameter to other functions
|
|
288
|
+
(`step1 = preprocess(df); step2 = enrich(step1)`), the checker follows the chain and unions their
|
|
289
|
+
requirements, catching a missing column even when no single function in the chain touches it directly.
|
|
290
|
+
Column-list slices (`df[["a", "b"]]`) contribute to the contract too.
|
|
291
|
+
|
|
266
292
|
### See Also
|
|
267
293
|
|
|
268
294
|
- [`examples/inference_example.py`](examples/inference_example.py) — single-file walkthrough of all four inference
|
|
269
295
|
scenarios with annotated ✓/✗ comments.
|
|
270
296
|
- [`examples/multi_file_inference/`](examples/multi_file_inference/) — multi-file project checked with
|
|
271
|
-
`typedframes check examples/multi_file_inference/`; no `BaseSchema` anywhere.
|
|
297
|
+
`typedframes check examples/multi_file_inference/`; no `BaseSchema` anywhere. Includes a function
|
|
298
|
+
parameter contract violation caught at the call site (`missing-column`).
|
|
272
299
|
- [`examples/multi_file_with_schema/`](examples/multi_file_with_schema/) — same scenario with `BaseSchema`
|
|
273
300
|
classes; the checker follows schemas across module boundaries via the project index.
|
|
274
301
|
|
|
@@ -293,6 +320,8 @@ typedframes check src/
|
|
|
293
320
|
**Features:**
|
|
294
321
|
- Catches column name errors
|
|
295
322
|
- Validates schema mismatches between functions
|
|
323
|
+
- Validates function parameter contracts across files, including transitively through chains of
|
|
324
|
+
helper functions (`missing-column`)
|
|
296
325
|
- Checks both pandas and polars code
|
|
297
326
|
- Significantly faster than mypy (see benchmarks below)
|
|
298
327
|
|
|
@@ -375,15 +404,15 @@ Fast feedback reduces development time. The typedframes Rust binary provides nea
|
|
|
375
404
|
|
|
376
405
|
**Benchmark results** (10 runs, 3 warmup, caches cleared between runs):
|
|
377
406
|
|
|
378
|
-
| Tool | Version | What it does | typedframes (13 files) | great_expectations (
|
|
407
|
+
| Tool | Version | What it does | typedframes (13 files) | great_expectations (485 files) |
|
|
379
408
|
|------|---------|--------------|------------------------|--------------------------------|
|
|
380
|
-
| typedframes | 0.
|
|
381
|
-
| ruff | 0.15.
|
|
382
|
-
| ty | 0.0.
|
|
383
|
-
| pyrefly |
|
|
384
|
-
| mypy |
|
|
385
|
-
| mypy + typedframes |
|
|
386
|
-
| pyright | 1.1.
|
|
409
|
+
| typedframes | 0.3.0 | DataFrame column checker | 81ms ±6ms | 3.64s ±9ms |
|
|
410
|
+
| ruff | 0.15.21 | Linter (no type checking) | 48ms ±13ms | 237ms ±31ms |
|
|
411
|
+
| ty | 0.0.58 | Type checker | 119ms ±14ms | 287ms ±33ms |
|
|
412
|
+
| pyrefly | 1.1.1 | Type checker | 162ms ±18ms | 390ms ±21ms |
|
|
413
|
+
| mypy | 2.2.0 | Type checker (no plugin) | 4.56s ±22ms | 7.31s ±35ms |
|
|
414
|
+
| mypy + typedframes | 2.2.0 | Type checker + column checker | 4.69s ±61ms | 10.89s ±356ms |
|
|
415
|
+
| pyright | 1.1.411 | Type checker | 1.39s ±17ms | 8.06s ±193ms |
|
|
387
416
|
|
|
388
417
|
*Run `uv run python benchmarks/benchmark_checkers.py` to reproduce.*
|
|
389
418
|
|
|
@@ -596,7 +625,7 @@ Comprehensive comparison of pandas/DataFrame typing and validation tools. **type
|
|
|
596
625
|
|
|
597
626
|
| Feature | typedframes | Pandera | Great Expectations | strictly_typed_pandas | pandas-stubs | dataenforce | pandas-type-checks | StaticFrame | narwhals | dataframely | patito |
|
|
598
627
|
|---------------------------------|------------------------|-------------|--------------------|-----------------------|--------------|-------------|--------------------|------------------|----------|------------------|------------------|
|
|
599
|
-
| **Version tested** | 0.
|
|
628
|
+
| **Version tested** | 0.3.0 | 0.32.1 | 1.18.2 | 0.3.7 | 3.0.3 | 0.1.2 | 1.1.3 | 5.0.0 | 2.23.0 | 2.13.0 | 0.8.6 |
|
|
600
629
|
| **Analysis Type** |
|
|
601
630
|
| When errors are caught | **Static (lint-time)** | Runtime | Runtime | Runtime | Static | Runtime | Runtime | Runtime | Runtime | Runtime | Runtime |
|
|
602
631
|
| **Static Analysis (our focus)** |
|
|
@@ -622,7 +651,7 @@ Comprehensive comparison of pandas/DataFrame typing and validation tools. **type
|
|
|
622
651
|
|
|
623
652
|
### Tool Descriptions
|
|
624
653
|
|
|
625
|
-
- **[Pandera](https://pandera.readthedocs.io/)** (v0.
|
|
654
|
+
- **[Pandera](https://pandera.readthedocs.io/)** (v0.32.1): Excellent runtime validation. Static analysis support exists
|
|
626
655
|
but has limitations—column access via `df["column"]` is not validated, and schema mismatches between functions may not
|
|
627
656
|
be caught.
|
|
628
657
|
|
|
@@ -630,30 +659,30 @@ Comprehensive comparison of pandas/DataFrame typing and validation tools. **type
|
|
|
630
659
|
hints for runtime validation via typeguard. Despite documentation implying mypy support, there is no mypy plugin —
|
|
631
660
|
column access errors are not caught statically. No standalone checker. No polars support.
|
|
632
661
|
|
|
633
|
-
- **[pandas-stubs](https://github.com/pandas-dev/pandas-stubs)** (v3.0.
|
|
662
|
+
- **[pandas-stubs](https://github.com/pandas-dev/pandas-stubs)** (v3.0.3): Official pandas type stubs. Provides
|
|
634
663
|
API-level types but no column-level checking.
|
|
635
664
|
|
|
636
665
|
- **[dataenforce](https://github.com/CedricFR/dataenforce)** (v0.1.2): Runtime validation via decorator. Marked as
|
|
637
|
-
experimental/not production-ready. Appears inactive.
|
|
666
|
+
experimental/not production-ready. Appears inactive. Broken on Python 3.13+ due to removal of internal typing APIs.
|
|
638
667
|
|
|
639
668
|
- **[pandas-type-checks](https://pypi.org/project/pandas-type-checks/)** (v1.1.3): Runtime validation decorator. No
|
|
640
669
|
static analysis.
|
|
641
670
|
|
|
642
|
-
- **[StaticFrame](https://github.com/static-frame/static-frame)** (
|
|
671
|
+
- **[StaticFrame](https://github.com/static-frame/static-frame)** (v5.0.0): Alternative immutable DataFrame library.
|
|
643
672
|
Not compatible with pandas/polars — requires a full rewrite to StaticFrame's own API. Column access is still
|
|
644
673
|
string-based; mypy does not catch column name typos. Type safety comes from immutability guarantees, not schema checking.
|
|
645
674
|
|
|
646
|
-
- **[narwhals](https://narwhals-dev.github.io/narwhals/)** (v2.
|
|
675
|
+
- **[narwhals](https://narwhals-dev.github.io/narwhals/)** (v2.23.0): Compatibility layer that provides a unified API
|
|
647
676
|
across pandas, polars, DuckDB, cuDF, and more. Solves a different problem—write-once-run-anywhere portability, not
|
|
648
677
|
type safety. See [Why Abstraction Layers Don't Solve Type Safety](#why-abstraction-layers-dont-solve-type-safety)
|
|
649
678
|
below.
|
|
650
679
|
|
|
651
|
-
- **[Great Expectations](https://greatexpectations.io/)** (v1.18.
|
|
680
|
+
- **[Great Expectations](https://greatexpectations.io/)** (v1.18.2): Comprehensive data quality framework. Defines
|
|
652
681
|
"expectations" (assertions) about data values, distributions, and schema properties. Excellent for runtime
|
|
653
682
|
validation, data documentation, and data quality monitoring. No static analysis or column-level type checking in
|
|
654
683
|
code. Supports pandas, Spark, and SQL backends.
|
|
655
684
|
|
|
656
|
-
- **[dataframely](https://github.com/Quantco/dataframely)** (v2.
|
|
685
|
+
- **[dataframely](https://github.com/Quantco/dataframely)** (v2.13.0): Polars-only runtime validation library from Quantco.
|
|
657
686
|
Schemas are defined as classes inheriting `dy.Schema` with typed descriptor fields (`dy.String()`, `dy.Float64()`)
|
|
658
687
|
and `@dy.rule()` decorators for cross-column and group-level constraints. Returns `dy.DataFrame[Schema]` generic
|
|
659
688
|
types that give call-site narrowing to type checkers, but does not validate column subscript access inside function
|
|
@@ -958,6 +987,8 @@ MIT License - see [LICENSE](LICENSE)
|
|
|
958
987
|
- [x] Pandera integration (`to_pandera_schema()`)
|
|
959
988
|
- [x] Cross-file schema inference (project-level index, `--no-index` flag)
|
|
960
989
|
- [x] Aggressive column inference (untracked-dataframe/dropped-unknown-column warnings, method chain propagation)
|
|
990
|
+
- [x] Function parameter contracts (`missing-column`), resolved transitively across chains of helper
|
|
991
|
+
functions and cross-file calls; schema-annotated parameters take priority over body-scanning
|
|
961
992
|
|
|
962
993
|
**Planned:**
|
|
963
994
|
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "typedframes"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Static analysis for pandas and polars DataFrames. Catch column errors at lint-time, not runtime."
|
|
9
9
|
keywords = ["pandas", "polars", "type-checking", "static-analysis", "dataframe", "linter", "mypy-plugin"]
|
|
10
10
|
readme = "README.md"
|
|
@@ -229,9 +229,9 @@ dependencies = [
|
|
|
229
229
|
|
|
230
230
|
[[package]]
|
|
231
231
|
name = "crossbeam-epoch"
|
|
232
|
-
version = "0.9.
|
|
232
|
+
version = "0.9.20"
|
|
233
233
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
234
|
-
checksum = "
|
|
234
|
+
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
|
235
235
|
dependencies = [
|
|
236
236
|
"crossbeam-utils",
|
|
237
237
|
]
|
|
@@ -1109,7 +1109,7 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
|
|
1109
1109
|
|
|
1110
1110
|
[[package]]
|
|
1111
1111
|
name = "typedframes_checker"
|
|
1112
|
-
version = "0.
|
|
1112
|
+
version = "0.3.0"
|
|
1113
1113
|
dependencies = [
|
|
1114
1114
|
"anyhow",
|
|
1115
1115
|
"criterion",
|