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.
Files changed (24) hide show
  1. {typedframes-0.2.2 → typedframes-0.3.0}/PKG-INFO +51 -20
  2. {typedframes-0.2.2 → typedframes-0.3.0}/README.md +50 -19
  3. {typedframes-0.2.2 → typedframes-0.3.0}/pyproject.toml +1 -1
  4. {typedframes-0.2.2 → typedframes-0.3.0}/rust/Cargo.lock +3 -3
  5. {typedframes-0.2.2 → typedframes-0.3.0}/rust/Cargo.toml +1 -1
  6. {typedframes-0.2.2 → typedframes-0.3.0}/rust/src/lib.rs +1461 -101
  7. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/__init__.py +1 -1
  8. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/pandas.py +2 -2
  9. {typedframes-0.2.2 → typedframes-0.3.0}/rust/README.md +0 -0
  10. {typedframes-0.2.2 → typedframes-0.3.0}/rust/benches/parser_bench.rs +0 -0
  11. {typedframes-0.2.2 → typedframes-0.3.0}/rust/src/main.rs +0 -0
  12. {typedframes-0.2.2 → typedframes-0.3.0}/rust/tests/integration_test.rs +0 -0
  13. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/base_schema.py +0 -0
  14. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/cli.py +0 -0
  15. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/column.py +0 -0
  16. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/column_group.py +0 -0
  17. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/column_group_error.py +0 -0
  18. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/column_set.py +0 -0
  19. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/missing_dependency_error.py +0 -0
  20. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/mypy.py +0 -0
  21. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/pandera.py +0 -0
  22. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/polars.py +0 -0
  23. {typedframes-0.2.2 → typedframes-0.3.0}/src/typedframes/py.typed +0 -0
  24. {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.2.2
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.2.1) is currently an experimental proof-of-concept. The core static analysis and mypy/Rust
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 {order_id, amount, status}
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 (488 files) |
441
+ | Tool | Version | What it does | typedframes (13 files) | great_expectations (485 files) |
413
442
  |------|---------|--------------|------------------------|--------------------------------|
414
- | typedframes | 0.2.1 | DataFrame column checker | 43ms ±531µs | 285ms ±4ms |
415
- | ruff | 0.15.4 | Linter (no type checking) | 27ms ±932µs | 251ms ±2ms |
416
- | ty | 0.0.19 | Type checker | 67ms ±1ms | 793ms ±14ms |
417
- | pyrefly | 0.54.0 | Type checker | 120ms ±2ms | 1.11s ±13ms |
418
- | mypy | 1.19.1 | Type checker (no plugin) | 3.47s ±15ms | 4.43s ±66ms |
419
- | mypy + typedframes | 1.19.1 | Type checker + column checker | 3.52s ±40ms | 4.79s ±113ms |
420
- | pyright | 1.1.408 | Type checker | 822ms ±55ms | 3.43s ±54ms |
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.2.1 | 0.29.0 | 1.18.0 | 0.3.7 | 3.0.3 | 0.1.2 | 1.1.3 | 4.1.0 | 2.22.1 | 2.10.1 | 0.8.6 |
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.29.0): Excellent runtime validation. Static analysis support exists
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.0): Official pandas type stubs. Provides
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)** (v4.1.0): Alternative immutable DataFrame library.
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.22.1): Compatibility layer that provides a unified API
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.0): Comprehensive data quality framework. Defines
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.10.1): Polars-only runtime validation library from Quantco.
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.2.1) is currently an experimental proof-of-concept. The core static analysis and mypy/Rust
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 {order_id, amount, status}
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 (488 files) |
407
+ | Tool | Version | What it does | typedframes (13 files) | great_expectations (485 files) |
379
408
  |------|---------|--------------|------------------------|--------------------------------|
380
- | typedframes | 0.2.1 | DataFrame column checker | 43ms ±531µs | 285ms ±4ms |
381
- | ruff | 0.15.4 | Linter (no type checking) | 27ms ±932µs | 251ms ±2ms |
382
- | ty | 0.0.19 | Type checker | 67ms ±1ms | 793ms ±14ms |
383
- | pyrefly | 0.54.0 | Type checker | 120ms ±2ms | 1.11s ±13ms |
384
- | mypy | 1.19.1 | Type checker (no plugin) | 3.47s ±15ms | 4.43s ±66ms |
385
- | mypy + typedframes | 1.19.1 | Type checker + column checker | 3.52s ±40ms | 4.79s ±113ms |
386
- | pyright | 1.1.408 | Type checker | 822ms ±55ms | 3.43s ±54ms |
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.2.1 | 0.29.0 | 1.18.0 | 0.3.7 | 3.0.3 | 0.1.2 | 1.1.3 | 4.1.0 | 2.22.1 | 2.10.1 | 0.8.6 |
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.29.0): Excellent runtime validation. Static analysis support exists
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.0): Official pandas type stubs. Provides
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)** (v4.1.0): Alternative immutable DataFrame library.
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.22.1): Compatibility layer that provides a unified API
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.0): Comprehensive data quality framework. Defines
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.10.1): Polars-only runtime validation library from Quantco.
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.2.2"
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.18"
232
+ version = "0.9.20"
233
233
  source = "registry+https://github.com/rust-lang/crates.io-index"
234
- checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
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.2.2"
1112
+ version = "0.3.0"
1113
1113
  dependencies = [
1114
1114
  "anyhow",
1115
1115
  "criterion",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "typedframes_checker"
3
- version = "0.2.2"
3
+ version = "0.3.0"
4
4
  edition = "2021"
5
5
  description = "A high-performance Rust-based checker for typedframes DataFrame column schemas"
6
6
  license = "MIT"