Skip to content

Commit af45b41

Browse files
Scott Sandersonbitglue
authored andcommitted
Warn on raise NotImplemented(...)
This is a common mistake for `raise NotImplementedError`. Since `NotImplemented` isn't an exception, it's never valid to raise it (barring strange circumstances where you've aliased `NotImplemented` in `__builtins__`).
1 parent 7a34cfd commit af45b41

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

pyflakes/checker.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,17 @@
3838
def getNodeType(node_class):
3939
# workaround str.upper() which is locale-dependent
4040
return str(unicode(node_class.__name__).upper())
41+
42+
def get_raise_argument(node):
43+
return node.type
44+
4145
else:
4246
def getNodeType(node_class):
4347
return node_class.__name__.upper()
4448

49+
def get_raise_argument(node):
50+
return node.exc
51+
4552
# Silence `pyflakes` from reporting `undefined name 'unicode'` in Python 3.
4653
unicode = str
4754

@@ -138,6 +145,10 @@ def convert_to_value(item):
138145
return UnhandledKeyType()
139146

140147

148+
def is_notimplemented_name_node(node):
149+
return isinstance(node, ast.Name) and getNodeName(node) == 'NotImplemented'
150+
151+
141152
class Binding(object):
142153
"""
143154
Represents the binding of a value to a name.
@@ -965,7 +976,7 @@ def ignore(self, node):
965976

966977
# "stmt" type nodes
967978
DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \
968-
ASYNCWITH = ASYNCWITHITEM = RAISE = TRYFINALLY = EXEC = \
979+
ASYNCWITH = ASYNCWITHITEM = TRYFINALLY = EXEC = \
969980
EXPR = ASSIGN = handleChildren
970981

971982
PASS = ignore
@@ -989,6 +1000,19 @@ def ignore(self, node):
9891000
EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = \
9901001
MATMULT = ignore
9911002

1003+
def RAISE(self, node):
1004+
self.handleChildren(node)
1005+
1006+
arg = get_raise_argument(node)
1007+
1008+
if isinstance(arg, ast.Call):
1009+
if is_notimplemented_name_node(arg.func):
1010+
# Handle "raise NotImplemented(...)"
1011+
self.report(messages.RaiseNotImplemented, node)
1012+
elif is_notimplemented_name_node(arg):
1013+
# Handle "raise NotImplemented"
1014+
self.report(messages.RaiseNotImplemented, node)
1015+
9921016
# additional node types
9931017
COMPREHENSION = KEYWORD = FORMATTEDVALUE = JOINEDSTR = handleChildren
9941018

pyflakes/messages.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,7 @@ class ForwardAnnotationSyntaxError(Message):
239239
def __init__(self, filename, loc, annotation):
240240
Message.__init__(self, filename, loc)
241241
self.message_args = (annotation,)
242+
243+
244+
class RaiseNotImplemented(Message):
245+
message = "'raise NotImplemented' should be 'raise NotImplementedError'"

pyflakes/test/test_other.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,3 +1983,20 @@ class A: pass
19831983
self.flakes('''
19841984
a: 'a: "A"'
19851985
''', m.ForwardAnnotationSyntaxError)
1986+
1987+
def test_raise_notimplemented(self):
1988+
self.flakes('''
1989+
raise NotImplementedError("This is fine")
1990+
''')
1991+
1992+
self.flakes('''
1993+
raise NotImplementedError
1994+
''')
1995+
1996+
self.flakes('''
1997+
raise NotImplemented("This isn't gonna work")
1998+
''', m.RaiseNotImplemented)
1999+
2000+
self.flakes('''
2001+
raise NotImplemented
2002+
''', m.RaiseNotImplemented)

0 commit comments

Comments
 (0)