8000 fix crash. Make identifier_to_string less footgunny. (#323) · python-trio/flake8-async@14d9906 · GitHub
[go: up one dir, main page]

Skip to content

Commit 14d9906

Browse files
authored
fix crash. Make identifier_to_string less footgunny. (#323)
* fix crash. Make identifier_to_string less footgunny. * add changelog & bump version. Fix incorrect changelog placement.
1 parent 7a45176 commit 14d9906

File tree

7 files changed

+41
-24
lines changed

7 files changed

+41
-24
lines changed

docs/changelog.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,24 @@ Changelog
44

55
`CalVer, YY.month.patch <https://calver.org/>`_
66

7+
24.11.2
8+
=======
9+
- Fix crash in ``Visitor91x`` on ``async with a().b():``.
10+
711
24.11.1
812
=======
913
- :ref:`ASYNC100 <async100>` now ignores :func:`trio.open_nursery` and :func:`anyio.create_task_group`
1014
as cancellation sources, because they are :ref:`schedule points <schedule_points>` but not
1115
:ref:`cancellation points <cancel_points>`.
16+
- :ref:`ASYNC101 <async101>` and :ref:`ASYNC119 <async119>` are now silenced for decorators in :ref:`transform-async-generator-decorators`.
1217

1318
24.10.2
1419
=======
15-
- :ref:`ASYNC101 <async101>` and :ref:`ASYNC119 <async119>` are now silenced for decorators in :ref:`transform-async-generator-decorators`
1620
- :ref:`ASYNC102 <async102>` now also warns about ``await()`` inside ``__aexit__``.
1721

1822
24.10.1
1923
=======
20-
- Add :ref:`ASYNC123 <async123>` bad-exception-group-flattening
24+
- Add :ref:`ASYNC123 <async123>` bad-exception-group-flattening.
2125

2226
24.9.5
2327
======

flake8_async/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939

4040
# CalVer: YY.month.patch, e.g. first release of July 2022 == "22.7.1"
41-
__version__ = "24.11.1"
41+
__version__ = "24.11.2"
4242

4343

4444
# taken from https://github.com/Zac-HD/shed

flake8_async/visitors/helpers.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -337,15 +337,20 @@ def build_cst_matcher(attr: str) -> m.BaseExpression:
337337
return m.Attribute(value=build_cst_matcher(body), attr=m.Name(value=tail))
338338

339339

340-
def identifier_to_string(attr: cst.Name | cst.Attribute) -> str | None:
341-
if isinstance(attr, cst.Name):
342-
return attr.value
343-
if not isinstance(attr.value, (cst.Attribute, cst.Name)):
344-
return None
345-
lhs = identifier_to_string(attr.value)
346-
if lhs is None:
347-
return None
348-
return lhs + "." + attr.attr.value
340+
def identifier_to_string(node: cst.CSTNode) -> str | None:
341+
"""Convert a simple identifier to a string.
342+
343+
If the node is composed of anything but cst.Name + cst.Attribute it returns None.
344+
"""
345+
if isinstance(node, cst.Name):
346+
return node.value
347+
if (
348+
isinstance(node, cst.Attribute)
349+
and (lhs := identifier_to_string(node.value)) is not None
350+
):
351+
return lhs + "." + node.attr.value
352+
353+
return None
349354

350355

351356
def with_has_call(

flake8_async/visitors/visitor91x.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -501,17 +501,16 @@ def _checkpoint_with(self, node: cst.With):
501501
"""
502502
if getattr(node, "asynchronous", None):
503503
for item in node.items:
504-
if not isinstance(item.item, cst.Call) or not isinstance(
505-
item.item.func, (cst.Attribute, cst.Name)
504+
if not (
505+
isinstance(item.item, cst.Call)
506+
and identifier_to_string(item.item.func)
507+
in (
508+
"trio.open_nursery",
509+
"anyio.create_task_group",
510+
)
506511
):
507512
self.checkpoint()
508513
break
509-
510-
func = identifier_to_string(item.item.func)
511-
assert func is not None
512-
if func not in ("trio.open_nursery", "anyio.create_task_group"):
513-
self.checkpoint()
514-
break
515514
else:
516515
self.uncheckpointed_statements = set()
517516

flake8_async/visitors/visitors.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import ast
66
from typing import TYPE_CHECKING, Any, cast
77

8-
import libcst as cst
9-
108
from .flake8asyncvisitor import Flake8AsyncVisitor, Flake8AsyncVisitor_cst
119
from .helpers import (
1210
disabled_by_default,
@@ -20,6 +18,8 @@
2018
if TYPE_CHECKING:
2119
from collections.abc import Mapping
2220

21+
import libcst as cst
22+
2323
LIBRARIES = ("trio", "anyio", "asyncio")
2424

2525

@@ -460,8 +460,7 @@ def visit_CompIf(self, node: cst.CSTNode):
460460

461461
def visit_Call(self, node: cst.Call):
462462
if (
463-
isinstance(node.func, (cst.Name, cst.Attribute))
464-
and identifier_to_string(node.func) == "asyncio.create_task"
463+
identifier_to_string(node.func) == "asyncio.create_task"
465464
and not self.safe_to_create_task
466465
):
467466
self.error(node)

tests/autofix_files/async100.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,8 @@ async def nursery_no_cancel_point():
141141
async def dont_crash_on_non_name_or_attr_call():
142142
async with contextlib.asynccontextmanager(agen_fn)():
143143
...
144+
145+
146+
async def another_weird_with_call():
147+
async with a().b():
148+
...

tests/eval_files/async100.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,8 @@ async def nursery_no_cancel_point():
141141
async def dont_crash_on_non_name_or_attr_call():
142142
async with contextlib.asynccontextmanager(agen_fn)():
143143
...
144+
145+
146+
async def another_weird_with_call():
147+
async with a().b():
148+
...

0 commit comments

Comments
 (0)
0