diff options
author | Anthony Sottile <asottile@umich.edu> | 2018-10-13 18:47:06 -0700 |
---|---|---|
committer | John Vandenberg <jayvdb@gmail.com> | 2018-11-01 03:53:58 +0700 |
commit | 91c9989de63ff7053a6c09313e2c5e09a98d46c0 (patch) | |
tree | 92e3f64a8131fb1b9549c894cb02aef1ef74ab9c | |
parent | 60c3b35769984534e2ad03d76637357818fe0112 (diff) | |
download | pyflakes-91c9989de63ff7053a6c09313e2c5e09a98d46c0.tar.gz |
Exempt typing.overload from duplicate detection
-rw-r--r-- | pyflakes/checker.py | 27 | ||||
-rw-r--r-- | pyflakes/test/test_doctests.py | 3 | ||||
-rw-r--r-- | pyflakes/test/test_other.py | 29 |
3 files changed, 56 insertions, 3 deletions
diff --git a/pyflakes/checker.py b/pyflakes/checker.py index f520325..ad25b5e 100644 --- a/pyflakes/checker.py +++ b/pyflakes/checker.py @@ -495,6 +495,28 @@ def getNodeName(node): return node.name +def is_typing_overload(value, scope): + def is_typing_overload_decorator(node): + return ( + ( + isinstance(node, ast.Name) and + node.id in scope and + scope[node.id].fullName == 'typing.overload' + ) or ( + isinstance(node, ast.Attribute) and + isinstance(node.value, ast.Name) and + node.value.id == 'typing' and + node.attr == 'overload' + ) + ) + + return ( + isinstance(value.source, ast.FunctionDef) and + len(value.source.decorator_list) == 1 and + is_typing_overload_decorator(value.source.decorator_list[0]) + ) + + class Checker(object): """ I check the cleanliness and sanity of Python code. @@ -747,8 +769,9 @@ class Checker(object): node, value.name, existing.source) elif not existing.used and value.redefines(existing): if value.name != '_' or isinstance(existing, Importation): - self.report(messages.RedefinedWhileUnused, - node, value.name, existing.source) + if not is_typing_overload(existing, self.scope): + self.report(messages.RedefinedWhileUnused, + node, value.name, existing.source) elif isinstance(existing, Importation) and value.redefines(existing): existing.redefined.append(node) diff --git a/pyflakes/test/test_doctests.py b/pyflakes/test/test_doctests.py index aed7957..b6d0f65 100644 --- a/pyflakes/test/test_doctests.py +++ b/pyflakes/test/test_doctests.py @@ -33,7 +33,8 @@ class _DoctestMixin(object): line.startswith('except ') or line.startswith('finally:') or line.startswith('else:') or - line.startswith('elif ')): + line.startswith('elif ') or + (lines and lines[-1].startswith(('>>> @', '... @')))): line = "... %s" % line else: line = ">>> %s" % line diff --git a/pyflakes/test/test_other.py b/pyflakes/test/test_other.py index e5da024..b8301ea 100644 --- a/pyflakes/test/test_other.py +++ b/pyflakes/test/test_other.py @@ -291,6 +291,35 @@ class Test(TestCase): pass """) + def test_typingOverload(self): + """Allow intentional redefinitions via @typing.overload""" + self.flakes(""" + import typing + from typing import overload + + @overload + def f(s): # type: (None) -> None + pass + + @overload + def f(s): # type: (int) -> int + pass + + def f(s): + return s + + @typing.overload + def g(s): # type: (None) -> None + pass + + @typing.overload + def g(s): # type: (int) -> int + pass + + def g(s): + return s + """) + def test_unaryPlus(self): """Don't die on unary +.""" self.flakes('+1') |