A highly opinionated flake8 plugin for Trio-related problems.
Project description
flake8-trio
A highly opinionated flake8 plugin for Trio-related problems.
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.
It also supports the anyio library.
Pairs well with flake8-bugbear.
Installation
pip install flake8-trio
List of warnings
- TRIO100: a
with trio.fail_after(...):orwith trio.move_on_after(...):context does not contain anyawaitstatements. This makes it pointless, as the timeout can only be triggered by a checkpoint. - TRIO101:
yieldinside a nursery or cancel scope is only safe when implementing a context manager - otherwise, it breaks exception handling. - TRIO102: it's unsafe to await inside
finally:orexcept BaseException/trio.Cancelledunless you use a shielded cancel scope with a timeout. - TRIO103:
except BaseException,except trio.Cancelledor a bareexcept:with a code path that doesn't re-raise. If you don't want to re-raiseBaseException, add a separate handler fortrio.Cancelledbefore. - TRIO104:
CancelledandBaseExceptionmust be re-raised - when a user tries toreturnorraisea different exception. - TRIO105: Calling a trio async function without immediately
awaiting it. - TRIO106: trio must be imported with
import triofor the linter to work. - TRIO107: Renamed to TRIO910
- TRIO108: Renamed to TRIO911
- TRIO109: Async function definition with a
timeoutparameter - usetrio.[fail/move_on]_[after/at]instead - TRIO110:
while <condition>: await trio.sleep()should be replaced by atrio.Event. - TRIO111: 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. - TRIO112: 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. - TRIO113: using
nursery.start_soonin__aenter__doesn't wait for the task to begin. Consider replacing withnursery.start. - TRIO114: Startable function (i.e. has a
task_statuskeyword parameter) not in--startable-in-context-managerparameter list, please add it so TRIO113 can catch errors when using it. - TRIO115: Replace
trio.sleep(0)with the more suggestivetrio.lowlevel.checkpoint(). - TRIO116:
trio.sleep()with >24 hour interval should usually betrio.sleep_forever(). - TRIO117: Don't raise or catch
trio.[NonBase]MultiError, prefer[exceptiongroup.]BaseExceptionGroup. Even if Trio still raisesMultiErrorfor legacy code, it can be caught withBaseExceptionGroupso it's fully redundant. - TRIO118: 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
- TRIO200: User-configured error for blocking sync calls in async functions. Does nothing by default, see
trio200-blocking-callsfor how to configure it. - TRIO210: Sync HTTP call in async function, use
httpx.AsyncClient. - TRIO211: Likely sync HTTP call in async function, use
httpx.AsyncClient. Looks forurllib3method calls on pool objects, but only matching on the method signature and not the object. - TRIO212: Blocking sync HTTP call on httpx object, use httpx.AsyncClient.
- TRIO220: Sync process call in async function, use
await nursery.start(trio.run_process, ...). - TRIO221: Sync process call in async function, use
await trio.run_process(...). - TRIO222: Sync
os.*call in async function, wrap inawait trio.to_thread.run_sync(). - TRIO230: Sync IO call in async function, use
trio.open_file(...). - TRIO231: Sync IO call in async function, use
trio.wrap_file(...). - TRIO232: Blocking sync call on file object, wrap the file object in
trio.wrap_file()to get an async file object. - TRIO240: Avoid using
os.pathin async functions, prefer usingtrio.Pathobjects.
Warnings disabled by default
- TRIO900: Async generator without
@asynccontextmanagernot allowed. - TRIO910: exit or
returnfrom async function with no guaranteed checkpoint or exception since function definition. - TRIO911: exit, yield or return from async iterable with no guaranteed checkpoint since possible function entry (yield or function definition)
Checkpoints are
await,async for, andasync with(on one of enter/exit).
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.
no-checkpoint-warning-decorators
Specify a list of decorators to disable checkpointing checks for, turning off TRIO910 and TRIO911 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,
trio200-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:
trio200-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)
Changelog
23.2.3
- Fix get_matching_call when passed a single string as base. Resolves possibly several false alarms, TRIO210 among them.
23.2.2
- Rename TRIO107 to TRIO910, and TRIO108 to TRIO911, and making them optional by default.
- Allow
@pytest.fixture()-decorated async generators, since they're morally context managers - Add support for checking code written against
anyio - Add TRIO118: Don't assign the value of
anyio.get_cancelled_exc_class()to a variable, since that breaks linter checks and multi-backend programs.
23.2.1
- TRIO103 and TRIO104 no longer triggers when
trio.Cancelledhas been handled in previous except handlers. - Add TRIO117: Reference to deprecated
trio.[NonBase]MultiError; use[Base]ExceptionGroupinstead. - Add TRIO232: blocking sync call on file object.
- Add TRIO212: blocking sync call on
httpx.Clientobject. - Add TRIO222: blocking sync call to
os.wait* - TRIO221 now also looks for
os.posix_spawn[p]
23.1.4
- TRIO114 avoids a false alarm on posonly args named "task_status"
- TRIO116 will now match on any attribute parameter named
.inf, not justmath.inf. - TRIO900 now only checks
@asynccontextmanager, not other decorators passed with --no-checkpoint-warning-decorators.
23.1.3
- Add TRIO240: usage of
os.pathin async function. - Add TRIO900: ban async generators not decorated with known safe decorator
23.1.2
- Add TRIO230, TRIO231 - sync IO calls in async function
23.1.1
- Add TRIO210, TRIO211 - blocking sync call in async function, using network packages (requests, httpx, urllib3)
- Add TRIO220, TRIO221 - blocking sync call in async function, using subprocess or os.
22.12.5
- The
--startable-in-context-managerand--trio200-blocking-callsoptions now handle spaces and newlines. - Now compatible with flake8-noqa's NQA102 and NQA103 checks.
22.12.4
- TRIO200 no longer warns on directly awaited calls
22.12.3
- Worked around configuration-parsing bug for TRIO200 warning (more to come)
22.12.2
- Add TRIO200: User-configured blocking sync call in async function
22.12.1
- TRIO114 will now trigger on the unqualified name, will now only check the first parameter directly, and parameters to function calls inside that.
- TRIO113 now only supports names that are valid identifiers, rather than fnmatch patterns.
- Add TRIO115: Use
trio.lowlevel.checkpoint()instead oftrio.sleep(0).
22.11.5
- Add TRIO116:
trio.sleep()with >24 hour interval should usually betrio.sleep_forever().
22.11.4
- Add TRIO114 Startable function not in
--startable-in-context-managerparameter list.
22.11.3
- Add TRIO113, prefer
await nursery.start(...)tonursery.start_soon()for compatible functions when opening a context manager
22.11.2
- TRIO105 now also checks that you
awaitednursery.start().
22.11.1
- TRIO102 is no longer skipped in (async) context managers, since it's not a missing-checkpoint warning.
22.9.2
- Fix a crash on nontrivial decorator expressions (calls, PEP-614) and document behavior.
22.9.1
- Add
--no-checkpoint-warning-decoratorsoption, to disable missing-checkpoint warnings for certain decorated functions.
22.8.8
- Fix false alarm on TRIO107 with checkpointing
tryand emptyfinally - Fix false alarm on TRIO107&108 with infinite loops
22.8.7
- TRIO107+108 now ignores
asynccontextmanagers, since both__aenter__and__aexit__should checkpoint.async withis also treated as checkpointing on both enter and exit. - TRIO107 now completely ignores any function whose body consists solely of ellipsis, pass, or string constants.
- TRIO103, 107 and 108 now inspects
whileconditions andforiterables to avoid false alarms on a couple cases where the loop body is guaranteed to run at least once.
22.8.6
- TRIO103 now correctly handles raises in loops, i.e.
raisein else is guaranteed to run unless there's abreakin the body.
22.8.5
- Add TRIO111: 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. - Add TRIO112: this single-task nursery could be replaced by awaiting the function call directly.
22.8.4
- Fix TRIO108 raising errors on yields in some sync code.
- TRIO109 now skips all decorated functions to avoid false alarms
22.8.3
- TRIO108 now gives multiple error messages; one for each path lacking a guaranteed checkpoint
22.8.2
- Merged TRIO108 into TRIO107
- TRIO108 now handles checkpointing in async iterators
22.8.1
- Added TRIO109: Async definitions should not have a
timeoutparameter. Usetrio.[fail/move_on]_[at/after] - Added TRIO110:
while <condition>: await trio.sleep()should be replaced by atrio.Event.
22.7.6
- Extend TRIO102 to also check inside
except BaseExceptionandexcept trio.Cancelled - Extend TRIO104 to also check for
yield - Update error messages on TRIO102 and TRIO103
22.7.5
- Add TRIO103:
except BaseExceptionorexcept trio.Cancelledwith a code path that doesn't re-raise - Add TRIO104: "Cancelled and BaseException must be re-raised" if user tries to return or raise a different exception.
- Added TRIO107: Async functions must have at least one checkpoint on every code path, unless an exception is raised
- Added TRIO108: Early return from async function must have at least one checkpoint on every code path before it.
22.7.4
- Added TRIO105 check for not immediately
awaiting async trio functions. - Added TRIO106 check that trio is imported in a form that the plugin can easily parse.
22.7.3
- Added TRIO102 check for unsafe checkpoints inside
finally:blocks
22.7.2
- Avoid
TRIO100false-alarms on cancel scopes containingasync fororasync with.
22.7.1
- Initial release with TRIO100 and TRIO101
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flake8-trio-23.2.3.tar.gz.
File metadata
- Download URL: flake8-trio-23.2.3.tar.gz
- Upload date:
- Size: 62.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e16d8f09f3c41998cad3e798193c575c6d2c864cb662700e42ac9edf1ab86021
|
|
| MD5 |
46d9a308841b609d37da84c1cda82c90
|
|
| BLAKE2b-256 |
5274a84107365bf284f5abb6e864e27ddd64da3db785b09d2cdab18ffd003e67
|
File details
Details for the file flake8_trio-23.2.3-py3-none-any.whl.
File metadata
- Download URL: flake8_trio-23.2.3-py3-none-any.whl
- Upload date:
- Size: 34.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb451e966cda04cb3440d3ac31d39e06489a75d8d38ee00e7f56d45779be3c74
|
|
| MD5 |
9994d1b40984caa5e007dcf59ca395f0
|
|
| BLAKE2b-256 |
bf4fe9a17e94c5a4b0fd11eceab8645a55f4b7e2939be569493c724e880a597c
|