Commit 67138ec
Feature/pydantic serialization (#1302)
## Changes
Follow-up to #1259, completing the Pydantic migration for the
declarative checks path.
Also addresses the review comment on #1259 about covering Pydantic
`ValidationError`
behaviour with tests: DQX callers never see raw
`pydantic_core.ValidationError` —
every entry point raises DQX error types with the pre-migration message
format.
**Validation & deserialization through Pydantic:**
- New `CheckSpec` / `CheckBlock` Pydantic schemas in
`checks_validator.py` own the
structural validation of check metadata dicts (required `check` key,
criticality enum,
`for_each_column` non-empty list, argument dict shape). Signature-based
argument
validation (function exists, required params, types) is unchanged and
runs after.
- Pydantic errors are translated back into the pre-existing
human-readable messages
(`_translate_pydantic_error`), so users and existing tests see identical
error strings.
Unmatched errors name the offending field path (e.g. `user_metadata ->
confidence`)
instead of a generic message. Translation matches on stable Pydantic
error *types*,
not version-dependent message text.
- `ChecksDeserializer.deserialize` reads typed attributes off the
validated `CheckSpec`
instead of raw-dict `.get()` calls, so schema, defaults, and validation
live in one place.
Note: it re-parses via `model_validate` after `validate_checks` —
structural parsing is
cheap, and having the validator return parsed specs would be a larger
API change.
- New `project_to_check_schema` strips storage-only columns
(`run_config_name`,
`created_at`, `rule_fingerprint`, `rule_set_fingerprint`) when loading
checks from
Lakebase, so stored checks round-trip cleanly into
`apply_checks_by_metadata` and match
the Delta path shape. The allow-list is derived from
`CheckSpec.model_fields`.
**`extra` policy on the migrated models (deliberate split):**
- `extra="forbid"` on
`DQRule`/`DQForEachColRule`/`BaseChecksStorageConfig`: a misspelled
kwarg raises `InvalidCheckError`/`InvalidConfigError` at construction.
This *restores
released behaviour* — v0.15.0 (last release) predates the Pydantic
migration and its
dataclasses raised `TypeError` on unknown kwargs; the lenient `ignore`
default was never
shipped.
- `extra="ignore"` on `CheckSpec`/`CheckBlock`: check *metadata*
legitimately carries
extra keys (storage columns, user files), and rejecting them would break
the
load -> apply round-trip.
**Cleanup:**
- Removed dead `checks_formats.py` (+ its tests):
`FILE_SERIALIZERS`/`FILE_DESERIALIZERS`
had no consumers anywhere in `src/` (already unused on `main`);
`SerializerFactory` is
the single source of truth for file formats.
### Linked issues
Resolves #1285
### Tests
- [x] manually tested
- [ ] added unit tests
- [ ] added integration tests
- [ ] added end-to-end tests
- [ ] added performance tests
New `tests/unit/test_pydantic_serialization.py` covers:
- **Fingerprint byte-parity corpus**: SHA-256 values captured *before*
the migration,
asserted byte-identical after — stored fingerprints in existing tables
stay valid.
- Every translated Pydantic error path (missing `check`, bad criticality
value *and* type,
non-list/empty `for_each_column`, wrong-typed fields reported with their
location).
- YAML/JSON round-trip incl. the `__decimal__` wire format; deserializer
dispatch to
`DQRowRule`/`DQDatasetRule`/`for_each_column`; storage-column tolerance
+ projection.
- Regression tests for `extra="forbid"` (unknown kwargs rejected,
wrapped in DQX errors).
---------
Co-authored-by: Marcin Wojtyczka <marcin.wojtyczka@databricks.com>1 parent d2b8e33 commit 67138ec
13 files changed
Lines changed: 1415 additions & 304 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
64 | 64 | | |
65 | 65 | | |
66 | 66 | | |
67 | | - | |
| 67 | + | |
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
| |||
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
25 | 50 | | |
26 | 51 | | |
27 | 52 | | |
| |||
226 | 251 | | |
227 | 252 | | |
228 | 253 | | |
229 | | - | |
| 254 | + | |
230 | 255 | | |
231 | 256 | | |
232 | 257 | | |
| |||
245 | 270 | | |
246 | 271 | | |
247 | 272 | | |
248 | | - | |
| 273 | + | |
249 | 274 | | |
250 | 275 | | |
251 | 276 | | |
252 | 277 | | |
253 | | - | |
254 | | - | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
255 | 282 | | |
256 | | - | |
257 | | - | |
258 | | - | |
| 283 | + | |
259 | 284 | | |
260 | 285 | | |
261 | 286 | | |
262 | | - | |
263 | | - | |
| 287 | + | |
| 288 | + | |
264 | 289 | | |
265 | 290 | | |
266 | 291 | | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
271 | 297 | | |
272 | 298 | | |
273 | 299 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
| |||
178 | 179 | | |
179 | 180 | | |
180 | 181 | | |
181 | | - | |
182 | | - | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
183 | 186 | | |
184 | 187 | | |
185 | 188 | | |
| |||
535 | 538 | | |
536 | 539 | | |
537 | 540 | | |
538 | | - | |
| 541 | + | |
539 | 542 | | |
540 | 543 | | |
541 | 544 | | |
| |||
779 | 782 | | |
780 | 783 | | |
781 | 784 | | |
782 | | - | |
| 785 | + | |
783 | 786 | | |
784 | 787 | | |
785 | 788 | | |
| |||
802 | 805 | | |
803 | 806 | | |
804 | 807 | | |
805 | | - | |
| 808 | + | |
806 | 809 | | |
807 | 810 | | |
808 | 811 | | |
| |||
819 | 822 | | |
820 | 823 | | |
821 | 824 | | |
822 | | - | |
823 | | - | |
| 825 | + | |
| 826 | + | |
824 | 827 | | |
825 | 828 | | |
826 | 829 | | |
| |||
0 commit comments