[MAINTENANCE] Type-check great_expectations/expectations/core/

Author: joshua-staufferCreated Sep 14, 2026Updated Sep 14, 2026
Labelshelp wantedmaintenanceblocked

Part of #12188.

What to do

Bring the 39 excluded modules under great_expectations/expectations/core/ into the type-check: remove their 39 exclude patterns from pyproject.toml, fix the errors mypy then reports in those modules, and regenerate the relaxation inventory in the same change.

Fix each error at its cause, in the newly checked module. Where a declared type is narrower than what in-repo callers legitimately pass, widen it — never narrow a parameter, rename a name, or change a default: these 39 classes are public API and GX ships zero breaking changes. If the only fix you can see changes runtime behavior, rendered output, or a public signature, comment on this issue before writing it. Done means: the modules are checked, the run is green, and the expectation test suites pass unmodified.

Where

  • great_expectations/expectations/core/*.py — 124 errors in 37 of the 39 files after #12189 merges (221 before it): 63 union-attr, 22 arg-type, 10 assignment, 9 var-annotated, 9 index, 6 attr-defined, a tail of 5. The top files: expect_column_kl_divergence_to_be_less_than.py 21, expect_table_columns_to_match_set.py 14, expect_column_quantile_values_to_be_between.py 12, expect_table_columns_to_match_ordered_list.py 10.
  • pyproject.toml — remove the 39 exclude entries under expectations/core/. Two of them (expect_column_values_to_be_of_type, expect_column_pair_values_to_be_in_set) already check clean; remove them too.
  • scripts/mypy_relaxation_inventory.json — regenerate with the guard's emit mode, never by hand.

How to verify

Files named on mypy's command line are checked even while an exclude pattern covers them, so this is red today and green only when both the errors and the patterns are gone (--cache-dir=/dev/null keeps the count independent of earlier runs):

bash
mypy --cache-dir=/dev/null --warn-unused-ignores --disallow-untyped-decorators great_expectations/expectations/core/*.py && ! grep -q "'expectations/core/" pyproject.toml

Then python scripts/mypy_config_guard.py --emit-inventory > scripts/mypy_relaxation_inventory.json, invoke type-check --ci, and pytest tests/expectations/core.

Before: 124 errors in 37 files with #12189 merged, 221 without it (at 3798c021b; the # N comments beside the exclude entries are stale — trust the run). invoke type-check --ci checks 900 files. After: the fence exits 0; invoke type-check --ci reports zero errors over 939 files; pytest tests/expectations/core passes as it does today.

Requirements

  1. When the type-check runs on the merged change, it reports zero errors and no exclude pattern naming a path under expectations/core/ remains.
  2. No public signature changes: every parameter type is at least as wide as before, no name, default, or return shape changes on any @public_api class or method.
  3. pytest tests/expectations/core must pass with the same outcomes as before, with no expected value, assertion, skip, or xfail changed or added.
  4. Errors are fixed in code. A new # type: ignore[code] is acceptable only where every code-level fix would change runtime behavior or break a public surface; each one must be single-line, carry the error code, carry a comment saying why, and be listed in the PR.
  5. No new per-module relaxation of any kind — no new exclude pattern, no new [[tool.mypy.overrides]] entry — for any module under great_expectations/.
  6. The inventory must be regenerated by python scripts/mypy_config_guard.py --emit-inventory in the same change, and the guard must pass.

Out of scope: the six render/renderer/ patterns (#12191); the follow_imports = 'silent' block (#12192); great_expectations/validator/computed_metric.py, great_expectations/render/components.py and the renderer configuration/result nullability convention, which were settled in #12116 — if an error traces back to one of those, comment here rather than re-fixing it locally; anything under tests/ (#12128).

Order

  • Blocked by #12189 — without it, 97 of the errors in these files are decorator noise.
  • Blocks #12191 — the two lifts edit the same lines of pyproject.toml and the inventory.

Notes

  • 57 of the 63 union-attr errors are configuration.kwargs or result.result reads inside renderer classmethods whose parameters are Optional[...] = None. That signature is the dispatch contract and stays — see the docstring on Expectation._prescriptive_renderer in great_expectations/expectations/expectation.py. Narrow at entry the way the 20 checked modules in the same directory already do: configuration.kwargs if configuration else {} in prescriptive renderers, assert result, "Must pass in result." in diagnostic ones.
  • If the count you see differs materially from 124, develop has moved — proceed on what you measure and say so in the PR. If you find a genuine runtime bug while typing a module, open a separate issue for it rather than fixing it here.

Source: fivetran/great_expectations