'NoneType' in contextmanager prevent proper RuntimeError to be raised
Daniel Gonçalves
daniel at base4.com.br
Wed May 20 20:08:07 EDT 2015
>From the "Lib/contextlib.py":
class GeneratorContextManager(object):
"""Helper for @contextmanager decorator."""
def __init__(self, gen):
self.gen = gen
def __enter__(self):
try:
return self.gen.next()
except StopIteration:
raise RuntimeError("generator didn't yield")
The line "raise RuntimerError(...)" never gets reached, since self.gen is None.
So you end up with an AttributeError: 'NoneType' object has no
attribute 'next', instead of the proper RuntimeError, making it harder
to debug.
Anyways, I know that it's strange to have a contextmanager that didn't yield.
I just stumbled upon this, by accident, and I think the way it's
implemented looks wrong :)
2015-05-20 20:44 GMT-03:00 MRAB <python at mrabarnett.plus.com>:
> On 2015-05-21 00:20, Daniel Gonçalves wrote:
>>
>> When you decorate a function with contextmanager that didn't yield you got
>> an AttributeError instead of a proper RuntimeError "generator didn't yield".
>> For example:
>>
>>>>> @contextlib.contextmanager
>>>>> def foo():
>>
>> ... pass
>> ...
>>>>>
>>>>> with foo():
>>
>> ... do_something()
>> ...
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> File "/usr/lib/python2.7/contextlib.py", line 17, in __enter__
>> return self.gen.next()
>> AttributeError: 'NoneType' object has no attribute 'next'
>>
>> The proper exception should be a RuntimerError with the "generator didn't
>> yield" message. At least for Python version 2.7.6.
>>
> If it doesn't contain a 'yield', it's not a generator, it's a function.
>
--
Daniel Gonçalves
Base4 Sistemas Ltda ME
www.base4.com.br
More information about the Python-list
mailing list