Repository: wemake-services/wemake-python-styleguide (Python)

Issue:
Allow `super()` as overused expression
We need to add a new predicate to allow `super()` calls here: https://github.com/wemake-services/wemake-python-styleguide/blob/39a3caeb9883c3112d878a88038e8b7331389265/wemake_python_styleguide/visitors/ast/complexity/overuses.py#L114

It is obviously allowed.

Then we need to add a unit test here: https://github.com/wemake-services/wemake-python-styleguide/blob/ed1afeb3366525f0b3f1adc346a189a3c0f3b923/tests/test_visitors/test_ast/test_complexity/test_overuses/test_overused_expressions.py

That's it. It is beginner friendly.


Discussion:
Can I take this one? Hacktoberfest is nearing its end and I'm one PR short.
@hhsdev sure! Thanks for your help! 



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index da344a9e4..12acaf3ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ We used to have incremental versioning before `0.1.0`.
 - Forbid incorrectly swapped variables
 - Forbids to use `+=` with list arguments
 - Forbids to use redundant subscripts (e.g., `[0:7]` or `[3:None]`)
+- Allow `super()` as a valid overused expression
 
 ### Bugfixes
 
diff --git a/wemake_python_styleguide/visitors/ast/complexity/overuses.py b/wemake_python_styleguide/visitors/ast/complexity/overuses.py
index f8fdc5bf4..981d3c6aa 100644
--- a/wemake_python_styleguide/visitors/ast/complexity/overuses.py
+++ b/wemake_python_styleguide/visitors/ast/complexity/overuses.py
@@ -117,6 +117,7 @@ def _add_expression(self, node: ast.AST) -> None:
             # DSL to be created: like django-orm, attrs, and dataclasses.
             # And these DSLs are built using attributes and calls.
             _is_class_context,
+            _is_super_call,
         ]
         if any(ignore(node) for ignore in ignore_predicates):
             return
@@ -186,3 +187,9 @@ def _post_visit(self) -> None:
 
 def _is_class_context(node: ast.AST) -> bool:
     return isinstance(nodes.get_context(node), ast.ClassDef)
+
+
+def _is_super_call(node: ast.AST) -> bool:
+    if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
+        return node.func.id == 'super'
+    return False


Test patch:
diff --git a/tests/test_visitors/test_ast/test_complexity/test_overuses/test_overused_expressions.py b/tests/test_visitors/test_ast/test_complexity/test_overuses/test_overused_expressions.py
index ed8e8e8c1..81b5ea944 100644
--- a/tests/test_visitors/test_ast/test_complexity/test_overuses/test_overused_expressions.py
+++ b/tests/test_visitors/test_ast/test_complexity/test_overuses/test_overused_expressions.py
@@ -74,7 +74,7 @@ def method(self, arg: List[int]) -> type.Any:
 
 # Expressions:
 
-expressions = (
+violating_expressions = (
     # Nodes:
     'assert 1',
     'a and b',
@@ -98,6 +98,10 @@ def method(self, arg: List[int]) -> type.Any:
     'x: types.List[Set[int]] = call()',  # call is raising
 )
 
+ignored_expressions = (
+    'super()',
+)
+
 
 @pytest.mark.parametrize('code', [
     function_context1,
@@ -108,7 +112,7 @@ def method(self, arg: List[int]) -> type.Any:
     method_context2,
     method_context3,
 ])
-@pytest.mark.parametrize('expression', expressions)
+@pytest.mark.parametrize('expression', violating_expressions)
 def test_func_expression_overuse(
     assert_errors,
     parse_ast_tree,
@@ -130,7 +134,7 @@ def test_func_expression_overuse(
 @pytest.mark.parametrize('code', [
     module_context,
 ])
-@pytest.mark.parametrize('expression', expressions)
+@pytest.mark.parametrize('expression', violating_expressions)
 def test_module_expression_overuse(
     assert_errors,
     parse_ast_tree,
@@ -151,7 +155,7 @@ def test_module_expression_overuse(
 @pytest.mark.parametrize('code', [
     class_context,
 ])
-@pytest.mark.parametrize('expression', expressions)
+@pytest.mark.parametrize('expression', violating_expressions)
 def test_class_expression_use(
     assert_errors,
     parse_ast_tree,
@@ -170,3 +174,32 @@ def test_class_expression_use(
     visitor.run()
 
     assert_errors(visitor, [])
+
+
+@pytest.mark.parametrize('code', [
+    function_context1,
+    function_context2,
+    function_context3,
+    function_context4,
+    method_context1,
+    method_context2,
+    method_context3,
+    module_context,
+])
+@pytest.mark.parametrize('expression', ignored_expressions)
+def test_ignored_expressions(
+    assert_errors,
+    parse_ast_tree,
+    options,
+    expression,
+    code,
+    mode,
+):
+    """Ensures that ignored expressions does not raise violations."""
+    tree = parse_ast_tree(mode(code.format(expression, expression)))
+
+    option_values = options(max_function_expressions=1)
+    visitor = ExpressionOveruseVisitor(option_values, tree=tree)
+    visitor.run()
+
+    assert_errors(visitor, [])