tablevalidator-databricks 0.1.2__tar.gz → 0.1.3__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.
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/PKG-INFO +7 -7
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/README.md +6 -6
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks/templates/widget_notebook.py.tmpl +20 -20
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks.egg-info/PKG-INFO +7 -7
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks.egg-info/scm_version.json +2 -2
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tests/test_generated_notebook_execution.py +65 -23
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/pyproject.toml +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/setup.cfg +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks/__init__.py +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks/cli/__init__.py +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks/cli/main.py +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks/generator/__init__.py +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks/generator/generator.py +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks.egg-info/SOURCES.txt +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks.egg-info/dependency_links.txt +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks.egg-info/entry_points.txt +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks.egg-info/requires.txt +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks.egg-info/scm_file_list.json +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tablevalidator_databricks.egg-info/top_level.txt +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tests/test_cli.py +0 -0
- {tablevalidator_databricks-0.1.2 → tablevalidator_databricks-0.1.3}/tests/test_generator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tablevalidator-databricks
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Generates a widget-driven Databricks notebook UI on top of the table-validator package - no code required to run a comparison.
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -45,12 +45,12 @@ Writes `./TableValidator.py` - a ready-to-use Databricks notebook. Options:
|
|
|
45
45
|
tablevalidator-databricks init --output MyValidation.py --mode full
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
- `--mode basic` - only the check-group
|
|
48
|
+
- `--mode basic` - only the check-group Yes/No dropdowns and table pickers.
|
|
49
49
|
- `--mode full` (default) - also shows optional filter widgets (only/
|
|
50
|
-
ignore columns, row filter, primary key).
|
|
51
|
-
- `--mode schema` - same widgets as `basic
|
|
52
|
-
schema-shape-only comparison
|
|
53
|
-
|
|
50
|
+
ignore columns, row filter, primary key). Every check defaults to "Yes".
|
|
51
|
+
- `--mode schema` - same widgets as `basic`, but Column/Row default to
|
|
52
|
+
"No" - a lightweight schema-shape-only comparison out of the box (still
|
|
53
|
+
changeable per-run).
|
|
54
54
|
|
|
55
55
|
Then, in your Databricks workspace: **Workspace -> Import**, format
|
|
56
56
|
"Source", and select the generated file. Databricks recognizes the
|
|
@@ -63,7 +63,7 @@ markers and opens it as a real notebook.
|
|
|
63
63
|
2. Queries Unity Catalog (`SHOW CATALOGS` / `SHOW SCHEMAS IN ...` /
|
|
64
64
|
`SHOW TABLES IN ...` via the notebook's own ambient Spark session) to
|
|
65
65
|
populate Source/Target Catalog, Schema, and Table dropdowns.
|
|
66
|
-
3. Shows a
|
|
66
|
+
3. Shows a Yes/No dropdown per check group (Catalog & Schema / Column /
|
|
67
67
|
Row - the three independently-selectable check groups the engine
|
|
68
68
|
actually supports) plus, in `full` mode, optional text widgets for
|
|
69
69
|
column filtering, a row filter, and a primary key.
|
|
@@ -31,12 +31,12 @@ Writes `./TableValidator.py` - a ready-to-use Databricks notebook. Options:
|
|
|
31
31
|
tablevalidator-databricks init --output MyValidation.py --mode full
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
- `--mode basic` - only the check-group
|
|
34
|
+
- `--mode basic` - only the check-group Yes/No dropdowns and table pickers.
|
|
35
35
|
- `--mode full` (default) - also shows optional filter widgets (only/
|
|
36
|
-
ignore columns, row filter, primary key).
|
|
37
|
-
- `--mode schema` - same widgets as `basic
|
|
38
|
-
schema-shape-only comparison
|
|
39
|
-
|
|
36
|
+
ignore columns, row filter, primary key). Every check defaults to "Yes".
|
|
37
|
+
- `--mode schema` - same widgets as `basic`, but Column/Row default to
|
|
38
|
+
"No" - a lightweight schema-shape-only comparison out of the box (still
|
|
39
|
+
changeable per-run).
|
|
40
40
|
|
|
41
41
|
Then, in your Databricks workspace: **Workspace -> Import**, format
|
|
42
42
|
"Source", and select the generated file. Databricks recognizes the
|
|
@@ -49,7 +49,7 @@ markers and opens it as a real notebook.
|
|
|
49
49
|
2. Queries Unity Catalog (`SHOW CATALOGS` / `SHOW SCHEMAS IN ...` /
|
|
50
50
|
`SHOW TABLES IN ...` via the notebook's own ambient Spark session) to
|
|
51
51
|
populate Source/Target Catalog, Schema, and Table dropdowns.
|
|
52
|
-
3. Shows a
|
|
52
|
+
3. Shows a Yes/No dropdown per check group (Catalog & Schema / Column /
|
|
53
53
|
Row - the three independently-selectable check groups the engine
|
|
54
54
|
actually supports) plus, in `full` mode, optional text widgets for
|
|
55
55
|
column filtering, a row filter, and a primary key.
|
|
@@ -180,18 +180,20 @@ print(
|
|
|
180
180
|
|
|
181
181
|
# COMMAND ----------
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
# dbutils.widgets.multiselect
|
|
185
|
-
#
|
|
186
|
-
#
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
#
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
dbutils.widgets.
|
|
183
|
+
# One Yes/No dropdown per check group, instead of a single multiselect -
|
|
184
|
+
# dbutils.widgets.multiselect enforces an internal "selection sequence"
|
|
185
|
+
# validation against its own default that was observed to reject even a
|
|
186
|
+
# same-length, same-items default on some Databricks runtimes/existing-
|
|
187
|
+
# widget states (DefaultValueNotInChoicesList), with no reliable
|
|
188
|
+
# workaround. Three independent dropdowns have no such cross-widget
|
|
189
|
+
# validation and are the more robust primitive for this.
|
|
190
|
+
_YES_NO = ["Yes", "No"]
|
|
191
|
+
_schema_default = "Yes"
|
|
192
|
+
_column_default = "No" if MODE == "schema" else "Yes"
|
|
193
|
+
_row_default = "No" if MODE == "schema" else "Yes"
|
|
194
|
+
dbutils.widgets.dropdown("check_catalog_schema", _schema_default, _YES_NO, "Run Catalog & Schema checks?")
|
|
195
|
+
dbutils.widgets.dropdown("check_column", _column_default, _YES_NO, "Run Column checks?")
|
|
196
|
+
dbutils.widgets.dropdown("check_row", _row_default, _YES_NO, "Run Row checks?")
|
|
195
197
|
|
|
196
198
|
if SHOW_OPTIONAL_WIDGETS:
|
|
197
199
|
dbutils.widgets.text("only_columns", "", "Only compare these columns (comma-separated, optional)")
|
|
@@ -279,15 +281,13 @@ def _source_or_target_string(prefix: str) -> str:
|
|
|
279
281
|
source = _source_or_target_string("source")
|
|
280
282
|
target = _source_or_target_string("target")
|
|
281
283
|
|
|
282
|
-
_CHECK_MAP = {
|
|
283
|
-
"Catalog & Schema": {ValidationType.CATALOG, ValidationType.SCHEMA},
|
|
284
|
-
"Column": {ValidationType.COLUMN},
|
|
285
|
-
"Row": {ValidationType.ROW},
|
|
286
|
-
}
|
|
287
|
-
selected_checks = [c for c in dbutils.widgets.get("checks").split(",") if c]
|
|
288
284
|
enabled_validations = set()
|
|
289
|
-
|
|
290
|
-
enabled_validations |=
|
|
285
|
+
if dbutils.widgets.get("check_catalog_schema") == "Yes":
|
|
286
|
+
enabled_validations |= {ValidationType.CATALOG, ValidationType.SCHEMA}
|
|
287
|
+
if dbutils.widgets.get("check_column") == "Yes":
|
|
288
|
+
enabled_validations |= {ValidationType.COLUMN}
|
|
289
|
+
if dbutils.widgets.get("check_row") == "Yes":
|
|
290
|
+
enabled_validations |= {ValidationType.ROW}
|
|
291
291
|
if not enabled_validations:
|
|
292
292
|
enabled_validations = None # fall back to validate_tables()'s own "run everything" default
|
|
293
293
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tablevalidator-databricks
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Generates a widget-driven Databricks notebook UI on top of the table-validator package - no code required to run a comparison.
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -45,12 +45,12 @@ Writes `./TableValidator.py` - a ready-to-use Databricks notebook. Options:
|
|
|
45
45
|
tablevalidator-databricks init --output MyValidation.py --mode full
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
- `--mode basic` - only the check-group
|
|
48
|
+
- `--mode basic` - only the check-group Yes/No dropdowns and table pickers.
|
|
49
49
|
- `--mode full` (default) - also shows optional filter widgets (only/
|
|
50
|
-
ignore columns, row filter, primary key).
|
|
51
|
-
- `--mode schema` - same widgets as `basic
|
|
52
|
-
schema-shape-only comparison
|
|
53
|
-
|
|
50
|
+
ignore columns, row filter, primary key). Every check defaults to "Yes".
|
|
51
|
+
- `--mode schema` - same widgets as `basic`, but Column/Row default to
|
|
52
|
+
"No" - a lightweight schema-shape-only comparison out of the box (still
|
|
53
|
+
changeable per-run).
|
|
54
54
|
|
|
55
55
|
Then, in your Databricks workspace: **Workspace -> Import**, format
|
|
56
56
|
"Source", and select the generated file. Databricks recognizes the
|
|
@@ -63,7 +63,7 @@ markers and opens it as a real notebook.
|
|
|
63
63
|
2. Queries Unity Catalog (`SHOW CATALOGS` / `SHOW SCHEMAS IN ...` /
|
|
64
64
|
`SHOW TABLES IN ...` via the notebook's own ambient Spark session) to
|
|
65
65
|
populate Source/Target Catalog, Schema, and Table dropdowns.
|
|
66
|
-
3. Shows a
|
|
66
|
+
3. Shows a Yes/No dropdown per check group (Catalog & Schema / Column /
|
|
67
67
|
Row - the three independently-selectable check groups the engine
|
|
68
68
|
actually supports) plus, in `full` mode, optional text widgets for
|
|
69
69
|
column filtering, a row filter, and a primary key.
|
|
@@ -15,6 +15,7 @@ from unittest.mock import MagicMock
|
|
|
15
15
|
|
|
16
16
|
import pytest
|
|
17
17
|
|
|
18
|
+
from table_validator.config.schema import ValidationType
|
|
18
19
|
from tablevalidator_databricks.generator.generator import generate_notebook
|
|
19
20
|
|
|
20
21
|
|
|
@@ -254,42 +255,83 @@ def test_catalog_override_drives_schema_and_table_lookup(notebook_path):
|
|
|
254
255
|
|
|
255
256
|
|
|
256
257
|
# ---------------------------------------------------------------------------
|
|
257
|
-
#
|
|
258
|
-
#
|
|
259
|
-
#
|
|
260
|
-
# DefaultValueNotInChoicesList
|
|
261
|
-
#
|
|
258
|
+
# Validation-checks selection - three independent Yes/No dropdowns
|
|
259
|
+
# (check_catalog_schema / check_column / check_row), replacing an earlier
|
|
260
|
+
# single dbutils.widgets.multiselect that was observed in production to
|
|
261
|
+
# raise DefaultValueNotInChoicesList even with a default that appeared to
|
|
262
|
+
# satisfy multiselect's own documented constraints - three independent
|
|
263
|
+
# dropdowns have no equivalent cross-widget validation.
|
|
262
264
|
# ---------------------------------------------------------------------------
|
|
263
|
-
def
|
|
264
|
-
|
|
265
|
-
|
|
265
|
+
def test_full_and_basic_mode_default_all_checks_to_yes(tmp_path: Path) -> None:
|
|
266
|
+
for mode in ("full", "basic"):
|
|
267
|
+
path = tmp_path / f"{mode}.py"
|
|
268
|
+
generate_notebook(path, mode)
|
|
269
|
+
spark = _fake_spark(
|
|
270
|
+
catalogs=["main"], schemas_by_catalog={"main": ["sales"]},
|
|
271
|
+
tables_by_schema={("main", "sales"): ["orders"]},
|
|
272
|
+
)
|
|
273
|
+
captured = {}
|
|
274
|
+
|
|
275
|
+
def fake_validate_tables(source, target, **kwargs):
|
|
276
|
+
captured["enabled_validations"] = kwargs.get("enabled_validations")
|
|
277
|
+
m = MagicMock()
|
|
278
|
+
m.__str__ = MagicMock(return_value="Overall status: PASS")
|
|
279
|
+
return m
|
|
266
280
|
|
|
281
|
+
_run_notebook(path, widget_values={}, spark=spark, validate_tables_mock=fake_validate_tables)
|
|
282
|
+
|
|
283
|
+
assert captured["enabled_validations"] == {
|
|
284
|
+
ValidationType.CATALOG, ValidationType.SCHEMA,
|
|
285
|
+
ValidationType.COLUMN, ValidationType.ROW,
|
|
286
|
+
}, f"mode={mode}"
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def test_schema_mode_defaults_column_and_row_checks_to_no(tmp_path: Path) -> None:
|
|
290
|
+
path = tmp_path / "schema.py"
|
|
291
|
+
generate_notebook(path, "schema")
|
|
267
292
|
spark = _fake_spark(
|
|
268
|
-
catalogs=["main"],
|
|
269
|
-
schemas_by_catalog={"main": ["sales"]},
|
|
293
|
+
catalogs=["main"], schemas_by_catalog={"main": ["sales"]},
|
|
270
294
|
tables_by_schema={("main", "sales"): ["orders"]},
|
|
271
295
|
)
|
|
296
|
+
captured = {}
|
|
297
|
+
|
|
298
|
+
def fake_validate_tables(source, target, **kwargs):
|
|
299
|
+
captured["enabled_validations"] = kwargs.get("enabled_validations")
|
|
300
|
+
m = MagicMock()
|
|
301
|
+
m.__str__ = MagicMock(return_value="Overall status: PASS")
|
|
302
|
+
return m
|
|
272
303
|
|
|
273
|
-
|
|
274
|
-
_run_notebook(path, widget_values={}, spark=spark, validate_tables_mock=MagicMock())
|
|
304
|
+
_run_notebook(path, widget_values={}, spark=spark, validate_tables_mock=fake_validate_tables)
|
|
275
305
|
|
|
306
|
+
assert captured["enabled_validations"] == {ValidationType.CATALOG, ValidationType.SCHEMA}
|
|
276
307
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
308
|
+
|
|
309
|
+
def test_deselecting_every_check_falls_back_to_run_everything(notebook_path):
|
|
310
|
+
"""All three Yes/No dropdowns set to "No" must fall back to
|
|
311
|
+
validate_tables()'s own "run everything" default (enabled_validations=
|
|
312
|
+
None), not silently run nothing."""
|
|
282
313
|
spark = _fake_spark(
|
|
283
|
-
catalogs=["main"],
|
|
284
|
-
schemas_by_catalog={"main": ["sales"]},
|
|
314
|
+
catalogs=["main"], schemas_by_catalog={"main": ["sales"]},
|
|
285
315
|
tables_by_schema={("main", "sales"): ["orders"]},
|
|
286
316
|
)
|
|
317
|
+
captured = {}
|
|
318
|
+
|
|
319
|
+
def fake_validate_tables(source, target, **kwargs):
|
|
320
|
+
captured["enabled_validations"] = kwargs.get("enabled_validations")
|
|
321
|
+
m = MagicMock()
|
|
322
|
+
m.__str__ = MagicMock(return_value="Overall status: PASS")
|
|
323
|
+
return m
|
|
287
324
|
|
|
288
|
-
|
|
325
|
+
_run_notebook(
|
|
326
|
+
notebook_path,
|
|
327
|
+
widget_values={
|
|
328
|
+
"check_catalog_schema": "No", "check_column": "No", "check_row": "No",
|
|
329
|
+
},
|
|
330
|
+
spark=spark,
|
|
331
|
+
validate_tables_mock=fake_validate_tables,
|
|
332
|
+
)
|
|
289
333
|
|
|
290
|
-
|
|
291
|
-
choices = fake_widgets.multiselect_choices["checks"]
|
|
292
|
-
assert fake_widgets.get("checks") == ",".join(choices)
|
|
334
|
+
assert captured["enabled_validations"] is None
|
|
293
335
|
|
|
294
336
|
|
|
295
337
|
# ---------------------------------------------------------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|