Skip to content

Commit bae0a63

Browse files
authored
Followup changes to fix ruff & pyright warnings (#203)
* Annotate error_codes with Mapping instead of dict to silence warnings about mutable classvar, Write __hash__ for Statement
1 parent 953a945 commit bae0a63

14 files changed

+86
-56
lines changed

flake8_trio/base.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,22 @@ class Statement(NamedTuple):
2929
lineno: int
3030
col_offset: int = -1
3131

32-
# pyright is unhappy about defining __eq__ but not __hash__ .. which it should
33-
# but it works :tm: and needs changing in a couple places to avoid it.
3432
def __eq__(self, other: object) -> bool:
3533
return (
3634
isinstance(other, Statement)
37-
and self[:2] == other[:2]
35+
and self.name == other.name
36+
and self.lineno == other.lineno
3837
and (
3938
self.col_offset == other.col_offset
4039
or -1 in (self.col_offset, other.col_offset)
4140
)
4241
)
4342

43+
# Objects that are equal needs to have the same hash, so we don't hash on
44+
# `col_offset` since it's a "wildcard" value
45+
def __hash__(self) -> int:
46+
return hash((self.name, self.lineno))
47+
4448

4549
class Error:
4650
def __init__(

flake8_trio/runner.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from .visitors.visitor_utility import NoqaHandler
2222

2323
if TYPE_CHECKING:
24-
from collections.abc import Iterable
24+
from collections.abc import Iterable, Mapping
2525

2626
from libcst import Module
2727

@@ -46,7 +46,7 @@ def __init__(self, options: Options):
4646
super().__init__()
4747
self.state = SharedState(options)
4848

49-
def selected(self, error_codes: dict[str, str]) -> bool:
49+
def selected(self, error_codes: Mapping[str, str]) -> bool:
5050
enabled_or_autofix = (
5151
self.state.options.enabled_codes | self.state.options.autofix_codes
5252
)

flake8_trio/visitors/flake8triovisitor.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
import ast
66
from abc import ABC
7-
from typing import TYPE_CHECKING, Any, ClassVar, Union
7+
from typing import TYPE_CHECKING, Any, Union
88

99
import libcst as cst
1010
from libcst.metadata import PositionProvider
1111

1212
from ..base import Error, Statement
1313

1414
if TYPE_CHECKING:
15-
from collections.abc import Iterable
15+
from collections.abc import Iterable, Mapping
1616

1717
from ..runner import SharedState
1818

@@ -23,7 +23,7 @@
2323

2424
class Flake8TrioVisitor(ast.NodeVisitor, ABC):
2525
# abstract attribute by not providing a value
26-
error_codes: ClassVar[dict[str, str]]
26+
error_codes: Mapping[str, str]
2727

2828
def __init__(self, shared_state: SharedState):
2929
super().__init__()
@@ -158,7 +158,7 @@ def add_library(self, name: str) -> None:
158158

159159
class Flake8TrioVisitor_cst(cst.CSTTransformer, ABC):
160160
# abstract attribute by not providing a value
161-
error_codes: dict[str, str]
161+
error_codes: Mapping[str, str]
162162
METADATA_DEPENDENCIES = (PositionProvider,)
163163

164164
def __init__(self, shared_state: SharedState):

flake8_trio/visitors/visitor100.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from __future__ import annotations
1010

11-
from typing import Any
11+
from typing import TYPE_CHECKING, Any
1212

1313
import libcst as cst
1414
import libcst.matchers as m
@@ -21,10 +21,13 @@
2121
with_has_call,
2222
)
2323

24+
if TYPE_CHECKING:
25+
from collections.abc import Mapping
26+
2427

2528
@error_class_cst
2629
class Visitor100_libcst(Flake8TrioVisitor_cst):
27-
error_codes = {
30+
error_codes: Mapping[str, str] = {
2831
"TRIO100": (
2932
"{0}.{1} context contains no checkpoints, remove the context or add"
3033
" `await {0}.lowlevel.checkpoint()`."

flake8_trio/visitors/visitor101.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
)
1818

1919
if TYPE_CHECKING:
20+
from collections.abc import Mapping
21+
2022
import libcst as cst
2123

2224

2325
@error_class_cst
2426
class Visitor101(Flake8TrioVisitor_cst):
25-
error_codes = {
27+
error_codes: Mapping[str, str] = {
2628
"TRIO101": (
2729
"`yield` inside a nursery or cancel scope is only safe when implementing "
2830
"a context manager - otherwise, it breaks exception handling."

flake8_trio/visitors/visitor102.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@
66
from __future__ import annotations
77

88
import ast
9-
from typing import Any
9+
from typing import TYPE_CHECKING, Any
1010

1111
from ..base import Statement
1212
from .flake8triovisitor import Flake8TrioVisitor
1313
from .helpers import cancel_scope_names, critical_except, error_class, get_matching_call
1414

15+
if TYPE_CHECKING:
16+
from collections.abc import Mapping
17+
1518

1619
@error_class
1720
class Visitor102(Flake8TrioVisitor):
18-
error_codes = {
21+
error_codes: Mapping[str, str] = {
1922
"TRIO102": (
2023
"await inside {0.name} on line {0.lineno} must have shielded cancel "
2124
"scope with a timeout."

flake8_trio/visitors/visitor103_104.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
from __future__ import annotations
1010

1111
import ast
12-
from typing import Any
12+
from typing import TYPE_CHECKING, Any
1313

1414
from .flake8triovisitor import Flake8TrioVisitor
1515
from .helpers import critical_except, error_class, iter_guaranteed_once
1616

17+
if TYPE_CHECKING:
18+
from collections.abc import Mapping
19+
1720
_trio103_common_msg = "{} block with a code path that doesn't re-raise the error."
1821
_suggestion = " Consider adding an `except {}: raise` before this exception handler."
1922
_suggestion_dict: dict[tuple[str, ...], str] = {
@@ -22,17 +25,19 @@
2225
}
2326
_suggestion_dict[("anyio", "trio")] = "[" + "|".join(_suggestion_dict.values()) + "]"
2427

28+
_error_codes = {
29+
"TRIO103": _trio103_common_msg,
30+
"TRIO104": "Cancelled (and therefore BaseException) must be re-raised.",
31+
}
32+
for poss_library in _suggestion_dict:
33+
_error_codes[f"TRIO103_{'_'.join(poss_library)}"] = (
34+
_trio103_common_msg + _suggestion.format(_suggestion_dict[poss_library])
35+
)
36+
2537

2638
@error_class
2739
class Visitor103_104(Flake8TrioVisitor):
28-
error_codes = {
29-
"TRIO103": _trio103_common_msg,
30-
"TRIO104": "Cancelled (and therefore BaseException) must be re-raised.",
31-
}
32-
for poss_library in _suggestion_dict:
33-
error_codes[f"TRIO103_{'_'.join(poss_library)}"] = (
34-
_trio103_common_msg + _suggestion.format(_suggestion_dict[poss_library])
35-
)
40+
error_codes: Mapping[str, str] = _error_codes
3641

3742
def __init__(self, *args: Any, **kwargs: Any):
3843
super().__init__(*args, **kwargs)

flake8_trio/visitors/visitor105.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33
from __future__ import annotations
44

55
import ast
6-
from typing import Any
6+
from typing import TYPE_CHECKING, Any
77

88
from .flake8triovisitor import Flake8TrioVisitor
99
from .helpers import error_class
1010

11+
if TYPE_CHECKING:
12+
from collections.abc import Mapping
13+
14+
1115
# used in 105
1216
trio_async_funcs = (
1317
"trio.aclose_forcefully",
@@ -39,7 +43,7 @@
3943

4044
@error_class
4145
class Visitor105(Flake8TrioVisitor):
42-
error_codes = {
46+
error_codes: Mapping[str, str] = {
4347
"TRIO105": "{0} async {1} must be immediately awaited.",
4448
}
4549

flake8_trio/visitors/visitor111.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@
33
from __future__ import annotations
44

55
import ast
6-
from typing import Any, NamedTuple
6+
from typing import TYPE_CHECKING, Any, NamedTuple
77

88
from .flake8triovisitor import Flake8TrioVisitor
99
from .helpers import error_class, get_matching_call
1010

11+
if TYPE_CHECKING:
12+
from collections.abc import Mapping
13+
1114

1215
@error_class
1316
class Visitor111(Flake8TrioVisitor):
14-
error_codes = {
17+
error_codes: Mapping[str, str] = {
1518
"TRIO111": (
1619
"variable {2} is usable within the context manager on line {0}, but that "
1720
"will close before nursery opened on line {1} - this is usually a bug. "

flake8_trio/visitors/visitor118.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@
88

99
import ast
1010
import re
11+
from typing import TYPE_CHECKING
1112

1213
from .flake8triovisitor import Flake8TrioVisitor
1314
from .helpers import error_class
1415

16+
if TYPE_CHECKING:
17+
from collections.abc import Mapping
18+
1519

1620
@error_class
1721
class Visitor118(Flake8TrioVisitor):
18-
error_codes = {
22+
error_codes: Mapping[str, str] = {
1923
"TRIO118": (
2024
"Don't assign the value of `anyio.get_cancelled_exc_class()` to a variable,"
2125
" since that breaks linter checks and multi-backend programs."

0 commit comments

Comments
 (0)