
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
93 lines
2.4 KiB
Plaintext
93 lines
2.4 KiB
Plaintext
== Why is this an issue?
|
||
|
||
:link-with-uscores1: https://docs.python.org/3/reference/datamodel.html?highlight=__exit__%20special#object.__exit__
|
||
|
||
The special method {link-with-uscores1}[``++__exit__++``] should only raise an exception when it fails. It should never raise the provided exception, it is the caller's responsibility.
|
||
|
||
Raising this exception will make the stack trace difficult to understand.
|
||
|
||
|
||
The ``++__exit__++`` method can filter passed-in exceptions by simply returning True or False.
|
||
|
||
|
||
This rule raises an issue when:
|
||
|
||
* an ``++__exit__++`` method has a bare ``++raise++`` outside of an ``++except++`` block.
|
||
* an ``++__exit__++`` method raises the exception provided as parameter.
|
||
|
||
|
||
=== Noncompliant code example
|
||
|
||
[source,python]
|
||
----
|
||
class MyContextManager:
|
||
def __enter__(self):
|
||
return self
|
||
def __exit__(self, *args):
|
||
raise # Noncompliant
|
||
raise args[2] # Noncompliant
|
||
|
||
class MyContextManager:
|
||
def __enter__(self):
|
||
return self
|
||
def __exit__(self, exc_type, exc_value, traceback):
|
||
raise exc_value # Noncompliant
|
||
----
|
||
|
||
|
||
=== Compliant solution
|
||
|
||
[source,python]
|
||
----
|
||
class MyContextManager:
|
||
def __enter__(self):
|
||
return self
|
||
def __exit__(self, exc_type, exc_value, traceback):
|
||
# by default the function will return None, which is always False, and the exc_value will naturally raise.
|
||
pass
|
||
|
||
class MyContextManager:
|
||
def __enter__(self, stop_exceptions):
|
||
return self
|
||
def __exit__(self, *args):
|
||
try:
|
||
print("42")
|
||
except:
|
||
print("exception")
|
||
raise # No issue when raising another exception. The __exit__ method can fail and raise an exception
|
||
raise MemoryError("No more memory") # This is ok too.
|
||
----
|
||
|
||
|
||
:link-with-uscores1: https://docs.python.org/3/reference/datamodel.html?highlight=__exit__%20special#object.__exit__
|
||
|
||
== Resources
|
||
|
||
* Python documentation – {link-with-uscores1}[The ``++__exit__++`` special method]
|
||
* PEP 343 – https://www.python.org/dev/peps/pep-0343/[The "with" Statement]
|
||
|
||
|
||
ifdef::env-github,rspecator-view[]
|
||
|
||
'''
|
||
== Implementation Specification
|
||
(visible only on this page)
|
||
|
||
=== Message
|
||
|
||
remove this "raise" statement and return "False" instead.
|
||
|
||
|
||
=== Highlighting
|
||
|
||
The "raise" statement.
|
||
|
||
|
||
'''
|
||
== Comments And Links
|
||
(visible only on this page)
|
||
|
||
=== is related to: S5747
|
||
|
||
endif::env-github,rspecator-view[]
|