Installation

Install from PyPI

pip install flake8-async

Usage

install and run through flake8

pip install flake8-async[flake8]
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:

minimum_pre_commit_version: '2.9.0'
repos:
- repo: https://github.com/python-trio/flake8-async
  rev: 25.3.1
  hooks:
    - id: flake8-async
      # args: ["--enable=ASYNC100,ASYNC112", "--disable=", "--autofix=ASYNC"]

This is often considerably faster for large projects, because pre-commit can avoid running flake8-async on unchanged files. flake8-async does not retain any memory between files, they are parsed completely independently.

Afterwards, run

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.

Note that this does not currently support reading config files, and does not respect # noqa comments.

pip install flake8-async
flake8-async

with autofixes

flake8-async --autofix=ASYNC

specifying source files

flake8-async my_python_file.py

zsh-only

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 flake8-async 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. 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, install and run with pre-commit, tox, hatch scripts, MakeFiles, etc.

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 noqas 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. 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. Defaults to “ASYNC”.

Example

enable=ASYNC1,ASYNC200

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. This is parsed after enable, so if a rule is both “enabled” and “disabled” it will be disabled. Defaults to “ASYNC9”.

Example

disable=ASYNC91,ASYNC117

autofix

Comma-separated list of error-codes to enable autofixing for if implemented. Requires running as a standalone program. Only a subset of rules support autofixing, see this list. Pass --autofix=ASYNC to enable all available autofixes.

Defaults to an empty list.

Example

autofix=ASYNC

error-on-autofix

Whether to also print an error message for autofixed errors. Defaults to False

Example

error-on-autofix=True

Modifying rule behaviour

anyio

Change the default library to be anyio instead of trio. This is mostly used for the sake of printing suggestions in error messages, but may affect some logic. If additional libraries are imported other than the default then rules will assume multiple are available simultaneously. It is currently not possible to set multiple default libraries, other than anyio`+`asyncio.

Example

anyio=True

asyncio

Set default library to be asyncio. See anyio

Example

asyncio=True

no-checkpoint-warning-decorators

Comma-separated list of decorators to disable checkpointing checks for, turning off ASYNC910, ASYNC911, and ASYNC124 warnings for functions decorated with any decorator matching against an entry 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.

Example

no-checkpoint-warning-decorators =
  mydecorator,
  mydecoratorpackage.checkpointing_decorators.*,
  ign*,
  *.ignore,

exception-suppress-context-managers

Comma-separated list of contextmanagers which may suppress exceptions without reraising. For ASYNC91x, these will be parsed in the worst-case scenario, where any checkpoints inside the contextmanager are not executed, and all exceptions are suppressed. contextlib.suppress will be added to the list after parsing, and some basic parsing of from contextlib import suppress is supported. Decorators can be dotted or not, as well as support * as a wildcard.

If you want to be extremely pessimistic, you can specify * as the context manager. We may add a whitelist option in the future to support this use-case better.

Example

exception-suppress-context-managers =
  mysuppressor,
  dangerouslibrary.*,
  *.suppress,

startable-in-context-manager

Comma-separated list of functions which should be used with trio.Nursery.start()/anyio.abc.TaskGroup.start() when opening a context manager. We then add known functions from Trio to this list, namely trio.run_process(), trio.serve_tcp(), trio.serve_ssl_over_tcp(), trio.serve_listeners(), and trio.DTLSEndpoint.serve(). AnyIO does not have any functions in its API that defines task_status. asyncio does not have an equivalent of start(), nor task_status, but you could still add functions to this list that you want to be extra careful about when opening in an asyncio.TaskGroup in an __aenter__

Names must be valid identifiers as per str.isidentifier(). Used by ASYNC113, and ASYNC114 will warn when encountering methods not in the list.

Example

startable-in-context-manager =
  myfun,
  myfun2,

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 ASYNC200 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)

transform-async-generator-decorators

Comma-separated list of decorators that make async generators safe, disabling ASYNC900, ASYNC101, and ASYNC119 warnings for functions decorated with any of them. [pytest.]fixture and [contextlib.]asynccontextmanager are always considered safe. Decorators can be dotted or not, as well as support * as a wildcard.

Example

transform-async-generator-decorators =
  fastapi.Depends
  trio_util.trio_async_generator