Skip to content

Improve retry error #106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ all: release
build: clean
# lint + unit tests + build egg (available in host ./dist)
dmake test build-egg
# + test egg on python 2 and 3 using egg from host
dmake test -s test-egg-py2:2.7
dmake test -s test-egg-py3:3.6
# + test egg on python 3 using egg from host
dmake test -s test-egg-py3:3.8

clean:
rm -rf dist
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

This client have been made in order to help you integrating our services within your apps in python.

Tested on python 2.7, 3.4, 3.5, 3.6.
Tested on python 3.8, 3.9, 3.10, 3.11.

# API Documentation

Expand Down
33 changes: 15 additions & 18 deletions deepomatic/api/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,28 @@

import json
from tenacity import RetryError
from requests import Response


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

class DeepomaticException(Exception):
def __init__(self, msg):
super(DeepomaticException, self).__init__(msg)

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


class CredentialsNotFound(DeepomaticException):
pass


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

class UnimplementedException(DeepomaticException):
def __init__(self, msg):
super(UnimplementedException, self).__init__(msg)


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

class NoData(DeepomaticException):
def __init__(self):
super(NoData, self).__init__("No data !! You may need to call '.retrieve()' ?")


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

class BadStatus(DeepomaticException):
"""
Thrown when HTTP response status_code < 200 or status_code >= 300.
Expand Down Expand Up @@ -93,8 +84,6 @@ class ServerError(BadStatus):
pass


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

class TaskError(DeepomaticException):
def __init__(self, task):
self.task = task
Expand All @@ -106,8 +95,6 @@ def get_task_id(self):
return self.task['id']


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

class TaskTimeout(DeepomaticException):
def __init__(self, task, retry_error=None):
self.task = task
Expand All @@ -120,11 +107,21 @@ def get_task_id(self):
return self.task['id']


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


class HTTPRetryError(RetryError):
pass
def __str__(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: renaming this could break sentry alert rules, need to pre-update those before merge?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could archive the previous alerts and let it create new ones ?

last_exception = self.last_attempt.exception(timeout=0)
msg = "Last attempt was "
if last_exception is not None:
exception_type = type(last_exception)
msg += f'an exception {exception_type} "{last_exception}"'
else:
last_result = self.last_attempt.result()
if isinstance(last_result, Response):
last_request = last_result.request
msg += f"a Response <status_code={last_result.status_code} method={last_request.method.upper()} url={last_request.url}>"
else:
return super().__str__()
return msg


class TaskRetryError(RetryError):
Expand Down
2 changes: 1 addition & 1 deletion deepomatic/api/http_retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Default(object):
RETRY_TIMEOUT = 60
RETRY_EXP_MAX = 10.
RETRY_EXP_MULTIPLIER = 0.5
RETRY_STATUS_CODES = [500, 502, 503, 504]
RETRY_STATUS_CODES = [502, 503, 504]
RETRY_EXCEPTION_TYPES = (RequestException, )
RETRY_EXCEPTION_TYPES_BLACKLIST = (ValueError, ProxyError, TooManyRedirects, URLRequired)

Expand Down
2 changes: 1 addition & 1 deletion deepomatic/api/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

class InferenceResource(object):
def inference(self, return_task=False, wait_task=True, **kwargs):
assert(self._pk is not None)
assert (self._pk is not None)

inputs = kwargs.pop('inputs', None)
if inputs is None:
Expand Down
2 changes: 1 addition & 1 deletion deepomatic/api/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
###############################################################################

def format_inputs(inputs, data):
assert(isinstance(inputs, list))
assert (isinstance(inputs, list))

data = copy.deepcopy(data)
files = {}
Expand Down
4 changes: 2 additions & 2 deletions deepomatic/api/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def __init__(self):

class UpdatableResource(object):
def update(self, replace=False, content_type='application/json', files=None, **kwargs):
assert(self._pk is not None)
assert (self._pk is not None)

if self._helper.check_query_parameters:
for arg_name in kwargs:
Expand All @@ -78,7 +78,7 @@ def update(self, replace=False, content_type='application/json', files=None, **k

class DeletableResource(object):
def delete(self):
assert(self._pk is not None)
assert (self._pk is not None)
return self._helper.delete(self._uri(pk=self._pk))


Expand Down
2 changes: 1 addition & 1 deletion deepomatic/api/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def retrieve(self, pk):
return self.__class__(self._helper, pk=pk)

def refresh(self):
assert(self._pk is not None)
assert (self._pk is not None)
self._data = self._helper.get(self._uri(pk=self._pk))
return self

Expand Down
2 changes: 1 addition & 1 deletion deepomatic/api/resources/recognition.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def get_base_uri(cls, pk, public=False, **kwargs):
return '/recognition/public/' if public else '/recognition/specs/'

def versions(self, offset=0, limit=100):
assert(self._pk is not None)
assert (self._pk is not None)
return ResourceList(RecognitionVersion, self._helper, self._uri(pk=self._pk, suffix='versions'), offset, limit)


Expand Down
2 changes: 1 addition & 1 deletion deepomatic/api/resources/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def list(self, task_ids):
"""
Returns a list of tasks
"""
assert(isinstance(task_ids, list))
assert (isinstance(task_ids, list))
return super(Task, self).list(task_ids=task_ids)

def wait(self, **retry_kwargs):
Expand Down
6 changes: 3 additions & 3 deletions demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,11 +343,11 @@ def demo(client=None):

# pending_tasks, error_tasks and success_tasks contains the original offset of the input parameter tasks
for pos, pending in pending_tasks:
assert(tasks[pos].pk == pending.pk)
assert (tasks[pos].pk == pending.pk)
for pos, err in error_tasks:
assert(tasks[pos].pk == err.pk)
assert (tasks[pos].pk == err.pk)
for pos, success in success_tasks:
assert(tasks[pos].pk == success.pk)
assert (tasks[pos].pk == success.pk)

###########
# Helpers #
Expand Down
12 changes: 1 addition & 11 deletions deploy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,7 @@ RUN python setup.py bdist_wheel

# ideally use ROOT_IMAGE but it's not yet doable in dmake
# => manually force root image here
FROM python:2.7 as runtime-py2

WORKDIR /app
# don't copy egg there: use universal egg from `build-egg` service at runtime
# prepare egg test: demo.py
COPY --from=build /app/demo.py /app/


# ideally use ROOT_IMAGE but it's not yet doable in dmake
# => manually force root image here
FROM python:3.6 as runtime-py3
FROM python:3.8 as runtime-py3

WORKDIR /app
# don't copy egg there: use universal egg from `build-egg` service at runtime
Expand Down
59 changes: 18 additions & 41 deletions dmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,30 @@ env:
master:
source: ${DEEPOMATIC_CONFIG_DIR}/prod.sh


docker:
base_image:
# This first item is a YAML template named "base_image"
# You can reuse it and override just some values with
# "- <<: *base_image" as used below.
- &base_image
name: deepomatic-client-python
variant: '2.7'
root_image: python:2.7
variant: '3.8'
root_image: python:3.8
copy_files:
- requirements.txt
- requirements.dev.txt
install_scripts:
- deploy/install.sh
# Nothing changes comparing to above, except 'variant' and 'root_image'
- <<: *base_image
variant: '3.4'
root_image: python:3.4
variant: '3.9'
root_image: python:3.9
- <<: *base_image
variant: '3.5'
root_image: python:3.5
variant: '3.10'
root_image: python:3.10
- <<: *base_image
variant: '3.6'
root_image: python:3.6

variant: '3.11'
root_image: python:3.11

services:
- service_name: client
Expand All @@ -47,10 +45,10 @@ services:
dockerfile: deploy/Dockerfile
target: dev
base_image_variant:
- '2.7'
- '3.4'
- '3.5'
- '3.6'
- '3.8'
- '3.9'
- '3.10'
- '3.11'
tests:
commands:
- LOG_LEVEL=DEBUG pytest --junit-xml=junit.xml --cov=. --cov-report=xml:coverage.xml --cov-report html:cover -vv /app/tests
Expand All @@ -63,17 +61,17 @@ services:
- service_name: build-egg
# unit tests must have passed on all supported platforms to build the universal egg
needed_services:
- client:2.7
- client:3.4
- client:3.5
- client:3.6
- client:3.8
- client:3.9
- client:3.10
- client:3.11
config:
docker_image:
build:
context: .
dockerfile: deploy/Dockerfile
target: build
base_image_variant: '3.6'
base_image_variant: '3.8'
tests:
# TODO follow up on https://github.com/Deepomatic/dmake/issues/311
data_volumes:
Expand All @@ -85,27 +83,6 @@ services:
- cp /app/dist/* /dist
- chmod -R a+w /dist

- service_name: test-egg-py2
needed_services:
- build-egg
config:
docker_image:
build:
context: .
dockerfile: deploy/Dockerfile
target: runtime-py2
# only used by dmake shell; bypassed by runtime-py2 Dockerfile target
base_image_variant:
- '2.7'
tests:
data_volumes:
- container_volume: /dist/
source: ./dist/
commands:
- pip install /dist/deepomatic_api-*.whl
- LOG_LEVEL=DEBUG python /app/demo.py


- service_name: test-egg-py3
needed_services:
- build-egg
Expand All @@ -117,7 +94,7 @@ services:
target: runtime-py3
# only used by dmake shell; bypassed by runtime-py3 Dockerfile target
base_image_variant:
- '3.6'
- '3.8'
tests:
data_volumes:
- container_volume: /dist/
Expand Down
10 changes: 5 additions & 5 deletions requirements.dev.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-r requirements.txt
pytest==4.6.5
pytest-cov==2.7.1
pytest-voluptuous==1.1.0
httpretty==0.9.6
flake8==3.8.4
pytest==7.4.3
pytest-cov==4.1.0
pytest-voluptuous==1.2.0
httpretty==1.1.4
flake8==6.1.0
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
numpy>=1.10.0,<2
promise>=2.1,<3
six>=1.10.0,<2
requests>=2.19.0,<3 # will not work below in python3
tenacity>=5.1,<9
12 changes: 5 additions & 7 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,14 @@
long_description_content_type='text/markdown',
data_files=[('', ['requirements.txt'])],
install_requires=requirements,
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
python_requires=">=3.8.*",
classifiers=[
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: what about python 3.12? shipped 2023-10-02

]
)
Loading