Repository: wemake-services/wemake-python-styleguide

Issue:
Possible use for `pass`
From:
WPS420 — Forbid some python keywords.

> pass keyword is just useless by design. There’s no use-case for it. Because it does literally nothing.

This is a snippet from a selector. In short, we need at the end a copy of render_data. We can get render_data out of doc, but sometimes we have only the data and no doc in sight.

`class RenderSettings(object):

    def __init__(
        self,
        doc: Optional[c4d.documents.BaseDocument] | None = None,
        render_data: Optional[RenderData] | None = None,
    ):
        match (doc, render_data):
            case (None, None):
                doc = c4d.documents.GetActiveDocument()
                render_data = doc.GetActiveRenderData()
            case (None, _):
                pass
            case (_, None):
                render_data = doc.GetActiveRenderData()
            case (_, _):
                raise ValueError("doc and render_data are mutually exclusive.")

        if render_data is None:
            raise RuntimeError("No render data found.")

        self.rd: RenderData = render_data.GetClone()`

It would seem, I literally want to just exit the match-case in a case where we have only render_data at the input.

Am I missing something?

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 678d78e8..c3a9baf7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -79,6 +79,7 @@ Semantic versioning in our case means:
 - Adds a new rule to find too many PEP695 type params
 - Allows any compares in `assert` statements for `WPS520`, #3112
 - Allows walrus operator (`:=`) in comprehesions #3121
+- Allows `pass` in `case` bodies
 - Does not count `self`, `cls`, and `mcs` as arguments
   for `WPS211` complexity check anymore, #2394
 - `WPS303`: Underscore (`_`) now only allowed with 3 digits after it, #3120
diff --git a/wemake_python_styleguide/visitors/ast/keywords.py b/wemake_python_styleguide/visitors/ast/keywords.py
index d84b35b9..338ebe4b 100644
--- a/wemake_python_styleguide/visitors/ast/keywords.py
+++ b/wemake_python_styleguide/visitors/ast/keywords.py
@@ -171,13 +171,19 @@ class WrongKeywordVisitor(BaseNodeVisitor):
         self.generic_visit(node)
 
     def _check_keyword(self, node: ast.AST) -> None:
-        if isinstance(node, self._forbidden_keywords):
-            if isinstance(node, ast.Delete):
-                message = 'del'
-            else:
-                message = node.__class__.__qualname__.lower()
+        if not isinstance(node, self._forbidden_keywords):
+            return
+        if isinstance(node, ast.Pass) and walk.get_closest_parent(
+            node, ast.match_case
+        ):
+            return  # We allow `pass` in `match: case:`
+
+        if isinstance(node, ast.Delete):
+            message = 'del'
+        else:
+            message = node.__class__.__qualname__.lower()
 
-            self.add_violation(WrongKeywordViolation(node, text=message))
+        self.add_violation(WrongKeywordViolation(node, text=message))
 
 
 @final


Test patch:
diff --git a/tests/test_visitors/test_ast/test_keywords/test_pass.py b/tests/test_visitors/test_ast/test_keywords/test_pass.py
index c35e76ed..55cbeeb1 100644
--- a/tests/test_visitors/test_ast/test_keywords/test_pass.py
+++ b/tests/test_visitors/test_ast/test_keywords/test_pass.py
@@ -36,6 +36,14 @@ except Exception:
     pass
 """
 
+pass_in_pattern_matching = """
+match some_value:
+    case None:
+        pass
+    case _:
+        raise ValueError
+"""
+
 
 @pytest.mark.parametrize(
     'code',
@@ -62,3 +70,24 @@ def test_pass_keyword(
 
     assert_errors(visitor, [WrongKeywordViolation])
     assert_error_text(visitor, 'pass')
+
+
+@pytest.mark.parametrize(
+    'code',
+    [
+        pass_in_pattern_matching,
+    ],
+)
+def test_pass_keyword_in_pattern_matching(
+    assert_errors,
+    parse_ast_tree,
+    code,
+    default_options,
+):
+    """Testing that `pass` keyword is allowed in PM."""
+    tree = parse_ast_tree(code)
+
+    visitor = WrongKeywordVisitor(default_options, tree=tree)
+    visitor.run()
+
+    assert_errors(visitor, [])