Skip to content

Commit 1d97dee

Browse files
committed
Add during_type_checking to __init__ and set it during construction.
1 parent 65b60bd commit 1d97dee

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
@@ -321,11 +321,12 @@ class Binding(object):
321321
the node that this binding was last used.
322322
"""
323323

324-
def __init__(self, name, source):
324+
def __init__(self, name, source, during_type_checking):
325325
self.name = name
326326
self.source = source
327327
self.used = False
328-
self.during_type_checking = False
328+
assert isinstance(during_type_checking, bool)
329+
self.during_type_checking = during_type_checking
329330

330331
def __str__(self):
331332
return self.name
@@ -350,7 +351,7 @@ class Builtin(Definition):
350351
"""A definition created for all Python builtins."""
351352

352353
def __init__(self, name):
353-
super(Builtin, self).__init__(name, None)
354+
super(Builtin, self).__init__(name, None, during_type_checking=False)
354355

355356
def __repr__(self):
356357
return '<%s object %r at 0x%x>' % (self.__class__.__name__,
@@ -392,10 +393,11 @@ class Importation(Definition):
392393
@type fullName: C{str}
393394
"""
394395

395-
def __init__(self, name, source, full_name=None):
396+
def __init__(self, name, source, during_type_checking, full_name=None):
396397
self.fullName = full_name or name
397398
self.redefined = []
398-
super(Importation, self).__init__(name, source)
399+
super(Importation, self).__init__(name, source,
400+
during_type_checking=during_type_checking)
399401

400402
def redefines(self, other):
401403
if isinstance(other, SubmoduleImportation):
@@ -440,11 +442,12 @@ class SubmoduleImportation(Importation):
440442
name is also the same, to avoid false positives.
441443
"""
442444

443-
def __init__(self, name, source):
445+
def __init__(self, name, source, during_type_checking):
444446
# A dot should only appear in the name when it is a submodule import
445447
assert '.' in name and (not source or isinstance(source, ast.Import))
446448
package_name = name.split('.')[0]
447-
super(SubmoduleImportation, self).__init__(package_name, source)
449+
super(SubmoduleImportation, self).__init__(
450+
package_name, source, during_type_checking=during_type_checking)
448451
self.fullName = name
449452

450453
def redefines(self, other):
@@ -462,7 +465,7 @@ def source_statement(self):
462465

463466
class ImportationFrom(Importation):
464467

465-
def __init__(self, name, source, module, real_name=None):
468+
def __init__(self, name, source, module, during_type_checking, real_name=None):
466469
self.module = module
467470
self.real_name = real_name or name
468471

@@ -471,7 +474,8 @@ def __init__(self, name, source, module, real_name=None):
471474
else:
472475
full_name = module + '.' + self.real_name
473476

474-
super(ImportationFrom, self).__init__(name, source, full_name)
477+
super(ImportationFrom, self).__init__(name, source, full_name=full_name,
478+
during_type_checking=during_type_checking)
475479

476480
def __str__(self):
477481
"""Return import full name with alias."""
@@ -493,8 +497,9 @@ def source_statement(self):
493497
class StarImportation(Importation):
494498
"""A binding created by a 'from x import *' statement."""
495499

496-
def __init__(self, name, source):
497-
super(StarImportation, self).__init__('*', source)
500+
def __init__(self, name, source, during_type_checking):
501+
super(StarImportation, self).__init__('*', source,
502+
during_type_checking=during_type_checking)
498503
# Each star importation needs a unique name, and
499504
# may not be the module name otherwise it will be deemed imported
500505
self.name = name + '.*'
@@ -520,14 +525,17 @@ class FutureImportation(ImportationFrom):
520525
"""
521526

522527
def __init__(self, name, source, scope):
523-
super(FutureImportation, self).__init__(name, source, '__future__')
528+
super(FutureImportation, self).__init__(name, source, '__future__',
529+
during_type_checking=False)
524530
self.used = (scope, source)
525531

526532

527533
class Argument(Binding):
528534
"""
529535
Represents binding a name as an argument.
530536
"""
537+
def __init__(self, name, source):
538+
super(Argument, self).__init__(name, source, during_type_checking=False)
531539

532540

533541
class Assignment(Binding):
@@ -577,7 +585,7 @@ class ExportBinding(Binding):
577585
C{__all__} will not have an unused import warning reported for them.
578586
"""
579587

580-
def __init__(self, name, source, scope):
588+
def __init__(self, name, source, scope, during_type_checking):
581589
if '__all__' in scope and isinstance(source, ast.AugAssign):
582590
self.names = list(scope['__all__'].names)
583591
else:
@@ -608,7 +616,7 @@ def _add_to_names(container):
608616
# If not list concatenation
609617
else:
610618
break
611-
super(ExportBinding, self).__init__(name, source)
619+
super(ExportBinding, self).__init__(name, source, during_type_checking)
612620

613621

614622
class Scope(dict):
@@ -1119,8 +1127,6 @@ def addBinding(self, node, value):
11191127
break
11201128
existing = scope.get(value.name)
11211129

1122-
value.during_type_checking = self._in_type_checking
1123-
11241130
if (existing and not isinstance(existing, Builtin) and
11251131
not self.differentForks(node, existing.source)):
11261132

@@ -1288,13 +1294,15 @@ def handleNodeStore(self, node):
12881294
elif isinstance(parent_stmt, (FOR_TYPES, ast.comprehension)) or (
12891295
parent_stmt != node._pyflakes_parent and
12901296
not self.isLiteralTupleUnpacking(parent_stmt)):
1291-
binding = Binding(name, node)
1297+
binding = Binding(name, node, during_type_checking=self._in_type_checking)
12921298
elif name == '__all__' and isinstance(self.scope, ModuleScope):
1293-
binding = ExportBinding(name, node._pyflakes_parent, self.scope)
1299+
binding = ExportBinding(name, node._pyflakes_parent, self.scope,
1300+
during_type_checking=self._in_type_checking)
12941301
elif PY2 and isinstance(getattr(node, 'ctx', None), ast.Param):
1295-
binding = Argument(name, self.getScopeNode(node))
1302+
binding = Argument(name, self.getScopeNode(node),
1303+
during_type_checking=self._in_type_checking)
12961304
else:
1297-
binding = Assignment(name, node)
1305+
binding = Assignment(name, node, during_type_checking=self._in_type_checking)
12981306
self.addBinding(node, binding)
12991307

13001308
def handleNodeDelete(self, node):
@@ -2009,7 +2017,8 @@ def GLOBAL(self, node):
20092017

20102018
# One 'global' statement can bind multiple (comma-delimited) names.
20112019
for node_name in node.names:
2012-
node_value = Assignment(node_name, node)
2020+
node_value = Assignment(node_name, node,
2021+
during_type_checking=self._in_type_checking)
20132022

20142023
# Remove UndefinedName messages already reported for this name.
20152024
# TODO: if the global is not used in this scope, it does not
@@ -2111,7 +2120,8 @@ def FUNCTIONDEF(self, node):
21112120
for deco in node.decorator_list:
21122121
self.handleNode(deco, node)
21132122
self.LAMBDA(node)
2114-
self.addBinding(node, FunctionDefinition(node.name, node))
2123+
self.addBinding(node, FunctionDefinition(
2124+
node.name, node, during_type_checking=self._in_type_checking))
21152125
# doctest does not process doctest within a doctest,
21162126
# or in nested functions.
21172127
if (self.withDoctest and
@@ -2236,7 +2246,8 @@ def CLASSDEF(self, node):
22362246
for stmt in node.body:
22372247
self.handleNode(stmt, node)
22382248
self.popScope()
2239-
self.addBinding(node, ClassDefinition(node.name, node))
2249+
self.addBinding(node, ClassDefinition(
2250+
node.name, node, during_type_checking=self._in_type_checking))
22402251

22412252
def AUGASSIGN(self, node):
22422253
self.handleNodeLoad(node.target)
@@ -2271,10 +2282,12 @@ def TUPLE(self, node):
22712282
def IMPORT(self, node):
22722283
for alias in node.names:
22732284
if '.' in alias.name and not alias.asname:
2274-
importation = SubmoduleImportation(alias.name, node)
2285+
importation = SubmoduleImportation(
2286+
alias.name, node, during_type_checking=self._in_type_checking)
22752287
else:
22762288
name = alias.asname or alias.name
2277-
importation = Importation(name, node, alias.name)
2289+
importation = Importation(name, node, full_name=alias.name,
2290+
during_type_checking=self._in_type_checking)
22782291
self.addBinding(node, importation)
22792292

22802293
def IMPORTFROM(self, node):
@@ -2299,16 +2312,17 @@ def IMPORTFROM(self, node):
22992312
elif alias.name == '*':
23002313
# Only Python 2, local import * is a SyntaxWarning
23012314
if not PY2 and not isinstance(self.scope, ModuleScope):
2302-
self.report(messages.ImportStarNotPermitted,
2303-
node, module)
2315+
self.report(messages.ImportStarNotPermitted, node, module)
23042316
continue
23052317

23062318
self.scope.importStarred = True
23072319
self.report(messages.ImportStarUsed, node, module)
2308-
importation = StarImportation(module, node)
2320+
importation = StarImportation(
2321+
module, node, during_type_checking=self._in_type_checking)
23092322
else:
2310-
importation = ImportationFrom(name, node,
2311-
module, alias.name)
2323+
importation = ImportationFrom(
2324+
name, node, module, real_name=alias.name,
2325+
during_type_checking=self._in_type_checking)
23122326
self.addBinding(node, importation)
23132327

23142328
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)