Skip to content

Commit 1996d57

Browse files
committed
Use match statement in checkers (1)
1 parent 4f98c18 commit 1996d57

File tree

6 files changed

+65
-57
lines changed

6 files changed

+65
-57
lines changed

pylint/checkers/match_statements_checker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ def visit_match(self, node: nodes.Match) -> None:
3737
"""
3838
for idx, case in enumerate(node.cases):
3939
match case.pattern:
40-
case nodes.MatchAs(pattern=None, name=nodes.AssignName()) if (
40+
case nodes.MatchAs(pattern=None, name=nodes.AssignName(name=n)) if (
4141
idx < len(node.cases) - 1
4242
):
4343
self.add_message(
4444
"bare-name-capture-pattern",
4545
node=case.pattern,
46-
args=case.pattern.name.name,
46+
args=n,
4747
confidence=HIGH,
4848
)
4949

pylint/extensions/_check_docs_utils.py

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -133,23 +133,24 @@ def possible_exc_types(node: nodes.NodeNG) -> set[nodes.ClassDef]:
133133
except astroid.InferenceError:
134134
pass
135135
else:
136-
target = _get_raise_target(node)
137-
if isinstance(target, nodes.ClassDef):
138-
exceptions = [target]
139-
elif isinstance(target, nodes.FunctionDef):
140-
for ret in target.nodes_of_class(nodes.Return):
141-
if ret.value is None:
142-
continue
143-
if ret.frame() != target:
144-
# return from inner function - ignore it
145-
continue
146-
147-
val = utils.safe_infer(ret.value)
148-
if val and utils.inherit_from_std_ex(val):
149-
if isinstance(val, nodes.ClassDef):
150-
exceptions.append(val)
151-
elif isinstance(val, astroid.Instance):
152-
exceptions.append(val.getattr("__class__")[0])
136+
match target := _get_raise_target(node):
137+
case nodes.ClassDef():
138+
exceptions = [target]
139+
case nodes.FunctionDef():
140+
for ret in target.nodes_of_class(nodes.Return):
141+
if ret.value is None:
142+
continue
143+
if ret.frame() != target:
144+
# return from inner function - ignore it
145+
continue
146+
147+
val = utils.safe_infer(ret.value)
148+
if val and utils.inherit_from_std_ex(val):
149+
match val:
150+
case nodes.ClassDef():
151+
exceptions.append(val)
152+
case astroid.Instance():
153+
exceptions.append(val.getattr("__class__")[0])
153154

154155
try:
155156
return {

pylint/extensions/code_style.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,13 @@ def _check_ignore_assignment_expr_suggestion(
309309
if isinstance(node.test, nodes.Compare):
310310
next_if_node: nodes.If | None = None
311311
next_sibling = node.next_sibling()
312-
if len(node.orelse) == 1 and isinstance(node.orelse[0], nodes.If):
313-
# elif block
314-
next_if_node = node.orelse[0]
315-
elif isinstance(next_sibling, nodes.If):
316-
# separate if block
317-
next_if_node = next_sibling
312+
match (node.orelse, next_sibling):
313+
case [[nodes.If() as next_if_node], _]:
314+
# elif block
315+
pass
316+
case [_, nodes.If() as next_if_node]:
317+
# separate if block
318+
pass
318319

319320
if ( # pylint: disable=too-many-boolean-expressions
320321
next_if_node is not None

pylint/extensions/for_any_all.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,13 @@ def _build_suggested_string(node: nodes.For, final_return_bool: bool) -> str:
147147
loop_iter = node.iter.as_string()
148148
test_node = next(node.body[0].get_children())
149149

150-
if isinstance(test_node, nodes.UnaryOp) and test_node.op == "not":
151-
# The condition is negated. Advance the node to the operand and modify the suggestion
152-
test_node = test_node.operand
153-
suggested_function = "all" if final_return_bool else "not all"
154-
else:
155-
suggested_function = "not any" if final_return_bool else "any"
150+
match test_node:
151+
case nodes.UnaryOp(op="not"):
152+
# The condition is negated. Advance the node to the operand and modify the suggestion
153+
test_node = test_node.operand
154+
suggested_function = "all" if final_return_bool else "not all"
155+
case _:
156+
suggested_function = "not any" if final_return_bool else "any"
156157

157158
test = test_node.as_string()
158159
return f"{suggested_function}({test} for {loop_var} in {loop_iter})"

pylint/extensions/private_import.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,15 @@ def _populate_type_annotations(
147147
if isinstance(usage_node, nodes.AssignName) and isinstance(
148148
usage_node.parent, (nodes.AnnAssign, nodes.Assign)
149149
):
150-
assign_parent = usage_node.parent
151-
if isinstance(assign_parent, nodes.AnnAssign):
152-
name_assignments.append(assign_parent)
153-
private_name = self._populate_type_annotations_annotation(
154-
usage_node.parent.annotation, all_used_type_annotations
155-
)
156-
elif isinstance(assign_parent, nodes.Assign):
157-
name_assignments.append(assign_parent)
150+
match assign_parent := usage_node.parent:
151+
case nodes.AnnAssign():
152+
name_assignments.append(assign_parent)
153+
private_name = self._populate_type_annotations_annotation(
154+
assign_parent.annotation,
155+
all_used_type_annotations,
156+
)
157+
case nodes.Assign():
158+
name_assignments.append(assign_parent)
158159

159160
if isinstance(usage_node, nodes.FunctionDef):
160161
self._populate_type_annotations_function(
@@ -194,24 +195,23 @@ def _populate_type_annotations_annotation(
194195
"""Handles the possibility of an annotation either being a Name, i.e. just type,
195196
or a Subscript e.g. `Optional[type]` or an Attribute, e.g. `pylint.lint.linter`.
196197
"""
197-
if isinstance(node, nodes.Name) and node.name not in all_used_type_annotations:
198-
all_used_type_annotations[node.name] = True
199-
return node.name # type: ignore[no-any-return]
200-
if isinstance(node, nodes.Subscript): # e.g. Optional[List[str]]
201-
# slice is the next nested type
202-
self._populate_type_annotations_annotation(
203-
node.slice, all_used_type_annotations
204-
)
205-
# value is the current type name: could be a Name or Attribute
206-
return self._populate_type_annotations_annotation(
207-
node.value, all_used_type_annotations
208-
)
209-
if isinstance(node, nodes.Attribute):
210-
# An attribute is a type like `pylint.lint.pylinter`. node.expr is the next level
211-
# up, could be another attribute
212-
return self._populate_type_annotations_annotation(
213-
node.expr, all_used_type_annotations
214-
)
198+
match node:
199+
case nodes.Name(name=n) if n not in all_used_type_annotations:
200+
all_used_type_annotations[n] = True
201+
return n # type: ignore[no-any-return]
202+
case nodes.Subscript(slice=s, value=v):
203+
# slice is the next nested type
204+
self._populate_type_annotations_annotation(s, all_used_type_annotations)
205+
# value is the current type name: could be a Name or Attribute
206+
return self._populate_type_annotations_annotation(
207+
v, all_used_type_annotations
208+
)
209+
case nodes.Attribute(expr=e):
210+
# An attribute is a type like `pylint.lint.pylinter`. node.expr is the next level
211+
# up, could be another attribute
212+
return self._populate_type_annotations_annotation(
213+
e, all_used_type_annotations
214+
)
215215
return None
216216

217217
@staticmethod

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ scripts_are_modules = true
207207
warn_unused_ignores = true
208208
show_error_codes = true
209209
enable_error_code = "ignore-without-code"
210+
disable_error_code = [
211+
# TODO: remove once match false-positives are fixed, probably in v1.18
212+
# https://github.com/python/mypy/pull/19708
213+
"has-type",
214+
]
210215
strict = true
211216
# TODO: Remove this once pytest has annotations
212217
disallow_untyped_decorators = false

0 commit comments

Comments
 (0)