pointblank 0.9.1__tar.gz → 0.9.2__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.
- {pointblank-0.9.1 → pointblank-0.9.2}/PKG-INFO +1 -1
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/_quarto.yml +1 -0
- pointblank-0.9.2/docs/blog/all-about-actions/index.qmd +434 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/_constants.py +14 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/_constants_translations.py +54 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/_interrogation.py +101 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/_utils.py +1 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/actions.py +2 -2
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/data/api-docs.txt +305 -4
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/thresholds.py +3 -2
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/validate.py +393 -11
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank.egg-info/PKG-INFO +1 -1
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank.egg-info/SOURCES.txt +1 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_comprehensive_validation_report_html_snap/comprehensive_validation_report.html +43 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_column.py +2 -2
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_validate.py +118 -2
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/CODE_OF_CONDUCT.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/ISSUE_TEMPLATE/bug.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/ISSUE_TEMPLATE/question.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/SECURITY.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/workflows/ci-docs.yaml +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/workflows/ci-tests.yaml +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.github/workflows/code-checks.yaml +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.gitignore +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.pre-commit-config.yaml +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/.vscode/settings.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/CITATION.cff +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/CONTRIBUTING.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/LICENSE +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/Makefile +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/README.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/data_raw/game_revenue.csv +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/data_raw/nycflights.csv +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/data_raw/nycflights.ddb +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/data_raw/small_table.csv +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/data_raw/x-01-parquet.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/data_raw/x-02-duckdb.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/data_raw/x-03-sqlite.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/.gitignore +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/_extensions/machow/interlinks/.gitignore +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/_extensions/machow/interlinks/_extension.yml +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/_extensions/machow/interlinks/interlinks.lua +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/fav-logo.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.de.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.es.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.fr.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.it.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.ja.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.ko.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.nl.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.pt-BR.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-sales-data.zh-CN.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-step-report.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank-tabular-report.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/pointblank_logo.svg +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/assets/validation-table-diagram.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/blog/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/blog/intro-pointblank/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/blog/intro-pointblank/pointblank-localized.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/blog/intro-pointblank/step_report.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/blog/intro-pointblank/validation-table-diagram.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/blog/intro-pointblank/validation-test-units.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/blog/pointblank_blog_logo.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/01-starter/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/02-advanced/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/03-data-extracts/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/04-sundered-data/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/05-step-report-column-check/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/06-step-report-schema-check/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/apply-checks-to-several-columns/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/check-row-column-counts/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/checks-for-missing/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/col-vals-custom-expr/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/column-selector-functions/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/comparisons-across-columns/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/data/game_revenue.parquet +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/expect-no-duplicate-rows/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/expect-no-duplicate-values/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/expect-text-pattern/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/failure-thresholds/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/img/advanced_validation.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/img/data_extracts.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/img/starter_validation.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/img/step_report_column_schema.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/img/step_report_column_values.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/img/sundered_data.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/mutate-table-in-step/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/numeric-comparisons/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/schema-check/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/set-membership/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/demos/using-parquet-data/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/styles.css +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/actions.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/briefs.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/col-summary-tbl.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/columns.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/extracts.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/index.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/langs.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/missing-vals-tbl.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/preprocessing.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/preview.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/segmentation.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/step-reports.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/sundering.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/thresholds.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/docs/user-guide/types.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/images/pointblank-tabular-report.png +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/images/pointblank_logo.svg +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/__init__.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/_constants_docs.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/_typing.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/_utils_check_args.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/_utils_html.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/assistant.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/column.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/data/game_revenue-duckdb.zip +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/data/game_revenue.zip +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/data/nycflights-duckdb.zip +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/data/nycflights.zip +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/data/polars-api-docs.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/data/small_table-duckdb.zip +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/data/small_table.zip +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/datascan.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/draft.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/schema.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank/tf.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank.egg-info/dependency_links.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank.egg-info/requires.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pointblank.egg-info/top_level.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/pyproject.toml +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/setup.cfg +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/__init__.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/manual_tests/schema_step_reports.qmd +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_datascan/test_col_summary_tbl_duckdb_snap/col_summary_html_duckdb.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_datascan/test_col_summary_tbl_pandas_snap/col_summary_html_pandas.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_datascan/test_col_summary_tbl_polars_snap/col_summary_html_polars.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_01/schema_step_report_01-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_01_1/schema_step_report_01-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_01_2/schema_step_report_01-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_01_3/schema_step_report_01-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_02/schema_step_report_02-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_02_1/schema_step_report_02-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_02_2/schema_step_report_02-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_02_3/schema_step_report_02-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_03/schema_step_report_03-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_03_1/schema_step_report_03-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_03_2/schema_step_report_03-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_03_3/schema_step_report_03-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_04/schema_step_report_04-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_05/schema_step_report_05-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_06/schema_step_report_06-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_07/schema_step_report_07-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_08/schema_step_report_08-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_09/schema_step_report_09-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_10/schema_step_report_10-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_11/schema_step_report_11-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_12/schema_step_report_12-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_13/schema_step_report_13-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_14/schema_step_report_14-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_14_1/schema_step_report_14-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_15/schema_step_report_15-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_15_1/schema_step_report_15-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_16/schema_step_report_16-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_16_1/schema_step_report_16-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_17/schema_step_report_17-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_17_1/schema_step_report_17-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_18/schema_step_report_18-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_18_1/schema_step_report_18-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_19/schema_step_report_19-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_19_1/schema_step_report_19-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_20/schema_step_report_20-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_20_1/schema_step_report_20-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_21/schema_step_report_21-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_21_1/schema_step_report_21-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_21_2/schema_step_report_21-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_21_3/schema_step_report_21-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_22/schema_step_report_22-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_22_1/schema_step_report_22-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_23/schema_step_report_23-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_23_1/schema_step_report_23-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_24/schema_step_report_24-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_24_1/schema_step_report_24-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_24_2/schema_step_report_24-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_24_3/schema_step_report_24-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_25/schema_step_report_25-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_25_1/schema_step_report_25-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_25_2/schema_step_report_25-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_25_3/schema_step_report_25-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_25_4/schema_step_report_25-4.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_step_report_25_5/schema_step_report_25-5.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_01-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_02-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_03-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_04-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_05-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_06-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_07-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_08-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_09-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_10-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_11-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_12-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_13-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_14-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_14-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_15-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_15-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_16-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_16-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_17-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_17-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_18-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_18-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_19-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_19-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_20-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_20-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_21-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_21-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_21-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_21-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_22-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_22-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_23-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_23-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_24-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_24-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_24-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_24-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-0.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-1.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-2.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-3.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-4.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-5.txt +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_no_interrogation_validation_report_html_snap/no_interrogation_validation_report.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_no_steps_validation_report_html_snap/no_steps_validation_report.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_briefs_global_local_html/validation_report_briefs_global_local.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_briefs_html/validation_report_with_briefs.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_duckdb/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_parquet/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_pd/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_pl/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_sqlite/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_duckdb/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_parquet/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_pd/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_pl/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_sqlite/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_segments_html/duckdb/validation_report_segments.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_segments_html/pandas/validation_report_segments.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_segments_html/polars/validation_report_segments.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_segments_with_pre_html/polars/validation_report_segments_with_pre.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_segments_with_pre_html/validation_report_segments_with_pre.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_duckdb/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_parquet/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_pd/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_pl/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_sqlite/validation_report.json +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_memtable_variable_names/selector_helper_functions_no_match.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pd_variable_names/selector_helper_functions_no_match.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pl_variable_names/selector_helper_functions_no_match.html +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_dates_times_text.ddb +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_dates_times_text.parquet +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_dates_times_text.sqlite +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_true_dates_times.ddb +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_xyz.ddb +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_xyz.parquet +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_xyz.sqlite +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_xyz_missing.ddb +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_xyz_missing.parquet +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/tbl_files/tbl_xyz_missing.sqlite +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test__interrogation.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test__utils.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test__utils_check_args.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_actions.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_assistant.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_datascan.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_draft.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_schema.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_tf.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/tests/test_thresholds.py +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.de.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.es.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.fr.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.it.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.ja.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.ko.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.nl.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.pt-BR.md +0 -0
- {pointblank-0.9.1 → pointblank-0.9.2}/translations/README.zh-CN.md +0 -0
|
@@ -133,6 +133,7 @@ quartodoc:
|
|
|
133
133
|
- name: Validate.row_count_match
|
|
134
134
|
- name: Validate.col_count_match
|
|
135
135
|
- name: Validate.conjointly
|
|
136
|
+
- name: Validate.specially
|
|
136
137
|
- title: Column Selection
|
|
137
138
|
desc: >
|
|
138
139
|
A flexible way to select columns for validation is to use the `col()` function along with
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
---
|
|
2
|
+
jupyter: python3
|
|
3
|
+
html-table-processing: none
|
|
4
|
+
title: "Level Up Your Data Validation with `Actions` and `FinalActions`"
|
|
5
|
+
author: Rich Iannone
|
|
6
|
+
date: 2025-05-02
|
|
7
|
+
freeze: true
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
```{python}
|
|
11
|
+
#| echo: false
|
|
12
|
+
#| output: false
|
|
13
|
+
import pointblank as pb
|
|
14
|
+
pb.config(report_incl_footer=False)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Data validation is only useful if you can respond appropriately when problems arise. That's why
|
|
18
|
+
Pointblank's recent `v0.8.0` and `v0.8.1` releases have significantly enhanced our action framework,
|
|
19
|
+
allowing you to create sophisticated, automated responses to validation failures.
|
|
20
|
+
|
|
21
|
+
In this post, we'll explore how to use:
|
|
22
|
+
|
|
23
|
+
1. **Actions** to respond to individual validation failures
|
|
24
|
+
2. **FinalActions** to execute code after your entire validation plan completes
|
|
25
|
+
3. New customization features that make your validation workflows more expressive
|
|
26
|
+
|
|
27
|
+
Let's dive into how these features can transform your data validation process from passive reporting
|
|
28
|
+
to active response.
|
|
29
|
+
|
|
30
|
+
## From Passive Validation to Active Response
|
|
31
|
+
|
|
32
|
+
Traditional data validation simply reports problems: "Column X has invalid values." But what if you
|
|
33
|
+
want to:
|
|
34
|
+
|
|
35
|
+
- send a Slack message when critical errors occur?
|
|
36
|
+
- log detailed diagnostics about failing data?
|
|
37
|
+
- trigger automatic data cleaning processes?
|
|
38
|
+
- generate custom reports for stakeholders?
|
|
39
|
+
|
|
40
|
+
This is where Pointblank's action system can help. By pairing thresholds with actions, you can
|
|
41
|
+
create automated responses that trigger exactly when needed.
|
|
42
|
+
|
|
43
|
+
## Getting Started with Actions
|
|
44
|
+
|
|
45
|
+
Actions are executed when validation steps fail to meet certain thresholds. Let's start with a
|
|
46
|
+
simple example:
|
|
47
|
+
|
|
48
|
+
```{python}
|
|
49
|
+
import pointblank as pb
|
|
50
|
+
|
|
51
|
+
validation_1 = (
|
|
52
|
+
pb.Validate(data=pb.load_dataset(dataset="small_table"))
|
|
53
|
+
.col_vals_gt(
|
|
54
|
+
columns="d",
|
|
55
|
+
value=1000,
|
|
56
|
+
thresholds=pb.Thresholds(warning=1, error=5),
|
|
57
|
+
actions=pb.Actions(
|
|
58
|
+
warning="⚠️ WARNING: Some values in column 'd' are below the minimum threshold!"
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
.interrogate()
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
validation_1
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
In this example:
|
|
68
|
+
|
|
69
|
+
1. we're validating that values in column "d" are greater than 1000
|
|
70
|
+
2. we set a warning threshold of 1 (triggers if any values fail)
|
|
71
|
+
3. we define an action that prints a warning message when the threshold is exceeded
|
|
72
|
+
|
|
73
|
+
Since several values in column `d` are below `1000`, our 'warning' action is triggered and the
|
|
74
|
+
message appears above the validation report.
|
|
75
|
+
|
|
76
|
+
## The Anatomy of Actions
|
|
77
|
+
|
|
78
|
+
The [`Actions`](https://posit-dev.github.io/pointblank/reference/Actions.html) class is a very
|
|
79
|
+
important piece of Pointblank's response system. Actions can be defined in several ways:
|
|
80
|
+
|
|
81
|
+
1. **String messages**: simple text output to the console
|
|
82
|
+
2. **Callable functions**: custom Python functions that execute when triggered
|
|
83
|
+
3. **Lists of strings/callables**: multiple actions that execute in sequence
|
|
84
|
+
|
|
85
|
+
Actions can be paired with different severity levels:
|
|
86
|
+
|
|
87
|
+
- 'warning': for minor issues that need attention
|
|
88
|
+
- 'error': for more significant problems
|
|
89
|
+
- 'critical': for severe issues that require immediate action
|
|
90
|
+
|
|
91
|
+
The `v0.8.0` release added two (very) useful new parameters:
|
|
92
|
+
|
|
93
|
+
- `default=`: apply the same action to all threshold levels
|
|
94
|
+
- `highest_only=`: only trigger the action for the highest threshold level reached (`True` by
|
|
95
|
+
default)
|
|
96
|
+
|
|
97
|
+
Let's see how these work in practice:
|
|
98
|
+
|
|
99
|
+
```{python}
|
|
100
|
+
def log_problem():
|
|
101
|
+
# Simple action that runs when thresholds are exceeded
|
|
102
|
+
print("A validation threshold has been exceeded!")
|
|
103
|
+
|
|
104
|
+
validation_2 = (
|
|
105
|
+
pb.Validate(
|
|
106
|
+
data=pb.load_dataset(dataset="game_revenue"),
|
|
107
|
+
thresholds=pb.Thresholds(warning=0.05, error=0.10, critical=0.15),
|
|
108
|
+
actions=pb.Actions(default=log_problem) # Apply this action to all threshold levels
|
|
109
|
+
)
|
|
110
|
+
.col_vals_regex(
|
|
111
|
+
columns="player_id",
|
|
112
|
+
pattern=r"[A-Z]{12}\d{3}"
|
|
113
|
+
)
|
|
114
|
+
.col_vals_gt(
|
|
115
|
+
columns="item_revenue",
|
|
116
|
+
value=0.10
|
|
117
|
+
)
|
|
118
|
+
.interrogate()
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
validation_2
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
In this example, we're using a simple function that prints a generic message whenever any threshold
|
|
125
|
+
is exceeded. By using the `Actions(default=)` parameter, this same function gets applied to all
|
|
126
|
+
threshold levels ('warning', 'error', and 'critical'). This saves you from having to define separate
|
|
127
|
+
actions for each level when you want the same behavior for all of them. The `highest_only=`
|
|
128
|
+
parameter (`True` by default, so not shown here) is complementary and it ensures that only the
|
|
129
|
+
action for the highest threshold level reached will be triggered, preventing multiple notifications
|
|
130
|
+
for the same validation failure.
|
|
131
|
+
|
|
132
|
+
## Dynamic Messages with Templating
|
|
133
|
+
|
|
134
|
+
Actions don't have to be static messages. With Pointblank's templating system, you can create
|
|
135
|
+
context-aware notifications that include details about the specific validation failure.
|
|
136
|
+
|
|
137
|
+
Available placeholders include:
|
|
138
|
+
|
|
139
|
+
- `{type}`: the validation step type (e.g., `"col_vals_gt"`)
|
|
140
|
+
- `{level}`: the threshold level ('warning', 'error', 'critical')
|
|
141
|
+
- `{step}` or `{i}`: the step number in the validation workflow
|
|
142
|
+
- `{col}` or `{column}`: the column name being validated
|
|
143
|
+
- `{val}` or `{value}`: the comparison value used in the validation
|
|
144
|
+
- `{time}`: when the action was executed
|
|
145
|
+
|
|
146
|
+
You can also capitalize placeholders (like `{LEVEL}`) to get uppercase text.
|
|
147
|
+
|
|
148
|
+
```{python}
|
|
149
|
+
action_template = "[{LEVEL}] Step {step}: Values in '{column}' failed validation against {value}."
|
|
150
|
+
|
|
151
|
+
validation_3 = (
|
|
152
|
+
pb.Validate(
|
|
153
|
+
data=pb.load_dataset(dataset="small_table"),
|
|
154
|
+
thresholds=pb.Thresholds(warning=1, error=4, critical=10),
|
|
155
|
+
actions=pb.Actions(default=action_template)
|
|
156
|
+
)
|
|
157
|
+
.col_vals_lt(
|
|
158
|
+
columns="d",
|
|
159
|
+
value=3000
|
|
160
|
+
)
|
|
161
|
+
.interrogate()
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
validation_3
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
This templating approach is a great way to create context-aware notifications that adapt to the
|
|
168
|
+
specific validation failures occurring. As the example shows, when values in column `d` fail
|
|
169
|
+
validation against the limit of `3000`, the template automatically generates a meaningful error
|
|
170
|
+
message showing exactly which step, column, and threshold value was involved.
|
|
171
|
+
|
|
172
|
+
## Accessing Metadata in Custom Action Functions
|
|
173
|
+
|
|
174
|
+
For more sophisticated actions, you often need access to details about the validation failure. The
|
|
175
|
+
`get_action_metadata()` function provides this context when called inside an action function:
|
|
176
|
+
|
|
177
|
+
```{python}
|
|
178
|
+
def send_detailed_alert():
|
|
179
|
+
# Get metadata about the validation failure
|
|
180
|
+
metadata = pb.get_action_metadata()
|
|
181
|
+
|
|
182
|
+
# Create a customized alert message
|
|
183
|
+
print(f"""
|
|
184
|
+
VALIDATION FAILURE DETAILS
|
|
185
|
+
-------------------------
|
|
186
|
+
Step: {metadata['step']}
|
|
187
|
+
Column: {metadata['column']}
|
|
188
|
+
Validation type: {metadata['type']}
|
|
189
|
+
Severity: {metadata['level']} (level {metadata['level_num']})
|
|
190
|
+
Time: {metadata['time']}
|
|
191
|
+
|
|
192
|
+
Explanation: {metadata['failure_text']}
|
|
193
|
+
""")
|
|
194
|
+
|
|
195
|
+
validation_4 = (
|
|
196
|
+
pb.Validate(
|
|
197
|
+
data=pb.load_dataset(dataset="small_table"),
|
|
198
|
+
thresholds=pb.Thresholds(critical=1),
|
|
199
|
+
actions=pb.Actions(critical=send_detailed_alert)
|
|
200
|
+
)
|
|
201
|
+
.col_vals_gt(
|
|
202
|
+
columns="d",
|
|
203
|
+
value=5000
|
|
204
|
+
)
|
|
205
|
+
.interrogate()
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
validation_4
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The metadata dictionary contains essential fields for a given validation step, including the step
|
|
212
|
+
number, column name, validation type, severity level, and failure explanation. This gives you
|
|
213
|
+
complete flexibility to create highly customized responses based on the specific nature of the
|
|
214
|
+
validation failure.
|
|
215
|
+
|
|
216
|
+
## Final Actions with `FinalActions`
|
|
217
|
+
|
|
218
|
+
While regular [`Actions`](https://posit-dev.github.io/pointblank/reference/Actions.html) are great
|
|
219
|
+
for responding to individual validation steps, sometimes you need to take action based on the
|
|
220
|
+
overall validation results. This is where the new `FinalActions` feature from `v0.8.1` comes in.
|
|
221
|
+
|
|
222
|
+
Unlike regular [`Actions`](https://posit-dev.github.io/pointblank/reference/Actions.html) that
|
|
223
|
+
trigger during validation,
|
|
224
|
+
[`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html) execute after
|
|
225
|
+
all validation steps are complete.
|
|
226
|
+
[`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html) accepts any
|
|
227
|
+
number of actions (strings or callables) and executes them in sequence. Each argument can be a
|
|
228
|
+
string message to display in the console, a callable function, or a list of strings/callables for
|
|
229
|
+
multiple actions to execute in sequence.
|
|
230
|
+
|
|
231
|
+
The real power of [`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html)
|
|
232
|
+
comes from the ability to access comprehensive information about your validation results using
|
|
233
|
+
[`get_validation_summary()`](https://posit-dev.github.io/pointblank/reference/get_validation_summary.html).
|
|
234
|
+
When called inside a function passed to
|
|
235
|
+
[`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html), this function
|
|
236
|
+
provides a dictionary containing counts of passing/failing steps and test units, threshold levels
|
|
237
|
+
exceeded, and much more:
|
|
238
|
+
|
|
239
|
+
```{python}
|
|
240
|
+
def generate_summary():
|
|
241
|
+
# Access comprehensive validation results
|
|
242
|
+
summary = pb.get_validation_summary()
|
|
243
|
+
|
|
244
|
+
print("\n=== VALIDATION SUMMARY ===")
|
|
245
|
+
print(f"Total steps: {summary['n_steps']}")
|
|
246
|
+
print(f"Passing steps: {summary['n_passing_steps']}")
|
|
247
|
+
print(f"Failing steps: {summary['n_failing_steps']}")
|
|
248
|
+
|
|
249
|
+
if summary['highest_severity'] == "critical":
|
|
250
|
+
print("\n⚠️ CRITICAL FAILURES DETECTED - immediate action required!")
|
|
251
|
+
elif summary['highest_severity'] == "error":
|
|
252
|
+
print("\n⚠️ ERRORS DETECTED - review needed")
|
|
253
|
+
elif summary['highest_severity'] == "warning":
|
|
254
|
+
print("\n⚠️ WARNINGS DETECTED - please investigate")
|
|
255
|
+
else:
|
|
256
|
+
print("\n✅ All validations passed!")
|
|
257
|
+
|
|
258
|
+
validation_5 = (
|
|
259
|
+
pb.Validate(
|
|
260
|
+
data=pb.load_dataset(dataset="small_table"),
|
|
261
|
+
tbl_name="small_table",
|
|
262
|
+
thresholds=pb.Thresholds(warning=1, error=5, critical=10),
|
|
263
|
+
final_actions=pb.FinalActions(
|
|
264
|
+
"Validation process complete.", # A simple string message
|
|
265
|
+
generate_summary # Our function using get_validation_summary()
|
|
266
|
+
)
|
|
267
|
+
)
|
|
268
|
+
.col_vals_gt(columns="a", value=1)
|
|
269
|
+
.col_vals_lt(columns="d", value=10000)
|
|
270
|
+
.interrogate()
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
validation_5
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The [`get_validation_summary()`](https://posit-dev.github.io/pointblank/reference/get_validation_summary.html)
|
|
277
|
+
function is only available within functions passed to
|
|
278
|
+
[`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html). It gives you
|
|
279
|
+
access to these key dictionary fields:
|
|
280
|
+
|
|
281
|
+
- `tbl_name`: name of the validated table
|
|
282
|
+
- `n_steps`: total number of validation steps
|
|
283
|
+
- `n_passing_steps`, n_failing_steps: count of passing/failing steps
|
|
284
|
+
- `n`, `n_passed`, `n_failed`: total test units and their pass/fail counts
|
|
285
|
+
- `highest_severity`: the most severe threshold level reached ('warning', 'error', 'critical')
|
|
286
|
+
- and many more detailed statistics
|
|
287
|
+
|
|
288
|
+
This information allows you to create detailed and specific final actions that can respond
|
|
289
|
+
appropriately to the overall validation results.
|
|
290
|
+
|
|
291
|
+
## Combining Regular and Final Actions
|
|
292
|
+
|
|
293
|
+
You can use both [`Actions`](https://posit-dev.github.io/pointblank/reference/Actions.html) and
|
|
294
|
+
[`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html) together for
|
|
295
|
+
comprehensive control over your validation workflow:
|
|
296
|
+
|
|
297
|
+
```{python}
|
|
298
|
+
def step_alert():
|
|
299
|
+
metadata = pb.get_action_metadata()
|
|
300
|
+
print(f"Step {metadata['step']} failed with {metadata['level']} severity")
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def final_summary():
|
|
304
|
+
summary = pb.get_validation_summary()
|
|
305
|
+
|
|
306
|
+
# Get counts by checking each step's status in the dictionaries
|
|
307
|
+
steps = range(1, summary['n_steps'] + 1)
|
|
308
|
+
n_critical = sum(1 for step in steps if summary['dict_critical'].get(step, False))
|
|
309
|
+
n_error = sum(1 for step in steps if summary['dict_error'].get(step, False))
|
|
310
|
+
n_warning = sum(1 for step in steps if summary['dict_warning'].get(step, False))
|
|
311
|
+
|
|
312
|
+
print(f"\nValidation complete with:")
|
|
313
|
+
print(f"- {n_critical} critical issues")
|
|
314
|
+
print(f"- {n_error} errors")
|
|
315
|
+
print(f"- {n_warning} warnings")
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
validation_6 = (
|
|
319
|
+
pb.Validate(
|
|
320
|
+
data=pb.load_dataset(dataset="small_table"),
|
|
321
|
+
thresholds=pb.Thresholds(warning=1, error=5, critical=10),
|
|
322
|
+
actions=pb.Actions(default=step_alert),
|
|
323
|
+
final_actions=pb.FinalActions(final_summary),
|
|
324
|
+
)
|
|
325
|
+
.col_vals_gt(columns="a", value=5)
|
|
326
|
+
.col_vals_lt(columns="d", value=1000)
|
|
327
|
+
.interrogate()
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
validation_6
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
This approach allows you to log individual step failures during the validation process using
|
|
334
|
+
[`Actions`](https://posit-dev.github.io/pointblank/reference/Actions.html) and generate a
|
|
335
|
+
comprehensive report after all validation steps are complete using
|
|
336
|
+
[`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html). Using both
|
|
337
|
+
action types gives you fine-grained control over when and how notifications and other actions are
|
|
338
|
+
triggered in your validation workflow.
|
|
339
|
+
|
|
340
|
+
## Real-World Example: Building an Automated Validation Pipeline
|
|
341
|
+
|
|
342
|
+
Let's put everything together in a more realistic example. Imagine you're validating a gaming
|
|
343
|
+
revenue dataset and want to:
|
|
344
|
+
|
|
345
|
+
1. log detailed information about each failure
|
|
346
|
+
2. send a Slack notification if critical failures occur
|
|
347
|
+
3. generate a comprehensive report after validation completes
|
|
348
|
+
|
|
349
|
+
```{python}
|
|
350
|
+
def log_step_failure():
|
|
351
|
+
metadata = pb.get_action_metadata()
|
|
352
|
+
print(f"[{metadata['level'].upper()}] Step {metadata['step']}: {metadata['failure_text']}")
|
|
353
|
+
|
|
354
|
+
def analyze_results():
|
|
355
|
+
summary = pb.get_validation_summary()
|
|
356
|
+
|
|
357
|
+
# Calculate overall pass rate
|
|
358
|
+
pass_rate = (summary['n_passing_steps'] / summary['n_steps']) * 100
|
|
359
|
+
|
|
360
|
+
print(f"\n==== VALIDATION RESULTS ====")
|
|
361
|
+
print(f"Table: {summary['tbl_name']}")
|
|
362
|
+
print(f"Pass rate: {pass_rate:.2f}%")
|
|
363
|
+
print(f"Failing steps: {summary['n_failing_steps']} of {summary['n_steps']}")
|
|
364
|
+
|
|
365
|
+
# In a real scenario, here you might:
|
|
366
|
+
# 1. Save results to a database
|
|
367
|
+
# 2. Generate and email an HTML report
|
|
368
|
+
# 3. Trigger data cleansing workflows
|
|
369
|
+
|
|
370
|
+
# Simulate a Slack notification
|
|
371
|
+
if summary['highest_severity'] == "critical":
|
|
372
|
+
print("\n🚨 [SLACK NOTIFICATION] Critical data quality issues detected!")
|
|
373
|
+
print("@data-team Please investigate immediately.")
|
|
374
|
+
|
|
375
|
+
# Create our validation workflow with actions
|
|
376
|
+
validation_7 = (
|
|
377
|
+
pb.Validate(
|
|
378
|
+
data=pb.load_dataset(dataset="game_revenue"),
|
|
379
|
+
tbl_name="game_revenue",
|
|
380
|
+
thresholds=pb.Thresholds(warning=0.05, error=0.10, critical=0.15),
|
|
381
|
+
actions=pb.Actions(default=log_step_failure, highest_only=True),
|
|
382
|
+
final_actions=pb.FinalActions(analyze_results),
|
|
383
|
+
brief=True # Add automatically-generated briefs
|
|
384
|
+
)
|
|
385
|
+
.col_vals_regex(
|
|
386
|
+
columns="player_id",
|
|
387
|
+
pattern=r"[A-Z]{12}\d{3}",
|
|
388
|
+
brief="Player IDs must follow standard format" # Custom brief text
|
|
389
|
+
)
|
|
390
|
+
.col_vals_gt(
|
|
391
|
+
columns="item_revenue",
|
|
392
|
+
value=0.10
|
|
393
|
+
)
|
|
394
|
+
.col_vals_gt(
|
|
395
|
+
columns="session_duration",
|
|
396
|
+
value=15
|
|
397
|
+
)
|
|
398
|
+
.interrogate()
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
validation_7
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Wrapping Up: from Passive Validation to Active Data Quality Management
|
|
405
|
+
|
|
406
|
+
With [`Actions`](https://posit-dev.github.io/pointblank/reference/Actions.html) and
|
|
407
|
+
[`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html), Pointblank is
|
|
408
|
+
now more of a complete data quality management system. Instead of just detecting problems, you can
|
|
409
|
+
now:
|
|
410
|
+
|
|
411
|
+
1. respond immediately to validation failures
|
|
412
|
+
2. customize responses based on severity level
|
|
413
|
+
3. generate comprehensive reports after validation completes
|
|
414
|
+
4. integrate with other systems through custom action functions
|
|
415
|
+
5. automate workflows based on validation results
|
|
416
|
+
|
|
417
|
+
These capabilities transform data validation from a passive reporting activity into an active
|
|
418
|
+
component of your data pipeline, helping ensure that data quality issues are detected, reported, and
|
|
419
|
+
addressed efficiently.
|
|
420
|
+
|
|
421
|
+
As we continue to enhance Pointblank, we'd love to hear how you're using
|
|
422
|
+
[`Actions`](https://posit-dev.github.io/pointblank/reference/Actions.html) and
|
|
423
|
+
[`FinalActions`](https://posit-dev.github.io/pointblank/reference/FinalActions.html) in your
|
|
424
|
+
workflows. Share your experiences or suggestions with us on
|
|
425
|
+
[Discord](https://discord.gg/YH7CybCNCQ) or file an issue on
|
|
426
|
+
[GitHub](https://github.com/posit-dev/pointblank/issues).
|
|
427
|
+
|
|
428
|
+
## Learn More
|
|
429
|
+
|
|
430
|
+
Explore our documentation to learn more about Pointblank's action capabilities:
|
|
431
|
+
|
|
432
|
+
- [Actions documentation](https://posit-dev.github.io/pointblank/reference/Actions.html)
|
|
433
|
+
- [FinalActions documentation](https://posit-dev.github.io/pointblank/reference/FinalActions.html)
|
|
434
|
+
- [User Guide on Triggering Actions](https://posit-dev.github.io/pointblank/user-guide/actions.html)
|
|
@@ -44,6 +44,7 @@ ASSERTION_TYPE_METHOD_MAP = {
|
|
|
44
44
|
"row_count_match": "row_count_match",
|
|
45
45
|
"col_count_match": "col_count_match",
|
|
46
46
|
"conjointly": "conjointly",
|
|
47
|
+
"specially": "specially",
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
METHOD_CATEGORY_MAP = {
|
|
@@ -69,6 +70,7 @@ METHOD_CATEGORY_MAP = {
|
|
|
69
70
|
"row_count_match": "ROW_COUNT_MATCH",
|
|
70
71
|
"col_count_match": "COL_COUNT_MATCH",
|
|
71
72
|
"conjointly": "CONJOINTLY",
|
|
73
|
+
"specially": "SPECIALLY",
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
COMPARISON_OPERATORS = {
|
|
@@ -455,6 +457,18 @@ SVG_ICONS_FOR_ASSERTION_TYPES = {
|
|
|
455
457
|
<path d="M51.8485976,12 L15.5758703,12 C13.9986329,12 12.712234,13.2863989 12.712234,14.8636364 L12.712234,51.1363636 C12.712234,52.7136011 13.9986329,54 15.5758703,54 L51.8485976,54 C53.4258351,54 54.712234,52.7136011 54.712234,51.1363636 L54.712234,14.8636364 C54.712234,13.2863989 53.4258351,12 51.8485976,12 Z M37.072234,44 L20.272234,44 L20.272234,42 L37.072234,42 L37.072234,44 Z M37.072234,34 L20.272234,34 L20.272234,32 L37.072234,32 L37.072234,34 Z M37.072234,24 L20.272234,24 L20.272234,22 L37.072234,22 L37.072234,24 Z M47.9233279,41.773438 L45.5706719,45.773438 C45.4427029,45.996094 45.239265,46.148438 45.0095779,46.1875 C44.9702029,46.195313 44.9275469,46.199219 44.88489,46.199219 C44.70114,46.199219 44.5206719,46.128906 44.373015,45.992188 L42.1877029,43.992188 C41.8202029,43.65625 41.7512969,43.027344 42.033484,42.589844 C42.3156719,42.152344 42.8439529,42.070313 43.2114529,42.40625 L44.697859,43.769531 L46.548484,40.625 C46.814265,40.171875 47.335984,40.0625 47.716609,40.378906 C48.097234,40.695313 48.189109,41.320313 47.9233279,41.773438 Z M47.9233279,31.773438 L45.5706719,35.773438 C45.4427029,35.996094 45.239265,36.148438 45.0095779,36.1875 C44.9702029,36.195313 44.9275469,36.199219 44.88489,36.199219 C44.70114,36.199219 44.5206719,36.128906 44.373015,35.992188 L42.1877029,33.992188 C41.8202029,33.65625 41.7512969,33.027344 42.033484,32.589844 C42.3156719,32.152344 42.8439529,32.070313 43.2114529,32.40625 L44.697859,33.769531 L46.548484,30.628906 C46.814265,30.175781 47.335984,30.0625 47.716609,30.382813 C48.097234,30.699219 48.189109,31.320313 47.9233279,31.773438 Z M47.9233279,21.773438 L45.5706719,25.773438 C45.4427029,25.996094 45.239265,26.148438 45.0095779,26.1875 C44.9702029,26.195313 44.9275469,26.199219 44.88489,26.199219 C44.70114,26.199219 44.5206719,26.128906 44.373015,25.992188 L42.1877029,23.992188 C41.8202029,23.65625 41.7512969,23.027344 42.033484,22.589844 C42.3156719,22.152344 42.8439529,22.070313 43.2114529,22.40625 L44.697859,23.769531 L46.548484,20.625 C46.814265,20.171875 47.335984,20.0625 47.716609,20.378906 C48.097234,20.699219 48.189109,21.320313 47.9233279,21.773438 Z" id="conjoint" fill="#000000" fill-rule="nonzero"></path>
|
|
456
458
|
</g>
|
|
457
459
|
</g>
|
|
460
|
+
</svg>""",
|
|
461
|
+
"specially": """<?xml version="1.0" encoding="UTF-8"?>
|
|
462
|
+
<svg width="67px" height="67px" viewBox="0 0 67 67" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
463
|
+
<title>specially</title>
|
|
464
|
+
<g id="All-Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
465
|
+
<g id="specially" transform="translate(0.000000, 0.206897)">
|
|
466
|
+
<path d="M56.712234,1 C59.1975153,1 61.4475153,2.00735931 63.076195,3.63603897 C64.7048747,5.26471863 65.712234,7.51471863 65.712234,10 L65.712234,10 L65.712234,65 L10.712234,65 C8.22695259,65 5.97695259,63.9926407 4.34827294,62.363961 C2.71959328,60.7352814 1.71223397,58.4852814 1.71223397,56 L1.71223397,56 L1.71223397,10 C1.71223397,7.51471863 2.71959328,5.26471863 4.34827294,3.63603897 C5.97695259,2.00735931 8.22695259,1 10.712234,1 L10.712234,1 Z" id="rectangle" stroke="#000000" stroke-width="2" fill="#FFFFFF"></path>
|
|
467
|
+
<g id="star" transform="translate(8.500000, 8.500000)" fill="#000000" fill-rule="nonzero">
|
|
468
|
+
<path d="M25,0 C24.5874484,0 24.2174517,0.254002847 24.068359,0.6386719 L17.902344,16.535156 L0.94921875,17.400391 C0.536124409,17.4213013 0.17852458,17.6943523 0.0495446395,18.0873515 C-0.0794353012,18.4803507 0.046820452,18.9122002 0.3671875,19.173828 L13.568359,29.966797 L9.2324219,46.34375 C9.12646963,46.7428009 9.27663058,47.1659433 9.61042698,47.4089402 C9.94422338,47.651937 10.3930345,47.664834 10.740234,47.441406 L25,38.289062 L39.259766,47.441406 C39.6069655,47.6648339 40.0557766,47.6519369 40.3895729,47.4089401 C40.7233693,47.1659432 40.8735302,46.7428009 40.767578,46.34375 L36.431641,29.966797 L49.632812,19.173828 C49.953179,18.9122002 50.0794348,18.4803507 49.9504549,18.0873516 C49.821475,17.6943524 49.4638753,17.4213014 49.050781,17.400391 L32.097656,16.535156 L25.931641,0.6386719 C25.7825483,0.254002847 25.4125516,0 25,0 Z M25,3.7636719 L30.466797,17.861328 C30.609689,18.2291416 30.9554962,18.4785515 31.349609,18.498047 L46.359375,19.265625 L34.667969,28.826172 C34.3646054,29.0742114 34.2340493,29.4765679 34.333984,29.855469 L38.175781,44.369141 L25.541016,36.257812 C25.2114789,36.0458536 24.7885211,36.0458536 24.458984,36.257812 L11.824219,44.369141 L15.666016,29.855469 C15.7659507,29.4765679 15.6353946,29.0742114 15.332031,28.826172 L3.640625,19.265625 L18.650391,18.498047 C19.0445038,18.4785515 19.390311,18.2291416 19.533203,17.861328 L25,3.7636719 Z" id="Shape"></path>
|
|
469
|
+
</g>
|
|
470
|
+
</g>
|
|
471
|
+
</g>
|
|
458
472
|
</svg>""",
|
|
459
473
|
}
|
|
460
474
|
|
|
@@ -1160,6 +1160,60 @@ EXPECT_FAIL_TEXT = {
|
|
|
1160
1160
|
"hi": "असफल परीक्षण इकाइयों की अधिकता जहां संयुक्त 'पास' इकाइयां होनी चाहिए थीं।",
|
|
1161
1161
|
"el": "Υπέρβαση αποτυχημένων μονάδων δοκιμής όπου θα έπρεπε να υπάρχουν κοινές μονάδες 'επιτυχίας'.",
|
|
1162
1162
|
},
|
|
1163
|
+
"specially_expectation_text": {
|
|
1164
|
+
"en": "Expect that special testing with a given function yields agreement.",
|
|
1165
|
+
"fr": "On s'attend à ce que les tests spéciaux avec une fonction donnée produisent un accord.",
|
|
1166
|
+
"de": "Erwarten Sie, dass spezielle Tests mit einer bestimmten Funktion Übereinstimmung ergeben.",
|
|
1167
|
+
"it": "Aspettati che i test speciali con una funzione data producano accordo.",
|
|
1168
|
+
"es": "Se espera que las pruebas especiales con una función dada produzcan concordancia.",
|
|
1169
|
+
"pt": "Espera-se que testes especiais com uma função dada produzam concordância.",
|
|
1170
|
+
"ro": "Se așteaptă ca testarea specială cu o funcție dată să producă acord.",
|
|
1171
|
+
"tr": "Belirli bir fonksiyonla özel testlerin uyum sağlamasını bekleyin.",
|
|
1172
|
+
"zh-Hans": "预期使用给定函数的特殊测试会产生一致结果。",
|
|
1173
|
+
"zh-Hant": "預期使用給定函數的特殊測試會產生一致結果。",
|
|
1174
|
+
"ja": "指定された関数による特別なテストが一致することを期待します。",
|
|
1175
|
+
"ko": "주어진 함수로 특수 테스트를 수행하면 일치함을 기대합니다.",
|
|
1176
|
+
"vi": "Kỳ vọng rằng kiểm tra đặc biệt với một hàm đã cho sẽ cho kết quả phù hợp.",
|
|
1177
|
+
"ru": "Ожидайте, что специальное тестирование с заданной функцией дает согласие.",
|
|
1178
|
+
"cs": "Očekává se, že speciální testování s danou funkcí přinese shodu.",
|
|
1179
|
+
"pl": "Oczekuj, że specjalne testowanie z użyciem danej funkcji przyniesie zgodność.",
|
|
1180
|
+
"da": "Forvent at speciel test med en given funktion giver overensstemmelse.",
|
|
1181
|
+
"sv": "Förvänta dig att speciell testning med en given funktion ger överensstämmelse.",
|
|
1182
|
+
"nb": "Forvent at spesiell testing med en gitt funksjon gir samsvar.",
|
|
1183
|
+
"nl": "Verwacht dat speciale tests met een gegeven functie overeenstemming opleveren.",
|
|
1184
|
+
"fi": "Odota, että erityinen testaus annetulla funktiolla tuottaa yhdenmukaisuuden.",
|
|
1185
|
+
"is": "Væntir þess að sérstök prófun með gefnu falli leiði til samræmis.",
|
|
1186
|
+
"ar": "توقع أن الاختبار الخاص بدالة معينة يؤدي إلى التوافق.",
|
|
1187
|
+
"hi": "अपेक्षा है कि दिए गए फ़ंक्शन के साथ विशेष परीक्षण सहमति प्रदान करेगा।",
|
|
1188
|
+
"el": "Αναμένεται ότι ο ειδικός έλεγχος με μια δεδομένη συνάρτηση αποδίδει συμφωνία.",
|
|
1189
|
+
},
|
|
1190
|
+
"specially_failure_text": {
|
|
1191
|
+
"en": "Exceedance of failed test units when performing specialized testing with a given function.",
|
|
1192
|
+
"fr": "Dépassement des unités de test ayant échoué lors de l'exécution de tests spécialisés avec une fonction donnée.",
|
|
1193
|
+
"de": "Überschreitung fehlgeschlagener Testeinheiten bei der Durchführung spezialisierter Tests mit einer bestimmten Funktion.",
|
|
1194
|
+
"it": "Superamento delle unità di test fallite durante l'esecuzione di test specializzati con una funzione data.",
|
|
1195
|
+
"es": "Se superó el número de unidades de prueba fallidas al realizar pruebas especializadas con una función dada.",
|
|
1196
|
+
"pt": "Excedeu o número de unidades de teste com falha ao realizar testes especializados com uma função dada.",
|
|
1197
|
+
"ro": "Depășirea unităților de test eșuate la efectuarea testării specializate cu o funcție dată.",
|
|
1198
|
+
"tr": "Belirli bir fonksiyonla özel testler yapılırken başarısız test birimlerinin aşılması.",
|
|
1199
|
+
"zh-Hans": "使用给定函数进行专门测试时,失败的测试单元数量超标。",
|
|
1200
|
+
"zh-Hant": "使用給定函數進行專門測試時,失敗的測試單元數量超標。",
|
|
1201
|
+
"ja": "指定された関数を使用した特殊テスト実行時のテスト単位の失敗の超過。",
|
|
1202
|
+
"ko": "주어진 함수로 특수 테스트를 수행할 때 실패한 테스트 단위 초과.",
|
|
1203
|
+
"vi": "Vượt quá số đơn vị kiểm tra thất bại khi thực hiện kiểm tra chuyên biệt với một hàm đã cho.",
|
|
1204
|
+
"ru": "Превышение неудачных тестовых единиц при выполнении специализированного тестирования с заданной функцией.",
|
|
1205
|
+
"cs": "Překročení počtu neúspěšných testovacích jednotek při provádění specializovaného testování s danou funkcí.",
|
|
1206
|
+
"pl": "Przekroczenie nieudanych jednostek testowych podczas przeprowadzania specjalistycznych testów z daną funkcją.",
|
|
1207
|
+
"da": "Overskridelse af fejlslagne testenheder ved udførelse af specialiseret test med en given funktion.",
|
|
1208
|
+
"sv": "Överskrider antalet misslyckade testenheter vid utförande av specialiserad testning med en given funktion.",
|
|
1209
|
+
"nb": "Overskridelse av mislykkede testenheter ved utførelse av spesialisert testing med en gitt funksjon.",
|
|
1210
|
+
"nl": "Overschrijding van mislukte testeenheden bij het uitvoeren van gespecialiseerde tests met een gegeven functie.",
|
|
1211
|
+
"fi": "Epäonnistuneiden testiyksiköiden ylitys suoritettaessa erikoistestejä annetulla funktiolla.",
|
|
1212
|
+
"is": "Of mörg misheppnuð próf við framkvæmd sérhæfðra prófana með gefnu falli.",
|
|
1213
|
+
"ar": "تجاوز وحدات الاختبار الفاشلة عند إجراء اختبار متخصص بدالة معينة.",
|
|
1214
|
+
"hi": "दिए गए फ़ंक्शन के साथ विशेष परीक्षण करते समय असफल परीक्षण इकाइयों की अधिकता।",
|
|
1215
|
+
"el": "Υπέρβαση αποτυχημένων μονάδων δοκιμής κατά την εκτέλεση εξειδικευμένων ελέγχων με μια δεδομένη συνάρτηση.",
|
|
1216
|
+
},
|
|
1163
1217
|
}
|
|
1164
1218
|
|
|
1165
1219
|
|
|
@@ -2248,6 +2248,107 @@ class ConjointlyValidation:
|
|
|
2248
2248
|
return results_tbl
|
|
2249
2249
|
|
|
2250
2250
|
|
|
2251
|
+
class SpeciallyValidation:
|
|
2252
|
+
def __init__(self, data_tbl, expression, threshold, tbl_type):
|
|
2253
|
+
self.data_tbl = data_tbl
|
|
2254
|
+
self.expression = expression
|
|
2255
|
+
self.threshold = threshold
|
|
2256
|
+
|
|
2257
|
+
# Detect the table type
|
|
2258
|
+
if tbl_type in (None, "local"):
|
|
2259
|
+
# Detect the table type using _get_tbl_type()
|
|
2260
|
+
self.tbl_type = _get_tbl_type(data=data_tbl)
|
|
2261
|
+
else:
|
|
2262
|
+
self.tbl_type = tbl_type
|
|
2263
|
+
|
|
2264
|
+
def get_test_results(self) -> any | list[bool]:
|
|
2265
|
+
"""Evaluate the expression get either a list of booleans or a results table."""
|
|
2266
|
+
|
|
2267
|
+
# Get the expression and inspect whether there is a `data` argument
|
|
2268
|
+
expression = self.expression
|
|
2269
|
+
|
|
2270
|
+
import inspect
|
|
2271
|
+
|
|
2272
|
+
# During execution of `specially` validation
|
|
2273
|
+
sig = inspect.signature(expression)
|
|
2274
|
+
params = list(sig.parameters.keys())
|
|
2275
|
+
|
|
2276
|
+
# Execute the function based on its signature
|
|
2277
|
+
if len(params) == 0:
|
|
2278
|
+
# No parameters: call without arguments
|
|
2279
|
+
result = expression()
|
|
2280
|
+
elif len(params) == 1:
|
|
2281
|
+
# One parameter: pass the data table
|
|
2282
|
+
data_tbl = self.data_tbl
|
|
2283
|
+
result = expression(data_tbl)
|
|
2284
|
+
else:
|
|
2285
|
+
# More than one parameter - this doesn't match either allowed signature
|
|
2286
|
+
raise ValueError(
|
|
2287
|
+
f"The function provided to 'specially()' should have either no parameters or a "
|
|
2288
|
+
f"single 'data' parameter, but it has {len(params)} parameters: {params}"
|
|
2289
|
+
)
|
|
2290
|
+
|
|
2291
|
+
# Determine if the object is a DataFrame by inspecting the string version of its type
|
|
2292
|
+
if (
|
|
2293
|
+
"pandas" in str(type(result))
|
|
2294
|
+
or "polars" in str(type(result))
|
|
2295
|
+
or "ibis" in str(type(result))
|
|
2296
|
+
):
|
|
2297
|
+
# Get the type of the table
|
|
2298
|
+
tbl_type = _get_tbl_type(data=result)
|
|
2299
|
+
|
|
2300
|
+
if "pandas" in tbl_type:
|
|
2301
|
+
# If it's a Pandas DataFrame, check if the last column is a boolean column
|
|
2302
|
+
last_col = result.iloc[:, -1]
|
|
2303
|
+
|
|
2304
|
+
import pandas as pd
|
|
2305
|
+
|
|
2306
|
+
if last_col.dtype == bool or pd.api.types.is_bool_dtype(last_col):
|
|
2307
|
+
# If the last column is a boolean column, rename it as `pb_is_good_`
|
|
2308
|
+
result.rename(columns={result.columns[-1]: "pb_is_good_"}, inplace=True)
|
|
2309
|
+
elif "polars" in tbl_type:
|
|
2310
|
+
# If it's a Polars DataFrame, check if the last column is a boolean column
|
|
2311
|
+
last_col_name = result.columns[-1]
|
|
2312
|
+
last_col_dtype = result.schema[last_col_name]
|
|
2313
|
+
|
|
2314
|
+
import polars as pl
|
|
2315
|
+
|
|
2316
|
+
if last_col_dtype == pl.Boolean:
|
|
2317
|
+
# If the last column is a boolean column, rename it as `pb_is_good_`
|
|
2318
|
+
result = result.rename({last_col_name: "pb_is_good_"})
|
|
2319
|
+
elif tbl_type in IBIS_BACKENDS:
|
|
2320
|
+
# If it's an Ibis table, check if the last column is a boolean column
|
|
2321
|
+
last_col_name = result.columns[-1]
|
|
2322
|
+
result_schema = result.schema()
|
|
2323
|
+
is_last_col_bool = str(result_schema[last_col_name]) == "boolean"
|
|
2324
|
+
|
|
2325
|
+
if is_last_col_bool:
|
|
2326
|
+
# If the last column is a boolean column, rename it as `pb_is_good_`
|
|
2327
|
+
result = result.rename(pb_is_good_=last_col_name)
|
|
2328
|
+
|
|
2329
|
+
else: # pragma: no cover
|
|
2330
|
+
raise NotImplementedError(f"Support for {tbl_type} is not yet implemented")
|
|
2331
|
+
|
|
2332
|
+
elif isinstance(result, bool):
|
|
2333
|
+
# If it's a single boolean, return that as a list
|
|
2334
|
+
return [result]
|
|
2335
|
+
|
|
2336
|
+
elif isinstance(result, list):
|
|
2337
|
+
# If it's a list, check that it is a boolean list
|
|
2338
|
+
if all(isinstance(x, bool) for x in result):
|
|
2339
|
+
# If it's a list of booleans, return it as is
|
|
2340
|
+
return result
|
|
2341
|
+
else:
|
|
2342
|
+
# If it's not a list of booleans, raise an error
|
|
2343
|
+
raise TypeError("The result is not a list of booleans.")
|
|
2344
|
+
else: # pragma: no cover
|
|
2345
|
+
# If it's not a DataFrame or a list, raise an error
|
|
2346
|
+
raise TypeError("The result is not a DataFrame or a list of booleans.")
|
|
2347
|
+
|
|
2348
|
+
# Return the results table or list of booleans
|
|
2349
|
+
return result
|
|
2350
|
+
|
|
2351
|
+
|
|
2251
2352
|
@dataclass
|
|
2252
2353
|
class NumberOfTestUnits:
|
|
2253
2354
|
"""
|