dataframely 2.13.0__tar.gz → 2.13.1__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.
- {dataframely-2.13.0 → dataframely-2.13.1}/PKG-INFO +1 -1
- dataframely-2.13.1/dataframely/_deprecation.py +58 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/collection/collection.py +56 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/schema.py +57 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/features/serialization.md +22 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/migration/index.md +5 -6
- {dataframely-2.13.0 → dataframely-2.13.1}/pyproject.toml +6 -3
- dataframely-2.13.1/tests/test_deprecation.py +149 -0
- dataframely-2.13.0/dataframely/_deprecation.py +0 -27
- dataframely-2.13.0/tests/test_deprecation.py +0 -24
- {dataframely-2.13.0 → dataframely-2.13.1}/.claude/CLAUDE.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.copier-answers.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.envrc +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.gitattributes +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/CODEOWNERS +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/copilot-instructions.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/dependabot.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/instructions/tests.instructions.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/release-drafter.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/workflows/build.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/workflows/chore.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/workflows/ci.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/workflows/copilot-setup-steps.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/workflows/nightly.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/workflows/release-drafter.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.github/workflows/scorecard.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.gitignore +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.lefthook.yaml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.prettierignore +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.prettierrc +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/.readthedocs.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/AGENTS.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/Cargo.lock +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/Cargo.toml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/LICENSE +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/README.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/SECURITY.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_base_schema.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_compat.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_filter.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_match_to_schema.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_native.pyi +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_plugin.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_polars.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_pydantic.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_rule.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_serialization.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_storage/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_storage/_base.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_storage/_exc.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_storage/_fsspec.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_storage/constants.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_storage/delta.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_storage/parquet.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/_typing.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/collection/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/collection/_base.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/collection/filter_result.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/_base.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/_mixins.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/_registry.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/_utils.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/any.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/array.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/binary.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/bool.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/categorical.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/datetime.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/decimal.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/enum.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/float.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/integer.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/list.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/object.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/string.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/columns/struct.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/config.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/exc.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/experimental/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/experimental/infer_schema.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/filter_result.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/functional.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/py.typed +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/random.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/testing/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/testing/const.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/testing/factory.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/testing/mask.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/testing/rules.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/dataframely/testing/storage.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docker-compose.yml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/_static/custom.css +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/_static/favicon.ico +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/_templates/autosummary/class.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/_templates/autosummary/method.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/_templates/classes/column.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/_templates/classes/error.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/_templates/classes/filter_result.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/collection/generation.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/collection/index.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/collection/io.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/collection/metadata.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/collection/operations.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/collection/validation.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/columns/index.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/errors/index.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/experimental/index.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/filter_result/failure_info.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/filter_result/index.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/index.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/misc/index.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/schema/conversion.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/schema/generation.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/schema/index.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/schema/io.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/schema/metadata.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/api/schema/validation.rst +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/conf.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/css/custom.css +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/coding-agents.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/development.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/examples/index.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/examples/real-world.ipynb +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/faq.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/features/column-metadata.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/features/data-generation.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/features/index.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/features/lazy-validation.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/features/primary-keys.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/features/sql-generation.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/index.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/migration/v1-v2.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/guides/quickstart.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/docs/index.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/pixi.lock +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/pixi.toml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/rust-toolchain.toml +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/skills/SKILL.md +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/src/lib.rs +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/src/polars_plugin/mod.rs +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/src/polars_plugin/rule_failure.rs +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/src/polars_plugin/utils.rs +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/src/polars_plugin/validation_error.rs +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/src/regex/errdefs.rs +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/src/regex/mod.rs +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/src/regex/repr.rs +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/benches/conftest.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/benches/test_collection.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/benches/test_failure.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/benches/test_schema.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_base.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_cast.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_collection_future_annotations.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_create_empty.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_dataframe_members.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_filter_one_to_n.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_filter_validate.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_ignore_in_filter.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_implementation.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_join.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_matches.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_optional_members.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_pipe.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_propagate_row_failures.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_repr.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_sample.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_serialization.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_skip_member_validation.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_storage.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/collection/test_validate_input.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_any.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_array.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_binary.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_datetime.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_decimal.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_enum.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_float.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_integer.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_list.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_object.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_string.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/column_types/test_struct.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_alias.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_base.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_check.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_default_dtypes.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_description.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_matches.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_metadata.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_polars_schema.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_pyarrow.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_pydantic.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_rules.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_sample.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_sqlalchemy_columns.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_str.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/columns/test_utils.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/conftest.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/core_validation/__init__.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/core_validation/test_match_to_schema.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/core_validation/test_rule_evaluation.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/experimental/test_infer_schema.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/failure_info/test_storage.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/functional/test_concat.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/functional/test_relationships.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_base.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_cast.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_create_empty.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_create_empty_if_none.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_filter.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_inheritance.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_matches.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_pydantic_model.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_read_write_parquet.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_repr.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_rule_implementation.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_sample.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_serialization.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_storage.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/schema/test_validate.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/storage/test_delta.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/storage/test_fsspec.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/test_compat.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/test_config.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/test_factory.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/test_native_regex.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/test_pydantic.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/test_random.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/test_serialization.py +0 -0
- {dataframely-2.13.0 → dataframely-2.13.1}/tests/test_typing.py +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright (c) QuantCo 2025-2026
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import warnings
|
|
8
|
+
from functools import wraps
|
|
9
|
+
from typing import TYPE_CHECKING, TypeVar
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Callable
|
|
13
|
+
from typing import ParamSpec
|
|
14
|
+
|
|
15
|
+
P = ParamSpec("P")
|
|
16
|
+
T = TypeVar("T")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def issue_deprecation_warning(message: str, *, version: str = "") -> None:
|
|
20
|
+
"""Issue a deprecation warning pointing at the caller of the deprecated method.
|
|
21
|
+
|
|
22
|
+
This must be called directly from the body of the deprecated (public) method so
|
|
23
|
+
that the warning points at the user's code rather than at dataframely internals.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
message: The message associated with the warning.
|
|
27
|
+
version: The dataframely version in which the deprecation occurred (if not
|
|
28
|
+
already part of ``message``).
|
|
29
|
+
"""
|
|
30
|
+
if version:
|
|
31
|
+
message = f"{message.strip()}\n(Deprecated in dataframely {version})"
|
|
32
|
+
# `stacklevel=2` blames the caller of the deprecated method (one frame up from this
|
|
33
|
+
# function). All call sites invoke this directly from the deprecated method body.
|
|
34
|
+
warnings.warn(message, DeprecationWarning, stacklevel=2)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if sys.version_info >= (3, 13):
|
|
38
|
+
from warnings import deprecated
|
|
39
|
+
else:
|
|
40
|
+
try:
|
|
41
|
+
from typing_extensions import deprecated
|
|
42
|
+
except ImportError: # pragma: no cover
|
|
43
|
+
|
|
44
|
+
def deprecated( # type: ignore[no-redef]
|
|
45
|
+
message: str,
|
|
46
|
+
) -> Callable[[Callable[P, T]], Callable[P, T]]:
|
|
47
|
+
"""Fallback for :func:`warnings.deprecated` without :pep:`702` support."""
|
|
48
|
+
|
|
49
|
+
def decorate(function: Callable[P, T]) -> Callable[P, T]:
|
|
50
|
+
@wraps(function)
|
|
51
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
52
|
+
issue_deprecation_warning(message)
|
|
53
|
+
return function(*args, **kwargs)
|
|
54
|
+
|
|
55
|
+
wrapper.__deprecated__ = message # type: ignore[attr-defined]
|
|
56
|
+
return wrapper
|
|
57
|
+
|
|
58
|
+
return decorate
|
|
@@ -28,6 +28,7 @@ import polars as pl
|
|
|
28
28
|
import polars.exceptions as plexc
|
|
29
29
|
|
|
30
30
|
from dataframely._compat import deltalake
|
|
31
|
+
from dataframely._deprecation import deprecated, issue_deprecation_warning
|
|
31
32
|
from dataframely._filter import Filter
|
|
32
33
|
from dataframely._native import format_rule_failures
|
|
33
34
|
from dataframely._plugin import all_rules_required
|
|
@@ -63,6 +64,15 @@ else:
|
|
|
63
64
|
|
|
64
65
|
_FILTER_COLUMN_PREFIX = "__DATAFRAMELY_FILTER_COLUMN__"
|
|
65
66
|
|
|
67
|
+
#: Deprecation message emitted when reading a collection with implicit validation, i.e.
|
|
68
|
+
#: with any ``validation`` other than ``"skip"`` (see #367).
|
|
69
|
+
_IMPLICIT_VALIDATION_DEPRECATION = (
|
|
70
|
+
"Reading a collection with `validation != 'skip'` is deprecated. Starting with "
|
|
71
|
+
"dataframely v3, data is read without inspecting schema metadata and without "
|
|
72
|
+
"running validation. Pass `validation='skip'` to opt into the future behavior, or "
|
|
73
|
+
"call `validate` explicitly if you require validation."
|
|
74
|
+
)
|
|
75
|
+
|
|
66
76
|
P = ParamSpec("P")
|
|
67
77
|
T = TypeVar("T")
|
|
68
78
|
|
|
@@ -1061,7 +1071,16 @@ class Collection(BaseCollection, ABC):
|
|
|
1061
1071
|
Attention:
|
|
1062
1072
|
Be aware that this method suffers from the same limitations as
|
|
1063
1073
|
:meth:`serialize`.
|
|
1074
|
+
|
|
1075
|
+
.. deprecated:: 3.0.0
|
|
1076
|
+
Reading with `validation != "skip"` is deprecated. Starting with
|
|
1077
|
+
dataframely v3, this method reads the data without inspecting any schema
|
|
1078
|
+
metadata and without running validation. Pass `validation="skip"` to opt
|
|
1079
|
+
into this behavior, or call :meth:`validate` explicitly if you require
|
|
1080
|
+
validation.
|
|
1064
1081
|
"""
|
|
1082
|
+
if validation != "skip":
|
|
1083
|
+
issue_deprecation_warning(_IMPLICIT_VALIDATION_DEPRECATION)
|
|
1065
1084
|
return cls._read(
|
|
1066
1085
|
backend=ParquetStorageBackend(),
|
|
1067
1086
|
validation=validation,
|
|
@@ -1118,7 +1137,16 @@ class Collection(BaseCollection, ABC):
|
|
|
1118
1137
|
Attention:
|
|
1119
1138
|
Be aware that this method suffers from the same limitations as
|
|
1120
1139
|
:meth:`serialize`.
|
|
1140
|
+
|
|
1141
|
+
.. deprecated:: 3.0.0
|
|
1142
|
+
Reading with `validation != "skip"` is deprecated. Starting with
|
|
1143
|
+
dataframely v3, this method reads the data without inspecting any schema
|
|
1144
|
+
metadata and without running validation. Pass `validation="skip"` to opt
|
|
1145
|
+
into this behavior, or call :meth:`validate` explicitly if you require
|
|
1146
|
+
validation.
|
|
1121
1147
|
"""
|
|
1148
|
+
if validation != "skip":
|
|
1149
|
+
issue_deprecation_warning(_IMPLICIT_VALIDATION_DEPRECATION)
|
|
1122
1150
|
return cls._read(
|
|
1123
1151
|
backend=ParquetStorageBackend(),
|
|
1124
1152
|
validation=validation,
|
|
@@ -1127,6 +1155,10 @@ class Collection(BaseCollection, ABC):
|
|
|
1127
1155
|
**kwargs,
|
|
1128
1156
|
)
|
|
1129
1157
|
|
|
1158
|
+
@deprecated(
|
|
1159
|
+
"`Collection.write_delta` is deprecated and will be removed in dataframely v3. "
|
|
1160
|
+
"Write the individual members with `polars.DataFrame.write_delta` instead."
|
|
1161
|
+
)
|
|
1130
1162
|
def write_delta(
|
|
1131
1163
|
self, target: str | Path | deltalake.DeltaTable, **kwargs: Any
|
|
1132
1164
|
) -> None:
|
|
@@ -1153,6 +1185,10 @@ class Collection(BaseCollection, ABC):
|
|
|
1153
1185
|
break your schema.
|
|
1154
1186
|
|
|
1155
1187
|
This method suffers from the same limitations as :meth:`~dataframely.Schema.serialize`.
|
|
1188
|
+
|
|
1189
|
+
.. deprecated:: 3.0.0
|
|
1190
|
+
This method is deprecated and will be removed in dataframely v3. Write the
|
|
1191
|
+
individual members with :meth:`polars.DataFrame.write_delta` instead.
|
|
1156
1192
|
"""
|
|
1157
1193
|
self._write(
|
|
1158
1194
|
backend=DeltaStorageBackend(),
|
|
@@ -1161,6 +1197,11 @@ class Collection(BaseCollection, ABC):
|
|
|
1161
1197
|
)
|
|
1162
1198
|
|
|
1163
1199
|
@classmethod
|
|
1200
|
+
@deprecated(
|
|
1201
|
+
"`Collection.scan_delta` is deprecated and will be removed in dataframely v3. "
|
|
1202
|
+
"Read the individual members with `polars.scan_delta` and call `validate` "
|
|
1203
|
+
"explicitly instead."
|
|
1204
|
+
)
|
|
1164
1205
|
def scan_delta(
|
|
1165
1206
|
cls,
|
|
1166
1207
|
source: str | Path | deltalake.DeltaTable,
|
|
@@ -1214,6 +1255,11 @@ class Collection(BaseCollection, ABC):
|
|
|
1214
1255
|
break your schema.
|
|
1215
1256
|
|
|
1216
1257
|
Be aware that this method suffers from the same limitations as :meth:`serialize`.
|
|
1258
|
+
|
|
1259
|
+
.. deprecated:: 3.0.0
|
|
1260
|
+
This method is deprecated and will be removed in dataframely v3. Read the
|
|
1261
|
+
individual members with :meth:`polars.scan_delta` and call :meth:`validate`
|
|
1262
|
+
explicitly instead.
|
|
1217
1263
|
"""
|
|
1218
1264
|
return cls._read(
|
|
1219
1265
|
backend=DeltaStorageBackend(),
|
|
@@ -1223,6 +1269,11 @@ class Collection(BaseCollection, ABC):
|
|
|
1223
1269
|
)
|
|
1224
1270
|
|
|
1225
1271
|
@classmethod
|
|
1272
|
+
@deprecated(
|
|
1273
|
+
"`Collection.read_delta` is deprecated and will be removed in dataframely v3. "
|
|
1274
|
+
"Read the individual members with `polars.read_delta` and call `validate` "
|
|
1275
|
+
"explicitly instead."
|
|
1276
|
+
)
|
|
1226
1277
|
def read_delta(
|
|
1227
1278
|
cls,
|
|
1228
1279
|
source: str | Path | deltalake.DeltaTable,
|
|
@@ -1275,6 +1326,11 @@ class Collection(BaseCollection, ABC):
|
|
|
1275
1326
|
break your schema.
|
|
1276
1327
|
|
|
1277
1328
|
Be aware that this method suffers from the same limitations as :meth:`serialize`.
|
|
1329
|
+
|
|
1330
|
+
.. deprecated:: 3.0.0
|
|
1331
|
+
This method is deprecated and will be removed in dataframely v3. Read the
|
|
1332
|
+
individual members with :meth:`polars.read_delta` and call :meth:`validate`
|
|
1333
|
+
explicitly instead.
|
|
1278
1334
|
"""
|
|
1279
1335
|
return cls._read(
|
|
1280
1336
|
backend=DeltaStorageBackend(),
|
|
@@ -18,6 +18,7 @@ from polars._typing import FileSource
|
|
|
18
18
|
|
|
19
19
|
from ._base_schema import ORIGINAL_COLUMN_PREFIX, BaseSchema
|
|
20
20
|
from ._compat import PartitionSchemeOrSinkDirectory, deltalake, pa, pydantic, sa
|
|
21
|
+
from ._deprecation import deprecated
|
|
21
22
|
from ._match_to_schema import match_to_schema
|
|
22
23
|
from ._native import format_rule_failures
|
|
23
24
|
from ._plugin import all_rules, all_rules_horizontal, all_rules_required
|
|
@@ -897,6 +898,10 @@ class Schema(BaseSchema, ABC):
|
|
|
897
898
|
# ------------------------------------ PARQUET ----------------------------------- #
|
|
898
899
|
|
|
899
900
|
@classmethod
|
|
901
|
+
@deprecated(
|
|
902
|
+
"`Schema.write_parquet` is deprecated and will be removed in dataframely v3. "
|
|
903
|
+
"Use `polars.DataFrame.write_parquet` directly instead."
|
|
904
|
+
)
|
|
900
905
|
def write_parquet(
|
|
901
906
|
cls, df: DataFrame[Self], /, file: str | Path | IO[bytes], **kwargs: Any
|
|
902
907
|
) -> None:
|
|
@@ -919,10 +924,18 @@ class Schema(BaseSchema, ABC):
|
|
|
919
924
|
Attention:
|
|
920
925
|
Be aware that this method suffers from the same limitations as
|
|
921
926
|
:meth:`serialize`.
|
|
927
|
+
|
|
928
|
+
.. deprecated:: 3.0.0
|
|
929
|
+
This method is deprecated and will be removed in dataframely v3. Use
|
|
930
|
+
:meth:`polars.DataFrame.write_parquet` directly instead.
|
|
922
931
|
"""
|
|
923
932
|
cls._write(df=df, backend=ParquetStorageBackend(), file=file, **kwargs)
|
|
924
933
|
|
|
925
934
|
@classmethod
|
|
935
|
+
@deprecated(
|
|
936
|
+
"`Schema.sink_parquet` is deprecated and will be removed in dataframely v3. "
|
|
937
|
+
"Use `polars.LazyFrame.sink_parquet` directly instead."
|
|
938
|
+
)
|
|
926
939
|
def sink_parquet(
|
|
927
940
|
cls,
|
|
928
941
|
lf: LazyFrame[Self],
|
|
@@ -947,10 +960,18 @@ class Schema(BaseSchema, ABC):
|
|
|
947
960
|
Attention:
|
|
948
961
|
Be aware that this method suffers from the same limitations as
|
|
949
962
|
:meth:`serialize`.
|
|
963
|
+
|
|
964
|
+
.. deprecated:: 3.0.0
|
|
965
|
+
This method is deprecated and will be removed in dataframely v3. Use
|
|
966
|
+
:meth:`polars.LazyFrame.sink_parquet` directly instead.
|
|
950
967
|
"""
|
|
951
968
|
cls._sink(lf=lf, backend=ParquetStorageBackend(), file=file, **kwargs)
|
|
952
969
|
|
|
953
970
|
@classmethod
|
|
971
|
+
@deprecated(
|
|
972
|
+
"`Schema.read_parquet` is deprecated and will be removed in dataframely v3. "
|
|
973
|
+
"Use `polars.read_parquet` and call `validate` explicitly instead."
|
|
974
|
+
)
|
|
954
975
|
def read_parquet(
|
|
955
976
|
cls,
|
|
956
977
|
source: FileSource,
|
|
@@ -997,6 +1018,10 @@ class Schema(BaseSchema, ABC):
|
|
|
997
1018
|
Attention:
|
|
998
1019
|
Be aware that this method suffers from the same limitations as
|
|
999
1020
|
:meth:`serialize`.
|
|
1021
|
+
|
|
1022
|
+
.. deprecated:: 3.0.0
|
|
1023
|
+
This method is deprecated and will be removed in dataframely v3. Use
|
|
1024
|
+
:meth:`polars.read_parquet` and call :meth:`validate` explicitly instead.
|
|
1000
1025
|
"""
|
|
1001
1026
|
return cls._read(
|
|
1002
1027
|
ParquetStorageBackend(),
|
|
@@ -1007,6 +1032,10 @@ class Schema(BaseSchema, ABC):
|
|
|
1007
1032
|
)
|
|
1008
1033
|
|
|
1009
1034
|
@classmethod
|
|
1035
|
+
@deprecated(
|
|
1036
|
+
"`Schema.scan_parquet` is deprecated and will be removed in dataframely v3. "
|
|
1037
|
+
"Use `polars.scan_parquet` and call `validate` explicitly instead."
|
|
1038
|
+
)
|
|
1010
1039
|
def scan_parquet(
|
|
1011
1040
|
cls,
|
|
1012
1041
|
source: FileSource,
|
|
@@ -1053,6 +1082,10 @@ class Schema(BaseSchema, ABC):
|
|
|
1053
1082
|
Attention:
|
|
1054
1083
|
Be aware that this method suffers from the same limitations as
|
|
1055
1084
|
:meth:`serialize`.
|
|
1085
|
+
|
|
1086
|
+
.. deprecated:: 3.0.0
|
|
1087
|
+
This method is deprecated and will be removed in dataframely v3. Use
|
|
1088
|
+
:meth:`polars.scan_parquet` and call :meth:`validate` explicitly instead.
|
|
1056
1089
|
"""
|
|
1057
1090
|
return cls._read(
|
|
1058
1091
|
ParquetStorageBackend(),
|
|
@@ -1099,6 +1132,10 @@ class Schema(BaseSchema, ABC):
|
|
|
1099
1132
|
|
|
1100
1133
|
# --------------------------------- Delta -----------------------------------------#
|
|
1101
1134
|
@classmethod
|
|
1135
|
+
@deprecated(
|
|
1136
|
+
"`Schema.write_delta` is deprecated and will be removed in dataframely v3. "
|
|
1137
|
+
"Use `polars.DataFrame.write_delta` directly instead."
|
|
1138
|
+
)
|
|
1102
1139
|
def write_delta(
|
|
1103
1140
|
cls,
|
|
1104
1141
|
df: DataFrame[Self],
|
|
@@ -1127,6 +1164,10 @@ class Schema(BaseSchema, ABC):
|
|
|
1127
1164
|
in violation of group constraints that dataframely cannot catch
|
|
1128
1165
|
without re-validating. Only use appends if you are certain that they do not
|
|
1129
1166
|
break your schema.
|
|
1167
|
+
|
|
1168
|
+
.. deprecated:: 3.0.0
|
|
1169
|
+
This method is deprecated and will be removed in dataframely v3. Use
|
|
1170
|
+
:meth:`polars.DataFrame.write_delta` directly instead.
|
|
1130
1171
|
"""
|
|
1131
1172
|
DeltaStorageBackend().write_frame(
|
|
1132
1173
|
df=df,
|
|
@@ -1135,6 +1176,10 @@ class Schema(BaseSchema, ABC):
|
|
|
1135
1176
|
)
|
|
1136
1177
|
|
|
1137
1178
|
@classmethod
|
|
1179
|
+
@deprecated(
|
|
1180
|
+
"`Schema.scan_delta` is deprecated and will be removed in dataframely v3. "
|
|
1181
|
+
"Use `polars.scan_delta` and call `validate` explicitly instead."
|
|
1182
|
+
)
|
|
1138
1183
|
def scan_delta(
|
|
1139
1184
|
cls,
|
|
1140
1185
|
source: str | Path | deltalake.DeltaTable,
|
|
@@ -1182,6 +1227,10 @@ class Schema(BaseSchema, ABC):
|
|
|
1182
1227
|
that are not through dataframely will result in losing the metadata.
|
|
1183
1228
|
|
|
1184
1229
|
This method suffers from the same limitations as :meth:`serialize`.
|
|
1230
|
+
|
|
1231
|
+
.. deprecated:: 3.0.0
|
|
1232
|
+
This method is deprecated and will be removed in dataframely v3. Use
|
|
1233
|
+
:meth:`polars.scan_delta` and call :meth:`validate` explicitly instead.
|
|
1185
1234
|
"""
|
|
1186
1235
|
return cls._read(
|
|
1187
1236
|
DeltaStorageBackend(),
|
|
@@ -1192,6 +1241,10 @@ class Schema(BaseSchema, ABC):
|
|
|
1192
1241
|
)
|
|
1193
1242
|
|
|
1194
1243
|
@classmethod
|
|
1244
|
+
@deprecated(
|
|
1245
|
+
"`Schema.read_delta` is deprecated and will be removed in dataframely v3. "
|
|
1246
|
+
"Use `polars.read_delta` and call `validate` explicitly instead."
|
|
1247
|
+
)
|
|
1195
1248
|
def read_delta(
|
|
1196
1249
|
cls,
|
|
1197
1250
|
source: str | Path | deltalake.DeltaTable,
|
|
@@ -1244,6 +1297,10 @@ class Schema(BaseSchema, ABC):
|
|
|
1244
1297
|
break your schema.
|
|
1245
1298
|
|
|
1246
1299
|
This method suffers from the same limitations as :meth:`serialize`.
|
|
1300
|
+
|
|
1301
|
+
.. deprecated:: 3.0.0
|
|
1302
|
+
This method is deprecated and will be removed in dataframely v3. Use
|
|
1303
|
+
:meth:`polars.read_delta` and call :meth:`validate` explicitly instead.
|
|
1247
1304
|
"""
|
|
1248
1305
|
return cls._read(
|
|
1249
1306
|
DeltaStorageBackend(),
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Serialization
|
|
2
2
|
|
|
3
|
+
```{warning}
|
|
4
|
+
Most of the I/O functionality described on this page is **deprecated** and will be
|
|
5
|
+
removed in dataframely v3 (see [#367](https://github.com/Quantco/dataframely/issues/367)).
|
|
6
|
+
Calling any of these methods now emits a {class}`DeprecationWarning`. Specifically:
|
|
7
|
+
|
|
8
|
+
- All I/O methods on {class}`~dataframely.Schema`
|
|
9
|
+
({meth}`~dataframely.Schema.write_parquet`, {meth}`~dataframely.Schema.sink_parquet`,
|
|
10
|
+
{meth}`~dataframely.Schema.read_parquet`, {meth}`~dataframely.Schema.scan_parquet`,
|
|
11
|
+
{meth}`~dataframely.Schema.write_delta`, {meth}`~dataframely.Schema.read_delta`,
|
|
12
|
+
{meth}`~dataframely.Schema.scan_delta`) are deprecated. Use the corresponding
|
|
13
|
+
`polars` functions directly and call {meth}`~dataframely.Schema.validate` explicitly
|
|
14
|
+
where validation is required.
|
|
15
|
+
- The `deltalake` I/O methods on {class}`~dataframely.Collection`
|
|
16
|
+
({meth}`~dataframely.Collection.write_delta`, {meth}`~dataframely.Collection.read_delta`,
|
|
17
|
+
{meth}`~dataframely.Collection.scan_delta`) are deprecated.
|
|
18
|
+
- {meth}`~dataframely.Collection.read_parquet` and
|
|
19
|
+
{meth}`~dataframely.Collection.scan_parquet` continue to exist, but reading with
|
|
20
|
+
`validation != "skip"` is deprecated: metadata will no longer be inspected and
|
|
21
|
+
validation will no longer run implicitly. Pass `validation="skip"` to opt into the
|
|
22
|
+
future behavior, or call {meth}`~dataframely.Collection.validate` explicitly.
|
|
23
|
+
```
|
|
24
|
+
|
|
3
25
|
`dataframely` provides support for easily storing and reading validated data.
|
|
4
26
|
`polars` already provides native support for serializing data frames into different storage
|
|
5
27
|
backends. For the storage of the data itself, `dataframely` usually dispatches to polars-native
|
|
@@ -26,17 +26,16 @@ As always, automated testing is useful here, but we also recommend checking the
|
|
|
26
26
|
[published on GitHub](https://github.com/Quantco/dataframely/releases).
|
|
27
27
|
|
|
28
28
|
In order to give users a heads-up before breaking changes are released, we introduce
|
|
29
|
-
[
|
|
29
|
+
[DeprecationWarnings](https://docs.python.org/3/library/exceptions.html#DeprecationWarning).
|
|
30
30
|
Warnings are the most direct and effective tool at our disposal for reaching users directly.
|
|
31
31
|
We therefore generally recommend that users do not silence such warnings explicitly, but instead migrate their code
|
|
32
32
|
proactively, whenever possible.
|
|
33
33
|
However, we also understand that the need for migration may catch users at an inconvenient time, and a temporary band
|
|
34
34
|
aid solution might be required.
|
|
35
|
-
Users can disable `
|
|
36
|
-
[python builtins](https://docs.python.org/3/library/warnings.html#warnings.filterwarnings)
|
|
37
|
-
builtins from tools
|
|
38
|
-
like [pytest](https://docs.pytest.org/en/stable/how-to/capture-warnings.html#controlling-warnings)
|
|
39
|
-
or by setting the `DATAFRAMELY_NO_FUTURE_WARNINGS` environment variable to `true` or `1`.
|
|
35
|
+
Users can disable `DeprecationWarnings` either through
|
|
36
|
+
[python builtins](https://docs.python.org/3/library/warnings.html#warnings.filterwarnings)
|
|
37
|
+
or through builtins from tools
|
|
38
|
+
like [pytest](https://docs.pytest.org/en/stable/how-to/capture-warnings.html#controlling-warnings).
|
|
40
39
|
|
|
41
40
|
## Experimental features
|
|
42
41
|
|
|
@@ -27,7 +27,7 @@ description = "A declarative, polars-native data frame validation library"
|
|
|
27
27
|
name = "dataframely"
|
|
28
28
|
readme = "README.md"
|
|
29
29
|
requires-python = ">=3.10"
|
|
30
|
-
version = "2.13.
|
|
30
|
+
version = "2.13.1"
|
|
31
31
|
|
|
32
32
|
[project.optional-dependencies]
|
|
33
33
|
deltalake = ["deltalake"]
|
|
@@ -107,10 +107,13 @@ addopts = "--import-mode=importlib --benchmark-skip -m 'not s3'"
|
|
|
107
107
|
filterwarnings = [
|
|
108
108
|
# By default, all warnings should yield errors
|
|
109
109
|
"error",
|
|
110
|
-
# Almost all tests are oblivious to the value of `nullable`. Let's ignore the warning as long as it exists.
|
|
111
|
-
"ignore:The 'nullable' argument was not explicitly set:FutureWarning",
|
|
112
110
|
# boto3 still uses .utcnow()
|
|
113
111
|
"ignore::DeprecationWarning:botocore.*:",
|
|
112
|
+
# I/O deprecation warnings (see #367) are asserted in dedicated tests via
|
|
113
|
+
# `pytest.warns`; silence them elsewhere so existing tests keep exercising the
|
|
114
|
+
# still-present functionality.
|
|
115
|
+
"ignore:.*Reading a collection with .validation.*:DeprecationWarning",
|
|
116
|
+
"ignore:.*deprecated and will be removed in dataframely v3.*:DeprecationWarning",
|
|
114
117
|
]
|
|
115
118
|
markers = [
|
|
116
119
|
"s3: tests that run against and S3 backend",
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Copyright (c) QuantCo 2025-2026
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
+
|
|
4
|
+
import warnings
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import polars as pl
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
import dataframely as dy
|
|
11
|
+
from dataframely._deprecation import deprecated, issue_deprecation_warning
|
|
12
|
+
|
|
13
|
+
# ------------------------------------ COMMON ------------------------------------- #
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_issue_deprecation_warning() -> None:
|
|
17
|
+
with pytest.warns(DeprecationWarning, match="my message"):
|
|
18
|
+
issue_deprecation_warning("my message")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_issue_deprecation_warning_with_version() -> None:
|
|
22
|
+
with pytest.warns(DeprecationWarning, match=r"Deprecated in dataframely 3\.0\.0"):
|
|
23
|
+
issue_deprecation_warning("my message", version="3.0.0")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_issue_deprecation_warning_points_at_caller() -> None:
|
|
27
|
+
# The warning should point at this test module, not at dataframely internals.
|
|
28
|
+
with pytest.warns(DeprecationWarning) as record:
|
|
29
|
+
issue_deprecation_warning("my message")
|
|
30
|
+
assert record[0].filename == __file__
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_deprecated_decorator_warns_and_calls() -> None:
|
|
34
|
+
@deprecated("`foo` is deprecated.")
|
|
35
|
+
def foo(x: int) -> int:
|
|
36
|
+
return x + 1
|
|
37
|
+
|
|
38
|
+
with pytest.warns(DeprecationWarning, match="`foo` is deprecated"):
|
|
39
|
+
assert foo(1) == 2
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# ------------------------------------ SCHEMA ------------------------------------- #
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class MySchema(dy.Schema):
|
|
46
|
+
a = dy.Int64()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@pytest.mark.parametrize("method", ["write_parquet", "sink_parquet"])
|
|
50
|
+
def test_schema_write_parquet_deprecated(tmp_path: Path, method: str) -> None:
|
|
51
|
+
df = MySchema.create_empty()
|
|
52
|
+
frame = df.lazy() if method == "sink_parquet" else df
|
|
53
|
+
with pytest.warns(DeprecationWarning, match=f"Schema.{method}"):
|
|
54
|
+
getattr(MySchema, method)(frame, tmp_path / "df.parquet")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@pytest.mark.parametrize("method", ["read_parquet", "scan_parquet"])
|
|
58
|
+
def test_schema_read_parquet_deprecated(tmp_path: Path, method: str) -> None:
|
|
59
|
+
# Arrange: write with plain polars to avoid the write deprecation warning.
|
|
60
|
+
file = tmp_path / "df.parquet"
|
|
61
|
+
pl.DataFrame({"a": []}, schema={"a": pl.Int64}).write_parquet(file)
|
|
62
|
+
|
|
63
|
+
# Act / Assert
|
|
64
|
+
with pytest.warns(DeprecationWarning, match=f"Schema.{method}"):
|
|
65
|
+
getattr(MySchema, method)(file, validation="skip")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_schema_write_delta_deprecated(tmp_path: Path) -> None:
|
|
69
|
+
pytest.importorskip("deltalake")
|
|
70
|
+
with pytest.warns(DeprecationWarning, match="Schema.write_delta"):
|
|
71
|
+
MySchema.write_delta(MySchema.create_empty(), str(tmp_path / "table"))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@pytest.mark.parametrize("method", ["read_delta", "scan_delta"])
|
|
75
|
+
def test_schema_read_delta_deprecated(tmp_path: Path, method: str) -> None:
|
|
76
|
+
pytest.importorskip("deltalake")
|
|
77
|
+
target = str(tmp_path / "table")
|
|
78
|
+
# Write with the (deprecated) writer, silencing its warning.
|
|
79
|
+
with warnings.catch_warnings():
|
|
80
|
+
warnings.simplefilter("ignore", DeprecationWarning)
|
|
81
|
+
MySchema.write_delta(MySchema.create_empty(), target)
|
|
82
|
+
|
|
83
|
+
with pytest.warns(DeprecationWarning, match=f"Schema.{method}"):
|
|
84
|
+
getattr(MySchema, method)(target, validation="skip")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# ---------------------------------- COLLECTION ----------------------------------- #
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class MyCollection(dy.Collection):
|
|
91
|
+
first: dy.LazyFrame[MySchema]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _empty_collection() -> MyCollection:
|
|
95
|
+
return MyCollection.create_empty()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@pytest.mark.parametrize("method", ["read_parquet", "scan_parquet"])
|
|
99
|
+
@pytest.mark.parametrize("validation", ["allow", "warn", "forbid"])
|
|
100
|
+
def test_collection_read_parquet_implicit_validation_deprecated(
|
|
101
|
+
tmp_path: Path, method: str, validation: str
|
|
102
|
+
) -> None:
|
|
103
|
+
# Arrange
|
|
104
|
+
_empty_collection().write_parquet(tmp_path)
|
|
105
|
+
|
|
106
|
+
# Act / Assert: implicit validation is deprecated for all but "skip".
|
|
107
|
+
with pytest.warns(DeprecationWarning, match="validation != 'skip'"):
|
|
108
|
+
getattr(MyCollection, method)(tmp_path, validation=validation)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@pytest.mark.parametrize("method", ["read_parquet", "scan_parquet"])
|
|
112
|
+
def test_collection_read_parquet_skip_not_deprecated(
|
|
113
|
+
tmp_path: Path, method: str
|
|
114
|
+
) -> None:
|
|
115
|
+
# Arrange
|
|
116
|
+
_empty_collection().write_parquet(tmp_path)
|
|
117
|
+
|
|
118
|
+
# Act / Assert: `validation="skip"` does not warn.
|
|
119
|
+
with warnings.catch_warnings():
|
|
120
|
+
warnings.simplefilter("error", DeprecationWarning)
|
|
121
|
+
getattr(MyCollection, method)(tmp_path, validation="skip")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@pytest.mark.parametrize("method", ["write_parquet", "sink_parquet"])
|
|
125
|
+
def test_collection_write_parquet_not_deprecated(tmp_path: Path, method: str) -> None:
|
|
126
|
+
# Act / Assert: writing parquet collections is retained without warning.
|
|
127
|
+
collection = _empty_collection()
|
|
128
|
+
with warnings.catch_warnings():
|
|
129
|
+
warnings.simplefilter("error", DeprecationWarning)
|
|
130
|
+
getattr(collection, method)(tmp_path)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_collection_write_delta_deprecated(tmp_path: Path) -> None:
|
|
134
|
+
pytest.importorskip("deltalake")
|
|
135
|
+
with pytest.warns(DeprecationWarning, match="Collection.write_delta"):
|
|
136
|
+
_empty_collection().write_delta(str(tmp_path / "table"))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@pytest.mark.parametrize("method", ["read_delta", "scan_delta"])
|
|
140
|
+
def test_collection_read_delta_deprecated(tmp_path: Path, method: str) -> None:
|
|
141
|
+
pytest.importorskip("deltalake")
|
|
142
|
+
target = str(tmp_path / "table")
|
|
143
|
+
# Write with the (deprecated) writer, silencing its warning.
|
|
144
|
+
with warnings.catch_warnings():
|
|
145
|
+
warnings.simplefilter("ignore", DeprecationWarning)
|
|
146
|
+
_empty_collection().write_delta(target)
|
|
147
|
+
|
|
148
|
+
with pytest.warns(DeprecationWarning, match=f"Collection.{method}"):
|
|
149
|
+
getattr(MyCollection, method)(target, validation="skip")
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# Copyright (c) QuantCo 2025-2026
|
|
2
|
-
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
-
|
|
4
|
-
import os
|
|
5
|
-
from collections.abc import Callable
|
|
6
|
-
from functools import wraps
|
|
7
|
-
|
|
8
|
-
TRUTHY_VALUES = ["1", "true"]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def skip_if(env: str) -> Callable:
|
|
12
|
-
"""Decorator to skip warnings based on environment variable.
|
|
13
|
-
|
|
14
|
-
If the environment variable is equivalent to any of TRUTHY_VALUES, the wrapped
|
|
15
|
-
function is skipped.
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
def decorator(fun: Callable) -> Callable:
|
|
19
|
-
@wraps(fun)
|
|
20
|
-
def wrapper() -> None:
|
|
21
|
-
if os.getenv(env, "").lower() in TRUTHY_VALUES:
|
|
22
|
-
return
|
|
23
|
-
fun()
|
|
24
|
-
|
|
25
|
-
return wrapper
|
|
26
|
-
|
|
27
|
-
return decorator
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# Copyright (c) QuantCo 2025-2026
|
|
2
|
-
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
-
|
|
4
|
-
import pytest
|
|
5
|
-
|
|
6
|
-
from dataframely._deprecation import skip_if
|
|
7
|
-
|
|
8
|
-
# ------------------------- Common ---------------------------------#
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@pytest.mark.parametrize("env_var", ["1", "True", "true"])
|
|
12
|
-
def test_skip_if(monkeypatch: pytest.MonkeyPatch, env_var: str) -> None:
|
|
13
|
-
"""The skip_if decorator should allow us to prevent execution of a wrapped
|
|
14
|
-
function."""
|
|
15
|
-
variable_name = "DATAFRAMELY_NO_FUTURE_WARNINGS"
|
|
16
|
-
|
|
17
|
-
@skip_if(variable_name)
|
|
18
|
-
def callable() -> None:
|
|
19
|
-
raise ValueError()
|
|
20
|
-
|
|
21
|
-
with pytest.raises(ValueError):
|
|
22
|
-
callable()
|
|
23
|
-
monkeypatch.setenv(variable_name, env_var)
|
|
24
|
-
callable()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|