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]