Commit f39b210
authored
Allow bypassing data quality checks via a config key (#1598)
* Fix preëxisting issues in test_sklearn_plot_extensions
* Add `disable_data_quality_checks` config key
## Context
`@check_output` and `@check_output_custom` decorators let users attach data validators to function outputs. At graph-construction time, each decorated node is expanded into a subgraph:
- `{name}_raw` — runs the actual function
- `{name}_{validator}` — one node per validator (tagged `hamilton.data_quality.contains_dq_results`)
- `{name}` — aggregates validation results and returns the raw output
This flag is useful for two main reasons:
1. Validation may be crucial during development, but carries a real runtime cost in production where the pipeline is already trusted. Previously there was no way to turn it off short of removing the decorators from the source code.
2. When generating graph visualizations and we don't want to crowd them with validation nodes, passing `disable_data_quality_checks=True` at construction time causes the `_raw` and validator nodes not to be added to the graph - so any visualization of that driver's graph will only show the "business logic" nodes.
## What was changed
### `hamilton/function_modifiers/validation.py`
`BaseDataValidationDecorator` (parent of both `check_output` and `check_output_custom`) now:
1. Overrides `optional_config()` to declare `{"disable_data_quality_checks": False}`. This registers the key with Hamilton's config-filtering pipeline so it is threaded through to `transform_node` automatically — no driver plumbing needed.
3. Adds an early-return guard at the top of `transform_node`:
```python
if config.get("disable_data_quality_checks", False):
return [node_]
```
When the flag is set, the node is returned unchanged — no `_raw` node, no validator nodes, and no expansion happens. The cost is literally zero: the extra nodes are never created.
### `hamilton/driver.py`
`Builder` gains a convenience method:
```python
def with_data_quality_disabled(self) -> "Builder":
return self.with_config({"disable_data_quality_checks": True})
```
This is a thin wrapper over `with_config` — discoverable by IDE autocomplete and explicit about intent. Because `with_config` does a dict `.update()`, a later call like `.with_config({"disable_data_quality_checks": False})` will re-enable validation, which is the expected last-write-wins behavior.
## Usage
**Via the `Builder` convenience method (recommended):**
```python
dr = (
hamilton.driver.Builder()
.with_modules(my_pipeline)
.with_data_quality_disabled()
.build()
)
```
**Via `with_config` directly (equivalent, useful when config is assembled dynamically):**
```python
dr = (
hamilton.driver.Builder()
.with_modules(my_pipeline)
.with_config({"disable_data_quality_checks": True})
.build()
)
```
**Legacy `Driver` constructor:**
```python
dr = hamilton.driver.Driver(
{"disable_data_quality_checks": True},
my_pipeline,
adapter=DefaultAdapter(),
)
```
## Tests added
| File | Test | What it covers |
|------|------|----------------|
| `tests/function_modifiers/test_validation.py` | `test_check_output_disabled_via_config_returns_original_node` | `check_output_custom` returns the original node unchanged when flag is set |
| `tests/function_modifiers/test_validation.py` | `test_check_output_builtin_disabled_via_config_returns_original_node` | `check_output` (built-in validators) also respects the flag |
| `tests/test_end_to_end.py` | `test_builder_with_data_quality_disabled_removes_validator_nodes` | No DQ-tagged nodes appear in `list_available_variables()` when disabled |
| `tests/test_end_to_end.py` | `test_builder_with_data_quality_disabled_still_executes_correctly` | Driver executes correctly and returns the function's real output when disabled |
| `tests/test_end_to_end.py` | `test_disable_data_quality_checks_config_key_works_directly` | Raw `with_config` path (no convenience method) also suppresses validator nodes |
All 13 pre-existing validation tests continue to pass.
## Design notes
- **Graph-construction time, not execution time.** Disabling at construction eliminates the extra nodes entirely. An execution-time approach (e.g., a lifecycle adapter) would still pay graph construction and scheduling overhead, and would be harder to reason about.
- **Config key, not a subclass.** A `NoValidationBuilder` subclass was considered. It was rejected: this is a single boolean flag, not a fundamentally different execution model. The existing `Builder` method pattern (`with_config`, `with_adapters`, …) is the right weight here. The `Builder.with_data_quality_disabled()` convenience method is offered as a discoverable alias — if maintainers prefer, the method alone (without the raw config key) or the raw key alone (without the method) is equally viable.
- **`optional_config()` is the correct hook.** Hamilton's `resolve_config` / `filter_config` machinery passes only declared config keys to each decorator. Registering the key via `optional_config()` means the flag is silently ignored (defaulting to `False`) by all existing drivers that never set it — no breaking change.
## Checklist
- [x] PR has an informative and human-readable title (this will be pulled into the release notes)
- [x] Changes are limited to a single goal (no scope creep)
- [x] Code passed the pre-commit check & code is left cleaner/nicer than when first encountered.
- [x] Any _change_ in functionality is tested
- [x] New functions are documented (with a description, list of inputs, and expected output)
- [x] Placeholder code is flagged / future TODOs are captured in comments
- [x] Project documentation has been updated if adding/changing functionality.1 parent 7644a30 commit f39b210
7 files changed
Lines changed: 167 additions & 6 deletions
File tree
- docs
- how-tos
- reference/decorators
- hamilton
- function_modifiers
- tests
- function_modifiers
- plugins
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 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 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
19 | 62 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
35 | 54 | | |
36 | 55 | | |
37 | 56 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
| |||
1843 | 1844 | | |
1844 | 1845 | | |
1845 | 1846 | | |
| 1847 | + | |
| 1848 | + | |
| 1849 | + | |
| 1850 | + | |
| 1851 | + | |
| 1852 | + | |
| 1853 | + | |
| 1854 | + | |
| 1855 | + | |
| 1856 | + | |
| 1857 | + | |
| 1858 | + | |
| 1859 | + | |
1846 | 1860 | | |
1847 | 1861 | | |
1848 | 1862 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
45 | 49 | | |
46 | 50 | | |
47 | 51 | | |
| 52 | + | |
| 53 | + | |
48 | 54 | | |
49 | 55 | | |
50 | 56 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
313 | 313 | | |
314 | 314 | | |
315 | 315 | | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
316 | 354 | | |
317 | 355 | | |
318 | 356 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
| |||
141 | 142 | | |
142 | 143 | | |
143 | 144 | | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
150 | 149 | | |
151 | 150 | | |
152 | 151 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
600 | 600 | | |
601 | 601 | | |
602 | 602 | | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
0 commit comments