From 1be8c2e3409ab9eb1b9b1c20bd6076f824c93f16 Mon Sep 17 00:00:00 2001 From: James Braza Date: Sun, 1 Sep 2024 03:16:57 -0700 Subject: [PATCH] Expand docs for `ASYNC109` (#13146) Co-authored-by: Alex Waygood --- .../rules/async_function_with_timeout.rs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/crates/ruff_linter/src/rules/flake8_async/rules/async_function_with_timeout.rs b/crates/ruff_linter/src/rules/flake8_async/rules/async_function_with_timeout.rs index 4ceedafb5b..943cc26288 100644 --- a/crates/ruff_linter/src/rules/flake8_async/rules/async_function_with_timeout.rs +++ b/crates/ruff_linter/src/rules/flake8_async/rules/async_function_with_timeout.rs @@ -9,13 +9,33 @@ use crate::rules::flake8_async::helpers::AsyncModule; use crate::settings::types::PythonVersion; /// ## What it does -/// Checks for `async` functions with a `timeout` argument. +/// Checks for `async` function definitions with `timeout` parameters. /// /// ## Why is this bad? /// Rather than implementing asynchronous timeout behavior manually, prefer /// built-in timeout functionality, such as `asyncio.timeout`, `trio.fail_after`, /// or `anyio.move_on_after`, among others. /// +/// This rule is highly opinionated to enforce a design pattern +/// called ["structured concurrency"] that allows for +/// `async` functions to be oblivious to timeouts, +/// instead letting callers to handle the logic with a context manager. +/// +/// ## Details +/// +/// This rule attempts to detect which async framework your code is using +/// by analysing the imports in the file it's checking. If it sees an +/// `anyio` import in your code, it will assume `anyio` is your framework +/// of choice; if it sees a `trio` import, it will assume `trio`; if it +/// sees neither, it will assume `asyncio`. `asyncio.timeout` was added +/// in Python 3.11, so if `asyncio` is detected as the framework being used, +/// this rule will be ignored when your configured [`target-version`] is set +/// to less than Python 3.11. +/// +/// For functions that wrap `asyncio.timeout`, `trio.fail_after` or +/// `anyio.move_on_after`, false positives from this rule can be avoided +/// by using a different parameter name. +/// /// ## Example /// /// ```python @@ -41,6 +61,8 @@ use crate::settings::types::PythonVersion; /// - [`asyncio` timeouts](https://docs.python.org/3/library/asyncio-task.html#timeouts) /// - [`anyio` timeouts](https://anyio.readthedocs.io/en/stable/cancellation.html) /// - [`trio` timeouts](https://trio.readthedocs.io/en/stable/reference-core.html#cancellation-and-timeouts) +/// +/// ["structured concurrency"]: https://vorpus.org/blog/some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world/#timeouts-and-cancellation #[violation] pub struct AsyncFunctionWithTimeout { module: AsyncModule,