Skip to content

Commit 3474adf

Browse files
committed
Add during_type_checking to __init__ and set it during construction.
1 parent b938b2b commit 3474adf

File tree

2 files changed

+70
-47
lines changed

2 files changed

+70
-47
lines changed

pyflakes/checker.py

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,12 @@ class Binding(object):
310310
the node that this binding was last used.
311311
"""
312312

313-
def __init__(self, name, source):
313+
def __init__(self, name, source, during_type_checking):
314314
self.name = name
315315
self.source = source
316316
self.used = False
317-
self.during_type_checking = False
317+
assert isinstance(during_type_checking, bool)
318+
self.during_type_checking = during_type_checking
318319

319320
def __str__(self):
320321
return self.name
@@ -339,7 +340,7 @@ class Builtin(Definition):
339340
"""A definition created for all Python builtins."""
340341

341342
def __init__(self, name):
342-
super(Builtin, self).__init__(name, None)
343+
super(Builtin, self).__init__(name, None, during_type_checking=False)
343344

344345
def __repr__(self):
345346
return '<%s object %r at 0x%x>' % (self.__class__.__name__,
@@ -381,10 +382,11 @@ class Importation(Definition):
381382
@type fullName: C{str}
382383
"""
383384

384-
def __init__(self, name, source, full_name=None):
385+
def __init__(self, name, source, during_type_checking, full_name=None):
385386
self.fullName = full_name or name
386387
self.redefined = []
387-
super(Importation, self).__init__(name, source)
388+
super(Importation, self).__init__(name, source,
389+
during_type_checking=during_type_checking)
388390

389391
def redefines(self, other):
390392
if isinstance(other, SubmoduleImportation):
@@ -429,11 +431,12 @@ class SubmoduleImportation(Importation):
429431
name is also the same, to avoid false positives.
430432
"""
431433

432-
def __init__(self, name, source):
434+
def __init__(self, name, source, during_type_checking):
433435
# A dot should only appear in the name when it is a submodule import
434436
assert '.' in name and (not source or isinstance(source, ast.Import))
435437
package_name = name.split('.')[0]
436-
super(SubmoduleImportation, self).__init__(package_name, source)
438+
super(SubmoduleImportation, self).__init__(
439+
package_name, source, during_type_checking=during_type_checking)
437440
self.fullName = name
438441

439442
def redefines(self, other):
@@ -451,7 +454,7 @@ def source_statement(self):
451454

452455
class ImportationFrom(Importation):
453456

454-
def __init__(self, name, source, module, real_name=None):
457+
def __init__(self, name, source, module, during_type_checking, real_name=None):
455458
self.module = module
456459
self.real_name = real_name or name
457460

@@ -460,7 +463,8 @@ def __init__(self, name, source, module, real_name=None):
460463
else:
461464
full_name = module + '.' + self.real_name
462465

463-
super(ImportationFrom, self).__init__(name, source, full_name)
466+
super(ImportationFrom, self).__init__(name, source, full_name=full_name,
467+
during_type_checking=during_type_checking)
464468

465469
def __str__(self):
466470
"""Return import full name with alias."""
@@ -482,8 +486,9 @@ def source_statement(self):
482486
class StarImportation(Importation):
483487
"""A binding created by a 'from x import *' statement."""
484488

485-
def __init__(self, name, source):
486-
super(StarImportation, self).__init__('*', source)
489+
def __init__(self, name, source, during_type_checking):
490+
super(StarImportation, self).__init__('*', source,
491+
during_type_checking=during_type_checking)
487492
# Each star importation needs a unique name, and
488493
# may not be the module name otherwise it will be deemed imported
489494
self.name = name + '.*'
@@ -509,14 +514,17 @@ class FutureImportation(ImportationFrom):
509514
"""
510515

511516
def __init__(self, name, source, scope):
512-
super(FutureImportation, self).__init__(name, source, '__future__')
517+
super(FutureImportation, self).__init__(name, source, '__future__',
518+
during_type_checking=False)
513519
self.used = (scope, source)
514520

515521

516522
class Argument(Binding):
517523
"""
518524
Represents binding a name as an argument.
519525
"""
526+
def __init__(self, name, source):
527+
super(Argument, self).__init__(name, source, during_type_checking=False)
520528

521529

522530
class Assignment(Binding):
@@ -552,7 +560,7 @@ class ExportBinding(Binding):
552560
C{__all__} will not have an unused import warning reported for them.
553561
"""
554562

555-
def __init__(self, name, source, scope):
563+
def __init__(self, name, source, scope, during_type_checking):
556564
if '__all__' in scope and isinstance(source, ast.AugAssign):
557565
self.names = list(scope['__all__'].names)
558566
else:
@@ -583,7 +591,7 @@ def _add_to_names(container):
583591
# If not list concatenation
584592
else:
585593
break
586-
super(ExportBinding, self).__init__(name, source)
594+
super(ExportBinding, self).__init__(name, source, during_type_checking)
587595

588596

589597
class Scope(dict):
@@ -1074,8 +1082,6 @@ def addBinding(self, node, value):
10741082
break
10751083
existing = scope.get(value.name)
10761084

1077-
value.during_type_checking = self._in_type_checking
1078-
10791085
if (existing and not isinstance(existing, Builtin) and
10801086
not self.differentForks(node, existing.source)):
10811087

@@ -1233,13 +1239,15 @@ def handleNodeStore(self, node):
12331239
if isinstance(parent_stmt, (FOR_TYPES, ast.comprehension)) or (
12341240
parent_stmt != node._pyflakes_parent and
12351241
not self.isLiteralTupleUnpacking(parent_stmt)):
1236-
binding = Binding(name, node)
1242+
binding = Binding(name, node, during_type_checking=self._in_type_checking)
12371243
elif name == '__all__' and isinstance(self.scope, ModuleScope):
1238-
binding = ExportBinding(name, node._pyflakes_parent, self.scope)
1244+
binding = ExportBinding(name, node._pyflakes_parent, self.scope,
1245+
during_type_checking=self._in_type_checking)
12391246
elif PY2 and isinstance(getattr(node, 'ctx', None), ast.Param):
1240-
binding = Argument(name, self.getScopeNode(node))
1247+
binding = Argument(name, self.getScopeNode(node),
1248+
during_type_checking=self._in_type_checking)
12411249
else:
1242-
binding = Assignment(name, node)
1250+
binding = Assignment(name, node, during_type_checking=self._in_type_checking)
12431251
self.addBinding(node, binding)
12441252

12451253
def handleNodeDelete(self, node):
@@ -1867,7 +1875,8 @@ def GLOBAL(self, node):
18671875

18681876
# One 'global' statement can bind multiple (comma-delimited) names.
18691877
for node_name in node.names:
1870-
node_value = Assignment(node_name, node)
1878+
node_value = Assignment(node_name, node,
1879+
during_type_checking=self._in_type_checking)
18711880

18721881
# Remove UndefinedName messages already reported for this name.
18731882
# TODO: if the global is not used in this scope, it does not
@@ -1969,7 +1978,8 @@ def FUNCTIONDEF(self, node):
19691978
for deco in node.decorator_list:
19701979
self.handleNode(deco, node)
19711980
self.LAMBDA(node)
1972-
self.addBinding(node, FunctionDefinition(node.name, node))
1981+
self.addBinding(node, FunctionDefinition(
1982+
node.name, node, during_type_checking=self._in_type_checking))
19731983
# doctest does not process doctest within a doctest,
19741984
# or in nested functions.
19751985
if (self.withDoctest and
@@ -2094,7 +2104,8 @@ def CLASSDEF(self, node):
20942104
for stmt in node.body:
20952105
self.handleNode(stmt, node)
20962106
self.popScope()
2097-
self.addBinding(node, ClassDefinition(node.name, node))
2107+
self.addBinding(node, ClassDefinition(
2108+
node.name, node, during_type_checking=self._in_type_checking))
20982109

20992110
def AUGASSIGN(self, node):
21002111
self.handleNodeLoad(node.target)
@@ -2129,10 +2140,12 @@ def TUPLE(self, node):
21292140
def IMPORT(self, node):
21302141
for alias in node.names:
21312142
if '.' in alias.name and not alias.asname:
2132-
importation = SubmoduleImportation(alias.name, node)
2143+
importation = SubmoduleImportation(
2144+
alias.name, node, during_type_checking=self._in_type_checking)
21332145
else:
21342146
name = alias.asname or alias.name
2135-
importation = Importation(name, node, alias.name)
2147+
importation = Importation(name, node, full_name=alias.name,
2148+
during_type_checking=self._in_type_checking)
21362149
self.addBinding(node, importation)
21372150

21382151
def IMPORTFROM(self, node):
@@ -2157,16 +2170,17 @@ def IMPORTFROM(self, node):
21572170
elif alias.name == '*':
21582171
# Only Python 2, local import * is a SyntaxWarning
21592172
if not PY2 and not isinstance(self.scope, ModuleScope):
2160-
self.report(messages.ImportStarNotPermitted,
2161-
node, module)
2173+
self.report(messages.ImportStarNotPermitted, node, module)
21622174
continue
21632175

21642176
self.scope.importStarred = True
21652177
self.report(messages.ImportStarUsed, node, module)
2166-
importation = StarImportation(module, node)
2178+
importation = StarImportation(
2179+
module, node, during_type_checking=self._in_type_checking)
21672180
else:
2168-
importation = ImportationFrom(name, node,
2169-
module, alias.name)
2181+
importation = ImportationFrom(
2182+
name, node, module, real_name=alias.name,
2183+
during_type_checking=self._in_type_checking)
21702184
self.addBinding(node, importation)
21712185

21722186
def TRY(self, node):

pyflakes/test/test_imports.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,78 +14,86 @@
1414
class TestImportationObject(TestCase):
1515

1616
def test_import_basic(self):
17-
binding = Importation('a', None, 'a')
17+
binding = Importation('a', None, during_type_checking=False, full_name='a')
1818
assert binding.source_statement == 'import a'
1919
assert str(binding) == 'a'
2020

2121
def test_import_as(self):
22-
binding = Importation('c', None, 'a')
22+
binding = Importation('c', None, during_type_checking=False, full_name='a')
2323
assert binding.source_statement == 'import a as c'
2424
assert str(binding) == 'a as c'
2525

2626
def test_import_submodule(self):
27-
binding = SubmoduleImportation('a.b', None)
27+
binding = SubmoduleImportation('a.b', None, during_type_checking=False)
2828
assert binding.source_statement == 'import a.b'
2929
assert str(binding) == 'a.b'
3030

3131
def test_import_submodule_as(self):
3232
# A submodule import with an as clause is not a SubmoduleImportation
33-
binding = Importation('c', None, 'a.b')
33+
binding = Importation('c', None, during_type_checking=False, full_name='a.b')
3434
assert binding.source_statement == 'import a.b as c'
3535
assert str(binding) == 'a.b as c'
3636

3737
def test_import_submodule_as_source_name(self):
38-
binding = Importation('a', None, 'a.b')
38+
binding = Importation('a', None, during_type_checking=False, full_name='a.b')
3939
assert binding.source_statement == 'import a.b as a'
4040
assert str(binding) == 'a.b as a'
4141

4242
def test_importfrom_relative(self):
43-
binding = ImportationFrom('a', None, '.', 'a')
43+
binding = ImportationFrom('a', None, '.',
44+
during_type_checking=False, real_name='a')
4445
assert binding.source_statement == 'from . import a'
4546
assert str(binding) == '.a'
4647

4748
def test_importfrom_relative_parent(self):
48-
binding = ImportationFrom('a', None, '..', 'a')
49+
binding = ImportationFrom('a', None, '..',
50+
during_type_checking=False, real_name='a')
4951
assert binding.source_statement == 'from .. import a'
5052
assert str(binding) == '..a'
5153

5254
def test_importfrom_relative_with_module(self):
53-
binding = ImportationFrom('b', None, '..a', 'b')
55+
binding = ImportationFrom('b', None, '..a',
56+
during_type_checking=False, real_name='b')
5457
assert binding.source_statement == 'from ..a import b'
5558
assert str(binding) == '..a.b'
5659

5760
def test_importfrom_relative_with_module_as(self):
58-
binding = ImportationFrom('c', None, '..a', 'b')
61+
binding = ImportationFrom('c', None, '..a',
62+
during_type_checking=False, real_name='b')
5963
assert binding.source_statement == 'from ..a import b as c'
6064
assert str(binding) == '..a.b as c'
6165

6266
def test_importfrom_member(self):
63-
binding = ImportationFrom('b', None, 'a', 'b')
67+
binding = ImportationFrom('b', None, 'a',
68+
during_type_checking=False, real_name='b')
6469
assert binding.source_statement == 'from a import b'
6570
assert str(binding) == 'a.b'
6671

6772
def test_importfrom_submodule_member(self):
68-
binding = ImportationFrom('c', None, 'a.b', 'c')
73+
binding = ImportationFrom('c', None, 'a.b',
74+
during_type_checking=False, real_name='c')
6975
assert binding.source_statement == 'from a.b import c'
7076
assert str(binding) == 'a.b.c'
7177

7278
def test_importfrom_member_as(self):
73-
binding = ImportationFrom('c', None, 'a', 'b')
79+
binding = ImportationFrom('c', None, 'a',
80+
during_type_checking=False, real_name='b')
7481
assert binding.source_statement == 'from a import b as c'
7582
assert str(binding) == 'a.b as c'
7683

7784
def test_importfrom_submodule_member_as(self):
78-
binding = ImportationFrom('d', None, 'a.b', 'c')
85+
binding = ImportationFrom('d', None, 'a.b',
86+
during_type_checking=False, real_name='c')
7987
assert binding.source_statement == 'from a.b import c as d'
8088
assert str(binding) == 'a.b.c as d'
8189

8290
def test_importfrom_star(self):
83-
binding = StarImportation('a.b', None)
91+
binding = StarImportation('a.b', None, during_type_checking=False)
8492
assert binding.source_statement == 'from a.b import *'
8593
assert str(binding) == 'a.b.*'
8694

8795
def test_importfrom_star_relative(self):
88-
binding = StarImportation('.b', None)
96+
binding = StarImportation('.b', None, during_type_checking=False)
8997
assert binding.source_statement == 'from .b import *'
9098
assert str(binding) == '.b.*'
9199

@@ -1040,16 +1048,17 @@ def test_ignoresTypingImports(self):
10401048
b()
10411049
''', m.UndefinedName)
10421050

1043-
def test_ignoresTypingClassDefinitino(self):
1051+
def test_ignoresTypingClassDefinition(self):
10441052
"""Ignores definitions within 'if TYPE_CHECKING' checking normal code."""
10451053
self.flakes('''
10461054
from typing import TYPE_CHECKING
10471055
if TYPE_CHECKING:
10481056
class T:
1049-
...
1057+
pass
10501058
t = T()
10511059
''', m.UndefinedName)
10521060

1061+
@skipIf(version_info < (3,), 'has type annotations')
10531062
def test_usesTypingImportsForAnnotations(self):
10541063
"""Uses imports within 'if TYPE_CHECKING' checking annotations."""
10551064
self.flakes('''

0 commit comments

Comments
 (0)