Skip to content

Commit

Permalink
Merge pull request #123 from cielavenir/raiseA002ForLambda
Browse files Browse the repository at this point in the history
Introduce A006 for lambda shadowing
  • Loading branch information
gforcada committed Apr 1, 2024
2 parents 5f02040 + 8702675 commit 116ce7b
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 2 deletions.
5 changes: 3 additions & 2 deletions CHANGES.rst
Expand Up @@ -3,10 +3,11 @@
Changelog
=========

2.3.1 (unreleased)
2.3.1 (2024-04-01)
------------------

- Nothing changed yet.
- Add rule for lambda argument shadowing (`A006`).
[cielavenir]


2.3.0 (2024-03-29)
Expand Down
3 changes: 3 additions & 0 deletions README.rst
Expand Up @@ -104,6 +104,9 @@ A004:
A005:
A module is shadowing a Python builtin module (e.g: `logging` or `socket`)

A006:
A lambda argument is shadowing a Python builtin.

License
-------
GPL 2.0
18 changes: 18 additions & 0 deletions flake8_builtins.py
Expand Up @@ -15,6 +15,7 @@ class BuiltinsChecker:
class_attribute_msg = 'A003 class attribute "{0}" is shadowing a Python builtin'
import_msg = 'A004 import statement "{0}" is shadowing a Python builtin'
module_name_msg = 'A005 the module is shadowing a Python builtin module "{0}"'
lambda_argument_msg = 'A006 lambda argument "{0}" is shadowing a Python builtin'

names = []
ignore_list = {
Expand Down Expand Up @@ -113,6 +114,9 @@ def run(self):
elif isinstance(statement, function_nodes):
value = self.check_function_definition(statement)

elif isinstance(statement, ast.Lambda):
value = self.check_lambda_definition(statement)

elif isinstance(statement, for_nodes):
value = self.check_for_loop(statement)

Expand Down Expand Up @@ -181,6 +185,20 @@ def check_function_definition(self, statement):
variable=arg.arg,
)

def check_lambda_definition(self, statement):
all_arguments = []
all_arguments.extend(statement.args.args)
all_arguments.extend(getattr(statement.args, 'kwonlyargs', []))
all_arguments.extend(getattr(statement.args, 'posonlyargs', []))

for arg in all_arguments:
if isinstance(arg, ast.arg) and arg.arg in self.names:
yield self.error(
arg,
message=self.lambda_argument_msg,
variable=arg.arg,
)

def check_for_loop(self, statement):
stack = [statement.target]
while stack:
Expand Down
14 changes: 14 additions & 0 deletions run_tests.py
Expand Up @@ -156,6 +156,11 @@ def bla(list):
check_code(source, 'A002')


def test_lambda_argument_message():
source = 'takefirst = lambda list: list[0]'
check_code(source, 'A006')


def test_keyword_argument_message():
source = """
def bla(dict=3):
Expand All @@ -182,6 +187,15 @@ def bla(list, /):
"""
check_code(source, 'A002')

@pytest.mark.skipif(
sys.version_info < (3, 8),
reason='This syntax is only valid in Python 3.8+',
)
def test_lambda_posonly_argument_message():
source = """
takefirst = lambda list, /: list[0]
"""
check_code(source, 'A006')

def test_no_error():
source = """def bla(first):\n b = 4"""
Expand Down

0 comments on commit 116ce7b

Please sign in to comment.