From 195b96abd9bc0567f0b5246723db128e04c322b9 Mon Sep 17 00:00:00 2001 From: Arthur Liou <102243981+artliou-scale@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:12:20 -0700 Subject: [PATCH] Update cancel_task to add clearUniqueId option (#53) * Update cancel_task to add clearUniqueId option * new endpoints and readme updates Co-authored-by: Fatih Kurtoglu --- README.rst | 45 +++++++++++++++++++++++++++++++++++++++++++- scaleapi/__init__.py | 40 +++++++++++++++++++++++++++++++++++++-- scaleapi/_version.py | 2 +- scaleapi/api.py | 8 +++++++- scaleapi/tasks.py | 12 ++++++++++-- tests/test_client.py | 25 ++++++++++++++++++++---- 6 files changed, 121 insertions(+), 11 deletions(-) diff --git a/README.rst b/README.rst index 9c27fce..5882de3 100644 --- a/README.rst +++ b/README.rst @@ -228,6 +228,49 @@ __ https://docs.scale.com/reference#cancel-task task = client.cancel_task('30553edd0b6a93f8f05f0fee') + # If you also want to clear 'unique_id' of a task while canceling + task = client.cancel_task('30553edd0b6a93f8f05f0fee', clear_unique_id=True) + + # cancel() is also available on task object + task = client.get_task('30553edd0b6a93f8f05f0fee') + task.cancel() + + # If you also want to clear 'unique_id' of a task while canceling + task.cancel(clear_unique_id=True) + + +Update A Task's Unique Id +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Update a given task's unique_id. Check out `Scale's API documentation`__ for more information. + +__ https://docs.scale.com/reference/update-task-unique-id + +.. code-block :: python + + task = client.update_task_unique_id('30553edd0b6a93f8f05f0fee', "new_unique_id") + + # update_unique_id() is also available on task object + task = client.get_task('30553edd0b6a93f8f05f0fee') + task.update_unique_id("new_unique_id") + + +Clear A Task's Unique Id +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Clear a given task's unique_id. Check out `Scale's API documentation`__ for more information. + +__ https://docs.scale.com/reference/delete-task-unique-id + +.. code-block :: python + + task = client.clear_task_unique_id('30553edd0b6a93f8f05f0fee') + + # clear_unique_id() is also available on task object + task = client.get_task('30553edd0b6a93f8f05f0fee') + task.clear_unique_id() + + Batches _______ @@ -351,7 +394,7 @@ __ https://docs.scale.com/reference#project-creation print(project.name) # Test_Project -Specify ``rapid=true`` for Rapid projects and ``studio=true`` for Studio projects. Throws ``ScaleDuplicateResource`` exception if a project with the same name already exists. +Specify ``rapid=true`` for Rapid projects and ``studio=true`` for Studio projects. Throws ``ScaleDuplicateResource`` exception if a project with the same name already exists. Retrieve Project ^^^^^^^^^^^^^^^^ diff --git a/scaleapi/__init__.py b/scaleapi/__init__.py index 99c4e08..79e83e0 100644 --- a/scaleapi/__init__.py +++ b/scaleapi/__init__.py @@ -64,20 +64,56 @@ def get_task(self, task_id: str) -> Task: endpoint = f"task/{task_id}" return Task(self.api.get_request(endpoint), self) - def cancel_task(self, task_id: str) -> Task: + def cancel_task(self, task_id: str, clear_unique_id: bool = False) -> Task: """Cancels a task and returns the associated task. Raises a ScaleException if it has already been canceled. Args: task_id (str): Task id + clear_unique_id (boolean): + Option to clear unique id when the task is deleted Returns: Task """ - endpoint = f"task/{task_id}/cancel" + if clear_unique_id: + endpoint = f"task/{task_id}/cancel?clear_unique_id=true" + else: + endpoint = f"task/{task_id}/cancel" return Task(self.api.post_request(endpoint), self) + def update_task_unique_id(self, task_id: str, unique_id: str) -> Task: + """Updates a task's unique_id and returns the associated task. + Raises a ScaleDuplicateResource exception if unique_id + is already in use. + + Args: + task_id (str): + Task id + unique_id (str): + unique_id to set + + Returns: + Task + """ + payload = dict(unique_id=unique_id) + endpoint = f"task/{task_id}/unique_id" + return Task(self.api.post_request(endpoint, body=payload), self) + + def clear_task_unique_id(self, task_id: str) -> Task: + """Clears a task's unique_id and returns the associated task. + + Args: + task_id (str): + Task id + + Returns: + Task + """ + endpoint = f"task/{task_id}/unique_id" + return Task(self.api.delete_request(endpoint), self) + def tasks(self, **kwargs) -> Tasklist: """Returns a list of your tasks. Returns up to 100 at a time, to get more, use the diff --git a/scaleapi/_version.py b/scaleapi/_version.py index f63d0be..5303485 100644 --- a/scaleapi/_version.py +++ b/scaleapi/_version.py @@ -1,2 +1,2 @@ -__version__ = "2.8.0" +__version__ = "2.9.0" __package_name__ = "scaleapi" diff --git a/scaleapi/api.py b/scaleapi/api.py index d588a1d..a440f43 100644 --- a/scaleapi/api.py +++ b/scaleapi/api.py @@ -13,7 +13,7 @@ HTTP_TOTAL_RETRIES = 3 # Number of total retries HTTP_RETRY_BACKOFF_FACTOR = 2 # Wait 1, 2, 4 seconds between retries HTTP_STATUS_FORCE_LIST = [408, 429] + list(range(500, 531)) -HTTP_RETRY_ALLOWED_METHODS = frozenset({"GET", "POST"}) +HTTP_RETRY_ALLOWED_METHODS = frozenset({"GET", "POST", "DELETE"}) class Api: @@ -134,6 +134,12 @@ def post_request(self, endpoint, body=None, files=None, data=None): data=data, ) + def delete_request(self, endpoint, params=None): + """Generic DELETE Request Wrapper""" + return self._api_request( + "DELETE", endpoint, headers=self._headers, auth=self._auth, params=params + ) + @staticmethod def _generate_useragent(extension: str = None) -> str: """Generates UserAgent parameter with module, Python diff --git a/scaleapi/tasks.py b/scaleapi/tasks.py index 919e6e9..12fcddb 100644 --- a/scaleapi/tasks.py +++ b/scaleapi/tasks.py @@ -84,6 +84,14 @@ def refresh(self): """Refreshes the task details.""" self._json = self._client.get_task(self.id).as_dict() - def cancel(self): + def cancel(self, clear_unique_id: bool = False): """Cancels the task""" - self._client.cancel_task(self.id) + self._client.cancel_task(self.id, clear_unique_id) + + def update_unique_id(self, unique_id: str): + """Updates unique_id of a task""" + self._client.update_task_unique_id(self.id, unique_id) + + def clear_unique_id(self): + """Clears unique_id of a task""" + self._client.clear_task_unique_id(self.id) diff --git a/tests/test_client.py b/tests/test_client.py index 02ad4df..48b9b7f 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -69,11 +69,28 @@ def make_a_task(unique_id: str = None, batch: str = None): return client.create_task(TaskType.ImageAnnotation, **args) -def test_uniquekey_fail(): - unique_key = str(uuid.uuid4()) - make_a_task(unique_key) +def test_unique_id_fail(): + unique_id = str(uuid.uuid4()) + make_a_task(unique_id) with pytest.raises(ScaleDuplicateResource): - make_a_task(unique_key) + make_a_task(unique_id) + + +def test_update_unique_id(): + unique_id = str(uuid.uuid4()) + task = make_a_task(unique_id) + unique_id_new = str(uuid.uuid4()) + + task = client.update_task_unique_id(task.id, unique_id_new) + assert unique_id_new == task.as_dict()["unique_id"] + + +def test_clear_unique_id(): + unique_id = str(uuid.uuid4()) + task = make_a_task(unique_id) + + task = client.clear_task_unique_id(task.id) + assert "unique_id" not in task.as_dict() def test_categorize_ok():