New submission from Daniel Grace: I was writing code for a class that uses one threading.RLock per object. For convenience, I wanted to be able to use that lock's context manager and acquire/release methods without referencing the lock directly, so I opted to take a shortcut by assigning self.__enter__ = self.lock.__enter__ and so forth.
This fails in Python 3.3.1 (self-compiled on Debian) and both "3.3.2+" and "2.7.5+" (currently available Ubuntu packages). Judging by the error messages, it looks 'with' is examining the __enter__ and __exit__ attributes defined on the instance's class, rather than those defined on the instance itself. The workaround here is simple enough, but I'm under the impression that it shouldn't be needed anyways. Test case follows: import threading class Foo(object): # Uncommenting these yields "NoneType is not callable" rather than an AttributeError # __enter__ = None # __exit__ = None # acquire = None # release = None # lock = None def __init__(self): self.lock = threading.RLock() print(repr(self.lock)) self.__enter__ = self.lock.__enter__ self.__exit__ = self.lock.__exit__ self.acquire = self.lock.acquire self.release = self.lock.release foo = Foo() # These all function as expected. The fourth line fails (correctly) on 2.7.5. print(repr(foo.__enter__)) print(repr(foo.__exit__)) print(foo.__enter__()) print(foo.__exit__()) # This does not with foo: pass ---------- components: Interpreter Core messages: 207457 nosy: dewin priority: normal severity: normal status: open title: 'with instance' references class's __enter__ attribute rather than instance's type: behavior versions: Python 2.7, Python 3.3 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue20149> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com