On Tue, Jun 20, 2017 at 10:18 AM, Steven D'Aprano <st...@pearwood.info> wrote: > Apparently you heavily use properties, and __getattr__, and find that > the two don't interact well together when the property getters and > setters themselves raise AttributeError. I think that's relevant > information that helps explain the problem you are hoping to fix. > > So I *think* this demonstrates the problem: > > class A(object): > eggs = "text" > def __getattr__(self, name): > if name == 'cheese': > return "cheddar" > raise AttributeError('%s missing' % name) > @property > def spam(self): > return self.eggs.uper() # Oops.
I'm quoting Steven's post, but I'm addressing the OP. One good solution to this is a "guard point" around your property functions. def noleak(*exc): def deco(func): @functools.wraps(func) def wrapper(*a, **kw): try: return func(*a, **kw) except exc: raise RuntimeError return wrapper return deco @property @noleak(AttributeError) def spam(self): return self.eggs.uper() In fact, you could make this into a self-wrapping system if you like: def property(func, *, _=property): return _(noleak(AttributeError)(func)) Now, all your @property functions will be guarded: any AttributeErrors they raise will actually bubble as RuntimeErrors instead. Making this work with setters and deleters is left as an exercise for the reader. ChrisA _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/