Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6cd9f02
move criticiality of rule inro _validate_attributes
cornzyblack Jul 17, 2025
98371b7
since criticality is validated after creation, filter by criticality …
cornzyblack Jul 17, 2025
1a58e16
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Jul 18, 2025
98803bc
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Jul 23, 2025
acf3767
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Jul 24, 2025
0766f2b
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Aug 2, 2025
3d0fd34
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Aug 7, 2025
e5712fc
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Aug 7, 2025
9bf6d98
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Aug 13, 2025
1e4d783
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Sep 1, 2025
fcdb1ce
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Sep 8, 2025
2393404
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Sep 16, 2025
eddc874
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Sep 19, 2025
c378b6d
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Sep 25, 2025
cb6f9ef
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Oct 15, 2025
9e4f192
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Dec 18, 2025
124e895
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Jan 10, 2026
f374908
Merge branch 'main' of github.com:cornzyblack/dqx
cornzyblack Jan 10, 2026
d5eb579
refactor: use special characters
cornzyblack Jan 10, 2026
257cd60
chore: create one function to handle SDK table location
cornzyblack Jan 10, 2026
4ab7169
chore: formatting
cornzyblack Jan 10, 2026
7a02a39
use spark.catalog.tableExists
mwojtyczka Jan 14, 2026
1850fda
improve existing tests
mwojtyczka Jan 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,8 @@ disable = [
"broad-exception-caught",
"rewrite-as-for-loop",
"redundant-returns-doc",
# dbx pylint is not up-to-date, e.g. spark.catalog.tableExists is compatible with UC since DBR 14+
"incompatible-with-uc"
]

# Enable the message, report, category or checker with the given id(s). You can
Expand Down
3 changes: 1 addition & 2 deletions src/databricks/labs/dqx/checks_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.exc import DatabaseError, ProgrammingError, OperationalError, IntegrityError


import yaml
from pyspark.sql import SparkSession
from databricks.sdk.errors import NotFound
Expand Down Expand Up @@ -107,7 +106,7 @@ def load(self, config: TableChecksStorageConfig) -> list[dict]:
NotFound: if the table does not exist in the workspace
"""
logger.info(f"Loading quality rules (checks) from table '{config.location}'")
if not self.ws.tables.exists(config.location).table_exists:
if not self.spark.catalog.tableExists(config.location):
raise NotFound(f"Checks table {config.location} does not exist in the workspace")
rules_df = self.spark.read.table(config.location)
return serialize_checks_from_dataframe(rules_df, run_config_name=config.run_config_name) or []
Expand Down
5 changes: 4 additions & 1 deletion tests/integration/test_ai_rules_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ def not_ends_with_suffix(column: str, suffix: str):

custom_check_functions = {"not_ends_with_suffix": not_ends_with_suffix}

user_input = USER_INPUT + "\nEmail address must not end with '@gmail.com'. Use not_ends_with_suffix function."
user_input = USER_INPUT + (
"\nEmail address must not end with '@gmail.com'. "
"Use not_ends_with_suffix function and don't add any extra quotes for suffix."
)

generator = DQGenerator(ws, spark, custom_check_functions=custom_check_functions)
actual_checks = generator.generate_dq_rules_ai_assisted(user_input=user_input)
Expand Down
15 changes: 15 additions & 0 deletions tests/integration/test_config_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,18 @@ def test_save_run_config_in_custom_folder_installation(ws, installation_ctx_cust
run_config_name="default", install_folder=installation_ctx_custom_install_folder.install_folder
)
assert actual_default_run_config == installation_ctx_custom_install_folder.config.get_run_config("default")


def test_save_workspace_config_with_extra_fields_in_user_installation(ws, installation_ctx, spark):
installation_ctx.installation.save(installation_ctx.config)

run_config = RunConfig(name="fake")
config = WorkspaceConfig(run_configs=[run_config])
# extra configs are skipped
config.extra_field = "extra_value"

product_name = installation_ctx.product_info.product_name()
ConfigSerializer(ws).save_config(config=config, assume_user=True, product_name=product_name)

actual_config = ConfigSerializer(ws).load_config(assume_user=True, product_name=product_name)
assert actual_config == config
Comment thread
mwojtyczka marked this conversation as resolved.
12 changes: 12 additions & 0 deletions tests/integration/test_save_and_load_checks_from_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ def test_load_checks_when_checks_table_does_not_exist(ws, make_schema, make_rand
engine.load_checks(config=config)


def test_load_checks_with_special_characters_in_table_name(ws, make_schema, make_random, spark):
catalog_name = TEST_CATALOG
schema_name = make_schema(catalog_name=catalog_name).name
table_name = f"`{catalog_name}`.`{schema_name}`.`table-with-special_chars$#@{make_random(5)}`"

engine = DQEngine(ws, spark)
config = TableChecksStorageConfig(location=table_name, run_config_name="default")
engine.save_checks(INPUT_CHECKS, config=config)
checks = engine.load_checks(config=config)
assert checks == EXPECTED_CHECKS, "Checks were not loaded correctly."


def test_save_and_load_checks_from_table(ws, make_schema, make_random, spark):
catalog_name = TEST_CATALOG
schema_name = make_schema(catalog_name=catalog_name).name
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_summary_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def test_engine_without_observer_no_metrics_saved(ws, spark, make_schema, make_r
else:
raise ValueError("Invalid 'apply_checks_method' used for testing observable metrics.")

assert not ws.tables.exists(metrics_table_name).table_exists
assert not spark.catalog.tableExists(metrics_table_name)


@pytest.mark.parametrize(
Expand Down