Skip to content

Fail Neo4jOperator argument mistakes at Dag parse time - #70508

Draft
ColtenOuO wants to merge 1 commit into
apache:mainfrom
ColtenOuO:revert-neo4j-cypher-provision-check
Draft

Fail Neo4jOperator argument mistakes at Dag parse time#70508
ColtenOuO wants to merge 1 commit into
apache:mainfrom
ColtenOuO:revert-neo4j-cypher-provision-check

Conversation

@ColtenOuO

@ColtenOuO ColtenOuO commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Note

Blocked on #70505. The validate-operators-init hook on main still flags
is None provision checks in __init__, so CI will be red until that merges.
Kept as a draft until then — verified clean against the checker from #70505
(exit 0, no exemption entry needed).

Moves the two argument-provision checks of Neo4jOperator back to __init__, one of the reverts tracked in #70503.

Whether cypher or sql was passed is a property of how the Dag was written, not of the rendered value. execute() cannot answer it: with render_template_as_native_obj=True a supplied field can render to None, so the check there reports an argument the author did provide as missing. Checking at construction also turns a static authoring mistake into a Dag import error rather than a failure on every task instance.

Both provision checks move, not only cypher is None. After #70373 the operator keeps sql and cypher as separate fields, so Neo4jOperator(sql=...) is valid with cypher unset — the constructor check has to be cypher is None and sql is None. Once it is written that way, leaving the mutual-exclusivity check in execute() would split two checks that ask the same question across two phases.

The execute() guard is kept deliberately: Neo4jHook.run takes a str, and the constructor check does not narrow self.cypher to str (it is legitimately None when sql was used). A passed field can also render to None, which is exactly the case the guard covers. cast would hide that and assert is not allowed in production code.

Testing done

related: #70503, #70505


Drafted-by: Claude Code (Opus 5); reviewed by @ColtenOuO before posting

Whether `cypher` or `sql` was passed is a property of how the Dag was
written, not of the rendered value, and the constructor is the only place
that can read it: under render_template_as_native_obj a supplied field can
render to None, so the same check in execute reports an argument the author
did provide as missing. Checking at construction also surfaces the mistake
as a Dag import error instead of once per task instance.

The execute guard stays: a passed field can still render to None and the
hook needs a query string.

related: apache#70503
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant