@@ -1423,28 +1423,55 @@ def ambiguous_identifier(logical_line, tokens):
1423
1423
1424
1424
Variables can be bound in several other contexts, including class
1425
1425
and function definitions, 'global' and 'nonlocal' statements,
1426
- exception handlers, and 'with' statements.
1426
+ exception handlers, and 'with' and 'for' statements.
1427
+ In addition, we have a special handling for function parameters.
1427
1428
1428
1429
Okay: except AttributeError as o:
1429
1430
Okay: with lock as L:
1431
+ Okay: foo(l=12)
1432
+ Okay: for a in foo(l=12):
1430
1433
E741: except AttributeError as O:
1431
1434
E741: with lock as l:
1432
1435
E741: global I
1433
1436
E741: nonlocal l
1437
+ E741: def foo(l):
1438
+ E741: def foo(l=12):
1439
+ E741: l = foo(l=12)
1440
+ E741: for l in range(10):
1434
1441
E742: class I(object):
1435
1442
E743: def l(x):
1436
1443
"""
1444
+ is_func_def = False # Set to true if 'def' is found
1445
+ parameter_parentheses_level = 0
1437
1446
idents_to_avoid = ('l' , 'O' , 'I' )
1438
1447
prev_type , prev_text , prev_start , prev_end , __ = tokens [0 ]
1439
1448
for token_type , text , start , end , line in tokens [1 :]:
1440
1449
ident = pos = None
1450
+ # find function definitions
1451
+ if prev_text == 'def' :
1452
+ is_func_def = True
1453
+ # update parameter parentheses level
1454
+ if parameter_parentheses_level == 0 and prev_type == tokenize .NAME and \
1455
+ token_type == tokenize .OP and text == '(' :
1456
+ parameter_parentheses_level = 1
1457
+ elif parameter_parentheses_level > 0 and token_type == tokenize .OP :
1458
+ if text == '(' :
1459
+ parameter_parentheses_level += 1
1460
+ elif text == ')' :
1461
+ parameter_parentheses_level -= 1
1441
1462
# identifiers on the lhs of an assignment operator
1442
- if token_type == tokenize .OP and '=' in text :
1463
+ if token_type == tokenize .OP and '=' in text and \
1464
+ parameter_parentheses_level == 0 :
1443
1465
if prev_text in idents_to_avoid :
1444
1466
ident = prev_text
1445
1467
pos = prev_start
1446
- # identifiers bound to values with 'as', 'global', or 'nonlocal'
1447
- if prev_text in ('as' , 'global' , 'nonlocal' ):
1468
+ # identifiers bound to values with 'as', 'for', 'global', or 'nonlocal'
1469
+ if prev_text in ('as' , 'for' , 'global' , 'nonlocal' ):
1470
+ if text in idents_to_avoid :
1471
+ ident = text
1472
+ pos = start
1473
+ # function parameter definitions
1474
+ if is_func_def :
1448
1475
if text in idents_to_avoid :
1449
1476
ident = text
1450
1477
pos = start
@@ -1456,6 +1483,7 @@ def ambiguous_identifier(logical_line, tokens):
1456
1483
yield start , "E743 ambiguous function definition '%s'" % text
1457
1484
if ident :
1458
1485
yield pos , "E741 ambiguous variable name '%s'" % ident
1486
+ prev_type = token_type
1459
1487
prev_text = text
1460
1488
prev_start = start
1461
1489
0 commit comments