Reputation: 43
I'm receiving an error of AttributeError: __exit__
in the code below after finishing the with
section. The Element object has is being returned in the with
and it has __exit__
defined, so I'm baffled.
class Builder:
def __init__(self):
print("Builder init fires")
def __getattr__(self, name):
return Element(name, self)
class Element:
def __init__(self, name, builder):
self.name = name
self.builder = builder
print("Element init fires for name of", self.name)
def __call__(*args, **kargs):
print("CALL fires, now with attributes listed:")
for attr, value in sorted(kargs.items()):
print(' %s=>%s' % (attr, value))
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
pass
aa = Builder()
with aa.feed(xmlns='http://www.w3.org/2005/Atom'):
print("INSIDE THE WITH")
Upvotes: 3
Views: 4067
Reputation: 15548
The value of expression after with
keyword must be a valid context manager. That means the value of the expresion must have attributes __enter__
and __exit__
and these must accept parameters described in docs With Statement Context Managers. You can easily verify that the part aa.feed
would be acceptable, but the value of whole expression is None
and it has no necessary attribute. A difference between Python 3.5 and 3.6 is that one fails on missing __exit__
and the latter on missing __enter__
. Nothing unexpected.
You also forgot self
in the line def __call__(self, *args, **kargs):
that would be a problem if you will use args and it is a pythonic pattern also with unused args.
Upvotes: 1