Skip to content

Commit bffc30c

Browse files
committed
doc updates. don't trigger on open_nursery in 102 (it didn't work anyway). async112 error message now specifies if its nursery or taskgroup.
1 parent 315cd5f commit bffc30c

File tree

5 files changed

+24
-19
lines changed

5 files changed

+24
-19
lines changed

docs/rules.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ ASYNC112 : useless-nursery
5555

5656
_`ASYNC113` : start-soon-in-aenter
5757
Using :meth:`~trio.Nursery.start_soon`/:meth:`~anyio.abc.TaskGroup.start_soon` in ``__aenter__`` doesn't wait for the task to begin.
58+
This will only warn about built-in functions and those listed in _`ASYNC114`.
59+
If you're starting a function that does not define `task_status`, then neither will trigger.
5860
Consider replacing with :meth:`~trio.Nursery.start`/:meth:`~anyio.abc.TaskGroup.start`.
5961

6062
_`ASYNC114` : startable-not-in-config

docs/usage.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,9 @@ Example
265265
``startable-in-context-manager``
266266
--------------------------------
267267

268-
Comma-separated list of methods which should be used with :meth:`trio.Nursery.start`/:meth:`anyio.abc.TaskGroup.start` when opening a context manager,
269-
in addition to the default :func:`trio.run_process`, :func:`trio.serve_tcp`, :func:`trio.serve_ssl_over_tcp`, and :func:`trio.serve_listeners`.
268+
Comma-separated list of methods which should be used with :meth:`trio.Nursery.start`/:meth:`anyio.abc.TaskGroup.start` when opening a context manager.
269+
This includes startable functions in the trio and anyio standard library by default, namely :func:`trio.run_process`, :func:`trio.serve_tcp`, :func:`trio.serve_ssl_over_tcp`, :func:`trio.serve_listeners`, :func:`trio.serve`, :func:`anyio.run_process`, :func:`anyio.serve_tcp`, :func:`anyio.serve_ssl_over_tcp`, :func:`anyio.serve_listeners`, and :func:`anyio.serve`.
270+
270271
Names must be valid identifiers as per :meth:`str.isidentifier`.
271272
Used by :ref:`ASYNC113 <async113>`, and :ref:`ASYNC114 <async114>` will warn when encountering methods not in the list.
272273

flake8_async/visitors/visitor102.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,7 @@ def visit_With(self, node: ast.With | ast.AsyncWith):
8787

8888
# Check for a `with trio.<scope_creator>`
8989
for item in node.items:
90-
call = get_matching_call(
91-
item.context_expr, "open_nursery", *cancel_scope_names
92-
)
90+
call = get_matching_call(item.context_expr, *cancel_scope_names)
9391
if call is None:
9492
continue
9593

flake8_async/visitors/visitors.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def visit_While(self, node: ast.While):
9595
class Visitor112(Flake8AsyncVisitor):
9696
error_codes: Mapping[str, str] = {
9797
"ASYNC112": (
98-
"Redundant nursery {}, consider replacing with directly awaiting "
98+
"Redundant {1} {0}, consider replacing with directly awaiting "
9999
"the function call."
100100
),
101101
}
@@ -113,19 +113,21 @@ def visit_With(self, node: ast.With | ast.AsyncWith):
113113
continue
114114
var_name = item.optional_vars.id
115115

116-
# check for trio.open_nursery and anyio.create_task_group
117-
nursery = get_matching_call(
118-
item.context_expr, "open_nursery", base="trio"
119-
) or get_matching_call(item.context_expr, "create_task_group", base="anyio")
120116
start_methods: tuple[str, ...] = ("start", "start_soon")
121-
if nursery is None:
122-
# check for asyncio.TaskGroup
123-
nursery = get_matching_call(
124-
item.context_expr, "TaskGroup", base="asyncio"
125-
)
126-
if nursery is None:
127-
continue
117+
# check for trio.open_nursery and anyio.create_task_group
118+
if get_matching_call(item.context_expr, "open_nursery", base="trio"):
119+
nursery_type = "nursery"
120+
121+
elif get_matching_call(
122+
item.context_expr, "create_task_group", base="anyio"
123+
):
124+
nursery_type = "taskgroup"
125+
# check for asyncio.TaskGroup
126+
elif get_matching_call(item.context_expr, "TaskGroup", base="asyncio"):
127+
nursery_type = "taskgroup"
128128
start_methods = ("create_task",)
129+
else:
130+
continue
129131

130132
body_call = node.body[0].value
131133
if isinstance(body_call, ast.Await):
@@ -142,7 +144,7 @@ def visit_With(self, node: ast.With | ast.AsyncWith):
142144
for n in self.walk(*body_call.args, *body_call.keywords)
143145
)
144146
):
145-
self.error(item.context_expr, var_name)
147+
self.error(item.context_expr, var_name, nursery_type)
146148

147149
visit_AsyncWith = visit_With
148150

tests/eval_files/async102.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ async def foo():
111111
myvar = True
112112
with trio.open_nursery(10) as s:
113113
s.shield = myvar
114-
await foo() # safe in theory, error: 12, Statement("try/finally", lineno-6)
114+
# this is not safe in theory - because `trio.open_nursery` is an async cm,
115+
# so it's not possible to open a nursery at all.
116+
await foo() # error: 12, Statement("try/finally", lineno-8)
115117
try:
116118
pass
117119
finally:

0 commit comments

Comments
 (0)