From 65b37d071db0d07473b44399ef2dd2435b11599d Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Fri, 12 Sep 2025 01:30:51 +0000 Subject: [PATCH 1/3] SDK regeneration --- .mock/definition/__package__.yml | 10 +- .mock/definition/dashboard.yml | 193 ++++----- .../{ => organizations}/invites.yml | 28 +- .mock/openapi/openapi.yaml | 90 ++--- pyproject.toml | 2 +- reference.md | 210 ++++++++++ .../organizations/__init__.py | 4 +- src/label_studio_sdk/organizations/client.py | 4 + .../organizations/invites/__init__.py | 2 + .../organizations/invites/client.py | 368 ++++++++++++++++++ tests/organizations/test_invites.py | 42 ++ 11 files changed, 769 insertions(+), 184 deletions(-) rename .mock/definition/{ => organizations}/invites.yml (72%) create mode 100644 src/label_studio_sdk/organizations/invites/__init__.py create mode 100644 src/label_studio_sdk/organizations/invites/client.py create mode 100644 tests/organizations/test_invites.py diff --git a/.mock/definition/__package__.yml b/.mock/definition/__package__.yml index 30dc10a8b..c10e74ca7 100644 --- a/.mock/definition/__package__.yml +++ b/.mock/definition/__package__.yml @@ -6,10 +6,10 @@ errors: examples: - value: key: value - NotImplementedError: - status-code: 501 + ForbiddenError: + status-code: 403 type: unknown - docs: KPI depends on other KPIs - not implemented + docs: Organization does not allow to invite people BadRequestError: status-code: 400 type: unknown @@ -24,10 +24,6 @@ errors: docs: Predicting error examples: - value: Server responded with an error. - ForbiddenError: - status-code: 403 - type: unknown - docs: Permission Denied MethodNotAllowedError: status-code: 405 type: unknown diff --git a/.mock/definition/dashboard.yml b/.mock/definition/dashboard.yml index 9dedabf81..98417b5ec 100644 --- a/.mock/definition/dashboard.yml +++ b/.mock/definition/dashboard.yml @@ -1,50 +1,80 @@ -imports: - root: __package__.yml +types: + ApiProjectsDashboardRetrieveResponse: + properties: + annotated_tasks: + type: optional + docs: Number of annotated (completed) tasks + annotations: + type: optional + docs: Total number of annotations + remaining_tasks: + type: optional + docs: Total number of uncompleted tasks + reviewed_tasks: + type: optional + docs: Number of tasks that have been reviewed by at least one reviewer + skipped_tasks: + type: optional + docs: Number of tasks that have been skipped by at least one annotator + tasks: + type: optional + docs: Total number of tasks + source: + openapi: openapi/openapi.yaml + ApiProjectsDashboardMembersRetrieveResponseStatsItem: + docs: User statistics + properties: + accepted: + type: optional + docs: Number of annotations marked as "Accepted" by reviewer + finished: + type: optional + gt: + type: optional + docs: Average agreement with Ground Truth annotations + mean_time: + type: optional + docs: Average mean time spent on annotation + median_time: + type: optional + docs: Average median time spent on annotation + predictions: + type: optional + docs: Average agreement with predictions + progress: + type: optional + docs: Fraction of annotation work done so far + rejected: + type: optional + docs: Number of annotations marked as "Rejected" by reviewer + review_score: + type: optional + docs: >- + Average reviewing score, when calling with "per_label=true", returns + dictionary with labels to score breakdown + skipped: + type: optional + source: + openapi: openapi/openapi.yaml + inline: true + ApiProjectsDashboardMembersRetrieveResponse: + docs: Task creation response + properties: + similarity: + type: optional>> + docs: Consensus statistics between different users + stats: + type: optional> + docs: Number of annotated (completed) tasks + users: + type: optional>> + docs: List of users + source: + openapi: openapi/openapi.yaml service: auth: false base-path: '' endpoints: - api_dashboards_kpis_retrieve: - path: /api/dashboards/{id}/kpis/{kpi_key} - method: GET - auth: true - docs: >- - Get Key Performance Indicator (KPI) data for a dashboard. Supports - various KPIs including: skipped_annotations, accepted_annotations, - rejected_annotations, average_time_per_task_min, total_annotations, - regions_created, and more. - source: - openapi: openapi/openapi.yaml - path-parameters: - id: integer - kpi_key: string - display-name: Get KPI data - request: - name: ApiDashboardsKpisRetrieveRequest - query-parameters: - end: - type: optional - docs: End date for filtering (ISO format) - members: - type: optional - allow-multiple: true - docs: Array of user IDs to filter by - start: - type: optional - docs: Start date for filtering (ISO format) - response: - docs: KPI data - type: map - errors: - - root.NotFoundError - - root.NotImplementedError - examples: - - path-parameters: - id: 1 - kpi_key: kpi_key - response: - body: - key: value api_projects_dashboard_retrieve: path: /api/projects/{id}/dashboard method: GET @@ -70,6 +100,8 @@ service: reviewed_tasks: 1 skipped_tasks: 1 tasks: 1 + audiences: + - internal api_projects_dashboard_members_retrieve: path: /api/projects/{id}/dashboard-members method: GET @@ -135,78 +167,7 @@ service: skipped: 1 users: - key: value + audiences: + - internal source: openapi: openapi/openapi.yaml -types: - ApiProjectsDashboardRetrieveResponse: - properties: - annotated_tasks: - type: optional - docs: Number of annotated (completed) tasks - annotations: - type: optional - docs: Total number of annotations - remaining_tasks: - type: optional - docs: Total number of uncompleted tasks - reviewed_tasks: - type: optional - docs: Number of tasks that have been reviewed by at least one reviewer - skipped_tasks: - type: optional - docs: Number of tasks that have been skipped by at least one annotator - tasks: - type: optional - docs: Total number of tasks - source: - openapi: openapi/openapi.yaml - ApiProjectsDashboardMembersRetrieveResponseStatsItem: - docs: User statistics - properties: - accepted: - type: optional - docs: Number of annotations marked as "Accepted" by reviewer - finished: - type: optional - gt: - type: optional - docs: Average agreement with Ground Truth annotations - mean_time: - type: optional - docs: Average mean time spent on annotation - median_time: - type: optional - docs: Average median time spent on annotation - predictions: - type: optional - docs: Average agreement with predictions - progress: - type: optional - docs: Fraction of annotation work done so far - rejected: - type: optional - docs: Number of annotations marked as "Rejected" by reviewer - review_score: - type: optional - docs: >- - Average reviewing score, when calling with "per_label=true", returns - dictionary with labels to score breakdown - skipped: - type: optional - source: - openapi: openapi/openapi.yaml - inline: true - ApiProjectsDashboardMembersRetrieveResponse: - docs: Task creation response - properties: - similarity: - type: optional>> - docs: Consensus statistics between different users - stats: - type: optional> - docs: Number of annotated (completed) tasks - users: - type: optional>> - docs: List of users - source: - openapi: openapi/openapi.yaml diff --git a/.mock/definition/invites.yml b/.mock/definition/organizations/invites.yml similarity index 72% rename from .mock/definition/invites.yml rename to .mock/definition/organizations/invites.yml index 34b5ba70f..accc3514a 100644 --- a/.mock/definition/invites.yml +++ b/.mock/definition/organizations/invites.yml @@ -1,8 +1,10 @@ +imports: + root: ../__package__.yml service: auth: false base-path: '' endpoints: - api_invite_retrieve: + get_invite_link: path: /api/invite method: GET auth: true @@ -10,13 +12,23 @@ service: source: openapi: openapi/openapi.yaml display-name: Invite people + response: + docs: '' + type: root.OrganizationInvite + errors: + - root.ForbiddenError examples: - - {} - api_invite_revoke_create: + - response: + body: + invite_url: invite_url + token: token + audiences: + - public + revoke_invite: path: /api/invite/revoke method: POST auth: true - docs: Revoke invite + docs: Revoke invite to organization source: openapi: openapi/openapi.yaml display-name: Revoke invite @@ -32,7 +44,9 @@ service: examples: - request: email: email - api_invite_send_email_create: + audiences: + - public + send_email: path: /api/invite/send-email method: POST auth: true @@ -50,10 +64,14 @@ service: validation: minLength: 1 content-type: application/json + errors: + - root.ForbiddenError examples: - request: emails: - emails role: role + audiences: + - public source: openapi: openapi/openapi.yaml diff --git a/.mock/openapi/openapi.yaml b/.mock/openapi/openapi.yaml index b81048642..314353b25 100644 --- a/.mock/openapi/openapi.yaml +++ b/.mock/openapi/openapi.yaml @@ -1361,55 +1361,6 @@ paths: - public x-fern-sdk-group-name: users x-fern-sdk-method-name: whoami - /api/dashboards/{id}/kpis/{kpi_key}: - get: - description: 'Get Key Performance Indicator (KPI) data for a dashboard. Supports various KPIs including: skipped_annotations, accepted_annotations, rejected_annotations, average_time_per_task_min, total_annotations, regions_created, and more.' - operationId: api_dashboards_kpis_retrieve - parameters: - - description: End date for filtering (ISO format) - in: query - name: end - schema: - type: string - - in: path - name: id - required: true - schema: - type: integer - - in: path - name: kpi_key - required: true - schema: - type: string - - description: Array of user IDs to filter by - in: query - name: members - schema: - items: - type: integer - type: array - - description: Start date for filtering (ISO format) - in: query - name: start - schema: - type: string - responses: - '200': - content: - application/json: - schema: - description: KPI data with the requested key and its value - type: object - description: KPI data - '404': - description: KPI not found - '501': - description: KPI depends on other KPIs - not implemented - security: - - Token: [] - summary: Get KPI data - tags: - - Dashboard /api/dataset-storages/: get: description: Retrieve a list of the dataset storages of all types with their IDs. @@ -3956,12 +3907,25 @@ paths: operationId: api_invite_retrieve responses: '200': - description: No response body + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationInvite' + description: '' + '403': + description: Organization does not allow to invite people security: - Token: [] summary: Invite people tags: + - Organizations - Invites + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - invites + x-fern-sdk-method-name: get_invite_link /api/invite/reset-token: post: description: Reset the token used in the invitation link to invite someone to an organization. @@ -3984,7 +3948,7 @@ paths: x-fern-sdk-method-name: reset_token /api/invite/revoke: post: - description: Revoke invite + description: Revoke invite to organization operationId: api_invite_revoke_create requestBody: content: @@ -4000,12 +3964,19 @@ paths: required: true responses: '200': - description: No response body + description: Invite revoked security: - Token: [] summary: Revoke invite tags: + - Organizations - Invites + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - invites + x-fern-sdk-method-name: revoke_invite /api/invite/send-email: post: description: Send email with invite to organization @@ -4024,12 +3995,21 @@ paths: required: true responses: '200': - description: No response body + description: Invite sent + '403': + description: Organization does not allow to invite people security: - Token: [] summary: Send email with invite tags: + - Organizations - Invites + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - invites + x-fern-sdk-method-name: send_email /api/jwt/settings: get: description: Retrieve JWT settings for the currently active organization. @@ -6754,6 +6734,8 @@ paths: summary: Get dashboard data for project tags: - Dashboard + x-fern-audiences: + - internal /api/projects/{id}/dashboard-members: get: deprecated: true @@ -6868,6 +6850,8 @@ paths: summary: Get dashboard data for members tags: - Dashboard + x-fern-audiences: + - internal /api/projects/{id}/duplicate/: post: description: Make a copy of project. diff --git a/pyproject.toml b/pyproject.toml index daaa1fd1b..87ea02761 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "label-studio-sdk" [tool.poetry] name = "label-studio-sdk" -version = "2.0.7.dev" +version = "2.0.7" description = "" readme = "README.md" authors = [] diff --git a/reference.md b/reference.md index a4b45447a..0442c4bca 100644 --- a/reference.md +++ b/reference.md @@ -24633,6 +24633,216 @@ client.import_storage.s3s.sync( + + + + +## Organizations Invites +
client.organizations.invites.get_invite_link() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get invite link for organization +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.invites.get_invite_link() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.invites.revoke_invite(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Revoke invite to organization +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.invites.revoke_invite( + email="email", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**email:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.invites.send_email(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Send email with invite to organization +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.invites.send_email( + emails=["emails"], + role="role", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**emails:** `typing.Sequence[str]` + +
+
+ +
+
+ +**role:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
diff --git a/src/label_studio_sdk/organizations/__init__.py b/src/label_studio_sdk/organizations/__init__.py index ff24acaa4..cd30f0883 100644 --- a/src/label_studio_sdk/organizations/__init__.py +++ b/src/label_studio_sdk/organizations/__init__.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from . import members +from . import invites, members -__all__ = ["members"] +__all__ = ["invites", "members"] diff --git a/src/label_studio_sdk/organizations/client.py b/src/label_studio_sdk/organizations/client.py index 610a041e9..38b3dc029 100644 --- a/src/label_studio_sdk/organizations/client.py +++ b/src/label_studio_sdk/organizations/client.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. from ..core.client_wrapper import SyncClientWrapper +from .invites.client import InvitesClient from .members.client import MembersClient import typing from ..core.request_options import RequestOptions @@ -12,12 +13,14 @@ from ..types.lse_organization import LseOrganization from ..core.jsonable_encoder import jsonable_encoder from ..core.client_wrapper import AsyncClientWrapper +from .invites.client import AsyncInvitesClient from .members.client import AsyncMembersClient class OrganizationsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper + self.invites = InvitesClient(client_wrapper=self._client_wrapper) self.members = MembersClient(client_wrapper=self._client_wrapper) def reset_token(self, *, request_options: typing.Optional[RequestOptions] = None) -> OrganizationInvite: @@ -164,6 +167,7 @@ def get(self, id: int, *, request_options: typing.Optional[RequestOptions] = Non class AsyncOrganizationsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper + self.invites = AsyncInvitesClient(client_wrapper=self._client_wrapper) self.members = AsyncMembersClient(client_wrapper=self._client_wrapper) async def reset_token(self, *, request_options: typing.Optional[RequestOptions] = None) -> OrganizationInvite: diff --git a/src/label_studio_sdk/organizations/invites/__init__.py b/src/label_studio_sdk/organizations/invites/__init__.py new file mode 100644 index 000000000..f3ea2659b --- /dev/null +++ b/src/label_studio_sdk/organizations/invites/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/src/label_studio_sdk/organizations/invites/client.py b/src/label_studio_sdk/organizations/invites/client.py new file mode 100644 index 000000000..e70cf89b4 --- /dev/null +++ b/src/label_studio_sdk/organizations/invites/client.py @@ -0,0 +1,368 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ...core.client_wrapper import SyncClientWrapper +from ...core.request_options import RequestOptions +from ...types.organization_invite import OrganizationInvite +from ...core.unchecked_base_model import construct_type +from ...errors.forbidden_error import ForbiddenError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class InvitesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_invite_link(self, *, request_options: typing.Optional[RequestOptions] = None) -> OrganizationInvite: + """ + Get invite link for organization + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationInvite + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.invites.get_invite_link() + """ + _response = self._client_wrapper.httpx_client.request( + "api/invite", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationInvite, + construct_type( + type_=OrganizationInvite, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + 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 revoke_invite(self, *, email: str, request_options: typing.Optional[RequestOptions] = None) -> None: + """ + Revoke invite to organization + + Parameters + ---------- + email : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.invites.revoke_invite( + email="email", + ) + """ + _response = self._client_wrapper.httpx_client.request( + "api/invite/revoke", + method="POST", + json={ + "email": email, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + _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 send_email( + self, *, emails: typing.Sequence[str], role: str, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Send email with invite to organization + + Parameters + ---------- + emails : typing.Sequence[str] + + role : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.invites.send_email( + emails=["emails"], + role="role", + ) + """ + _response = self._client_wrapper.httpx_client.request( + "api/invite/send-email", + method="POST", + json={ + "emails": emails, + "role": role, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 403: + raise ForbiddenError( + 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) + + +class AsyncInvitesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_invite_link(self, *, request_options: typing.Optional[RequestOptions] = None) -> OrganizationInvite: + """ + Get invite link for organization + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationInvite + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.invites.get_invite_link() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "api/invite", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationInvite, + construct_type( + type_=OrganizationInvite, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + 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 revoke_invite(self, *, email: str, request_options: typing.Optional[RequestOptions] = None) -> None: + """ + Revoke invite to organization + + Parameters + ---------- + email : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.invites.revoke_invite( + email="email", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "api/invite/revoke", + method="POST", + json={ + "email": email, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + _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 send_email( + self, *, emails: typing.Sequence[str], role: str, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Send email with invite to organization + + Parameters + ---------- + emails : typing.Sequence[str] + + role : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.invites.send_email( + emails=["emails"], + role="role", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "api/invite/send-email", + method="POST", + json={ + "emails": emails, + "role": role, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 403: + raise ForbiddenError( + 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) diff --git a/tests/organizations/test_invites.py b/tests/organizations/test_invites.py new file mode 100644 index 000000000..a4e357542 --- /dev/null +++ b/tests/organizations/test_invites.py @@ -0,0 +1,42 @@ +# This file was auto-generated by Fern from our API Definition. + +from label_studio_sdk import LabelStudio +from label_studio_sdk import AsyncLabelStudio +import typing +from ..utilities import validate_response + + +async def test_get_invite_link(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = {"invite_url": "invite_url", "token": "token"} + expected_types: typing.Any = {"invite_url": None, "token": None} + response = client.organizations.invites.get_invite_link() + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.invites.get_invite_link() + validate_response(async_response, expected_response, expected_types) + + +async def test_revoke_invite(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.organizations.invites.revoke_invite(email="email") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.organizations.invites.revoke_invite(email="email") # type: ignore[func-returns-value] + is None + ) + + +async def test_send_email(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.organizations.invites.send_email(emails=["emails"], role="role") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.organizations.invites.send_email(emails=["emails"], role="role") # type: ignore[func-returns-value] + is None + ) From 5a77347e2e4ff0500e2be6c0c48bc3f35aacbe5f Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Fri, 12 Sep 2025 02:24:23 +0000 Subject: [PATCH 2/3] SDK regeneration --- .mock/definition/organizations/invites.yml | 2 +- .mock/openapi/openapi.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.mock/definition/organizations/invites.yml b/.mock/definition/organizations/invites.yml index accc3514a..8d36c3da1 100644 --- a/.mock/definition/organizations/invites.yml +++ b/.mock/definition/organizations/invites.yml @@ -11,7 +11,7 @@ service: docs: Get invite link for organization source: openapi: openapi/openapi.yaml - display-name: Invite people + display-name: Get invite link response: docs: '' type: root.OrganizationInvite diff --git a/.mock/openapi/openapi.yaml b/.mock/openapi/openapi.yaml index 314353b25..364a5d088 100644 --- a/.mock/openapi/openapi.yaml +++ b/.mock/openapi/openapi.yaml @@ -3916,7 +3916,7 @@ paths: description: Organization does not allow to invite people security: - Token: [] - summary: Invite people + summary: Get invite link tags: - Organizations - Invites From 7ee8b9561b98b45a238c075974e76f71a5c5a959 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Fri, 12 Sep 2025 14:54:50 +0000 Subject: [PATCH 3/3] SDK regeneration