<div dir="ltr"><br><div class="gmail_extra"><div class="gmail_quote">On Fri, Jul 12, 2013 at 10:09 AM, Monty Taylor <span dir="ltr"><<a href="mailto:mordred@inaugust.com" target="_blank">mordred@inaugust.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im"><br>
<br>
On 07/11/2013 05:20 AM, Mark McLoughlin wrote:<br>
> On Wed, 2013-07-10 at 19:49 -0400, Monty Taylor wrote:<br>
>> I'd like top-post and hijack this thread for another exception related<br>
>> thing:<br>
>><br>
>> a) Anyone writing code such as:<br>
>><br>
>> try:<br>
>>   blah()<br>
>> except SomeException:<br>
>>   raise SomeOtherExceptionLeavingOutStackContextFromSomeException<br>
>><br>
>> should be mocked ruthlessly.<br>
><br>
> Ok, mock me ruthlessly then.<br>
<br>
</div>Mock. Mock. Mock. Mock.<br>
<div class="im"><br>
> Part of designing any API is specifying what predictable exceptions it<br>
> will raise. For any predictable error condition, you don't want callers<br>
> to have to catch random exceptions from the underlying libraries you<br>
> might be calling into.<br>
<br>
</div>Absolutely. But you don't want to go so overboard that you remove the<br>
ability for a developer to debug it. More importantly, INSIDE of server<br>
code, we're not designing fun apis for the consumption of people we<br>
don't know. There is clearly an API, but we are the consumers of our own<br>
API.<br></blockquote><div><br></div><div style>Lies! Write everything to be intuitive for new contributors or we won't have any :(</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="im"><br>
> Say if I was designing an image downloading API, I'd do something like<br>
> this:<br>
><br>
>   <a href="https://gist.github.com/markmc/5973868" target="_blank">https://gist.github.com/markmc/5973868</a><br>
><br>
> Assume there's a tonne more stuff that the API would do. You don't want<br>
> callers to have to catch socket.error exceptions and whatever other<br>
> exceptions might be thrown.<br>
><br>
> That works out as:<br>
><br>
>   Traceback (most recent call last):<br>
>     File "t.py", line 20, in <module><br>
>       download_image('localhost', 3366, 'foobar')<br>
>     File "t.py", line 18, in download_image<br>
>       raise ImageDownloadFailure(host, port, path, e.strerror)<br>
>   __main__.ImageDownloadFailure: Failed to download foobar from localhost:3366: Connection refused<br>
><br>
> Which is a pretty clear exception.<br>
<br>
</div>Right, but what if the message from the exception does not give you<br>
enough information to walk down the stack and see it...<br>
<br>
Also, I have more than once seen:<br>
<br>
class MyIOError(Exception):<br>
    pass<br>
<div class="im"><br>
try:<br>
    s = socket.create_connection((host, port))<br>
</div>except socket.error:<br>
    raise MyIOError("something went wrong!")<br>
<br>
Which is an extreme example of where my rage comes from, but not a made<br>
up example. I have, actually, seen code exactly like that - in Nova.<br>
<br>
BTW - I'd have download_image return None if it can't download the<br>
image, and I'd have it either deal with the socket.error or not locally<br>
at the source. But now we're nitpicking.<br>
<div class="im"><br>
> But I think what you're saying is missing is the stack trace from the<br>
> underlying exception.<br>
<br>
</div>YES - and I'll let David's response respond to the details of the rest...<br>
<br>
But essentially, what I was really mocking earlier is throwing a new<br>
exception in such a way that you lose the exception propagation path. So<br>
if you throw an exception inside of an except block, you should be sure<br>
that you're passing on all of the info, because if a developer gets an<br>
exception, it's quite likely that they want to know how to fix it. :)<br>
<div class="im"><br>
> As I understood it, Python doesn't have a way of chaining exceptions<br>
> like this but e.g. Java does. A little bit more poking right now shows<br>
> up this:<br>
><br>
>   <a href="http://www.python.org/dev/peps/pep-3134/" target="_blank">http://www.python.org/dev/peps/pep-3134/</a><br>
><br>
> i.e. we can't do the right thing until Python 3, where we'd do:<br>
><br>
>  def download_image(host, port, path):<br>
>      try:<br>
>          s = socket.create_connection((host, port))<br>
>      except socket.error as e:<br>
>          raise ImageDownloadFailure(host, port, path, e.strerror) from e<br>
<br>
</div>This will certainly be cleaner to write and read.<br>
<div class="HOEnZb"><div class="h5"><br>
> I haven't read the PEP in detail yet, though.<br>
><br>
> Cheers,<br>
> Mark.<br>
><br>
><br>
> _______________________________________________<br>
> OpenStack-dev mailing list<br>
> <a href="mailto:OpenStack-dev@lists.openstack.org">OpenStack-dev@lists.openstack.org</a><br>
> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
><br>
<br>
_______________________________________________<br>
OpenStack-dev mailing list<br>
<a href="mailto:OpenStack-dev@lists.openstack.org">OpenStack-dev@lists.openstack.org</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div><br></div>-Dolph
</div></div>