On 31Dec2015 16:12, Steven D'Aprano <st...@pearwood.info> wrote:
On Thu, 31 Dec 2015 03:03 pm, Cameron Simpson wrote:
Steven D'Aprano (that's me) wrote this:
Whereas if _validate does what it is supposed to do, and is working
correctly, you will see:
Traceback (most recent call last):
File "spam", line 19, in this
File "spam", line 29, in that
File "spam", line 39, in other
File "spam", line 5, in _validate
ThingyError: ...
and the reader has to understand the internal workings of _validate
sufficiently to infer that this exception is not a bug in _validate but an
expected failure mode of other when you pass a bad argument.
Would it not be useful then to name the including function in the
exception text?
You mean change the signature of _validate to:
def _validate(a, b, name_of_caller):
...
and have function "other" call it like this:
def other(arg1, arg2):
_validate(arg1, arg2, "other")
# if we reach this line, the arguments were validated
# and we can continue
...
I think that's pretty horrible. I'm not sure whether that would be more, or
less, horrible than having _validate automagically determine the caller's
name by looking in the call stack.
No, I meant your latter suggestion above: consult the call stack to fish out
the calling function name. Something like:
from cs.py.stack import caller
...
def _validate(...):
frame = caller()
funcname = frame.functionname
and then use funcname in the messages, or greater detail. Caller() is available
here:
https://bitbucket.org/cameron_simpson/css/src/tip/lib/python/cs/py/stack.py?fileviewer=file-view-default
for the fiddliness. The horribleness is at least concealed, unless you're
nesting _validate implementations.
I confess that when I want to check several things I would like to return
several failure indications. So thing on that line, how about this:
for blam in _validate(a, b):
raise blam
which leaves you open to gatheroing them all up instead of aborting on the
first complaint.
Are you sure? I would have expected that raising the first exception would
exit the loop.
In the bare form, surely, just like your "if". But in principle you could
gather all the exceptions together and raise a new exception with details
attached.
I think this is a win for debuggability. (Is that a word?) But it's a bit
annoying to do it today, since you have to save the return result and
explicitly compare it to None. If "raise None" was a no-op, it would feel
more natural to just say raise _validate() and trust that if _validate
falls out the end and returns None, the raise will be a no-op.
This is a nice idea though. Succinct and expressive, though people would
have to learn that:
raise foo()
does not unconditionally abort at this point.
Yes, that crossed my mind. Maybe if there was a second keyword:
raiseif foo()
which only raised if foo() returned a non-None value. That's kind of like
the "or die" idiom from Perl, I guess. But of course requiring a second
keyword will almost certainly doom this proposal -- it is only of benefit
at the margins as it is.
I'd rather your original myself: plain "raise". Another keyword seems a reach,
and I don't like it. And I don't like "raiseif"; I've got a bunch of "blahif"
functions of similar flavour and I'm stuff unhappy with their names.
I think it is a small thing to learn, especially as "raise None" is already an
error.
Cheers,
Cameron Simpson <c...@zip.com.au>
--
https://mail.python.org/mailman/listinfo/python-list