Repository: wemake-services/wemake-python-styleguide

Issue:
Feature: check `lambda` functions for the number of arguments
We already have the logic to check regular an `async` functions for the number of arguments.
https://github.com/wemake-services/wemake-python-styleguide/blob/master/wemake_python_styleguide/visitors/ast/complexity/function.py#L155

But we need to check `lambda` functions as well. Since one can create a `lambda` function that receives too many arguments. 

What needs to be done:
1. We need to implement a new handler for `Lambda` node in the visitor above
2. We need to unit test this behavior here: https://github.com/wemake-services/wemake-python-styleguide/blob/master/tests/test_checkers/test_high_complexity.py


Discussion:

Resolving patch:
diff --git a/wemake_python_styleguide/types.py b/wemake_python_styleguide/types.py
--- a/wemake_python_styleguide/types.py
+++ b/wemake_python_styleguide/types.py
@@ -36,6 +36,13 @@
 #: In cases we need to work with both function definitions:
 AnyFunctionDef = Union[ast.FunctionDef, ast.AsyncFunctionDef]
 
+#: In cases we need to work with all function definitions (including Lambda)
+AnyFunctionDefAndLambda = Union[
+    ast.FunctionDef,
+    ast.AsyncFunctionDef,
+    ast.Lambda,
+]
+
 #: Flake8 API format to return error messages:
 CheckResult = Tuple[int, int, str, type]
 
diff --git a/wemake_python_styleguide/visitors/ast/complexity/function.py b/wemake_python_styleguide/visitors/ast/complexity/function.py
--- a/wemake_python_styleguide/visitors/ast/complexity/function.py
+++ b/wemake_python_styleguide/visitors/ast/complexity/function.py
@@ -5,7 +5,10 @@
 from typing import DefaultDict, List
 
 from wemake_python_styleguide.logics.functions import is_method
-from wemake_python_styleguide.types import AnyFunctionDef
+from wemake_python_styleguide.types import (
+    AnyFunctionDef,
+    AnyFunctionDefAndLambda,
+)
 from wemake_python_styleguide.violations.complexity import (
     TooManyArgumentsViolation,
     TooManyElifsViolation,
@@ -17,13 +20,14 @@
 from wemake_python_styleguide.visitors.decorators import alias
 
 FunctionCounter = DefaultDict[AnyFunctionDef, int]
+FunctionCounterWithLambda = DefaultDict[AnyFunctionDefAndLambda, int]
 
 
 class _ComplexityCounter(object):
     """Helper class to encapsulate logic from the visitor."""
 
     def __init__(self) -> None:
-        self.arguments: FunctionCounter = defaultdict(int)
+        self.arguments: FunctionCounterWithLambda = defaultdict(int)
         self.elifs: FunctionCounter = defaultdict(int)
         self.returns: FunctionCounter = defaultdict(int)
         self.expressions: FunctionCounter = defaultdict(int)
@@ -67,7 +71,7 @@ def _check_sub_node(self, node: AnyFunctionDef, sub_node) -> None:
         elif isinstance(sub_node, ast.If):
             self._update_elifs(node, sub_node)
 
-    def check_arguments_count(self, node: AnyFunctionDef) -> None:
+    def check_arguments_count(self, node: AnyFunctionDefAndLambda) -> None:
         """Checks the number of the arguments in a function."""
         counter = 0
         has_extra_arg = 0
@@ -167,3 +171,14 @@ def visit_any_function(self, node: AnyFunctionDef) -> None:
         self._counter.check_arguments_count(node)
         self._counter.check_function_complexity(node)
         self.generic_visit(node)
+
+    def visit_Lambda(self, node: ast.Lambda) -> None:
+        """
+        Checks lambda function's internal complexity.
+
+        Raises:
+            TooManyArgumentsViolation
+
+        """
+        self._counter.check_arguments_count(node)
+        self.generic_visit(node)


Test patch:
diff --git a/tests/fixtures/config/wrong_arguments_lambda.py b/tests/fixtures/config/wrong_arguments_lambda.py
new file mode 100644
--- /dev/null
+++ b/tests/fixtures/config/wrong_arguments_lambda.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+
+"""
+This file contains lambda functions with too many arguments.
+"""
+
+
+x = lambda one, *two, three=3, four=4, **five: one
+
+y = lambda one, two, *three, four=4, five=5, **six: one
+
+
+def method_with_internal_lambda_function():
+    y = lambda one, two, *three, four=4, five=5, **six: one
+
+
+class ClassWithWrongMethodArgs:
+    def class_method_with_internal_lambda_function(self):
+        y = lambda one, two, *three, four=4, five=5, **six: one
+
+    def error_method_with_internal_lambda_function(self, one, two, *three, four=4, five=5, **six):
+        y = lambda one, two, *three, four=4, five=5, **six: one
diff --git a/tests/test_checkers/test_high_complexity.py b/tests/test_checkers/test_high_complexity.py
--- a/tests/test_checkers/test_high_complexity.py
+++ b/tests/test_checkers/test_high_complexity.py
@@ -21,3 +21,23 @@ def test_too_many_arguments_in_fixture(absolute_path):
     stdout, _ = process.communicate()
 
     assert stdout.count(b'Z211') == 4
+
+
+def test_too_many_arguments_in_lambda_fixture(absolute_path):
+    """
+    End-to-End test to check arguments count in lambda.
+
+    It is required due to how 'function_type' parameter
+    works inside 'flake8'.
+
+    Otherwise it is not set, unit tests can not cover `is_method` correctly.
+    """
+    filename = absolute_path('fixtures', 'config', 'wrong_arguments_lambda.py')
+    process = subprocess.Popen(
+        ['flake8', '--select', 'Z', filename],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+    )
+    stdout, _ = process.communicate()
+
+    assert stdout.count(b'Z211') == 5