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

Reply via email to