Skip to content

Commit e2d764a

Browse files
committed
Add trio[300], async functions should not have a timeout parameter
1 parent b53e5fa commit e2d764a

File tree

4 files changed

+76
-0
lines changed

4 files changed

+76
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Changelog
22
*[CalVer, YY.month.patch](https://calver.org/)*
33

4+
## Future
5+
- Added TRIO300: Async definitions should not have a `timeout` parameter. Use `trio.[fail/move_on]_[at/after]`
6+
47
## 22.7.6
58
- Extend TRIO102 to also check inside `except BaseException` and `except trio.Cancelled`
69
- Extend TRIO104 to also check for `yield`

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ pip install flake8-trio
3131
- **TRIO107**: Async functions must have at least one checkpoint on every code path, unless an exception is raised.
3232
- **TRIO108**: Early return from async function must have at least one checkpoint on every code path before it, unless an exception is raised.
3333
Checkpoints are `await`, `async with` `async for`.
34+
- **TRIO300**: Async function definition with a `timeout` parameter - use `trio.[fail/move_on]_[after/at]` instead"

flake8_trio.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ def visit_FunctionDef(self, node: Union[ast.FunctionDef, ast.AsyncFunctionDef]):
157157
self._safe_decorator, self._yield_is_error = outer
158158

159159
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef):
160+
self.check_300(node.args)
160161
self.visit_FunctionDef(node)
161162

162163
def visit_Yield(self, node: ast.Yield):
@@ -187,6 +188,11 @@ def visit_Import(self, node: ast.Import):
187188
if name.name == "trio" and name.asname is not None:
188189
self.problems.append(make_error(TRIO106, node.lineno, node.col_offset))
189190

191+
def check_300(self, args: ast.arguments):
192+
for arg in (*args.posonlyargs, *args.args, *args.kwonlyargs):
193+
if arg.arg == "timeout":
194+
self.error(TRIO300, arg.lineno, arg.col_offset)
195+
190196

191197
def critical_except(node: ast.ExceptHandler) -> Optional[Tuple[int, int, str]]:
192198
def has_exception(node: Optional[ast.expr]) -> str:
@@ -629,3 +635,4 @@ def run(self) -> Generator[Tuple[int, int, str, Type[Any]], None, None]:
629635
TRIO106 = "TRIO106: trio must be imported with `import trio` for the linter to work"
630636
TRIO107 = "TRIO107: Async functions must have at least one checkpoint on every code path, unless an exception is raised"
631637
TRIO108 = "TRIO108: Early return from async function must have at least one checkpoint on every code path before it."
638+
TRIO300 = "TRIO300: Async function definition with a `timeout` parameter - use `trio.[fail/move_on]_[after/at]` instead"

tests/trio300.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
timeout = 10
2+
3+
4+
async def foo():
5+
return
6+
7+
8+
# args
9+
async def foo_1(timeout): # error: 16
10+
return
11+
12+
13+
# arg in args wih default & annotation
14+
async def foo_2(timeout: int = 3): # error: 16
15+
return
16+
17+
18+
# vararg
19+
async def foo_3(*timeout): # ??
20+
return
21+
22+
23+
# kwarg
24+
async def foo_4(**timeout): # ??
25+
return
26+
27+
28+
# correct line/col
29+
async def foo_5(
30+
bar,
31+
timeouts,
32+
my_timeout,
33+
timeout_,
34+
timeout, # error: 4
35+
):
36+
return
37+
38+
39+
# posonlyargs
40+
async def foo_6(
41+
timeout, # error: 4
42+
/,
43+
bar,
44+
):
45+
return
46+
47+
48+
# kwonlyargs
49+
async def foo_7(
50+
*,
51+
timeout, # error: 4
52+
):
53+
return
54+
55+
56+
# kwonlyargs (and kw_defaults)
57+
async def foo_8(
58+
*,
59+
timeout=5, # error: 4
60+
):
61+
return
62+
63+
64+
async def foo_9(k=timeout):
65+
return

0 commit comments

Comments
 (0)