From 06db5a454eba061ebc0475a63c41cff6fcbbba7f Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Wed, 20 Mar 2024 14:48:29 +0100
Subject: [PATCH 01/11] add basic sphinx & readthedocs stuff
---
.readthedocs.yaml | 33 +++++++++++++++++++++++++++++++++
docs/Makefile | 20 ++++++++++++++++++++
docs/make.bat | 35 +++++++++++++++++++++++++++++++++++
docs/source/conf.py | 37 +++++++++++++++++++++++++++++++++++++
docs/source/index.rst | 20 ++++++++++++++++++++
5 files changed, 145 insertions(+)
create mode 100644 .readthedocs.yaml
create mode 100644 docs/Makefile
create mode 100644 docs/make.bat
create mode 100644 docs/source/conf.py
create mode 100644 docs/source/index.rst
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 00000000..7f972414
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,33 @@
+---
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the OS, Python version and other tools you might need
+build:
+ os: ubuntu-lts-latest
+ tools:
+ python: latest
+ # You can also specify other tool versions:
+ # nodejs: "19"
+ # rust: "1.64"
+ # golang: "1.19"
+
+# Build documentation in the "docs/" directory with Sphinx
+sphinx:
+ configuration: docs/conf.py
+
+# Optionally build your docs in additional formats such as PDF and ePub
+# formats:
+# - pdf
+# - epub
+
+# Optional but recommended, declare the Python requirements required
+# to build your documentation
+# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
+# python:
+# install:
+# - requirements: docs/requirements.txt
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 00000000..d0c3cbf1
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 00000000..dc1312ab
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.https://www.sphinx-doc.org/
+ exit /b 1
+)
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 00000000..5fb5fe49
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,37 @@
+"""Configuration file for the Sphinx documentation builder.
+
+For the full list of built-in configuration values, see the documentation:
+https://www.sphinx-doc.org/en/master/usage/configuration.html
+"""
+
+import flake8_async
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = "flake8-async"
+# A001: shadowing python builtin
+copyright = "2024, Zac Hatfield-Dodds, John Litborn, and Contributors" # noqa: A001
+author = "Zac Hatfield-Dodds, John Litborn, and Contributors"
+
+
+version = flake8_async.__version__
+release = version
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions: list[str] = []
+
+templates_path = ["_templates"]
+exclude_patterns: list[str] = []
+
+# Warn about all references to unknown targets
+nitpicky = True
+
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = "alabaster"
+html_static_path = ["_static"]
diff --git a/docs/source/index.rst b/docs/source/index.rst
new file mode 100644
index 00000000..14d26b46
--- /dev/null
+++ b/docs/source/index.rst
@@ -0,0 +1,20 @@
+.. flake8-async documentation master file, created by
+ sphinx-quickstart on Wed Mar 20 13:37:26 2024.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to flake8-async's documentation!
+========================================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
From 2ebfb1f557ba88010f77ea364de8fc1cb7cefa91 Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Wed, 20 Mar 2024 14:56:01 +0100
Subject: [PATCH 02/11] test triggering RTD ci
From 07283a531639f615dc649c12183d1aa5dfd3a5dc Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Wed, 20 Mar 2024 15:02:41 +0100
Subject: [PATCH 03/11] add __init__, point to correct conf location
---
.readthedocs.yaml | 2 +-
docs/source/__init__.py | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
create mode 100644 docs/source/__init__.py
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 7f972414..a9132bee 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -18,7 +18,7 @@ build:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
- configuration: docs/conf.py
+ configuration: docs/source/conf.py
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
diff --git a/docs/source/__init__.py b/docs/source/__init__.py
new file mode 100644
index 00000000..6e0a7009
--- /dev/null
+++ b/docs/source/__init__.py
@@ -0,0 +1,4 @@
+"""Documentation for flake8-async.
+
+Ruff raised INP001 "implicit namespace package" without this file.
+"""
From e8216e5b2cda6b56b6192ea83be1b8cfcb345b51 Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Wed, 20 Mar 2024 15:16:31 +0100
Subject: [PATCH 04/11] skip separating source dir, add path to flake8_async in
sys.path
---
docs/Makefile | 4 ++--
docs/{source => }/__init__.py | 0
docs/{source => }/conf.py | 6 +++++-
docs/{source => }/index.rst | 0
4 files changed, 7 insertions(+), 3 deletions(-)
rename docs/{source => }/__init__.py (100%)
rename docs/{source => }/conf.py (88%)
rename docs/{source => }/index.rst (100%)
diff --git a/docs/Makefile b/docs/Makefile
index d0c3cbf1..d4bb2cbb 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -5,8 +5,8 @@
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
-SOURCEDIR = source
-BUILDDIR = build
+SOURCEDIR = .
+BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
diff --git a/docs/source/__init__.py b/docs/__init__.py
similarity index 100%
rename from docs/source/__init__.py
rename to docs/__init__.py
diff --git a/docs/source/conf.py b/docs/conf.py
similarity index 88%
rename from docs/source/conf.py
rename to docs/conf.py
index 5fb5fe49..e8d17beb 100644
--- a/docs/source/conf.py
+++ b/docs/conf.py
@@ -4,6 +4,10 @@
https://www.sphinx-doc.org/en/master/usage/configuration.html
"""
+import sys
+from pathlib import Path
+
+sys.path.insert(0, str(Path("..").resolve()))
import flake8_async
# -- Project information -----------------------------------------------------
@@ -24,7 +28,7 @@
extensions: list[str] = []
templates_path = ["_templates"]
-exclude_patterns: list[str] = []
+exclude_patterns: list[str] = ["_build", "Thumbs.db", ".DS_Store"]
# Warn about all references to unknown targets
nitpicky = True
diff --git a/docs/source/index.rst b/docs/index.rst
similarity index 100%
rename from docs/source/index.rst
rename to docs/index.rst
From edeafaa3f527e7dd74fddb8c5bde6c01bdfea58c Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Wed, 20 Mar 2024 15:17:39 +0100
Subject: [PATCH 05/11] update readthedocs.yaml
---
.readthedocs.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index a9132bee..7f972414 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -18,7 +18,7 @@ build:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
- configuration: docs/source/conf.py
+ configuration: docs/conf.py
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
From ef55fe1bbced0d1d97bc7b58e735e7660ecce09f Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Fri, 12 Apr 2024 13:23:02 +0200
Subject: [PATCH 06/11] add docs/requirements.txt, add tox target for making
docs, silence a warning
---
.readthedocs.yaml | 6 +++---
docs/conf.py | 4 +++-
docs/requirements.txt | 1 +
tox.ini | 12 ++++++++++++
4 files changed, 19 insertions(+), 4 deletions(-)
create mode 100644 docs/requirements.txt
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 7f972414..f46cd713 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -28,6 +28,6 @@ sphinx:
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
-# python:
-# install:
-# - requirements: docs/requirements.txt
+python:
+ install:
+ - requirements: docs/requirements.txt
diff --git a/docs/conf.py b/docs/conf.py
index e8d17beb..830d78b4 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -38,4 +38,6 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = "alabaster"
-html_static_path = ["_static"]
+# We don't currently use the _static directory, and git doesn't allow empty directories,
+# so leaving it commented out for now to silence a warning.
+# `html_static_path = ["_static"]`
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 00000000..d3a945f2
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1 @@
+libcst
diff --git a/tox.ini b/tox.ini
index b7e9febc..761ce975 100644
--- a/tox.ini
+++ b/tox.ini
@@ -20,6 +20,18 @@ deps =
commands =
pytest {posargs:-n auto}
+[testenv:docs]
+description = Generate docs locally
+deps =
+ sphinx
+ readthedocs-sphinx-ext
+ -r docs/requirements.txt
+allowlist_externals = make
+changedir = docs
+skip_install = True
+commands =
+ make html
+
# Settings for other tools
[pytest]
addopts =
From dbde890be7b661eef093112d5062a81a1943ae74 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Fri, 12 Apr 2024 11:25:04 +0000
Subject: [PATCH 07/11] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
.readthedocs.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index f46cd713..07156efb 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -29,5 +29,5 @@ sphinx:
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
- install:
- - requirements: docs/requirements.txt
+ install:
+ - requirements: docs/requirements.txt
From 0b7c3f7ae967dc8225ca7d8058a9aac2dfcb002e Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Fri, 12 Apr 2024 16:38:22 +0200
Subject: [PATCH 08/11] slowly getting there.... credits to Claude for
converting the markdown to rst
---
docs/index.rst | 204 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 203 insertions(+), 1 deletion(-)
diff --git a/docs/index.rst b/docs/index.rst
index 14d26b46..39bbf3af 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,18 +3,220 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
-Welcome to flake8-async's documentation!
+flake8-async
========================================
.. toctree::
:maxdepth: 2
:caption: Contents:
+ rules
Indices and tables
==================
+* :doc:`rules`
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+
+
+A highly opinionated flake8 plugin for problems related to `Trio `_, `AnyIO `_, or `asyncio `_.
+This can include anything from outright bugs, to pointless/dead code,
+to likely performance issues, to minor points of idiom that might signal
+a misunderstanding.
+It may well be too noisy for anyone with different opinions, that's OK.
+Pairs well with flake8-bugbear.
+Some checks are incorporated into `ruff `_.
+This plugin was previously known as flake8-trio, and there was a separate small plugin known as flake8-async for asyncio. But this plugin was a superset of the checks in flake8-async, and support for anyio was added, so it's now named flake8-async to more properly convey its usage. At the same time all error codes were renamed from TRIOxxx to ASYNCxxx, as was previously used by the old flake8-async.
+
+Installation
+------------
+
+.. code-block:: console
+
+ pip install flake8-async
+
+Usage
+--------
+
+install and run through flake8
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: sh
+
+ pip install flake8 flake8-async
+ flake8 .
+
+install and run with pre-commit
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you use `pre-commit `_, you can use it with flake8-async by
+adding the following to your ``.pre-commit-config.yaml``:
+
+.. code-block:: yaml
+
+ minimum_pre_commit_version: '2.9.0'
+ repos:
+ - repo: https://github.com/python-trio/flake8-async
+ rev: 23.2.5
+ hooks:
+ - id: flake8-async
+ # args: [--enable=ASYNC, --disable=ASYNC9, --autofix=ASYNC]
+
+This is often considerably faster for large projects, because ``pre-commit``
+can avoid running ``flake8-async`` on unchanged files.
+Afterwards, run
+
+.. code-block:: sh
+
+ pip install pre-commit flake8-async
+ pre-commit run .
+
+install and run as standalone
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If inside a git repository, running without arguments will run it against all ``*.py`` files in the repository.
+
+.. code-block:: sh
+
+ pip install flake8-async
+ flake8-async
+
+with autofixes
+""""""""""""""
+
+.. code-block:: sh
+
+ flake8-async --autofix=ASYNC
+
+specifying source files
+"""""""""""""""""""""""
+
+.. code-block:: sh
+
+ flake8-async my_python_file.py
+
+zsh-only
+''''''''
+
+.. code-block:: zsh
+
+ flake8-async **/*.py
+
+
+Run through ruff
+^^^^^^^^^^^^^^^^
+`Ruff ` is a linter and formatter that reimplements a lot of rules from various flake8 plugins. They currently only support a small subset of the rules though, see https://github.com/astral-sh/ruff/issues/8451 for current status and https://docs.astral.sh/ruff/rules/#flake8-async-async for documentation.
+
+Configuration
+-------------
+
+`You can configure flake8 with command-line options `_,
+but we prefer using a config file. The file needs to start with a section marker ``[flake8]`` and the following options are then parsed using flake8's config parser, and can be used just like any other flake8 options.
+Note that it's not currently possible to use a configuration file when running ``flake8-async`` standalone.
+
+``ValueError`` when trying to ``ignore`` error codes in config file
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Error codes with more than three letters are not possible to ``ignore`` in
+config files since flake8>=6, as flake8 tries to validate correct
+configuration with a regex. We have decided not to conform to this, as it
+would be a breaking change for end-users requiring them to update ``noqa``\ s
+and configurations, we think the ``ASYNC`` code is much more readable than
+e.g. ``ASYxxx``, and ruff does not enforce such a limit. The easiest option
+for users hitting this error is to instead use the ``--disable`` option as
+documented `below <#--disable>`__. See further discussion and other
+workarounds in https://github.com/python-trio/flake8-async/issues/230.
+
+
+``--enable``
+^^^^^^^^^^^^
+
+Comma-separated list of error codes to enable, similar to flake8 --select but is additionally more performant as it will disable non-enabled visitors from running instead of just silencing their errors.
+
+``--disable``
+^^^^^^^^^^^^^
+
+Comma-separated list of error codes to disable, similar to flake8 --ignore but is additionally more performant as it will disable non-enabled visitors from running instead of just silencing their errors.
+
+``--autofix``
+^^^^^^^^^^^^^
+
+Comma-separated list of error-codes to enable autofixing for if implemented. Requires running as a standalone program. Pass ``--autofix=ASYNC`` to enable all autofixes.
+
+
+``--error-on-autofix``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Whether to also print an error message for autofixed errors.
+
+``--anyio``
+^^^^^^^^^^^
+
+Change the default library to be anyio instead of trio. If trio is imported it will assume both are available and print suggestions with [anyio/trio].
+
+``no-checkpoint-warning-decorators``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Comma-separated list of decorators to disable checkpointing checks for, turning off ASYNC910 and ASYNC911 warnings for functions decorated with any decorator matching any in the list. Matching is done with `fnmatch `_. Defaults to disabling for ``asynccontextmanager``.
+
+Decorators-to-match must be identifiers or dotted names only (not PEP-614 expressions), and will match against the name only - e.g. ``foo.bar`` matches ``foo.bar``, ``foo.bar()``, and ``foo.bar(args, here)``, etc.
+
+For example:
+
+::
+
+ no-checkpoint-warning-decorators =
+ mydecorator,
+ mydecoratorpackage.checkpointing_decorators.*,
+ ign*,
+ *.ignore,
+
+``startable-in-context-manager``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Comma-separated list of methods which should be used with ``.start()`` when opening a context manager,
+in addition to the default ``trio.run_process``, ``trio.serve_tcp``, ``trio.serve_ssl_over_tcp``, and
+``trio.serve_listeners``. Names must be valid identifiers as per ``str.isidentifier()``. For example:
+
+::
+
+ startable-in-context-manager =
+ myfun,
+ myfun2,
+
+.. async200-blocking-calls:
+
+``async200-blocking-calls``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Comma-separated list of pairs of values separated by ``->`` (optional whitespace stripped), where the first is a pattern for a call that should raise an error if found inside an async function, and the second is what should be suggested to use instead. It uses fnmatch as per `no-checkpoint-warning-decorators`_ for matching. The part after ``->`` is not used by the checker other than when printing the error, so you could add extra info there if you want.
+
+The format of the error message is ``User-configured blocking sync call {0} in async function, consider replacing with {1}.``, where ``{0}`` is the pattern the call matches and ``{1}`` is the suggested replacement.
+
+Example:
+
+::
+
+ async200-blocking-calls =
+ my_blocking_call -> async.alternative,
+ module.block_call -> other_function_to_use,
+ common_error_call -> alternative(). But sometimes you should use other_function(). Ask joe if you're unsure which one,
+ dangerous_module.* -> corresponding function in safe_module,
+ *.dangerous_call -> .safe_call()
+
+Specified patterns must not have parentheses, and will only match when the pattern is the name of a call, so given the above configuration
+
+::
+
+ async def my_function():
+ my_blocking_call() # this would raise an error
+ x = my_blocking_call(a, b, c) # as would this
+ y = my_blocking_call # but not this
+ y() # or this
+ [my_blocking_call][0]() # nor this
+ def my_blocking_call(): # it's also safe to use the name in other contexts
+ ...
+ arbitrary_other_function(my_blocking_call=None)
From 1a4d5efa7d9f76b2da59894c307435c5acbc00ce Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Mon, 15 Apr 2024 11:23:09 +0200
Subject: [PATCH 09/11] break out rules.rst and usage.rst, various small
updates
---
docs/index.rst | 219 +++++--------------------------------------------
docs/rules.rst | 55 +++++++++++++
docs/usage.rst | 207 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 284 insertions(+), 197 deletions(-)
create mode 100644 docs/rules.rst
create mode 100644 docs/usage.rst
diff --git a/docs/index.rst b/docs/index.rst
index 39bbf3af..ddebd9ca 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,220 +3,45 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
+############
flake8-async
-========================================
-
-.. toctree::
- :maxdepth: 2
- :caption: Contents:
-
- rules
+############
-Indices and tables
-==================
-
-* :doc:`rules`
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
+A highly opinionated flake8 plugin for problems related to `Trio `_, `AnyIO `_, or `asyncio `_.
-A highly opinionated flake8 plugin for problems related to `Trio `_, `AnyIO `_, or `asyncio `_.
This can include anything from outright bugs, to pointless/dead code,
to likely performance issues, to minor points of idiom that might signal
a misunderstanding.
-It may well be too noisy for anyone with different opinions, that's OK.
-Pairs well with flake8-bugbear.
-Some checks are incorporated into `ruff `_.
-This plugin was previously known as flake8-trio, and there was a separate small plugin known as flake8-async for asyncio. But this plugin was a superset of the checks in flake8-async, and support for anyio was added, so it's now named flake8-async to more properly convey its usage. At the same time all error codes were renamed from TRIOxxx to ASYNCxxx, as was previously used by the old flake8-async.
-
-Installation
-------------
-
-.. code-block:: console
-
- pip install flake8-async
-
-Usage
---------
-
-install and run through flake8
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. code-block:: sh
-
- pip install flake8 flake8-async
- flake8 .
-
-install and run with pre-commit
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-If you use `pre-commit `_, you can use it with flake8-async by
-adding the following to your ``.pre-commit-config.yaml``:
-
-.. code-block:: yaml
-
- minimum_pre_commit_version: '2.9.0'
- repos:
- - repo: https://github.com/python-trio/flake8-async
- rev: 23.2.5
- hooks:
- - id: flake8-async
- # args: [--enable=ASYNC, --disable=ASYNC9, --autofix=ASYNC]
-
-This is often considerably faster for large projects, because ``pre-commit``
-can avoid running ``flake8-async`` on unchanged files.
-Afterwards, run
-
-.. code-block:: sh
-
- pip install pre-commit flake8-async
- pre-commit run .
-
-install and run as standalone
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-If inside a git repository, running without arguments will run it against all ``*.py`` files in the repository.
-
-.. code-block:: sh
-
- pip install flake8-async
- flake8-async
-
-with autofixes
-""""""""""""""
-
-.. code-block:: sh
-
- flake8-async --autofix=ASYNC
-
-specifying source files
-"""""""""""""""""""""""
-
-.. code-block:: sh
-
- flake8-async my_python_file.py
-zsh-only
-''''''''
-.. code-block:: zsh
-
- flake8-async **/*.py
-
-
-Run through ruff
-^^^^^^^^^^^^^^^^
-`Ruff ` is a linter and formatter that reimplements a lot of rules from various flake8 plugins. They currently only support a small subset of the rules though, see https://github.com/astral-sh/ruff/issues/8451 for current status and https://docs.astral.sh/ruff/rules/#flake8-async-async for documentation.
-
-Configuration
--------------
-
-`You can configure flake8 with command-line options `_,
-but we prefer using a config file. The file needs to start with a section marker ``[flake8]`` and the following options are then parsed using flake8's config parser, and can be used just like any other flake8 options.
-Note that it's not currently possible to use a configuration file when running ``flake8-async`` standalone.
-
-``ValueError`` when trying to ``ignore`` error codes in config file
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Error codes with more than three letters are not possible to ``ignore`` in
-config files since flake8>=6, as flake8 tries to validate correct
-configuration with a regex. We have decided not to conform to this, as it
-would be a breaking change for end-users requiring them to update ``noqa``\ s
-and configurations, we think the ``ASYNC`` code is much more readable than
-e.g. ``ASYxxx``, and ruff does not enforce such a limit. The easiest option
-for users hitting this error is to instead use the ``--disable`` option as
-documented `below <#--disable>`__. See further discussion and other
-workarounds in https://github.com/python-trio/flake8-async/issues/230.
-
-
-``--enable``
-^^^^^^^^^^^^
-
-Comma-separated list of error codes to enable, similar to flake8 --select but is additionally more performant as it will disable non-enabled visitors from running instead of just silencing their errors.
-
-``--disable``
-^^^^^^^^^^^^^
-
-Comma-separated list of error codes to disable, similar to flake8 --ignore but is additionally more performant as it will disable non-enabled visitors from running instead of just silencing their errors.
-
-``--autofix``
-^^^^^^^^^^^^^
-
-Comma-separated list of error-codes to enable autofixing for if implemented. Requires running as a standalone program. Pass ``--autofix=ASYNC`` to enable all autofixes.
-
-
-``--error-on-autofix``
-^^^^^^^^^^^^^^^^^^^^^^
-
-Whether to also print an error message for autofixed errors.
-
-``--anyio``
-^^^^^^^^^^^
-
-Change the default library to be anyio instead of trio. If trio is imported it will assume both are available and print suggestions with [anyio/trio].
-
-``no-checkpoint-warning-decorators``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Comma-separated list of decorators to disable checkpointing checks for, turning off ASYNC910 and ASYNC911 warnings for functions decorated with any decorator matching any in the list. Matching is done with `fnmatch `_. Defaults to disabling for ``asynccontextmanager``.
-
-Decorators-to-match must be identifiers or dotted names only (not PEP-614 expressions), and will match against the name only - e.g. ``foo.bar`` matches ``foo.bar``, ``foo.bar()``, and ``foo.bar(args, here)``, etc.
-
-For example:
-
-::
-
- no-checkpoint-warning-decorators =
- mydecorator,
- mydecoratorpackage.checkpointing_decorators.*,
- ign*,
- *.ignore,
-
-``startable-in-context-manager``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Comma-separated list of methods which should be used with ``.start()`` when opening a context manager,
-in addition to the default ``trio.run_process``, ``trio.serve_tcp``, ``trio.serve_ssl_over_tcp``, and
-``trio.serve_listeners``. Names must be valid identifiers as per ``str.isidentifier()``. For example:
-
-::
-
- startable-in-context-manager =
- myfun,
- myfun2,
+The plugin may well be too noisy or pedantic depending on your requirements or opinions, in which case you should consider :ref:`--disable` for those rules.
+Pairs well with flake8-bugbear.
-.. async200-blocking-calls:
-``async200-blocking-calls``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Some checks are incorporated into `ruff `_.
-Comma-separated list of pairs of values separated by ``->`` (optional whitespace stripped), where the first is a pattern for a call that should raise an error if found inside an async function, and the second is what should be suggested to use instead. It uses fnmatch as per `no-checkpoint-warning-decorators`_ for matching. The part after ``->`` is not used by the checker other than when printing the error, so you could add extra info there if you want.
-The format of the error message is ``User-configured blocking sync call {0} in async function, consider replacing with {1}.``, where ``{0}`` is the pattern the call matches and ``{1}`` is the suggested replacement.
+This plugin was previously known as flake8-trio, and there was a separate small plugin known as flake8-async for asyncio. But this plugin was a superset of the checks in flake8-async, and support for anyio was added, so it's now named flake8-async to more properly convey its usage. At the same time all error codes were renamed from TRIOxxx to ASYNCxxx, as was previously used by the old flake8-async.
-Example:
-::
+*********
+Contents:
+*********
+.. toctree::
+ :maxdepth: 2
- async200-blocking-calls =
- my_blocking_call -> async.alternative,
- module.block_call -> other_function_to_use,
- common_error_call -> alternative(). But sometimes you should use other_function(). Ask joe if you're unsure which one,
- dangerous_module.* -> corresponding function in safe_module,
- *.dangerous_call -> .safe_call()
+ usage
+ rules
-Specified patterns must not have parentheses, and will only match when the pattern is the name of a call, so given the above configuration
-::
+******************
+Indices and tables
+******************
- async def my_function():
- my_blocking_call() # this would raise an error
- x = my_blocking_call(a, b, c) # as would this
- y = my_blocking_call # but not this
- y() # or this
- [my_blocking_call][0]() # nor this
- def my_blocking_call(): # it's also safe to use the name in other contexts
- ...
- arbitrary_other_function(my_blocking_call=None)
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+* :doc:`usage`
+* :doc:`rules`
diff --git a/docs/rules.rst b/docs/rules.rst
new file mode 100644
index 00000000..3b6f378d
--- /dev/null
+++ b/docs/rules.rst
@@ -0,0 +1,55 @@
+List of warnings
+------------------
+
+- **ASYNC100**: A ``with [trio/anyio].fail_after(...):`` or ``with [trio/anyio].move_on_after(...):`` context does not contain any ``await`` statements. This makes it pointless, as the timeout can only be triggered by a checkpoint. This check also allows ``yield`` statements, since checkpoints can happen in the caller we yield to.
+- **ASYNC101**: ``yield`` inside a trio/anyio nursery or cancel scope is only safe when implementing a context manager - otherwise, it breaks exception handling.
+- **ASYNC102**: It's unsafe to await inside ``finally:`` or ``except BaseException/trio.Cancelled/anyio.get_cancelled_exc_class()/asyncio.exceptions.CancelledError`` unless you use a shielded cancel scope with a timeout. This is currently not able to detect asyncio shields.
+- **ASYNC103**: ``except BaseException/trio.Cancelled/anyio.get_cancelled_exc_class()/asyncio.exceptions.CancelledError``, or a bare ``except:`` with a code path that doesn't re-raise. If you don't want to re-raise ``BaseException``, add a separate handler for ``trio.Cancelled``/``anyio.get_cancelled_exc_class()``/``asyncio.exceptions.CancelledError`` before.
+- **ASYNC104**: ``trio.Cancelled``/``anyio.get_cancelled_exc_class()``/``asyncio.exceptions.CancelledError``/``BaseException`` must be re-raised. The same as ASYNC103, except specifically triggered on ``return`` or a different exception being raised.
+- **ASYNC105**: Calling a trio async function without immediately ``await``\ ing it. This is only supported with trio functions, but you can get similar functionality with a type-checker.
+- **ASYNC106**: ``trio``/``anyio``/``asyncio`` must be imported with ``import trio``/``import anyio``/``import asyncio`` for the linter to work.
+- **ASYNC109**: Async function definition with a ``timeout`` parameter - use ``[trio/anyio].[fail/move_on]_[after/at]`` instead.
+- **ASYNC110**: ``while : await [trio/anyio].sleep()`` should be replaced by a ``[trio/anyio].Event``.
+- **ASYNC111**: Variable, from context manager opened inside nursery, passed to ``start[_soon]`` might be invalidly accessed while in use, due to context manager closing before the nursery. This is usually a bug, and nurseries should generally be the inner-most context manager.
+- **ASYNC112**: Nursery body with only a call to ``nursery.start[_soon]`` and not passing itself as a parameter can be replaced with a regular function call.
+- **ASYNC113**: Using ``nursery.start_soon`` in ``__aenter__`` doesn't wait for the task to begin. Consider replacing with ``nursery.start``.
+- **ASYNC114**: Startable function (i.e. has a ``task_status`` keyword parameter) not in ``--startable-in-context-manager`` parameter list, please add it so ASYNC113 can catch errors when using it.
+- **ASYNC115**: Replace ``[trio/anyio].sleep(0)`` with the more suggestive ``[trio/anyio].lowlevel.checkpoint()``.
+- **ASYNC116**: ``[trio/anyio].sleep()`` with >24 hour interval should usually be ``[trio/anyio].sleep_forever()``.
+- **ASYNC118**: Don't assign the value of ``anyio.get_cancelled_exc_class()`` to a variable, since that breaks linter checks and multi-backend programs.
+
+Warnings for blocking sync calls in async functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Note: 22X, 23X and 24X has not had asyncio-specific suggestions written.
+
+
+- **ASYNC200**: User-configured error for blocking sync calls in async functions. Does nothing by default, see :ref:`async200-blocking-calls` for how to configure it.
+- **ASYNC210**: Sync HTTP call in async function, use ``httpx.AsyncClient``. This and the other ASYNC21x checks look for usage of ``urllib3`` and ``httpx.Client``, and recommend using ``httpx.AsyncClient`` as that's the largest http client supporting anyio/trio.
+- **ASYNC211**: Likely sync HTTP call in async function, use ``httpx.AsyncClient``. Looks for ``urllib3`` method calls on pool objects, but only matching on the method signature and not the object.
+- **ASYNC212**: Blocking sync HTTP call on httpx object, use httpx.AsyncClient.
+- **ASYNC220**: Sync process call in async function, use ``await nursery.start([trio/anyio].run_process, ...)``. ``asyncio`` users can use `asyncio.create_subprocess_[exec/shell] `_.
+- **ASYNC221**: Sync process call in async function, use ``await [trio/anyio].run_process(...)``. ``asyncio`` users can use `asyncio.create_subprocess_[exec/shell] `_.
+- **ASYNC222**: Sync ``os.*`` call in async function, wrap in ``await [trio/anyio].to_thread.run_sync()``. ``asyncio`` users can use `asyncio.loop.run_in_executor `_.
+- **ASYNC230**: Sync IO call in async function, use ``[trio/anyio].open_file(...)``. ``asyncio`` users need to use a library such as `aiofiles `_, or switch to `anyio `_.
+- **ASYNC231**: Sync IO call in async function, use ``[trio/anyio].wrap_file(...)``. ``asyncio`` users need to use a library such as `aiofiles `_, or switch to `anyio `_.
+- **ASYNC232**: Blocking sync call on file object, wrap the file object in ``[trio/anyio].wrap_file()`` to get an async file object.
+- **ASYNC240**: Avoid using ``os.path`` in async functions, prefer using ``[trio/anyio].Path`` objects. ``asyncio`` users should consider `aiopath `_ or `anyio `_.
+- **ASYNC250**: Builtin ``input()`` should not be called from async function. Wrap in ``[trio/anyio].to_thread.run_sync()`` or ``asyncio.loop.run_in_executor()``.
+- **ASYNC251**: ``time.sleep(...)`` should not be called from async function. Use ``[trio/anyio/asyncio].sleep(...)``.
+
+Warnings disabled by default
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- **ASYNC900**: Async generator without ``@asynccontextmanager`` not allowed. You might want to enable this on a codebase since async generators are inherently unsafe and cleanup logic might not be performed. See https://github.com/python-trio/flake8-async/issues/211 and https://discuss.python.org/t/using-exceptiongroup-at-anthropic-experience-report/20888/6 for discussion.
+- **ASYNC910**: Exit or ``return`` from async function with no guaranteed checkpoint or exception since function definition. You might want to enable this on a codebase to make it easier to reason about checkpoints, and make the logic of ASYNC911 correct.
+- **ASYNC911**: Exit, ``yield`` or ``return`` from async iterable with no guaranteed checkpoint since possible function entry (yield or function definition)
+ Checkpoints are ``await``, ``async for``, and ``async with`` (on one of enter/exit).
+
+Removed warnings
+~~~~~~~~~~~~~~~~
+
+- **TRIOxxx**: All error codes are now renamed ASYNCxxx
+- **TRIO107**: Renamed to TRIO910
+- **TRIO108**: Renamed to TRIO911
+- **TRIO117**: Don't raise
diff --git a/docs/usage.rst b/docs/usage.rst
new file mode 100644
index 00000000..2cadfbac
--- /dev/null
+++ b/docs/usage.rst
@@ -0,0 +1,207 @@
+************
+Installation
+************
+
+.. code-block:: console
+
+ pip install flake8-async
+
+*****
+Usage
+*****
+
+install and run through flake8
+==============================
+
+.. code-block:: sh
+
+ pip install flake8 flake8-async
+ flake8 .
+
+install and run with pre-commit
+===============================
+
+If you use `pre-commit `_, you can use it with flake8-async by
+adding the following to your ``.pre-commit-config.yaml``:
+
+.. code-block:: yaml
+
+ minimum_pre_commit_version: '2.9.0'
+ repos:
+ - repo: https://github.com/python-trio/flake8-async
+ rev: 23.2.5
+ hooks:
+ - id: flake8-async
+ # args: [--enable=ASYNC, --disable=ASYNC9, --autofix=ASYNC]
+
+This is often considerably faster for large projects, because ``pre-commit``
+can avoid running ``flake8-async`` on unchanged files.
+Afterwards, run
+
+.. code-block:: sh
+
+ pip install pre-commit flake8-async
+ pre-commit run .
+
+install and run as standalone
+=============================
+
+If inside a git repository, running without arguments will run it against all ``*.py`` files in the repository.
+
+.. code-block:: sh
+
+ pip install flake8-async
+ flake8-async
+
+with autofixes
+--------------
+
+.. code-block:: sh
+
+ flake8-async --autofix=ASYNC
+
+specifying source files
+-----------------------
+
+.. code-block:: sh
+
+ flake8-async my_python_file.py
+
+zsh-only
+^^^^^^^^
+
+.. code-block:: zsh
+
+ flake8-async **/*.py
+
+
+Run through ruff
+================
+`Ruff ` is a linter and formatter that reimplements a lot of rules from various flake8 plugins. They currently only support a small subset of the rules though, see https://github.com/astral-sh/ruff/issues/8451 for current status and https://docs.astral.sh/ruff/rules/#flake8-async-async for documentation.
+
+*************
+Configuration
+*************
+
+`You can configure flake8 with command-line options `_,
+but we prefer using a config file. The file needs to start with a section marker ``[flake8]`` and the following options are then parsed using flake8's config parser, and can be used just like any other flake8 options.
+Note that it's not currently possible to use a configuration file when running ``flake8-async`` standalone.
+
+Selecting rules
+===============
+
+``ValueError`` when trying to ``ignore`` error codes in config file
+-------------------------------------------------------------------
+
+Error codes with more than three letters are not possible to ``ignore`` in
+config files since flake8>=6, as flake8 tries to validate correct
+configuration with a regex. We have decided not to conform to this, as it
+would be a breaking change for end-users requiring them to update ``noqa``\ s
+and configurations, we think the ``ASYNC`` code is much more readable than
+e.g. ``ASYxxx``, and ruff does not enforce such a limit. The easiest option
+for users hitting this error is to instead use the ``--disable`` option as
+documented `below <#--disable>`__. See further discussion and other
+workarounds in https://github.com/python-trio/flake8-async/issues/230.
+
+
+``--enable``
+------------
+
+Comma-separated list of error codes to enable, similar to flake8 --select but is additionally more performant as it will disable non-enabled visitors from running instead of just silencing their errors.
+
+.. _--disable:
+
+``--disable``
+-------------
+
+Comma-separated list of error codes to disable, similar to flake8 ``--ignore`` but is additionally more performant as it will disable non-enabled visitors from running instead of just silencing their errors. It will also bypass errors introduced in flake8>=6, see above.
+
+``--autofix``
+-------------
+
+Comma-separated list of error-codes to enable autofixing for if implemented. Requires running as a standalone program. Pass ``--autofix=ASYNC`` to enable all autofixes.
+
+
+``--error-on-autofix``
+----------------------
+
+Whether to also print an error message for autofixed errors.
+
+Modifying rule behaviour
+========================
+
+.. _--anyio:
+
+``--anyio``
+-----------
+
+Change the default library to be anyio instead of trio. If trio is imported it will assume both are available and print suggestions with [anyio/trio].
+
+``--asyncio``
+-------------
+Set default library to be ``asyncio``. See :ref:`--anyio`
+
+
+``no-checkpoint-warning-decorators``
+------------------------------------
+
+Comma-separated list of decorators to disable checkpointing checks for, turning off ASYNC910 and ASYNC911 warnings for functions decorated with any decorator matching any in the list. Matching is done with `fnmatch `_. Defaults to disabling for ``asynccontextmanager``.
+
+Decorators-to-match must be identifiers or dotted names only (not PEP-614 expressions), and will match against the name only - e.g. ``foo.bar`` matches ``foo.bar``, ``foo.bar()``, and ``foo.bar(args, here)``, etc.
+
+For example:
+
+::
+
+ no-checkpoint-warning-decorators =
+ mydecorator,
+ mydecoratorpackage.checkpointing_decorators.*,
+ ign*,
+ *.ignore,
+
+``startable-in-context-manager``
+--------------------------------
+
+Comma-separated list of methods which should be used with ``.start()`` when opening a context manager,
+in addition to the default ``trio.run_process``, ``trio.serve_tcp``, ``trio.serve_ssl_over_tcp``, and
+``trio.serve_listeners``. Names must be valid identifiers as per ``str.isidentifier()``. For example:
+
+::
+
+ startable-in-context-manager =
+ myfun,
+ myfun2,
+
+.. async200-blocking-calls:
+
+``async200-blocking-calls``
+---------------------------
+
+Comma-separated list of pairs of values separated by ``->`` (optional whitespace stripped), where the first is a pattern for a call that should raise an error if found inside an async function, and the second is what should be suggested to use instead. It uses fnmatch as per `no-checkpoint-warning-decorators`_ for matching. The part after ``->`` is not used by the checker other than when printing the error, so you could add extra info there if you want.
+
+The format of the error message is ``User-configured blocking sync call {0} in async function, consider replacing with {1}.``, where ``{0}`` is the pattern the call matches and ``{1}`` is the suggested replacement.
+
+Example:
+
+::
+
+ async200-blocking-calls =
+ my_blocking_call -> async.alternative,
+ module.block_call -> other_function_to_use,
+ common_error_call -> alternative(). But sometimes you should use other_function(). Ask joe if you're unsure which one,
+ dangerous_module.* -> corresponding function in safe_module,
+ *.dangerous_call -> .safe_call()
+
+Specified patterns must not have parentheses, and will only match when the pattern is the name of a call, so given the above configuration
+
+::
+
+ async def my_function():
+ my_blocking_call() # this would raise an error
+ x = my_blocking_call(a, b, c) # as would this
+ y = my_blocking_call # but not this
+ y() # or this
+ [my_blocking_call][0]() # nor this
+ def my_blocking_call(): # it's also safe to use the name in other contexts
+ ...
+ arbitrary_other_function(my_blocking_call=None)
From 1ca1d96243af4d30548aeb73f40b6405d1e5beb2 Mon Sep 17 00:00:00 2001
From: John Litborn <11260241+jakkdl@users.noreply.github.com>
Date: Tue, 16 Apr 2024 13:32:16 +0200
Subject: [PATCH 10/11] Apply suggestions from code review
Co-authored-by: Zac Hatfield-Dodds
---
docs/index.rst | 2 +-
docs/usage.rst | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/docs/index.rst b/docs/index.rst
index ddebd9ca..05d3270c 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -23,7 +23,7 @@ Pairs well with flake8-bugbear.
Some checks are incorporated into `ruff `_.
-This plugin was previously known as flake8-trio, and there was a separate small plugin known as flake8-async for asyncio. But this plugin was a superset of the checks in flake8-async, and support for anyio was added, so it's now named flake8-async to more properly convey its usage. At the same time all error codes were renamed from TRIOxxx to ASYNCxxx, as was previously used by the old flake8-async.
+We previously maintained separate flake8-async and flake8-trio plugins, but merged both into this plugin under the more general "flake8-async" name after flake8-trio grew support for anyio and asyncio and became a superset of the former flake8-async. All flake8-trio error codes were renamed from TRIOxxx to ASYNCxxx and the flake8-trio package is now deprecated.
*********
diff --git a/docs/usage.rst b/docs/usage.rst
index 2cadfbac..a7def4da 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -77,7 +77,9 @@ zsh-only
Run through ruff
================
-`Ruff ` is a linter and formatter that reimplements a lot of rules from various flake8 plugins. They currently only support a small subset of the rules though, see https://github.com/astral-sh/ruff/issues/8451 for current status and https://docs.astral.sh/ruff/rules/#flake8-async-async for documentation.
+`Ruff `_ is a linter and formatter that reimplements a lot of rules from various flake8 plugins.
+
+They currently only support a small subset of the rules though, see https://github.com/astral-sh/ruff/issues/8451 for current status and https://docs.astral.sh/ruff/rules/#flake8-async-async for documentation.
*************
Configuration
From efe6556bf51c5356b7b3622d91a607e800f7bf03 Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Tue, 16 Apr 2024 14:54:43 +0200
Subject: [PATCH 11/11] update docs after review
---
docs/index.rst | 2 +-
docs/rules.rst | 22 +++++++++++++---------
docs/usage.rst | 13 +++++++++----
3 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/docs/index.rst b/docs/index.rst
index 05d3270c..d41e7ff2 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -20,7 +20,7 @@ The plugin may well be too noisy or pedantic depending on your requirements or o
Pairs well with flake8-bugbear.
-Some checks are incorporated into `ruff `_.
+Some rules are incorporated into `ruff `_.
We previously maintained separate flake8-async and flake8-trio plugins, but merged both into this plugin under the more general "flake8-async" name after flake8-trio grew support for anyio and asyncio and became a superset of the former flake8-async. All flake8-trio error codes were renamed from TRIOxxx to ASYNCxxx and the flake8-trio package is now deprecated.
diff --git a/docs/rules.rst b/docs/rules.rst
index 3b6f378d..007a5485 100644
--- a/docs/rules.rst
+++ b/docs/rules.rst
@@ -1,5 +1,9 @@
-List of warnings
-------------------
+****************
+List of rules
+****************
+
+General rules
+=============
- **ASYNC100**: A ``with [trio/anyio].fail_after(...):`` or ``with [trio/anyio].move_on_after(...):`` context does not contain any ``await`` statements. This makes it pointless, as the timeout can only be triggered by a checkpoint. This check also allows ``yield`` statements, since checkpoints can happen in the caller we yield to.
- **ASYNC101**: ``yield`` inside a trio/anyio nursery or cancel scope is only safe when implementing a context manager - otherwise, it breaks exception handling.
@@ -18,8 +22,8 @@ List of warnings
- **ASYNC116**: ``[trio/anyio].sleep()`` with >24 hour interval should usually be ``[trio/anyio].sleep_forever()``.
- **ASYNC118**: Don't assign the value of ``anyio.get_cancelled_exc_class()`` to a variable, since that breaks linter checks and multi-backend programs.
-Warnings for blocking sync calls in async functions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Blocking sync calls in async functions
+======================================
Note: 22X, 23X and 24X has not had asyncio-specific suggestions written.
@@ -38,18 +42,18 @@ Note: 22X, 23X and 24X has not had asyncio-specific suggestions written.
- **ASYNC250**: Builtin ``input()`` should not be called from async function. Wrap in ``[trio/anyio].to_thread.run_sync()`` or ``asyncio.loop.run_in_executor()``.
- **ASYNC251**: ``time.sleep(...)`` should not be called from async function. Use ``[trio/anyio/asyncio].sleep(...)``.
-Warnings disabled by default
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Optional rules disabled by default
+==================================
- **ASYNC900**: Async generator without ``@asynccontextmanager`` not allowed. You might want to enable this on a codebase since async generators are inherently unsafe and cleanup logic might not be performed. See https://github.com/python-trio/flake8-async/issues/211 and https://discuss.python.org/t/using-exceptiongroup-at-anthropic-experience-report/20888/6 for discussion.
- **ASYNC910**: Exit or ``return`` from async function with no guaranteed checkpoint or exception since function definition. You might want to enable this on a codebase to make it easier to reason about checkpoints, and make the logic of ASYNC911 correct.
- **ASYNC911**: Exit, ``yield`` or ``return`` from async iterable with no guaranteed checkpoint since possible function entry (yield or function definition)
Checkpoints are ``await``, ``async for``, and ``async with`` (on one of enter/exit).
-Removed warnings
-~~~~~~~~~~~~~~~~
+Removed rules
+================
- **TRIOxxx**: All error codes are now renamed ASYNCxxx
- **TRIO107**: Renamed to TRIO910
- **TRIO108**: Renamed to TRIO911
-- **TRIO117**: Don't raise
+- **TRIO117**: "Don't raise or catch ``trio.[NonBase]MultiError``, prefer ``[exceptiongroup.]BaseExceptionGroup``." ``MultiError`` was removed in trio==0.24.0.
diff --git a/docs/usage.rst b/docs/usage.rst
index a7def4da..78aba3bc 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -18,6 +18,8 @@ install and run through flake8
pip install flake8 flake8-async
flake8 .
+.. _install-run-pre-commit:
+
install and run with pre-commit
===============================
@@ -85,9 +87,12 @@ They currently only support a small subset of the rules though, see https://gith
Configuration
*************
-`You can configure flake8 with command-line options `_,
-but we prefer using a config file. The file needs to start with a section marker ``[flake8]`` and the following options are then parsed using flake8's config parser, and can be used just like any other flake8 options.
-Note that it's not currently possible to use a configuration file when running ``flake8-async`` standalone.
+`You can configure flake8 with command-line options `_,
+but we prefer using a config file. See general documentation for `configuring flake8 `_ which also handles options registered by plugins such as ``flake8-async``.
+
+If you want to use a ``pyproject.toml`` file for configuring flake8 we recommend `pyproject-flake8 ` or similar.
+
+Note that when running ``flake8-async`` as a standalone it's not currently possible to use a configuration file. Consider using some wrapper that lets you specify command-line flags in a file. For example, :ref:`install-run-pre-commit`, `tox `, `hatch scripts `, MakeFiles, etc.
Selecting rules
===============
@@ -174,7 +179,7 @@ in addition to the default ``trio.run_process``, ``trio.serve_tcp``, ``trio.serv
myfun,
myfun2,
-.. async200-blocking-calls:
+.. _async200-blocking-calls:
``async200-blocking-calls``
---------------------------