Skip to content

Enable ruff B023 (function-uses-loop-variable) and fix violations - #70640

Open
dkranchii wants to merge 1 commit into
apache:mainfrom
dkranchii:enable-ruff-b023-fix-closure-loop-var
Open

Enable ruff B023 (function-uses-loop-variable) and fix violations#70640
dkranchii wants to merge 1 commit into
apache:mainfrom
dkranchii:enable-ruff-b023-fix-closure-loop-var

Conversation

@dkranchii

Copy link
Copy Markdown
Contributor

B023 catches the late-binding closure-over-loop-variable footgun where a function defined inside a loop captures the loop variable by reference, so every function in the resulting list sees the same (final) value — a classic silent-bug source in Python. See the Python FAQ entry.

The one user-visible fix is in providers/standard/.../triggers/file.py, where the FileTrigger's os.walk lambda was dispatched to a worker thread via anyio.to_thread.run_sync while the outer glob iteration could advance, potentially walking the wrong path.

The rest are pre-existing latent-bug or false-positive sites fixed by binding the loop-derived variable as a default argument on the inner function or lambda:

  • airflow-core/.../0101_3_2_0_ui_improvements_for_deadlines.py (migration; 7 sites in one nested function)
  • dev/breeze/.../ui_commands.py (two i18n helpers)
  • devel-common/src/sphinx_exts/providers_extensions.py (two class-extras lambdas)
  • providers/apache/hive/tests/unit/.../test_s3_to_hive.py
  • providers/exasol/tests/unit/exasol/hooks/test_sql.py
  • providers/google/tests/system/.../example_cloud_sql_query.py
  • providers/smtp/src/airflow/providers/smtp/hooks/smtp.py (OAuth2 auth callback)
  • shared/secrets_masker/.../secrets_masker.py (subclass compat shim)

Follows the pattern of #66977 (B015), #66978 (PLE1205), #66979 (B008), and #66960 (trigger init/serialize static check).


Was generative AI tooling used to co-author this PR?
  • Yes — Cursor

B023 catches the late-binding closure-over-loop-variable footgun where
a function defined inside a loop captures the loop variable by
reference, so every function in the resulting list sees the same
(final) value — a classic silent-bug source in Python
(https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result).

The one user-visible fix is in providers/standard/.../triggers/file.py,
where the FileTrigger's os.walk lambda was dispatched to a worker
thread via anyio.to_thread.run_sync while the outer glob iteration
could advance, potentially walking the wrong path.

The rest are pre-existing latent-bug or false-positive sites in a
migration script, breeze translation helpers, sphinx extensions, a
system-test example DAG, the SMTP OAuth2 auth callback, secrets_masker
subclass compat shim, and two provider unit tests — fixed by binding
the loop-derived variable as a default argument on the inner function
or lambda.
@dkranchii
dkranchii force-pushed the enable-ruff-b023-fix-closure-loop-var branch from 7d9712b to 61c8f4b Compare July 28, 2026 20:20
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