diff --git a/docs/en/_includes/toloka-kit-reference-toc.yaml b/docs/en/_includes/toloka-kit-reference-toc.yaml index d07ad37d..7333c14b 100644 --- a/docs/en/_includes/toloka-kit-reference-toc.yaml +++ b/docs/en/_includes/toloka-kit-reference-toc.yaml @@ -26,6 +26,8 @@ items: items: - name: archive_app_project href: ../toloka-kit/reference/toloka.client.TolokaClient.archive_app_project.md + - name: unarchive_app_project + href: ../toloka-kit/reference/toloka.client.TolokaClient.unarchive_app_project.md - name: create_app_batch href: ../toloka-kit/reference/toloka.client.TolokaClient.create_app_batch.md - name: patch_app_batch @@ -66,8 +68,12 @@ items: href: ../toloka-kit/reference/toloka.client.TolokaClient.stop_app_batch.md - name: resume_app_batch href: ../toloka-kit/reference/toloka.client.TolokaClient.resume_app_batch.md - - name: unarchive_app_project - href: ../toloka-kit/reference/toloka.client.TolokaClient.unarchive_app_project.md + - name: archive_app_batch + href: ../toloka-kit/reference/toloka.client.TolokaClient.archive_app_batch.md + - name: unarchive_app_batch + href: ../toloka-kit/reference/toloka.client.TolokaClient.unarchive_app_batch.md + - name: start_sync_batch_processing + href: ../toloka-kit/reference/toloka.client.TolokaClient.start_sync_batch_processing.md - name: assignments items: - name: accept_assignment @@ -408,6 +414,8 @@ items: - name: _AppError href: ../toloka-kit/reference/toloka.client.app._AppError.md hidden: true + - name: BaseApp + href: ../toloka-kit/reference/toloka.client.app.BaseApp.md - name: App href: ../toloka-kit/reference/toloka.client.app.App.md - name: AppLightestResult @@ -418,8 +426,13 @@ items: - name: AppBatch.Status href: ../toloka-kit/reference/toloka.client.app.AppBatch.Status.md hidden: true + - name: AppBatch.PriorityOrder + href: ../toloka-kit/reference/toloka.client.app.AppBatch.PriorityOrder.md + hidden: true - name: AppBatchCreateRequest href: ../toloka-kit/reference/toloka.client.app.AppBatchCreateRequest.md + - name: SyncBatchCreateRequest + href: ../toloka-kit/reference/toloka.client.app.SyncBatchCreateRequest.md - name: AppItemImport href: ../toloka-kit/reference/toloka.client.app.AppItemImport.md hidden: true @@ -428,6 +441,8 @@ items: - name: AppItem.Status href: ../toloka-kit/reference/toloka.client.app.AppItem.Status.md hidden: true + - name: AppItemCreateRequest + href: ../toloka-kit/reference/toloka.client.app.AppItemCreateRequest.md - name: AppItemsCreateRequest href: ../toloka-kit/reference/toloka.client.app.AppItemsCreateRequest.md - name: AppProject @@ -1999,6 +2014,8 @@ items: items: - name: archive_app_project href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.archive_app_project.md + - name: unarchive_app_project + href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.unarchive_app_project.md - name: create_app_batch href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.create_app_batch.md - name: patch_app_batch @@ -2039,8 +2056,12 @@ items: href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.stop_app_batch.md - name: resume_app_batch href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.resume_app_batch.md - - name: unarchive_app_project - href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.unarchive_app_project.md + - name: archive_app_batch + href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.archive_app_batch.md + - name: unarchive_app_batch + href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.unarchive_app_batch.md + - name: start_sync_batch_processing + href: ../toloka-kit/reference/toloka.async_client.client.AsyncTolokaClient.start_sync_batch_processing.md - name: assignments items: - name: accept_assignment diff --git a/misc/stubmaker/src/tk_stubgen/builder/tk_representations_tree_builder.py b/misc/stubmaker/src/tk_stubgen/builder/tk_representations_tree_builder.py index 3ae75383..1840ce6b 100644 --- a/misc/stubmaker/src/tk_stubgen/builder/tk_representations_tree_builder.py +++ b/misc/stubmaker/src/tk_stubgen/builder/tk_representations_tree_builder.py @@ -1,4 +1,5 @@ import inspect +from typing import Any import attr from stubmaker.builder.common import BaseDefinition, Node @@ -29,4 +30,8 @@ def get_literal(self, node): if node.obj is attr.NOTHING: node.obj = ... + # stubmaker does not support forward references properly + if isinstance(node.obj, str) and node.obj == 'typing.ClassVar[Retry]': + node.obj = Any + return super().get_literal(node) diff --git a/misc/stubmaker/src/tk_stubgen/viewers/stub_viewer.py b/misc/stubmaker/src/tk_stubgen/viewers/stub_viewer.py index 493ca391..7a37cc97 100644 --- a/misc/stubmaker/src/tk_stubgen/viewers/stub_viewer.py +++ b/misc/stubmaker/src/tk_stubgen/viewers/stub_viewer.py @@ -1,6 +1,8 @@ __all__ = [ 'TolokaKitStubViewer', ] + +from stubmaker.builder.literals import TypeHintLiteral from stubmaker.viewers.common import add_inherited_singledispatchmethod from stubmaker.viewers.stub_viewer import StubViewer from stubmaker.viewers.util import indent diff --git a/src/async_client/client.pyi b/src/async_client/client.pyi index 567908f4..7db0a651 100644 --- a/src/async_client/client.pyi +++ b/src/async_client/client.pyi @@ -5359,7 +5359,7 @@ class AsyncTolokaClient: self, request: toloka.client.search_requests.AppSearchRequest, batch_size: typing.Optional[int] = None - ) -> toloka.util.async_utils.AsyncGenAdapter[toloka.client.app.App, None]: + ) -> toloka.util.async_utils.AsyncGenAdapter[toloka.client.app.BaseApp, None]: """Finds all App solutions that match certain criteria. `get_apps` returns a generator. You can iterate over all found solutions using the generator. Several requests to the Toloka server are possible while iterating. @@ -5392,7 +5392,7 @@ class AsyncTolokaClient: id_gt: typing.Optional[str] = None, id_gte: typing.Optional[str] = None, batch_size: typing.Optional[int] = None - ) -> toloka.util.async_utils.AsyncGenAdapter[toloka.client.app.App, None]: + ) -> toloka.util.async_utils.AsyncGenAdapter[toloka.client.app.BaseApp, None]: """Finds all App solutions that match certain criteria. `get_apps` returns a generator. You can iterate over all found solutions using the generator. Several requests to the Toloka server are possible while iterating. @@ -5607,7 +5607,9 @@ class AsyncTolokaClient: async def create_app_item( self, app_project_id: str, - app_item: toloka.client.app.AppItem + app_item: toloka.client.app.AppItem, + *, + force_new_original: typing.Optional[bool] = None ) -> toloka.client.app.AppItem: """Creates an App task item in Toloka. @@ -5630,6 +5632,8 @@ class AsyncTolokaClient: Args: app_project_id: The ID of the App project to create the item in. app_item: The task item with parameters. + force_new_original: Whether to enable or disable the deduplication for the item in the request. + When set to true, the item will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. Returns: AppItem: Created App task item with updated parameters. @@ -5642,7 +5646,8 @@ class AsyncTolokaClient: app_project_id: str, *, batch_id: typing.Optional[str] = None, - input_data: typing.Optional[typing.Dict[str, typing.Any]] = None + input_data: typing.Optional[typing.Dict[str, typing.Any]] = None, + force_new_original: typing.Optional[bool] = None ) -> toloka.client.app.AppItem: """Creates an App task item in Toloka. @@ -5665,6 +5670,8 @@ class AsyncTolokaClient: Args: app_project_id: The ID of the App project to create the item in. app_item: The task item with parameters. + force_new_original: Whether to enable or disable the deduplication for the item in the request. + When set to true, the item will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. Returns: AppItem: Created App task item with updated parameters. @@ -5707,7 +5714,9 @@ class AsyncTolokaClient: app_project_id: str, *, batch_id: typing.Optional[str] = None, - items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None + items: typing.List[typing.Dict[str, typing.Any]], + force_new_original: typing.Optional[bool] = None, + ignore_errors: typing.Optional[bool] = None ) -> typing.List[str]: """Creates task items in an App project in Toloka and adds them to an existing batch. @@ -5955,7 +5964,10 @@ class AsyncTolokaClient: app_project_id: str, *, name: typing.Optional[str] = None, - items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None + items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None, + priority_order: typing.Optional[toloka.client.app.AppBatch.PriorityOrder] = None, + force_new_original: typing.Optional[bool] = None, + ignore_errors: typing.Optional[bool] = None ) -> toloka.client.app.AppBatch: """Creates a batch with task items in an App project in Toloka. @@ -6041,7 +6053,8 @@ class AsyncTolokaClient: app_project_id: str, batch_id: str, *, - name: typing.Optional[str] = None + name: typing.Optional[str] = None, + priority_order: typing.Optional[toloka.client.app.AppBatch.PriorityOrder] = None ) -> toloka.client.app.AppBatch: """Updates an App batch. @@ -6065,11 +6078,55 @@ class AsyncTolokaClient: """ ... + async def archive_app_batch( + self, + app_project_id: str, + batch_id: str + ) -> None: + """Archives the batch with the ID specified in the request to hide its data. + + You can archive the batches which are not currently being processed (are not in the `PROCESSING` status). You + must stop the batches before archiving them. The batch gets the `ARCHIVE` status. + + Example: + >>> toloka_client.archive_app_batch( + >>> app_project_id='Q2d15QBjpwWuDz8Z321g', + >>> batch_id='4Va2BBWKL88S4QyAgVje' + >>> ) + ... + + Args: + app_project_id: The ID of the project with which the batch is associated. + batch_id: The ID of the batch you want to archive. + """ + ... + + async def unarchive_app_batch( + self, + app_project_id: str, + batch_id: str + ) -> None: + """Changes the batch status to the last one it had before archiving. After the operation, you can process the + batch again. + + Example: + >>> toloka_client.unarchive_app_batch( + >>> app_project_id='Q2d15QBjpwWuDz8Z321g', + >>> batch_id='4Va2BBWKL88S4QyAgVje' + >>> ) + ... + + Args: + app_project_id: The ID of the project with which the batch is associated. + batch_id: The ID of the batch you want to unarchive. + """ + ... + async def start_app_batch( self, app_project_id: str, batch_id: str - ): + ) -> None: """Launches annotation of a batch of task items in an App project. Example: @@ -6085,11 +6142,28 @@ class AsyncTolokaClient: """ ... + async def start_sync_batch_processing( + self, + app_project_id: str, + request: toloka.client.app.SyncBatchCreateRequest + ) -> toloka.client.app.AppBatch: + """Starts processing the batch with the ID specified in the request. + + This batch processing is applicable for solutions which use synchronous protocols only. + + Args: + app_project_id: The ID of the project with which the batch is associated. + + Returns: + AppBatch: The response to the request to start sync batch processing. + """ + ... + async def stop_app_batch( self, app_project_id: str, batch_id: str - ): + ) -> None: """Stops annotation of a batch of task items in an App project. Processing can be stopped only for the batch with the `PROCESSING` status. @@ -6111,7 +6185,7 @@ class AsyncTolokaClient: self, app_project_id: str, batch_id: str - ): + ) -> None: """Resumes annotation of a batch of task items in an App project. Processing can be resumed only for the batch with the `STOPPING` or `STOPPED` status. diff --git a/src/client/__init__.py b/src/client/__init__.py index f82817d8..9e962f30 100644 --- a/src/client/__init__.py +++ b/src/client/__init__.py @@ -135,11 +135,14 @@ from .app import ( App, AppItem, + AppItemCreateRequest, AppProject, AppBatch, AppBatchPatch, AppBatchCreateRequest, AppItemsCreateRequest, + BaseApp, + SyncBatchCreateRequest, ) from .assignment import Assignment, AssignmentPatch, GetAssignmentsTsvParameters from .attachment import Attachment @@ -4004,7 +4007,7 @@ def get_apps( self, request: search_requests.AppSearchRequest, batch_size: Optional[int] = None - ) -> Generator[App, None, None]: + ) -> Generator[BaseApp, None, None]: """Finds all App solutions that match certain criteria. `get_apps` returns a generator. You can iterate over all found solutions using the generator. Several requests to the Toloka server are possible while iterating. @@ -4122,7 +4125,13 @@ def get_app_items( @expand('app_item') @add_headers('client') - def create_app_item(self, app_project_id: str, app_item: AppItem) -> AppItem: + def create_app_item( + self, + app_project_id: str, + app_item: AppItem, + *, + force_new_original: Optional[bool] = None, + ) -> AppItem: """Creates an App task item in Toloka. Example: @@ -4144,11 +4153,18 @@ def create_app_item(self, app_project_id: str, app_item: AppItem) -> AppItem: Args: app_project_id: The ID of the App project to create the item in. app_item: The task item with parameters. + force_new_original: Whether to enable or disable the deduplication for the item in the request. + When set to true, the item will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. Returns: AppItem: Created App task item with updated parameters. """ - response = self._request('post', f'/app/v0/app-projects/{app_project_id}/items', json=unstructure(app_item)) + request = AppItemCreateRequest( + batch_id=app_item.batch_id, + input_data=app_item.input_data, + force_new_original=force_new_original + ) + response = self._request('post', f'/app/v0/app-projects/{app_project_id}/items', json=unstructure(request)) return structure(response, AppItem) @expand('request') @@ -4352,7 +4368,47 @@ def patch_app_batch(self, app_project_id: str, batch_id: str, patch: AppBatchPat return structure(response, AppBatch) @add_headers('client') - def start_app_batch(self, app_project_id: str, batch_id: str): + def archive_app_batch(self, app_project_id: str, batch_id: str) -> None: + """Archives the batch with the ID specified in the request to hide its data. + + You can archive the batches which are not currently being processed (are not in the `PROCESSING` status). You + must stop the batches before archiving them. The batch gets the `ARCHIVE` status. + + Example: + >>> toloka_client.archive_app_batch( + >>> app_project_id='Q2d15QBjpwWuDz8Z321g', + >>> batch_id='4Va2BBWKL88S4QyAgVje' + >>> ) + ... + + Args: + app_project_id: The ID of the project with which the batch is associated. + batch_id: The ID of the batch you want to archive. + """ + self._raw_request('post', f'/app/v0/app-projects/{app_project_id}/batches/{batch_id}/archive') + return + + @add_headers('client') + def unarchive_app_batch(self, app_project_id: str, batch_id: str) -> None: + """Changes the batch status to the last one it had before archiving. After the operation, you can process the + batch again. + + Example: + >>> toloka_client.unarchive_app_batch( + >>> app_project_id='Q2d15QBjpwWuDz8Z321g', + >>> batch_id='4Va2BBWKL88S4QyAgVje' + >>> ) + ... + + Args: + app_project_id: The ID of the project with which the batch is associated. + batch_id: The ID of the batch you want to unarchive. + """ + self._raw_request('post', f'/app/v0/app-projects/{app_project_id}/batches/{batch_id}/unarchive') + return + + @add_headers('client') + def start_app_batch(self, app_project_id: str, batch_id: str) -> None: """Launches annotation of a batch of task items in an App project. Example: @@ -4370,7 +4426,27 @@ def start_app_batch(self, app_project_id: str, batch_id: str): return @add_headers('client') - def stop_app_batch(self, app_project_id: str, batch_id: str): + def start_sync_batch_processing(self, app_project_id: str, request: SyncBatchCreateRequest) -> AppBatch: + """Starts processing the batch with the ID specified in the request. + + This batch processing is applicable for solutions which use synchronous protocols only. + + Args: + app_project_id: The ID of the project with which the batch is associated. + + Returns: + AppBatch: The response to the request to start sync batch processing. + """ + + response = self._request( + 'post', + f'/app/v0/app-projects/{app_project_id}/batches/sync', + json=unstructure(request), + ) + return AppBatch.structure(response) + + @add_headers('client') + def stop_app_batch(self, app_project_id: str, batch_id: str) -> None: """Stops annotation of a batch of task items in an App project. Processing can be stopped only for the batch with the `PROCESSING` status. @@ -4390,7 +4466,7 @@ def stop_app_batch(self, app_project_id: str, batch_id: str): return @add_headers('client') - def resume_app_batch(self, app_project_id: str, batch_id: str): + def resume_app_batch(self, app_project_id: str, batch_id: str) -> None: """Resumes annotation of a batch of task items in an App project. Processing can be resumed only for the batch with the `STOPPING` or `STOPPED` status. diff --git a/src/client/__init__.pyi b/src/client/__init__.pyi index 96598fce..39d8cb68 100644 --- a/src/client/__init__.pyi +++ b/src/client/__init__.pyi @@ -5589,7 +5589,7 @@ class TolokaClient: self, request: toloka.client.search_requests.AppSearchRequest, batch_size: typing.Optional[int] = None - ) -> typing.Generator[toloka.client.app.App, None, None]: + ) -> typing.Generator[toloka.client.app.BaseApp, None, None]: """Finds all App solutions that match certain criteria. `get_apps` returns a generator. You can iterate over all found solutions using the generator. Several requests to the Toloka server are possible while iterating. @@ -5622,7 +5622,7 @@ class TolokaClient: id_gt: typing.Optional[str] = None, id_gte: typing.Optional[str] = None, batch_size: typing.Optional[int] = None - ) -> typing.Generator[toloka.client.app.App, None, None]: + ) -> typing.Generator[toloka.client.app.BaseApp, None, None]: """Finds all App solutions that match certain criteria. `get_apps` returns a generator. You can iterate over all found solutions using the generator. Several requests to the Toloka server are possible while iterating. @@ -5837,7 +5837,9 @@ class TolokaClient: def create_app_item( self, app_project_id: str, - app_item: toloka.client.app.AppItem + app_item: toloka.client.app.AppItem, + *, + force_new_original: typing.Optional[bool] = None ) -> toloka.client.app.AppItem: """Creates an App task item in Toloka. @@ -5860,6 +5862,8 @@ class TolokaClient: Args: app_project_id: The ID of the App project to create the item in. app_item: The task item with parameters. + force_new_original: Whether to enable or disable the deduplication for the item in the request. + When set to true, the item will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. Returns: AppItem: Created App task item with updated parameters. @@ -5872,7 +5876,8 @@ class TolokaClient: app_project_id: str, *, batch_id: typing.Optional[str] = None, - input_data: typing.Optional[typing.Dict[str, typing.Any]] = None + input_data: typing.Optional[typing.Dict[str, typing.Any]] = None, + force_new_original: typing.Optional[bool] = None ) -> toloka.client.app.AppItem: """Creates an App task item in Toloka. @@ -5895,6 +5900,8 @@ class TolokaClient: Args: app_project_id: The ID of the App project to create the item in. app_item: The task item with parameters. + force_new_original: Whether to enable or disable the deduplication for the item in the request. + When set to true, the item will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. Returns: AppItem: Created App task item with updated parameters. @@ -5937,7 +5944,9 @@ class TolokaClient: app_project_id: str, *, batch_id: typing.Optional[str] = None, - items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None + items: typing.List[typing.Dict[str, typing.Any]], + force_new_original: typing.Optional[bool] = None, + ignore_errors: typing.Optional[bool] = None ) -> typing.List[str]: """Creates task items in an App project in Toloka and adds them to an existing batch. @@ -6185,7 +6194,10 @@ class TolokaClient: app_project_id: str, *, name: typing.Optional[str] = None, - items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None + items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None, + priority_order: typing.Optional[toloka.client.app.AppBatch.PriorityOrder] = None, + force_new_original: typing.Optional[bool] = None, + ignore_errors: typing.Optional[bool] = None ) -> toloka.client.app.AppBatch: """Creates a batch with task items in an App project in Toloka. @@ -6271,7 +6283,8 @@ class TolokaClient: app_project_id: str, batch_id: str, *, - name: typing.Optional[str] = None + name: typing.Optional[str] = None, + priority_order: typing.Optional[toloka.client.app.AppBatch.PriorityOrder] = None ) -> toloka.client.app.AppBatch: """Updates an App batch. @@ -6295,11 +6308,55 @@ class TolokaClient: """ ... + def archive_app_batch( + self, + app_project_id: str, + batch_id: str + ) -> None: + """Archives the batch with the ID specified in the request to hide its data. + + You can archive the batches which are not currently being processed (are not in the `PROCESSING` status). You + must stop the batches before archiving them. The batch gets the `ARCHIVE` status. + + Example: + >>> toloka_client.archive_app_batch( + >>> app_project_id='Q2d15QBjpwWuDz8Z321g', + >>> batch_id='4Va2BBWKL88S4QyAgVje' + >>> ) + ... + + Args: + app_project_id: The ID of the project with which the batch is associated. + batch_id: The ID of the batch you want to archive. + """ + ... + + def unarchive_app_batch( + self, + app_project_id: str, + batch_id: str + ) -> None: + """Changes the batch status to the last one it had before archiving. After the operation, you can process the + batch again. + + Example: + >>> toloka_client.unarchive_app_batch( + >>> app_project_id='Q2d15QBjpwWuDz8Z321g', + >>> batch_id='4Va2BBWKL88S4QyAgVje' + >>> ) + ... + + Args: + app_project_id: The ID of the project with which the batch is associated. + batch_id: The ID of the batch you want to unarchive. + """ + ... + def start_app_batch( self, app_project_id: str, batch_id: str - ): + ) -> None: """Launches annotation of a batch of task items in an App project. Example: @@ -6315,11 +6372,28 @@ class TolokaClient: """ ... + def start_sync_batch_processing( + self, + app_project_id: str, + request: toloka.client.app.SyncBatchCreateRequest + ) -> toloka.client.app.AppBatch: + """Starts processing the batch with the ID specified in the request. + + This batch processing is applicable for solutions which use synchronous protocols only. + + Args: + app_project_id: The ID of the project with which the batch is associated. + + Returns: + AppBatch: The response to the request to start sync batch processing. + """ + ... + def stop_app_batch( self, app_project_id: str, batch_id: str - ): + ) -> None: """Stops annotation of a batch of task items in an App project. Processing can be stopped only for the batch with the `PROCESSING` status. @@ -6341,7 +6415,7 @@ class TolokaClient: self, app_project_id: str, batch_id: str - ): + ) -> None: """Resumes annotation of a batch of task items in an App project. Processing can be resumed only for the batch with the `STOPPING` or `STOPPED` status. diff --git a/src/client/app/__init__.py b/src/client/app/__init__.py index 0565a507..e80e0345 100644 --- a/src/client/app/__init__.py +++ b/src/client/app/__init__.py @@ -1,20 +1,23 @@ __all__ = [ - 'AppProject', 'App', - 'AppItem', - 'AppItemsCreateRequest', 'AppBatch', 'AppBatchCreateRequest', 'AppBatchPatch', + 'AppItem', + 'AppItemCreateRequest', + 'AppItemsCreateRequest', + 'AppProject', + 'SyncBatchCreateRequest', ] import datetime import decimal from enum import unique -from typing import Dict, Any, List +from typing import Dict, Any, List, Optional from ..primitives.base import BaseTolokaObject from ..project.field_spec import FieldSpec from ...util._codegen import attribute +from ...util._docstrings import inherit_docstrings from ...util._extendable_enum import ExtendableStrEnum @@ -132,22 +135,38 @@ class Status(ExtendableStrEnum): app: AppLightestResult = attribute(readonly=True) -class App(BaseTolokaObject): - """An [App](https://toloka.ai/docs/api/apps-reference/#tag--app) solution. - - Each App solution targets specific type of tasks which can be solved using Toloka. +class BaseApp(BaseTolokaObject): + """A lightweight representation of an [App](https://toloka.ai/docs/api/apps-reference/#tag--app) solution. Attributes: id: The ID of the App solution. name: The solution name. image: A link to the solution interface preview image. description: The solution description. - constraints_description: The description of limitations. default_item_price: The default cost of one annotated item. + examples: Example description of tasks which can be solved with this solution. + """ + + id: str + name: str + image: str + description: str + default_item_price: decimal.Decimal + examples: Any + + +@inherit_docstrings +class App(BaseApp): + """An [App](https://toloka.ai/docs/api/apps-reference/#tag--app) solution. + + Each App solution targets specific type of tasks which can be solved using Toloka. + + Attributes: + constraints_description: The description of limitations. param_spec: The specification of parameters used to create a project. input_spec: The schema of solution input data. output_spec: The schema of solution output data. - examples: Example description of tasks which can be solved with this solution. + input_format_info: Information about the input data format. Example: @@ -159,16 +178,10 @@ class App(BaseTolokaObject): ... """ - id: str - name: str - image: str - description: str constraints_description: str - default_item_price: decimal.Decimal param_spec: Dict input_spec: Dict[str, FieldSpec] output_spec: Dict[str, FieldSpec] - examples: Any input_format_info: Dict @@ -228,16 +241,39 @@ class Status(ExtendableStrEnum): finished_at: datetime.datetime = attribute(readonly=True) +class AppItemCreateRequest(BaseTolokaObject): + """Parameters of a request for creating single item. + + Attributes: + batch_id: The ID of the batch that contains the item. + input_data: Input data. It must follow the solution schema described in `App.input_spec`. + force_new_original: Whether to enable or disable the deduplication for the item in the request. + When set to true, the item will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. + """ + + batch_id: str + input_data: Dict[str, Any] + force_new_original: Optional[bool] = None + + class AppItemsCreateRequest(BaseTolokaObject): """Parameters of a request for creating multiple items. Attributes: batch_id: The ID of the batch to place items to. items: A list with items. The items must follow the solution schema described in `App.input_spec`. + force_new_original: Whether to enable or disable the deduplication for all the items in the request. + When set to true, all the items will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. + ignore_errors: Whether the data with incorrect items can be uploaded. Default is `False`. + * `True` — If incorrect task items are present, they will be skipped and the response will contain the information about errors. + * `False` — If incorrect task items are present, the data will not be uploaded and the response will contain the information about the errors. + You can only use this parameter if batch_id is specified in the request. """ batch_id: str - items: List[Dict[str, Any]] + items: List[Dict[str, Any]] = attribute(required=True) + force_new_original: bool + ignore_errors: bool class AppItemImport(BaseTolokaObject): @@ -247,11 +283,13 @@ class AppItemImport(BaseTolokaObject): id: The ID. records_count: The total number of items sent by a client. records_processed: The number of items processed during the operation. + records_skipped: The number of items which had incorrect parameters and were not uploaded during the operation. The detailed information about the error is returned in the `errors` field. errors: Information about items with incorrect parameters which were not added. """ id: str records_count: int records_processed: int + records_skipped: int errors: Dict @@ -273,11 +311,16 @@ class AppBatch(BaseTolokaObject): started_at: The date and time when batch processing started. finished_at: The date and time when batch processing was completed. read_only: Whether the batch can be updated or not. + priority_order: The batch priority. See [PriorityOrder](toloka.client.app.AppBatch.PriorityOrder.md) for details. Default is `FIVE`. last_items_import: Information about the last operation that added items. confidence_avg: Average labeling quality. items_processed_count: The number of labeled items. eta: Expected date and time when batch processing will be completed. + etd: The expected date and time when processing of the queued batch will be started. The parameter is present in the response when the batch status is equal to `QUEUED`, otherwise it's `None`. + app_project_eta: The expected date and time when processing of all the batches associated with the project will be completed. + The parameter is present in the response when the project contains batches in the status equal to `QUEUED` or `PROCESSING`, otherwise it's `None`. items_per_state: Statistics on the number of items in each state. + current_time: The server-side date and time when the response was formed. Example: >>> batches = toloka_client.get_app_batches(app_project_id='Q2d15QBjpwWuDz8Z321g', status='NEW') @@ -292,6 +335,8 @@ class Status(ExtendableStrEnum): Attributes: NEW: The processing of the batch items is not started. + QUEUED: The batch is ready for labeling but is currently queued because other batches with higher priority are being labeled. + Labeling of these batches will automatically start once the labeling of the batches with higher priority finishes. PROCESSING: Batch items are being processed by Tolokers. COMPLETED: Annotation of all batch items is completed. ERROR: An error occurred during processing. @@ -304,6 +349,7 @@ class Status(ExtendableStrEnum): """ NEW = 'NEW' + QUEUED = 'QUEUED' PROCESSING = 'PROCESSING' COMPLETED = 'COMPLETED' ERROR = 'ERROR' @@ -314,6 +360,18 @@ class Status(ExtendableStrEnum): STOPPING = 'STOPPING' STOPPED = 'STOPPED' + @unique + class PriorityOrder(ExtendableStrEnum): + """The batch priority. ONE is the highest value. The batch items with this priority_order value will be sent + for labeling first in the queue. + """ + + ONE = 'ONE' + TWO = 'TWO' + THREE = 'THREE' + FOUR = 'FOUR' + FIVE = 'FIVE' + id: str app_project_id: str name: str @@ -326,16 +384,39 @@ class Status(ExtendableStrEnum): started_at: datetime.datetime finished_at: datetime.datetime read_only: bool + priority_order: PriorityOrder last_items_import: AppItemImport confidence_avg: float items_processed_count: int eta: datetime.datetime + etd: datetime.datetime + app_project_eta: datetime.datetime items_per_state: Dict + current_time: datetime.datetime class AppBatchCreateRequest(BaseTolokaObject): """Parameters of a request for creating multiple App task items in a batch. + Attributes: + name: The batch name. + items: A list with task items. The items must follow the solution schema described in the `App.input_spec`. + priority_order: The batch priority. See [PriorityOrder](toloka.client.app.AppBatch.PriorityOrder.md) for details. Default is `FIVE`. + force_new_original: Whether to enable or disable the deduplication for all the items in the request. + When set to true, all the items will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. + ignore_errors: Whether the data with incorrect items can be uploaded. Default is `False`. + """ + + name: str + items: List[Dict[str, Any]] + priority_order: AppBatch.PriorityOrder + force_new_original: bool + ignore_errors: bool + + +class SyncBatchCreateRequest(BaseTolokaObject): + """The batch to be created with the list of the task items. + Attributes: name: The batch name. items: A list with task items. The items must follow the solution schema described in the `App.input_spec`. @@ -350,5 +431,7 @@ class AppBatchPatch(BaseTolokaObject): Attributes: name: The new batch name. + priority_order: The batch priority. See [PriorityOrder](toloka.client.app.AppBatch.PriorityOrder.md) for details. """ name: str + priority_order: AppBatch.PriorityOrder diff --git a/src/client/app/__init__.pyi b/src/client/app/__init__.pyi index c5ef1d9c..857615ab 100644 --- a/src/client/app/__init__.pyi +++ b/src/client/app/__init__.pyi @@ -1,11 +1,13 @@ __all__ = [ - 'AppProject', 'App', - 'AppItem', - 'AppItemsCreateRequest', 'AppBatch', 'AppBatchCreateRequest', 'AppBatchPatch', + 'AppItem', + 'AppItemCreateRequest', + 'AppItemsCreateRequest', + 'AppProject', + 'SyncBatchCreateRequest', ] import datetime import decimal @@ -174,7 +176,42 @@ class AppProject(toloka.client.primitives.base.BaseTolokaObject): app: typing.Optional[AppLightestResult] -class App(toloka.client.primitives.base.BaseTolokaObject): +class BaseApp(toloka.client.primitives.base.BaseTolokaObject): + """A lightweight representation of an [App](https://toloka.ai/docs/api/apps-reference/#tag--app) solution. + + Attributes: + id: The ID of the App solution. + name: The solution name. + image: A link to the solution interface preview image. + description: The solution description. + default_item_price: The default cost of one annotated item. + examples: Example description of tasks which can be solved with this solution. + """ + + def __init__( + self, + *, + id: typing.Optional[str] = None, + name: typing.Optional[str] = None, + image: typing.Optional[str] = None, + description: typing.Optional[str] = None, + default_item_price: typing.Optional[decimal.Decimal] = None, + examples: typing.Optional[typing.Any] = None + ) -> None: + """Method generated by attrs for class BaseApp. + """ + ... + + _unexpected: typing.Optional[typing.Dict[str, typing.Any]] + id: typing.Optional[str] + name: typing.Optional[str] + image: typing.Optional[str] + description: typing.Optional[str] + default_item_price: typing.Optional[decimal.Decimal] + examples: typing.Optional[typing.Any] + + +class App(BaseApp): """An [App](https://toloka.ai/docs/api/apps-reference/#tag--app) solution. Each App solution targets specific type of tasks which can be solved using Toloka. @@ -184,15 +221,15 @@ class App(toloka.client.primitives.base.BaseTolokaObject): name: The solution name. image: A link to the solution interface preview image. description: The solution description. - constraints_description: The description of limitations. default_item_price: The default cost of one annotated item. + examples: Example description of tasks which can be solved with this solution. + constraints_description: The description of limitations. param_spec: The specification of parameters used to create a project. input_spec: The schema of solution input data. output_spec: The schema of solution output data. - examples: Example description of tasks which can be solved with this solution. input_format_info: Information about the input data format. - Example: + Examples: Showing all available App solutions. >>> apps = toloka_client.get_apps() @@ -208,12 +245,12 @@ class App(toloka.client.primitives.base.BaseTolokaObject): name: typing.Optional[str] = None, image: typing.Optional[str] = None, description: typing.Optional[str] = None, - constraints_description: typing.Optional[str] = None, default_item_price: typing.Optional[decimal.Decimal] = None, + examples: typing.Optional[typing.Any] = None, + constraints_description: typing.Optional[str] = None, param_spec: typing.Optional[typing.Dict] = None, input_spec: typing.Optional[typing.Dict[str, toloka.client.project.field_spec.FieldSpec]] = None, output_spec: typing.Optional[typing.Dict[str, toloka.client.project.field_spec.FieldSpec]] = None, - examples: typing.Optional[typing.Any] = None, input_format_info: typing.Optional[typing.Dict] = None ) -> None: """Method generated by attrs for class App. @@ -225,12 +262,12 @@ class App(toloka.client.primitives.base.BaseTolokaObject): name: typing.Optional[str] image: typing.Optional[str] description: typing.Optional[str] - constraints_description: typing.Optional[str] default_item_price: typing.Optional[decimal.Decimal] + examples: typing.Optional[typing.Any] + constraints_description: typing.Optional[str] param_spec: typing.Optional[typing.Dict] input_spec: typing.Optional[typing.Dict[str, toloka.client.project.field_spec.FieldSpec]] output_spec: typing.Optional[typing.Dict[str, toloka.client.project.field_spec.FieldSpec]] - examples: typing.Optional[typing.Any] input_format_info: typing.Optional[typing.Dict] @@ -310,19 +347,54 @@ class AppItem(toloka.client.primitives.base.BaseTolokaObject): finished_at: typing.Optional[datetime.datetime] +class AppItemCreateRequest(toloka.client.primitives.base.BaseTolokaObject): + """Parameters of a request for creating single item. + + Attributes: + batch_id: The ID of the batch that contains the item. + input_data: Input data. It must follow the solution schema described in `App.input_spec`. + force_new_original: Whether to enable or disable the deduplication for the item in the request. + When set to true, the item will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. + """ + + def __init__( + self, + *, + batch_id: typing.Optional[str] = None, + input_data: typing.Optional[typing.Dict[str, typing.Any]] = None, + force_new_original: typing.Optional[bool] = None + ) -> None: + """Method generated by attrs for class AppItemCreateRequest. + """ + ... + + _unexpected: typing.Optional[typing.Dict[str, typing.Any]] + batch_id: typing.Optional[str] + input_data: typing.Optional[typing.Dict[str, typing.Any]] + force_new_original: typing.Optional[bool] + + class AppItemsCreateRequest(toloka.client.primitives.base.BaseTolokaObject): """Parameters of a request for creating multiple items. Attributes: batch_id: The ID of the batch to place items to. items: A list with items. The items must follow the solution schema described in `App.input_spec`. + force_new_original: Whether to enable or disable the deduplication for all the items in the request. + When set to true, all the items will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. + ignore_errors: Whether the data with incorrect items can be uploaded. Default is `False`. + * `True` — If incorrect task items are present, they will be skipped and the response will contain the information about errors. + * `False` — If incorrect task items are present, the data will not be uploaded and the response will contain the information about the errors. + You can only use this parameter if batch_id is specified in the request. """ def __init__( self, *, batch_id: typing.Optional[str] = None, - items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None + items: typing.List[typing.Dict[str, typing.Any]], + force_new_original: typing.Optional[bool] = None, + ignore_errors: typing.Optional[bool] = None ) -> None: """Method generated by attrs for class AppItemsCreateRequest. """ @@ -330,7 +402,9 @@ class AppItemsCreateRequest(toloka.client.primitives.base.BaseTolokaObject): _unexpected: typing.Optional[typing.Dict[str, typing.Any]] batch_id: typing.Optional[str] - items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] + items: typing.List[typing.Dict[str, typing.Any]] + force_new_original: typing.Optional[bool] + ignore_errors: typing.Optional[bool] class AppItemImport(toloka.client.primitives.base.BaseTolokaObject): @@ -340,6 +414,7 @@ class AppItemImport(toloka.client.primitives.base.BaseTolokaObject): id: The ID. records_count: The total number of items sent by a client. records_processed: The number of items processed during the operation. + records_skipped: The number of items which had incorrect parameters and were not uploaded during the operation. The detailed information about the error is returned in the `errors` field. errors: Information about items with incorrect parameters which were not added. """ @@ -349,6 +424,7 @@ class AppItemImport(toloka.client.primitives.base.BaseTolokaObject): id: typing.Optional[str] = None, records_count: typing.Optional[int] = None, records_processed: typing.Optional[int] = None, + records_skipped: typing.Optional[int] = None, errors: typing.Optional[typing.Dict] = None ) -> None: """Method generated by attrs for class AppItemImport. @@ -359,6 +435,7 @@ class AppItemImport(toloka.client.primitives.base.BaseTolokaObject): id: typing.Optional[str] records_count: typing.Optional[int] records_processed: typing.Optional[int] + records_skipped: typing.Optional[int] errors: typing.Optional[typing.Dict] @@ -380,11 +457,16 @@ class AppBatch(toloka.client.primitives.base.BaseTolokaObject): started_at: The date and time when batch processing started. finished_at: The date and time when batch processing was completed. read_only: Whether the batch can be updated or not. + priority_order: The batch priority. See [PriorityOrder](toloka.client.app.AppBatch.PriorityOrder.md) for details. Default is `FIVE`. last_items_import: Information about the last operation that added items. confidence_avg: Average labeling quality. items_processed_count: The number of labeled items. eta: Expected date and time when batch processing will be completed. + etd: The expected date and time when processing of the queued batch will be started. The parameter is present in the response when the batch status is equal to `QUEUED`, otherwise it's `None`. + app_project_eta: The expected date and time when processing of all the batches associated with the project will be completed. + The parameter is present in the response when the project contains batches in the status equal to `QUEUED` or `PROCESSING`, otherwise it's `None`. items_per_state: Statistics on the number of items in each state. + current_time: The server-side date and time when the response was formed. Example: >>> batches = toloka_client.get_app_batches(app_project_id='Q2d15QBjpwWuDz8Z321g', status='NEW') @@ -398,6 +480,8 @@ class AppBatch(toloka.client.primitives.base.BaseTolokaObject): Attributes: NEW: The processing of the batch items is not started. + QUEUED: The batch is ready for labeling but is currently queued because other batches with higher priority are being labeled. + Labeling of these batches will automatically start once the labeling of the batches with higher priority finishes. PROCESSING: Batch items are being processed by Tolokers. COMPLETED: Annotation of all batch items is completed. ERROR: An error occurred during processing. @@ -410,6 +494,7 @@ class AppBatch(toloka.client.primitives.base.BaseTolokaObject): """ NEW = 'NEW' + QUEUED = 'QUEUED' PROCESSING = 'PROCESSING' COMPLETED = 'COMPLETED' ERROR = 'ERROR' @@ -420,6 +505,17 @@ class AppBatch(toloka.client.primitives.base.BaseTolokaObject): STOPPING = 'STOPPING' STOPPED = 'STOPPED' + class PriorityOrder(toloka.util._extendable_enum.ExtendableStrEnum): + """The batch priority. ONE is the highest value. The batch items with this priority_order value will be sent + for labeling first in the queue. + """ + + ONE = 'ONE' + TWO = 'TWO' + THREE = 'THREE' + FOUR = 'FOUR' + FIVE = 'FIVE' + def __init__( self, *, @@ -435,11 +531,15 @@ class AppBatch(toloka.client.primitives.base.BaseTolokaObject): started_at: typing.Optional[datetime.datetime] = None, finished_at: typing.Optional[datetime.datetime] = None, read_only: typing.Optional[bool] = None, + priority_order: typing.Optional[PriorityOrder] = None, last_items_import: typing.Optional[AppItemImport] = None, confidence_avg: typing.Optional[float] = None, items_processed_count: typing.Optional[int] = None, eta: typing.Optional[datetime.datetime] = None, - items_per_state: typing.Optional[typing.Dict] = None + etd: typing.Optional[datetime.datetime] = None, + app_project_eta: typing.Optional[datetime.datetime] = None, + items_per_state: typing.Optional[typing.Dict] = None, + current_time: typing.Optional[datetime.datetime] = None ) -> None: """Method generated by attrs for class AppBatch. """ @@ -458,11 +558,15 @@ class AppBatch(toloka.client.primitives.base.BaseTolokaObject): started_at: typing.Optional[datetime.datetime] finished_at: typing.Optional[datetime.datetime] read_only: typing.Optional[bool] + priority_order: typing.Optional[PriorityOrder] last_items_import: typing.Optional[AppItemImport] confidence_avg: typing.Optional[float] items_processed_count: typing.Optional[int] eta: typing.Optional[datetime.datetime] + etd: typing.Optional[datetime.datetime] + app_project_eta: typing.Optional[datetime.datetime] items_per_state: typing.Optional[typing.Dict] + current_time: typing.Optional[datetime.datetime] class AppBatchCreateRequest(toloka.client.primitives.base.BaseTolokaObject): @@ -471,13 +575,20 @@ class AppBatchCreateRequest(toloka.client.primitives.base.BaseTolokaObject): Attributes: name: The batch name. items: A list with task items. The items must follow the solution schema described in the `App.input_spec`. + priority_order: The batch priority. See [PriorityOrder](toloka.client.app.AppBatch.PriorityOrder.md) for details. Default is `FIVE`. + force_new_original: Whether to enable or disable the deduplication for all the items in the request. + When set to true, all the items will be re-labeled regardless of whether pre-labeled duplicates exist. Default is `False`. + ignore_errors: Whether the data with incorrect items can be uploaded. Default is `False`. """ def __init__( self, *, name: typing.Optional[str] = None, - items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None + items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None, + priority_order: typing.Optional[AppBatch.PriorityOrder] = None, + force_new_original: typing.Optional[bool] = None, + ignore_errors: typing.Optional[bool] = None ) -> None: """Method generated by attrs for class AppBatchCreateRequest. """ @@ -486,6 +597,32 @@ class AppBatchCreateRequest(toloka.client.primitives.base.BaseTolokaObject): _unexpected: typing.Optional[typing.Dict[str, typing.Any]] name: typing.Optional[str] items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] + priority_order: typing.Optional[AppBatch.PriorityOrder] + force_new_original: typing.Optional[bool] + ignore_errors: typing.Optional[bool] + + +class SyncBatchCreateRequest(toloka.client.primitives.base.BaseTolokaObject): + """The batch to be created with the list of the task items. + + Attributes: + name: The batch name. + items: A list with task items. The items must follow the solution schema described in the `App.input_spec`. + """ + + def __init__( + self, + *, + name: typing.Optional[str] = None, + items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None + ) -> None: + """Method generated by attrs for class SyncBatchCreateRequest. + """ + ... + + _unexpected: typing.Optional[typing.Dict[str, typing.Any]] + name: typing.Optional[str] + items: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] class AppBatchPatch(toloka.client.primitives.base.BaseTolokaObject): @@ -493,12 +630,19 @@ class AppBatchPatch(toloka.client.primitives.base.BaseTolokaObject): Attributes: name: The new batch name. + priority_order: The batch priority. See [PriorityOrder](toloka.client.app.AppBatch.PriorityOrder.md) for details. """ - def __init__(self, *, name: typing.Optional[str] = None) -> None: + def __init__( + self, + *, + name: typing.Optional[str] = None, + priority_order: typing.Optional[AppBatch.PriorityOrder] = None + ) -> None: """Method generated by attrs for class AppBatchPatch. """ ... _unexpected: typing.Optional[typing.Dict[str, typing.Any]] name: typing.Optional[str] + priority_order: typing.Optional[AppBatch.PriorityOrder] diff --git a/src/client/primitives/adapters.py b/src/client/primitives/adapters.py index c78d79dc..b7b33bbc 100644 --- a/src/client/primitives/adapters.py +++ b/src/client/primitives/adapters.py @@ -74,7 +74,7 @@ def _(exception: httpx.NetworkError): @_map_httpx_exception_to_urllib3_exception.register def _(exception: httpx.ConnectError): - return urllib3.exceptions.NewConnectionError(pool=None, message=str(exception)) # type: ignore + return urllib3.exceptions.NewConnectionError(None, str(exception)) # type: ignore @_map_httpx_exception_to_urllib3_exception.register diff --git a/src/client/primitives/retry.pyi b/src/client/primitives/retry.pyi index 316d3236..7040ae8e 100644 --- a/src/client/primitives/retry.pyi +++ b/src/client/primitives/retry.pyi @@ -45,6 +45,7 @@ class TolokaRetry(urllib3.util.retry.Retry): **kwargs ) -> urllib3.util.retry.Retry: ... + DEFAULT: typing.Any _retry_quotas: typing.Union[typing.List[str], str, None] diff --git a/src/client/project/__init__.py b/src/client/project/__init__.py index d5a9a7eb..7fb9127f 100644 --- a/src/client/project/__init__.py +++ b/src/client/project/__init__.py @@ -263,10 +263,12 @@ class ProjectUpdateDifferenceLevel(ExtendableStrEnum): """The level of a project update difference. Attributes: + EQUAL: The update does not change the project. BREAKING_CHANGE: The update is a breaking change. NON_BREAKING_CHANGE: The update is not a breaking change. """ + EQUAL = 'EQUAL' BREAKING_CHANGE = 'BREAKING_CHANGE' NON_BREAKING_CHANGE = 'NON_BREAKING_CHANGE' diff --git a/src/client/project/__init__.pyi b/src/client/project/__init__.pyi index f879f3eb..37937d4a 100644 --- a/src/client/project/__init__.pyi +++ b/src/client/project/__init__.pyi @@ -273,10 +273,12 @@ class ProjectUpdateDifferenceLevel(toloka.util._extendable_enum.ExtendableStrEnu """The level of a project update difference. Attributes: + EQUAL: The update does not change the project. BREAKING_CHANGE: The update is a breaking change. NON_BREAKING_CHANGE: The update is not a breaking change. """ + EQUAL = 'EQUAL' BREAKING_CHANGE = 'BREAKING_CHANGE' NON_BREAKING_CHANGE = 'NON_BREAKING_CHANGE' diff --git a/tests/app/conftest.py b/tests/app/conftest.py index 16f3bbfc..8b22fc96 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -162,7 +162,6 @@ def app_item_map(): 'id': '124', 'text': 'I smell bad after the last night.' }, - 'errors': [], } @@ -190,6 +189,7 @@ def app_item_import_map(): 'id': '123', 'records_count': 1000, 'records_processed': 10, + 'records_skipped': 20, 'errors': {} } @@ -209,9 +209,13 @@ def app_batch_map(app_item_import_map): 'confidence_avg': 50., 'items_processed_count': 10, 'eta': '2021-09-28T16:07:13.400000', + 'etd': '2021-09-28T16:07:13.400000', + 'app_project_eta': '2021-09-28T16:07:13.400000', + 'current_time': '2021-09-28T16:07:13.400000', 'items_per_state': {}, 'created_at': '2021-09-28T15:56:25.193000', 'started_at': '2021-09-28T15:56:30.201000', 'finished_at': '2021-09-28T16:07:13.400000', 'read_only': False, + 'priority_order': 'THREE', } diff --git a/tests/app/test_app.py b/tests/app/test_app.py index 1145c506..72974943 100644 --- a/tests/app/test_app.py +++ b/tests/app/test_app.py @@ -8,6 +8,7 @@ import simplejson import toloka.client as client from httpx import QueryParams +from toloka.client.app import AppItemCreateRequest, SyncBatchCreateRequest from ..testutils.util_functions import check_headers @@ -458,12 +459,36 @@ def app_items(request): } check_headers(request, expected_headers) - assert app_item_map == simplejson.loads(request.content) + expected_request = AppItemCreateRequest( + batch_id=app_item_map['batch_id'], + input_data=app_item_map['input_data'], + force_new_original=True, + ) + assert expected_request.unstructure() == simplejson.loads(request.content) return httpx.Response(text=simplejson.dumps(app_item_map_with_readonly), status_code=201) respx_mock.post(f'{toloka_app_url}/app-projects/123/items').mock(side_effect=app_items) app_item = client.structure(app_item_map, client.app.AppItem) - result = toloka_client_prod.create_app_item('123', app_item) + result = toloka_client_prod.create_app_item('123', app_item, force_new_original=True) + assert app_item_map_with_readonly == client.unstructure(result) + + +def test_create_app_item_expanded( + respx_mock, toloka_client_prod, toloka_app_url, app_item_map, app_item_map_with_readonly, +): + def app_items(request): + expected_headers = { + 'X-Caller-Context': 'client' if isinstance(toloka_client_prod, client.TolokaClient) else 'async_client', + 'X-Top-Level-Method': 'create_app_item', + 'X-Low-Level-Method': 'create_app_item', + } + check_headers(request, expected_headers) + + assert app_item_map == simplejson.loads(request.content) + return httpx.Response(text=simplejson.dumps(app_item_map_with_readonly), status_code=201) + + respx_mock.post(f'{toloka_app_url}/app-projects/123/items').mock(side_effect=app_items) + result = toloka_client_prod.create_app_item('123', **app_item_map) assert app_item_map_with_readonly == client.unstructure(result) @@ -619,7 +644,10 @@ def get_app_batch(request): def test_create_app_batch(respx_mock, toloka_client_prod, toloka_app_url, app_item_map, app_batch_map): app_batch_create_request = { - 'items': [app_item_map['input_data']] + 'items': [app_item_map['input_data']], + 'priority_order': app_batch_map['priority_order'], + 'force_new_original': True, + 'ignore_errors': False, } def app_batch(request): @@ -639,6 +667,30 @@ def app_batch(request): assert app_batch_map == client.unstructure(result) +def test_start_sync_batch_processing(respx_mock, toloka_client_prod, toloka_app_url, app_item_map, app_batch_map): + + app_batch_create_request = { + 'items': [app_item_map['input_data']], + 'name': 'name', + } + + def app_batch(request): + expected_headers = { + 'X-Caller-Context': 'client' if isinstance(toloka_client_prod, client.TolokaClient) else 'async_client', + 'X-Top-Level-Method': 'start_sync_batch_processing', + 'X-Low-Level-Method': 'start_sync_batch_processing', + } + check_headers(request, expected_headers) + + assert app_batch_create_request == simplejson.loads(request.content) + return httpx.Response(text=simplejson.dumps(app_batch_map), status_code=201) + + respx_mock.post(f'{toloka_app_url}/app-projects/123/batches/sync').mock(side_effect=app_batch) + sync_batch_create_request_obj = SyncBatchCreateRequest.structure(app_batch_create_request) + result = toloka_client_prod.start_sync_batch_processing(app_project_id='123', request=sync_batch_create_request_obj) + assert app_batch_map == client.unstructure(result) + + def test_patch_app_batch(respx_mock, toloka_client_prod, toloka_app_url, app_batch_map): app_batch_patch_request = { @@ -667,7 +719,7 @@ def patch_app_batch(request): @pytest.mark.parametrize( - 'method_name', ('start_app_batch', 'stop_app_batch', 'resume_app_batch') + 'method_name', ('start_app_batch', 'stop_app_batch', 'resume_app_batch', 'archive_app_batch', 'unarchive_app_batch') ) def test_change_app_batch_status(respx_mock, toloka_client_prod, toloka_app_url, method_name): diff --git a/tests/test_project.py b/tests/test_project.py index 60c5b7f0..91e0a4e9 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -865,6 +865,13 @@ def test_localization_funcs(project_map): assert client.unstructure(project1) == client.unstructure(project5) +@pytest.fixture +def project_check_map_equal(): + return { + 'differenceLevel': 'EQUAL' + } + + @pytest.fixture def project_check_map_breaking_change(): return { @@ -882,6 +889,7 @@ def project_check_map_non_breaking_change(): @pytest.mark.parametrize( 'project_check_map,difference_level', [ + (lazy_fixture('project_check_map_equal'), ProjectUpdateDifferenceLevel.EQUAL), (lazy_fixture('project_check_map_breaking_change'), ProjectUpdateDifferenceLevel.BREAKING_CHANGE), (lazy_fixture('project_check_map_non_breaking_change'), ProjectUpdateDifferenceLevel.NON_BREAKING_CHANGE), ] diff --git a/tox.ini b/tox.ini index 08d3a41a..2b9c6bc4 100644 --- a/tox.ini +++ b/tox.ini @@ -61,7 +61,7 @@ commands = [testenv:py310-stubgeneration-all] deps = {[testenv]deps} - stubmaker==0.0.3 + stubmaker==0.1.0 commands = pytest misc/stubmaker/tests -vv # Builds and uploads package to PyPI