Checking components¶
Airflow validates many extension points only when the scheduler, worker, or Dag processor
discovers them. Run check_component first to catch contract errors against the installed
Airflow release without starting a database or mutating Airflow's live registries:
from piab.components import check_component
def test_my_timetable_conforms():
check_component(MyTimetable).raise_for_problems()
Use this check for timetables, listeners, executors, XCom backends, priority-weight strategies,
notifiers, secrets backends, policies, plugins, and providers. Test operators, hooks, sensors,
and @task decorators through the fidelity ladder instead.
Choose the component kind¶
check_component normally detects the kind from inheritance, Airflow's pluggy markers, plugin
shape, or a callable named get_provider_info. Pass a class or an existing instance; the
checker never constructs a class, so required and side-effectful constructors are safe.
Force the kind when the component is intentionally duck-typed or still incomplete:
from piab.components import ComponentKind, check_component
report = check_component(MyListener, kind=ComponentKind.LISTENER)
This matters because an unrecognized component returns a clean report: no applicable checks is
not the same as a validated contract. ComponentKind contains TIMETABLE, LISTENER,
EXECUTOR, XCOM, WEIGHT_STRATEGY, NOTIFIER, SECRETS_BACKEND, POLICY, PLUGIN, and
PROVIDER.
The report¶
Checks accumulate every finding instead of stopping at the first one:
report = check_component(MyExecutor)
report.ok
report.problems # tuple[ComponentProblem, ...]
report.summary()
report.certification # CertificationTier | None
report.raise_for_problems()
Each ComponentProblem has a machine-readable code, a specific message, and a corrective
hint. raise_for_problems() raises ComponentContractError with the complete summary;
otherwise a report never fails the test by itself.
On an uncertified Airflow release, available checks still run against live capabilities and
report.certification is PROBED. Timetable checks work on both Airflow families. The other
kinds are Airflow 3 checks and produce no findings on Airflow 2.
What gets checked¶
Every ComponentProblem.code value is part of the diagnostic contract:
| Kind | Problem codes |
|---|---|
| Timetable | timetable-local-qualname, timetable-missing-protocol-method, timetable-serialize-pair-incomplete, timetable-serialize-not-json, timetable-round-trip-mismatch |
| Listener | listener-no-matching-hookspec, listener-unknown-argument, listener-core-manager-only, listener-sdk-manager-only |
| Executor | executor-missing-override, executor-stale-attribute, executor-flag-wrong-type |
| XCom backend | xcom-orm-deserialize-removed, xcom-backend-signature |
| Priority-weight strategy | weight-strategy-abstract, weight-strategy-hash-of-none |
| Notifier | notifier-missing-notify, notifier-template-fields-unresolvable |
| Secrets backend | secrets-backend-raises-on-miss |
| Policy | policy-unknown-hookspec, policy-argument-name-mismatch |
| Plugin | plugin-name-missing |
| Provider | provider-info-schema, provider-package-name-mismatch, provider-no-entry-point |
Timetables¶
Timetable checks catch local classes that Airflow cannot resolve, required scheduling methods
left on their raising defaults, incomplete serialize/deserialize pairs, and non-JSON state
returned by an instance. The Timetables page covers logic tests,
serialization round trips, and automatic registration through dag_maker.
Execution components¶
- Executors: required lifecycle overrides, ignored 2.x-era attributes, and the installed release's sentry capability name and type.
- XCom backends: the removed ORM deserializer and serialization methods that no longer accept the base class's real call shape.
- Priority-weight strategies: abstract implementations and classes that cannot serve as set or dictionary keys.
A clean report does not run a workload. Exercise an executor through
run_dag(..., executor=...); the
Cookbook contains a complete serial example.
Observability components¶
- Listeners and policies: hook names and arguments against the installed hookspecs; listeners also report hooks available through only one listener manager.
- Notifiers: a missing synchronous
notify; on an instance, unresolvedtemplate_fields.
Plain functions loaded through airflow_local_settings.py use the older policy mechanism and
are not policy components.
Distribution components¶
- Secrets backends: declared lookup return types that exclude
None. The checker never calls a backend or fabricates credentials, so an unannotated lookup produces no finding. - Plugins: a missing plugin name.
- Providers: the installed provider-info schema, package-name agreement, and the
apache_airflow_providerentry point.
Pass the provider's get_provider_info callable, not its result. The schema check invokes it
because ProvidersManager does too. Package and entry-point checks are skipped when the
callable cannot be attributed to an installed distribution. Use an isolated process to prove
the entry point itself resolves; see
Registration and packaging.
Shape is not registration¶
A clean report proves that the checked shape matches the installed release. It does not prove that production can discover the component or that the component behaves correctly. Continue with Registration and packaging, then exercise the behavior at the appropriate rung of the fidelity ladder.