On 23Jun2017 11:48, Nick Coghlan <ncogh...@gmail.com> wrote:
On 23 June 2017 at 09:29, Cameron Simpson <c...@zip.com.au> wrote:
This is so common that I actually keep around a special hack:
def prop(func):
''' The builtin @property decorator lets internal AttributeErrors
escape.
While that can support properties that appear to exist
conditionally,
in practice this is almost never what I want, and it masks deeper
errors.
Hence this wrapper for @property that transmutes internal
AttributeErrors
into RuntimeErrors.
'''
def wrapper(*a, **kw):
try:
return func(*a, **kw)
except AttributeError as e:
e2 = RuntimeError("inner function %s raised %s" % (func, e))
if sys.version_info[0] >= 3:
try:
eval('raise e2 from e', globals(), locals())
except:
# FIXME: why does this raise a SyntaxError?
raise e
else:
raise e2
return property(wrapper)
Slight tangent, but I do sometimes wonder if adding a decorator
factory like the following to functools might be useful:
def raise_when_returned(return_exc):
def decorator(f):
@wraps(f)
def wrapper(*args, **kwds):
try:
result = f(*args, **kwds)
except selective_exc as unexpected_exc:
msg = "inner function {} raised {}".format(f,
unexpected_exc)
raise RuntimeError(msg) from unexpected_exc
if isinstance(result, return_exc):
raise result
return result
It's essentially a generalisation of PEP 479 to arbitrary exception
types, since it lets you mark a particular exception type as being
communicated back to the wrapper via the return channel rather than as
a regular exception:
def with_traceback(exc):
try:
raise exc
except BaseException as caught_exc:
return caught_exc
@property
@raise_when_returned(AttributeError)
def target(self):
if len(self.targets) == 1:
return self.targets[0]
return with_traceback(AttributeError('only exists when this
has exactly one target'))
Funnily enough I have an @transmute decorator which serves just this purpose.
It doesn't see as much use as I might imagine, but that is partially because my
function predates "raise ... from", which meant that it loses the stack trace
from the transmuted exception, impeding debugging. I need to revisit it with
that in mind.
So yes, your proposed decorator has supporting real world use cases in my
world.
Cheers,
Cameron Simpson <c...@zip.com.au>
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/