Skip to content

Commit d4f75f8

Browse files
Version 2.2.0 changes (#42)
* release notes and guides * get_tasks_count, exception name * version and readme updates
1 parent 8e248f2 commit d4f75f8

8 files changed

+243
-44
lines changed

README.rst

+35-7
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ ____________
2424
.. code-block:: bash
2525
2626
$ pip install --upgrade scaleapi
27-
27+
2828
.. code-block:: bash
2929
3030
$ conda install -c conda-forge scaleapi
@@ -66,7 +66,7 @@ __ https://docs.scale.com/reference
6666
.. code-block:: python
6767
6868
from scaleapi.tasks import TaskType
69-
from scaleapi.exceptions import ScaleDuplicateTask
69+
from scaleapi.exceptions import ScaleDuplicateResource
7070
7171
payload = dict(
7272
project = "test_project",
@@ -86,7 +86,7 @@ __ https://docs.scale.com/reference
8686
8787
try:
8888
client.create_task(TaskType.ImageAnnotation, **payload)
89-
except ScaleDuplicateTask as err:
89+
except ScaleDuplicateResource as err:
9090
print(err.message) # If unique_id is already used for a different task
9191
9292
@@ -149,8 +149,8 @@ Accessing ``task.params`` child objects directly at task level is **deprecated**
149149
task.params["geometries"] # task.geometries is DEPRECATED
150150
task.params["attachment"] # task.attachment is DEPRECATED
151151
152-
List Tasks
153-
^^^^^^^^^^
152+
Retrieve List of Tasks
153+
^^^^^^^^^^^^^^^^^^^^^^
154154

155155
Retrieve a list of `Task` objects, with filters for: ``project_name``, ``batch_name``, ``type``, ``status``,
156156
``review_status``, ``unique_id``, ``completed_after``, ``completed_before``, ``updated_after``, ``updated_before``,
@@ -191,6 +191,28 @@ __ https://docs.scale.com/reference#list-multiple-tasks
191191
task_list = list(tasks)
192192
print(f"{len(task_list))} tasks retrieved")
193193
194+
Get Tasks Count
195+
^^^^^^^^^^^^^^^
196+
197+
``get_tasks_count()`` method returns the number of tasks with the given optional parameters for: ``project_name``, ``batch_name``, ``type``, ``status``,
198+
``review_status``, ``unique_id``, ``completed_after``, ``completed_before``, ``updated_after``, ``updated_before``,
199+
``created_after``, ``created_before`` and ``tags``.
200+
201+
.. code-block :: python
202+
203+
from scaleapi.tasks import TaskReviewStatus, TaskStatus
204+
205+
task_count = client.get_tasks_count(
206+
project_name = "My Project",
207+
created_after = "2020-09-08",
208+
completed_before = "2021-04-01",
209+
status = TaskStatus.Completed,
210+
review_status = TaskReviewStatus.Accepted
211+
)
212+
213+
print(task_count) # 1923
214+
215+
194216
Cancel Task
195217
^^^^^^^^^^^
196218

@@ -214,12 +236,16 @@ __ https://docs.scale.com/reference#batch-creation
214236

215237
.. code-block:: python
216238
217-
client.create_batch(
239+
batch = client.create_batch(
218240
project = "test_project",
219241
callback = "http://www.example.com/callback",
220242
batch_name = "batch_name_01_07_2021"
221243
)
222244
245+
print(batch.name) # batch_name_01_07_2021
246+
247+
Throws ``ScaleDuplicateResource`` exception if a batch with the same name already exists.
248+
223249
Finalize Batch
224250
^^^^^^^^^^^^^^^
225251

@@ -321,6 +347,8 @@ __ https://docs.scale.com/reference#project-creation
321347
322348
print(project.name) # Test_Project
323349
350+
Throws ``ScaleDuplicateResource`` exception if a project with the same name already exists.
351+
324352
Retrieve Project
325353
^^^^^^^^^^^^^^^^
326354

@@ -445,7 +473,7 @@ as a `ScaleException` parent type and child exceptions:
445473
- ``ScaleUnauthorized``: 401 - Unauthorized -- No valid API key provided.
446474
- ``ScaleNotEnabled``: 402 - Not enabled -- Please contact sales@scaleapi.com before creating this type of task.
447475
- ``ScaleResourceNotFound``: 404 - Not Found -- The requested resource doesn't exist.
448-
- ``ScaleDuplicateTask``: 409 - Conflict -- The provided idempotency key or unique_id is already in use for a different request.
476+
- ``ScaleDuplicateResource``: 409 - Conflict -- Object already exists with same name, idempotency key or unique_id.
449477
- ``ScaleTooManyRequests``: 429 - Too Many Requests -- Too many requests hit the API too quickly.
450478
- ``ScaleInternalError``: 500 - Internal Server Error -- We had a problem with our server. Try again later.
451479
- ``ScaleServiceUnavailable``: 503 - Server Timeout From Request Queueing -- Try again later.

docs/migration_guide.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ SDK now supports auto-retry in case of a `408`, `429` or `5xx` error occurs.
8181
### New Exceptions
8282

8383
New error types are introduces if you want to handle specific exception cases.
84-
`ScaleInvalidRequest`, `ScaleUnauthorized`, `ScaleNotEnabled`, `ScaleResourceNotFound`, `ScaleDuplicateTask`, `ScaleTooManyRequests`, `ScaleInternalError` and `ScaleTimeoutError`.
84+
`ScaleInvalidRequest`, `ScaleUnauthorized`, `ScaleNotEnabled`, `ScaleResourceNotFound`, `ScaleDuplicateResource`, `ScaleTooManyRequests`, `ScaleInternalError` and `ScaleTimeoutError`.
8585

8686
All new error types are child of the existing `ScaleException` which can be used to handle all cases.
8787

docs/pypi_update_guide.md

+18-4
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,29 @@ _Creating and deploying a new package version is easy!_
66

77
1. Ensure you're on the latest `master` branch
88

9-
2. Ensure you have access to a PyPI account that is a maintainer of [scaleapi](https://pypi.org/project/scaleapi/) on PyPI
9+
2. Ensure the master already has an incremented version
1010

11-
### Deployment Steps:
11+
3. *(Required if you are manually publishing to PyPI)* Ensure you have access to a PyPI account that is a maintainer of [scaleapi](https://pypi.org/project/scaleapi/) on PyPI
1212

13-
**Step 0: Critical - Bump Project Version**
13+
**How to Bump Project Version**
1414

1515
Ensure `_version.py` has an updated project version. If not, please increment the project version, commit and push the changes.
1616

1717
We use [semantic versioning](https://packaging.python.org/guides/distributing-packages-using-setuptools/#semantic-versioning-preferred). If you are adding a meaningful feature, bump the minor version. If you are fixing a bug, bump the incremental version.
18+
### Deployment:
19+
20+
21+
#### Automated Deployment and Publish with CircleCI:
22+
23+
Our repo already has a publish worklow built into the CircleCI. It's trigerred when there's a new release on GitHub, with a specific version tag.
24+
25+
In order to deploy and publish a new version:
26+
- Create a new [Release](https://github.com/scaleapi/scaleapi-python-client/releases) on GitHub
27+
- Create and assign a new tag in the release page with the following template: `vX.Y.Z` Please make sure `X.Y.Z` is matching the version in the `_version.py`.
28+
- *i.e.* If the version in `_version.py` is **2.3.1** then the tag should be **v2.3.1**
29+
- Provide release notes by following the [Release Notes Template](release_notes_template.md) and filling relevant sections to your changes.
30+
#### *(Unpreferred)* Manual Deployment and Publish:
31+
1832

1933
**Step 1: Run Publish Script**
2034

@@ -36,4 +50,4 @@ SCALE_TEST_API_KEY="{apikey}|{userid}|test" ./publish.sh runtest
3650

3751
**Step 3: Create a New Release**
3852

39-
Create a [new release](https://github.com/scaleapi/scaleapi-python-client/releases/new) on GitHub with a matching version tag _(i.e. v2.0.1)_. Please provide a summary about new features and fixed bugs in the Release Notes.
53+
Create a [new release](https://github.com/scaleapi/scaleapi-python-client/releases/new) on GitHub with a matching version tag _(i.e. v2.0.1)_. Provide release notes by following the [Release Notes Template](release_notes_template.md) and filling relevant sections to your changes.

docs/release_notes_template.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
## Upgrade Steps
2+
- [IF ANY IMMEDIATE ACTION IS REQUIRED]
3+
4+
## Breaking Changes
5+
- [BIG NEW FEATURES]
6+
7+
## New Features
8+
- [ANY NEW FEATURES]
9+
10+
## Bug Fixes
11+
- [IF AN ISSUE IS RESOLVED, PLEASE LINK TO ISSUE#]
12+
13+
## Improvements
14+
- [IMPROVEMENTS ON EXISTING FEATURES]
15+
16+
## Known Issues
17+
- [KEEP SECTION UPDATED WITH KNOWN ISSUES]
18+
19+
## Other Changes and Notes
20+
- [MISC]

scaleapi/__init__.py

+156-25
Original file line numberDiff line numberDiff line change
@@ -262,32 +262,24 @@ def get_tasks(
262262
next_token = None
263263
has_more = True
264264

265-
while has_more:
266-
tasks_args = {
267-
"next_token": next_token,
268-
"start_time": created_after,
269-
"end_time": created_before,
270-
"project": project_name,
271-
"batch": batch_name,
272-
"completed_before": completed_before,
273-
"completed_after": completed_after,
274-
"tags": tags,
275-
"updated_before": updated_before,
276-
"updated_after": updated_after,
277-
"unique_id": unique_id,
278-
}
279-
280-
if status:
281-
tasks_args["status"] = status.value
282-
if task_type:
283-
tasks_args["type"] = task_type.value
284-
if review_status:
285-
if isinstance(review_status, List):
286-
value = ",".join(map(lambda x: x.value, review_status))
287-
else:
288-
value = review_status.value
265+
tasks_args = self._process_tasks_endpoint_args(
266+
project_name,
267+
batch_name,
268+
task_type,
269+
status,
270+
review_status,
271+
unique_id,
272+
completed_after,
273+
completed_before,
274+
updated_after,
275+
updated_before,
276+
created_after,
277+
created_before,
278+
tags,
279+
)
289280

290-
tasks_args["customer_review_status"] = value
281+
while has_more:
282+
tasks_args["next_token"] = next_token
291283

292284
tasks = self.tasks(**tasks_args)
293285
for task in tasks.docs:
@@ -296,6 +288,145 @@ def get_tasks(
296288
next_token = tasks.next_token
297289
has_more = tasks.has_more
298290

291+
def get_tasks_count(
292+
self,
293+
project_name: str,
294+
batch_name: str = None,
295+
task_type: TaskType = None,
296+
status: TaskStatus = None,
297+
review_status: Union[List[TaskReviewStatus], TaskReviewStatus] = None,
298+
unique_id: Union[List[str], str] = None,
299+
completed_after: str = None,
300+
completed_before: str = None,
301+
updated_after: str = None,
302+
updated_before: str = None,
303+
created_after: str = None,
304+
created_before: str = None,
305+
tags: Union[List[str], str] = None,
306+
) -> int:
307+
"""Returns number of tasks with given filters.
308+
309+
Args:
310+
project_name (str):
311+
Project Name
312+
313+
batch_name (str, optional):
314+
Batch Name
315+
316+
task_type (TaskType, optional):
317+
Task type to filter i.e. `TaskType.TextCollection`
318+
319+
status (TaskStatus, optional):
320+
Task status i.e. `TaskStatus.Completed`
321+
322+
review_status (List[TaskReviewStatus] | TaskReviewStatus):
323+
The status of the audit result of the task.
324+
Input can be a single element or a list of
325+
TaskReviewStatus. i.e. `TaskReviewStatus.Accepted` to
326+
filter the tasks that you accepted after audit.
327+
328+
unique_id (List[str] | str, optional):
329+
The unique_id of a task. Multiple unique IDs can be
330+
specified at the same time as a list.
331+
332+
completed_after (str, optional):
333+
The minimum value of `completed_at` in UTC timezone
334+
ISO format: 'YYYY-MM-DD HH:MM:SS.mmmmmm'
335+
336+
completed_before (str, optional):
337+
The maximum value of `completed_at` in UTC timezone
338+
ISO format: 'YYYY-MM-DD HH:MM:SS.mmmmmm'
339+
340+
updated_after (str, optional):
341+
The minimum value of `updated_at` in UTC timezone
342+
ISO format: 'YYYY-MM-DD HH:MM:SS.mmmmmm'
343+
344+
updated_before (str, optional):
345+
The maximum value of `updated_at` in UTC timezone
346+
ISO format: 'YYYY-MM-DD HH:MM:SS.mmmmmm'
347+
348+
created_after (str, optional):
349+
The minimum value of `created_at` in UTC timezone
350+
ISO format: 'YYYY-MM-DD HH:MM:SS.mmmmmm'
351+
352+
created_before (str, optional):
353+
The maximum value of `created_at` in UTC timezone
354+
ISO format: 'YYYY-MM-DD HH:MM:SS.mmmmmm'
355+
356+
tags (List[str] | str, optional):
357+
The tags of a task; multiple tags can be
358+
specified as a list.
359+
360+
Returns:
361+
int:
362+
Returns number of tasks
363+
"""
364+
365+
tasks_args = self._process_tasks_endpoint_args(
366+
project_name,
367+
batch_name,
368+
task_type,
369+
status,
370+
review_status,
371+
unique_id,
372+
completed_after,
373+
completed_before,
374+
updated_after,
375+
updated_before,
376+
created_after,
377+
created_before,
378+
tags,
379+
)
380+
381+
tasks_args["limit"] = 1
382+
383+
tasks = self.tasks(**tasks_args)
384+
return tasks.total
385+
386+
@staticmethod
387+
def _process_tasks_endpoint_args(
388+
project_name: str,
389+
batch_name: str = None,
390+
task_type: TaskType = None,
391+
status: TaskStatus = None,
392+
review_status: Union[List[TaskReviewStatus], TaskReviewStatus] = None,
393+
unique_id: Union[List[str], str] = None,
394+
completed_after: str = None,
395+
completed_before: str = None,
396+
updated_after: str = None,
397+
updated_before: str = None,
398+
created_after: str = None,
399+
created_before: str = None,
400+
tags: Union[List[str], str] = None,
401+
):
402+
"""Generates args for /tasks endpoint."""
403+
tasks_args = {
404+
"start_time": created_after,
405+
"end_time": created_before,
406+
"project": project_name,
407+
"batch": batch_name,
408+
"completed_before": completed_before,
409+
"completed_after": completed_after,
410+
"tags": tags,
411+
"updated_before": updated_before,
412+
"updated_after": updated_after,
413+
"unique_id": unique_id,
414+
}
415+
416+
if status:
417+
tasks_args["status"] = status.value
418+
if task_type:
419+
tasks_args["type"] = task_type.value
420+
if review_status:
421+
if isinstance(review_status, List):
422+
value = ",".join(map(lambda x: x.value, review_status))
423+
else:
424+
value = review_status.value
425+
426+
tasks_args["customer_review_status"] = value
427+
428+
return tasks_args
429+
299430
def create_task(self, task_type: TaskType, **kwargs) -> Task:
300431
"""This method can be used for any Scale supported task type.
301432
Parameters may differ based on the given task_type.

scaleapi/_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "2.1.0"
1+
__version__ = "2.2.0"
22
__package_name__ = "scaleapi"

scaleapi/exceptions.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ class ScaleResourceNotFound(ScaleException):
4848
code = 404
4949

5050

51-
class ScaleDuplicateTask(ScaleException):
52-
"""409 - Conflict -- The provided idempotency key or unique_id is
53-
already in use for a different request.
51+
class ScaleDuplicateResource(ScaleException):
52+
"""409 - Conflict -- Object already exists with same name,
53+
idempotency key or unique_id.
5454
"""
5555

5656
code = 409
@@ -89,7 +89,7 @@ class ScaleTimeoutError(ScaleException):
8989
ScaleUnauthorized.code: ScaleUnauthorized,
9090
ScaleNotEnabled.code: ScaleNotEnabled,
9191
ScaleResourceNotFound.code: ScaleResourceNotFound,
92-
ScaleDuplicateTask.code: ScaleDuplicateTask,
92+
ScaleDuplicateResource.code: ScaleDuplicateResource,
9393
ScaleTooManyRequests.code: ScaleTooManyRequests,
9494
ScaleInternalError.code: ScaleInternalError,
9595
ScaleTimeoutError.code: ScaleTimeoutError,

0 commit comments

Comments
 (0)