diff --git a/Makefile b/Makefile index 866f3c9..02d1a74 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README.md b/README.md index 7585af8..c6252eb 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/deepomatic/api/exceptions.py b/deepomatic/api/exceptions.py index 97df5e4..f16c481 100644 --- a/deepomatic/api/exceptions.py +++ b/deepomatic/api/exceptions.py @@ -26,35 +26,25 @@ from tenacity import RetryError -############################################################################### - 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. @@ -93,8 +83,6 @@ class ServerError(BadStatus): pass -############################################################################### - class TaskError(DeepomaticException): def __init__(self, task): self.task = task @@ -106,8 +94,6 @@ def get_task_id(self): return self.task['id'] -############################################################################### - class TaskTimeout(DeepomaticException): def __init__(self, task, retry_error=None): self.task = task @@ -120,9 +106,6 @@ def get_task_id(self): return self.task['id'] -############################################################################### - - class HTTPRetryError(RetryError): pass diff --git a/deepomatic/api/inference.py b/deepomatic/api/inference.py index 1c94f01..cfd8796 100644 --- a/deepomatic/api/inference.py +++ b/deepomatic/api/inference.py @@ -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: diff --git a/deepomatic/api/inputs.py b/deepomatic/api/inputs.py index 5f0a338..ae1b91f 100644 --- a/deepomatic/api/inputs.py +++ b/deepomatic/api/inputs.py @@ -32,7 +32,7 @@ ############################################################################### def format_inputs(inputs, data): - assert(isinstance(inputs, list)) + assert (isinstance(inputs, list)) data = copy.deepcopy(data) files = {} diff --git a/deepomatic/api/mixins.py b/deepomatic/api/mixins.py index a6857e2..9ddf478 100644 --- a/deepomatic/api/mixins.py +++ b/deepomatic/api/mixins.py @@ -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: @@ -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)) diff --git a/deepomatic/api/resource.py b/deepomatic/api/resource.py index c52c473..c6bab3a 100644 --- a/deepomatic/api/resource.py +++ b/deepomatic/api/resource.py @@ -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 diff --git a/deepomatic/api/resources/recognition.py b/deepomatic/api/resources/recognition.py index 35005a0..5e1140f 100644 --- a/deepomatic/api/resources/recognition.py +++ b/deepomatic/api/resources/recognition.py @@ -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) diff --git a/deepomatic/api/resources/task.py b/deepomatic/api/resources/task.py index 56bc119..52b0f71 100644 --- a/deepomatic/api/resources/task.py +++ b/deepomatic/api/resources/task.py @@ -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): diff --git a/demo.py b/demo.py index 1f7013a..b3650ff 100644 --- a/demo.py +++ b/demo.py @@ -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 # diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 7cb1700..d7272ed 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -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 diff --git a/dmake.yml b/dmake.yml index 473e42f..5788288 100644 --- a/dmake.yml +++ b/dmake.yml @@ -11,7 +11,6 @@ env: master: source: ${DEEPOMATIC_CONFIG_DIR}/prod.sh - docker: base_image: # This first item is a YAML template named "base_image" @@ -19,8 +18,8 @@ docker: # "- <<: *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 @@ -28,15 +27,14 @@ docker: - 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 @@ -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 @@ -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: @@ -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 @@ -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/ diff --git a/requirements.dev.txt b/requirements.dev.txt index a579324..d1c3a38 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -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 diff --git a/requirements.txt b/requirements.txt index 8721b2c..db6096a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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 diff --git a/setup.py b/setup.py index f0d6af7..77c0c66 100644 --- a/setup.py +++ b/setup.py @@ -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', ] ) diff --git a/tests/test_client.py b/tests/test_client.py index d02b315..598cca7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -294,11 +294,11 @@ def test_batch_wait(self, client): # 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) assert inference_schema(2, 0, 'golden retriever', 0.8) == success['data'] # Task* str(): oneliners (easier to parse in log tooling)