jedcunningham opened a new pull request, #72861:
URL: https://github.com/apache/airflow/pull/72861

   The Dag version inflation check only spotted a Dag constructor when the 
callable resolved
   through a from-import of airflow's `DAG` or `dag`. A Dag built from a 
subclass, or reached
   through an aliased module import, produced no warnings at all — and since 
task detection keys
   off the same predicate, neither did any task inside its `with` block.
   
   Detection now uses the callable's name as well as the import table. The 
check runs before the
   Dag file is imported, so there is no object to test — the name and the 
file's own imports are
   the only evidence available.
   
   Newly caught, both silent before:
   
   ```python
   # a Dag subclass from a shared library — the task inside it is flagged too
   with TeamDAG():
       BashOperator(task_id=f"t_{datetime.now()}")
   
   # a module reached through an aliased import: import airflow.sdk as sdk
   sdk.DAG(start_date=datetime.now())
   ```
   
   Three consequences of the heuristic, worth a reviewer's attention:
   
   - A non-Dag named `*Dag` assigned to a variable is treated as a Dag, so real 
warnings on later
     uses of that variable are lost:
   
     ```python
     stamp = StampDag(datetime.now())        # flagged as a Dag constructor
     with DAG():
         BashOperator(task_id=f"a_{stamp}")  # warned before this change, 
silent now
     ```
   
     Tracking the assignment anyway would restore that warning, at the cost of 
the common path:
   
     ```python
     dag = DAG(start_date=datetime.now())  # the real problem, already warned
     BashOperator(dag=dag)                 # would start warning, though 
nothing is wrong
     ```
   
     Both are a varying-valued call detected as a Dag constructor and assigned 
to a name, so
     nothing downstream separates them — it is a choice of which one to get 
wrong. Assigning a Dag
     and passing `dag=dag` to its tasks is everyday Airflow; naming a non-Dag 
`*Dag` is not. So
     tracking would trade a rare miss for a routine false positive, on the very 
case the check
     exists to catch.
   - The suffix is case-sensitive, so `create_DAG()` matches where 
`create_dag()` does not. A name
     cannot tell a Dag subclass from a factory function.
   - At `error` level a false positive marks the Dag stale, so it stops 
scheduling rather than
     merely failing to parse. The default is `warning`, so this is opt-in.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Opus 5)
   
   Generated-by: Claude Code (Opus 5)
   


-- 
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