diff --git a/pyflakes/checker.py b/pyflakes/checker.py index 3b35ca64..acf7b29d 100644 --- a/pyflakes/checker.py +++ b/pyflakes/checker.py @@ -449,8 +449,14 @@ def addBinding(self, node, value): self.report(messages.RedefinedWhileUnused, node, value.name, existing.source) - elif isinstance(existing, Importation) and value.redefines(existing): - existing.redefined.append(node) + elif isinstance(existing, Importation): + if isinstance(node, (ast.Import, ast.ImportFrom)): + if not isinstance(self.scope, DoctestScope): + self.report(messages.ImportShadowedByImport, + node, value.name, existing.source) + + elif value.redefines(existing): + existing.redefined.append(node) if value.name in self.scope: # then assume the rebound name is used as a global or within a loop diff --git a/pyflakes/messages.py b/pyflakes/messages.py index 27167e03..461d8cf3 100644 --- a/pyflakes/messages.py +++ b/pyflakes/messages.py @@ -41,6 +41,14 @@ def __init__(self, filename, loc, name, orig_loc): self.message_args = (name, orig_loc.lineno) +class ImportShadowedByImport(Message): + message = 'import %r from line %r shadowed by import' + + def __init__(self, filename, loc, name, orig_loc): + Message.__init__(self, filename, loc) + self.message_args = (name, orig_loc.lineno) + + class ImportShadowedByLoopVar(Message): message = 'import %r from line %r shadowed by loop variable' diff --git a/pyflakes/test/test_doctests.py b/pyflakes/test/test_doctests.py index 30576bde..c4238c05 100644 --- a/pyflakes/test/test_doctests.py +++ b/pyflakes/test/test_doctests.py @@ -9,7 +9,7 @@ from pyflakes.test.test_other import Test as TestOther from pyflakes.test.test_imports import Test as TestImports from pyflakes.test.test_undefined_names import Test as TestUndefinedNames -from pyflakes.test.harness import TestCase, skip +from pyflakes.test.harness import TestCase class _DoctestMixin(object): @@ -193,7 +193,6 @@ def doctest_stuff(): ''' """) - @skip("todo") def test_importBeforeAndInDoctest(self): self.flakes(''' import foo @@ -205,7 +204,7 @@ def doctest_stuff(): """ foo - ''', m.RedefinedWhileUnused) + ''') def test_importInDoctestAndAfter(self): self.flakes(''' diff --git a/pyflakes/test/test_imports.py b/pyflakes/test/test_imports.py index 6cd0ec5f..a210661c 100644 --- a/pyflakes/test/test_imports.py +++ b/pyflakes/test/test_imports.py @@ -184,9 +184,8 @@ def bar(): def baz(): def fu(): pass - ''', - m.RedefinedWhileUnused, m.RedefinedWhileUnused, - m.UnusedImport, m.UnusedImport) + ''', *(m.ImportShadowedByImport, m.RedefinedWhileUnused, + m.UnusedImport, m.UnusedImport)) def test_redefinedButUsedLater(self): """ @@ -564,6 +563,15 @@ def bar(): fu ''', m.UnusedImport, m.UndefinedName) + def test_shadowedInNestedScope(self): + self.flakes(''' + import fu + def bar(): + import fu + fu + fu + ''', m.ImportShadowedByImport) + def test_methodsDontUseClassScope(self): self.flakes(''' class bar: