pointblank 0.8.0__tar.gz → 0.8.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.
Files changed (266) hide show
  1. {pointblank-0.8.0 → pointblank-0.8.1}/PKG-INFO +1 -1
  2. {pointblank-0.8.0 → pointblank-0.8.1}/docs/_quarto.yml +5 -0
  3. pointblank-0.8.1/docs/blog/index.qmd +10 -0
  4. pointblank-0.8.1/docs/blog/intro-pointblank/index.qmd +263 -0
  5. pointblank-0.8.1/docs/blog/intro-pointblank/pointblank-localized.png +0 -0
  6. pointblank-0.8.1/docs/blog/intro-pointblank/step_report.png +0 -0
  7. pointblank-0.8.1/docs/blog/intro-pointblank/validation-table-diagram.png +0 -0
  8. pointblank-0.8.1/docs/blog/intro-pointblank/validation-test-units.png +0 -0
  9. pointblank-0.8.1/docs/blog/pointblank_blog_logo.png +0 -0
  10. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/__init__.py +4 -1
  11. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/_constants_translations.py +2 -2
  12. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/thresholds.py +145 -1
  13. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/validate.py +315 -3
  14. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank.egg-info/PKG-INFO +1 -1
  15. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank.egg-info/SOURCES.txt +7 -0
  16. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test_validate.py +259 -0
  17. {pointblank-0.8.0 → pointblank-0.8.1}/.github/CODE_OF_CONDUCT.md +0 -0
  18. {pointblank-0.8.0 → pointblank-0.8.1}/.github/ISSUE_TEMPLATE/bug.md +0 -0
  19. {pointblank-0.8.0 → pointblank-0.8.1}/.github/ISSUE_TEMPLATE/feature.md +0 -0
  20. {pointblank-0.8.0 → pointblank-0.8.1}/.github/ISSUE_TEMPLATE/question.md +0 -0
  21. {pointblank-0.8.0 → pointblank-0.8.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  22. {pointblank-0.8.0 → pointblank-0.8.1}/.github/SECURITY.md +0 -0
  23. {pointblank-0.8.0 → pointblank-0.8.1}/.github/workflows/ci-docs.yaml +0 -0
  24. {pointblank-0.8.0 → pointblank-0.8.1}/.github/workflows/ci-tests.yaml +0 -0
  25. {pointblank-0.8.0 → pointblank-0.8.1}/.github/workflows/code-checks.yaml +0 -0
  26. {pointblank-0.8.0 → pointblank-0.8.1}/.gitignore +0 -0
  27. {pointblank-0.8.0 → pointblank-0.8.1}/.pre-commit-config.yaml +0 -0
  28. {pointblank-0.8.0 → pointblank-0.8.1}/.vscode/settings.json +0 -0
  29. {pointblank-0.8.0 → pointblank-0.8.1}/CITATION.cff +0 -0
  30. {pointblank-0.8.0 → pointblank-0.8.1}/CONTRIBUTING.md +0 -0
  31. {pointblank-0.8.0 → pointblank-0.8.1}/LICENSE +0 -0
  32. {pointblank-0.8.0 → pointblank-0.8.1}/Makefile +0 -0
  33. {pointblank-0.8.0 → pointblank-0.8.1}/README.md +0 -0
  34. {pointblank-0.8.0 → pointblank-0.8.1}/data_raw/game_revenue.csv +0 -0
  35. {pointblank-0.8.0 → pointblank-0.8.1}/data_raw/nycflights.csv +0 -0
  36. {pointblank-0.8.0 → pointblank-0.8.1}/data_raw/nycflights.ddb +0 -0
  37. {pointblank-0.8.0 → pointblank-0.8.1}/data_raw/small_table.csv +0 -0
  38. {pointblank-0.8.0 → pointblank-0.8.1}/data_raw/x-01-parquet.qmd +0 -0
  39. {pointblank-0.8.0 → pointblank-0.8.1}/data_raw/x-02-duckdb.qmd +0 -0
  40. {pointblank-0.8.0 → pointblank-0.8.1}/data_raw/x-03-sqlite.qmd +0 -0
  41. {pointblank-0.8.0 → pointblank-0.8.1}/docs/.gitignore +0 -0
  42. {pointblank-0.8.0 → pointblank-0.8.1}/docs/_extensions/machow/interlinks/.gitignore +0 -0
  43. {pointblank-0.8.0 → pointblank-0.8.1}/docs/_extensions/machow/interlinks/_extension.yml +0 -0
  44. {pointblank-0.8.0 → pointblank-0.8.1}/docs/_extensions/machow/interlinks/interlinks.lua +0 -0
  45. {pointblank-0.8.0 → pointblank-0.8.1}/docs/assets/fav-logo.png +0 -0
  46. {pointblank-0.8.0 → pointblank-0.8.1}/docs/assets/pointblank-tabular-report.png +0 -0
  47. {pointblank-0.8.0 → pointblank-0.8.1}/docs/assets/pointblank_logo.svg +0 -0
  48. {pointblank-0.8.0 → pointblank-0.8.1}/docs/assets/validation-table-diagram.png +0 -0
  49. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/01-starter/index.qmd +0 -0
  50. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/02-advanced/index.qmd +0 -0
  51. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/03-data-extracts/index.qmd +0 -0
  52. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/04-sundered-data/index.qmd +0 -0
  53. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/05-step-report-column-check/index.qmd +0 -0
  54. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/06-step-report-schema-check/index.qmd +0 -0
  55. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/apply-checks-to-several-columns/index.qmd +0 -0
  56. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/check-row-column-counts/index.qmd +0 -0
  57. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/checks-for-missing/index.qmd +0 -0
  58. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/col-vals-custom-expr/index.qmd +0 -0
  59. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/column-selector-functions/index.qmd +0 -0
  60. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/comparisons-across-columns/index.qmd +0 -0
  61. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/data/game_revenue.parquet +0 -0
  62. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/expect-no-duplicate-rows/index.qmd +0 -0
  63. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/expect-no-duplicate-values/index.qmd +0 -0
  64. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/expect-text-pattern/index.qmd +0 -0
  65. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/failure-thresholds/index.qmd +0 -0
  66. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/img/advanced_validation.png +0 -0
  67. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/img/data_extracts.png +0 -0
  68. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/img/starter_validation.png +0 -0
  69. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/img/step_report_column_schema.png +0 -0
  70. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/img/step_report_column_values.png +0 -0
  71. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/img/sundered_data.png +0 -0
  72. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/index.qmd +0 -0
  73. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/mutate-table-in-step/index.qmd +0 -0
  74. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/numeric-comparisons/index.qmd +0 -0
  75. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/schema-check/index.qmd +0 -0
  76. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/set-membership/index.qmd +0 -0
  77. {pointblank-0.8.0 → pointblank-0.8.1}/docs/demos/using-parquet-data/index.qmd +0 -0
  78. {pointblank-0.8.0 → pointblank-0.8.1}/docs/index.qmd +0 -0
  79. {pointblank-0.8.0 → pointblank-0.8.1}/docs/styles.css +0 -0
  80. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/across.qmd +0 -0
  81. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/actions.qmd +0 -0
  82. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/col-summary-tbl.qmd +0 -0
  83. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/columns.qmd +0 -0
  84. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/extracts.qmd +0 -0
  85. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/index.qmd +0 -0
  86. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/missing-vals-tbl.qmd +0 -0
  87. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/preprocessing.qmd +0 -0
  88. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/preview.qmd +0 -0
  89. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/sundering.qmd +0 -0
  90. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/thresholds.qmd +0 -0
  91. {pointblank-0.8.0 → pointblank-0.8.1}/docs/user-guide/types.qmd +0 -0
  92. {pointblank-0.8.0 → pointblank-0.8.1}/images/pointblank-tabular-report.png +0 -0
  93. {pointblank-0.8.0 → pointblank-0.8.1}/images/pointblank_logo.svg +0 -0
  94. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/_constants.py +0 -0
  95. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/_constants_docs.py +0 -0
  96. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/_interrogation.py +0 -0
  97. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/_typing.py +0 -0
  98. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/_utils.py +0 -0
  99. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/_utils_check_args.py +0 -0
  100. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/_utils_html.py +0 -0
  101. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/assistant.py +0 -0
  102. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/column.py +0 -0
  103. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/data/api-docs.txt +0 -0
  104. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/data/game_revenue-duckdb.zip +0 -0
  105. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/data/game_revenue.zip +0 -0
  106. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/data/nycflights-duckdb.zip +0 -0
  107. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/data/nycflights.zip +0 -0
  108. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/data/polars-api-docs.txt +0 -0
  109. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/data/small_table-duckdb.zip +0 -0
  110. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/data/small_table.zip +0 -0
  111. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/datascan.py +0 -0
  112. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/draft.py +0 -0
  113. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/schema.py +0 -0
  114. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank/tf.py +0 -0
  115. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank.egg-info/dependency_links.txt +0 -0
  116. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank.egg-info/requires.txt +0 -0
  117. {pointblank-0.8.0 → pointblank-0.8.1}/pointblank.egg-info/top_level.txt +0 -0
  118. {pointblank-0.8.0 → pointblank-0.8.1}/pyproject.toml +0 -0
  119. {pointblank-0.8.0 → pointblank-0.8.1}/setup.cfg +0 -0
  120. {pointblank-0.8.0 → pointblank-0.8.1}/tests/__init__.py +0 -0
  121. {pointblank-0.8.0 → pointblank-0.8.1}/tests/manual_tests/schema_step_reports.qmd +0 -0
  122. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_datascan/test_col_summary_tbl_duckdb_snap/col_summary_html_duckdb.html +0 -0
  123. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_datascan/test_col_summary_tbl_pandas_snap/col_summary_html_pandas.html +0 -0
  124. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_datascan/test_col_summary_tbl_polars_snap/col_summary_html_polars.html +0 -0
  125. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_comprehensive_validation_report_html_snap/comprehensive_validation_report.html +0 -0
  126. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_01/schema_step_report_01-0.txt +0 -0
  127. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_01_1/schema_step_report_01-1.txt +0 -0
  128. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_01_2/schema_step_report_01-2.txt +0 -0
  129. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_01_3/schema_step_report_01-3.txt +0 -0
  130. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_02/schema_step_report_02-0.txt +0 -0
  131. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_02_1/schema_step_report_02-1.txt +0 -0
  132. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_02_2/schema_step_report_02-2.txt +0 -0
  133. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_02_3/schema_step_report_02-3.txt +0 -0
  134. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_03/schema_step_report_03-0.txt +0 -0
  135. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_03_1/schema_step_report_03-1.txt +0 -0
  136. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_03_2/schema_step_report_03-2.txt +0 -0
  137. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_03_3/schema_step_report_03-3.txt +0 -0
  138. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_04/schema_step_report_04-0.txt +0 -0
  139. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_05/schema_step_report_05-0.txt +0 -0
  140. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_06/schema_step_report_06-0.txt +0 -0
  141. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_07/schema_step_report_07-0.txt +0 -0
  142. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_08/schema_step_report_08-0.txt +0 -0
  143. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_09/schema_step_report_09-0.txt +0 -0
  144. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_10/schema_step_report_10-0.txt +0 -0
  145. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_11/schema_step_report_11-0.txt +0 -0
  146. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_12/schema_step_report_12-0.txt +0 -0
  147. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_13/schema_step_report_13-0.txt +0 -0
  148. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_14/schema_step_report_14-0.txt +0 -0
  149. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_14_1/schema_step_report_14-1.txt +0 -0
  150. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_15/schema_step_report_15-0.txt +0 -0
  151. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_15_1/schema_step_report_15-1.txt +0 -0
  152. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_16/schema_step_report_16-0.txt +0 -0
  153. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_16_1/schema_step_report_16-1.txt +0 -0
  154. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_17/schema_step_report_17-0.txt +0 -0
  155. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_17_1/schema_step_report_17-1.txt +0 -0
  156. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_18/schema_step_report_18-0.txt +0 -0
  157. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_18_1/schema_step_report_18-1.txt +0 -0
  158. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_19/schema_step_report_19-0.txt +0 -0
  159. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_19_1/schema_step_report_19-1.txt +0 -0
  160. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_20/schema_step_report_20-0.txt +0 -0
  161. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_20_1/schema_step_report_20-1.txt +0 -0
  162. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_21/schema_step_report_21-0.txt +0 -0
  163. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_21_1/schema_step_report_21-1.txt +0 -0
  164. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_21_2/schema_step_report_21-2.txt +0 -0
  165. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_21_3/schema_step_report_21-3.txt +0 -0
  166. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_22/schema_step_report_22-0.txt +0 -0
  167. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_22_1/schema_step_report_22-1.txt +0 -0
  168. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_23/schema_step_report_23-0.txt +0 -0
  169. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_23_1/schema_step_report_23-1.txt +0 -0
  170. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_24/schema_step_report_24-0.txt +0 -0
  171. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_24_1/schema_step_report_24-1.txt +0 -0
  172. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_24_2/schema_step_report_24-2.txt +0 -0
  173. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_24_3/schema_step_report_24-3.txt +0 -0
  174. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_25/schema_step_report_25-0.txt +0 -0
  175. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_25_1/schema_step_report_25-1.txt +0 -0
  176. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_25_2/schema_step_report_25-2.txt +0 -0
  177. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_25_3/schema_step_report_25-3.txt +0 -0
  178. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_25_4/schema_step_report_25-4.txt +0 -0
  179. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_step_report_25_5/schema_step_report_25-5.txt +0 -0
  180. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_01-0.txt +0 -0
  181. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_02-0.txt +0 -0
  182. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_03-0.txt +0 -0
  183. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_04-0.txt +0 -0
  184. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_05-0.txt +0 -0
  185. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_06-0.txt +0 -0
  186. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_07-0.txt +0 -0
  187. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_08-0.txt +0 -0
  188. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_09-0.txt +0 -0
  189. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_10-0.txt +0 -0
  190. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_11-0.txt +0 -0
  191. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_12-0.txt +0 -0
  192. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_13-0.txt +0 -0
  193. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_14-0.txt +0 -0
  194. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_14-1.txt +0 -0
  195. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_15-0.txt +0 -0
  196. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_15-1.txt +0 -0
  197. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_16-0.txt +0 -0
  198. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_16-1.txt +0 -0
  199. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_17-0.txt +0 -0
  200. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_17-1.txt +0 -0
  201. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_18-0.txt +0 -0
  202. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_18-1.txt +0 -0
  203. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_19-0.txt +0 -0
  204. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_19-1.txt +0 -0
  205. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_20-0.txt +0 -0
  206. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_20-1.txt +0 -0
  207. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_21-0.txt +0 -0
  208. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_21-1.txt +0 -0
  209. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_21-2.txt +0 -0
  210. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_21-3.txt +0 -0
  211. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_22-0.txt +0 -0
  212. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_22-1.txt +0 -0
  213. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_23-0.txt +0 -0
  214. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_23-1.txt +0 -0
  215. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_24-0.txt +0 -0
  216. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_24-1.txt +0 -0
  217. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_24-2.txt +0 -0
  218. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_24-3.txt +0 -0
  219. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-0.txt +0 -0
  220. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-1.txt +0 -0
  221. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-2.txt +0 -0
  222. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-3.txt +0 -0
  223. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-4.txt +0 -0
  224. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_get_schema_validation_info/schema_info_25-5.txt +0 -0
  225. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_no_interrogation_validation_report_html_snap/no_interrogation_validation_report.html +0 -0
  226. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_no_steps_validation_report_html_snap/no_steps_validation_report.html +0 -0
  227. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_briefs_global_local_html/validation_report_briefs_global_local.html +0 -0
  228. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_briefs_html/validation_report_with_briefs.html +0 -0
  229. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_duckdb/validation_report.json +0 -0
  230. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_parquet/validation_report.json +0 -0
  231. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_pd/validation_report.json +0 -0
  232. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_pl/validation_report.json +0 -0
  233. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_interrogate_snap/tbl_sqlite/validation_report.json +0 -0
  234. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_duckdb/validation_report.json +0 -0
  235. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_parquet/validation_report.json +0 -0
  236. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_pd/validation_report.json +0 -0
  237. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_pl/validation_report.json +0 -0
  238. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_no_interrogate_snap/tbl_sqlite/validation_report.json +0 -0
  239. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_duckdb/validation_report.json +0 -0
  240. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_parquet/validation_report.json +0 -0
  241. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_pd/validation_report.json +0 -0
  242. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_pl/validation_report.json +0 -0
  243. {pointblank-0.8.0 → pointblank-0.8.1}/tests/snapshots/test_validate/test_validation_report_use_fields_snap/tbl_sqlite/validation_report.json +0 -0
  244. {pointblank-0.8.0 → pointblank-0.8.1}/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
  245. {pointblank-0.8.0 → pointblank-0.8.1}/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
  246. {pointblank-0.8.0 → pointblank-0.8.1}/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
  247. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_dates_times_text.ddb +0 -0
  248. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_dates_times_text.parquet +0 -0
  249. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_dates_times_text.sqlite +0 -0
  250. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_true_dates_times.ddb +0 -0
  251. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_xyz.ddb +0 -0
  252. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_xyz.parquet +0 -0
  253. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_xyz.sqlite +0 -0
  254. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_xyz_missing.ddb +0 -0
  255. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_xyz_missing.parquet +0 -0
  256. {pointblank-0.8.0 → pointblank-0.8.1}/tests/tbl_files/tbl_xyz_missing.sqlite +0 -0
  257. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test__interrogation.py +0 -0
  258. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test__utils.py +0 -0
  259. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test__utils_check_args.py +0 -0
  260. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test_assistant.py +0 -0
  261. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test_column.py +0 -0
  262. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test_datascan.py +0 -0
  263. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test_draft.py +0 -0
  264. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test_schema.py +0 -0
  265. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test_tf.py +0 -0
  266. {pointblank-0.8.0 → pointblank-0.8.1}/tests/test_thresholds.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pointblank
3
- Version: 0.8.0
3
+ Version: 0.8.1
4
4
  Summary: Find out if your data is what you think it is.
5
5
  Author-email: Richard Iannone <riannone@me.com>
6
6
  License: MIT License
@@ -42,6 +42,8 @@ website:
42
42
  file: demos/index.qmd
43
43
  - href: reference/index.qmd
44
44
  text: API Reference
45
+ - href: blog/index.qmd
46
+ text: Pointblog
45
47
  right:
46
48
  - icon: discord
47
49
  href: https://discord.com/invite/YH7CybCNCQ
@@ -96,6 +98,8 @@ quartodoc:
96
98
  members: []
97
99
  - name: Thresholds
98
100
  - name: Actions
101
+ members: []
102
+ - name: FinalActions
99
103
  - name: Schema
100
104
  members: []
101
105
  - name: DraftValidation
@@ -193,4 +197,5 @@ quartodoc:
193
197
  - name: get_column_count
194
198
  - name: get_row_count
195
199
  - name: get_action_metadata
200
+ - name: get_validation_summary
196
201
  - name: config
@@ -0,0 +1,10 @@
1
+ ---
2
+ listing:
3
+ type: table
4
+ sort: "date desc"
5
+ feed: true
6
+ contents:
7
+ - "**.qmd"
8
+ ---
9
+
10
+ ![](./pointblank_blog_logo.png)
@@ -0,0 +1,263 @@
1
+ ---
2
+ jupyter: python3
3
+ html-table-processing: none
4
+ title: "Introducing Pointblank"
5
+ author: Rich Iannone
6
+ date: 2024-04-04
7
+ freeze: true
8
+ ---
9
+
10
+ If you have tabular data (and who doesn't?) this is the package for you! I've long been interested
11
+ in data quality and so I've spent a lot of time building tooling that makes it possible to perform
12
+ data quality checks. And there's so many reasons to care about data quality. If I were to put down
13
+ just one good reason for why data quality is worth your time it is because having good data quality
14
+ strongly determines the quality of decisions.
15
+
16
+ Having the ability to distinguish bad data from good data is the first step in solving DQ issues,
17
+ and the sustained practice of doing data validation will guard against intrusions of poor-quality
18
+ data. Pointblank has been designed to really help here. Though it's a fairly new package it is
19
+ currently quite capable. And it's available in PyPI, so you can install it by using:
20
+
21
+ ```bash
22
+ pip install pointblank
23
+ ```
24
+
25
+ ::: {.callout-note}
26
+ To run the examples in this post, you'll need to have a DataFrame library installed. Pointblank
27
+ works seamlessly with both Polars and Pandas but you'll need to install at least one of them on your
28
+ own. We also have a DuckDB example that's running via Ibis (so, you'll have to install Ibis with
29
+ the DuckDB backend for that to work).
30
+ :::
31
+
32
+ ## How Pointblank Transforms Your Data Validation Workflow
33
+
34
+ What sets Pointblank apart is its intuitive, expressive approach to data validation. Rather than
35
+ writing dozens of ad-hoc checks scattered throughout your codebase, Pointblank lets you define a
36
+ comprehensive validation plan with just a few lines of code. The fluent API makes your validation
37
+ intentions crystal clear, whether you're ensuring numeric values fall within expected ranges, text
38
+ fields match specific patterns, or relationships between columns remain consistent.
39
+
40
+ But say you find problems. What are you gonna do about it? Well, Pointblank wants to help at not
41
+ just finding problems but helping you understand them. When validation failures occur, the detailed
42
+ reporting capabilities (in the form of beautiful, sharable tables) show you exactly where issues
43
+ are. Right down to the specific rows and columns. This transforms data validation from a binary
44
+ pass/fail exercise into a super-insightful diagnostic tool.
45
+
46
+ ![](./step_report.png)
47
+
48
+ Here's the the best part: Pointblank is designed to work with your existing data stack. Whether
49
+ you're using Polars, Pandas, DuckDB, or other database systems, Pointblank tries hard to integrate
50
+ without forcing you to change your workflow. We also have international spoken language support for
51
+ reporting, meaning that validation reports can be localized to your team's preferred language. This
52
+ making data quality accessible to everyone in your organization (like a team sport!).
53
+
54
+ ![](./pointblank-localized.png)
55
+
56
+ Alright! Let's look at a few demonstrations of Pointblank's capabilities for data validation.
57
+
58
+ ## The Data Validation Workflow
59
+
60
+ Let's get right to performing a basic check of a Polars DataFrame. We'll make use of the included
61
+ `small_table` dataset.
62
+
63
+ ```{python}
64
+ import pointblank as pb
65
+
66
+ small_table = pb.load_dataset(dataset="small_table", tbl_type="polars")
67
+
68
+ validation_1 = (
69
+ pb.Validate(
70
+ data=small_table,
71
+ tbl_name="small_table",
72
+ label="Example Validation"
73
+ )
74
+ .col_vals_lt(columns="a", value=10)
75
+ .col_vals_between(columns="d", left=0, right=5000)
76
+ .col_vals_in_set(columns="f", set=["low", "mid", "high"])
77
+ .col_vals_regex(columns="b", pattern=r"^[0-9]-[a-z]{3}-[0-9]{3}$")
78
+ .interrogate()
79
+ )
80
+
81
+ validation_1
82
+ ```
83
+
84
+ There's a lot to take in here so let's break down the code first! Note these three key pieces:
85
+
86
+ - the `Validate(data=...)` argument takes a DataFrame (or database table) that you want to validate
87
+ - the methods starting with `col_*` specify validation steps that run on specific columns
88
+ - the `interrogate()` method executes the validation plan on the table (it's the finishing step)
89
+
90
+ This common pattern is used in a validation workflow, where
91
+ [`Validate`](https://posit-dev.github.io/pointblank/reference/Validate.html) and
92
+ [`interrogate()`](https://posit-dev.github.io/pointblank/reference/Validate.interrogate.html)
93
+ bookend a validation plan generated through calling validation methods.
94
+
95
+ Now, onto the result: it's a table! Naturally, we're using the awesome Great Tables package here in
96
+ Pointblank to really give you the goods on how the validation went down. Each row in this reporting
97
+ table represents a single validation step (one for each invocation of a `col_vals_*()` validation
98
+ method). Generally speaking, the left side of the validation report tables outlines the key
99
+ validation rules, and the right side provides the results of each validation step.
100
+
101
+ We tried to keep it simple in principle, but a lot of useful information can be packed into this
102
+ validation table. Here's a diagram that describes a few of the important parts of the validation
103
+ report table:
104
+
105
+ ![](validation-table-diagram.png){width=100%}
106
+
107
+ All of those numbers under the `UNITS`, `PASS`, and `FAIL` columns have to do with test units, a
108
+ measure of central importance in Pointblank. Each validation step will execute a type of validation
109
+ test on the target table. For example, a
110
+ [`col_vals_lt()`](https://posit-dev.github.io/pointblank/reference/Validate.col_vals_lt.html)
111
+ validation step can test that each value in a column is less than a specified number. The key
112
+ finding that’s reported as a result of this test is the number of test units that pass or fail. This
113
+ little diagram explains what those numbers mean:
114
+
115
+ ![](validation-test-units.png){width=50%, text-align=center}
116
+
117
+ Failing test units can be tied to threshold levels, which can provide a better indication of whether
118
+ failures should raise some basic awareness or spur you into action. Here's a validation workflow
119
+ that sets three failure threshold levels that signal the severity of data quality problems:
120
+
121
+ ```{python}
122
+ import pointblank as pb
123
+ import polars as pl
124
+
125
+ validation_2 = (
126
+ pb.Validate(
127
+ data=pb.load_dataset(dataset="game_revenue", tbl_type="polars"),
128
+ tbl_name="game_revenue",
129
+ label="Data validation with threshold levels set.",
130
+ thresholds=pb.Thresholds(warning=1, error=20, critical=0.10),
131
+ )
132
+ .col_vals_regex(columns="player_id", pattern=r"^[A-Z]{12}[0-9]{3}$") # STEP 1
133
+ .col_vals_gt(columns="session_duration", value=5) # STEP 2
134
+ .col_vals_ge(columns="item_revenue", value=0.02) # STEP 3
135
+ .col_vals_in_set(columns="item_type", set=["iap", "ad"]) # STEP 4
136
+ .col_vals_in_set( # STEP 5
137
+ columns="acquisition",
138
+ set=["google", "facebook", "organic", "crosspromo", "other_campaign"]
139
+ )
140
+ .col_vals_not_in_set(columns="country", set=["Mongolia", "Germany"]) # STEP 6
141
+ .col_vals_between( # STEP 7
142
+ columns="session_duration",
143
+ left=10, right=50,
144
+ pre = lambda df: df.select(pl.median("session_duration"))
145
+ )
146
+ .rows_distinct(columns_subset=["player_id", "session_id", "time"]) # STEP 8
147
+ .row_count_match(count=2000) # STEP 9
148
+ .col_exists(columns="start_day") # STEP 10
149
+ .interrogate()
150
+ )
151
+
152
+ validation_2
153
+ ```
154
+
155
+ This data validation makes use of the many
156
+ [validation methods available in the library](https://posit-dev.github.io/pointblank/reference/#validation-steps).
157
+ Because thresholds have been set at the `Validate(thresholds=)` parameter, we can now see where
158
+ certain validation steps have greater amounts of failures. Any validation steps with green
159
+ indicators passed with flying colors, whereas: (1) gray indicates the 'warning' condition was met
160
+ (at least one test unit failing), (2) yellow is for the 'error' condition (20 or more test units
161
+ failing), and (3) red means 'critical' and that's tripped when 10% of all test units are failing
162
+ ones.
163
+
164
+ Reporting tables are essential to the package and they help communicate what went wrong (or well) in
165
+ a validation workflow. Now let's look at some additional reporting that Pointblank can give you to
166
+ better understand *where* things might've gone wrong.
167
+
168
+ ## Reporting for Individual Validation Steps
169
+
170
+ The second validation step of the previous data validation showed 18 failing test units. That
171
+ translates to 18 spots in a 2,000 row DataFrame where a data quality assertion failed. We often
172
+ would like to know exactly what that failing data is; it's usually the next step toward addressing
173
+ data quality issues.
174
+
175
+ Pointblank offers a method that gives you a tabular report on a specific step:
176
+ [`get_step_report()`](https://posit-dev.github.io/pointblank/reference/Validate.get_step_report.html).
177
+ The previous tables you've seen (the validation report table) dealt with providing a summary of all
178
+ validation steps. In contrast, a focused report on a single step can help to get to the heart of a data
179
+ quality issue. Here's how that looks for Step 2:
180
+
181
+ ```{python}
182
+ validation_2.get_step_report(i=2)
183
+ ```
184
+
185
+ This report provides the 18 rows where the failure occurred. If you scroll the table to the right
186
+ you'll see the column that underwent testing (`session_duration`) is highlighted in red. All of
187
+ these values are `5.0` or less, which is in violation of the assertion (in the header) that
188
+ `session_duration > 5`.
189
+
190
+ These types of bespoke reports are useful for finding a needle in a haystack. Another good use for
191
+ a step report is when validating a table schema. Using the
192
+ [`col_schema_match()`](https://posit-dev.github.io/pointblank/reference/Validate.col_schema_match.html)
193
+ validation method with a table schema prepared with the
194
+ [`Schema`](https://posit-dev.github.io/pointblank/reference/Schema.html) class allows us to verify
195
+ our understanding of the table structure. Here is a validation that performs a schema validation
196
+ with the `small_table` dataset prepared as a DuckDB table:
197
+
198
+ ```{python}
199
+ import pointblank as pb
200
+
201
+ # Create a schema for the target table (`small_table` as a DuckDB table)
202
+ schema = pb.Schema(
203
+ columns=[
204
+ ("date_time", "timestamp(6)"),
205
+ ("dates", "date"),
206
+ ("a", "int64"),
207
+ ("b",),
208
+ ("c",),
209
+ ("d", "float64"),
210
+ ("e", ["bool", "boolean"]),
211
+ ("f", "str"),
212
+ ]
213
+ )
214
+
215
+ # Use the `col_schema_match()` validation method to perform a schema check
216
+ validation_3 = (
217
+ pb.Validate(
218
+ data=pb.load_dataset(dataset="small_table", tbl_type="duckdb"),
219
+ tbl_name="small_table",
220
+ label="Schema check"
221
+ )
222
+ .col_schema_match(schema=schema)
223
+ .interrogate()
224
+ )
225
+
226
+ validation_3
227
+ ```
228
+
229
+ This step fails, but the validation report table doesn't tell us how (or where). Using
230
+ [`get_step_report()](https://posit-dev.github.io/pointblank/reference/Validate.get_step_report.html)
231
+ will show us what the underlying issues are:
232
+
233
+ ```{python}
234
+ validation_3.get_step_report(i=1)
235
+ ```
236
+
237
+ The step report here shows the target table's schema on the left side and the expectation of the
238
+ schema on the right side. There appears to be two problems with our supplied schema:
239
+
240
+ 1. the second column is actually `date` instead of `dates`
241
+ 2. the dtype of the `f` column is `"string"` and not `"str"`
242
+
243
+ The convenience of this step report means we only have to look at one display of information, rather
244
+ than having to collect up the individual pieces and make careful comparisons.
245
+
246
+ ## Much More in Store
247
+
248
+ Pointblank tries really hard to make it easy for you to test your data. All sorts of input tables
249
+ are supported since we integrate with the brilliant
250
+ [Narwhals](https://narwhals-dev.github.io/narwhals/) and
251
+ [Ibis](https://ibis-project.org) libraries. And even through the project has only started four
252
+ months ago, we already have an extensive catalog of well-tested validation methods.
253
+
254
+ We care a great deal about documentation so much recent effort has been placed on getting the
255
+ [**User Guide**](https://posit-dev.github.io/pointblank/user-guide/) written. We hope it provides
256
+ for gentle introduction to the major features of the library. If you want some quick examples to get
257
+ your imagination going, check out our
258
+ [gallery of examples](https://posit-dev.github.io/pointblank/demos/).
259
+
260
+ We really care about what **you** want in a validation package, so talk to us :) We just started a
261
+ [Discord](https://discord.com/invite/YH7CybCNCQ) so feel free to hop on and ask us anything.
262
+ Alternatively, we always like to get [issues](https://github.com/posit-dev/pointblank/issues) so
263
+ don't be shy in letting us know how we could improve!
@@ -24,13 +24,14 @@ from pointblank.datascan import DataScan, col_summary_tbl
24
24
  from pointblank.draft import DraftValidation
25
25
  from pointblank.schema import Schema
26
26
  from pointblank.tf import TF
27
- from pointblank.thresholds import Actions, Thresholds
27
+ from pointblank.thresholds import Actions, FinalActions, Thresholds
28
28
  from pointblank.validate import (
29
29
  Validate,
30
30
  config,
31
31
  get_action_metadata,
32
32
  get_column_count,
33
33
  get_row_count,
34
+ get_validation_summary,
34
35
  load_dataset,
35
36
  missing_vals_tbl,
36
37
  preview,
@@ -42,6 +43,7 @@ __all__ = [
42
43
  "Validate",
43
44
  "Thresholds",
44
45
  "Actions",
46
+ "FinalActions",
45
47
  "Schema",
46
48
  "DataScan",
47
49
  "DraftValidation",
@@ -59,6 +61,7 @@ __all__ = [
59
61
  "preview",
60
62
  "missing_vals_tbl",
61
63
  "get_action_metadata",
64
+ "get_validation_summary",
62
65
  "get_column_count",
63
66
  "get_row_count",
64
67
  ]
@@ -78,7 +78,7 @@ EXPECT_FAIL_TEXT = {
78
78
  "ro": "Se așteaptă ca valorile din {column_text} să fie {operator} {values_text}.",
79
79
  "tr": "Beklenti, {column_text} 'deki değerlerin {operator} {values_text} olması gerektiğidir.",
80
80
  "zh-Hans": "预期在{column_text} 的值应当{operator} {values_text}。",
81
- "zh-Hant": "{column_text}之值應為{operator} {values_text}。",
81
+ "zh-Hant": "{column_text}之值應{operator} {values_text}。",
82
82
  "ja": "{column_text}の値が{operator} {values_text}であることを期待します。",
83
83
  "ko": "{column_text}의 값이 {operator} {values_text}이어야 합니다.",
84
84
  "ru": "Ожидайте, что значения в {column_text} должны быть {operator} {values_text}.",
@@ -101,7 +101,7 @@ EXPECT_FAIL_TEXT = {
101
101
  "ro": "Depășirea unităților de test eșuate unde valorile din {column_text} ar fi trebuit să fie {operator} {values_text}.",
102
102
  "tr": "{column_text} 'deki değerlerin {operator} {values_text} olması gereken başarısız test birimlerinin aşılması.",
103
103
  "zh-Hans": "错误过多,其中{column_text}中的值应当被 {operator} {values_text}。",
104
- "zh-Hant": "錯誤過多,{column_text}之值應為{operator} {values_text}。",
104
+ "zh-Hant": "錯誤過多,{column_text}之值應{operator} {values_text}。",
105
105
  "ja": "{column_text}の値が{operator} {values_text}であるべきテスト単位の失敗の超過。",
106
106
  "ko": "{column_text}의 값이 {operator} {values_text}이어야 했던 실패한 테스트 단위 초과.",
107
107
  "ru": "Превышение неудачных тестовых единиц, где значения в {column_text} должны были быть {operator} {values_text}.",
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from dataclasses import dataclass, field
4
4
  from typing import Callable
5
5
 
6
- __all__ = ["Thresholds", "Actions"]
6
+ __all__ = ["Thresholds", "Actions", "FinalActions"]
7
7
 
8
8
 
9
9
  @dataclass
@@ -373,6 +373,15 @@ class Actions:
373
373
  displayed as `"WARNING: 'col_vals_gt' threshold exceeded for column a."` when the 'warning'
374
374
  threshold is exceeded in a 'col_vals_gt' validation step involving column `a`.
375
375
 
376
+ Crafting Callables with `get_action_metadata()`
377
+ -----------------------------------------------
378
+ When creating a callable function to be used as an action, you can use the
379
+ [`get_action_metadata()`](`pointblank.get_action_metadata`) function to retrieve metadata about
380
+ the step where the action is executed. This metadata contains information about the validation
381
+ step, including the step type, level, step number, column name, and associated value. You can
382
+ use this information to craft your action message or to take specific actions based on the
383
+ metadata provided.
384
+
376
385
  Examples
377
386
  --------
378
387
  ```{python}
@@ -484,3 +493,138 @@ class Actions:
484
493
 
485
494
  def _get_action(self, level: str) -> list[str | Callable]:
486
495
  return getattr(self, level)
496
+
497
+
498
+ @dataclass
499
+ class FinalActions:
500
+ """
501
+ Define actions to be taken after validation is complete.
502
+
503
+ Final actions are executed after all validation steps have been completed. They provide a
504
+ mechanism to respond to the overall validation results, such as sending alerts when critical
505
+ failures are detected or generating summary reports.
506
+
507
+ Parameters
508
+ ----------
509
+ *actions
510
+ One or more actions to execute after validation. An action can be (1) a callable function
511
+ that will be executed with no arguments, or (2) a string message that will be printed to the
512
+ console.
513
+
514
+ Returns
515
+ -------
516
+ FinalActions
517
+ An `FinalActions` object. This can be used when using the
518
+ [`Validate`](`pointblank.Validate`) class (to set final actions for the validation
519
+ workflow).
520
+
521
+ Types of Actions
522
+ ----------------
523
+ Final actions can be defined in two different ways:
524
+
525
+ 1. **String**: A message to be displayed when the validation is complete.
526
+ 2. **Callable**: A function that is called when the validation is complete.
527
+
528
+ The actions are executed at the end of the validation workflow. When providing a string, it will
529
+ simply be printed to the console. A callable will also be executed at the time of validation
530
+ completion. Several strings and callables can be provided to the `FinalActions` class, and
531
+ they will be executed in the order they are provided.
532
+
533
+ Crafting Callables with `get_validation_summary()`
534
+ -------------------------------------------------
535
+ When creating a callable function to be used as a final action, you can use the
536
+ [`get_validation_summary()`](`pointblank.get_validation_summary`) function to retrieve the
537
+ summary of the validation results. This summary contains information about the validation
538
+ workflow, including the number of test units, the number of failing test units, and the
539
+ threshold levels that were exceeded. You can use this information to craft your final action
540
+ message or to take specific actions based on the validation results.
541
+
542
+ Examples
543
+ --------
544
+ Final actions provide a powerful way to respond to the overall results of a validation workflow.
545
+ They're especially useful for sending notifications, generating reports, or taking corrective
546
+ actions based on the complete validation outcome.
547
+
548
+ The following example shows how to create a final action that checks for critical failures
549
+ and sends an alert:
550
+
551
+ ```python
552
+ import pointblank as pb
553
+
554
+ def send_alert():
555
+ summary = pb.get_validation_summary()
556
+ if summary["highest_severity"] == "critical":
557
+ print(f"ALERT: Critical validation failures found in {summary['table_name']}")
558
+
559
+ validation = (
560
+ pb.Validate(
561
+ data=my_data,
562
+ final_actions=pb.FinalActions(send_alert)
563
+ )
564
+ .col_vals_gt(columns="revenue", value=0)
565
+ .interrogate()
566
+ )
567
+ ```
568
+
569
+ In this example, the `send_alert()` function is defined to check the validation summary for
570
+ critical failures. If any are found, an alert message is printed to the console. The function is
571
+ passed to the `FinalActions` class, which ensures it will be executed after all validation steps
572
+ are complete. Note that we used the `get_validation_summary()` function to retrieve the summary
573
+ of the validation results to help craft the alert message.
574
+
575
+ Multiple final actions can be provided in a sequence. They will be executed in the order they
576
+ are specified after all validation steps have completed:
577
+
578
+ ```python
579
+ validation = (
580
+ pb.Validate(
581
+ data=my_data,
582
+ final_actions=pb.FinalActions(
583
+ "Validation complete.", # a string message
584
+ send_alert, # a callable function
585
+ generate_report # another callable function
586
+ )
587
+ )
588
+ .col_vals_gt(columns="revenue", value=0)
589
+ .interrogate()
590
+ )
591
+ ```
592
+ """
593
+
594
+ actions: list | str | Callable
595
+
596
+ def __init__(self, *args):
597
+ # Check that all arguments are either strings or callables
598
+ for arg in args:
599
+ if not isinstance(arg, (str, Callable)) and not (
600
+ isinstance(arg, list) and all(isinstance(item, (str, Callable)) for item in arg)
601
+ ):
602
+ raise TypeError(
603
+ f"All final actions must be strings, callables, or lists of strings/callables. "
604
+ f"Got {type(arg).__name__} instead."
605
+ )
606
+
607
+ if len(args) == 0:
608
+ self.actions = []
609
+ elif len(args) == 1:
610
+ # If a single action is provided, store it directly (not in a list)
611
+ self.actions = args[0]
612
+ else:
613
+ # Multiple actions, store as a list
614
+ self.actions = list(args)
615
+
616
+ def __repr__(self) -> str:
617
+ if isinstance(self.actions, list):
618
+ action_reprs = ", ".join(
619
+ f"'{a}'" if isinstance(a, str) else a.__name__ for a in self.actions
620
+ )
621
+ return f"FinalActions([{action_reprs}])"
622
+ elif isinstance(self.actions, str):
623
+ return f"FinalActions('{self.actions}')"
624
+ elif callable(self.actions):
625
+ return f"FinalActions({self.actions.__name__})"
626
+ else:
627
+ return f"FinalActions({self.actions})" # pragma: no cover
628
+
629
+ def __str__(self) -> str:
630
+ return self.__repr__()