shahar1 opened a new issue, #70503:
URL: https://github.com/apache/airflow/issues/70503

   ### Background
   
   `validate-operators-init` flags every read of a template-field parameter in 
`__init__`. A companion PR narrows that: a `field is None` / `field is not 
None` check reads whether the argument was *passed*, not its value, and belongs 
in the constructor. (With `render_template_as_native_obj=True` a provided field 
renders to `None`, so the same check in `execute()` reports a supplied argument 
as missing; and raising at construction surfaces a static authoring mistake as 
a Dag import error rather than per task instance.)
   
   Replaying both checker versions over every exemption entry removed so far 
(31 PRs, 48 entries) shows **8 entries across 5 PRs** where the old rule forced 
a change that was not needed. Those PRs are merged and green — nothing is 
broken — but the files now carry comments and regression tests asserting the 
placement the docs discourage, and contributors working #70296 learn the rule 
by reading them.
   
   This issue tracks putting them back. Each is independent; separate PRs are 
fine.
   
   ### Revert
   
   - [ ] `providers/common/ai/.../operators/agent.py` (#70338) — 
`message_history is not None and enable_hitl_review` is pure provision. Restore 
to `__init__`, revert 
`test_agent.py::test_message_history_with_hitl_review_raises` to 
constructor-raises. The comment `# message_history is a template field; 
validate the combination after rendering.` states the rule wrongly and must go.
   - [ ] `providers/databricks/.../operators/databricks_repos.py` (#70341) — 
all four `branch`/`tag`/`repo_id`/`repo_path` checks in 
`DatabricksReposCreate/Update/DeleteOperator` are pure provision. Restore to 
`__init__`; revert the two tests docstringed *"rejected at execute, after 
rendering"*.
   - [ ] `providers/neo4j/.../operators/neo4j.py` (#70348) — `if cypher is 
None: raise` returns to `__init__`. The deprecation-warning placement is a 
separate question; #70373's rationale stands independently.
   
   ### Split, don't revert
   
   - [ ] `providers/common/ai/.../operators/document_loader.py` (#70338) — the 
`source_path`/`source_bytes` exclusivity is provision and returns to 
`__init__`. The third check, `source_bytes is not None and file_type is None`, 
backs the downstream `assert self.file_type is not None`; `file_type` is a 
template field, so that assumption only holds after rendering and it stays in 
`execute()`. Update the comment to say which is which — this is the canonical 
example of the boundary.
   
   ### Leave alone (listed so nobody reverts them by pattern-match)
   
   - `providers/weaviate/.../operators/weaviate.py` (#70326) — making 
`input_data` required is already released; reverting would be a second API 
break. The `execute()` check becomes belt-and-braces and is harmless.
   - `providers/teradata/.../transfers/teradata_to_teradata.py` (#70392) — 
`self.sql_params or {}` at the use site is equivalent. No value in churning it 
back.
   
   ### Not in scope
   
   The other 40 exemption entries removed so far are genuine value reads 
(`ruleset.strip()`, `isinstance(mongo_query, list)`, `source not in 
SUPPORTED_SOURCES`, ...). They stay flagged under the narrowed rule and must 
not be reverted.
   
   ### Verifying a revert
   
   Run the hook on the file after the change — all six classes above are clean 
under the narrowed rule, so no exemption entries need re-adding:
   
   ```
   uv run --script scripts/ci/prek/validate_operators_init.py <path>
   ```
   
   related: #70296
   
   ---
   Drafted-by: Claude Code (Opus 5) (no human review before posting)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to