Skip to content

Commit b1ee795

Browse files
Merge pull request #20086 from joefarebrother/python-qual-raise-not-implemented
Python: Modernise raise-not-implemented query
2 parents 621b483 + a8cc144 commit b1ee795

File tree

3 files changed

+24
-14
lines changed

3 files changed

+24
-14
lines changed

python/ql/src/Exceptions/NotImplementedIsNotAnException.qhelp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,25 @@
44
<qhelp>
55
<overview>
66

7-
<p><code>NotImplemented</code> is not an Exception, but is often mistakenly used in place of <code>NotImplementedError</code>.
8-
Executing <code>raise NotImplemented</code> or <code>raise NotImplemented()</code> will raise a <code>TypeError</code>.
9-
When <code>raise NotImplemented</code> is used to mark code that is genuinely never called, this mistake is benign.
10-
11-
However, should it be called, then a <code>TypeError</code> will be raised rather than the expected <code>NotImplemented</code>,
12-
which might make debugging the issue difficult.
7+
<p>
8+
The constant <code>NotImplemented</code> is not an <code>Exception</code>, but is often confused for <code>NotImplementedError</code>.
9+
If it is used as an exception, such as in <code>raise NotImplemented</code> or <code>raise NotImplemented("message")</code>,
10+
a <code>TypeError</code> will be raised rather than the expected <code>NotImplemented</code>. This may make debugging more difficult.
1311
</p>
1412

15-
<p>The correct use of <code>NotImplemented</code> is to implement binary operators.
13+
<p><code>NotImplemented</code> should only be used as a special return value for implementing special methods such as <code>__lt__</code>.
1614
Code that is not intended to be called should raise <code>NotImplementedError</code>.</p>
1715

1816
</overview>
1917
<recommendation>
20-
<p>Replace uses of <code>NotImplemented</code> with <code>NotImplementedError</code>.</p>
18+
<p>If a <code>NotImplementedError</code> is intended to be raised, replace the use of <code>NotImplemented</code>
19+
with that. If <code>NotImplemented</code> is intended to be returned rather than raised, replace the <code>raise</code> with <code>return NotImplemented</code>.
20+
</p>
2121
</recommendation>
2222
<example>
2323

2424
<p>
25-
In the example below, the method <code>wrong</code> will incorrectly raise a <code>TypeError</code> when called.
25+
In the following example, the method <code>wrong</code> will incorrectly raise a <code>TypeError</code> when called.
2626
The method <code>right</code> will raise a <code>NotImplementedError</code>.
2727
</p>
2828

@@ -34,6 +34,7 @@ The method <code>right</code> will raise a <code>NotImplementedError</code>.
3434
<references>
3535

3636
<li>Python Language Reference: <a href="https://docs.python.org/library/exceptions.html#NotImplementedError">The NotImplementedError exception</a>.</li>
37+
<li>Python Language Reference: <a href="https://docs.python.org/3/library/constants.html#NotImplemented">The NotImplemented constant</a>.</li>
3738
<li>Python Language Reference: <a href="https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types">Emulating numeric types</a>.</li>
3839

3940
</references>
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
2-
* @name NotImplemented is not an Exception
3-
* @description Using 'NotImplemented' as an exception will result in a type error.
2+
* @name Raising `NotImplemented`
3+
* @description Using `NotImplemented` as an exception will result in a type error.
44
* @kind problem
55
* @problem.severity warning
66
* @sub-severity high
@@ -12,8 +12,17 @@
1212
*/
1313

1414
import python
15-
import Exceptions.NotImplemented
15+
import semmle.python.ApiGraphs
16+
17+
predicate raiseNotImplemented(Raise raise, Expr notImpl) {
18+
exists(API::Node n | n = API::builtin("NotImplemented") |
19+
notImpl = n.getACall().asExpr()
20+
or
21+
n.asSource().flowsTo(DataFlow::exprNode(notImpl))
22+
) and
23+
notImpl = raise.getException()
24+
}
1625

1726
from Expr notimpl
18-
where use_of_not_implemented_in_raise(_, notimpl)
27+
where raiseNotImplemented(_, notimpl)
1928
select notimpl, "NotImplemented is not an Exception. Did you mean NotImplementedError?"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
| exceptions_test.py:170:11:170:24 | NotImplemented | NotImplemented is not an Exception. Did you mean NotImplementedError? |
2-
| exceptions_test.py:173:11:173:24 | NotImplemented | NotImplemented is not an Exception. Did you mean NotImplementedError? |
2+
| exceptions_test.py:173:11:173:26 | NotImplemented() | NotImplemented is not an Exception. Did you mean NotImplementedError? |

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy