From 0c00bbdf4fc8ca50c50db0ac2e75d102702a8a03 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:34:30 +0000 Subject: [PATCH 1/3] SDK regeneration --- .gitignore | 1 - .mock/definition/projects.yml | 40 +++++ .mock/openapi/openapi.yaml | 54 ++++++ reference.md | 84 +++++++++ src/label_studio_sdk/__init__.py | 2 + src/label_studio_sdk/projects/__init__.py | 2 + src/label_studio_sdk/projects/client.py | 160 ++++++++++++++++++ .../projects/types/__init__.py | 2 + .../projects_import_predictions_response.py | 26 +++ tests/test_projects.py | 13 ++ 10 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 src/label_studio_sdk/projects/types/projects_import_predictions_response.py diff --git a/.gitignore b/.gitignore index 4d31c22e3..0da665fee 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,3 @@ dist/ __pycache__/ poetry.toml .ruff_cache/ -CLAUDE.local.md diff --git a/.mock/definition/projects.yml b/.mock/definition/projects.yml index 61ccd1794..e599a896c 100644 --- a/.mock/definition/projects.yml +++ b/.mock/definition/projects.yml @@ -74,6 +74,14 @@ types: docs: Number of tasks added source: openapi: openapi/openapi.yaml + ProjectsImportPredictionsResponse: + docs: Import result + properties: + created: + type: optional + docs: Number of predictions created + source: + openapi: openapi/openapi.yaml ApiProjectsProjectExtraParamsRetrieveResponse: docs: Create or change annotator weights for statistics properties: @@ -995,6 +1003,38 @@ service: task_count: 1 audiences: - public + import_predictions: + path: /api/projects/{id}/import/predictions + method: POST + auth: true + docs: Import model predictions for tasks in the specified project. + source: + openapi: openapi/openapi.yaml + path-parameters: + id: + type: integer + docs: A unique integer value identifying this project. + display-name: Import predictions + request: + body: list + content-type: application/json + response: + docs: Predictions successfully imported + type: ProjectsImportPredictionsResponse + errors: + - root.BadRequestError + examples: + - path-parameters: + id: 1 + request: + - result: + - key: value + task: 1 + response: + body: + created: 1 + audiences: + - public api_projects_members_create: path: /api/projects/{id}/members/ method: POST diff --git a/.mock/openapi/openapi.yaml b/.mock/openapi/openapi.yaml index 7d39fed28..7aa3e0828 100644 --- a/.mock/openapi/openapi.yaml +++ b/.mock/openapi/openapi.yaml @@ -7486,6 +7486,60 @@ paths: - public x-fern-sdk-group-name: projects x-fern-sdk-method-name: import_tasks + /api/projects/{id}/import/predictions: + post: + description: Import model predictions for tasks in the specified project. + operationId: api_projects_import_predictions_create + parameters: + - description: A unique integer value identifying this project. + in: path + name: id + required: true + schema: + type: integer + requestBody: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/PredictionRequest' + type: array + application/x-www-form-urlencoded: + schema: + items: + $ref: '#/components/schemas/PredictionRequest' + type: array + multipart/form-data: + schema: + items: + $ref: '#/components/schemas/PredictionRequest' + type: array + required: true + responses: + '201': + content: + application/json: + schema: + description: Import result + properties: + created: + description: Number of predictions created + title: created + type: integer + title: Predictions import response + type: object + description: Predictions successfully imported + '400': + description: Bad Request + security: + - Token: [] + summary: Import predictions + tags: + - Import + x-fern-audiences: + - public + x-fern-sdk-group-name: projects + x-fern-sdk-method-name: import_predictions /api/projects/{id}/imports/{import_pk}/: get: description: Return data related to async project import operation diff --git a/reference.md b/reference.md index 930874a0f..9920dc9db 100644 --- a/reference.md +++ b/reference.md @@ -9865,6 +9865,90 @@ client.projects.import_tasks( + + + + +
client.projects.import_predictions(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Import model predictions for tasks in the specified project. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio, PredictionRequest + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.projects.import_predictions( + id=1, + request=[ + PredictionRequest( + result=[{"key": "value"}], + task=1, + ) + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` — A unique integer value identifying this project. + +
+
+ +
+
+ +**request:** `typing.Sequence[PredictionRequest]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
diff --git a/src/label_studio_sdk/__init__.py b/src/label_studio_sdk/__init__.py index 06bdf3946..85aebcb1c 100644 --- a/src/label_studio_sdk/__init__.py +++ b/src/label_studio_sdk/__init__.py @@ -292,6 +292,7 @@ PatchedLseProjectUpdateRequestSampling, PatchedLseProjectUpdateRequestSkipQueue, ProjectsDuplicateResponse, + ProjectsImportPredictionsResponse, ProjectsImportTasksResponse, ProjectsListRequestFilter, ) @@ -537,6 +538,7 @@ "ProjectTemplate", "ProjectTemplateRequest", "ProjectsDuplicateResponse", + "ProjectsImportPredictionsResponse", "ProjectsImportTasksResponse", "ProjectsListRequestFilter", "PromptsCompatibleProjectsRequestProjectType", diff --git a/src/label_studio_sdk/projects/__init__.py b/src/label_studio_sdk/projects/__init__.py index e9a3bbac5..fee07c3bc 100644 --- a/src/label_studio_sdk/projects/__init__.py +++ b/src/label_studio_sdk/projects/__init__.py @@ -6,6 +6,7 @@ PatchedLseProjectUpdateRequestSampling, PatchedLseProjectUpdateRequestSkipQueue, ProjectsDuplicateResponse, + ProjectsImportPredictionsResponse, ProjectsImportTasksResponse, ProjectsListRequestFilter, ) @@ -58,6 +59,7 @@ "PatchedLseProjectUpdateRequestSampling", "PatchedLseProjectUpdateRequestSkipQueue", "ProjectsDuplicateResponse", + "ProjectsImportPredictionsResponse", "ProjectsImportTasksResponse", "ProjectsListRequestFilter", "StatsIaaResponse", diff --git a/src/label_studio_sdk/projects/client.py b/src/label_studio_sdk/projects/client.py index 669713c29..953cf22bd 100644 --- a/src/label_studio_sdk/projects/client.py +++ b/src/label_studio_sdk/projects/client.py @@ -35,6 +35,8 @@ from ..types.import_api_request import ImportApiRequest from .types.projects_import_tasks_response import ProjectsImportTasksResponse from ..errors.bad_request_error import BadRequestError +from ..types.prediction_request import PredictionRequest +from .types.projects_import_predictions_response import ProjectsImportPredictionsResponse from ..types.project_label_config import ProjectLabelConfig from ..core.client_wrapper import AsyncClientWrapper from .exports.client import AsyncExportsClient @@ -1018,6 +1020,81 @@ def import_tasks( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def import_predictions( + self, + id: int, + *, + request: typing.Sequence[PredictionRequest], + request_options: typing.Optional[RequestOptions] = None, + ) -> ProjectsImportPredictionsResponse: + """ + Import model predictions for tasks in the specified project. + + Parameters + ---------- + id : int + A unique integer value identifying this project. + + request : typing.Sequence[PredictionRequest] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProjectsImportPredictionsResponse + Predictions successfully imported + + Examples + -------- + from label_studio_sdk import LabelStudio, PredictionRequest + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.projects.import_predictions( + id=1, + request=[ + PredictionRequest( + result=[{"key": "value"}], + task=1, + ) + ], + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/projects/{jsonable_encoder(id)}/import/predictions", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[PredictionRequest], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ProjectsImportPredictionsResponse, + construct_type( + type_=ProjectsImportPredictionsResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + def validate_label_config( self, id: int, *, label_config: str, request_options: typing.Optional[RequestOptions] = None ) -> ProjectLabelConfig: @@ -2109,6 +2186,89 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + async def import_predictions( + self, + id: int, + *, + request: typing.Sequence[PredictionRequest], + request_options: typing.Optional[RequestOptions] = None, + ) -> ProjectsImportPredictionsResponse: + """ + Import model predictions for tasks in the specified project. + + Parameters + ---------- + id : int + A unique integer value identifying this project. + + request : typing.Sequence[PredictionRequest] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProjectsImportPredictionsResponse + Predictions successfully imported + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio, PredictionRequest + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.projects.import_predictions( + id=1, + request=[ + PredictionRequest( + result=[{"key": "value"}], + task=1, + ) + ], + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/projects/{jsonable_encoder(id)}/import/predictions", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[PredictionRequest], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ProjectsImportPredictionsResponse, + construct_type( + type_=ProjectsImportPredictionsResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + async def validate_label_config( self, id: int, *, label_config: str, request_options: typing.Optional[RequestOptions] = None ) -> ProjectLabelConfig: diff --git a/src/label_studio_sdk/projects/types/__init__.py b/src/label_studio_sdk/projects/types/__init__.py index 3150776e6..a36bd4d7a 100644 --- a/src/label_studio_sdk/projects/types/__init__.py +++ b/src/label_studio_sdk/projects/types/__init__.py @@ -5,6 +5,7 @@ from .patched_lse_project_update_request_sampling import PatchedLseProjectUpdateRequestSampling from .patched_lse_project_update_request_skip_queue import PatchedLseProjectUpdateRequestSkipQueue from .projects_duplicate_response import ProjectsDuplicateResponse +from .projects_import_predictions_response import ProjectsImportPredictionsResponse from .projects_import_tasks_response import ProjectsImportTasksResponse from .projects_list_request_filter import ProjectsListRequestFilter @@ -14,6 +15,7 @@ "PatchedLseProjectUpdateRequestSampling", "PatchedLseProjectUpdateRequestSkipQueue", "ProjectsDuplicateResponse", + "ProjectsImportPredictionsResponse", "ProjectsImportTasksResponse", "ProjectsListRequestFilter", ] diff --git a/src/label_studio_sdk/projects/types/projects_import_predictions_response.py b/src/label_studio_sdk/projects/types/projects_import_predictions_response.py new file mode 100644 index 000000000..a0954f47c --- /dev/null +++ b/src/label_studio_sdk/projects/types/projects_import_predictions_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.unchecked_base_model import UncheckedBaseModel +import typing +import pydantic +from ...core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ProjectsImportPredictionsResponse(UncheckedBaseModel): + """ + Import result + """ + + created: typing.Optional[int] = pydantic.Field(default=None) + """ + Number of predictions created + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/tests/test_projects.py b/tests/test_projects.py index 51d214139..376a5a31d 100644 --- a/tests/test_projects.py +++ b/tests/test_projects.py @@ -4,6 +4,7 @@ from label_studio_sdk import AsyncLabelStudio import typing from .utilities import validate_response +from label_studio_sdk import PredictionRequest async def test_create(client: LabelStudio, async_client: AsyncLabelStudio) -> None: @@ -496,6 +497,18 @@ async def test_import_tasks(client: LabelStudio, async_client: AsyncLabelStudio) validate_response(async_response, expected_response, expected_types) +async def test_import_predictions(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = {"created": 1} + expected_types: typing.Any = {"created": "integer"} + response = client.projects.import_predictions(id=1, request=[PredictionRequest(result=[{"key": "value"}], task=1)]) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.projects.import_predictions( + id=1, request=[PredictionRequest(result=[{"key": "value"}], task=1)] + ) + validate_response(async_response, expected_response, expected_types) + + async def test_validate_label_config(client: LabelStudio, async_client: AsyncLabelStudio) -> None: expected_response: typing.Any = {"label_config": "label_config"} expected_types: typing.Any = {"label_config": None} From 353c811193ffc9772b6cac4a8a2989fad1d333ac Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:38:17 +0000 Subject: [PATCH 2/3] SDK regeneration From 83f2c2ee4d7daabae5f5d182e65502e754390ea0 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 22:56:32 +0000 Subject: [PATCH 3/3] SDK regeneration