summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Sottile <asottile@umich.edu>2018-10-13 18:47:06 -0700
committerJohn Vandenberg <jayvdb@gmail.com>2018-11-01 03:53:58 +0700
commit91c9989de63ff7053a6c09313e2c5e09a98d46c0 (patch)
tree92e3f64a8131fb1b9549c894cb02aef1ef74ab9c
parent60c3b35769984534e2ad03d76637357818fe0112 (diff)
downloadpyflakes-91c9989de63ff7053a6c09313e2c5e09a98d46c0.tar.gz
Exempt typing.overload from duplicate detection
-rw-r--r--pyflakes/checker.py27
-rw-r--r--pyflakes/test/test_doctests.py3
-rw-r--r--pyflakes/test/test_other.py29
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')