Same reformatting for this one. +1 for this one as well. Also, we miss the 
voting period for both

Best,
Wei

——

Hello everyone,  

I'd like to initiate a vote on a new DAG authorship best practice.

Proposal:  
When a `@task.branch` (or `BranchPythonOperator`) function has at least two 
`return` statements, and exactly one of them returns a non-empty list, the 
function is effectively acting as a binary gate — either run a specific set of 
downstream tasks, or skip them all.

In that case, `@task.short_circuit` (`ShortCircuitOperator`) is a simpler and 
more readable alternative: it expresses the same intent by returning 
True/False, rather than requiring the caller to reason about list-vs-empty-list 
semantics.

Before:

    from airflow.decorators import task

    @task.branch
    def check_condition():
        if some_condition:
            return ["downstream_task"]
        return []

After:

    from airflow.decorators import task

    @task.short_circuit
    def check_condition():
        return some_condition

The same principle applies to the classic operator form.

Rationale:

- Clarity: `@task.short_circuit` makes intent immediately obvious — the task 
either proceeds or it doesn't. Readers no longer need to inspect return values 
to determine that the branch is binary.  
- Less boilerplate: Eliminates the need to wrap a boolean condition in a 
single-element list.  
- Correct semantics: `@task.branch` with a single non-empty return is a 
degenerate case of branching; `@task.short_circuit` is the idiomatic tool for 
this pattern.  
- Consistency: The rule applies equally to the TaskFlow API (`@task.branch`) 
and the traditional operator API (`BranchPythonOperator`), covering both 
authorship styles uniformly.

Cases NOT affected by this proposal:

- Functions with multiple non-empty list returns are genuine branching logic — 
no change suggested.  
- Functions with only a single return — no change suggested.  
- Functions returning non-list values (strings, None, etc.) — no change 
suggested.

Call for Consensus:  
Please let me know if you have concerns, questions, or support.

Thank you,  
Dev-iL

See Also:  
1. https://github.com/apache/airflow/issues/43176#issuecomment-2667604469 — 
original proposal in the static checks tracking issue  
2. https://github.com/astral-sh/ruff/pull/23579 — Draft Ruff PR implementing 
(`task-branch-as-short-circuit`)

> On Mar 17, 2026, at 6:03 PM, Dev-iL <[email protected]> wrote:
> 
> |Hello everyone,|
> ||
> |I'd like to initiate a vote on a new DAG authorship best practice.|
> ||
> |## Proposal|
> ||
> |When a `@task.branch` (or `BranchPythonOperator`) function has **at least 
> two `return` statements**, and **exactly one of them returns a non-empty 
> list**, the function is effectively acting as a binary gate — either run a 
> specific set of downstream tasks, or skip them all.|
> ||
> |In that case, **`@task.short_circuit`** (`ShortCircuitOperator`) is a 
> simpler and more readable alternative: it expresses the same intent by 
> returning `True`/`False`, rather than requiring the caller to reason about 
> list-vs-empty-list semantics.|
> ||
> |### Before|
> ||
> |```python|
> |from airflow.decorators import task|
> ||
> |@task.branch|
> |def check_condition():|
> |if some_condition:|
> |return ["downstream_task"]|
> |return []|
> |```|
> ||
> |### After|
> ||
> |```python|
> |from airflow.decorators import task|
> ||
> |@task.short_circuit|
> |def check_condition():|
> |return some_condition|
> |```|
> ||
> |The same principle applies to the classic operator form.|
> ||
> |## Rationale|
> ||
> |- **Clarity:** `@task.short_circuit` makes intent immediately obvious — the 
> task either proceeds or it doesn't. Readers no longer need to inspect return 
> values to determine that the branch is binary.|
> |- **Less boilerplate:** Eliminates the need to wrap a boolean condition in a 
> single-element list.|
> |- **Correct semantics:** `@task.branch` with a single non-empty return is a 
> degenerate case of branching; `@task.short_circuit` is the idiomatic tool for 
> this pattern.|
> |- **Consistency:** The rule applies equally to the TaskFlow API 
> (`@task.branch`) and the traditional operator API (`BranchPythonOperator`), 
> covering both authorship styles uniformly.|
> ||
> |## Cases NOT affected by this proposal|
> ||
> |This best practice only applies when the function structure is unambiguously 
> binary:|
> ||
> |- Functions with **multiple non-empty list returns** are genuine branching 
> logic — no change suggested.|
> |- Functions with **only a single return** — no change suggested.|
> |- Functions returning **non-list values** (strings, `None`, etc.) — no 
> change suggested.|
> ||
> |## Call for Consensus|
> ||
> |Please let me know if you have concerns, questions, or support.|
> ||
> |Thank you,|
> |Dev-iL|
> ||
> |---|
> ||
> |## See Also|
> ||
> |1. [apache/airflow#43176 
> (comment)](https://github.com/apache/airflow/issues/43176#issuecomment-2667604469)
>  — original proposal in the static checks tracking issue|
> |2. [astral-sh/ruff#23579](https://github.com/astral-sh/ruff/pull/23579) — 
> Draft Ruff PR implementing (`task-branch-as-short-circuit`)|
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to