Skip to content

Comments

Fix ASYNC240: replace blocking filesystem calls with anyio#61616

Merged
jscheffl merged 10 commits intoapache:mainfrom
andreahlert:fix/async240-blocking-fs-calls
Feb 8, 2026
Merged

Fix ASYNC240: replace blocking filesystem calls with anyio#61616
jscheffl merged 10 commits intoapache:mainfrom
andreahlert:fix/async240-blocking-fs-calls

Conversation

@andreahlert
Copy link
Contributor

Summary

Replace blocking os.path and pathlib.Path calls inside async functions with async-safe anyio.Path equivalents, fixing all ASYNC240 lint violations and re-enabling the rule.

  • providers/standard/triggers/file.py: Replace os.path.isfile(), os.path.getmtime(), os.walk(), os.remove() with anyio.Path and anyio.to_thread.run_sync()
  • providers/edge3/cli/worker.py: Replace pathlib.exists(), pathlib.stat() with anyio.Path
  • devel-common/sphinx_exts/pagefind_search/builder.py: Replace pathlib.glob(), pathlib.is_file(), pathlib.read_text() with anyio.Path
  • Test files: Convert blocking pathlib calls in async tests to anyio.Path
  • pyproject.toml: Remove ASYNC240 from the ruff ignore list

closes #61418
Related: #61417

Decision context

anyio was chosen as the async filesystem library per discussion on the issue (approved by @jscheffl). It is already a transitive dependency of the project via httpx, sqlalchemy async, etc.

Test plan

  • Verify ruff check --select ASYNC240 passes with zero violations
  • Run providers/standard/tests/unit/standard/triggers/test_file.py
  • Run providers/edge3/tests/unit/edge3/cli/test_worker.py
  • Run airflow-core/tests/unit/api_fastapi/auth/test_tokens.py

…th anyio

Replace blocking os.path and pathlib.Path calls inside async functions
with async-safe anyio.Path equivalents to prevent blocking the event
loop during filesystem I/O. Re-enable the ASYNC240 ruff rule.

closes apache#61418
@boring-cyborg boring-cyborg bot added area:API Airflow's REST/HTTP API area:providers area:Triggerer provider:edge Edge Executor / Worker (AIP-69) / edge3 provider:standard labels Feb 7, 2026
anyio.Path.glob() returns AsyncIterator, not Awaitable. Use a sync
helper function with anyio.to_thread.run_sync instead.
Copy link
Member

@dheerajturaga dheerajturaga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The edge provider changes look good. The only observation is the test style inconsistency

The test_cli_test_with_deferrable_operator test was mocking os.path.isfile
and os.path.getmtime, but these calls were replaced with anyio.Path in
the FileTrigger. The stale mocks caused the trigger's while-True loop to
never find the file, resulting in an infinite hang that timed out CI.
@andreahlert
Copy link
Contributor Author

All feedback addressed. The only CI failure is a timeout on the GPG keys download step (infra issue, not related to the changes here). Happy to rebase if needed.

Copy link
Contributor

@jscheffl jscheffl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Thanks for the fix!

@jscheffl
Copy link
Contributor

jscheffl commented Feb 8, 2026

Even better... wondered a moment why you can directly import anyio w/o changing any project dependencies until I realized that it was already installed as transitive dependency via httpx and starlette. So great that we picked this, even missed in the proposal to use anyio...

@jscheffl jscheffl merged commit 0681126 into apache:main Feb 8, 2026
436 of 437 checks passed
jhgoebbert pushed a commit to jhgoebbert/airflow_Owen-CH-Leung that referenced this pull request Feb 8, 2026
)

* Fix ASYNC240: replace blocking filesystem calls in async functions with anyio

Replace blocking os.path and pathlib.Path calls inside async functions
with async-safe anyio.Path equivalents to prevent blocking the event
loop during filesystem I/O. Re-enable the ASYNC240 ruff rule.

closes apache#61418

* Fix mypy error: use sync helper for pathlib.glob in async context

anyio.Path.glob() returns AsyncIterator, not Awaitable. Use a sync
helper function with anyio.to_thread.run_sync instead.

* Retrigger CI

* Fix ruff format: add blank line before nested function definition

* Remove newsfragment: internal change, not user-facing

* Fix CLI test hang: update mocks to use anyio.Path instead of os.path

The test_cli_test_with_deferrable_operator test was mocking os.path.isfile
and os.path.getmtime, but these calls were replaced with anyio.Path in
the FileTrigger. The stale mocks caused the trigger's while-True loop to
never find the file, resulting in an infinite hang that timed out CI.

* Cache anyio.Path instance in test to match production code style

* Retrigger CI
Ratasa143 pushed a commit to Ratasa143/airflow that referenced this pull request Feb 15, 2026
)

* Fix ASYNC240: replace blocking filesystem calls in async functions with anyio

Replace blocking os.path and pathlib.Path calls inside async functions
with async-safe anyio.Path equivalents to prevent blocking the event
loop during filesystem I/O. Re-enable the ASYNC240 ruff rule.

closes apache#61418

* Fix mypy error: use sync helper for pathlib.glob in async context

anyio.Path.glob() returns AsyncIterator, not Awaitable. Use a sync
helper function with anyio.to_thread.run_sync instead.

* Retrigger CI

* Fix ruff format: add blank line before nested function definition

* Remove newsfragment: internal change, not user-facing

* Fix CLI test hang: update mocks to use anyio.Path instead of os.path

The test_cli_test_with_deferrable_operator test was mocking os.path.isfile
and os.path.getmtime, but these calls were replaced with anyio.Path in
the FileTrigger. The stale mocks caused the trigger's while-True loop to
never find the file, resulting in an infinite hang that timed out CI.

* Cache anyio.Path instance in test to match production code style

* Retrigger CI
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:API Airflow's REST/HTTP API area:providers area:Triggerer provider:edge Edge Executor / Worker (AIP-69) / edge3 provider:standard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix ASYNC240 rule findings

5 participants