Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions deepomatic/api/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ def __init__(self):
###############################################################################

class BadStatus(DeepomaticException):
"""
Thrown when HTTP response status_code < 200 or status_code >= 300.
"""
def __init__(self, response):
self.response = response

Expand All @@ -68,6 +71,22 @@ def __str__(self):
return "Bad status code %s with body %s" % (self.response.status_code, self.response.content)


class ClientError(BadStatus):
"""
Thrown when HTTP response status_code is a 4xx.
The client sent a bad request.
"""
pass


class ServerError(BadStatus):
"""
Thrown when HTTP response status_code is a 5xx.
The request seems to be valid but the server couldn't handle it for some reason.
"""
pass


###############################################################################

class TaskError(DeepomaticException):
Expand Down
15 changes: 11 additions & 4 deletions deepomatic/api/http_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
import sys

import requests
from deepomatic.api.exceptions import BadStatus, DeepomaticException
from deepomatic.api.exceptions import (BadStatus, ServerError,
ClientError, DeepomaticException)
from deepomatic.api.http_retry import HTTPRetry
from deepomatic.api.version import __title__, __version__
from requests.structures import CaseInsensitiveDict
Expand Down Expand Up @@ -256,11 +257,17 @@ def make_request(self, func, resource, params=None, data=None,
for file in opened_files:
file.close()

if response.status_code == 204: # delete
status_code = response.status_code
if status_code == 204: # delete
return None

if response.status_code < 200 or response.status_code >= 300:
raise BadStatus(response)
if status_code < 200 or status_code >= 300:
if status_code >= 400 and status_code < 500:
raise ClientError(response)
elif status_code >= 500 and status_code < 600:
raise ServerError(response)
else:
raise BadStatus(response)

if stream:
# we asked for a stream, we let the user download it as he wants or it will load everything in RAM
Expand Down
14 changes: 11 additions & 3 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import requests
import six
from deepomatic.api.client import Client
from deepomatic.api.exceptions import BadStatus, TaskTimeout, HTTPRetryError, TaskRetryError
from deepomatic.api.exceptions import ServerError, ClientError, TaskTimeout, HTTPRetryError, TaskRetryError
from deepomatic.api.http_retry import HTTPRetry
from deepomatic.api.inputs import ImageInput
from deepomatic.api.version import __title__, __version__
Expand Down Expand Up @@ -299,6 +299,14 @@ def test_batch_wait(self, client):
assert(tasks[pos].pk == success.pk)
assert inference_schema(2, 0, 'golden retriever', 0.8) == success['data']

def test_client_error(self, client):
spec = client.RecognitionSpec.retrieve('imagenet-inception-v3')
with pytest.raises(ClientError) as exc:
spec.inference(inputs=[])

assert 400 == exc.value.status_code
assert 'error' in exc.value.json()


class TestClientRetry(object):
DEFAULT_TIMEOUT = 2
Expand Down Expand Up @@ -355,12 +363,12 @@ def test_no_retry_create_network(self):
client = self.get_client_with_retry()
# Creating network doesn't retry, we directly get a 502
t = time.time()
with pytest.raises(BadStatus) as exc:
with pytest.raises(ServerError) as exc:
client.Network.create(name="My first network",
framework='tensorflow-1.x',
preprocessing=["useless"],
files=["useless"])
assert 502 == exc.status_code
assert 502 == exc.value.status_code
assert time.time() - t < 0.3

def test_retry_task_with_http_errors(self):
Expand Down