Added support for error handling#17
Conversation
|
Hi @thinkingserious ! I have added custom exception handling. Do suggest changes for improvements. |
|
Hi @w- ! Have a look at this. What do you think? :) |
|
Hey guys, i'll be out of town on vacation for the next few days. won't be able to respond on this topic till then. |
|
Thanks for the heads up @w- and I hope you enjoy the vacation :) |
|
@w-, Do you have time to take a look? Thanks! |
|
In the meantime, how about I add tests for this? With Regards, |
|
Please add the test in the existing file. Thanks! |
python_http_client/__init__.py
Outdated
| @@ -1 +1,2 @@ | |||
| from .client import Client | |||
| from .exceptions import * No newline at end of file | |||
There was a problem hiding this comment.
even though there are many classes., I would change this to an explicit import
| 503 : ServiceUnavailableError | ||
| } | ||
|
|
||
| def handle_error(error): |
There was a problem hiding this comment.
this should probably get_HTTPError(error) and it should return an instance of the specific error class instead of raising it.
There was a problem hiding this comment.
Umm.. Can you give an example? I can't visualize this.
There was a problem hiding this comment.
this is what i think the function should be
def get_HTTPError(error):
try:
http_err_obj = err_dict[error.code](error)
except KeyError:
http_err_obj = HttpError(error)
return http_err_obj
python_http_client/exceptions.py
Outdated
| } | ||
|
|
||
| def handle_error(error): | ||
| exc = err_dict[error.code](error) |
There was a problem hiding this comment.
we want a try/catch here in event that the error.code doesn't match anything in our dict. it should then set err as a generic HTTPError
There was a problem hiding this comment.
Actually I just put in a few errors, the ones that SendGrid servers returns, just for showing the approach. If approved, I will add the rest of the error.
python_http_client/exceptions.py
Outdated
|
|
||
| def handle_error(error): | ||
| exc = err_dict[error.code](error) | ||
| exc.__cause__ = None |
There was a problem hiding this comment.
as per https://www.python.org/dev/peps/pep-3134/
we probably want __cause__ to be the original error.
There was a problem hiding this comment.
If we won't to do this then an ugly traceback is produced in Python 3. In this PR, we are raising our custom exception when an urllib.HTTPError is raised. Here, in python 3 , such a thing will be displayed the output.
Traceback (most recent call last):
File "/home/dibya/workspace/python-http-client/python_http_client/client.py", line 141, in _make_request
return opener.open(request)
File "/usr/lib/python3.5/urllib/request.py", line 472, in open
response = meth(req, response)
File "/usr/lib/python3.5/urllib/request.py", line 582, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python3.5/urllib/request.py", line 504, in error
result = self._call_chain(*args)
File "/usr/lib/python3.5/urllib/request.py", line 444, in _call_chain
result = func(*args)
File "/usr/lib/python3.5/urllib/request.py", line 696, in http_error_302
return self.parent.open(new, timeout=req.timeout)
File "/usr/lib/python3.5/urllib/request.py", line 472, in open
response = meth(req, response)
File "/usr/lib/python3.5/urllib/request.py", line 582, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python3.5/urllib/request.py", line 510, in error
return self._call_chain(*args)
File "/usr/lib/python3.5/urllib/request.py", line 444, in _call_chain
result = func(*args)
File "/usr/lib/python3.5/urllib/request.py", line 590, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 401: UNAUTHORIZED
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 7, in <module>
r = a.name.api.get()
File "/home/dibya/workspace/python-http-client/python_http_client/client.py", line 209, in http_request
return Response(self._make_request(opener, request))
File "/home/dibya/workspace/python-http-client/python_http_client/client.py", line 143, in _make_request
handle_error(err)
File "/home/dibya/workspace/python-http-client/python_http_client/exceptions.py", line 53, in handle_error
raise exc
python_http_client.exceptions.UnauthorizedError: HTTP Error 401: UNAUTHORIZED
If we set the __cause__ to None, then only the part below During handling of the above exception, another exception occurred: is shown, which is all that should be displayed.
There was a problem hiding this comment.
I see. ok. I guess it is preferable to be None
python_http_client/exceptions.py
Outdated
| def __init__(self,error): | ||
| self.code = error.code | ||
| self.reason = error.reason | ||
| #self.headers = error.headers |
There was a problem hiding this comment.
both headers and body are important to record in the new HTTPError object.
There was a problem hiding this comment.
The HTTPError thrown by urllib module doesn't have a body attribute and in python versions <= 3.3, they don't have the headers attribute as well. I just commented this out so that this can be discussed further.
There was a problem hiding this comment.
it does. you have to read docs and look at the source.
HTTPError is based on URLError which has the following attributes
err.url
err.code
err.hdrs
# to get the body
err.read()There was a problem hiding this comment.
Ah! Since it was not mentioned in the documentation, I missed it. Thanks for the tip! :)
python_http_client/exceptions.py
Outdated
| class HTTPError(Exception): | ||
| ''' Base of all other errors''' | ||
| def __init__(self,error): | ||
| self.code = error.code |
There was a problem hiding this comment.
keeping in line with other http libraries, I think that self.code should actually be self.status_code. personal preference only.
There was a problem hiding this comment.
Sure we can. It'll be more evident.
python_http_client/client.py
Outdated
| try: | ||
| return opener.open(request) | ||
| except HTTPError as err: | ||
| handle_error(err) |
There was a problem hiding this comment.
@w- Here, I am handling the urllib.HTTPError. What you are saying is, we do this:-
try:
return opener.open(request)
except HTTPError as err:
raise get_HTTPError(err)
Am I right?
|
Hi @thinkingserious and @w- , Edit :- After pushing an commit the coverage passed but is now failing 😕 I not really familiar with this. I need some help here. With Best Regards, |
|
Hi @thinkingserious, With Regards, |
|
I'm ok with this. |
|
Hi @thinkingserious, |
|
Per sendgrid/sendgrid-python#323 if we could get examples of these awesome new exceptions in the README so other devs don't need to go surfing into tests to see examples of exceptions and what can cause them, I think that'd be super helpful. |
andriisoldatenko
left a comment
There was a problem hiding this comment.
Please check code using flake8/pep8
| pass | ||
|
|
||
| class MethodNotAllowedError(HTTPError): | ||
| pass |
There was a problem hiding this comment.
could you please use spaces and pep8
Custom exceptions for
python_http_clienthave been added. Only few exceptions have been added.Others will be added soon.