diff --git a/.circleci/config.yml b/.circleci/config.yml index 3512303..ef7f185 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,9 +20,6 @@ jobs: - run: name: Lint command: poetry run lint - - run: - name: Check code formatting - command: poetry run check_format - persist_to_workspace: root: ~/project paths: diff --git a/README.md b/README.md index 67e61b6..3f90fa4 100644 --- a/README.md +++ b/README.md @@ -26,29 +26,31 @@ Create a `RoomApi` instance, providing the jellyfish server address and api toke ```python from jellyfish import RoomApi -room_api = RoomApi(server_address='localhost:5002', server_api_token='development') +room_api = RoomApi(server_address="localhost:5002", server_api_token="development") ``` You can use it to interact with Jellyfish, manage rooms, peers and components ```python # Create a room -jellyfish_address, room = room_api.create_room(video_codec='h264') -# 'localhost:5002', Room(components=[], config=RoomConfig(max_peers=None, video_codec='h264'), id='5a099a31-0eb2-4c28-84af-a1ec55c228af', peers=[])) +jellyfish_address, room = room_api.create_room(video_codec="h264", webhook_url="http://localhost:5000/webhook") +# '127.0.0.1:5002', Room(components=[], config=RoomConfig(max_peers=None, video_codec=, webhook_url='http://localhost:5000/webhook'), id='1d905478-ccfc-44d6-a6e7-8ccb1b38d955', peers=[]) # Add peer to the room from jellyfish import PeerOptionsWebRTC peer_token, peer_webrtc = room_api.add_peer(room.id, options=PeerOptionsWebRTC()) -# 'AgDYfrCSigFiAA', Peer(id='2869fb5', status=, type='webrtc') +# 'M8TUGhj-L11KpyG-2zBPIo', Peer(id='b1232c7e-c969-4450-acdf-ea24f3cdd7f6', status=, type='webrtc') # Add component to the room from jellyfish import ComponentOptionsHLS component_hls = room_api.add_component(room.id, options=ComponentOptionsHLS()) -# Component(actual_instance=ComponentHLS(id='c0dfab50-cafd-438d-985e-7b8f97ae55e3', metadata=ComponentMetadataHLS(low_latency=False, playable=False), type='hls')) +# ComponentHLS(id='5f062447-a9f7-45ed-8d1b-511f77dc78ae', properties=ComponentPropertiesHLS(low_latency=False, persistent=False, playable=False, subscribe_mode=, target_window_duration=None), type='hls') ``` +All methods in `RoomApi` may raise one of the exceptions deriving from `jellyfish.errors.HTTPError`. They are defined in `jellyfish.errors`. + #### Notifier Create `Notifier` instance @@ -96,14 +98,14 @@ You can test the SDK by running poetry run ci_test ``` -## Format&Lint +## Format & Lint You can format code by running ```console poetry run format ``` You can check linter by running -``` +```console poetry run lint ``` diff --git a/generate_client.sh b/generate_client.sh deleted file mode 100755 index 6df6d12..0000000 --- a/generate_client.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -TMP_DIR="openapi_client_generated" -PACKAGE_NAME="_openapi_client" - -openapi-generator-cli generate \ - -i https://raw.githubusercontent.com/jellyfish-dev/jellyfish/main/openapi.yaml \ - -g python \ - -o $TMP_DIR \ - -t templates \ - --package-name jellyfish.$PACKAGE_NAME \ - --global-property apis,models,modelTests=false,apiTests=false,modelDocs=false,apiDocs=false,supportingFiles \ - --additional-properties useOneOfDiscriminatorLookup=true && -rm -rf jellyfish/$PACKAGE_NAME -mv $TMP_DIR/jellyfish/$PACKAGE_NAME jellyfish/$PACKAGE_NAME -rm -rf $TMP_DIR diff --git a/jellyfish/__init__.py b/jellyfish/__init__.py index 2bc93fd..4d51a02 100644 --- a/jellyfish/__init__.py +++ b/jellyfish/__init__.py @@ -4,38 +4,32 @@ # pylint: disable=locally-disabled, no-name-in-module, import-error -from pydantic.error_wrappers import ValidationError - -# API -from jellyfish._room_api import RoomApi -from jellyfish._recording_api import RecordingApi -from jellyfish._ws_notifier import Notifier -from jellyfish._webhook_notifier import receive_json +# Exceptions and Server Messages +from jellyfish import errors, events # Models -from jellyfish._openapi_client import ( - Room, - RoomConfig, - Peer, - Component, +from jellyfish._openapi_client.models import ( ComponentHLS, - ComponentRTSP, - ComponentOptions, - ComponentOptionsRTSP, ComponentOptionsHLS, + ComponentOptionsHLSSubscribeMode, + ComponentOptionsRTSP, + ComponentPropertiesHLS, + ComponentPropertiesHLSSubscribeMode, + ComponentPropertiesRTSP, + ComponentRTSP, + Peer, PeerOptionsWebRTC, + PeerStatus, + Room, + RoomConfig, + RoomConfigVideoCodec, ) -# Server Messages -from jellyfish import events - -# Exceptions -from jellyfish._openapi_client.exceptions import ( - UnauthorizedException, - NotFoundException, - BadRequestException, -) - +# API +from jellyfish._webhook_notifier import receive_json +from jellyfish._ws_notifier import Notifier +from jellyfish.api._recording_api import RecordingApi +from jellyfish.api._room_api import RoomApi __all__ = [ "RoomApi", @@ -43,19 +37,20 @@ "Notifier", "receive_json", "Room", + "RoomConfig", + "RoomConfigVideoCodec", "Peer", - "Component", + "PeerOptionsWebRTC", + "PeerStatus", "ComponentHLS", - "ComponentRTSP", "ComponentOptionsHLS", - "RoomConfig", - "ComponentOptions", + "ComponentOptionsHLSSubscribeMode", + "ComponentPropertiesHLS", + "ComponentPropertiesHLSSubscribeMode", + "ComponentRTSP", "ComponentOptionsRTSP", - "PeerOptionsWebRTC", + "ComponentPropertiesRTSP", "events", - "UnauthorizedException", - "NotFoundException", - "BadRequestException", + "errors", ] - __docformat__ = "restructuredtext" diff --git a/jellyfish/_openapi_client/__init__.py b/jellyfish/_openapi_client/__init__.py index 34855c8..559de5e 100644 --- a/jellyfish/_openapi_client/__init__.py +++ b/jellyfish/_openapi_client/__init__.py @@ -1,73 +1,7 @@ -# coding: utf-8 +""" A client library for accessing Jellyfish Media Server """ +from .client import AuthenticatedClient, Client -# flake8: noqa - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -__version__ = "1.0.0" - -# import apis into sdk package -from jellyfish._openapi_client.api.hls_api import HlsApi -from jellyfish._openapi_client.api.recording_api import RecordingApi -from jellyfish._openapi_client.api.room_api import RoomApi - -# import ApiClient -from jellyfish._openapi_client.api_response import ApiResponse -from jellyfish._openapi_client.api_client import ApiClient -from jellyfish._openapi_client.configuration import Configuration -from jellyfish._openapi_client.exceptions import OpenApiException -from jellyfish._openapi_client.exceptions import ApiTypeError -from jellyfish._openapi_client.exceptions import ApiValueError -from jellyfish._openapi_client.exceptions import ApiKeyError -from jellyfish._openapi_client.exceptions import ApiAttributeError -from jellyfish._openapi_client.exceptions import ApiException - -# import models into sdk package -from jellyfish._openapi_client.models.add_component_request import AddComponentRequest -from jellyfish._openapi_client.models.add_peer_request import AddPeerRequest -from jellyfish._openapi_client.models.component import Component -from jellyfish._openapi_client.models.component_details_response import ( - ComponentDetailsResponse, -) -from jellyfish._openapi_client.models.component_hls import ComponentHLS -from jellyfish._openapi_client.models.component_metadata_hls import ComponentMetadataHLS -from jellyfish._openapi_client.models.component_options import ComponentOptions -from jellyfish._openapi_client.models.component_options_hls import ComponentOptionsHLS -from jellyfish._openapi_client.models.component_options_hlss3 import ( - ComponentOptionsHLSS3, -) -from jellyfish._openapi_client.models.component_options_rtsp import ComponentOptionsRTSP -from jellyfish._openapi_client.models.component_rtsp import ComponentRTSP -from jellyfish._openapi_client.models.error import Error -from jellyfish._openapi_client.models.hls_skip import HlsSkip -from jellyfish._openapi_client.models.peer import Peer -from jellyfish._openapi_client.models.peer_details_response import PeerDetailsResponse -from jellyfish._openapi_client.models.peer_details_response_data import ( - PeerDetailsResponseData, -) -from jellyfish._openapi_client.models.peer_options import PeerOptions -from jellyfish._openapi_client.models.peer_options_web_rtc import PeerOptionsWebRTC -from jellyfish._openapi_client.models.peer_status import PeerStatus -from jellyfish._openapi_client.models.recording_list_response import ( - RecordingListResponse, -) -from jellyfish._openapi_client.models.room import Room -from jellyfish._openapi_client.models.room_config import RoomConfig -from jellyfish._openapi_client.models.room_create_details_response import ( - RoomCreateDetailsResponse, -) -from jellyfish._openapi_client.models.room_create_details_response_data import ( - RoomCreateDetailsResponseData, +__all__ = ( + "AuthenticatedClient", + "Client", ) -from jellyfish._openapi_client.models.room_details_response import RoomDetailsResponse -from jellyfish._openapi_client.models.rooms_listing_response import RoomsListingResponse -from jellyfish._openapi_client.models.s3_credentials import S3Credentials -from jellyfish._openapi_client.models.subscription_config import SubscriptionConfig diff --git a/jellyfish/_openapi_client/api/__init__.py b/jellyfish/_openapi_client/api/__init__.py index 4d0419d..dc035f4 100644 --- a/jellyfish/_openapi_client/api/__init__.py +++ b/jellyfish/_openapi_client/api/__init__.py @@ -1,6 +1 @@ -# flake8: noqa - -# import apis into api package -from jellyfish._openapi_client.api.hls_api import HlsApi -from jellyfish._openapi_client.api.recording_api import RecordingApi -from jellyfish._openapi_client.api.room_api import RoomApi +""" Contains methods for accessing the API """ diff --git a/jellyfish/_openapi_client/api/hls/__init__.py b/jellyfish/_openapi_client/api/hls/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/jellyfish/_openapi_client/api/hls/get_hls_content.py b/jellyfish/_openapi_client/api/hls/get_hls_content.py new file mode 100644 index 0000000..a064207 --- /dev/null +++ b/jellyfish/_openapi_client/api/hls/get_hls_content.py @@ -0,0 +1,243 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + room_id: str, + filename: str, + *, + field_hls_msn: Union[Unset, None, int] = UNSET, + field_hls_part: Union[Unset, None, int] = UNSET, + field_hls_skip: Union[Unset, None, str] = UNSET, + range_: Union[Unset, str] = UNSET, +) -> Dict[str, Any]: + headers = {} + if not isinstance(range_, Unset): + headers["range"] = range_ + + params: Dict[str, Any] = {} + params["_HLS_msn"] = field_hls_msn + + params["_HLS_part"] = field_hls_part + + params["_HLS_skip"] = field_hls_skip + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + return { + "method": "get", + "url": "/hls/{room_id}/{filename}".format( + room_id=room_id, + filename=filename, + ), + "params": params, + "headers": headers, + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, str]]: + if response.status_code == HTTPStatus.OK: + response_200 = cast(str, response.json()) + return response_200 + if response.status_code == HTTPStatus.BAD_REQUEST: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, str]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + filename: str, + *, + client: Union[AuthenticatedClient, Client], + field_hls_msn: Union[Unset, None, int] = UNSET, + field_hls_part: Union[Unset, None, int] = UNSET, + field_hls_skip: Union[Unset, None, str] = UNSET, + range_: Union[Unset, str] = UNSET, +) -> Response[Union[Error, str]]: + """Retrieve HLS Content + + Args: + room_id (str): + filename (str): + field_hls_msn (Union[Unset, None, int]): Segment sequence number Example: 10. + field_hls_part (Union[Unset, None, int]): Partial segment sequence number Example: 10. + field_hls_skip (Union[Unset, None, str]): Set to "YES" if delta manifest should be + requested Example: True. + range_ (Union[Unset, str]): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, str]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + filename=filename, + field_hls_msn=field_hls_msn, + field_hls_part=field_hls_part, + field_hls_skip=field_hls_skip, + range_=range_, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + filename: str, + *, + client: Union[AuthenticatedClient, Client], + field_hls_msn: Union[Unset, None, int] = UNSET, + field_hls_part: Union[Unset, None, int] = UNSET, + field_hls_skip: Union[Unset, None, str] = UNSET, + range_: Union[Unset, str] = UNSET, +) -> Optional[Union[Error, str]]: + """Retrieve HLS Content + + Args: + room_id (str): + filename (str): + field_hls_msn (Union[Unset, None, int]): Segment sequence number Example: 10. + field_hls_part (Union[Unset, None, int]): Partial segment sequence number Example: 10. + field_hls_skip (Union[Unset, None, str]): Set to "YES" if delta manifest should be + requested Example: True. + range_ (Union[Unset, str]): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, str] + """ + + return sync_detailed( + room_id=room_id, + filename=filename, + client=client, + field_hls_msn=field_hls_msn, + field_hls_part=field_hls_part, + field_hls_skip=field_hls_skip, + range_=range_, + ).parsed + + +async def asyncio_detailed( + room_id: str, + filename: str, + *, + client: Union[AuthenticatedClient, Client], + field_hls_msn: Union[Unset, None, int] = UNSET, + field_hls_part: Union[Unset, None, int] = UNSET, + field_hls_skip: Union[Unset, None, str] = UNSET, + range_: Union[Unset, str] = UNSET, +) -> Response[Union[Error, str]]: + """Retrieve HLS Content + + Args: + room_id (str): + filename (str): + field_hls_msn (Union[Unset, None, int]): Segment sequence number Example: 10. + field_hls_part (Union[Unset, None, int]): Partial segment sequence number Example: 10. + field_hls_skip (Union[Unset, None, str]): Set to "YES" if delta manifest should be + requested Example: True. + range_ (Union[Unset, str]): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, str]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + filename=filename, + field_hls_msn=field_hls_msn, + field_hls_part=field_hls_part, + field_hls_skip=field_hls_skip, + range_=range_, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + filename: str, + *, + client: Union[AuthenticatedClient, Client], + field_hls_msn: Union[Unset, None, int] = UNSET, + field_hls_part: Union[Unset, None, int] = UNSET, + field_hls_skip: Union[Unset, None, str] = UNSET, + range_: Union[Unset, str] = UNSET, +) -> Optional[Union[Error, str]]: + """Retrieve HLS Content + + Args: + room_id (str): + filename (str): + field_hls_msn (Union[Unset, None, int]): Segment sequence number Example: 10. + field_hls_part (Union[Unset, None, int]): Partial segment sequence number Example: 10. + field_hls_skip (Union[Unset, None, str]): Set to "YES" if delta manifest should be + requested Example: True. + range_ (Union[Unset, str]): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, str] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + filename=filename, + client=client, + field_hls_msn=field_hls_msn, + field_hls_part=field_hls_part, + field_hls_skip=field_hls_skip, + range_=range_, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/hls/subscribe_tracks.py b/jellyfish/_openapi_client/api/hls/subscribe_tracks.py new file mode 100644 index 0000000..2038556 --- /dev/null +++ b/jellyfish/_openapi_client/api/hls/subscribe_tracks.py @@ -0,0 +1,175 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.subscription_config import SubscriptionConfig +from ...types import Response + + +def _get_kwargs( + room_id: str, + *, + json_body: SubscriptionConfig, +) -> Dict[str, Any]: + json_json_body = json_body.to_dict() + + return { + "method": "post", + "url": "/hls/{room_id}/subscribe".format( + room_id=room_id, + ), + "json": json_json_body, + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == HTTPStatus.CREATED: + response_201 = cast(Any, None) + return response_201 + if response.status_code == HTTPStatus.BAD_REQUEST: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: SubscriptionConfig, +) -> Response[Union[Any, Error]]: + """Subscribe hls component for tracks + + Args: + room_id (str): + json_body (SubscriptionConfig): Subscription config + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + json_body=json_body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: SubscriptionConfig, +) -> Optional[Union[Any, Error]]: + """Subscribe hls component for tracks + + Args: + room_id (str): + json_body (SubscriptionConfig): Subscription config + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + room_id=room_id, + client=client, + json_body=json_body, + ).parsed + + +async def asyncio_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: SubscriptionConfig, +) -> Response[Union[Any, Error]]: + """Subscribe hls component for tracks + + Args: + room_id (str): + json_body (SubscriptionConfig): Subscription config + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + json_body=json_body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: SubscriptionConfig, +) -> Optional[Union[Any, Error]]: + """Subscribe hls component for tracks + + Args: + room_id (str): + json_body (SubscriptionConfig): Subscription config + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + client=client, + json_body=json_body, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/hls_api.py b/jellyfish/_openapi_client/api/hls_api.py deleted file mode 100644 index db66759..0000000 --- a/jellyfish/_openapi_client/api/hls_api.py +++ /dev/null @@ -1,435 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import re # noqa: F401 -import io -import warnings - -from pydantic import validate_arguments, ValidationError -from typing_extensions import Annotated - -from pydantic import Field, StrictStr, conint - -from typing import Optional - -from jellyfish._openapi_client.models.hls_skip import HlsSkip -from jellyfish._openapi_client.models.subscription_config import SubscriptionConfig - -from jellyfish._openapi_client.api_client import ApiClient -from jellyfish._openapi_client.api_response import ApiResponse -from jellyfish._openapi_client.exceptions import ( # noqa: F401 - ApiTypeError, - ApiValueError, -) - - -class HlsApi(object): - """NOTE: This class is auto generated by OpenAPI Generator - Ref: https://openapi-generator.tech - - Do not edit the class manually. - """ - - def __init__(self, api_client=None): - if api_client is None: - api_client = ApiClient.get_default() - self.api_client = api_client - - @validate_arguments - def get_hls_content( - self, - room_id: Annotated[StrictStr, Field(..., description="Room id")], - filename: Annotated[StrictStr, Field(..., description="Name of the file")], - range: Annotated[ - Optional[StrictStr], Field(description="Byte range of partial segment") - ] = None, - hls_msn: Annotated[ - Optional[conint(strict=True, ge=0)], - Field(description="Segment sequence number"), - ] = None, - hls_part: Annotated[ - Optional[conint(strict=True, ge=0)], - Field(description="Partial segment sequence number"), - ] = None, - hls_skip: Annotated[ - Optional[HlsSkip], Field(description="Is delta manifest requested") - ] = None, - **kwargs - ) -> str: # noqa: E501 - """Retrieve HLS Content # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_hls_content(room_id, filename, range, hls_msn, hls_part, hls_skip, async_req=True) - >>> result = thread.get() - - :param room_id: Room id (required) - :type room_id: str - :param filename: Name of the file (required) - :type filename: str - :param range: Byte range of partial segment - :type range: str - :param hls_msn: Segment sequence number - :type hls_msn: int - :param hls_part: Partial segment sequence number - :type hls_part: int - :param hls_skip: Is delta manifest requested - :type hls_skip: HlsSkip - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: str - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the get_hls_content_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.get_hls_content_with_http_info( - room_id, filename, range, hls_msn, hls_part, hls_skip, **kwargs - ) # noqa: E501 - - @validate_arguments - def get_hls_content_with_http_info( - self, - room_id: Annotated[StrictStr, Field(..., description="Room id")], - filename: Annotated[StrictStr, Field(..., description="Name of the file")], - range: Annotated[ - Optional[StrictStr], Field(description="Byte range of partial segment") - ] = None, - hls_msn: Annotated[ - Optional[conint(strict=True, ge=0)], - Field(description="Segment sequence number"), - ] = None, - hls_part: Annotated[ - Optional[conint(strict=True, ge=0)], - Field(description="Partial segment sequence number"), - ] = None, - hls_skip: Annotated[ - Optional[HlsSkip], Field(description="Is delta manifest requested") - ] = None, - **kwargs - ) -> ApiResponse: # noqa: E501 - """Retrieve HLS Content # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_hls_content_with_http_info(room_id, filename, range, hls_msn, hls_part, hls_skip, async_req=True) - >>> result = thread.get() - - :param room_id: Room id (required) - :type room_id: str - :param filename: Name of the file (required) - :type filename: str - :param range: Byte range of partial segment - :type range: str - :param hls_msn: Segment sequence number - :type hls_msn: int - :param hls_part: Partial segment sequence number - :type hls_part: int - :param hls_skip: Is delta manifest requested - :type hls_skip: HlsSkip - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: tuple(str, status_code(int), headers(HTTPHeaderDict)) - """ - - _params = locals() - - _all_params = [ - "room_id", - "filename", - "range", - "hls_msn", - "hls_part", - "hls_skip", - ] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method get_hls_content" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["room_id"]: - _path_params["room_id"] = _params["room_id"] - - if _params["filename"]: - _path_params["filename"] = _params["filename"] - - # process the query parameters - _query_params = [] - if _params.get("hls_msn") is not None: # noqa: E501 - _query_params.append(("_HLS_msn", _params["hls_msn"])) - - if _params.get("hls_part") is not None: # noqa: E501 - _query_params.append(("_HLS_part", _params["hls_part"])) - - if _params.get("hls_skip") is not None: # noqa: E501 - _query_params.append(("_HLS_skip", _params["hls_skip"].value)) - - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - if _params["range"]: - _header_params["range"] = _params["range"] - - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = { - "200": "str", - "404": "Error", - } - - return self.api_client.call_api( - "/hls/{room_id}/{filename}", - "GET", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def subscribe_tracks( - self, - room_id: Annotated[StrictStr, Field(..., description="Room ID")], - subscription_config: Annotated[ - Optional[SubscriptionConfig], Field(description="Subscribe configuration") - ] = None, - **kwargs - ) -> None: # noqa: E501 - """Subscribe hls component for tracks # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.subscribe_tracks(room_id, subscription_config, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param subscription_config: Subscribe configuration - :type subscription_config: SubscriptionConfig - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the subscribe_tracks_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.subscribe_tracks_with_http_info( - room_id, subscription_config, **kwargs - ) # noqa: E501 - - @validate_arguments - def subscribe_tracks_with_http_info( - self, - room_id: Annotated[StrictStr, Field(..., description="Room ID")], - subscription_config: Annotated[ - Optional[SubscriptionConfig], Field(description="Subscribe configuration") - ] = None, - **kwargs - ) -> ApiResponse: # noqa: E501 - """Subscribe hls component for tracks # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.subscribe_tracks_with_http_info(room_id, subscription_config, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param subscription_config: Subscribe configuration - :type subscription_config: SubscriptionConfig - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - - _params = locals() - - _all_params = ["room_id", "subscription_config"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method subscribe_tracks" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["room_id"]: - _path_params["room_id"] = _params["room_id"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - if _params["subscription_config"] is not None: - _body_params = _params["subscription_config"] - - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # set the HTTP header `Content-Type` - _content_types_list = _params.get( - "_content_type", - self.api_client.select_header_content_type(["application/json"]), - ) - if _content_types_list: - _header_params["Content-Type"] = _content_types_list - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = {} - - return self.api_client.call_api( - "/hls/{room_id}/subscribe", - "POST", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) diff --git a/jellyfish/_openapi_client/api/recording/__init__.py b/jellyfish/_openapi_client/api/recording/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/jellyfish/_openapi_client/api/recording/delete_recording.py b/jellyfish/_openapi_client/api/recording/delete_recording.py new file mode 100644 index 0000000..ae6ba21 --- /dev/null +++ b/jellyfish/_openapi_client/api/recording/delete_recording.py @@ -0,0 +1,157 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + recording_id: str, +) -> Dict[str, Any]: + return { + "method": "delete", + "url": "/recording/{recording_id}".format( + recording_id=recording_id, + ), + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == HTTPStatus.NO_CONTENT: + response_204 = cast(Any, None) + return response_204 + if response.status_code == HTTPStatus.BAD_REQUEST: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + recording_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Any, Error]]: + """Deletes the recording + + Args: + recording_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + recording_id=recording_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + recording_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Any, Error]]: + """Deletes the recording + + Args: + recording_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + recording_id=recording_id, + client=client, + ).parsed + + +async def asyncio_detailed( + recording_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Any, Error]]: + """Deletes the recording + + Args: + recording_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + recording_id=recording_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + recording_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Any, Error]]: + """Deletes the recording + + Args: + recording_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + recording_id=recording_id, + client=client, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/recording/get_recording_content.py b/jellyfish/_openapi_client/api/recording/get_recording_content.py new file mode 100644 index 0000000..436b522 --- /dev/null +++ b/jellyfish/_openapi_client/api/recording/get_recording_content.py @@ -0,0 +1,171 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + recording_id: str, + filename: str, +) -> Dict[str, Any]: + return { + "method": "get", + "url": "/recording/{recording_id}/{filename}".format( + recording_id=recording_id, + filename=filename, + ), + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, str]]: + if response.status_code == HTTPStatus.OK: + response_200 = cast(str, response.json()) + return response_200 + if response.status_code == HTTPStatus.BAD_REQUEST: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, str]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + recording_id: str, + filename: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Error, str]]: + """Retrieve Recording (HLS) Content + + Args: + recording_id (str): + filename (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, str]] + """ + + kwargs = _get_kwargs( + recording_id=recording_id, + filename=filename, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + recording_id: str, + filename: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Error, str]]: + """Retrieve Recording (HLS) Content + + Args: + recording_id (str): + filename (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, str] + """ + + return sync_detailed( + recording_id=recording_id, + filename=filename, + client=client, + ).parsed + + +async def asyncio_detailed( + recording_id: str, + filename: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Error, str]]: + """Retrieve Recording (HLS) Content + + Args: + recording_id (str): + filename (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, str]] + """ + + kwargs = _get_kwargs( + recording_id=recording_id, + filename=filename, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + recording_id: str, + filename: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Error, str]]: + """Retrieve Recording (HLS) Content + + Args: + recording_id (str): + filename (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, str] + """ + + return ( + await asyncio_detailed( + recording_id=recording_id, + filename=filename, + client=client, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/recording/get_recordings.py b/jellyfish/_openapi_client/api/recording/get_recordings.py new file mode 100644 index 0000000..8855ab9 --- /dev/null +++ b/jellyfish/_openapi_client/api/recording/get_recordings.py @@ -0,0 +1,129 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.recording_list_response import RecordingListResponse +from ...types import Response + + +def _get_kwargs() -> Dict[str, Any]: + return { + "method": "get", + "url": "/recording", + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, RecordingListResponse]]: + if response.status_code == HTTPStatus.OK: + response_200 = RecordingListResponse.from_dict(response.json()) + + return response_200 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, RecordingListResponse]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Error, RecordingListResponse]]: + """Lists all available recordings + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, RecordingListResponse]] + """ + + kwargs = _get_kwargs() + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Error, RecordingListResponse]]: + """Lists all available recordings + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, RecordingListResponse] + """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Error, RecordingListResponse]]: + """Lists all available recordings + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, RecordingListResponse]] + """ + + kwargs = _get_kwargs() + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Error, RecordingListResponse]]: + """Lists all available recordings + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, RecordingListResponse] + """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/recording_api.py b/jellyfish/_openapi_client/api/recording_api.py deleted file mode 100644 index bfa91a9..0000000 --- a/jellyfish/_openapi_client/api/recording_api.py +++ /dev/null @@ -1,484 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import re # noqa: F401 -import io -import warnings - -from pydantic import validate_arguments, ValidationError -from typing_extensions import Annotated - -from pydantic import Field, StrictStr - -from jellyfish._openapi_client.models.recording_list_response import ( - RecordingListResponse, -) - -from jellyfish._openapi_client.api_client import ApiClient -from jellyfish._openapi_client.api_response import ApiResponse -from jellyfish._openapi_client.exceptions import ( # noqa: F401 - ApiTypeError, - ApiValueError, -) - - -class RecordingApi(object): - """NOTE: This class is auto generated by OpenAPI Generator - Ref: https://openapi-generator.tech - - Do not edit the class manually. - """ - - def __init__(self, api_client=None): - if api_client is None: - api_client = ApiClient.get_default() - self.api_client = api_client - - @validate_arguments - def delete_recording( - self, - recording_id: Annotated[StrictStr, Field(..., description="Recording id")], - **kwargs - ) -> None: # noqa: E501 - """Deletes the recording # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.delete_recording(recording_id, async_req=True) - >>> result = thread.get() - - :param recording_id: Recording id (required) - :type recording_id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the delete_recording_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.delete_recording_with_http_info( - recording_id, **kwargs - ) # noqa: E501 - - @validate_arguments - def delete_recording_with_http_info( - self, - recording_id: Annotated[StrictStr, Field(..., description="Recording id")], - **kwargs - ) -> ApiResponse: # noqa: E501 - """Deletes the recording # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.delete_recording_with_http_info(recording_id, async_req=True) - >>> result = thread.get() - - :param recording_id: Recording id (required) - :type recording_id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - - _params = locals() - - _all_params = ["recording_id"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method delete_recording" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["recording_id"]: - _path_params["recording_id"] = _params["recording_id"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = {} - - return self.api_client.call_api( - "/recording/{recording_id}", - "DELETE", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def get_recording_content( - self, - recording_id: Annotated[StrictStr, Field(..., description="Recording id")], - filename: Annotated[StrictStr, Field(..., description="Name of the file")], - **kwargs - ) -> str: # noqa: E501 - """Retrieve Recording (HLS) Content # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_recording_content(recording_id, filename, async_req=True) - >>> result = thread.get() - - :param recording_id: Recording id (required) - :type recording_id: str - :param filename: Name of the file (required) - :type filename: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: str - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the get_recording_content_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.get_recording_content_with_http_info( - recording_id, filename, **kwargs - ) # noqa: E501 - - @validate_arguments - def get_recording_content_with_http_info( - self, - recording_id: Annotated[StrictStr, Field(..., description="Recording id")], - filename: Annotated[StrictStr, Field(..., description="Name of the file")], - **kwargs - ) -> ApiResponse: # noqa: E501 - """Retrieve Recording (HLS) Content # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_recording_content_with_http_info(recording_id, filename, async_req=True) - >>> result = thread.get() - - :param recording_id: Recording id (required) - :type recording_id: str - :param filename: Name of the file (required) - :type filename: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: tuple(str, status_code(int), headers(HTTPHeaderDict)) - """ - - _params = locals() - - _all_params = ["recording_id", "filename"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method get_recording_content" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["recording_id"]: - _path_params["recording_id"] = _params["recording_id"] - - if _params["filename"]: - _path_params["filename"] = _params["filename"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = { - "200": "str", - "404": "Error", - } - - return self.api_client.call_api( - "/recording/{recording_id}/{filename}", - "GET", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def get_recordings(self, **kwargs) -> RecordingListResponse: # noqa: E501 - """Lists all available recordings # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_recordings(async_req=True) - >>> result = thread.get() - - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: RecordingListResponse - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the get_recordings_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.get_recordings_with_http_info(**kwargs) # noqa: E501 - - @validate_arguments - def get_recordings_with_http_info(self, **kwargs) -> ApiResponse: # noqa: E501 - """Lists all available recordings # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_recordings_with_http_info(async_req=True) - >>> result = thread.get() - - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: tuple(RecordingListResponse, status_code(int), headers(HTTPHeaderDict)) - """ - - _params = locals() - - _all_params = [] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method get_recordings" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = { - "200": "RecordingListResponse", - "404": "Error", - } - - return self.api_client.call_api( - "/recording", - "GET", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) diff --git a/jellyfish/_openapi_client/api/room/__init__.py b/jellyfish/_openapi_client/api/room/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/jellyfish/_openapi_client/api/room/add_component.py b/jellyfish/_openapi_client/api/room/add_component.py new file mode 100644 index 0000000..376628c --- /dev/null +++ b/jellyfish/_openapi_client/api/room/add_component.py @@ -0,0 +1,181 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.add_component_json_body import AddComponentJsonBody +from ...models.component_details_response import ComponentDetailsResponse +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + room_id: str, + *, + json_body: AddComponentJsonBody, +) -> Dict[str, Any]: + json_json_body = json_body.to_dict() + + return { + "method": "post", + "url": "/room/{room_id}/component".format( + room_id=room_id, + ), + "json": json_json_body, + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[ComponentDetailsResponse, Error]]: + if response.status_code == HTTPStatus.CREATED: + response_201 = ComponentDetailsResponse.from_dict(response.json()) + + return response_201 + if response.status_code == HTTPStatus.BAD_REQUEST: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == HTTPStatus.UNAUTHORIZED: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[ComponentDetailsResponse, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: AddComponentJsonBody, +) -> Response[Union[ComponentDetailsResponse, Error]]: + """Creates the component and adds it to the room + + Args: + room_id (str): + json_body (AddComponentJsonBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[ComponentDetailsResponse, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + json_body=json_body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: AddComponentJsonBody, +) -> Optional[Union[ComponentDetailsResponse, Error]]: + """Creates the component and adds it to the room + + Args: + room_id (str): + json_body (AddComponentJsonBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[ComponentDetailsResponse, Error] + """ + + return sync_detailed( + room_id=room_id, + client=client, + json_body=json_body, + ).parsed + + +async def asyncio_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: AddComponentJsonBody, +) -> Response[Union[ComponentDetailsResponse, Error]]: + """Creates the component and adds it to the room + + Args: + room_id (str): + json_body (AddComponentJsonBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[ComponentDetailsResponse, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + json_body=json_body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: AddComponentJsonBody, +) -> Optional[Union[ComponentDetailsResponse, Error]]: + """Creates the component and adds it to the room + + Args: + room_id (str): + json_body (AddComponentJsonBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[ComponentDetailsResponse, Error] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + client=client, + json_body=json_body, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/room/add_peer.py b/jellyfish/_openapi_client/api/room/add_peer.py new file mode 100644 index 0000000..82a3b18 --- /dev/null +++ b/jellyfish/_openapi_client/api/room/add_peer.py @@ -0,0 +1,185 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.add_peer_json_body import AddPeerJsonBody +from ...models.error import Error +from ...models.peer_details_response import PeerDetailsResponse +from ...types import Response + + +def _get_kwargs( + room_id: str, + *, + json_body: AddPeerJsonBody, +) -> Dict[str, Any]: + json_json_body = json_body.to_dict() + + return { + "method": "post", + "url": "/room/{room_id}/peer".format( + room_id=room_id, + ), + "json": json_json_body, + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, PeerDetailsResponse]]: + if response.status_code == HTTPStatus.CREATED: + response_201 = PeerDetailsResponse.from_dict(response.json()) + + return response_201 + if response.status_code == HTTPStatus.BAD_REQUEST: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == HTTPStatus.UNAUTHORIZED: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if response.status_code == HTTPStatus.SERVICE_UNAVAILABLE: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, PeerDetailsResponse]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: AddPeerJsonBody, +) -> Response[Union[Error, PeerDetailsResponse]]: + """Create peer + + Args: + room_id (str): + json_body (AddPeerJsonBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, PeerDetailsResponse]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + json_body=json_body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: AddPeerJsonBody, +) -> Optional[Union[Error, PeerDetailsResponse]]: + """Create peer + + Args: + room_id (str): + json_body (AddPeerJsonBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, PeerDetailsResponse] + """ + + return sync_detailed( + room_id=room_id, + client=client, + json_body=json_body, + ).parsed + + +async def asyncio_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: AddPeerJsonBody, +) -> Response[Union[Error, PeerDetailsResponse]]: + """Create peer + + Args: + room_id (str): + json_body (AddPeerJsonBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, PeerDetailsResponse]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + json_body=json_body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], + json_body: AddPeerJsonBody, +) -> Optional[Union[Error, PeerDetailsResponse]]: + """Create peer + + Args: + room_id (str): + json_body (AddPeerJsonBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, PeerDetailsResponse] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + client=client, + json_body=json_body, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/room/create_room.py b/jellyfish/_openapi_client/api/room/create_room.py new file mode 100644 index 0000000..c03f2a1 --- /dev/null +++ b/jellyfish/_openapi_client/api/room/create_room.py @@ -0,0 +1,162 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.room_config import RoomConfig +from ...models.room_create_details_response import RoomCreateDetailsResponse +from ...types import Response + + +def _get_kwargs( + *, + json_body: RoomConfig, +) -> Dict[str, Any]: + json_json_body = json_body.to_dict() + + return { + "method": "post", + "url": "/room", + "json": json_json_body, + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, RoomCreateDetailsResponse]]: + if response.status_code == HTTPStatus.CREATED: + response_201 = RoomCreateDetailsResponse.from_dict(response.json()) + + return response_201 + if response.status_code == HTTPStatus.BAD_REQUEST: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == HTTPStatus.UNAUTHORIZED: + response_401 = Error.from_dict(response.json()) + + return response_401 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, RoomCreateDetailsResponse]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: Union[AuthenticatedClient, Client], + json_body: RoomConfig, +) -> Response[Union[Error, RoomCreateDetailsResponse]]: + """Creates a room + + Args: + json_body (RoomConfig): Room configuration + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, RoomCreateDetailsResponse]] + """ + + kwargs = _get_kwargs( + json_body=json_body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: Union[AuthenticatedClient, Client], + json_body: RoomConfig, +) -> Optional[Union[Error, RoomCreateDetailsResponse]]: + """Creates a room + + Args: + json_body (RoomConfig): Room configuration + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, RoomCreateDetailsResponse] + """ + + return sync_detailed( + client=client, + json_body=json_body, + ).parsed + + +async def asyncio_detailed( + *, + client: Union[AuthenticatedClient, Client], + json_body: RoomConfig, +) -> Response[Union[Error, RoomCreateDetailsResponse]]: + """Creates a room + + Args: + json_body (RoomConfig): Room configuration + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, RoomCreateDetailsResponse]] + """ + + kwargs = _get_kwargs( + json_body=json_body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: Union[AuthenticatedClient, Client], + json_body: RoomConfig, +) -> Optional[Union[Error, RoomCreateDetailsResponse]]: + """Creates a room + + Args: + json_body (RoomConfig): Room configuration + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, RoomCreateDetailsResponse] + """ + + return ( + await asyncio_detailed( + client=client, + json_body=json_body, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/room/delete_component.py b/jellyfish/_openapi_client/api/room/delete_component.py new file mode 100644 index 0000000..c5fc775 --- /dev/null +++ b/jellyfish/_openapi_client/api/room/delete_component.py @@ -0,0 +1,171 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + room_id: str, + id: str, +) -> Dict[str, Any]: + return { + "method": "delete", + "url": "/room/{room_id}/component/{id}".format( + room_id=room_id, + id=id, + ), + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == HTTPStatus.NO_CONTENT: + response_204 = cast(Any, None) + return response_204 + if response.status_code == HTTPStatus.UNAUTHORIZED: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Any, Error]]: + """Delete the component from the room + + Args: + room_id (str): + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Any, Error]]: + """Delete the component from the room + + Args: + room_id (str): + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + room_id=room_id, + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + room_id: str, + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Any, Error]]: + """Delete the component from the room + + Args: + room_id (str): + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Any, Error]]: + """Delete the component from the room + + Args: + room_id (str): + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + id=id, + client=client, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/room/delete_peer.py b/jellyfish/_openapi_client/api/room/delete_peer.py new file mode 100644 index 0000000..e6045df --- /dev/null +++ b/jellyfish/_openapi_client/api/room/delete_peer.py @@ -0,0 +1,171 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + room_id: str, + id: str, +) -> Dict[str, Any]: + return { + "method": "delete", + "url": "/room/{room_id}/peer/{id}".format( + room_id=room_id, + id=id, + ), + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == HTTPStatus.NO_CONTENT: + response_204 = cast(Any, None) + return response_204 + if response.status_code == HTTPStatus.UNAUTHORIZED: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Any, Error]]: + """Delete peer + + Args: + room_id (str): + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Any, Error]]: + """Delete peer + + Args: + room_id (str): + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + room_id=room_id, + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + room_id: str, + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Any, Error]]: + """Delete peer + + Args: + room_id (str): + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Any, Error]]: + """Delete peer + + Args: + room_id (str): + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + id=id, + client=client, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/room/delete_room.py b/jellyfish/_openapi_client/api/room/delete_room.py new file mode 100644 index 0000000..1ccbcd6 --- /dev/null +++ b/jellyfish/_openapi_client/api/room/delete_room.py @@ -0,0 +1,157 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + room_id: str, +) -> Dict[str, Any]: + return { + "method": "delete", + "url": "/room/{room_id}".format( + room_id=room_id, + ), + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == HTTPStatus.NO_CONTENT: + response_204 = cast(Any, None) + return response_204 + if response.status_code == HTTPStatus.UNAUTHORIZED: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Any, Error]]: + """Delete the room + + Args: + room_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Any, Error]]: + """Delete the room + + Args: + room_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + room_id=room_id, + client=client, + ).parsed + + +async def asyncio_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Any, Error]]: + """Delete the room + + Args: + room_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Any, Error]]: + """Delete the room + + Args: + room_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + client=client, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/room/get_all_rooms.py b/jellyfish/_openapi_client/api/room/get_all_rooms.py new file mode 100644 index 0000000..149daf5 --- /dev/null +++ b/jellyfish/_openapi_client/api/room/get_all_rooms.py @@ -0,0 +1,129 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.rooms_listing_response import RoomsListingResponse +from ...types import Response + + +def _get_kwargs() -> Dict[str, Any]: + return { + "method": "get", + "url": "/room", + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, RoomsListingResponse]]: + if response.status_code == HTTPStatus.OK: + response_200 = RoomsListingResponse.from_dict(response.json()) + + return response_200 + if response.status_code == HTTPStatus.UNAUTHORIZED: + response_401 = Error.from_dict(response.json()) + + return response_401 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, RoomsListingResponse]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Error, RoomsListingResponse]]: + """Show information about all rooms + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, RoomsListingResponse]] + """ + + kwargs = _get_kwargs() + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Error, RoomsListingResponse]]: + """Show information about all rooms + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, RoomsListingResponse] + """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Error, RoomsListingResponse]]: + """Show information about all rooms + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, RoomsListingResponse]] + """ + + kwargs = _get_kwargs() + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Error, RoomsListingResponse]]: + """Show information about all rooms + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, RoomsListingResponse] + """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/room/get_room.py b/jellyfish/_openapi_client/api/room/get_room.py new file mode 100644 index 0000000..f6a60ba --- /dev/null +++ b/jellyfish/_openapi_client/api/room/get_room.py @@ -0,0 +1,159 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.room_details_response import RoomDetailsResponse +from ...types import Response + + +def _get_kwargs( + room_id: str, +) -> Dict[str, Any]: + return { + "method": "get", + "url": "/room/{room_id}".format( + room_id=room_id, + ), + } + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, RoomDetailsResponse]]: + if response.status_code == HTTPStatus.OK: + response_200 = RoomDetailsResponse.from_dict(response.json()) + + return response_200 + if response.status_code == HTTPStatus.UNAUTHORIZED: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == HTTPStatus.NOT_FOUND: + response_404 = Error.from_dict(response.json()) + + return response_404 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, RoomDetailsResponse]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Error, RoomDetailsResponse]]: + """Shows information about the room + + Args: + room_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, RoomDetailsResponse]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Error, RoomDetailsResponse]]: + """Shows information about the room + + Args: + room_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, RoomDetailsResponse] + """ + + return sync_detailed( + room_id=room_id, + client=client, + ).parsed + + +async def asyncio_detailed( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Union[Error, RoomDetailsResponse]]: + """Shows information about the room + + Args: + room_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, RoomDetailsResponse]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Union[Error, RoomDetailsResponse]]: + """Shows information about the room + + Args: + room_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, RoomDetailsResponse] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + client=client, + ) + ).parsed diff --git a/jellyfish/_openapi_client/api/room_api.py b/jellyfish/_openapi_client/api/room_api.py deleted file mode 100644 index d8ef113..0000000 --- a/jellyfish/_openapi_client/api/room_api.py +++ /dev/null @@ -1,1292 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import re # noqa: F401 -import io -import warnings - -from pydantic import validate_arguments, ValidationError -from typing_extensions import Annotated - -from pydantic import Field, StrictStr - -from typing import Optional - -from jellyfish._openapi_client.models.add_component_request import AddComponentRequest -from jellyfish._openapi_client.models.add_peer_request import AddPeerRequest -from jellyfish._openapi_client.models.component_details_response import ( - ComponentDetailsResponse, -) -from jellyfish._openapi_client.models.peer_details_response import PeerDetailsResponse -from jellyfish._openapi_client.models.room_config import RoomConfig -from jellyfish._openapi_client.models.room_create_details_response import ( - RoomCreateDetailsResponse, -) -from jellyfish._openapi_client.models.room_details_response import RoomDetailsResponse -from jellyfish._openapi_client.models.rooms_listing_response import RoomsListingResponse - -from jellyfish._openapi_client.api_client import ApiClient -from jellyfish._openapi_client.api_response import ApiResponse -from jellyfish._openapi_client.exceptions import ( # noqa: F401 - ApiTypeError, - ApiValueError, -) - - -class RoomApi(object): - """NOTE: This class is auto generated by OpenAPI Generator - Ref: https://openapi-generator.tech - - Do not edit the class manually. - """ - - def __init__(self, api_client=None): - if api_client is None: - api_client = ApiClient.get_default() - self.api_client = api_client - - @validate_arguments - def add_component( - self, - room_id: Annotated[StrictStr, Field(..., description="Room ID")], - add_component_request: Annotated[ - Optional[AddComponentRequest], Field(description="Component config") - ] = None, - **kwargs - ) -> ComponentDetailsResponse: # noqa: E501 - """Creates the component and adds it to the room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.add_component(room_id, add_component_request, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param add_component_request: Component config - :type add_component_request: AddComponentRequest - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: ComponentDetailsResponse - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the add_component_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.add_component_with_http_info( - room_id, add_component_request, **kwargs - ) # noqa: E501 - - @validate_arguments - def add_component_with_http_info( - self, - room_id: Annotated[StrictStr, Field(..., description="Room ID")], - add_component_request: Annotated[ - Optional[AddComponentRequest], Field(description="Component config") - ] = None, - **kwargs - ) -> ApiResponse: # noqa: E501 - """Creates the component and adds it to the room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.add_component_with_http_info(room_id, add_component_request, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param add_component_request: Component config - :type add_component_request: AddComponentRequest - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: tuple(ComponentDetailsResponse, status_code(int), headers(HTTPHeaderDict)) - """ - - _params = locals() - - _all_params = ["room_id", "add_component_request"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method add_component" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["room_id"]: - _path_params["room_id"] = _params["room_id"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - if _params["add_component_request"] is not None: - _body_params = _params["add_component_request"] - - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # set the HTTP header `Content-Type` - _content_types_list = _params.get( - "_content_type", - self.api_client.select_header_content_type(["application/json"]), - ) - if _content_types_list: - _header_params["Content-Type"] = _content_types_list - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = { - "201": "ComponentDetailsResponse", - "400": "Error", - "401": "Error", - "404": "Error", - } - - return self.api_client.call_api( - "/room/{room_id}/component", - "POST", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def add_peer( - self, - room_id: Annotated[StrictStr, Field(..., description="Room id")], - add_peer_request: Annotated[ - Optional[AddPeerRequest], Field(description="Peer specification") - ] = None, - **kwargs - ) -> PeerDetailsResponse: # noqa: E501 - """Create peer # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.add_peer(room_id, add_peer_request, async_req=True) - >>> result = thread.get() - - :param room_id: Room id (required) - :type room_id: str - :param add_peer_request: Peer specification - :type add_peer_request: AddPeerRequest - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: PeerDetailsResponse - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the add_peer_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.add_peer_with_http_info( - room_id, add_peer_request, **kwargs - ) # noqa: E501 - - @validate_arguments - def add_peer_with_http_info( - self, - room_id: Annotated[StrictStr, Field(..., description="Room id")], - add_peer_request: Annotated[ - Optional[AddPeerRequest], Field(description="Peer specification") - ] = None, - **kwargs - ) -> ApiResponse: # noqa: E501 - """Create peer # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.add_peer_with_http_info(room_id, add_peer_request, async_req=True) - >>> result = thread.get() - - :param room_id: Room id (required) - :type room_id: str - :param add_peer_request: Peer specification - :type add_peer_request: AddPeerRequest - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: tuple(PeerDetailsResponse, status_code(int), headers(HTTPHeaderDict)) - """ - - _params = locals() - - _all_params = ["room_id", "add_peer_request"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method add_peer" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["room_id"]: - _path_params["room_id"] = _params["room_id"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - if _params["add_peer_request"] is not None: - _body_params = _params["add_peer_request"] - - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # set the HTTP header `Content-Type` - _content_types_list = _params.get( - "_content_type", - self.api_client.select_header_content_type(["application/json"]), - ) - if _content_types_list: - _header_params["Content-Type"] = _content_types_list - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = { - "201": "PeerDetailsResponse", - "400": "Error", - "401": "Error", - "404": "Error", - "503": "Error", - } - - return self.api_client.call_api( - "/room/{room_id}/peer", - "POST", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def create_room( - self, - room_config: Annotated[ - Optional[RoomConfig], Field(description="Room configuration") - ] = None, - **kwargs - ) -> RoomCreateDetailsResponse: # noqa: E501 - """Creates a room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.create_room(room_config, async_req=True) - >>> result = thread.get() - - :param room_config: Room configuration - :type room_config: RoomConfig - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: RoomCreateDetailsResponse - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the create_room_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.create_room_with_http_info(room_config, **kwargs) # noqa: E501 - - @validate_arguments - def create_room_with_http_info( - self, - room_config: Annotated[ - Optional[RoomConfig], Field(description="Room configuration") - ] = None, - **kwargs - ) -> ApiResponse: # noqa: E501 - """Creates a room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.create_room_with_http_info(room_config, async_req=True) - >>> result = thread.get() - - :param room_config: Room configuration - :type room_config: RoomConfig - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: tuple(RoomCreateDetailsResponse, status_code(int), headers(HTTPHeaderDict)) - """ - - _params = locals() - - _all_params = ["room_config"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method create_room" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - if _params["room_config"] is not None: - _body_params = _params["room_config"] - - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # set the HTTP header `Content-Type` - _content_types_list = _params.get( - "_content_type", - self.api_client.select_header_content_type(["application/json"]), - ) - if _content_types_list: - _header_params["Content-Type"] = _content_types_list - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = { - "201": "RoomCreateDetailsResponse", - "400": "Error", - "401": "Error", - } - - return self.api_client.call_api( - "/room", - "POST", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def delete_component( - self, - room_id: Annotated[StrictStr, Field(..., description="Room ID")], - id: Annotated[StrictStr, Field(..., description="Component ID")], - **kwargs - ) -> None: # noqa: E501 - """Delete the component from the room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.delete_component(room_id, id, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param id: Component ID (required) - :type id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the delete_component_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.delete_component_with_http_info(room_id, id, **kwargs) # noqa: E501 - - @validate_arguments - def delete_component_with_http_info( - self, - room_id: Annotated[StrictStr, Field(..., description="Room ID")], - id: Annotated[StrictStr, Field(..., description="Component ID")], - **kwargs - ) -> ApiResponse: # noqa: E501 - """Delete the component from the room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.delete_component_with_http_info(room_id, id, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param id: Component ID (required) - :type id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - - _params = locals() - - _all_params = ["room_id", "id"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method delete_component" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["room_id"]: - _path_params["room_id"] = _params["room_id"] - - if _params["id"]: - _path_params["id"] = _params["id"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = {} - - return self.api_client.call_api( - "/room/{room_id}/component/{id}", - "DELETE", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def delete_peer( - self, - room_id: Annotated[StrictStr, Field(..., description="Room ID")], - id: Annotated[StrictStr, Field(..., description="Peer id")], - **kwargs - ) -> None: # noqa: E501 - """Delete peer # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.delete_peer(room_id, id, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param id: Peer id (required) - :type id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the delete_peer_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.delete_peer_with_http_info(room_id, id, **kwargs) # noqa: E501 - - @validate_arguments - def delete_peer_with_http_info( - self, - room_id: Annotated[StrictStr, Field(..., description="Room ID")], - id: Annotated[StrictStr, Field(..., description="Peer id")], - **kwargs - ) -> ApiResponse: # noqa: E501 - """Delete peer # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.delete_peer_with_http_info(room_id, id, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param id: Peer id (required) - :type id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - - _params = locals() - - _all_params = ["room_id", "id"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method delete_peer" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["room_id"]: - _path_params["room_id"] = _params["room_id"] - - if _params["id"]: - _path_params["id"] = _params["id"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = {} - - return self.api_client.call_api( - "/room/{room_id}/peer/{id}", - "DELETE", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def delete_room( - self, room_id: Annotated[StrictStr, Field(..., description="Room id")], **kwargs - ) -> None: # noqa: E501 - """Delete the room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.delete_room(room_id, async_req=True) - >>> result = thread.get() - - :param room_id: Room id (required) - :type room_id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the delete_room_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.delete_room_with_http_info(room_id, **kwargs) # noqa: E501 - - @validate_arguments - def delete_room_with_http_info( - self, room_id: Annotated[StrictStr, Field(..., description="Room id")], **kwargs - ) -> ApiResponse: # noqa: E501 - """Delete the room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.delete_room_with_http_info(room_id, async_req=True) - >>> result = thread.get() - - :param room_id: Room id (required) - :type room_id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: None - """ - - _params = locals() - - _all_params = ["room_id"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method delete_room" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["room_id"]: - _path_params["room_id"] = _params["room_id"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = {} - - return self.api_client.call_api( - "/room/{room_id}", - "DELETE", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def get_all_rooms(self, **kwargs) -> RoomsListingResponse: # noqa: E501 - """Show information about all rooms # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_all_rooms(async_req=True) - >>> result = thread.get() - - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: RoomsListingResponse - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the get_all_rooms_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.get_all_rooms_with_http_info(**kwargs) # noqa: E501 - - @validate_arguments - def get_all_rooms_with_http_info(self, **kwargs) -> ApiResponse: # noqa: E501 - """Show information about all rooms # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_all_rooms_with_http_info(async_req=True) - >>> result = thread.get() - - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: tuple(RoomsListingResponse, status_code(int), headers(HTTPHeaderDict)) - """ - - _params = locals() - - _all_params = [] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method get_all_rooms" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = { - "200": "RoomsListingResponse", - "401": "Error", - } - - return self.api_client.call_api( - "/room", - "GET", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) - - @validate_arguments - def get_room( - self, room_id: Annotated[StrictStr, Field(..., description="Room ID")], **kwargs - ) -> RoomDetailsResponse: # noqa: E501 - """Shows information about the room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_room(room_id, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: RoomDetailsResponse - """ - kwargs["_return_http_data_only"] = True - if "_preload_content" in kwargs: - raise ValueError( - "Error! Please call the get_room_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" - ) - return self.get_room_with_http_info(room_id, **kwargs) # noqa: E501 - - @validate_arguments - def get_room_with_http_info( - self, room_id: Annotated[StrictStr, Field(..., description="Room ID")], **kwargs - ) -> ApiResponse: # noqa: E501 - """Shows information about the room # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.get_room_with_http_info(room_id, async_req=True) - >>> result = thread.get() - - :param room_id: Room ID (required) - :type room_id: str - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :type _preload_content: bool, optional - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :type _return_http_data_only: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :type _content_type: string, optional: force content-type for the request - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: tuple(RoomDetailsResponse, status_code(int), headers(HTTPHeaderDict)) - """ - - _params = locals() - - _all_params = ["room_id"] - _all_params.extend( - [ - "async_req", - "_return_http_data_only", - "_preload_content", - "_request_timeout", - "_request_auth", - "_content_type", - "_headers", - ] - ) - - # validate the arguments - for _key, _val in _params["kwargs"].items(): - if _key not in _all_params: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method get_room" % _key - ) - _params[_key] = _val - del _params["kwargs"] - - _collection_formats = {} - - # process the path parameters - _path_params = {} - if _params["room_id"]: - _path_params["room_id"] = _params["room_id"] - - # process the query parameters - _query_params = [] - # process the header parameters - _header_params = dict(_params.get("_headers", {})) - # process the form parameters - _form_params = [] - _files = {} - # process the body parameter - _body_params = None - # set the HTTP header `Accept` - _header_params["Accept"] = self.api_client.select_header_accept( - ["application/json"] - ) # noqa: E501 - - # authentication setting - _auth_settings = ["authorization"] # noqa: E501 - - _response_types_map = { - "200": "RoomDetailsResponse", - "401": "Error", - "404": "Error", - } - - return self.api_client.call_api( - "/room/{room_id}", - "GET", - _path_params, - _query_params, - _header_params, - body=_body_params, - post_params=_form_params, - files=_files, - response_types_map=_response_types_map, - auth_settings=_auth_settings, - async_req=_params.get("async_req"), - _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501 - _preload_content=_params.get("_preload_content", True), - _request_timeout=_params.get("_request_timeout"), - collection_formats=_collection_formats, - _request_auth=_params.get("_request_auth"), - ) diff --git a/jellyfish/_openapi_client/api_client.py b/jellyfish/_openapi_client/api_client.py deleted file mode 100644 index 029df4d..0000000 --- a/jellyfish/_openapi_client/api_client.py +++ /dev/null @@ -1,835 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import atexit -import datetime -from dateutil.parser import parse -import json -import mimetypes -from multiprocessing.pool import ThreadPool -import os -import re -import tempfile - -from urllib.parse import quote - -from jellyfish._openapi_client.configuration import Configuration -from jellyfish._openapi_client.api_response import ApiResponse -import jellyfish._openapi_client.models -from jellyfish._openapi_client import rest -from jellyfish._openapi_client.exceptions import ApiValueError, ApiException - - -class ApiClient(object): - """Generic API client for OpenAPI client library builds. - - OpenAPI generic API client. This client handles the client- - server communication, and is invariant across implementations. Specifics of - the methods and models for each application are generated from the OpenAPI - templates. - - :param configuration: .Configuration object for this client - :param header_name: a header to pass when making calls to the API. - :param header_value: a header value to pass when making calls to - the API. - :param cookie: a cookie to include in the header when making calls - to the API - :param pool_threads: The number of threads to use for async requests - to the API. More threads means more concurrent API requests. - """ - - PRIMITIVE_TYPES = (float, bool, bytes, str, int) - NATIVE_TYPES_MAPPING = { - "int": int, - "long": int, # TODO remove as only py3 is supported? - "float": float, - "str": str, - "bool": bool, - "date": datetime.date, - "datetime": datetime.datetime, - "object": object, - } - _pool = None - - def __init__( - self, - configuration=None, - header_name=None, - header_value=None, - cookie=None, - pool_threads=1, - ): - # use default configuration if none is provided - if configuration is None: - configuration = Configuration.get_default() - self.configuration = configuration - self.pool_threads = pool_threads - - self.rest_client = rest.RESTClientObject(configuration) - self.default_headers = {} - if header_name is not None: - self.default_headers[header_name] = header_value - self.cookie = cookie - # Set default User-Agent. - self.user_agent = "OpenAPI-Generator/1.0.0/python" - self.client_side_validation = configuration.client_side_validation - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.close() - - def close(self): - if self._pool: - self._pool.close() - self._pool.join() - self._pool = None - if hasattr(atexit, "unregister"): - atexit.unregister(self.close) - - @property - def pool(self): - """Create thread pool on first request - avoids instantiating unused threadpool for blocking clients. - """ - if self._pool is None: - atexit.register(self.close) - self._pool = ThreadPool(self.pool_threads) - return self._pool - - @property - def user_agent(self): - """User agent for this API client""" - return self.default_headers["User-Agent"] - - @user_agent.setter - def user_agent(self, value): - self.default_headers["User-Agent"] = value - - def set_default_header(self, header_name, header_value): - self.default_headers[header_name] = header_value - - _default = None - - @classmethod - def get_default(cls): - """Return new instance of ApiClient. - - This method returns newly created, based on default constructor, - object of ApiClient class or returns a copy of default - ApiClient. - - :return: The ApiClient object. - """ - if cls._default is None: - cls._default = ApiClient() - return cls._default - - @classmethod - def set_default(cls, default): - """Set default instance of ApiClient. - - It stores default ApiClient. - - :param default: object of ApiClient. - """ - cls._default = default - - def __call_api( - self, - resource_path, - method, - path_params=None, - query_params=None, - header_params=None, - body=None, - post_params=None, - files=None, - response_types_map=None, - auth_settings=None, - _return_http_data_only=None, - collection_formats=None, - _preload_content=True, - _request_timeout=None, - _host=None, - _request_auth=None, - ): - config = self.configuration - - # header parameters - header_params = header_params or {} - header_params.update(self.default_headers) - if self.cookie: - header_params["Cookie"] = self.cookie - if header_params: - header_params = self.sanitize_for_serialization(header_params) - header_params = dict( - self.parameters_to_tuples(header_params, collection_formats) - ) - - # path parameters - if path_params: - path_params = self.sanitize_for_serialization(path_params) - path_params = self.parameters_to_tuples(path_params, collection_formats) - for k, v in path_params: - # specified safe chars, encode everything - resource_path = resource_path.replace( - "{%s}" % k, quote(str(v), safe=config.safe_chars_for_path_param) - ) - - # post parameters - if post_params or files: - post_params = post_params if post_params else [] - post_params = self.sanitize_for_serialization(post_params) - post_params = self.parameters_to_tuples(post_params, collection_formats) - post_params.extend(self.files_parameters(files)) - - # auth setting - self.update_params_for_auth( - header_params, - query_params, - auth_settings, - resource_path, - method, - body, - request_auth=_request_auth, - ) - - # body - if body: - body = self.sanitize_for_serialization(body) - - # request url - if _host is None: - url = self.configuration.host + resource_path - else: - # use server/host defined in path or operation instead - url = _host + resource_path - - # query parameters - if query_params: - query_params = self.sanitize_for_serialization(query_params) - url_query = self.parameters_to_url_query(query_params, collection_formats) - url += "?" + url_query - - try: - # perform request and return response - response_data = self.request( - method, - url, - query_params=query_params, - headers=header_params, - post_params=post_params, - body=body, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - ) - except ApiException as e: - if e.body: - e.body = e.body.decode("utf-8") - raise e - - self.last_response = response_data - - return_data = None # assuming derialization is not needed - # data needs deserialization or returns HTTP data (deserialized) only - if _preload_content or _return_http_data_only: - response_type = response_types_map.get(str(response_data.status), None) - - if response_type == "bytearray": - response_data.data = response_data.data - else: - match = None - content_type = response_data.getheader("content-type") - if content_type is not None: - match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type) - encoding = match.group(1) if match else "utf-8" - response_data.data = response_data.data.decode(encoding) - - # deserialize response data - if response_type == "bytearray": - return_data = response_data.data - elif response_type: - return_data = self.deserialize(response_data, response_type) - else: - return_data = None - - if _return_http_data_only: - return return_data - else: - return ApiResponse( - status_code=response_data.status, - data=return_data, - headers=response_data.getheaders(), - raw_data=response_data.data, - ) - - def sanitize_for_serialization(self, obj): - """Builds a JSON POST object. - - If obj is None, return None. - If obj is str, int, long, float, bool, return directly. - If obj is datetime.datetime, datetime.date - convert to string in iso8601 format. - If obj is list, sanitize each element in the list. - If obj is dict, return the dict. - If obj is OpenAPI model, return the properties dict. - - :param obj: The data to serialize. - :return: The serialized form of data. - """ - if obj is None: - return None - elif isinstance(obj, self.PRIMITIVE_TYPES): - return obj - elif isinstance(obj, list): - return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj] - elif isinstance(obj, tuple): - return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj) - elif isinstance(obj, (datetime.datetime, datetime.date)): - return obj.isoformat() - - if isinstance(obj, dict): - obj_dict = obj - else: - # Convert model obj to dict except - # attributes `openapi_types`, `attribute_map` - # and attributes which value is not None. - # Convert attribute name to json key in - # model definition for request. - obj_dict = obj.to_dict() - - return { - key: self.sanitize_for_serialization(val) for key, val in obj_dict.items() - } - - def deserialize(self, response, response_type): - """Deserializes response into an object. - - :param response: RESTResponse object to be deserialized. - :param response_type: class literal for - deserialized object, or string of class name. - - :return: deserialized object. - """ - # handle file downloading - # save response body into a tmp file and return the instance - if response_type == "file": - return self.__deserialize_file(response) - - # fetch data from response object - try: - data = json.loads(response.data) - except ValueError: - data = response.data - - return self.__deserialize(data, response_type) - - def __deserialize(self, data, klass): - """Deserializes dict, list, str into an object. - - :param data: dict, list or str. - :param klass: class literal, or string of class name. - - :return: object. - """ - if data is None: - return None - - if type(klass) == str: - if klass.startswith("List["): - sub_kls = re.match(r"List\[(.*)]", klass).group(1) - return [self.__deserialize(sub_data, sub_kls) for sub_data in data] - - if klass.startswith("Dict["): - sub_kls = re.match(r"Dict\[([^,]*), (.*)]", klass).group(2) - return {k: self.__deserialize(v, sub_kls) for k, v in data.items()} - - # convert str to class - if klass in self.NATIVE_TYPES_MAPPING: - klass = self.NATIVE_TYPES_MAPPING[klass] - else: - klass = getattr(jellyfish._openapi_client.models, klass) - - if klass in self.PRIMITIVE_TYPES: - return self.__deserialize_primitive(data, klass) - elif klass == object: - return self.__deserialize_object(data) - elif klass == datetime.date: - return self.__deserialize_date(data) - elif klass == datetime.datetime: - return self.__deserialize_datetime(data) - else: - return self.__deserialize_model(data, klass) - - def call_api( - self, - resource_path, - method, - path_params=None, - query_params=None, - header_params=None, - body=None, - post_params=None, - files=None, - response_types_map=None, - auth_settings=None, - async_req=None, - _return_http_data_only=None, - collection_formats=None, - _preload_content=True, - _request_timeout=None, - _host=None, - _request_auth=None, - ): - """Makes the HTTP request (synchronous) and returns deserialized data. - - To make an async_req request, set the async_req parameter. - - :param resource_path: Path to method endpoint. - :param method: Method to call. - :param path_params: Path parameters in the url. - :param query_params: Query parameters in the url. - :param header_params: Header parameters to be - placed in the request header. - :param body: Request body. - :param post_params dict: Request post form parameters, - for `application/x-www-form-urlencoded`, `multipart/form-data`. - :param auth_settings list: Auth Settings names for the request. - :param response: Response data type. - :param files dict: key -> filename, value -> filepath, - for `multipart/form-data`. - :param async_req bool: execute request asynchronously - :param _return_http_data_only: response data instead of ApiResponse - object with status code, headers, etc - :param _preload_content: if False, the ApiResponse.data will - be set to none and raw_data will store the - HTTP response body without reading/decoding. - Default is True. - :param collection_formats: dict of collection formats for path, query, - header, and post parameters. - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_token: dict, optional - :return: - If async_req parameter is True, - the request will be called asynchronously. - The method will return the request thread. - If parameter async_req is False or missing, - then the method will return the response directly. - """ - if not async_req: - return self.__call_api( - resource_path, - method, - path_params, - query_params, - header_params, - body, - post_params, - files, - response_types_map, - auth_settings, - _return_http_data_only, - collection_formats, - _preload_content, - _request_timeout, - _host, - _request_auth, - ) - - return self.pool.apply_async( - self.__call_api, - ( - resource_path, - method, - path_params, - query_params, - header_params, - body, - post_params, - files, - response_types_map, - auth_settings, - _return_http_data_only, - collection_formats, - _preload_content, - _request_timeout, - _host, - _request_auth, - ), - ) - - def request( - self, - method, - url, - query_params=None, - headers=None, - post_params=None, - body=None, - _preload_content=True, - _request_timeout=None, - ): - """Makes the HTTP request using RESTClient.""" - if method == "GET": - return self.rest_client.get_request( - url, - query_params=query_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - headers=headers, - ) - elif method == "HEAD": - return self.rest_client.head_request( - url, - query_params=query_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - headers=headers, - ) - elif method == "OPTIONS": - return self.rest_client.options_request( - url, - query_params=query_params, - headers=headers, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - ) - elif method == "POST": - return self.rest_client.post_request( - url, - query_params=query_params, - headers=headers, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) - elif method == "PUT": - return self.rest_client.put_request( - url, - query_params=query_params, - headers=headers, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) - elif method == "PATCH": - return self.rest_client.patch_request( - url, - query_params=query_params, - headers=headers, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) - elif method == "DELETE": - return self.rest_client.delete_request( - url, - query_params=query_params, - headers=headers, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) - else: - raise ApiValueError( - "http method must be `GET`, `HEAD`, `OPTIONS`," - " `POST`, `PATCH`, `PUT` or `DELETE`." - ) - - def parameters_to_tuples(self, params, collection_formats): - """Get parameters as list of tuples, formatting collections. - - :param params: Parameters as dict or list of two-tuples - :param dict collection_formats: Parameter collection formats - :return: Parameters as list of tuples, collections formatted - """ - new_params = [] - if collection_formats is None: - collection_formats = {} - for k, v in ( - params.items() if isinstance(params, dict) else params - ): # noqa: E501 - if k in collection_formats: - collection_format = collection_formats[k] - if collection_format == "multi": - new_params.extend((k, value) for value in v) - else: - if collection_format == "ssv": - delimiter = " " - elif collection_format == "tsv": - delimiter = "\t" - elif collection_format == "pipes": - delimiter = "|" - else: # csv is the default - delimiter = "," - new_params.append((k, delimiter.join(str(value) for value in v))) - else: - new_params.append((k, v)) - return new_params - - def parameters_to_url_query(self, params, collection_formats): - """Get parameters as list of tuples, formatting collections. - - :param params: Parameters as dict or list of two-tuples - :param dict collection_formats: Parameter collection formats - :return: URL query string (e.g. a=Hello%20World&b=123) - """ - new_params = [] - if collection_formats is None: - collection_formats = {} - for k, v in ( - params.items() if isinstance(params, dict) else params - ): # noqa: E501 - if isinstance(v, (int, float)): - v = str(v) - if isinstance(v, bool): - v = str(v).lower() - if isinstance(v, dict): - v = json.dumps(v) - - if k in collection_formats: - collection_format = collection_formats[k] - if collection_format == "multi": - new_params.extend((k, value) for value in v) - else: - if collection_format == "ssv": - delimiter = " " - elif collection_format == "tsv": - delimiter = "\t" - elif collection_format == "pipes": - delimiter = "|" - else: # csv is the default - delimiter = "," - new_params.append( - (k, delimiter.join(quote(str(value)) for value in v)) - ) - else: - new_params.append((k, quote(str(v)))) - - return "&".join(["=".join(item) for item in new_params]) - - def files_parameters(self, files=None): - """Builds form parameters. - - :param files: File parameters. - :return: Form parameters with files. - """ - params = [] - - if files: - for k, v in files.items(): - if not v: - continue - file_names = v if type(v) is list else [v] - for n in file_names: - with open(n, "rb") as f: - filename = os.path.basename(f.name) - filedata = f.read() - mimetype = ( - mimetypes.guess_type(filename)[0] - or "application/octet-stream" - ) - params.append(tuple([k, tuple([filename, filedata, mimetype])])) - - return params - - def select_header_accept(self, accepts): - """Returns `Accept` based on an array of accepts provided. - - :param accepts: List of headers. - :return: Accept (e.g. application/json). - """ - if not accepts: - return - - for accept in accepts: - if re.search("json", accept, re.IGNORECASE): - return accept - - return accepts[0] - - def select_header_content_type(self, content_types): - """Returns `Content-Type` based on an array of content_types provided. - - :param content_types: List of content-types. - :return: Content-Type (e.g. application/json). - """ - if not content_types: - return None - - for content_type in content_types: - if re.search("json", content_type, re.IGNORECASE): - return content_type - - return content_types[0] - - def update_params_for_auth( - self, - headers, - queries, - auth_settings, - resource_path, - method, - body, - request_auth=None, - ): - """Updates header and query params based on authentication setting. - - :param headers: Header parameters dict to be updated. - :param queries: Query parameters tuple list to be updated. - :param auth_settings: Authentication setting identifiers list. - :resource_path: A string representation of the HTTP request resource path. - :method: A string representation of the HTTP request method. - :body: A object representing the body of the HTTP request. - The object type is the return value of sanitize_for_serialization(). - :param request_auth: if set, the provided settings will - override the token in the configuration. - """ - if not auth_settings: - return - - if request_auth: - self._apply_auth_params( - headers, queries, resource_path, method, body, request_auth - ) - return - - for auth in auth_settings: - auth_setting = self.configuration.auth_settings().get(auth) - if auth_setting: - self._apply_auth_params( - headers, queries, resource_path, method, body, auth_setting - ) - - def _apply_auth_params( - self, headers, queries, resource_path, method, body, auth_setting - ): - """Updates the request parameters based on a single auth_setting - - :param headers: Header parameters dict to be updated. - :param queries: Query parameters tuple list to be updated. - :resource_path: A string representation of the HTTP request resource path. - :method: A string representation of the HTTP request method. - :body: A object representing the body of the HTTP request. - The object type is the return value of sanitize_for_serialization(). - :param auth_setting: auth settings for the endpoint - """ - if auth_setting["in"] == "cookie": - headers["Cookie"] = auth_setting["value"] - elif auth_setting["in"] == "header": - if auth_setting["type"] != "http-signature": - headers[auth_setting["key"]] = auth_setting["value"] - elif auth_setting["in"] == "query": - queries.append((auth_setting["key"], auth_setting["value"])) - else: - raise ApiValueError("Authentication token must be in `query` or `header`") - - def __deserialize_file(self, response): - """Deserializes body to file - - Saves response body into a file in a temporary folder, - using the filename from the `Content-Disposition` header if provided. - - :param response: RESTResponse. - :return: file path. - """ - fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) - os.close(fd) - os.remove(path) - - content_disposition = response.getheader("Content-Disposition") - if content_disposition: - filename = re.search( - r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition - ).group(1) - path = os.path.join(os.path.dirname(path), filename) - - with open(path, "wb") as f: - f.write(response.data) - - return path - - def __deserialize_primitive(self, data, klass): - """Deserializes string to primitive type. - - :param data: str. - :param klass: class literal. - - :return: int, long, float, str, bool. - """ - try: - return klass(data) - except UnicodeEncodeError: - return str(data) - except TypeError: - return data - - def __deserialize_object(self, value): - """Return an original value. - - :return: object. - """ - return value - - def __deserialize_date(self, string): - """Deserializes string to date. - - :param string: str. - :return: date. - """ - try: - return parse(string).date() - except ImportError: - return string - except ValueError: - raise rest.ApiException( - status=0, reason="Failed to parse `{0}` as date object".format(string) - ) - - def __deserialize_datetime(self, string): - """Deserializes string to datetime. - - The string should be in iso8601 datetime format. - - :param string: str. - :return: datetime. - """ - try: - return parse(string) - except ImportError: - return string - except ValueError: - raise rest.ApiException( - status=0, - reason=("Failed to parse `{0}` as datetime object".format(string)), - ) - - def __deserialize_model(self, data, klass): - """Deserializes list or dict to model. - - :param data: dict, list. - :param klass: class literal. - :return: model object. - """ - - return klass.from_dict(data) diff --git a/jellyfish/_openapi_client/api_response.py b/jellyfish/_openapi_client/api_response.py deleted file mode 100644 index 0af0a2d..0000000 --- a/jellyfish/_openapi_client/api_response.py +++ /dev/null @@ -1,26 +0,0 @@ -"""API response object.""" - -from __future__ import annotations -from typing import Any, Dict, Optional -from pydantic import Field, StrictInt, StrictStr - - -class ApiResponse: - """ - API response object - """ - - status_code: Optional[StrictInt] = Field(None, description="HTTP status code") - headers: Optional[Dict[StrictStr, StrictStr]] = Field( - None, description="HTTP headers" - ) - data: Optional[Any] = Field( - None, description="Deserialized data given the data type" - ) - raw_data: Optional[Any] = Field(None, description="Raw data (HTTP response body)") - - def __init__(self, status_code=None, headers=None, data=None, raw_data=None): - self.status_code = status_code - self.headers = headers - self.data = data - self.raw_data = raw_data diff --git a/jellyfish/_openapi_client/client.py b/jellyfish/_openapi_client/client.py new file mode 100644 index 0000000..0a07559 --- /dev/null +++ b/jellyfish/_openapi_client/client.py @@ -0,0 +1,274 @@ +import ssl +from typing import Any, Dict, Optional, Union + +import httpx +from attrs import define, evolve, field + + +@define +class Client: + """A class for keeping track of data related to the API + + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str + _cookies: Dict[str, str] = field(factory=dict, kw_only=True) + _headers: Dict[str, str] = field(factory=dict, kw_only=True) + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) + _follow_redirects: bool = field(default=False, kw_only=True) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True) + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + def with_headers(self, headers: Dict[str, str]) -> "Client": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "Client": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: httpx.Timeout) -> "Client": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_httpx_client(self, client: httpx.Client) -> "Client": + """Manually the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_httpx_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._client + + def __enter__(self) -> "Client": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_httpx_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for internal httpx.Client (see httpx docs)""" + self.get_httpx_client().__exit__(*args, **kwargs) + + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_httpx_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._async_client + + async def __aenter__(self) -> "Client": + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" + await self.get_async_httpx_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" + await self.get_async_httpx_client().__aexit__(*args, **kwargs) + + +@define +class AuthenticatedClient: + """A Client which has been authenticated for use on secured endpoints + + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + token: The token to use for authentication + prefix: The prefix to use for the Authorization header + auth_header_name: The name of the Authorization header + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str + _cookies: Dict[str, str] = field(factory=dict, kw_only=True) + _headers: Dict[str, str] = field(factory=dict, kw_only=True) + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True) + _follow_redirects: bool = field(default=False, kw_only=True) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True) + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + token: str + prefix: str = "Bearer" + auth_header_name: str = "Authorization" + + def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": + """Manually the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_httpx_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._headers[self.auth_header_name] = ( + f"{self.prefix} {self.token}" if self.prefix else self.token + ) + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._client + + def __enter__(self) -> "AuthenticatedClient": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_httpx_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for internal httpx.Client (see httpx docs)""" + self.get_httpx_client().__exit__(*args, **kwargs) + + def set_async_httpx_client( + self, async_client: httpx.AsyncClient + ) -> "AuthenticatedClient": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_httpx_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._headers[self.auth_header_name] = ( + f"{self.prefix} {self.token}" if self.prefix else self.token + ) + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._async_client + + async def __aenter__(self) -> "AuthenticatedClient": + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" + await self.get_async_httpx_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" + await self.get_async_httpx_client().__aexit__(*args, **kwargs) diff --git a/jellyfish/_openapi_client/configuration.py b/jellyfish/_openapi_client/configuration.py deleted file mode 100644 index 0d45d5c..0000000 --- a/jellyfish/_openapi_client/configuration.py +++ /dev/null @@ -1,458 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import copy -import logging -import multiprocessing -import sys -import urllib3 - -import http.client as httplib -from jellyfish._openapi_client.exceptions import ApiValueError - -JSON_SCHEMA_VALIDATION_KEYWORDS = { - "multipleOf", - "maximum", - "exclusiveMaximum", - "minimum", - "exclusiveMinimum", - "maxLength", - "minLength", - "pattern", - "maxItems", - "minItems", -} - - -class Configuration(object): - """This class contains various settings of the API client. - - :param host: Base url. - :param api_key: Dict to store API key(s). - Each entry in the dict specifies an API key. - The dict key is the name of the security scheme in the OAS specification. - The dict value is the API key secret. - :param api_key_prefix: Dict to store API prefix (e.g. Bearer). - The dict key is the name of the security scheme in the OAS specification. - The dict value is an API key prefix when generating the auth data. - :param username: Username for HTTP basic authentication. - :param password: Password for HTTP basic authentication. - :param access_token: Access token. - :param server_index: Index to servers configuration. - :param server_variables: Mapping with string values to replace variables in - templated server configuration. The validation of enums is performed for - variables with defined enum values before. - :param server_operation_index: Mapping from operation ID to an index to server - configuration. - :param server_operation_variables: Mapping from operation ID to a mapping with - string values to replace variables in templated server configuration. - The validation of enums is performed for variables with defined enum values before. - :param ssl_ca_cert: str - the path to a file of concatenated CA certificates - in PEM format. - - :Example: - """ - - _default = None - - def __init__( - self, - host=None, - api_key=None, - api_key_prefix=None, - username=None, - password=None, - access_token=None, - server_index=None, - server_variables=None, - server_operation_index=None, - server_operation_variables=None, - ssl_ca_cert=None, - ): - """Constructor""" - self._base_path = "http://localhost" if host is None else host - """Default Base url - """ - self.server_index = 0 if server_index is None and host is None else server_index - self.server_operation_index = server_operation_index or {} - """Default server index - """ - self.server_variables = server_variables or {} - self.server_operation_variables = server_operation_variables or {} - """Default server variables - """ - self.temp_folder_path = None - """Temp file folder for downloading files - """ - # Authentication Settings - self.api_key = {} - if api_key: - self.api_key = api_key - """dict to store API key(s) - """ - self.api_key_prefix = {} - if api_key_prefix: - self.api_key_prefix = api_key_prefix - """dict to store API prefix (e.g. Bearer) - """ - self.refresh_api_key_hook = None - """function hook to refresh API key if expired - """ - self.username = username - """Username for HTTP basic authentication - """ - self.password = password - """Password for HTTP basic authentication - """ - self.access_token = access_token - """Access token - """ - self.logger = {} - """Logging Settings - """ - self.logger["package_logger"] = logging.getLogger("jellyfish._openapi_client") - self.logger["urllib3_logger"] = logging.getLogger("urllib3") - self.logger_format = "%(asctime)s %(levelname)s %(message)s" - """Log format - """ - self.logger_stream_handler = None - """Log stream handler - """ - self.logger_file_handler = None - """Log file handler - """ - self.logger_file = None - """Debug file location - """ - self.debug = False - """Debug switch - """ - - self.verify_ssl = True - """SSL/TLS verification - Set this to false to skip verifying SSL certificate when calling API - from https server. - """ - self.ssl_ca_cert = ssl_ca_cert - """Set this to customize the certificate file to verify the peer. - """ - self.cert_file = None - """client certificate file - """ - self.key_file = None - """client key file - """ - self.assert_hostname = None - """Set this to True/False to enable/disable SSL hostname verification. - """ - self.tls_server_name = None - """SSL/TLS Server Name Indication (SNI) - Set this to the SNI value expected by the server. - """ - - self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 - """urllib3 connection pool's maximum number of connections saved - per pool. urllib3 uses 1 connection as default value, but this is - not the best value when you are making a lot of possibly parallel - requests to the same host, which is often the case here. - cpu_count * 5 is used as default value to increase performance. - """ - - self.proxy = None - """Proxy URL - """ - self.proxy_headers = None - """Proxy headers - """ - self.safe_chars_for_path_param = "" - """Safe chars for path_param - """ - self.retries = None - """Adding retries to override urllib3 default value 3 - """ - # Enable client side validation - self.client_side_validation = True - - self.socket_options = None - """Options to pass down to the underlying urllib3 socket - """ - - self.datetime_format = "%Y-%m-%dT%H:%M:%S.%f%z" - """datetime format - """ - - self.date_format = "%Y-%m-%d" - """date format - """ - - def __deepcopy__(self, memo): - cls = self.__class__ - result = cls.__new__(cls) - memo[id(self)] = result - for k, v in self.__dict__.items(): - if k not in ("logger", "logger_file_handler"): - setattr(result, k, copy.deepcopy(v, memo)) - # shallow copy of loggers - result.logger = copy.copy(self.logger) - # use setters to configure loggers - result.logger_file = self.logger_file - result.debug = self.debug - return result - - def __setattr__(self, name, value): - object.__setattr__(self, name, value) - - @classmethod - def set_default(cls, default): - """Set default instance of configuration. - - It stores default configuration, which can be - returned by get_default_copy method. - - :param default: object of Configuration - """ - cls._default = default - - @classmethod - def get_default_copy(cls): - """Deprecated. Please use `get_default` instead. - - Deprecated. Please use `get_default` instead. - - :return: The configuration object. - """ - return cls.get_default() - - @classmethod - def get_default(cls): - """Return the default configuration. - - This method returns newly created, based on default constructor, - object of Configuration class or returns a copy of default - configuration. - - :return: The configuration object. - """ - if cls._default is None: - cls._default = Configuration() - return cls._default - - @property - def logger_file(self): - """The logger file. - - If the logger_file is None, then add stream handler and remove file - handler. Otherwise, add file handler and remove stream handler. - - :param value: The logger_file path. - :type: str - """ - return self.__logger_file - - @logger_file.setter - def logger_file(self, value): - """The logger file. - - If the logger_file is None, then add stream handler and remove file - handler. Otherwise, add file handler and remove stream handler. - - :param value: The logger_file path. - :type: str - """ - self.__logger_file = value - if self.__logger_file: - # If set logging file, - # then add file handler and remove stream handler. - self.logger_file_handler = logging.FileHandler(self.__logger_file) - self.logger_file_handler.setFormatter(self.logger_formatter) - for _, logger in self.logger.items(): - logger.addHandler(self.logger_file_handler) - - @property - def debug(self): - """Debug status - - :param value: The debug status, True or False. - :type: bool - """ - return self.__debug - - @debug.setter - def debug(self, value): - """Debug status - - :param value: The debug status, True or False. - :type: bool - """ - self.__debug = value - if self.__debug: - # if debug status is True, turn on debug logging - for _, logger in self.logger.items(): - logger.setLevel(logging.DEBUG) - # turn on httplib debug - httplib.HTTPConnection.debuglevel = 1 - else: - # if debug status is False, turn off debug logging, - # setting log level to default `logging.WARNING` - for _, logger in self.logger.items(): - logger.setLevel(logging.WARNING) - # turn off httplib debug - httplib.HTTPConnection.debuglevel = 0 - - @property - def logger_format(self): - """The logger format. - - The logger_formatter will be updated when sets logger_format. - - :param value: The format string. - :type: str - """ - return self.__logger_format - - @logger_format.setter - def logger_format(self, value): - """The logger format. - - The logger_formatter will be updated when sets logger_format. - - :param value: The format string. - :type: str - """ - self.__logger_format = value - self.logger_formatter = logging.Formatter(self.__logger_format) - - def get_api_key_with_prefix(self, identifier, alias=None): - """Gets API key (with prefix if set). - - :param identifier: The identifier of apiKey. - :param alias: The alternative identifier of apiKey. - :return: The token for api key authentication. - """ - if self.refresh_api_key_hook is not None: - self.refresh_api_key_hook(self) - key = self.api_key.get( - identifier, self.api_key.get(alias) if alias is not None else None - ) - if key: - prefix = self.api_key_prefix.get(identifier) - if prefix: - return "%s %s" % (prefix, key) - else: - return key - - def get_basic_auth_token(self): - """Gets HTTP basic authentication header (string). - - :return: The token for basic HTTP authentication. - """ - username = "" - if self.username is not None: - username = self.username - password = "" - if self.password is not None: - password = self.password - return urllib3.util.make_headers(basic_auth=username + ":" + password).get( - "authorization" - ) - - def auth_settings(self): - """Gets Auth Settings dict for api client. - - :return: The Auth Settings information dict. - """ - auth = {} - if self.access_token is not None: - auth["authorization"] = { - "type": "bearer", - "in": "header", - "key": "Authorization", - "value": "Bearer " + self.access_token, - } - return auth - - def to_debug_report(self): - """Gets the essential information for debugging. - - :return: The report for debugging. - """ - return ( - "Python SDK Debug Report:\n" - "OS: {env}\n" - "Python Version: {pyversion}\n" - "Version of the API: 0.2.0\n" - "SDK Package Version: 1.0.0".format(env=sys.platform, pyversion=sys.version) - ) - - def get_host_settings(self): - """Gets an array of host settings - - :return: An array of host settings - """ - return [ - { - "url": "", - "description": "No description provided", - } - ] - - def get_host_from_settings(self, index, variables=None, servers=None): - """Gets host URL based on the index and variables - :param index: array index of the host settings - :param variables: hash of variable and the corresponding value - :param servers: an array of host settings or None - :return: URL based on host settings - """ - if index is None: - return self._base_path - - variables = {} if variables is None else variables - servers = self.get_host_settings() if servers is None else servers - - try: - server = servers[index] - except IndexError: - raise ValueError( - "Invalid index {0} when selecting the host settings. " - "Must be less than {1}".format(index, len(servers)) - ) - - url = server["url"] - - # go through variables and replace placeholders - for variable_name, variable in server.get("variables", {}).items(): - used_value = variables.get(variable_name, variable["default_value"]) - - if "enum_values" in variable and used_value not in variable["enum_values"]: - raise ValueError( - "The variable `{0}` in the host URL has invalid value " - "{1}. Must be {2}.".format( - variable_name, variables[variable_name], variable["enum_values"] - ) - ) - - url = url.replace("{" + variable_name + "}", used_value) - - return url - - @property - def host(self): - """Return generated host.""" - return self.get_host_from_settings( - self.server_index, variables=self.server_variables - ) - - @host.setter - def host(self, value): - """Fix base path.""" - self._base_path = value - self.server_index = None diff --git a/jellyfish/_openapi_client/errors.py b/jellyfish/_openapi_client/errors.py new file mode 100644 index 0000000..426f8a2 --- /dev/null +++ b/jellyfish/_openapi_client/errors.py @@ -0,0 +1,14 @@ +""" Contains shared errors types that can be raised from API functions """ + + +class UnexpectedStatus(Exception): + """Raised by api functions when the response status an undocumented status and Client.raise_on_unexpected_status is True""" + + def __init__(self, status_code: int, content: bytes): + self.status_code = status_code + self.content = content + + super().__init__(f"Unexpected status code: {status_code}") + + +__all__ = ["UnexpectedStatus"] diff --git a/jellyfish/_openapi_client/exceptions.py b/jellyfish/_openapi_client/exceptions.py deleted file mode 100644 index 3a6c92c..0000000 --- a/jellyfish/_openapi_client/exceptions.py +++ /dev/null @@ -1,157 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -class OpenApiException(Exception): - """The base exception class for all OpenAPIExceptions""" - - -class ApiTypeError(OpenApiException, TypeError): - def __init__(self, msg, path_to_item=None, valid_classes=None, key_type=None): - """Raises an exception for TypeErrors - - Args: - msg (str): the exception message - - Keyword Args: - path_to_item (list): a list of keys an indices to get to the - current_item - None if unset - valid_classes (tuple): the primitive classes that current item - should be an instance of - None if unset - key_type (bool): False if our value is a value in a dict - True if it is a key in a dict - False if our item is an item in a list - None if unset - """ - self.path_to_item = path_to_item - self.valid_classes = valid_classes - self.key_type = key_type - full_msg = msg - if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiTypeError, self).__init__(full_msg) - - -class ApiValueError(OpenApiException, ValueError): - def __init__(self, msg, path_to_item=None): - """ - Args: - msg (str): the exception message - - Keyword Args: - path_to_item (list) the path to the exception in the - received_data dict. None if unset - """ - - self.path_to_item = path_to_item - full_msg = msg - if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiValueError, self).__init__(full_msg) - - -class ApiAttributeError(OpenApiException, AttributeError): - def __init__(self, msg, path_to_item=None): - """ - Raised when an attribute reference or assignment fails. - - Args: - msg (str): the exception message - - Keyword Args: - path_to_item (None/list) the path to the exception in the - received_data dict - """ - self.path_to_item = path_to_item - full_msg = msg - if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiAttributeError, self).__init__(full_msg) - - -class ApiKeyError(OpenApiException, KeyError): - def __init__(self, msg, path_to_item=None): - """ - Args: - msg (str): the exception message - - Keyword Args: - path_to_item (None/list) the path to the exception in the - received_data dict - """ - self.path_to_item = path_to_item - full_msg = msg - if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiKeyError, self).__init__(full_msg) - - -class ApiException(OpenApiException): - def __init__(self, status=None, reason=None, http_resp=None): - if http_resp: - self.status = http_resp.status - self.reason = http_resp.reason - self.body = http_resp.data - self.headers = http_resp.getheaders() - else: - self.status = status - self.reason = reason - self.body = None - self.headers = None - - def __str__(self): - """Custom error messages for exception""" - error_message = "({0})\n" "Reason: {1}\n".format(self.status, self.reason) - if self.headers: - error_message += "HTTP response headers: {0}\n".format(self.headers) - - if self.body: - error_message += "HTTP response body: {0}\n".format(self.body) - - return error_message - - -class BadRequestException(ApiException): - def __init__(self, status=None, reason=None, http_resp=None): - super(BadRequestException, self).__init__(status, reason, http_resp) - - -class NotFoundException(ApiException): - def __init__(self, status=None, reason=None, http_resp=None): - super(NotFoundException, self).__init__(status, reason, http_resp) - - -class UnauthorizedException(ApiException): - def __init__(self, status=None, reason=None, http_resp=None): - super(UnauthorizedException, self).__init__(status, reason, http_resp) - - -class ForbiddenException(ApiException): - def __init__(self, status=None, reason=None, http_resp=None): - super(ForbiddenException, self).__init__(status, reason, http_resp) - - -class ServiceException(ApiException): - def __init__(self, status=None, reason=None, http_resp=None): - super(ServiceException, self).__init__(status, reason, http_resp) - - -def render_path(path_to_item): - """Returns a string representation of a path""" - result = "" - for pth in path_to_item: - if isinstance(pth, int): - result += "[{0}]".format(pth) - else: - result += "['{0}']".format(pth) - return result diff --git a/jellyfish/_openapi_client/models/__init__.py b/jellyfish/_openapi_client/models/__init__.py index dc1acea..2b23d0b 100644 --- a/jellyfish/_openapi_client/models/__init__.py +++ b/jellyfish/_openapi_client/models/__init__.py @@ -1,54 +1,63 @@ -# coding: utf-8 +""" Contains all the data models used in inputs/outputs """ -# flake8: noqa -""" - Python API wrapper for Jellyfish Media Server +from .add_component_json_body import AddComponentJsonBody +from .add_peer_json_body import AddPeerJsonBody +from .component_details_response import ComponentDetailsResponse +from .component_file import ComponentFile +from .component_hls import ComponentHLS +from .component_options_file import ComponentOptionsFile +from .component_options_hls import ComponentOptionsHLS +from .component_options_hls_subscribe_mode import ComponentOptionsHLSSubscribeMode +from .component_options_rtsp import ComponentOptionsRTSP +from .component_properties_hls import ComponentPropertiesHLS +from .component_properties_hls_subscribe_mode import ComponentPropertiesHLSSubscribeMode +from .component_properties_rtsp import ComponentPropertiesRTSP +from .component_rtsp import ComponentRTSP +from .error import Error +from .peer import Peer +from .peer_details_response import PeerDetailsResponse +from .peer_details_response_data import PeerDetailsResponseData +from .peer_options_web_rtc import PeerOptionsWebRTC +from .peer_status import PeerStatus +from .recording_list_response import RecordingListResponse +from .room import Room +from .room_config import RoomConfig +from .room_config_video_codec import RoomConfigVideoCodec +from .room_create_details_response import RoomCreateDetailsResponse +from .room_create_details_response_data import RoomCreateDetailsResponseData +from .room_details_response import RoomDetailsResponse +from .rooms_listing_response import RoomsListingResponse +from .s3_credentials import S3Credentials +from .subscription_config import SubscriptionConfig - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -# import models into model package -from jellyfish._openapi_client.models.add_component_request import AddComponentRequest -from jellyfish._openapi_client.models.add_peer_request import AddPeerRequest -from jellyfish._openapi_client.models.component import Component -from jellyfish._openapi_client.models.component_details_response import ( - ComponentDetailsResponse, -) -from jellyfish._openapi_client.models.component_hls import ComponentHLS -from jellyfish._openapi_client.models.component_metadata_hls import ComponentMetadataHLS -from jellyfish._openapi_client.models.component_options import ComponentOptions -from jellyfish._openapi_client.models.component_options_hls import ComponentOptionsHLS -from jellyfish._openapi_client.models.component_options_hlss3 import ( - ComponentOptionsHLSS3, -) -from jellyfish._openapi_client.models.component_options_rtsp import ComponentOptionsRTSP -from jellyfish._openapi_client.models.component_rtsp import ComponentRTSP -from jellyfish._openapi_client.models.error import Error -from jellyfish._openapi_client.models.hls_skip import HlsSkip -from jellyfish._openapi_client.models.peer import Peer -from jellyfish._openapi_client.models.peer_details_response import PeerDetailsResponse -from jellyfish._openapi_client.models.peer_details_response_data import ( - PeerDetailsResponseData, -) -from jellyfish._openapi_client.models.peer_options import PeerOptions -from jellyfish._openapi_client.models.peer_options_web_rtc import PeerOptionsWebRTC -from jellyfish._openapi_client.models.peer_status import PeerStatus -from jellyfish._openapi_client.models.recording_list_response import ( - RecordingListResponse, -) -from jellyfish._openapi_client.models.room import Room -from jellyfish._openapi_client.models.room_config import RoomConfig -from jellyfish._openapi_client.models.room_create_details_response import ( - RoomCreateDetailsResponse, -) -from jellyfish._openapi_client.models.room_create_details_response_data import ( - RoomCreateDetailsResponseData, +__all__ = ( + "AddComponentJsonBody", + "AddPeerJsonBody", + "ComponentDetailsResponse", + "ComponentFile", + "ComponentHLS", + "ComponentOptionsFile", + "ComponentOptionsHLS", + "ComponentOptionsHLSSubscribeMode", + "ComponentOptionsRTSP", + "ComponentPropertiesHLS", + "ComponentPropertiesHLSSubscribeMode", + "ComponentPropertiesRTSP", + "ComponentRTSP", + "Error", + "Peer", + "PeerDetailsResponse", + "PeerDetailsResponseData", + "PeerOptionsWebRTC", + "PeerStatus", + "RecordingListResponse", + "Room", + "RoomConfig", + "RoomConfigVideoCodec", + "RoomCreateDetailsResponse", + "RoomCreateDetailsResponseData", + "RoomDetailsResponse", + "RoomsListingResponse", + "S3Credentials", + "SubscriptionConfig", ) -from jellyfish._openapi_client.models.room_details_response import RoomDetailsResponse -from jellyfish._openapi_client.models.rooms_listing_response import RoomsListingResponse -from jellyfish._openapi_client.models.s3_credentials import S3Credentials -from jellyfish._openapi_client.models.subscription_config import SubscriptionConfig diff --git a/jellyfish/_openapi_client/models/add_component_json_body.py b/jellyfish/_openapi_client/models/add_component_json_body.py new file mode 100644 index 0000000..82c7699 --- /dev/null +++ b/jellyfish/_openapi_client/models/add_component_json_body.py @@ -0,0 +1,131 @@ +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.component_options_file import ComponentOptionsFile + from ..models.component_options_hls import ComponentOptionsHLS + from ..models.component_options_rtsp import ComponentOptionsRTSP + + +T = TypeVar("T", bound="AddComponentJsonBody") + + +@_attrs_define +class AddComponentJsonBody: + """ """ + + type: str + """Component type""" + options: Union[ + "ComponentOptionsFile", "ComponentOptionsHLS", "ComponentOptionsRTSP", Unset + ] = UNSET + """Component-specific options""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + from ..models.component_options_hls import ComponentOptionsHLS + from ..models.component_options_rtsp import ComponentOptionsRTSP + + type = self.type + options: Union[Dict[str, Any], Unset] + if isinstance(self.options, Unset): + options = UNSET + + elif isinstance(self.options, ComponentOptionsHLS): + options = self.options.to_dict() + + elif isinstance(self.options, ComponentOptionsRTSP): + options = self.options.to_dict() + + else: + options = self.options.to_dict() + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "type": type, + } + ) + if options is not UNSET: + field_dict["options"] = options + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.component_options_file import ComponentOptionsFile + from ..models.component_options_hls import ComponentOptionsHLS + from ..models.component_options_rtsp import ComponentOptionsRTSP + + d = src_dict.copy() + type = d.pop("type") + + def _parse_options( + data: object, + ) -> Union[ + "ComponentOptionsFile", "ComponentOptionsHLS", "ComponentOptionsRTSP", Unset + ]: + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_options_type_0 = ( + ComponentOptionsHLS.from_dict(data) + ) + + return componentsschemas_component_options_type_0 + except: # noqa: E722 + pass + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_options_type_1 = ( + ComponentOptionsRTSP.from_dict(data) + ) + + return componentsschemas_component_options_type_1 + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_options_type_2 = ComponentOptionsFile.from_dict( + data + ) + + return componentsschemas_component_options_type_2 + + options = _parse_options(d.pop("options", UNSET)) + + add_component_json_body = cls( + type=type, + options=options, + ) + + add_component_json_body.additional_properties = d + return add_component_json_body + + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/add_component_request.py b/jellyfish/_openapi_client/models/add_component_request.py deleted file mode 100644 index 50d2544..0000000 --- a/jellyfish/_openapi_client/models/add_component_request.py +++ /dev/null @@ -1,77 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - - -from typing import Optional -from pydantic import BaseModel, Field, StrictStr -from jellyfish._openapi_client.models.component_options import ComponentOptions - - -class AddComponentRequest(BaseModel): - """ - AddComponentRequest - """ - - options: Optional[ComponentOptions] = None - type: StrictStr = Field(..., description="Component type") - __properties = ["options", "type"] - - class Config: - """Pydantic configuration""" - - allow_population_by_field_name = True - validate_assignment = True - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) - - @classmethod - def from_json(cls, json_str: str) -> AddComponentRequest: - """Create an instance of AddComponentRequest from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of options - if self.options: - _dict["options"] = self.options.to_dict() - return _dict - - @classmethod - def from_dict(cls, obj: dict) -> AddComponentRequest: - """Create an instance of AddComponentRequest from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return AddComponentRequest.parse_obj(obj) - - _obj = AddComponentRequest.parse_obj( - { - "options": ComponentOptions.from_dict(obj.get("options")) - if obj.get("options") is not None - else None, - "type": obj.get("type"), - } - ) - return _obj diff --git a/jellyfish/_openapi_client/models/add_peer_json_body.py b/jellyfish/_openapi_client/models/add_peer_json_body.py new file mode 100644 index 0000000..bf67477 --- /dev/null +++ b/jellyfish/_openapi_client/models/add_peer_json_body.py @@ -0,0 +1,74 @@ +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.peer_options_web_rtc import PeerOptionsWebRTC + + +T = TypeVar("T", bound="AddPeerJsonBody") + + +@_attrs_define +class AddPeerJsonBody: + """ """ + + options: "PeerOptionsWebRTC" + """Options specific to the WebRTC peer""" + type: str + """Peer type""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + options = self.options.to_dict() + + type = self.type + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "options": options, + "type": type, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.peer_options_web_rtc import PeerOptionsWebRTC + + d = src_dict.copy() + options = PeerOptionsWebRTC.from_dict(d.pop("options")) + + type = d.pop("type") + + add_peer_json_body = cls( + options=options, + type=type, + ) + + add_peer_json_body.additional_properties = d + return add_peer_json_body + + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/add_peer_request.py b/jellyfish/_openapi_client/models/add_peer_request.py deleted file mode 100644 index 5e6453d..0000000 --- a/jellyfish/_openapi_client/models/add_peer_request.py +++ /dev/null @@ -1,76 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - - -from pydantic import BaseModel, Field, StrictStr -from jellyfish._openapi_client.models.peer_options import PeerOptions - - -class AddPeerRequest(BaseModel): - """ - AddPeerRequest - """ - - options: PeerOptions = Field(...) - type: StrictStr = Field(..., description="Peer type") - __properties = ["options", "type"] - - class Config: - """Pydantic configuration""" - - allow_population_by_field_name = True - validate_assignment = True - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) - - @classmethod - def from_json(cls, json_str: str) -> AddPeerRequest: - """Create an instance of AddPeerRequest from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of options - if self.options: - _dict["options"] = self.options.to_dict() - return _dict - - @classmethod - def from_dict(cls, obj: dict) -> AddPeerRequest: - """Create an instance of AddPeerRequest from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return AddPeerRequest.parse_obj(obj) - - _obj = AddPeerRequest.parse_obj( - { - "options": PeerOptions.from_dict(obj.get("options")) - if obj.get("options") is not None - else None, - "type": obj.get("type"), - } - ) - return _obj diff --git a/jellyfish/_openapi_client/models/component.py b/jellyfish/_openapi_client/models/component.py deleted file mode 100644 index 72413b0..0000000 --- a/jellyfish/_openapi_client/models/component.py +++ /dev/null @@ -1,188 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -from inspect import getfullargspec -import json -import pprint -import re # noqa: F401 - -from typing import Any, List, Optional -from pydantic import BaseModel, Field, StrictStr, ValidationError, validator -from jellyfish._openapi_client.models.component_hls import ComponentHLS -from jellyfish._openapi_client.models.component_rtsp import ComponentRTSP -from typing import Union, Any, List, TYPE_CHECKING -from pydantic import StrictStr, Field - -COMPONENT_ONE_OF_SCHEMAS = ["ComponentHLS", "ComponentRTSP"] - - -class Component(BaseModel): - """ - Describes component - """ - - # data type: ComponentHLS - oneof_schema_1_validator: Optional[ComponentHLS] = None - # data type: ComponentRTSP - oneof_schema_2_validator: Optional[ComponentRTSP] = None - if TYPE_CHECKING: - actual_instance: Union[ComponentHLS, ComponentRTSP] - else: - actual_instance: Any - one_of_schemas: List[str] = Field(COMPONENT_ONE_OF_SCHEMAS, const=True) - - class Config: - validate_assignment = True - - discriminator_value_class_map = {} - - def __init__(self, *args, **kwargs): - if args: - if len(args) > 1: - raise ValueError( - "If a position argument is used, only 1 is allowed to set `actual_instance`" - ) - if kwargs: - raise ValueError( - "If a position argument is used, keyword arguments cannot be used." - ) - super().__init__(actual_instance=args[0]) - else: - super().__init__(**kwargs) - - @validator("actual_instance") - def actual_instance_must_validate_oneof(cls, v): - instance = Component.construct() - error_messages = [] - match = 0 - # validate data type: ComponentHLS - if not isinstance(v, ComponentHLS): - error_messages.append( - f"Error! Input type `{type(v)}` is not `ComponentHLS`" - ) - else: - match += 1 - # validate data type: ComponentRTSP - if not isinstance(v, ComponentRTSP): - error_messages.append( - f"Error! Input type `{type(v)}` is not `ComponentRTSP`" - ) - else: - match += 1 - if match > 1: - # more than 1 match - raise ValueError( - "Multiple matches found when setting `actual_instance` in Component with oneOf schemas: ComponentHLS, ComponentRTSP. Details: " - + ", ".join(error_messages) - ) - elif match == 0: - # no match - raise ValueError( - "No match found when setting `actual_instance` in Component with oneOf schemas: ComponentHLS, ComponentRTSP. Details: " - + ", ".join(error_messages) - ) - else: - return v - - @classmethod - def from_dict(cls, obj: dict) -> Component: - return cls.from_json(json.dumps(obj)) - - @classmethod - def from_json(cls, json_str: str) -> Component: - """Returns the object represented by the json string""" - instance = Component.construct() - error_messages = [] - match = 0 - - # use oneOf discriminator to lookup the data type - _data_type = json.loads(json_str).get("type") - if not _data_type: - raise ValueError( - "Failed to lookup data type from the field `type` in the input." - ) - - # check if data type is `ComponentHLS` - if _data_type == "ComponentHLS": - instance.actual_instance = ComponentHLS.from_json(json_str) - return instance - - # check if data type is `ComponentRTSP` - if _data_type == "ComponentRTSP": - instance.actual_instance = ComponentRTSP.from_json(json_str) - return instance - - # check if data type is `ComponentHLS` - if _data_type == "hls": - instance.actual_instance = ComponentHLS.from_json(json_str) - return instance - - # check if data type is `ComponentRTSP` - if _data_type == "rtsp": - instance.actual_instance = ComponentRTSP.from_json(json_str) - return instance - - # deserialize data into ComponentHLS - try: - instance.actual_instance = ComponentHLS.from_json(json_str) - match += 1 - except (ValidationError, ValueError) as e: - error_messages.append(str(e)) - # deserialize data into ComponentRTSP - try: - instance.actual_instance = ComponentRTSP.from_json(json_str) - match += 1 - except (ValidationError, ValueError) as e: - error_messages.append(str(e)) - - if match > 1: - # more than 1 match - raise ValueError( - "Multiple matches found when deserializing the JSON string into Component with oneOf schemas: ComponentHLS, ComponentRTSP. Details: " - + ", ".join(error_messages) - ) - elif match == 0: - # no match - raise ValueError( - "No match found when deserializing the JSON string into Component with oneOf schemas: ComponentHLS, ComponentRTSP. Details: " - + ", ".join(error_messages) - ) - else: - return instance - - def to_json(self) -> str: - """Returns the JSON representation of the actual instance""" - if self.actual_instance is None: - return "null" - - to_json = getattr(self.actual_instance, "to_json", None) - if callable(to_json): - return self.actual_instance.to_json() - else: - return json.dumps(self.actual_instance) - - def to_dict(self) -> dict: - """Returns the dict representation of the actual instance""" - if self.actual_instance is None: - return None - - to_dict = getattr(self.actual_instance, "to_dict", None) - if callable(to_dict): - return self.actual_instance.to_dict() - else: - # primitive type - return self.actual_instance - - def to_str(self) -> str: - """Returns the string representation of the actual instance""" - return pprint.pformat(self.dict()) diff --git a/jellyfish/_openapi_client/models/component_details_response.py b/jellyfish/_openapi_client/models/component_details_response.py index 5cac9bf..959e0bc 100644 --- a/jellyfish/_openapi_client/models/component_details_response.py +++ b/jellyfish/_openapi_client/models/component_details_response.py @@ -1,74 +1,108 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.component_file import ComponentFile + from ..models.component_hls import ComponentHLS + from ..models.component_rtsp import ComponentRTSP - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="ComponentDetailsResponse") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class ComponentDetailsResponse: + """Response containing component details""" -from pydantic import BaseModel, Field -from jellyfish._openapi_client.models.component import Component + data: Union["ComponentFile", "ComponentHLS", "ComponentRTSP"] + """Describes component""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + from ..models.component_hls import ComponentHLS + from ..models.component_rtsp import ComponentRTSP -class ComponentDetailsResponse(BaseModel): - """ - Response containing component details - """ + data: Dict[str, Any] - data: Component = Field(...) - __properties = ["data"] + if isinstance(self.data, ComponentHLS): + data = self.data.to_dict() - class Config: - """Pydantic configuration""" + elif isinstance(self.data, ComponentRTSP): + data = self.data.to_dict() - allow_population_by_field_name = True - validate_assignment = True + else: + data = self.data.to_dict() - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + return field_dict @classmethod - def from_json(cls, json_str: str) -> ComponentDetailsResponse: - """Create an instance of ComponentDetailsResponse from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of data - if self.data: - _dict["data"] = self.data.to_dict() - return _dict + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.component_file import ComponentFile + from ..models.component_hls import ComponentHLS + from ..models.component_rtsp import ComponentRTSP + + d = src_dict.copy() + + def _parse_data( + data: object, + ) -> Union["ComponentFile", "ComponentHLS", "ComponentRTSP"]: + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_type_0 = ComponentHLS.from_dict(data) + + return componentsschemas_component_type_0 + except: # noqa: E722 + pass + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_type_1 = ComponentRTSP.from_dict(data) + + return componentsschemas_component_type_1 + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_type_2 = ComponentFile.from_dict(data) + + return componentsschemas_component_type_2 + + data = _parse_data(d.pop("data")) + + component_details_response = cls( + data=data, + ) - @classmethod - def from_dict(cls, obj: dict) -> ComponentDetailsResponse: - """Create an instance of ComponentDetailsResponse from a dict""" - if obj is None: - return None + component_details_response.additional_properties = d + return component_details_response - if not isinstance(obj, dict): - return ComponentDetailsResponse.parse_obj(obj) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - _obj = ComponentDetailsResponse.parse_obj( - { - "data": Component.from_dict(obj.get("data")) - if obj.get("data") is not None - else None - } - ) - return _obj + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/component_file.py b/jellyfish/_openapi_client/models/component_file.py new file mode 100644 index 0000000..ee01e93 --- /dev/null +++ b/jellyfish/_openapi_client/models/component_file.py @@ -0,0 +1,67 @@ +from typing import Any, Dict, List, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="ComponentFile") + + +@_attrs_define +class ComponentFile: + """Describes the File component""" + + id: str + """Assigned component ID""" + type: str + """Component type""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + id = self.id + type = self.type + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "type": type, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + id = d.pop("id") + + type = d.pop("type") + + component_file = cls( + id=id, + type=type, + ) + + component_file.additional_properties = d + return component_file + + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/component_hls.py b/jellyfish/_openapi_client/models/component_hls.py index acedabe..a78a4ff 100644 --- a/jellyfish/_openapi_client/models/component_hls.py +++ b/jellyfish/_openapi_client/models/component_hls.py @@ -1,78 +1,81 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.component_properties_hls import ComponentPropertiesHLS - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="ComponentHLS") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class ComponentHLS: + """Describes the HLS component""" -from pydantic import BaseModel, Field, StrictStr -from jellyfish._openapi_client.models.component_metadata_hls import ComponentMetadataHLS + id: str + """Assigned component ID""" + properties: "ComponentPropertiesHLS" + """Properties specific to the HLS component""" + type: str + """Component type""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + id = self.id + properties = self.properties.to_dict() -class ComponentHLS(BaseModel): - """ - Describes HLS component - """ + type = self.type - id: StrictStr = Field(..., description="Assigned component ID") - metadata: ComponentMetadataHLS = Field(...) - type: StrictStr = Field(..., description="Component type") - __properties = ["id", "metadata", "type"] + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "properties": properties, + "type": type, + } + ) - class Config: - """Pydantic configuration""" + return field_dict - allow_population_by_field_name = True - validate_assignment = True + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.component_properties_hls import ComponentPropertiesHLS - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + d = src_dict.copy() + id = d.pop("id") - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + properties = ComponentPropertiesHLS.from_dict(d.pop("properties")) - @classmethod - def from_json(cls, json_str: str) -> ComponentHLS: - """Create an instance of ComponentHLS from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of metadata - if self.metadata: - _dict["metadata"] = self.metadata.to_dict() - return _dict + type = d.pop("type") - @classmethod - def from_dict(cls, obj: dict) -> ComponentHLS: - """Create an instance of ComponentHLS from a dict""" - if obj is None: - return None + component_hls = cls( + id=id, + properties=properties, + type=type, + ) - if not isinstance(obj, dict): - return ComponentHLS.parse_obj(obj) + component_hls.additional_properties = d + return component_hls - _obj = ComponentHLS.parse_obj( - { - "id": obj.get("id"), - "metadata": ComponentMetadataHLS.from_dict(obj.get("metadata")) - if obj.get("metadata") is not None - else None, - "type": obj.get("type"), - } - ) - return _obj + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/component_metadata_hls.py b/jellyfish/_openapi_client/models/component_metadata_hls.py deleted file mode 100644 index 68f0936..0000000 --- a/jellyfish/_openapi_client/models/component_metadata_hls.py +++ /dev/null @@ -1,112 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - - -from typing import Optional -from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, validator - - -class ComponentMetadataHLS(BaseModel): - """ - Metadata specific to the HLS component - """ - - low_latency: StrictBool = Field( - ..., alias="lowLatency", description="Whether the component uses LL-HLS" - ) - persistent: StrictBool = Field( - ..., description="Whether the video is stored after end of stream" - ) - playable: StrictBool = Field( - ..., description="Whether the generated HLS playlist is playable" - ) - subscribe_mode: StrictStr = Field( - ..., - alias="subscribeMode", - description="Whether the HLS component should subscribe to tracks automatically or manually", - ) - target_window_duration: Optional[StrictInt] = Field( - ..., - alias="targetWindowDuration", - description="Duration of stream available for viewer", - ) - __properties = [ - "lowLatency", - "persistent", - "playable", - "subscribeMode", - "targetWindowDuration", - ] - - @validator("subscribe_mode") - def subscribe_mode_validate_enum(cls, value): - """Validates the enum""" - if value not in ("auto", "manual"): - raise ValueError("must be one of enum values ('auto', 'manual')") - return value - - class Config: - """Pydantic configuration""" - - allow_population_by_field_name = True - validate_assignment = True - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) - - @classmethod - def from_json(cls, json_str: str) -> ComponentMetadataHLS: - """Create an instance of ComponentMetadataHLS from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # set to None if target_window_duration (nullable) is None - # and __fields_set__ contains the field - if ( - self.target_window_duration is None - and "target_window_duration" in self.__fields_set__ - ): - _dict["targetWindowDuration"] = None - - return _dict - - @classmethod - def from_dict(cls, obj: dict) -> ComponentMetadataHLS: - """Create an instance of ComponentMetadataHLS from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return ComponentMetadataHLS.parse_obj(obj) - - _obj = ComponentMetadataHLS.parse_obj( - { - "low_latency": obj.get("lowLatency"), - "persistent": obj.get("persistent"), - "playable": obj.get("playable"), - "subscribe_mode": obj.get("subscribeMode"), - "target_window_duration": obj.get("targetWindowDuration"), - } - ) - return _obj diff --git a/jellyfish/_openapi_client/models/component_options.py b/jellyfish/_openapi_client/models/component_options.py deleted file mode 100644 index 26e3dda..0000000 --- a/jellyfish/_openapi_client/models/component_options.py +++ /dev/null @@ -1,159 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -from inspect import getfullargspec -import json -import pprint -import re # noqa: F401 - -from typing import Any, List, Optional -from pydantic import BaseModel, Field, StrictStr, ValidationError, validator -from jellyfish._openapi_client.models.component_options_hls import ComponentOptionsHLS -from jellyfish._openapi_client.models.component_options_rtsp import ComponentOptionsRTSP -from typing import Union, Any, List, TYPE_CHECKING -from pydantic import StrictStr, Field - -COMPONENTOPTIONS_ONE_OF_SCHEMAS = ["ComponentOptionsHLS", "ComponentOptionsRTSP"] - - -class ComponentOptions(BaseModel): - """ - Component-specific options - """ - - # data type: ComponentOptionsHLS - oneof_schema_1_validator: Optional[ComponentOptionsHLS] = None - # data type: ComponentOptionsRTSP - oneof_schema_2_validator: Optional[ComponentOptionsRTSP] = None - if TYPE_CHECKING: - actual_instance: Union[ComponentOptionsHLS, ComponentOptionsRTSP] - else: - actual_instance: Any - one_of_schemas: List[str] = Field(COMPONENTOPTIONS_ONE_OF_SCHEMAS, const=True) - - class Config: - validate_assignment = True - - def __init__(self, *args, **kwargs): - if args: - if len(args) > 1: - raise ValueError( - "If a position argument is used, only 1 is allowed to set `actual_instance`" - ) - if kwargs: - raise ValueError( - "If a position argument is used, keyword arguments cannot be used." - ) - super().__init__(actual_instance=args[0]) - else: - super().__init__(**kwargs) - - @validator("actual_instance") - def actual_instance_must_validate_oneof(cls, v): - instance = ComponentOptions.construct() - error_messages = [] - match = 0 - # validate data type: ComponentOptionsHLS - if not isinstance(v, ComponentOptionsHLS): - error_messages.append( - f"Error! Input type `{type(v)}` is not `ComponentOptionsHLS`" - ) - else: - match += 1 - # validate data type: ComponentOptionsRTSP - if not isinstance(v, ComponentOptionsRTSP): - error_messages.append( - f"Error! Input type `{type(v)}` is not `ComponentOptionsRTSP`" - ) - else: - match += 1 - if match > 1: - # more than 1 match - raise ValueError( - "Multiple matches found when setting `actual_instance` in ComponentOptions with oneOf schemas: ComponentOptionsHLS, ComponentOptionsRTSP. Details: " - + ", ".join(error_messages) - ) - elif match == 0: - # no match - raise ValueError( - "No match found when setting `actual_instance` in ComponentOptions with oneOf schemas: ComponentOptionsHLS, ComponentOptionsRTSP. Details: " - + ", ".join(error_messages) - ) - else: - return v - - @classmethod - def from_dict(cls, obj: dict) -> ComponentOptions: - return cls.from_json(json.dumps(obj)) - - @classmethod - def from_json(cls, json_str: str) -> ComponentOptions: - """Returns the object represented by the json string""" - instance = ComponentOptions.construct() - error_messages = [] - match = 0 - - # deserialize data into ComponentOptionsHLS - try: - instance.actual_instance = ComponentOptionsHLS.from_json(json_str) - match += 1 - except (ValidationError, ValueError) as e: - error_messages.append(str(e)) - # deserialize data into ComponentOptionsRTSP - try: - instance.actual_instance = ComponentOptionsRTSP.from_json(json_str) - match += 1 - except (ValidationError, ValueError) as e: - error_messages.append(str(e)) - - if match > 1: - # more than 1 match - raise ValueError( - "Multiple matches found when deserializing the JSON string into ComponentOptions with oneOf schemas: ComponentOptionsHLS, ComponentOptionsRTSP. Details: " - + ", ".join(error_messages) - ) - elif match == 0: - # no match - raise ValueError( - "No match found when deserializing the JSON string into ComponentOptions with oneOf schemas: ComponentOptionsHLS, ComponentOptionsRTSP. Details: " - + ", ".join(error_messages) - ) - else: - return instance - - def to_json(self) -> str: - """Returns the JSON representation of the actual instance""" - if self.actual_instance is None: - return "null" - - to_json = getattr(self.actual_instance, "to_json", None) - if callable(to_json): - return self.actual_instance.to_json() - else: - return json.dumps(self.actual_instance) - - def to_dict(self) -> dict: - """Returns the dict representation of the actual instance""" - if self.actual_instance is None: - return None - - to_dict = getattr(self.actual_instance, "to_dict", None) - if callable(to_dict): - return self.actual_instance.to_dict() - else: - # primitive type - return self.actual_instance - - def to_str(self) -> str: - """Returns the string representation of the actual instance""" - return pprint.pformat(self.dict()) diff --git a/jellyfish/_openapi_client/models/component_options_file.py b/jellyfish/_openapi_client/models/component_options_file.py new file mode 100644 index 0000000..7760da7 --- /dev/null +++ b/jellyfish/_openapi_client/models/component_options_file.py @@ -0,0 +1,60 @@ +from typing import Any, Dict, List, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="ComponentOptionsFile") + + +@_attrs_define +class ComponentOptionsFile: + """Options specific to the File component""" + + file_path: str + """Path to track file. Must be either OPUS encapsulated in Ogg or raw h264""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + file_path = self.file_path + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "filePath": file_path, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + file_path = d.pop("filePath") + + component_options_file = cls( + file_path=file_path, + ) + + component_options_file.additional_properties = d + return component_options_file + + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/component_options_hls.py b/jellyfish/_openapi_client/models/component_options_hls.py index 3f31589..4142984 100644 --- a/jellyfish/_openapi_client/models/component_options_hls.py +++ b/jellyfish/_openapi_client/models/component_options_hls.py @@ -1,132 +1,121 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 +from ..models.component_options_hls_subscribe_mode import ( + ComponentOptionsHLSSubscribeMode, +) +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.s3_credentials import S3Credentials + + +T = TypeVar("T", bound="ComponentOptionsHLS") + + +@_attrs_define +class ComponentOptionsHLS: + """Options specific to the HLS component""" + + low_latency: Union[Unset, bool] = False + """Whether the component should use LL-HLS""" + persistent: Union[Unset, bool] = False + """Whether the video is stored after end of stream""" + s3: Union[Unset, None, "S3Credentials"] = UNSET + """An AWS S3 credential that will be used to send HLS stream. The stream will only be uploaded if credentials are provided""" + subscribe_mode: Union[ + Unset, ComponentOptionsHLSSubscribeMode + ] = ComponentOptionsHLSSubscribeMode.AUTO + """Whether the HLS component should subscribe to tracks automatically or manually.""" + target_window_duration: Union[Unset, None, int] = UNSET + """Duration of stream available for viewer""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + low_latency = self.low_latency + persistent = self.persistent + s3: Union[Unset, None, Dict[str, Any]] = UNSET + if not isinstance(self.s3, Unset): + s3 = self.s3.to_dict() if self.s3 else None + + subscribe_mode: Union[Unset, str] = UNSET + if not isinstance(self.subscribe_mode, Unset): + subscribe_mode = self.subscribe_mode.value + + target_window_duration = self.target_window_duration + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if low_latency is not UNSET: + field_dict["lowLatency"] = low_latency + if persistent is not UNSET: + field_dict["persistent"] = persistent + if s3 is not UNSET: + field_dict["s3"] = s3 + if subscribe_mode is not UNSET: + field_dict["subscribeMode"] = subscribe_mode + if target_window_duration is not UNSET: + field_dict["targetWindowDuration"] = target_window_duration + + return field_dict + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.s3_credentials import S3Credentials + + d = src_dict.copy() + low_latency = d.pop("lowLatency", UNSET) + + persistent = d.pop("persistent", UNSET) + + _s3 = d.pop("s3", UNSET) + s3: Union[Unset, None, S3Credentials] + if _s3 is None: + s3 = None + elif isinstance(_s3, Unset): + s3 = UNSET + else: + s3 = S3Credentials.from_dict(_s3) + + _subscribe_mode = d.pop("subscribeMode", UNSET) + subscribe_mode: Union[Unset, ComponentOptionsHLSSubscribeMode] + if isinstance(_subscribe_mode, Unset): + subscribe_mode = UNSET + else: + subscribe_mode = ComponentOptionsHLSSubscribeMode(_subscribe_mode) + + target_window_duration = d.pop("targetWindowDuration", UNSET) + + component_options_hls = cls( + low_latency=low_latency, + persistent=persistent, + s3=s3, + subscribe_mode=subscribe_mode, + target_window_duration=target_window_duration, + ) -from __future__ import annotations -import pprint -import re # noqa: F401 -import json + component_options_hls.additional_properties = d + return component_options_hls + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) -from typing import Optional -from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, validator -from jellyfish._openapi_client.models.component_options_hlss3 import ( - ComponentOptionsHLSS3, -) + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value -class ComponentOptionsHLS(BaseModel): - """ - Options specific to the HLS component - """ - - low_latency: Optional[StrictBool] = Field( - False, alias="lowLatency", description="Whether the component should use LL-HLS" - ) - persistent: Optional[StrictBool] = Field( - False, description="Whether the video is stored after end of stream" - ) - s3: Optional[ComponentOptionsHLSS3] = None - subscribe_mode: Optional[StrictStr] = Field( - "auto", - alias="subscribeMode", - description="Whether the HLS component should subscribe to tracks automatically or manually.", - ) - target_window_duration: Optional[StrictInt] = Field( - None, - alias="targetWindowDuration", - description="Duration of stream available for viewer", - ) - __properties = [ - "lowLatency", - "persistent", - "s3", - "subscribeMode", - "targetWindowDuration", - ] - - @validator("subscribe_mode") - def subscribe_mode_validate_enum(cls, value): - """Validates the enum""" - if value is None: - return value - - if value not in ("auto", "manual"): - raise ValueError("must be one of enum values ('auto', 'manual')") - return value - - class Config: - """Pydantic configuration""" - - allow_population_by_field_name = True - validate_assignment = True - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] - @classmethod - def from_json(cls, json_str: str) -> ComponentOptionsHLS: - """Create an instance of ComponentOptionsHLS from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of s3 - if self.s3: - _dict["s3"] = self.s3.to_dict() - # set to None if s3 (nullable) is None - # and __fields_set__ contains the field - if self.s3 is None and "s3" in self.__fields_set__: - _dict["s3"] = None - - # set to None if target_window_duration (nullable) is None - # and __fields_set__ contains the field - if ( - self.target_window_duration is None - and "target_window_duration" in self.__fields_set__ - ): - _dict["targetWindowDuration"] = None - - return _dict - - @classmethod - def from_dict(cls, obj: dict) -> ComponentOptionsHLS: - """Create an instance of ComponentOptionsHLS from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return ComponentOptionsHLS.parse_obj(obj) - - _obj = ComponentOptionsHLS.parse_obj( - { - "low_latency": obj.get("lowLatency") - if obj.get("lowLatency") is not None - else False, - "persistent": obj.get("persistent") - if obj.get("persistent") is not None - else False, - "s3": ComponentOptionsHLSS3.from_dict(obj.get("s3")) - if obj.get("s3") is not None - else None, - "subscribe_mode": obj.get("subscribeMode") - if obj.get("subscribeMode") is not None - else "auto", - "target_window_duration": obj.get("targetWindowDuration"), - } - ) - return _obj + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/component_options_hls_subscribe_mode.py b/jellyfish/_openapi_client/models/component_options_hls_subscribe_mode.py new file mode 100644 index 0000000..5336deb --- /dev/null +++ b/jellyfish/_openapi_client/models/component_options_hls_subscribe_mode.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class ComponentOptionsHLSSubscribeMode(str, Enum): + """Whether the HLS component should subscribe to tracks automatically or manually.""" + + AUTO = "auto" + MANUAL = "manual" + + def __str__(self) -> str: + return str(self.value) diff --git a/jellyfish/_openapi_client/models/component_options_hlss3.py b/jellyfish/_openapi_client/models/component_options_hlss3.py deleted file mode 100644 index cb146dd..0000000 --- a/jellyfish/_openapi_client/models/component_options_hlss3.py +++ /dev/null @@ -1,149 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -from inspect import getfullargspec -import json -import pprint -import re # noqa: F401 - -from typing import Any, List, Optional -from pydantic import BaseModel, Field, StrictStr, ValidationError, validator -from jellyfish._openapi_client.models.s3_credentials import S3Credentials -from typing import Union, Any, List, TYPE_CHECKING -from pydantic import StrictStr, Field - -COMPONENTOPTIONSHLSS3_ONE_OF_SCHEMAS = ["S3Credentials"] - - -class ComponentOptionsHLSS3(BaseModel): - """ - Credentials to AWS S3 bucket. - """ - - # data type: S3Credentials - oneof_schema_1_validator: Optional[S3Credentials] = None - if TYPE_CHECKING: - actual_instance: Union[S3Credentials] - else: - actual_instance: Any - one_of_schemas: List[str] = Field(COMPONENTOPTIONSHLSS3_ONE_OF_SCHEMAS, const=True) - - class Config: - validate_assignment = True - - def __init__(self, *args, **kwargs): - if args: - if len(args) > 1: - raise ValueError( - "If a position argument is used, only 1 is allowed to set `actual_instance`" - ) - if kwargs: - raise ValueError( - "If a position argument is used, keyword arguments cannot be used." - ) - super().__init__(actual_instance=args[0]) - else: - super().__init__(**kwargs) - - @validator("actual_instance") - def actual_instance_must_validate_oneof(cls, v): - if v is None: - return v - - instance = ComponentOptionsHLSS3.construct() - error_messages = [] - match = 0 - # validate data type: S3Credentials - if not isinstance(v, S3Credentials): - error_messages.append( - f"Error! Input type `{type(v)}` is not `S3Credentials`" - ) - else: - match += 1 - if match > 1: - # more than 1 match - raise ValueError( - "Multiple matches found when setting `actual_instance` in ComponentOptionsHLSS3 with oneOf schemas: S3Credentials. Details: " - + ", ".join(error_messages) - ) - elif match == 0: - # no match - raise ValueError( - "No match found when setting `actual_instance` in ComponentOptionsHLSS3 with oneOf schemas: S3Credentials. Details: " - + ", ".join(error_messages) - ) - else: - return v - - @classmethod - def from_dict(cls, obj: dict) -> ComponentOptionsHLSS3: - return cls.from_json(json.dumps(obj)) - - @classmethod - def from_json(cls, json_str: str) -> ComponentOptionsHLSS3: - """Returns the object represented by the json string""" - instance = ComponentOptionsHLSS3.construct() - if json_str is None: - return instance - - error_messages = [] - match = 0 - - # deserialize data into S3Credentials - try: - instance.actual_instance = S3Credentials.from_json(json_str) - match += 1 - except (ValidationError, ValueError) as e: - error_messages.append(str(e)) - - if match > 1: - # more than 1 match - raise ValueError( - "Multiple matches found when deserializing the JSON string into ComponentOptionsHLSS3 with oneOf schemas: S3Credentials. Details: " - + ", ".join(error_messages) - ) - elif match == 0: - # no match - raise ValueError( - "No match found when deserializing the JSON string into ComponentOptionsHLSS3 with oneOf schemas: S3Credentials. Details: " - + ", ".join(error_messages) - ) - else: - return instance - - def to_json(self) -> str: - """Returns the JSON representation of the actual instance""" - if self.actual_instance is None: - return "null" - - to_json = getattr(self.actual_instance, "to_json", None) - if callable(to_json): - return self.actual_instance.to_json() - else: - return json.dumps(self.actual_instance) - - def to_dict(self) -> dict: - """Returns the dict representation of the actual instance""" - if self.actual_instance is None: - return None - - to_dict = getattr(self.actual_instance, "to_dict", None) - if callable(to_dict): - return self.actual_instance.to_dict() - else: - # primitive type - return self.actual_instance - - def to_str(self) -> str: - """Returns the string representation of the actual instance""" - return pprint.pformat(self.dict()) diff --git a/jellyfish/_openapi_client/models/component_options_rtsp.py b/jellyfish/_openapi_client/models/component_options_rtsp.py index 7f6983f..83dc334 100644 --- a/jellyfish/_openapi_client/models/component_options_rtsp.py +++ b/jellyfish/_openapi_client/models/component_options_rtsp.py @@ -1,107 +1,94 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - - -from typing import Optional -from pydantic import BaseModel, Field, StrictBool, StrictStr, conint - - -class ComponentOptionsRTSP(BaseModel): - """ - Options specific to the RTSP component - """ - - keep_alive_interval: Optional[conint(strict=True, ge=0)] = Field( - 15000, - alias="keepAliveInterval", - description="Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source", - ) - pierce_nat: Optional[StrictBool] = Field( - True, - alias="pierceNat", - description="Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup", - ) - reconnect_delay: Optional[conint(strict=True, ge=0)] = Field( - 15000, - alias="reconnectDelay", - description="Delay (in ms) between successive reconnect attempts", - ) - rtp_port: Optional[conint(strict=True, le=65535, ge=1)] = Field( - 20000, alias="rtpPort", description="Local port RTP stream will be received at" - ) - source_uri: StrictStr = Field( - ..., alias="sourceUri", description="URI of RTSP source stream" - ) - __properties = [ - "keepAliveInterval", - "pierceNat", - "reconnectDelay", - "rtpPort", - "sourceUri", - ] - - class Config: - """Pydantic configuration""" - - allow_population_by_field_name = True - validate_assignment = True - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) +from typing import Any, Dict, List, Type, TypeVar, Union + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ComponentOptionsRTSP") + + +@_attrs_define +class ComponentOptionsRTSP: + """Options specific to the RTSP component""" + + source_uri: str + """URI of RTSP source stream""" + keep_alive_interval: Union[Unset, int] = 15000 + """Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source""" + pierce_nat: Union[Unset, bool] = True + """Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup""" + reconnect_delay: Union[Unset, int] = 15000 + """Delay (in ms) between successive reconnect attempts""" + rtp_port: Union[Unset, int] = 20000 + """Local port RTP stream will be received at""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + source_uri = self.source_uri + keep_alive_interval = self.keep_alive_interval + pierce_nat = self.pierce_nat + reconnect_delay = self.reconnect_delay + rtp_port = self.rtp_port + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "sourceUri": source_uri, + } + ) + if keep_alive_interval is not UNSET: + field_dict["keepAliveInterval"] = keep_alive_interval + if pierce_nat is not UNSET: + field_dict["pierceNat"] = pierce_nat + if reconnect_delay is not UNSET: + field_dict["reconnectDelay"] = reconnect_delay + if rtp_port is not UNSET: + field_dict["rtpPort"] = rtp_port + + return field_dict @classmethod - def from_json(cls, json_str: str) -> ComponentOptionsRTSP: - """Create an instance of ComponentOptionsRTSP from a JSON string""" - return cls.from_dict(json.loads(json_str)) + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + source_uri = d.pop("sourceUri") - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - return _dict + keep_alive_interval = d.pop("keepAliveInterval", UNSET) - @classmethod - def from_dict(cls, obj: dict) -> ComponentOptionsRTSP: - """Create an instance of ComponentOptionsRTSP from a dict""" - if obj is None: - return None + pierce_nat = d.pop("pierceNat", UNSET) - if not isinstance(obj, dict): - return ComponentOptionsRTSP.parse_obj(obj) + reconnect_delay = d.pop("reconnectDelay", UNSET) - _obj = ComponentOptionsRTSP.parse_obj( - { - "keep_alive_interval": obj.get("keepAliveInterval") - if obj.get("keepAliveInterval") is not None - else 15000, - "pierce_nat": obj.get("pierceNat") - if obj.get("pierceNat") is not None - else True, - "reconnect_delay": obj.get("reconnectDelay") - if obj.get("reconnectDelay") is not None - else 15000, - "rtp_port": obj.get("rtpPort") - if obj.get("rtpPort") is not None - else 20000, - "source_uri": obj.get("sourceUri"), - } + rtp_port = d.pop("rtpPort", UNSET) + + component_options_rtsp = cls( + source_uri=source_uri, + keep_alive_interval=keep_alive_interval, + pierce_nat=pierce_nat, + reconnect_delay=reconnect_delay, + rtp_port=rtp_port, ) - return _obj + + component_options_rtsp.additional_properties = d + return component_options_rtsp + + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/component_properties_hls.py b/jellyfish/_openapi_client/models/component_properties_hls.py new file mode 100644 index 0000000..6575ca2 --- /dev/null +++ b/jellyfish/_openapi_client/models/component_properties_hls.py @@ -0,0 +1,93 @@ +from typing import Any, Dict, List, Optional, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.component_properties_hls_subscribe_mode import ( + ComponentPropertiesHLSSubscribeMode, +) + +T = TypeVar("T", bound="ComponentPropertiesHLS") + + +@_attrs_define +class ComponentPropertiesHLS: + """Properties specific to the HLS component""" + + low_latency: bool + """Whether the component uses LL-HLS""" + persistent: bool + """Whether the video is stored after end of stream""" + playable: bool + """Whether the generated HLS playlist is playable""" + subscribe_mode: ComponentPropertiesHLSSubscribeMode + """Whether the HLS component should subscribe to tracks automatically or manually""" + target_window_duration: Optional[int] + """Duration of stream available for viewer""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + low_latency = self.low_latency + persistent = self.persistent + playable = self.playable + subscribe_mode = self.subscribe_mode.value + + target_window_duration = self.target_window_duration + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "lowLatency": low_latency, + "persistent": persistent, + "playable": playable, + "subscribeMode": subscribe_mode, + "targetWindowDuration": target_window_duration, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + low_latency = d.pop("lowLatency") + + persistent = d.pop("persistent") + + playable = d.pop("playable") + + subscribe_mode = ComponentPropertiesHLSSubscribeMode(d.pop("subscribeMode")) + + target_window_duration = d.pop("targetWindowDuration") + + component_properties_hls = cls( + low_latency=low_latency, + persistent=persistent, + playable=playable, + subscribe_mode=subscribe_mode, + target_window_duration=target_window_duration, + ) + + component_properties_hls.additional_properties = d + return component_properties_hls + + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/component_properties_hls_subscribe_mode.py b/jellyfish/_openapi_client/models/component_properties_hls_subscribe_mode.py new file mode 100644 index 0000000..d95a59e --- /dev/null +++ b/jellyfish/_openapi_client/models/component_properties_hls_subscribe_mode.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class ComponentPropertiesHLSSubscribeMode(str, Enum): + """Whether the HLS component should subscribe to tracks automatically or manually""" + + AUTO = "auto" + MANUAL = "manual" + + def __str__(self) -> str: + return str(self.value) diff --git a/jellyfish/_openapi_client/models/component_properties_rtsp.py b/jellyfish/_openapi_client/models/component_properties_rtsp.py new file mode 100644 index 0000000..e8a86b0 --- /dev/null +++ b/jellyfish/_openapi_client/models/component_properties_rtsp.py @@ -0,0 +1,49 @@ +from typing import Any, Dict, List, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="ComponentPropertiesRTSP") + + +@_attrs_define +class ComponentPropertiesRTSP: + """Properties specific to the RTSP component""" + + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + component_properties_rtsp = cls() + + component_properties_rtsp.additional_properties = d + return component_properties_rtsp + + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/component_rtsp.py b/jellyfish/_openapi_client/models/component_rtsp.py index dc6797c..c2b1f0e 100644 --- a/jellyfish/_openapi_client/models/component_rtsp.py +++ b/jellyfish/_openapi_client/models/component_rtsp.py @@ -1,75 +1,81 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.component_properties_rtsp import ComponentPropertiesRTSP - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="ComponentRTSP") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class ComponentRTSP: + """Describes the RTSP component""" -from typing import Any, Dict -from pydantic import BaseModel, Field, StrictStr + id: str + """Assigned component ID""" + properties: "ComponentPropertiesRTSP" + """Properties specific to the RTSP component""" + type: str + """Component type""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + id = self.id + properties = self.properties.to_dict() -class ComponentRTSP(BaseModel): - """ - Describes RTSP component - """ + type = self.type - id: StrictStr = Field(..., description="Assigned component ID") - metadata: Dict[str, Any] = Field( - ..., description="Metadata specific to the RTSP component" - ) - type: StrictStr = Field(..., description="Component type") - __properties = ["id", "metadata", "type"] + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "properties": properties, + "type": type, + } + ) - class Config: - """Pydantic configuration""" + return field_dict - allow_population_by_field_name = True - validate_assignment = True + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.component_properties_rtsp import ComponentPropertiesRTSP - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + d = src_dict.copy() + id = d.pop("id") - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + properties = ComponentPropertiesRTSP.from_dict(d.pop("properties")) - @classmethod - def from_json(cls, json_str: str) -> ComponentRTSP: - """Create an instance of ComponentRTSP from a JSON string""" - return cls.from_dict(json.loads(json_str)) + type = d.pop("type") - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - return _dict + component_rtsp = cls( + id=id, + properties=properties, + type=type, + ) - @classmethod - def from_dict(cls, obj: dict) -> ComponentRTSP: - """Create an instance of ComponentRTSP from a dict""" - if obj is None: - return None + component_rtsp.additional_properties = d + return component_rtsp - if not isinstance(obj, dict): - return ComponentRTSP.parse_obj(obj) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - _obj = ComponentRTSP.parse_obj( - { - "id": obj.get("id"), - "metadata": obj.get("metadata"), - "type": obj.get("type"), - } - ) - return _obj + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/error.py b/jellyfish/_openapi_client/models/error.py index cdb9dcc..d6f271d 100644 --- a/jellyfish/_openapi_client/models/error.py +++ b/jellyfish/_openapi_client/models/error.py @@ -1,64 +1,60 @@ -# coding: utf-8 +from typing import Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +T = TypeVar("T", bound="Error") - Do not edit the class manually. -""" # noqa: E501 +@_attrs_define +class Error: + """Error message""" -from __future__ import annotations -import pprint -import re # noqa: F401 -import json + errors: str + """Error details""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + errors = self.errors -from pydantic import BaseModel, Field, StrictStr + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "errors": errors, + } + ) + return field_dict -class Error(BaseModel): - """ - Error message - """ - - errors: StrictStr = Field(..., description="Error details") - __properties = ["errors"] - - class Config: - """Pydantic configuration""" - - allow_population_by_field_name = True - validate_assignment = True + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + errors = d.pop("errors") - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + error = cls( + errors=errors, + ) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + error.additional_properties = d + return error - @classmethod - def from_json(cls, json_str: str) -> Error: - """Create an instance of Error from a JSON string""" - return cls.from_dict(json.loads(json_str)) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - return _dict + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - @classmethod - def from_dict(cls, obj: dict) -> Error: - """Create an instance of Error from a dict""" - if obj is None: - return None + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - if not isinstance(obj, dict): - return Error.parse_obj(obj) + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] - _obj = Error.parse_obj({"errors": obj.get("errors")}) - return _obj + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/hls_skip.py b/jellyfish/_openapi_client/models/hls_skip.py deleted file mode 100644 index ce51cf2..0000000 --- a/jellyfish/_openapi_client/models/hls_skip.py +++ /dev/null @@ -1,32 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import json -import pprint -import re # noqa: F401 -from aenum import Enum, no_arg - - -class HlsSkip(str, Enum): - """ - Is delta manifest requested - """ - - """ - allowed enum values - """ - TRUE = "true" - - @classmethod - def from_json(cls, json_str: str) -> HlsSkip: - """Create an instance of HlsSkip from a JSON string""" - return HlsSkip(json.loads(json_str)) diff --git a/jellyfish/_openapi_client/models/peer.py b/jellyfish/_openapi_client/models/peer.py index 3a8e8ac..2c435fd 100644 --- a/jellyfish/_openapi_client/models/peer.py +++ b/jellyfish/_openapi_client/models/peer.py @@ -1,69 +1,77 @@ -# coding: utf-8 +from typing import Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +from ..models.peer_status import PeerStatus - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="Peer") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class Peer: + """Describes peer status""" + id: str + """Assigned peer id""" + status: PeerStatus + """Informs about the peer status""" + type: str + """Peer type""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" -from pydantic import BaseModel, Field, StrictStr -from jellyfish._openapi_client.models.peer_status import PeerStatus + def to_dict(self) -> Dict[str, Any]: + """@private""" + id = self.id + status = self.status.value + type = self.type -class Peer(BaseModel): - """ - Describes peer status - """ + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "status": status, + "type": type, + } + ) - id: StrictStr = Field(..., description="Assigned peer id") - status: PeerStatus = Field(...) - type: StrictStr = Field(..., description="Peer type") - __properties = ["id", "status", "type"] + return field_dict - class Config: - """Pydantic configuration""" + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + id = d.pop("id") - allow_population_by_field_name = True - validate_assignment = True + status = PeerStatus(d.pop("status")) - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + type = d.pop("type") - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + peer = cls( + id=id, + status=status, + type=type, + ) - @classmethod - def from_json(cls, json_str: str) -> Peer: - """Create an instance of Peer from a JSON string""" - return cls.from_dict(json.loads(json_str)) + peer.additional_properties = d + return peer - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - return _dict + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - @classmethod - def from_dict(cls, obj: dict) -> Peer: - """Create an instance of Peer from a dict""" - if obj is None: - return None + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - if not isinstance(obj, dict): - return Peer.parse_obj(obj) + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - _obj = Peer.parse_obj( - {"id": obj.get("id"), "status": obj.get("status"), "type": obj.get("type")} - ) - return _obj + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/peer_details_response.py b/jellyfish/_openapi_client/models/peer_details_response.py index ec905a1..5a90e27 100644 --- a/jellyfish/_openapi_client/models/peer_details_response.py +++ b/jellyfish/_openapi_client/models/peer_details_response.py @@ -1,76 +1,66 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.peer_details_response_data import PeerDetailsResponseData - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="PeerDetailsResponse") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class PeerDetailsResponse: + """Response containing peer details and their token""" -from pydantic import BaseModel, Field -from jellyfish._openapi_client.models.peer_details_response_data import ( - PeerDetailsResponseData, -) + data: "PeerDetailsResponseData" + """""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + data = self.data.to_dict() -class PeerDetailsResponse(BaseModel): - """ - Response containing peer details and their token - """ + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) - data: PeerDetailsResponseData = Field(...) - __properties = ["data"] + return field_dict - class Config: - """Pydantic configuration""" + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.peer_details_response_data import PeerDetailsResponseData - allow_population_by_field_name = True - validate_assignment = True + d = src_dict.copy() + data = PeerDetailsResponseData.from_dict(d.pop("data")) - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + peer_details_response = cls( + data=data, + ) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + peer_details_response.additional_properties = d + return peer_details_response - @classmethod - def from_json(cls, json_str: str) -> PeerDetailsResponse: - """Create an instance of PeerDetailsResponse from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of data - if self.data: - _dict["data"] = self.data.to_dict() - return _dict + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - @classmethod - def from_dict(cls, obj: dict) -> PeerDetailsResponse: - """Create an instance of PeerDetailsResponse from a dict""" - if obj is None: - return None + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - if not isinstance(obj, dict): - return PeerDetailsResponse.parse_obj(obj) + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - _obj = PeerDetailsResponse.parse_obj( - { - "data": PeerDetailsResponseData.from_dict(obj.get("data")) - if obj.get("data") is not None - else None - } - ) - return _obj + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/peer_details_response_data.py b/jellyfish/_openapi_client/models/peer_details_response_data.py index 2923e15..fb298ca 100644 --- a/jellyfish/_openapi_client/models/peer_details_response_data.py +++ b/jellyfish/_openapi_client/models/peer_details_response_data.py @@ -1,78 +1,74 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.peer import Peer - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="PeerDetailsResponseData") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class PeerDetailsResponseData: + """ """ -from pydantic import BaseModel, Field, StrictStr -from jellyfish._openapi_client.models.peer import Peer + peer: "Peer" + """Describes peer status""" + token: str + """Token for authorizing websocket connection""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + peer = self.peer.to_dict() -class PeerDetailsResponseData(BaseModel): - """ - PeerDetailsResponseData - """ + token = self.token - peer: Peer = Field(...) - token: StrictStr = Field( - ..., description="Token for authorizing websocket connection" - ) - __properties = ["peer", "token"] + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "peer": peer, + "token": token, + } + ) - class Config: - """Pydantic configuration""" + return field_dict - allow_population_by_field_name = True - validate_assignment = True + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.peer import Peer - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + d = src_dict.copy() + peer = Peer.from_dict(d.pop("peer")) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + token = d.pop("token") - @classmethod - def from_json(cls, json_str: str) -> PeerDetailsResponseData: - """Create an instance of PeerDetailsResponseData from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of peer - if self.peer: - _dict["peer"] = self.peer.to_dict() - return _dict + peer_details_response_data = cls( + peer=peer, + token=token, + ) - @classmethod - def from_dict(cls, obj: dict) -> PeerDetailsResponseData: - """Create an instance of PeerDetailsResponseData from a dict""" - if obj is None: - return None + peer_details_response_data.additional_properties = d + return peer_details_response_data - if not isinstance(obj, dict): - return PeerDetailsResponseData.parse_obj(obj) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - _obj = PeerDetailsResponseData.parse_obj( - { - "peer": Peer.from_dict(obj.get("peer")) - if obj.get("peer") is not None - else None, - "token": obj.get("token"), - } - ) - return _obj + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/peer_options.py b/jellyfish/_openapi_client/models/peer_options.py deleted file mode 100644 index 6f3caf2..0000000 --- a/jellyfish/_openapi_client/models/peer_options.py +++ /dev/null @@ -1,143 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -from inspect import getfullargspec -import json -import pprint -import re # noqa: F401 - -from typing import Any, List, Optional -from pydantic import BaseModel, Field, StrictStr, ValidationError, validator -from jellyfish._openapi_client.models.peer_options_web_rtc import PeerOptionsWebRTC -from typing import Union, Any, List, TYPE_CHECKING -from pydantic import StrictStr, Field - -PEEROPTIONS_ONE_OF_SCHEMAS = ["PeerOptionsWebRTC"] - - -class PeerOptions(BaseModel): - """ - Peer-specific options - """ - - # data type: PeerOptionsWebRTC - oneof_schema_1_validator: Optional[PeerOptionsWebRTC] = None - if TYPE_CHECKING: - actual_instance: Union[PeerOptionsWebRTC] - else: - actual_instance: Any - one_of_schemas: List[str] = Field(PEEROPTIONS_ONE_OF_SCHEMAS, const=True) - - class Config: - validate_assignment = True - - def __init__(self, *args, **kwargs): - if args: - if len(args) > 1: - raise ValueError( - "If a position argument is used, only 1 is allowed to set `actual_instance`" - ) - if kwargs: - raise ValueError( - "If a position argument is used, keyword arguments cannot be used." - ) - super().__init__(actual_instance=args[0]) - else: - super().__init__(**kwargs) - - @validator("actual_instance") - def actual_instance_must_validate_oneof(cls, v): - instance = PeerOptions.construct() - error_messages = [] - match = 0 - # validate data type: PeerOptionsWebRTC - if not isinstance(v, PeerOptionsWebRTC): - error_messages.append( - f"Error! Input type `{type(v)}` is not `PeerOptionsWebRTC`" - ) - else: - match += 1 - if match > 1: - # more than 1 match - raise ValueError( - "Multiple matches found when setting `actual_instance` in PeerOptions with oneOf schemas: PeerOptionsWebRTC. Details: " - + ", ".join(error_messages) - ) - elif match == 0: - # no match - raise ValueError( - "No match found when setting `actual_instance` in PeerOptions with oneOf schemas: PeerOptionsWebRTC. Details: " - + ", ".join(error_messages) - ) - else: - return v - - @classmethod - def from_dict(cls, obj: dict) -> PeerOptions: - return cls.from_json(json.dumps(obj)) - - @classmethod - def from_json(cls, json_str: str) -> PeerOptions: - """Returns the object represented by the json string""" - instance = PeerOptions.construct() - error_messages = [] - match = 0 - - # deserialize data into PeerOptionsWebRTC - try: - instance.actual_instance = PeerOptionsWebRTC.from_json(json_str) - match += 1 - except (ValidationError, ValueError) as e: - error_messages.append(str(e)) - - if match > 1: - # more than 1 match - raise ValueError( - "Multiple matches found when deserializing the JSON string into PeerOptions with oneOf schemas: PeerOptionsWebRTC. Details: " - + ", ".join(error_messages) - ) - elif match == 0: - # no match - raise ValueError( - "No match found when deserializing the JSON string into PeerOptions with oneOf schemas: PeerOptionsWebRTC. Details: " - + ", ".join(error_messages) - ) - else: - return instance - - def to_json(self) -> str: - """Returns the JSON representation of the actual instance""" - if self.actual_instance is None: - return "null" - - to_json = getattr(self.actual_instance, "to_json", None) - if callable(to_json): - return self.actual_instance.to_json() - else: - return json.dumps(self.actual_instance) - - def to_dict(self) -> dict: - """Returns the dict representation of the actual instance""" - if self.actual_instance is None: - return None - - to_dict = getattr(self.actual_instance, "to_dict", None) - if callable(to_dict): - return self.actual_instance.to_dict() - else: - # primitive type - return self.actual_instance - - def to_str(self) -> str: - """Returns the string representation of the actual instance""" - return pprint.pformat(self.dict()) diff --git a/jellyfish/_openapi_client/models/peer_options_web_rtc.py b/jellyfish/_openapi_client/models/peer_options_web_rtc.py index c58f889..0163ef7 100644 --- a/jellyfish/_openapi_client/models/peer_options_web_rtc.py +++ b/jellyfish/_openapi_client/models/peer_options_web_rtc.py @@ -1,73 +1,60 @@ -# coding: utf-8 +from typing import Any, Dict, List, Type, TypeVar, Union -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +from ..types import UNSET, Unset - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="PeerOptionsWebRTC") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class PeerOptionsWebRTC: + """Options specific to the WebRTC peer""" + enable_simulcast: Union[Unset, bool] = True + """Enables the peer to use simulcast""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" -from typing import Optional -from pydantic import BaseModel, Field, StrictBool + def to_dict(self) -> Dict[str, Any]: + """@private""" + enable_simulcast = self.enable_simulcast + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if enable_simulcast is not UNSET: + field_dict["enableSimulcast"] = enable_simulcast -class PeerOptionsWebRTC(BaseModel): - """ - Options specific to the WebRTC peer - """ + return field_dict - enable_simulcast: Optional[StrictBool] = Field( - True, alias="enableSimulcast", description="Enables the peer to use simulcast" - ) - __properties = ["enableSimulcast"] + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + enable_simulcast = d.pop("enableSimulcast", UNSET) - class Config: - """Pydantic configuration""" + peer_options_web_rtc = cls( + enable_simulcast=enable_simulcast, + ) - allow_population_by_field_name = True - validate_assignment = True + peer_options_web_rtc.additional_properties = d + return peer_options_web_rtc - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - @classmethod - def from_json(cls, json_str: str) -> PeerOptionsWebRTC: - """Create an instance of PeerOptionsWebRTC from a JSON string""" - return cls.from_dict(json.loads(json_str)) + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - return _dict + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] - @classmethod - def from_dict(cls, obj: dict) -> PeerOptionsWebRTC: - """Create an instance of PeerOptionsWebRTC from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return PeerOptionsWebRTC.parse_obj(obj) - - _obj = PeerOptionsWebRTC.parse_obj( - { - "enable_simulcast": obj.get("enableSimulcast") - if obj.get("enableSimulcast") is not None - else True - } - ) - return _obj + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/peer_status.py b/jellyfish/_openapi_client/models/peer_status.py index d43864f..f922886 100644 --- a/jellyfish/_openapi_client/models/peer_status.py +++ b/jellyfish/_openapi_client/models/peer_status.py @@ -1,33 +1,11 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import json -import pprint -import re # noqa: F401 -from aenum import Enum, no_arg +from enum import Enum class PeerStatus(str, Enum): - """ - Informs about the peer status - """ + """Informs about the peer status""" - """ - allowed enum values - """ CONNECTED = "connected" DISCONNECTED = "disconnected" - @classmethod - def from_json(cls, json_str: str) -> PeerStatus: - """Create an instance of PeerStatus from a JSON string""" - return PeerStatus(json.loads(json_str)) + def __str__(self) -> str: + return str(self.value) diff --git a/jellyfish/_openapi_client/models/recording_list_response.py b/jellyfish/_openapi_client/models/recording_list_response.py index 1378b7e..de63699 100644 --- a/jellyfish/_openapi_client/models/recording_list_response.py +++ b/jellyfish/_openapi_client/models/recording_list_response.py @@ -1,65 +1,60 @@ -# coding: utf-8 +from typing import Any, Dict, List, Type, TypeVar, cast -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +T = TypeVar("T", bound="RecordingListResponse") - Do not edit the class manually. -""" # noqa: E501 +@_attrs_define +class RecordingListResponse: + """Response containing list of all recording""" -from __future__ import annotations -import pprint -import re # noqa: F401 -import json + data: List[str] + """None""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + data = self.data -from typing import List -from pydantic import BaseModel, Field, StrictStr, conlist + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + return field_dict -class RecordingListResponse(BaseModel): - """ - Response containing list of all recording - """ - - data: conlist(StrictStr) = Field(...) - __properties = ["data"] - - class Config: - """Pydantic configuration""" - - allow_population_by_field_name = True - validate_assignment = True + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + data = cast(List[str], d.pop("data")) - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + recording_list_response = cls( + data=data, + ) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + recording_list_response.additional_properties = d + return recording_list_response - @classmethod - def from_json(cls, json_str: str) -> RecordingListResponse: - """Create an instance of RecordingListResponse from a JSON string""" - return cls.from_dict(json.loads(json_str)) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - return _dict + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - @classmethod - def from_dict(cls, obj: dict) -> RecordingListResponse: - """Create an instance of RecordingListResponse from a dict""" - if obj is None: - return None + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - if not isinstance(obj, dict): - return RecordingListResponse.parse_obj(obj) + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] - _obj = RecordingListResponse.parse_obj({"data": obj.get("data")}) - return _obj + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/room.py b/jellyfish/_openapi_client/models/room.py index 1f81b37..62fcbae 100644 --- a/jellyfish/_openapi_client/models/room.py +++ b/jellyfish/_openapi_client/models/room.py @@ -1,103 +1,153 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.component_file import ComponentFile + from ..models.component_hls import ComponentHLS + from ..models.component_rtsp import ComponentRTSP + from ..models.peer import Peer + from ..models.room_config import RoomConfig - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="Room") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class Room: + """Description of the room state""" -from typing import List -from pydantic import BaseModel, Field, StrictStr, conlist -from jellyfish._openapi_client.models.component import Component -from jellyfish._openapi_client.models.peer import Peer -from jellyfish._openapi_client.models.room_config import RoomConfig + components: List[Union["ComponentFile", "ComponentHLS", "ComponentRTSP"]] + """List of all components""" + config: "RoomConfig" + """Room configuration""" + id: str + """Room ID""" + peers: List["Peer"] + """List of all peers""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + from ..models.component_hls import ComponentHLS + from ..models.component_rtsp import ComponentRTSP -class Room(BaseModel): - """ - Description of the room state - """ + components = [] + for components_item_data in self.components: + components_item: Dict[str, Any] - components: conlist(Component) = Field(...) - config: RoomConfig = Field(...) - id: StrictStr = Field(..., description="Room ID") - peers: conlist(Peer) = Field(...) - __properties = ["components", "config", "id", "peers"] + if isinstance(components_item_data, ComponentHLS): + components_item = components_item_data.to_dict() - class Config: - """Pydantic configuration""" + elif isinstance(components_item_data, ComponentRTSP): + components_item = components_item_data.to_dict() - allow_population_by_field_name = True - validate_assignment = True + else: + components_item = components_item_data.to_dict() - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + components.append(components_item) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + config = self.config.to_dict() - @classmethod - def from_json(cls, json_str: str) -> Room: - """Create an instance of Room from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of each item in components (list) - _items = [] - if self.components: - for _item in self.components: - if _item: - _items.append(_item.to_dict()) - _dict["components"] = _items - # override the default output from pydantic by calling `to_dict()` of config - if self.config: - _dict["config"] = self.config.to_dict() - # override the default output from pydantic by calling `to_dict()` of each item in peers (list) - _items = [] - if self.peers: - for _item in self.peers: - if _item: - _items.append(_item.to_dict()) - _dict["peers"] = _items - return _dict - - @classmethod - def from_dict(cls, obj: dict) -> Room: - """Create an instance of Room from a dict""" - if obj is None: - return None + id = self.id + peers = [] + for peers_item_data in self.peers: + peers_item = peers_item_data.to_dict() - if not isinstance(obj, dict): - return Room.parse_obj(obj) + peers.append(peers_item) - _obj = Room.parse_obj( + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( { - "components": [ - Component.from_dict(_item) for _item in obj.get("components") - ] - if obj.get("components") is not None - else None, - "config": RoomConfig.from_dict(obj.get("config")) - if obj.get("config") is not None - else None, - "id": obj.get("id"), - "peers": [Peer.from_dict(_item) for _item in obj.get("peers")] - if obj.get("peers") is not None - else None, + "components": components, + "config": config, + "id": id, + "peers": peers, } ) - return _obj + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.component_file import ComponentFile + from ..models.component_hls import ComponentHLS + from ..models.component_rtsp import ComponentRTSP + from ..models.peer import Peer + from ..models.room_config import RoomConfig + + d = src_dict.copy() + components = [] + _components = d.pop("components") + for components_item_data in _components: + + def _parse_components_item( + data: object, + ) -> Union["ComponentFile", "ComponentHLS", "ComponentRTSP"]: + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_type_0 = ComponentHLS.from_dict(data) + + return componentsschemas_component_type_0 + except: # noqa: E722 + pass + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_type_1 = ComponentRTSP.from_dict(data) + + return componentsschemas_component_type_1 + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + componentsschemas_component_type_2 = ComponentFile.from_dict(data) + + return componentsschemas_component_type_2 + + components_item = _parse_components_item(components_item_data) + + components.append(components_item) + + config = RoomConfig.from_dict(d.pop("config")) + + id = d.pop("id") + + peers = [] + _peers = d.pop("peers") + for peers_item_data in _peers: + peers_item = Peer.from_dict(peers_item_data) + + peers.append(peers_item) + + room = cls( + components=components, + config=config, + id=id, + peers=peers, + ) + + room.additional_properties = d + return room + + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/room_config.py b/jellyfish/_openapi_client/models/room_config.py index d17ba5a..ede86ec 100644 --- a/jellyfish/_openapi_client/models/room_config.py +++ b/jellyfish/_openapi_client/models/room_config.py @@ -1,110 +1,87 @@ -# coding: utf-8 +from typing import Any, Dict, List, Type, TypeVar, Union -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +from ..models.room_config_video_codec import RoomConfigVideoCodec +from ..types import UNSET, Unset - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="RoomConfig") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class RoomConfig: + """Room configuration""" + max_peers: Union[Unset, None, int] = UNSET + """Maximum amount of peers allowed into the room""" + video_codec: Union[Unset, None, RoomConfigVideoCodec] = UNSET + """Enforces video codec for each peer in the room""" + webhook_url: Union[Unset, None, str] = UNSET + """URL where Jellyfish notifications will be sent""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" -from typing import Optional -from pydantic import BaseModel, Field, StrictStr, conint, validator + def to_dict(self) -> Dict[str, Any]: + """@private""" + max_peers = self.max_peers + video_codec: Union[Unset, None, str] = UNSET + if not isinstance(self.video_codec, Unset): + video_codec = self.video_codec.value if self.video_codec else None + webhook_url = self.webhook_url -class RoomConfig(BaseModel): - """ - Room configuration - """ + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if max_peers is not UNSET: + field_dict["maxPeers"] = max_peers + if video_codec is not UNSET: + field_dict["videoCodec"] = video_codec + if webhook_url is not UNSET: + field_dict["webhookUrl"] = webhook_url - max_peers: Optional[conint(strict=True, ge=1)] = Field( - None, - alias="maxPeers", - description="Maximum amount of peers allowed into the room", - ) - video_codec: Optional[StrictStr] = Field( - None, - alias="videoCodec", - description="Enforces video codec for each peer in the room", - ) - webhook_url: Optional[StrictStr] = Field( - None, - alias="webhookUrl", - description="URL where Jellyfish notifications will be sent", - ) - __properties = ["maxPeers", "videoCodec", "webhookUrl"] + return field_dict - @validator("video_codec") - def video_codec_validate_enum(cls, value): - """Validates the enum""" - if value is None: - return value - - if value not in ("h264", "vp8"): - raise ValueError("must be one of enum values ('h264', 'vp8')") - return value + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + max_peers = d.pop("maxPeers", UNSET) + + _video_codec = d.pop("videoCodec", UNSET) + video_codec: Union[Unset, None, RoomConfigVideoCodec] + if _video_codec is None: + video_codec = None + elif isinstance(_video_codec, Unset): + video_codec = UNSET + else: + video_codec = RoomConfigVideoCodec(_video_codec) + + webhook_url = d.pop("webhookUrl", UNSET) + + room_config = cls( + max_peers=max_peers, + video_codec=video_codec, + webhook_url=webhook_url, + ) - class Config: - """Pydantic configuration""" + room_config.additional_properties = d + return room_config - allow_population_by_field_name = True - validate_assignment = True + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - @classmethod - def from_json(cls, json_str: str) -> RoomConfig: - """Create an instance of RoomConfig from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # set to None if max_peers (nullable) is None - # and __fields_set__ contains the field - if self.max_peers is None and "max_peers" in self.__fields_set__: - _dict["maxPeers"] = None - - # set to None if video_codec (nullable) is None - # and __fields_set__ contains the field - if self.video_codec is None and "video_codec" in self.__fields_set__: - _dict["videoCodec"] = None - - # set to None if webhook_url (nullable) is None - # and __fields_set__ contains the field - if self.webhook_url is None and "webhook_url" in self.__fields_set__: - _dict["webhookUrl"] = None - - return _dict + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] - @classmethod - def from_dict(cls, obj: dict) -> RoomConfig: - """Create an instance of RoomConfig from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return RoomConfig.parse_obj(obj) - - _obj = RoomConfig.parse_obj( - { - "max_peers": obj.get("maxPeers"), - "video_codec": obj.get("videoCodec"), - "webhook_url": obj.get("webhookUrl"), - } - ) - return _obj + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/room_config_video_codec.py b/jellyfish/_openapi_client/models/room_config_video_codec.py new file mode 100644 index 0000000..972e4dd --- /dev/null +++ b/jellyfish/_openapi_client/models/room_config_video_codec.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class RoomConfigVideoCodec(str, Enum): + """Enforces video codec for each peer in the room""" + + H264 = "h264" + VP8 = "vp8" + + def __str__(self) -> str: + return str(self.value) diff --git a/jellyfish/_openapi_client/models/room_create_details_response.py b/jellyfish/_openapi_client/models/room_create_details_response.py index d31ac50..8194c0e 100644 --- a/jellyfish/_openapi_client/models/room_create_details_response.py +++ b/jellyfish/_openapi_client/models/room_create_details_response.py @@ -1,76 +1,68 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.room_create_details_response_data import RoomCreateDetailsResponseData - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="RoomCreateDetailsResponse") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class RoomCreateDetailsResponse: + """Response containing room details""" -from pydantic import BaseModel, Field -from jellyfish._openapi_client.models.room_create_details_response_data import ( - RoomCreateDetailsResponseData, -) + data: "RoomCreateDetailsResponseData" + """""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + data = self.data.to_dict() -class RoomCreateDetailsResponse(BaseModel): - """ - Response containing room details - """ + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) - data: RoomCreateDetailsResponseData = Field(...) - __properties = ["data"] + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.room_create_details_response_data import ( + RoomCreateDetailsResponseData, + ) - class Config: - """Pydantic configuration""" + d = src_dict.copy() + data = RoomCreateDetailsResponseData.from_dict(d.pop("data")) - allow_population_by_field_name = True - validate_assignment = True + room_create_details_response = cls( + data=data, + ) - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + room_create_details_response.additional_properties = d + return room_create_details_response - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - @classmethod - def from_json(cls, json_str: str) -> RoomCreateDetailsResponse: - """Create an instance of RoomCreateDetailsResponse from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of data - if self.data: - _dict["data"] = self.data.to_dict() - return _dict + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - @classmethod - def from_dict(cls, obj: dict) -> RoomCreateDetailsResponse: - """Create an instance of RoomCreateDetailsResponse from a dict""" - if obj is None: - return None + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - if not isinstance(obj, dict): - return RoomCreateDetailsResponse.parse_obj(obj) + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] - _obj = RoomCreateDetailsResponse.parse_obj( - { - "data": RoomCreateDetailsResponseData.from_dict(obj.get("data")) - if obj.get("data") is not None - else None - } - ) - return _obj + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/room_create_details_response_data.py b/jellyfish/_openapi_client/models/room_create_details_response_data.py index 3c886fc..09bab6e 100644 --- a/jellyfish/_openapi_client/models/room_create_details_response_data.py +++ b/jellyfish/_openapi_client/models/room_create_details_response_data.py @@ -1,79 +1,73 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.room import Room - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="RoomCreateDetailsResponseData") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class RoomCreateDetailsResponseData: + """ """ -from pydantic import BaseModel, Field, StrictStr -from jellyfish._openapi_client.models.room import Room + jellyfish_address: str + """Jellyfish instance address where the room was created. This might be different than the address of Jellyfish where the request was sent only when running a cluster of Jellyfishes.""" + room: "Room" + """Description of the room state""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + jellyfish_address = self.jellyfish_address + room = self.room.to_dict() -class RoomCreateDetailsResponseData(BaseModel): - """ - RoomCreateDetailsResponseData - """ + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "jellyfish_address": jellyfish_address, + "room": room, + } + ) - jellyfish_address: StrictStr = Field( - ..., - description="Jellyfish instance address where the room was created. This might be different than the address of Jellyfish where the request was sent only when running a cluster of Jellyfishes.", - ) - room: Room = Field(...) - __properties = ["jellyfish_address", "room"] + return field_dict - class Config: - """Pydantic configuration""" + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.room import Room - allow_population_by_field_name = True - validate_assignment = True + d = src_dict.copy() + jellyfish_address = d.pop("jellyfish_address") - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + room = Room.from_dict(d.pop("room")) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + room_create_details_response_data = cls( + jellyfish_address=jellyfish_address, + room=room, + ) - @classmethod - def from_json(cls, json_str: str) -> RoomCreateDetailsResponseData: - """Create an instance of RoomCreateDetailsResponseData from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of room - if self.room: - _dict["room"] = self.room.to_dict() - return _dict + room_create_details_response_data.additional_properties = d + return room_create_details_response_data - @classmethod - def from_dict(cls, obj: dict) -> RoomCreateDetailsResponseData: - """Create an instance of RoomCreateDetailsResponseData from a dict""" - if obj is None: - return None + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - if not isinstance(obj, dict): - return RoomCreateDetailsResponseData.parse_obj(obj) + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - _obj = RoomCreateDetailsResponseData.parse_obj( - { - "jellyfish_address": obj.get("jellyfish_address"), - "room": Room.from_dict(obj.get("room")) - if obj.get("room") is not None - else None, - } - ) - return _obj + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/room_details_response.py b/jellyfish/_openapi_client/models/room_details_response.py index 85c4135..9d3427b 100644 --- a/jellyfish/_openapi_client/models/room_details_response.py +++ b/jellyfish/_openapi_client/models/room_details_response.py @@ -1,74 +1,66 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.room import Room - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="RoomDetailsResponse") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class RoomDetailsResponse: + """Response containing room details""" -from pydantic import BaseModel, Field -from jellyfish._openapi_client.models.room import Room + data: "Room" + """Description of the room state""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + data = self.data.to_dict() -class RoomDetailsResponse(BaseModel): - """ - Response containing room details - """ + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) - data: Room = Field(...) - __properties = ["data"] + return field_dict - class Config: - """Pydantic configuration""" + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.room import Room - allow_population_by_field_name = True - validate_assignment = True + d = src_dict.copy() + data = Room.from_dict(d.pop("data")) - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + room_details_response = cls( + data=data, + ) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + room_details_response.additional_properties = d + return room_details_response - @classmethod - def from_json(cls, json_str: str) -> RoomDetailsResponse: - """Create an instance of RoomDetailsResponse from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of data - if self.data: - _dict["data"] = self.data.to_dict() - return _dict + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - @classmethod - def from_dict(cls, obj: dict) -> RoomDetailsResponse: - """Create an instance of RoomDetailsResponse from a dict""" - if obj is None: - return None + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - if not isinstance(obj, dict): - return RoomDetailsResponse.parse_obj(obj) + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - _obj = RoomDetailsResponse.parse_obj( - { - "data": Room.from_dict(obj.get("data")) - if obj.get("data") is not None - else None - } - ) - return _obj + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/rooms_listing_response.py b/jellyfish/_openapi_client/models/rooms_listing_response.py index 4467c10..828f4f7 100644 --- a/jellyfish/_openapi_client/models/rooms_listing_response.py +++ b/jellyfish/_openapi_client/models/rooms_listing_response.py @@ -1,79 +1,75 @@ -# coding: utf-8 +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +if TYPE_CHECKING: + from ..models.room import Room - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="RoomsListingResponse") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class RoomsListingResponse: + """Response containing list of all rooms""" -from typing import List -from pydantic import BaseModel, Field, conlist -from jellyfish._openapi_client.models.room import Room + data: List["Room"] + """None""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + def to_dict(self) -> Dict[str, Any]: + """@private""" + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() -class RoomsListingResponse(BaseModel): - """ - Response containing list of all rooms - """ + data.append(data_item) - data: conlist(Room) = Field(...) - __properties = ["data"] + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) - class Config: - """Pydantic configuration""" + return field_dict - allow_population_by_field_name = True - validate_assignment = True + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + from ..models.room import Room - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + d = src_dict.copy() + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = Room.from_dict(data_item_data) - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + data.append(data_item) - @classmethod - def from_json(cls, json_str: str) -> RoomsListingResponse: - """Create an instance of RoomsListingResponse from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - # override the default output from pydantic by calling `to_dict()` of each item in data (list) - _items = [] - if self.data: - for _item in self.data: - if _item: - _items.append(_item.to_dict()) - _dict["data"] = _items - return _dict + rooms_listing_response = cls( + data=data, + ) - @classmethod - def from_dict(cls, obj: dict) -> RoomsListingResponse: - """Create an instance of RoomsListingResponse from a dict""" - if obj is None: - return None + rooms_listing_response.additional_properties = d + return rooms_listing_response - if not isinstance(obj, dict): - return RoomsListingResponse.parse_obj(obj) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - _obj = RoomsListingResponse.parse_obj( - { - "data": [Room.from_dict(_item) for _item in obj.get("data")] - if obj.get("data") is not None - else None - } - ) - return _obj + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/s3_credentials.py b/jellyfish/_openapi_client/models/s3_credentials.py index 55ff77a..f662177 100644 --- a/jellyfish/_openapi_client/models/s3_credentials.py +++ b/jellyfish/_openapi_client/models/s3_credentials.py @@ -1,86 +1,84 @@ -# coding: utf-8 +from typing import Any, Dict, List, Type, TypeVar -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +T = TypeVar("T", bound="S3Credentials") - Do not edit the class manually. -""" # noqa: E501 +@_attrs_define +class S3Credentials: + """An AWS S3 credential that will be used to send HLS stream. The stream will only be uploaded if credentials are + provided -from __future__ import annotations -import pprint -import re # noqa: F401 -import json + """ + access_key_id: str + """An AWS access key identifier, linked to your AWS account.""" + bucket: str + """The name of the S3 bucket where your data will be stored.""" + region: str + """The AWS region where your bucket is located.""" + secret_access_key: str + """The secret key that is linked to the Access Key ID.""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" + + def to_dict(self) -> Dict[str, Any]: + """@private""" + access_key_id = self.access_key_id + bucket = self.bucket + region = self.region + secret_access_key = self.secret_access_key + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "accessKeyId": access_key_id, + "bucket": bucket, + "region": region, + "secretAccessKey": secret_access_key, + } + ) -from pydantic import BaseModel, Field, StrictStr + return field_dict + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + access_key_id = d.pop("accessKeyId") -class S3Credentials(BaseModel): - """ - An AWS S3 credential that will be used to send HLS stream. The stream will only be uploaded if credentials are provided - """ + bucket = d.pop("bucket") - access_key_id: StrictStr = Field( - ..., - alias="accessKeyId", - description="An AWS access key identifier, linked to your AWS account.", - ) - bucket: StrictStr = Field( - ..., description="The name of the S3 bucket where your data will be stored." - ) - region: StrictStr = Field( - ..., description="The AWS region where your bucket is located." - ) - secret_access_key: StrictStr = Field( - ..., - alias="secretAccessKey", - description="The secret key that is linked to the Access Key ID.", - ) - __properties = ["accessKeyId", "bucket", "region", "secretAccessKey"] - - class Config: - """Pydantic configuration""" - - allow_population_by_field_name = True - validate_assignment = True - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + region = d.pop("region") - @classmethod - def from_json(cls, json_str: str) -> S3Credentials: - """Create an instance of S3Credentials from a JSON string""" - return cls.from_dict(json.loads(json_str)) + secret_access_key = d.pop("secretAccessKey") - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - return _dict + s3_credentials = cls( + access_key_id=access_key_id, + bucket=bucket, + region=region, + secret_access_key=secret_access_key, + ) - @classmethod - def from_dict(cls, obj: dict) -> S3Credentials: - """Create an instance of S3Credentials from a dict""" - if obj is None: - return None + s3_credentials.additional_properties = d + return s3_credentials - if not isinstance(obj, dict): - return S3Credentials.parse_obj(obj) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - _obj = S3Credentials.parse_obj( - { - "access_key_id": obj.get("accessKeyId"), - "bucket": obj.get("bucket"), - "region": obj.get("region"), - "secret_access_key": obj.get("secretAccessKey"), - } - ) - return _obj + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/models/subscription_config.py b/jellyfish/_openapi_client/models/subscription_config.py index 8c2fe76..4a33621 100644 --- a/jellyfish/_openapi_client/models/subscription_config.py +++ b/jellyfish/_openapi_client/models/subscription_config.py @@ -1,67 +1,62 @@ -# coding: utf-8 +from typing import Any, Dict, List, Type, TypeVar, Union, cast -""" - Python API wrapper for Jellyfish Media Server +from attrs import define as _attrs_define +from attrs import field as _attrs_field - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) +from ..types import UNSET, Unset - Do not edit the class manually. -""" # noqa: E501 +T = TypeVar("T", bound="SubscriptionConfig") -from __future__ import annotations -import pprint -import re # noqa: F401 -import json +@_attrs_define +class SubscriptionConfig: + """Subscription config""" + tracks: Union[Unset, List[str]] = UNSET + """List of tracks that hls endpoint will subscribe for""" + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + """@private""" -from typing import List, Optional -from pydantic import BaseModel, Field, StrictStr, conlist + def to_dict(self) -> Dict[str, Any]: + """@private""" + tracks: Union[Unset, List[str]] = UNSET + if not isinstance(self.tracks, Unset): + tracks = self.tracks + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if tracks is not UNSET: + field_dict["tracks"] = tracks -class SubscriptionConfig(BaseModel): - """ - Subscription config - """ + return field_dict - tracks: Optional[conlist(StrictStr)] = Field( - None, description="List of tracks that hls endpoint will subscribe for" - ) - __properties = ["tracks"] - - class Config: - """Pydantic configuration""" + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + d = src_dict.copy() + tracks = cast(List[str], d.pop("tracks", UNSET)) - allow_population_by_field_name = True - validate_assignment = True + subscription_config = cls( + tracks=tracks, + ) - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.dict(by_alias=True)) + subscription_config.additional_properties = d + return subscription_config - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - return json.dumps(self.to_dict()) + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) - @classmethod - def from_json(cls, json_str: str) -> SubscriptionConfig: - """Create an instance of SubscriptionConfig from a JSON string""" - return cls.from_dict(json.loads(json_str)) + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] - def to_dict(self): - """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) - return _dict - - @classmethod - def from_dict(cls, obj: dict) -> SubscriptionConfig: - """Create an instance of SubscriptionConfig from a dict""" - if obj is None: - return None + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value - if not isinstance(obj, dict): - return SubscriptionConfig.parse_obj(obj) + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] - _obj = SubscriptionConfig.parse_obj({"tracks": obj.get("tracks")}) - return _obj + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/jellyfish/_openapi_client/py.typed b/jellyfish/_openapi_client/py.typed index e69de29..1aad327 100644 --- a/jellyfish/_openapi_client/py.typed +++ b/jellyfish/_openapi_client/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561 \ No newline at end of file diff --git a/jellyfish/_openapi_client/rest.py b/jellyfish/_openapi_client/rest.py deleted file mode 100644 index fbd7734..0000000 --- a/jellyfish/_openapi_client/rest.py +++ /dev/null @@ -1,401 +0,0 @@ -# coding: utf-8 - -""" - Python API wrapper for Jellyfish Media Server - - The version of the OpenAPI document: 0.2.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import io -import json -import logging -import re -import ssl - -from urllib.parse import urlencode, quote_plus -import urllib3 - -from jellyfish._openapi_client.exceptions import ( - ApiException, - UnauthorizedException, - ForbiddenException, - NotFoundException, - ServiceException, - ApiValueError, - BadRequestException, -) - - -logger = logging.getLogger(__name__) - - -class RESTResponse(io.IOBase): - def __init__(self, resp): - self.urllib3_response = resp - self.status = resp.status - self.reason = resp.reason - self.data = resp.data - - def getheaders(self): - """Returns a dictionary of the response headers.""" - return self.urllib3_response.headers - - def getheader(self, name, default=None): - """Returns a given response header.""" - return self.urllib3_response.headers.get(name, default) - - -class RESTClientObject(object): - def __init__(self, configuration, pools_size=4, maxsize=None): - # urllib3.PoolManager will pass all kw parameters to connectionpool - # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 - # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 - # maxsize is the number of requests to host that are allowed in parallel # noqa: E501 - # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501 - - # cert_reqs - if configuration.verify_ssl: - cert_reqs = ssl.CERT_REQUIRED - else: - cert_reqs = ssl.CERT_NONE - - addition_pool_args = {} - if configuration.assert_hostname is not None: - addition_pool_args[ - "assert_hostname" - ] = configuration.assert_hostname # noqa: E501 - - if configuration.retries is not None: - addition_pool_args["retries"] = configuration.retries - - if configuration.tls_server_name: - addition_pool_args["server_hostname"] = configuration.tls_server_name - - if configuration.socket_options is not None: - addition_pool_args["socket_options"] = configuration.socket_options - - if maxsize is None: - if configuration.connection_pool_maxsize is not None: - maxsize = configuration.connection_pool_maxsize - else: - maxsize = 4 - - # https pool manager - if configuration.proxy: - self.pool_manager = urllib3.ProxyManager( - num_pools=pools_size, - maxsize=maxsize, - cert_reqs=cert_reqs, - ca_certs=configuration.ssl_ca_cert, - cert_file=configuration.cert_file, - key_file=configuration.key_file, - proxy_url=configuration.proxy, - proxy_headers=configuration.proxy_headers, - **addition_pool_args - ) - else: - self.pool_manager = urllib3.PoolManager( - num_pools=pools_size, - maxsize=maxsize, - cert_reqs=cert_reqs, - ca_certs=configuration.ssl_ca_cert, - cert_file=configuration.cert_file, - key_file=configuration.key_file, - **addition_pool_args - ) - - def request( - self, - method, - url, - query_params=None, - headers=None, - body=None, - post_params=None, - _preload_content=True, - _request_timeout=None, - ): - """Perform requests. - - :param method: http request method - :param url: http request url - :param query_params: query parameters in the url - :param headers: http request headers - :param body: request json body, for `application/json` - :param post_params: request post parameters, - `application/x-www-form-urlencoded` - and `multipart/form-data` - :param _preload_content: if False, the urllib3.HTTPResponse object will - be returned without reading/decoding response - data. Default is True. - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - """ - method = method.upper() - assert method in ["GET", "HEAD", "DELETE", "POST", "PUT", "PATCH", "OPTIONS"] - - if post_params and body: - raise ApiValueError( - "body parameter cannot be used with post_params parameter." - ) - - post_params = post_params or {} - headers = headers or {} - # url already contains the URL query string - # so reset query_params to empty dict - query_params = {} - - timeout = None - if _request_timeout: - if isinstance(_request_timeout, (int, float)): # noqa: E501,F821 - timeout = urllib3.Timeout(total=_request_timeout) - elif isinstance(_request_timeout, tuple) and len(_request_timeout) == 2: - timeout = urllib3.Timeout( - connect=_request_timeout[0], read=_request_timeout[1] - ) - - try: - # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` - if method in ["POST", "PUT", "PATCH", "OPTIONS", "DELETE"]: - # no content type provided or payload is json - if not headers.get("Content-Type") or re.search( - "json", headers["Content-Type"], re.IGNORECASE - ): - request_body = None - if body is not None: - request_body = json.dumps(body) - r = self.pool_manager.request( - method, - url, - body=request_body, - preload_content=_preload_content, - timeout=timeout, - headers=headers, - ) - elif ( - headers["Content-Type"] == "application/x-www-form-urlencoded" - ): # noqa: E501 - r = self.pool_manager.request( - method, - url, - fields=post_params, - encode_multipart=False, - preload_content=_preload_content, - timeout=timeout, - headers=headers, - ) - elif headers["Content-Type"] == "multipart/form-data": - # must del headers['Content-Type'], or the correct - # Content-Type which generated by urllib3 will be - # overwritten. - del headers["Content-Type"] - r = self.pool_manager.request( - method, - url, - fields=post_params, - encode_multipart=True, - preload_content=_preload_content, - timeout=timeout, - headers=headers, - ) - # Pass a `string` parameter directly in the body to support - # other content types than Json when `body` argument is - # provided in serialized form - elif isinstance(body, str) or isinstance(body, bytes): - request_body = body - r = self.pool_manager.request( - method, - url, - body=request_body, - preload_content=_preload_content, - timeout=timeout, - headers=headers, - ) - else: - # Cannot generate the request from given parameters - msg = """Cannot prepare a request message for provided - arguments. Please check that your arguments match - declared content type.""" - raise ApiException(status=0, reason=msg) - # For `GET`, `HEAD` - else: - r = self.pool_manager.request( - method, - url, - fields={}, - preload_content=_preload_content, - timeout=timeout, - headers=headers, - ) - except urllib3.exceptions.SSLError as e: - msg = "{0}\n{1}".format(type(e).__name__, str(e)) - raise ApiException(status=0, reason=msg) - - if _preload_content: - r = RESTResponse(r) - - # log response body - logger.debug("response body: %s", r.data) - - if not 200 <= r.status <= 299: - if r.status == 400: - raise BadRequestException(http_resp=r) - - if r.status == 401: - raise UnauthorizedException(http_resp=r) - - if r.status == 403: - raise ForbiddenException(http_resp=r) - - if r.status == 404: - raise NotFoundException(http_resp=r) - - if 500 <= r.status <= 599: - raise ServiceException(http_resp=r) - - raise ApiException(http_resp=r) - - return r - - def get_request( - self, - url, - headers=None, - query_params=None, - _preload_content=True, - _request_timeout=None, - ): - return self.request( - "GET", - url, - headers=headers, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - query_params=query_params, - ) - - def head_request( - self, - url, - headers=None, - query_params=None, - _preload_content=True, - _request_timeout=None, - ): - return self.request( - "HEAD", - url, - headers=headers, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - query_params=query_params, - ) - - def options_request( - self, - url, - headers=None, - query_params=None, - post_params=None, - body=None, - _preload_content=True, - _request_timeout=None, - ): - return self.request( - "OPTIONS", - url, - headers=headers, - query_params=query_params, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) - - def delete_request( - self, - url, - headers=None, - query_params=None, - body=None, - _preload_content=True, - _request_timeout=None, - ): - return self.request( - "DELETE", - url, - headers=headers, - query_params=query_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) - - def post_request( - self, - url, - headers=None, - query_params=None, - post_params=None, - body=None, - _preload_content=True, - _request_timeout=None, - ): - return self.request( - "POST", - url, - headers=headers, - query_params=query_params, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) - - def put_request( - self, - url, - headers=None, - query_params=None, - post_params=None, - body=None, - _preload_content=True, - _request_timeout=None, - ): - return self.request( - "PUT", - url, - headers=headers, - query_params=query_params, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) - - def patch_request( - self, - url, - headers=None, - query_params=None, - post_params=None, - body=None, - _preload_content=True, - _request_timeout=None, - ): - return self.request( - "PATCH", - url, - headers=headers, - query_params=query_params, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body, - ) diff --git a/jellyfish/_openapi_client/types.py b/jellyfish/_openapi_client/types.py new file mode 100644 index 0000000..15700b8 --- /dev/null +++ b/jellyfish/_openapi_client/types.py @@ -0,0 +1,44 @@ +""" Contains some shared types for properties """ +from http import HTTPStatus +from typing import BinaryIO, Generic, Literal, MutableMapping, Optional, Tuple, TypeVar + +from attrs import define + + +class Unset: + def __bool__(self) -> Literal[False]: + return False + + +UNSET: Unset = Unset() + +FileJsonType = Tuple[Optional[str], BinaryIO, Optional[str]] + + +@define +class File: + """Contains information for file uploads""" + + payload: BinaryIO + file_name: Optional[str] = None + mime_type: Optional[str] = None + + def to_tuple(self) -> FileJsonType: + """Return a tuple representation that httpx will accept for multipart/form-data""" + return self.file_name, self.payload, self.mime_type + + +T = TypeVar("T") + + +@define +class Response(Generic[T]): + """A response from an endpoint""" + + status_code: HTTPStatus + content: bytes + headers: MutableMapping[str, str] + parsed: Optional[T] + + +__all__ = ["File", "Response", "FileJsonType"] diff --git a/jellyfish/_webhook_notifier.py b/jellyfish/_webhook_notifier.py index d4e2d6d..020f959 100644 --- a/jellyfish/_webhook_notifier.py +++ b/jellyfish/_webhook_notifier.py @@ -3,16 +3,18 @@ notification from jellyfish to notification structs. """ -from typing import Any, Dict +from typing import Dict import betterproto -from jellyfish.events import ServerMessage +from jellyfish.events._protos.jellyfish import ServerMessage -def receive_json(json: Dict) -> Any: +def receive_json(json: Dict) -> betterproto.Message: """ Transform received json notification to adequate notification instance. + + The available notifications are listed in `jellyfish.events` module. """ msg = json["notification"] msg = bytes(msg, "utf-8") diff --git a/jellyfish/_ws_notifier.py b/jellyfish/_ws_notifier.py index de46ee9..941c730 100644 --- a/jellyfish/_ws_notifier.py +++ b/jellyfish/_ws_notifier.py @@ -3,21 +3,20 @@ """ import asyncio -from typing import Callable, Any +from typing import Any, Callable import betterproto - from websockets import client from websockets.exceptions import ConnectionClosed -from jellyfish.events import ( +from jellyfish.events import ServerMessageMetricsReport +from jellyfish.events._protos.jellyfish import ( ServerMessage, - ServerMessageAuthRequest, ServerMessageAuthenticated, - ServerMessageSubscribeRequest, + ServerMessageAuthRequest, ServerMessageEventType, + ServerMessageSubscribeRequest, ServerMessageSubscribeResponse, - ServerMessageMetricsReport, ) diff --git a/jellyfish/api/__init__.py b/jellyfish/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/jellyfish/api/_base_api.py b/jellyfish/api/_base_api.py new file mode 100644 index 0000000..9c0369b --- /dev/null +++ b/jellyfish/api/_base_api.py @@ -0,0 +1,26 @@ +from jellyfish._openapi_client.client import AuthenticatedClient +from jellyfish._openapi_client.models import Error +from jellyfish._openapi_client.types import Response +from jellyfish.errors import HTTPError + + +class BaseApi: + def __init__( + self, + server_address: str = "localhost:5002", + server_api_token: str = "development", + secure: bool = False, + ): + protocol = "https" if secure else "http" + + self.client = AuthenticatedClient( + f"{protocol}://{server_address}", token=server_api_token + ) + + def _request(self, method, **kwargs): + response: Response = method.sync_detailed(client=self.client, **kwargs) + + if isinstance(response.parsed, Error): + raise HTTPError.from_response(response) + + return response.parsed diff --git a/jellyfish/_recording_api.py b/jellyfish/api/_recording_api.py similarity index 54% rename from jellyfish/_recording_api.py rename to jellyfish/api/_recording_api.py index b6fbe0d..e765a0b 100644 --- a/jellyfish/_recording_api.py +++ b/jellyfish/api/_recording_api.py @@ -2,10 +2,11 @@ RecordingApi used to manage rooms """ -from jellyfish import _openapi_client as jellyfish_api +from jellyfish._openapi_client.api.recording import delete_recording, get_recordings +from jellyfish.api._base_api import BaseApi -class RecordingApi: +class RecordingApi(BaseApi): """Allows for managing recordings""" def __init__( @@ -19,20 +20,18 @@ def __init__( Set secure to `True` for `https` and `False` for `http` connection (default). """ - protocol = "https" if secure else "http" - self._configuration = jellyfish_api.Configuration( - host=f"{protocol}://{server_address}", access_token=server_api_token + super().__init__( + server_address=server_address, + server_api_token=server_api_token, + secure=secure, ) - self._api_client = jellyfish_api.ApiClient(self._configuration) - self._recording_api = jellyfish_api.RecordingApi(self._api_client) - def get_list(self) -> list: """Returns a list of available recordings""" - return self._recording_api.get_recordings().data + return self._request(get_recordings).data def delete(self, recording_id: str): """Deletes recording with given id""" - return self._recording_api.delete_recording(recording_id) + return self._request(delete_recording, recording_id=recording_id) diff --git a/jellyfish/_room_api.py b/jellyfish/api/_room_api.py similarity index 50% rename from jellyfish/_room_api.py rename to jellyfish/api/_room_api.py index 81691bd..7d6555a 100644 --- a/jellyfish/_room_api.py +++ b/jellyfish/api/_room_api.py @@ -2,26 +2,35 @@ RoomApi used to manage rooms """ -from typing import Union, Literal - -from jellyfish import _openapi_client as jellyfish_api - -from jellyfish._openapi_client import ( - AddPeerRequest, - AddComponentRequest, - PeerOptions, - PeerOptionsWebRTC, - Component, - ComponentOptions, +from typing import Literal, Union + +from jellyfish._openapi_client.api.hls import subscribe_tracks as hls_subscribe_tracks +from jellyfish._openapi_client.api.room import add_component as room_add_component +from jellyfish._openapi_client.api.room import add_peer as room_add_peer +from jellyfish._openapi_client.api.room import create_room as room_create_room +from jellyfish._openapi_client.api.room import delete_component as room_delete_component +from jellyfish._openapi_client.api.room import delete_peer as room_delete_peer +from jellyfish._openapi_client.api.room import delete_room as room_delete_room +from jellyfish._openapi_client.api.room import get_all_rooms as room_get_all_rooms +from jellyfish._openapi_client.api.room import get_room as room_get_room +from jellyfish._openapi_client.models import ( + AddComponentJsonBody, + AddPeerJsonBody, + ComponentHLS, ComponentOptionsHLS, ComponentOptionsRTSP, + ComponentRTSP, + Peer, + PeerOptionsWebRTC, Room, RoomConfig, - Peer, + RoomConfigVideoCodec, + SubscriptionConfig, ) +from jellyfish.api._base_api import BaseApi -class RoomApi: +class RoomApi(BaseApi): """Allows for managing rooms""" def __init__( @@ -34,16 +43,12 @@ def __init__( Create RoomApi instance, providing the jellyfish address and api token. Set secure to `True` for `https` and `False` for `http` connection (default). """ - - protocol = "https" if secure else "http" - self._configuration = jellyfish_api.Configuration( - host=f"{protocol}://{server_address}", access_token=server_api_token + super().__init__( + server_address=server_address, + server_api_token=server_api_token, + secure=secure, ) - self._api_client = jellyfish_api.ApiClient(self._configuration) - self._room_api = jellyfish_api.RoomApi(self._api_client) - self._hls_api = jellyfish_api.HlsApi(self._api_client) - def create_room( self, max_peers: int = None, @@ -57,30 +62,36 @@ def create_room( in which the room has been created and the created `Room` The returned address may be different from the current `RoomApi` instance. - In such case, a new `RoomApi` instance has to be created using the returned address - in order to interact with the room. + In such case, a new `RoomApi` instance has to be created using + the returned address in order to interact with the room. """ + + if video_codec is not None: + video_codec = RoomConfigVideoCodec(video_codec) + else: + video_codec = None + room_config = RoomConfig( - maxPeers=max_peers, videoCodec=video_codec, webhook_url=webhook_url + max_peers=max_peers, video_codec=video_codec, webhook_url=webhook_url ) - resp = self._room_api.create_room(room_config) + resp = self._request(room_create_room, json_body=room_config) return (resp.data.jellyfish_address, resp.data.room) def delete_room(self, room_id: str) -> None: """Deletes a room""" - return self._room_api.delete_room(room_id) + return self._request(room_delete_room, room_id=room_id) def get_all_rooms(self) -> list: """Returns list of all rooms""" - return self._room_api.get_all_rooms().data + return self._request(room_get_all_rooms).data def get_room(self, room_id: str) -> Room: """Returns room with the given id""" - return self._room_api.get_room(room_id).data + return self._request(room_get_room, room_id=room_id).data def add_peer(self, room_id: str, options: PeerOptionsWebRTC) -> (str, Peer): """ @@ -88,25 +99,24 @@ def add_peer(self, room_id: str, options: PeerOptionsWebRTC) -> (str, Peer): Currently only `webrtc` peer is supported - Returns a tuple (`peer_token`, `Peer`) - the token needed by Peer to authenticate - to Jellyfish and the new `Peer` + Returns a tuple (`peer_token`, `Peer`) - the token needed by Peer + to authenticate to Jellyfish and the new `Peer` """ peer_type = "webrtc" - options = PeerOptions(options) - request = AddPeerRequest(type=peer_type, options=options) + json_body = AddPeerJsonBody(type=peer_type, options=options) - resp = self._room_api.add_peer(room_id, request) + resp = self._request(room_add_peer, room_id=room_id, json_body=json_body) return (resp.data.token, resp.data.peer) def delete_peer(self, room_id: str, peer_id: str) -> None: """Deletes peer""" - return self._room_api.delete_peer(room_id, peer_id) + return self._request(room_delete_peer, id=peer_id, room_id=room_id) def add_component( self, room_id: str, options: Union[ComponentOptionsHLS, ComponentOptionsRTSP] - ) -> Component: + ) -> Union[ComponentHLS, ComponentRTSP]: """Creates component in the room""" if isinstance(options, ComponentOptionsHLS): @@ -118,17 +128,22 @@ def add_component( "options must be either ComponentOptionsHLS or ComponentOptionsRTSP" ) - options = ComponentOptions(options) - request = AddComponentRequest(type=component_type, options=options) + json_body = AddComponentJsonBody(type=component_type, options=options) - return self._room_api.add_component(room_id, request).data + return self._request( + room_add_component, room_id=room_id, json_body=json_body + ).data def delete_component(self, room_id: str, component_id: str) -> None: """Deletes component""" - return self._room_api.delete_component(room_id, component_id) + return self._request(room_delete_component, id=component_id, room_id=room_id) def hls_subscribe(self, room_id: str, tracks: list): """subscribes hls component for tracks""" - return self._hls_api.subscribe_tracks(room_id, {"tracks": tracks}) + subscription_config = SubscriptionConfig(tracks=tracks) + + return self._request( + hls_subscribe_tracks, room_id=room_id, json_body=subscription_config + ) diff --git a/jellyfish/errors.py b/jellyfish/errors.py new file mode 100644 index 0000000..7b4c3cc --- /dev/null +++ b/jellyfish/errors.py @@ -0,0 +1,49 @@ +from http import HTTPStatus + +from jellyfish._openapi_client.types import Response + + +class HTTPError(Exception): + """""" + + @staticmethod + def from_response(response: Response): + """@private""" + errors = response.parsed.errors + print("resp errors", errors) + + if response.status_code == HTTPStatus.BAD_REQUEST: + return BadRequestError(errors) + + if response.status_code == HTTPStatus.UNAUTHORIZED: + return UnauthorizedError(errors) + + if response.status_code == HTTPStatus.NOT_FOUND: + return NotFoundError(errors) + + if response.status_code == HTTPStatus.SERVICE_UNAVAILABLE: + return ServiceUnavailableError(errors) + + +class BadRequestError(HTTPError): + def __init__(self, errors): + """@private""" + super().__init__(errors) + + +class UnauthorizedError(HTTPError): + def __init__(self, errors): + """@private""" + super().__init__(errors) + + +class NotFoundError(HTTPError): + def __init__(self, errors): + """@private""" + super().__init__(errors) + + +class ServiceUnavailableError(HTTPError): + def __init__(self, errors): + """@private""" + super().__init__(errors) diff --git a/jellyfish/events/__init__.py b/jellyfish/events/__init__.py index 05e4b01..f7b8606 100644 --- a/jellyfish/events/__init__.py +++ b/jellyfish/events/__init__.py @@ -2,27 +2,17 @@ Server events being sent Jellyfish """ -# Private messages -from jellyfish.events._protos.jellyfish import ( - ServerMessage, - ServerMessageAuthenticated, - ServerMessageAuthRequest, - ServerMessageEventType, - ServerMessageSubscribeResponse, - ServerMessageSubscribeRequest, -) - # Exported messages from jellyfish.events._protos.jellyfish import ( ServerMessageComponentCrashed, ServerMessageHlsPlayable, ServerMessageMetricsReport, - ServerMessagePeerCrashed, ServerMessagePeerConnected, + ServerMessagePeerCrashed, ServerMessagePeerDisconnected, ServerMessageRoomCrashed, - ServerMessageRoomDeleted, ServerMessageRoomCreated, + ServerMessageRoomDeleted, ) __all__ = [ diff --git a/jellyfish/events/_protos/jellyfish/__init__.py b/jellyfish/events/_protos/jellyfish/__init__.py index 7891f60..60b5403 100644 --- a/jellyfish/events/_protos/jellyfish/__init__.py +++ b/jellyfish/events/_protos/jellyfish/__init__.py @@ -55,6 +55,12 @@ class ServerMessage(betterproto.Message): hls_playable: "ServerMessageHlsPlayable" = betterproto.message_field( 13, group="content" ) + hls_uploaded: "ServerMessageHlsUploaded" = betterproto.message_field( + 14, group="content" + ) + hls_upload_crashed: "ServerMessageHlsUploadCrashed" = betterproto.message_field( + 15, group="content" + ) @dataclass(eq=False, repr=False) @@ -125,3 +131,13 @@ class ServerMessageMetricsReport(betterproto.Message): class ServerMessageHlsPlayable(betterproto.Message): room_id: str = betterproto.string_field(1) component_id: str = betterproto.string_field(2) + + +@dataclass(eq=False, repr=False) +class ServerMessageHlsUploaded(betterproto.Message): + room_id: str = betterproto.string_field(1) + + +@dataclass(eq=False, repr=False) +class ServerMessageHlsUploadCrashed(betterproto.Message): + room_id: str = betterproto.string_field(1) diff --git a/openapi-python-client-config.yaml b/openapi-python-client-config.yaml new file mode 100644 index 0000000..04b91da --- /dev/null +++ b/openapi-python-client-config.yaml @@ -0,0 +1,2 @@ +project_name_override: jellyfish +package_name_override: _openapi_client diff --git a/openapi_templates/model.py.jinja b/openapi_templates/model.py.jinja new file mode 100644 index 0000000..e6e7c71 --- /dev/null +++ b/openapi_templates/model.py.jinja @@ -0,0 +1,207 @@ +from typing import Any, Dict, Type, TypeVar, Tuple, Optional, BinaryIO, TextIO, TYPE_CHECKING + +{% if model.additional_properties %} +from typing import List + +{% endif %} + +from attrs import define as _attrs_define +from attrs import field as _attrs_field +{% if model.is_multipart_body %} +import json +{% endif %} + +from ..types import UNSET, Unset + +{% for relative in model.relative_imports %} +{{ relative }} +{% endfor %} + +{% for lazy_import in model.lazy_imports %} +{% if loop.first %} +if TYPE_CHECKING: +{% endif %} + {{ lazy_import }} +{% endfor %} + + +{% if model.additional_properties %} +{% set additional_property_type = 'Any' if model.additional_properties == True else model.additional_properties.get_type_string(quoted=not model.additional_properties.is_base_type) %} +{% endif %} + +{% set class_name = model.class_info.name %} +{% set module_name = model.class_info.module_name %} + +{% from "helpers.jinja" import safe_docstring %} + +T = TypeVar("T", bound="{{ class_name }}") + +{% macro class_docstring_content(model) %} + {% if model.title %}{{ model.title | wordwrap(116) }} + + {% endif -%} + {%- if model.description %}{{ model.description | wordwrap(116) }} + + {% endif %} + {% if not model.title and not model.description %} + {# Leave extra space so that a section doesn't start on the first line #} + + {% endif %} + {% if model.example %} + Example: + {{ model.example | string | wordwrap(112) | indent(12) }} + + {% endif %} +{% endmacro %} + +@_attrs_define +class {{ class_name }}: + {{ safe_docstring(class_docstring_content(model)) | indent(4) }} + + {% for property in model.required_properties + model.optional_properties %} + {% if property.default is none and property.required %} + {{ property.to_string() }} + """{{ property.description }}""" + {% endif %} + {% endfor %} + {% for property in model.required_properties + model.optional_properties %} + {% if property.default is not none or not property.required %} + {{ property.to_string() }} + """{{ property.description }}""" + {% endif %} + {% endfor %} + {% if model.additional_properties %} + additional_properties: Dict[str, {{ additional_property_type }}] = _attrs_field(init=False, factory=dict) + """@private""" + {% endif %} + +{% macro _to_dict(multipart=False) %} +{% for property in model.required_properties + model.optional_properties %} +{% import "property_templates/" + property.template as prop_template %} +{% if prop_template.transform %} +{{ prop_template.transform(property, "self." + property.python_name, property.python_name, multipart=multipart) }} +{% elif multipart %} +{{ property.python_name }} = self.{{ property.python_name }} if isinstance(self.{{ property.python_name }}, Unset) else (None, str(self.{{ property.python_name }}).encode(), "text/plain") +{% else %} +{{ property.python_name }} = self.{{ property.python_name }} +{% endif %} +{% endfor %} + +field_dict: Dict[str, Any] = {} +{% if model.additional_properties %} +{% if model.additional_properties.template %}{# Can be a bool instead of an object #} + {% import "property_templates/" + model.additional_properties.template as prop_template %} +{% else %} + {% set prop_template = None %} +{% endif %} +{% if prop_template and prop_template.transform %} +for prop_name, prop in self.additional_properties.items(): + {{ prop_template.transform(model.additional_properties, "prop", "field_dict[prop_name]", multipart=multipart, declare_type=false) | indent(4) }} +{% elif multipart %} +field_dict.update({ + key: (None, str(value).encode(), "text/plain") + for key, value in self.additional_properties.items() +}) +{% else %} +field_dict.update(self.additional_properties) +{% endif %} +{% endif %} +field_dict.update({ + {% for property in model.required_properties + model.optional_properties %} + {% if property.required %} + "{{ property.name }}": {{ property.python_name }}, + {% endif %} + {% endfor %} +}) +{% for property in model.optional_properties %} +{% if not property.required %} +if {{ property.python_name }} is not UNSET: + field_dict["{{ property.name }}"] = {{ property.python_name }} +{% endif %} +{% endfor %} + +return field_dict +{% endmacro %} + + def to_dict(self) -> Dict[str, Any]: + """@private""" + {% for lazy_import in model.lazy_imports %} + {{ lazy_import }} + {% endfor %} + {{ _to_dict() | indent(8) }} + +{% if model.is_multipart_body %} + def to_multipart(self) -> Dict[str, Any]: + {{ _to_dict(multipart=True) | indent(8) }} +{% endif %} + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + """@private""" + {% for lazy_import in model.lazy_imports %} + {{ lazy_import }} + {% endfor %} + d = src_dict.copy() +{% for property in model.required_properties + model.optional_properties %} + {% if property.required %} + {% set property_source = 'd.pop("' + property.name + '")' %} + {% else %} + {% set property_source = 'd.pop("' + property.name + '", UNSET)' %} + {% endif %} + {% import "property_templates/" + property.template as prop_template %} + {% if prop_template.construct %} + {{ prop_template.construct(property, property_source) | indent(8) }} + {% else %} + {{ property.python_name }} = {{ property_source }} + {% endif %} + +{% endfor %} + {{ module_name }} = cls( +{% for property in model.required_properties + model.optional_properties %} + {{ property.python_name }}={{ property.python_name }}, +{% endfor %} + ) + +{% if model.additional_properties %} + {% if model.additional_properties.template %}{# Can be a bool instead of an object #} + {% import "property_templates/" + model.additional_properties.template as prop_template %} + +{% if model.additional_properties.lazy_imports %} + {% for lazy_import in model.additional_properties.lazy_imports %} + {{ lazy_import }} + {% endfor %} +{% endif %} + {% else %} + {% set prop_template = None %} + {% endif %} + {% if prop_template and prop_template.construct %} + additional_properties = {} + for prop_name, prop_dict in d.items(): + {{ prop_template.construct(model.additional_properties, "prop_dict") | indent(12) }} + additional_properties[prop_name] = {{ model.additional_properties.python_name }} + + {{ module_name }}.additional_properties = additional_properties + {% else %} + {{ module_name }}.additional_properties = d + {% endif %} +{% endif %} + return {{ module_name }} + + {% if model.additional_properties %} + @property + def additional_keys(self) -> List[str]: + """@private""" + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> {{ additional_property_type }}: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: {{ additional_property_type }}) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties + {% endif %} diff --git a/openapi_templates/str_enum.py.jinja b/openapi_templates/str_enum.py.jinja new file mode 100644 index 0000000..87581e9 --- /dev/null +++ b/openapi_templates/str_enum.py.jinja @@ -0,0 +1,10 @@ +from enum import Enum + +class {{ enum.class_info.name }}(str, Enum): + """{{ enum.description }}""" + {% for key, value in enum.values|dictsort(true) %} + {{ key }} = "{{ value }}" + {% endfor %} + + def __str__(self) -> str: + return str(self.value) diff --git a/poetry.lock b/poetry.lock index d8f8dd6..3398e21 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "aenum" @@ -12,6 +12,41 @@ files = [ {file = "aenum-3.1.15.tar.gz", hash = "sha256:8cbd76cd18c4f870ff39b24284d3ea028fbe8731a58df3aa581e434c575b9559"}, ] +[[package]] +name = "annotated-types" +version = "0.6.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, + {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} + +[[package]] +name = "anyio" +version = "4.1.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"}, + {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] + [[package]] name = "astroid" version = "2.15.8" @@ -46,6 +81,24 @@ files = [ six = ">=1.6.1,<2.0" wheel = ">=0.23.0,<1.0" +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + [[package]] name = "betterproto" version = "2.0.0b6" @@ -69,29 +122,33 @@ compiler = ["black (>=19.3b0)", "isort (>=5.11.5,<6.0.0)", "jinja2 (>=3.0.3)"] [[package]] name = "black" -version = "23.11.0" +version = "23.12.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911"}, - {file = "black-23.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f"}, - {file = "black-23.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394"}, - {file = "black-23.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f"}, - {file = "black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479"}, - {file = "black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244"}, - {file = "black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221"}, - {file = "black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5"}, - {file = "black-23.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187"}, - {file = "black-23.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6"}, - {file = "black-23.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b"}, - {file = "black-23.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142"}, - {file = "black-23.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055"}, - {file = "black-23.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4"}, - {file = "black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06"}, - {file = "black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07"}, - {file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"}, - {file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"}, + {file = "black-23.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:67f19562d367468ab59bd6c36a72b2c84bc2f16b59788690e02bbcb140a77175"}, + {file = "black-23.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bbd75d9f28a7283b7426160ca21c5bd640ca7cd8ef6630b4754b6df9e2da8462"}, + {file = "black-23.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:593596f699ca2dcbbbdfa59fcda7d8ad6604370c10228223cd6cf6ce1ce7ed7e"}, + {file = "black-23.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:12d5f10cce8dc27202e9a252acd1c9a426c83f95496c959406c96b785a92bb7d"}, + {file = "black-23.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e73c5e3d37e5a3513d16b33305713237a234396ae56769b839d7c40759b8a41c"}, + {file = "black-23.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ba09cae1657c4f8a8c9ff6cfd4a6baaf915bb4ef7d03acffe6a2f6585fa1bd01"}, + {file = "black-23.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace64c1a349c162d6da3cef91e3b0e78c4fc596ffde9413efa0525456148873d"}, + {file = "black-23.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:72db37a2266b16d256b3ea88b9affcdd5c41a74db551ec3dd4609a59c17d25bf"}, + {file = "black-23.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fdf6f23c83078a6c8da2442f4d4eeb19c28ac2a6416da7671b72f0295c4a697b"}, + {file = "black-23.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39dda060b9b395a6b7bf9c5db28ac87b3c3f48d4fdff470fa8a94ab8271da47e"}, + {file = "black-23.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7231670266ca5191a76cb838185d9be59cfa4f5dd401b7c1c70b993c58f6b1b5"}, + {file = "black-23.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:193946e634e80bfb3aec41830f5d7431f8dd5b20d11d89be14b84a97c6b8bc75"}, + {file = "black-23.12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bcf91b01ddd91a2fed9a8006d7baa94ccefe7e518556470cf40213bd3d44bbbc"}, + {file = "black-23.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:996650a89fe5892714ea4ea87bc45e41a59a1e01675c42c433a35b490e5aa3f0"}, + {file = "black-23.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdbff34c487239a63d86db0c9385b27cdd68b1bfa4e706aa74bb94a435403672"}, + {file = "black-23.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:97af22278043a6a1272daca10a6f4d36c04dfa77e61cbaaf4482e08f3640e9f0"}, + {file = "black-23.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ead25c273adfad1095a8ad32afdb8304933efba56e3c1d31b0fee4143a1e424a"}, + {file = "black-23.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c71048345bdbced456cddf1622832276d98a710196b842407840ae8055ade6ee"}, + {file = "black-23.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a832b6e00eef2c13b3239d514ea3b7d5cc3eaa03d0474eedcbbda59441ba5d"}, + {file = "black-23.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:6a82a711d13e61840fb11a6dfecc7287f2424f1ca34765e70c909a35ffa7fb95"}, + {file = "black-23.12.0-py3-none-any.whl", hash = "sha256:a7c07db8200b5315dc07e331dda4d889a56f6bf4db6a9c2a526fa3166a81614f"}, + {file = "black-23.12.0.tar.gz", hash = "sha256:330a327b422aca0634ecd115985c1c7fd7bdb5b5a2ef8aa9888a82e2ebe9437a"}, ] [package.dependencies] @@ -105,7 +162,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -122,13 +179,13 @@ files = [ [[package]] name = "certifi" -version = "2023.7.22" +version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, ] [[package]] @@ -271,13 +328,13 @@ graph = ["objgraph (>=1.7.2)"] [[package]] name = "exceptiongroup" -version = "1.1.3" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] @@ -340,6 +397,17 @@ multidict = "*" [package.extras] protobuf = ["protobuf (>=3.20.0)"] +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + [[package]] name = "h2" version = "4.1.0" @@ -366,6 +434,51 @@ files = [ {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, ] +[[package]] +name = "httpcore" +version = "1.0.2" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"}, + {file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.23.0)"] + +[[package]] +name = "httpx" +version = "0.25.2" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118"}, + {file = "httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + [[package]] name = "hyperframe" version = "6.0.1" @@ -379,31 +492,31 @@ files = [ [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] [[package]] name = "importlib-metadata" -version = "6.8.0" +version = "7.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, - {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] @@ -438,21 +551,15 @@ files = [ [[package]] name = "isort" -version = "5.12.0" +version = "5.13.1" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, + {file = "isort-5.13.1-py3-none-any.whl", hash = "sha256:56a51732c25f94ca96f6721be206dd96a95f42950502eb26c1015d333bc6edb7"}, + {file = "isort-5.13.1.tar.gz", hash = "sha256:aaed790b463e8703fb1eddb831dfa8e8616bacde2c083bd557ef73c8189b7263"}, ] -[package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] - [[package]] name = "itsdangerous" version = "2.1.2" @@ -784,6 +891,30 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "openapi-python-client" +version = "0.16.0" +description = "Generate modern Python clients from OpenAPI" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "openapi_python_client-0.16.0-py3-none-any.whl", hash = "sha256:2250a718703f99d6e55ff1b6b0bb7bb37f8d6424343d0f86a03d420869860578"}, + {file = "openapi_python_client-0.16.0.tar.gz", hash = "sha256:c1b76d97d1276462445cded66b8e0c9095fa11002f695e5dcc212b45b8bfee9c"}, +] + +[package.dependencies] +attrs = ">=21.3.0" +colorama = {version = ">=0.4.3,<0.5.0", markers = "sys_platform == \"win32\""} +httpx = ">=0.20.0,<0.26.0" +jinja2 = ">=3.0.0,<4.0.0" +pydantic = ">=2.1.1,<3.0.0" +python-dateutil = ">=2.8.1,<3.0.0" +PyYAML = ">=6.0,<7.0" +ruff = ">=0.1.2,<0.2.0" +shellingham = ">=1.3.2,<2.0.0" +typer = ">0.6,<0.10" +typing-extensions = ">=4.8.0,<5.0.0" + [[package]] name = "packaging" version = "23.2" @@ -797,13 +928,13 @@ files = [ [[package]] name = "pathspec" -version = "0.11.2" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] @@ -828,13 +959,13 @@ dev = ["black", "hypothesis", "mypy", "pygments (>=2.14.0)", "pytest", "pytest-c [[package]] name = "platformdirs" -version = "4.0.0" +version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"}, - {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"}, + {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, + {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, ] [package.extras] @@ -858,69 +989,154 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pydantic" -version = "1.10.13" -description = "Data validation and settings management using python type hints" +version = "2.5.2" +description = "Data validation using Python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"}, - {file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"}, - {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"}, - {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"}, - {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"}, - {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"}, - {file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"}, - {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, - {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, - {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, - {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, - {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, - {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, - {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, - {file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"}, - {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"}, - {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"}, - {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"}, - {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"}, - {file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"}, - {file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"}, - {file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"}, - {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"}, - {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"}, - {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"}, - {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"}, - {file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"}, - {file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"}, - {file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"}, - {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"}, - {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"}, - {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"}, - {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"}, - {file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"}, - {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, - {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, + {file = "pydantic-2.5.2-py3-none-any.whl", hash = "sha256:80c50fb8e3dcecfddae1adbcc00ec5822918490c99ab31f6cf6140ca1c1429f0"}, + {file = "pydantic-2.5.2.tar.gz", hash = "sha256:ff177ba64c6faf73d7afa2e8cad38fd456c0dbe01c9954e71038001cd15a6edd"}, ] [package.dependencies] -typing-extensions = ">=4.2.0" +annotated-types = ">=0.4.0" +pydantic-core = "2.14.5" +typing-extensions = ">=4.6.1" [package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.14.5" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.14.5-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:7e88f5696153dc516ba6e79f82cc4747e87027205f0e02390c21f7cb3bd8abfd"}, + {file = "pydantic_core-2.14.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4641e8ad4efb697f38a9b64ca0523b557c7931c5f84e0fd377a9a3b05121f0de"}, + {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:774de879d212db5ce02dfbf5b0da9a0ea386aeba12b0b95674a4ce0593df3d07"}, + {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ebb4e035e28f49b6f1a7032920bb9a0c064aedbbabe52c543343d39341a5b2a3"}, + {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b53e9ad053cd064f7e473a5f29b37fc4cc9dc6d35f341e6afc0155ea257fc911"}, + {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aa1768c151cf562a9992462239dfc356b3d1037cc5a3ac829bb7f3bda7cc1f9"}, + {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eac5c82fc632c599f4639a5886f96867ffced74458c7db61bc9a66ccb8ee3113"}, + {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2ae91f50ccc5810b2f1b6b858257c9ad2e08da70bf890dee02de1775a387c66"}, + {file = "pydantic_core-2.14.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6b9ff467ffbab9110e80e8c8de3bcfce8e8b0fd5661ac44a09ae5901668ba997"}, + {file = "pydantic_core-2.14.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:61ea96a78378e3bd5a0be99b0e5ed00057b71f66115f5404d0dae4819f495093"}, + {file = "pydantic_core-2.14.5-cp310-none-win32.whl", hash = "sha256:bb4c2eda937a5e74c38a41b33d8c77220380a388d689bcdb9b187cf6224c9720"}, + {file = "pydantic_core-2.14.5-cp310-none-win_amd64.whl", hash = "sha256:b7851992faf25eac90bfcb7bfd19e1f5ffa00afd57daec8a0042e63c74a4551b"}, + {file = "pydantic_core-2.14.5-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:4e40f2bd0d57dac3feb3a3aed50f17d83436c9e6b09b16af271b6230a2915459"}, + {file = "pydantic_core-2.14.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab1cdb0f14dc161ebc268c09db04d2c9e6f70027f3b42446fa11c153521c0e88"}, + {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aae7ea3a1c5bb40c93cad361b3e869b180ac174656120c42b9fadebf685d121b"}, + {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:60b7607753ba62cf0739177913b858140f11b8af72f22860c28eabb2f0a61937"}, + {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2248485b0322c75aee7565d95ad0e16f1c67403a470d02f94da7344184be770f"}, + {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:823fcc638f67035137a5cd3f1584a4542d35a951c3cc68c6ead1df7dac825c26"}, + {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96581cfefa9123accc465a5fd0cc833ac4d75d55cc30b633b402e00e7ced00a6"}, + {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a33324437018bf6ba1bb0f921788788641439e0ed654b233285b9c69704c27b4"}, + {file = "pydantic_core-2.14.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9bd18fee0923ca10f9a3ff67d4851c9d3e22b7bc63d1eddc12f439f436f2aada"}, + {file = "pydantic_core-2.14.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:853a2295c00f1d4429db4c0fb9475958543ee80cfd310814b5c0ef502de24dda"}, + {file = "pydantic_core-2.14.5-cp311-none-win32.whl", hash = "sha256:cb774298da62aea5c80a89bd58c40205ab4c2abf4834453b5de207d59d2e1651"}, + {file = "pydantic_core-2.14.5-cp311-none-win_amd64.whl", hash = "sha256:e87fc540c6cac7f29ede02e0f989d4233f88ad439c5cdee56f693cc9c1c78077"}, + {file = "pydantic_core-2.14.5-cp311-none-win_arm64.whl", hash = "sha256:57d52fa717ff445cb0a5ab5237db502e6be50809b43a596fb569630c665abddf"}, + {file = "pydantic_core-2.14.5-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:e60f112ac88db9261ad3a52032ea46388378034f3279c643499edb982536a093"}, + {file = "pydantic_core-2.14.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6e227c40c02fd873c2a73a98c1280c10315cbebe26734c196ef4514776120aeb"}, + {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0cbc7fff06a90bbd875cc201f94ef0ee3929dfbd5c55a06674b60857b8b85ed"}, + {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:103ef8d5b58596a731b690112819501ba1db7a36f4ee99f7892c40da02c3e189"}, + {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c949f04ecad823f81b1ba94e7d189d9dfb81edbb94ed3f8acfce41e682e48cef"}, + {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1452a1acdf914d194159439eb21e56b89aa903f2e1c65c60b9d874f9b950e5d"}, + {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb4679d4c2b089e5ef89756bc73e1926745e995d76e11925e3e96a76d5fa51fc"}, + {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf9d3fe53b1ee360e2421be95e62ca9b3296bf3f2fb2d3b83ca49ad3f925835e"}, + {file = "pydantic_core-2.14.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:70f4b4851dbb500129681d04cc955be2a90b2248d69273a787dda120d5cf1f69"}, + {file = "pydantic_core-2.14.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:59986de5710ad9613ff61dd9b02bdd2f615f1a7052304b79cc8fa2eb4e336d2d"}, + {file = "pydantic_core-2.14.5-cp312-none-win32.whl", hash = "sha256:699156034181e2ce106c89ddb4b6504c30db8caa86e0c30de47b3e0654543260"}, + {file = "pydantic_core-2.14.5-cp312-none-win_amd64.whl", hash = "sha256:5baab5455c7a538ac7e8bf1feec4278a66436197592a9bed538160a2e7d11e36"}, + {file = "pydantic_core-2.14.5-cp312-none-win_arm64.whl", hash = "sha256:e47e9a08bcc04d20975b6434cc50bf82665fbc751bcce739d04a3120428f3e27"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:af36f36538418f3806048f3b242a1777e2540ff9efaa667c27da63d2749dbce0"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:45e95333b8418ded64745f14574aa9bfc212cb4fbeed7a687b0c6e53b5e188cd"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e47a76848f92529879ecfc417ff88a2806438f57be4a6a8bf2961e8f9ca9ec7"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d81e6987b27bc7d101c8597e1cd2bcaa2fee5e8e0f356735c7ed34368c471550"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34708cc82c330e303f4ce87758828ef6e457681b58ce0e921b6e97937dd1e2a3"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c1988019752138b974c28f43751528116bcceadad85f33a258869e641d753"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e4d090e73e0725b2904fdbdd8d73b8802ddd691ef9254577b708d413bf3006e"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5c7d5b5005f177764e96bd584d7bf28d6e26e96f2a541fdddb934c486e36fd59"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a71891847f0a73b1b9eb86d089baee301477abef45f7eaf303495cd1473613e4"}, + {file = "pydantic_core-2.14.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a717aef6971208f0851a2420b075338e33083111d92041157bbe0e2713b37325"}, + {file = "pydantic_core-2.14.5-cp37-none-win32.whl", hash = "sha256:de790a3b5aa2124b8b78ae5faa033937a72da8efe74b9231698b5a1dd9be3405"}, + {file = "pydantic_core-2.14.5-cp37-none-win_amd64.whl", hash = "sha256:6c327e9cd849b564b234da821236e6bcbe4f359a42ee05050dc79d8ed2a91588"}, + {file = "pydantic_core-2.14.5-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:ef98ca7d5995a82f43ec0ab39c4caf6a9b994cb0b53648ff61716370eadc43cf"}, + {file = "pydantic_core-2.14.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6eae413494a1c3f89055da7a5515f32e05ebc1a234c27674a6956755fb2236f"}, + {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcf4e6d85614f7a4956c2de5a56531f44efb973d2fe4a444d7251df5d5c4dcfd"}, + {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6637560562134b0e17de333d18e69e312e0458ee4455bdad12c37100b7cad706"}, + {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77fa384d8e118b3077cccfcaf91bf83c31fe4dc850b5e6ee3dc14dc3d61bdba1"}, + {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16e29bad40bcf97aac682a58861249ca9dcc57c3f6be22f506501833ddb8939c"}, + {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531f4b4252fac6ca476fbe0e6f60f16f5b65d3e6b583bc4d87645e4e5ddde331"}, + {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:074f3d86f081ce61414d2dc44901f4f83617329c6f3ab49d2bc6c96948b2c26b"}, + {file = "pydantic_core-2.14.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c2adbe22ab4babbca99c75c5d07aaf74f43c3195384ec07ccbd2f9e3bddaecec"}, + {file = "pydantic_core-2.14.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0f6116a558fd06d1b7c2902d1c4cf64a5bd49d67c3540e61eccca93f41418124"}, + {file = "pydantic_core-2.14.5-cp38-none-win32.whl", hash = "sha256:fe0a5a1025eb797752136ac8b4fa21aa891e3d74fd340f864ff982d649691867"}, + {file = "pydantic_core-2.14.5-cp38-none-win_amd64.whl", hash = "sha256:079206491c435b60778cf2b0ee5fd645e61ffd6e70c47806c9ed51fc75af078d"}, + {file = "pydantic_core-2.14.5-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:a6a16f4a527aae4f49c875da3cdc9508ac7eef26e7977952608610104244e1b7"}, + {file = "pydantic_core-2.14.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:abf058be9517dc877227ec3223f0300034bd0e9f53aebd63cf4456c8cb1e0863"}, + {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49b08aae5013640a3bfa25a8eebbd95638ec3f4b2eaf6ed82cf0c7047133f03b"}, + {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c2d97e906b4ff36eb464d52a3bc7d720bd6261f64bc4bcdbcd2c557c02081ed2"}, + {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3128e0bbc8c091ec4375a1828d6118bc20404883169ac95ffa8d983b293611e6"}, + {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88e74ab0cdd84ad0614e2750f903bb0d610cc8af2cc17f72c28163acfcf372a4"}, + {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c339dabd8ee15f8259ee0f202679b6324926e5bc9e9a40bf981ce77c038553db"}, + {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3387277f1bf659caf1724e1afe8ee7dbc9952a82d90f858ebb931880216ea955"}, + {file = "pydantic_core-2.14.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ba6b6b3846cfc10fdb4c971980a954e49d447cd215ed5a77ec8190bc93dd7bc5"}, + {file = "pydantic_core-2.14.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca61d858e4107ce5e1330a74724fe757fc7135190eb5ce5c9d0191729f033209"}, + {file = "pydantic_core-2.14.5-cp39-none-win32.whl", hash = "sha256:ec1e72d6412f7126eb7b2e3bfca42b15e6e389e1bc88ea0069d0cc1742f477c6"}, + {file = "pydantic_core-2.14.5-cp39-none-win_amd64.whl", hash = "sha256:c0b97ec434041827935044bbbe52b03d6018c2897349670ff8fe11ed24d1d4ab"}, + {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:79e0a2cdbdc7af3f4aee3210b1172ab53d7ddb6a2d8c24119b5706e622b346d0"}, + {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:678265f7b14e138d9a541ddabbe033012a2953315739f8cfa6d754cc8063e8ca"}, + {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95b15e855ae44f0c6341ceb74df61b606e11f1087e87dcb7482377374aac6abe"}, + {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09b0e985fbaf13e6b06a56d21694d12ebca6ce5414b9211edf6f17738d82b0f8"}, + {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ad873900297bb36e4b6b3f7029d88ff9829ecdc15d5cf20161775ce12306f8a"}, + {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2d0ae0d8670164e10accbeb31d5ad45adb71292032d0fdb9079912907f0085f4"}, + {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d37f8ec982ead9ba0a22a996129594938138a1503237b87318392a48882d50b7"}, + {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:35613015f0ba7e14c29ac6c2483a657ec740e5ac5758d993fdd5870b07a61d8b"}, + {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab4ea451082e684198636565224bbb179575efc1658c48281b2c866bfd4ddf04"}, + {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ce601907e99ea5b4adb807ded3570ea62186b17f88e271569144e8cca4409c7"}, + {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb2ed8b3fe4bf4506d6dab3b93b83bbc22237e230cba03866d561c3577517d18"}, + {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70f947628e074bb2526ba1b151cee10e4c3b9670af4dbb4d73bc8a89445916b5"}, + {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4bc536201426451f06f044dfbf341c09f540b4ebdb9fd8d2c6164d733de5e634"}, + {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4791cf0f8c3104ac668797d8c514afb3431bc3305f5638add0ba1a5a37e0d88"}, + {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:038c9f763e650712b899f983076ce783175397c848da04985658e7628cbe873b"}, + {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:27548e16c79702f1e03f5628589c6057c9ae17c95b4c449de3c66b589ead0520"}, + {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c97bee68898f3f4344eb02fec316db93d9700fb1e6a5b760ffa20d71d9a46ce3"}, + {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9b759b77f5337b4ea024f03abc6464c9f35d9718de01cfe6bae9f2e139c397e"}, + {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:439c9afe34638ace43a49bf72d201e0ffc1a800295bed8420c2a9ca8d5e3dbb3"}, + {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ba39688799094c75ea8a16a6b544eb57b5b0f3328697084f3f2790892510d144"}, + {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ccd4d5702bb90b84df13bd491be8d900b92016c5a455b7e14630ad7449eb03f8"}, + {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:81982d78a45d1e5396819bbb4ece1fadfe5f079335dd28c4ab3427cd95389944"}, + {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:7f8210297b04e53bc3da35db08b7302a6a1f4889c79173af69b72ec9754796b8"}, + {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:8c8a8812fe6f43a3a5b054af6ac2d7b8605c7bcab2804a8a7d68b53f3cd86e00"}, + {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:206ed23aecd67c71daf5c02c3cd19c0501b01ef3cbf7782db9e4e051426b3d0d"}, + {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2027d05c8aebe61d898d4cffd774840a9cb82ed356ba47a90d99ad768f39789"}, + {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40180930807ce806aa71eda5a5a5447abb6b6a3c0b4b3b1b1962651906484d68"}, + {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:615a0a4bff11c45eb3c1996ceed5bdaa2f7b432425253a7c2eed33bb86d80abc"}, + {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5e412d717366e0677ef767eac93566582518fe8be923361a5c204c1a62eaafe"}, + {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:513b07e99c0a267b1d954243845d8a833758a6726a3b5d8948306e3fe14675e3"}, + {file = "pydantic_core-2.14.5.tar.gz", hash = "sha256:6d30226dfc816dd0fdf120cae611dd2215117e4f9b124af8c60ab9093b6e8e71"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pygments" -version = "2.16.1" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] [package.extras] plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" @@ -1113,6 +1329,43 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "ruff" +version = "0.1.7" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7f80496854fdc65b6659c271d2c26e90d4d401e6a4a31908e7e334fab4645aac"}, + {file = "ruff-0.1.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1ea109bdb23c2a4413f397ebd8ac32cb498bee234d4191ae1a310af760e5d287"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0c2de9dd9daf5e07624c24add25c3a490dbf74b0e9bca4145c632457b3b42a"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:69a4bed13bc1d5dabf3902522b5a2aadfebe28226c6269694283c3b0cecb45fd"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de02ca331f2143195a712983a57137c5ec0f10acc4aa81f7c1f86519e52b92a1"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45b38c3f8788a65e6a2cab02e0f7adfa88872696839d9882c13b7e2f35d64c5f"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c64cb67b2025b1ac6d58e5ffca8f7b3f7fd921f35e78198411237e4f0db8e73"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dcc6bb2f4df59cb5b4b40ff14be7d57012179d69c6565c1da0d1f013d29951b"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2bb4bb6bbe921f6b4f5b6fdd8d8468c940731cb9406f274ae8c5ed7a78c478"}, + {file = "ruff-0.1.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:276a89bcb149b3d8c1b11d91aa81898fe698900ed553a08129b38d9d6570e717"}, + {file = "ruff-0.1.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:90c958fe950735041f1c80d21b42184f1072cc3975d05e736e8d66fc377119ea"}, + {file = "ruff-0.1.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6b05e3b123f93bb4146a761b7a7d57af8cb7384ccb2502d29d736eaade0db519"}, + {file = "ruff-0.1.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:290ecab680dce94affebefe0bbca2322a6277e83d4f29234627e0f8f6b4fa9ce"}, + {file = "ruff-0.1.7-py3-none-win32.whl", hash = "sha256:416dfd0bd45d1a2baa3b1b07b1b9758e7d993c256d3e51dc6e03a5e7901c7d80"}, + {file = "ruff-0.1.7-py3-none-win_amd64.whl", hash = "sha256:4af95fd1d3b001fc41325064336db36e3d27d2004cdb6d21fd617d45a172dd96"}, + {file = "ruff-0.1.7-py3-none-win_arm64.whl", hash = "sha256:0683b7bfbb95e6df3c7c04fe9d78f631f8e8ba4868dfc932d43d690698057e2e"}, + {file = "ruff-0.1.7.tar.gz", hash = "sha256:dffd699d07abf54833e5f6cc50b85a6ff043715da8788c4a79bcd4ab4734d306"}, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] + [[package]] name = "six" version = "1.16.0" @@ -1124,6 +1377,17 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + [[package]] name = "tomli" version = "2.0.1" @@ -1137,24 +1401,45 @@ files = [ [[package]] name = "tomlkit" -version = "0.12.2" +version = "0.12.3" description = "Style preserving TOML library" optional = false python-versions = ">=3.7" files = [ - {file = "tomlkit-0.12.2-py3-none-any.whl", hash = "sha256:eeea7ac7563faeab0a1ed8fe12c2e5a51c61f933f2502f7e9db0241a65163ad0"}, - {file = "tomlkit-0.12.2.tar.gz", hash = "sha256:df32fab589a81f0d7dc525a4267b6d7a64ee99619cbd1eeb0fae32c1dd426977"}, + {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, + {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, ] +[[package]] +name = "typer" +version = "0.9.0" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.6" +files = [ + {file = "typer-0.9.0-py3-none-any.whl", hash = "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee"}, + {file = "typer-0.9.0.tar.gz", hash = "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2"}, +] + +[package.dependencies] +click = ">=7.1.1,<9.0.0" +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] +test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] + [[package]] name = "typing-extensions" -version = "4.8.0" +version = "4.9.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, - {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, ] [[package]] @@ -1324,13 +1609,13 @@ watchdog = ["watchdog (>=2.3)"] [[package]] name = "wheel" -version = "0.41.3" +version = "0.42.0" description = "A built-package format for Python" optional = false python-versions = ">=3.7" files = [ - {file = "wheel-0.41.3-py3-none-any.whl", hash = "sha256:488609bc63a29322326e05560731bf7bfea8e48ad646e1f5e40d366607de0942"}, - {file = "wheel-0.41.3.tar.gz", hash = "sha256:4d4987ce51a49370ea65c0bfd2234e8ce80a12780820d9dc462597a6e60d0841"}, + {file = "wheel-0.42.0-py3-none-any.whl", hash = "sha256:177f9c9b0d45c47873b619f5b650346d632cdc35fb5e4d25058e09c9e581433d"}, + {file = "wheel-0.42.0.tar.gz", hash = "sha256:c45be39f7882c9d34243236f2d63cbd58039e360f85d0913425fbd7ceea617a8"}, ] [package.extras] @@ -1433,4 +1718,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "19e4eba5fe6c55f6175f688fbe084c73ad023d646b1a701c5e7f85c7fbd8ec11" +content-hash = "50a2fb308d1136e379d26b0057912c8343c833f74a351b58257be569c0b10a63" diff --git a/test_commands.py b/poetry_scripts.py similarity index 68% rename from test_commands.py rename to poetry_scripts.py index 402ec55..fc48bd3 100644 --- a/test_commands.py +++ b/poetry_scripts.py @@ -1,9 +1,7 @@ import os +import shutil import sys from pathlib import Path -import shutil -import pdoc as p -from pdoc import render def check_exit_code(command): @@ -16,27 +14,28 @@ def run_tests(): check_exit_code("docker rm -f jellyfish") check_exit_code("docker compose -f docker-compose-test.yaml pull") check_exit_code( - "docker compose -f docker-compose-test.yaml up --remove-orphans test --exit-code-from test" + "docker compose -f docker-compose-test.yaml up --remove-orphans test \ + --exit-code-from test" ) check_exit_code("docker compose -f docker-compose-test.yaml down") -def check_format(): - check_exit_code("black --check .") - - def run_formatter(): - check_exit_code("black .") + check_exit_code("ruff format .") def run_linter(): - check_exit_code("poetry run pylint --rcfile=pylintrc jellyfish tests") + check_exit_code("ruff check .") + + +def run_linter_fix(): + check_exit_code("ruff check . --fix") def generate_docs(): check_exit_code( "pdoc \ - --no-include-undocumented \ + --include-undocumented \ --favicon https://logo.swmansion.com/membrane/\?width\=100\&variant\=signetDark\ --logo https://logo.swmansion.com/membrane/\?width\=70\&variant\=signetDark\ -t doc_templates \ @@ -55,3 +54,13 @@ def generate_docs(): # ...and rename the .html files to .md so that mkdocs picks them up! for f in out.glob("**/*.html"): f.rename(f.with_suffix(".md")) + + +def update_client(): + check_exit_code( + "openapi-python-client update\ + --url https://raw.githubusercontent.com/jellyfish-dev/" + "jellyfish/main/openapi.yaml \ + --config openapi-python-client-config.yaml \ + --custom-template-path=openapi_templates" + ) diff --git a/protos b/protos index a6f6971..3781848 160000 --- a/protos +++ b/protos @@ -1 +1 @@ -Subproject commit a6f69712da283d13ae8b6e828694b48fce92a9e5 +Subproject commit 3781848239f67a88866f861fa798a8c18384e666 diff --git a/pylintrc b/pylintrc deleted file mode 100644 index 33374d2..0000000 --- a/pylintrc +++ /dev/null @@ -1,631 +0,0 @@ -[MAIN] - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Clear in-memory caches upon conclusion of linting. Useful if running pylint -# in a server-like mode. -clear-cache-post-run=no - -# Load and enable all available extensions. Use --list-extensions to see a list -# all available extensions. -#enable-all-extensions= - -# In error mode, messages with a category besides ERROR or FATAL are -# suppressed, and no reports are done by default. Error mode is compatible with -# disabling specific errors. -#errors-only= - -# Always return a 0 (non-error) status code, even if lint errors are found. -# This is primarily useful in continuous integration scripts. -#exit-zero= - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code. -extension-pkg-allow-list= - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code. (This is an alternative name to extension-pkg-allow-list -# for backward compatibility.) -extension-pkg-whitelist= - -# Return non-zero exit code if any of these messages/categories are detected, -# even if score is above --fail-under value. Syntax same as enable. Messages -# specified are enabled, while categories only check already-enabled messages. -fail-on= - -# Specify a score threshold under which the program will exit with error. -fail-under=10 - -# Interpret the stdin as a python script, whose filename needs to be passed as -# the module_or_package argument. -#from-stdin= - -# Files or directories to be skipped. They should be base names, not paths. -ignore=CVS - -# Add files or directories matching the regular expressions patterns to the -# ignore-list. The regex matches against paths and can be in Posix or Windows -# format. Because '\\' represents the directory delimiter on Windows systems, -# it can't be used as an escape character. -ignore-paths=jellyfish/_openapi_client/,jellyfish/events/_protos/,tests/support/protos - -# Files or directories matching the regular expression patterns are skipped. -# The regex matches against base names, not paths. The default value ignores -# Emacs file locks -ignore-patterns=^\.# - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis). It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the -# number of processors available to use, and will cap the count on Windows to -# avoid hangs. -jobs=1 - -# Control the amount of potential inferred values when inferring a single -# object. This can help the performance when dealing with large functions or -# complex, nested conditions. -limit-inference-results=100 - -# List of plugins (as comma separated values of python module names) to load, -# usually to register additional checkers. -load-plugins= - -# Pickle collected data for later comparisons. -persistent=yes - -# Minimum Python version to use for version dependent checks. Will default to -# the version used to run pylint. -py-version=3.11 - -# Discover python modules and packages in the file system subtree. -recursive=no - -# Add paths to the list of the source roots. Supports globbing patterns. The -# source root is an absolute path or a path relative to the current working -# directory used to determine a package namespace for modules located under the -# source root. -source-roots= - -# When enabled, pylint would attempt to guess common misconfiguration and emit -# user-friendly hints instead of false-positive error messages. -suggestion-mode=yes - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - -# In verbose mode, extra non-checker-related info will be displayed. -#verbose= - - -[BASIC] - -# Naming style matching correct argument names. -argument-naming-style=snake_case - -# Regular expression matching correct argument names. Overrides argument- -# naming-style. If left empty, argument names will be checked with the set -# naming style. -#argument-rgx= - -# Naming style matching correct attribute names. -attr-naming-style=snake_case - -# Regular expression matching correct attribute names. Overrides attr-naming- -# style. If left empty, attribute names will be checked with the set naming -# style. -#attr-rgx= - -# Bad variable names which should always be refused, separated by a comma. -bad-names=foo, - bar, - baz, - toto, - tutu, - tata - -# Bad variable names regexes, separated by a comma. If names match any regex, -# they will always be refused -bad-names-rgxs= - -# Naming style matching correct class attribute names. -class-attribute-naming-style=any - -# Regular expression matching correct class attribute names. Overrides class- -# attribute-naming-style. If left empty, class attribute names will be checked -# with the set naming style. -#class-attribute-rgx= - -# Naming style matching correct class constant names. -class-const-naming-style=UPPER_CASE - -# Regular expression matching correct class constant names. Overrides class- -# const-naming-style. If left empty, class constant names will be checked with -# the set naming style. -#class-const-rgx= - -# Naming style matching correct class names. -class-naming-style=PascalCase - -# Regular expression matching correct class names. Overrides class-naming- -# style. If left empty, class names will be checked with the set naming style. -#class-rgx= - -# Naming style matching correct constant names. -const-naming-style=UPPER_CASE - -# Regular expression matching correct constant names. Overrides const-naming- -# style. If left empty, constant names will be checked with the set naming -# style. -#const-rgx= - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Naming style matching correct function names. -function-naming-style=snake_case - -# Regular expression matching correct function names. Overrides function- -# naming-style. If left empty, function names will be checked with the set -# naming style. -#function-rgx= - -# Good variable names which should always be accepted, separated by a comma. -good-names=i, - j, - k, - ex, - Run, - _ - -# Good variable names regexes, separated by a comma. If names match any regex, -# they will always be accepted -good-names-rgxs= - -# Include a hint for the correct naming format with invalid-name. -include-naming-hint=no - -# Naming style matching correct inline iteration names. -inlinevar-naming-style=any - -# Regular expression matching correct inline iteration names. Overrides -# inlinevar-naming-style. If left empty, inline iteration names will be checked -# with the set naming style. -#inlinevar-rgx= - -# Naming style matching correct method names. -method-naming-style=snake_case - -# Regular expression matching correct method names. Overrides method-naming- -# style. If left empty, method names will be checked with the set naming style. -#method-rgx= - -# Naming style matching correct module names. -module-naming-style=snake_case - -# Regular expression matching correct module names. Overrides module-naming- -# style. If left empty, module names will be checked with the set naming style. -#module-rgx= - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -# These decorators are taken in consideration only for invalid-name. -property-classes=abc.abstractproperty - -# Regular expression matching correct type alias names. If left empty, type -# alias names will be checked with the set naming style. -#typealias-rgx= - -# Regular expression matching correct type variable names. If left empty, type -# variable names will be checked with the set naming style. -#typevar-rgx= - -# Naming style matching correct variable names. -variable-naming-style=snake_case - -# Regular expression matching correct variable names. Overrides variable- -# naming-style. If left empty, variable names will be checked with the set -# naming style. -#variable-rgx= - - -[CLASSES] - -# Warn about protected attribute access inside special methods -check-protected-access-in-special-methods=no - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__, - __new__, - setUp, - asyncSetUp, - __post_init__ - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[DESIGN] - -# List of regular expressions of class ancestor names to ignore when counting -# public methods (see R0903) -exclude-too-few-public-methods= - -# List of qualified class names to ignore when counting class parents (see -# R0901) -ignored-parents= - -# Maximum number of arguments for function / method. -max-args=5 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Maximum number of boolean expressions in an if statement (see R0916). -max-bool-expr=5 - -# Maximum number of branch for function / method body. -max-branches=12 - -# Maximum number of locals for function / method body. -max-locals=15 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body. -max-returns=6 - -# Maximum number of statements in function / method body. -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when caught. -overgeneral-exceptions=builtins.BaseException,builtins.Exception - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=100 - -# Maximum number of lines in a module. -max-module-lines=1000 - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[IMPORTS] - -# List of modules that can be imported at any level, not just the top level -# one. -allow-any-import-level= - -# Allow explicit reexports by alias from a package __init__. -allow-reexport-from-package=no - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Deprecated modules which should not be used, separated by a comma. -deprecated-modules= - -# Output a graph (.gv or any supported image format) of external dependencies -# to the given file (report RP0402 must not be disabled). -ext-import-graph= - -# Output a graph (.gv or any supported image format) of all (i.e. internal and -# external) dependencies to the given file (report RP0402 must not be -# disabled). -import-graph= - -# Output a graph (.gv or any supported image format) of internal dependencies -# to the given file (report RP0402 must not be disabled). -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - -# Couples of modules and preferred modules, separated by a comma. -preferred-modules= - - -[LOGGING] - -# The type of string formatting that logging methods do. `old` means using % -# formatting, `new` is for `{}` formatting. -logging-format-style=old - -# Logging modules to check that the string format arguments are in logging -# function parameter format. -logging-modules=logging - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, -# UNDEFINED. -confidence=HIGH, - CONTROL_FLOW, - INFERENCE, - INFERENCE_FAILURE, - UNDEFINED - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once). You can also use "--disable=all" to -# disable everything first and then re-enable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use "--disable=all --enable=classes -# --disable=W". -disable=raw-checker-failed, - bad-inline-option, - locally-disabled, - file-ignored, - suppressed-message, - useless-suppression, - deprecated-pragma, - use-symbolic-message-instead - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member - - -[METHOD_ARGS] - -# List of qualified names (i.e., library.method) which require a timeout -# parameter e.g. 'requests.api.get,requests.api.post' -timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME, - XXX, - TODO - -# Regular expression of note tags to take in consideration. -notes-rgx= - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - -# Complete name of functions that never returns. When checking for -# inconsistent-return-statements if a never returning function is called then -# it will be considered as an explicit return statement and no message will be -# printed. -never-returning-functions=sys.exit,argparse.parse_error - - -[REPORTS] - -# Python expression which should return a score less than or equal to 10. You -# have access to the variables 'fatal', 'error', 'warning', 'refactor', -# 'convention', and 'info' which contain the number of messages in each -# category, as well as 'statement' which is the total number of statements -# analyzed. This score is used by the global evaluation report (RP0004). -evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details. -msg-template= - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio). You can also give a reporter class, e.g. -# mypackage.mymodule.MyReporterClass. -#output-format= - -# Tells whether to display a full report or only the messages. -reports=no - -# Activate the evaluation score. -score=yes - - -[SIMILARITIES] - -# Comments are removed from the similarity computation -ignore-comments=yes - -# Docstrings are removed from the similarity computation -ignore-docstrings=yes - -# Imports are removed from the similarity computation -ignore-imports=yes - -# Signatures are removed from the similarity computation -ignore-signatures=yes - -# Minimum lines number of a similarity. -min-similarity-lines=4 - - -[SPELLING] - -# Limits count of emitted suggestions for spelling mistakes. -max-spelling-suggestions=4 - -# Spelling dictionary name. No available dictionaries : You need to install -# both the python package and the system dependency for enchant to work.. -spelling-dict= - -# List of comma separated words that should be considered directives if they -# appear at the beginning of a comment and should not be checked. -spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains the private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to the private dictionary (see the -# --spelling-private-dict-file option) instead of raising a message. -spelling-store-unknown-words=no - - -[STRING] - -# This flag controls whether inconsistent-quotes generates a warning when the -# character used as a quote delimiter is used inconsistently within a module. -check-quote-consistency=no - -# This flag controls whether the implicit-str-concat should generate a warning -# on implicit string concatenation in sequences defined over several lines. -check-str-concat-over-line-jumps=no - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether to warn about missing members when the owner of the attribute -# is inferred to be None. -ignore-none=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of symbolic message names to ignore for Mixin members. -ignored-checks-for-mixins=no-member, - not-async-context-manager, - not-context-manager, - attribute-defined-outside-init - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - -# Regex pattern to define which classes are considered mixins. -mixin-class-rgx=.*[Mm]ixin - -# List of decorators that change the signature of a decorated function. -signature-mutators= - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid defining new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of names allowed to shadow builtins -allowed-redefined-builtins= - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_, - _cb - -# A regular expression matching the name of dummy variables (i.e. expected to -# not be used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io diff --git a/pyproject.toml b/pyproject.toml index 3267f55..14d7eef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "jellyfish-server-sdk" -version = "0.1.0" +version = "0.2.0-dev" description = "Python server SDK for the Jellyfish media server" authors = ["Jellyfish Team"] homepage = "https://github.com/jellyfish-dev/python-server-sdk" @@ -13,18 +13,19 @@ packages = [{ include = "jellyfish" }] python = "^3.8" websockets = "^11.0.3" urllib3 = ">=1.25.3,<2" -pydantic = "<2" aenum = "^3.1.15" python-dateutil = "^2.8.2" betterproto = "2.0.0b6" +httpx = ">=0.20.0,<0.26.0" +attrs = ">=21.3.0" [tool.poetry.group.dev.dependencies] -pylint = "^2.17.6" betterproto = { version = "= 2.0.0b6", extras = ["compiler"] } -black = "^23.10.0" pdoc = "^14.1.0" mkdocs = "^1.5.3" mike = "^2.0.0" +openapi-python-client = "^0.16.0" +ruff = "^0.1.7" [tool.poetry.group.test.dependencies] pytest = "^7.4.2" @@ -37,8 +38,19 @@ requires = ["poetry-core>=1.6.0"] build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] -ci_test = "test_commands:run_tests" -format = "test_commands:run_formatter" -check_format = "test_commands:check_format" -lint = "test_commands:run_linter" -generate_docs = "test_commands:generate_docs" +ci_test = "poetry_scripts:run_tests" +format = "poetry_scripts:run_formatter" +lint = "poetry_scripts:run_linter" +fix_lint = "poetry_scripts:run_linter_fix" +generate_docs = "poetry_scripts:generate_docs" +update_client = "poetry_scripts:update_client" + +[tool.ruff] +select = ["F", "I"] + +[tool.ruff.lint] +select = ["F", "I", "E"] +ignore = [] + +[tool.ruff.extend-per-file-ignores] +"jellyfish/_openapi_client/**" = ["E501"] diff --git a/templates/partial_header.mustache b/templates/partial_header.mustache deleted file mode 100644 index 5857428..0000000 --- a/templates/partial_header.mustache +++ /dev/null @@ -1,17 +0,0 @@ -""" -{{#appName}} -{{/appName}} -{{#appDescription}} - Python API wrapper for Jellyfish Media Server - -{{/appDescription}} - {{#version}} - The version of the OpenAPI document: {{{.}}} - {{/version}} - {{#infoEmail}} - Contact: {{{.}}} - {{/infoEmail}} - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 diff --git a/tests/support/peer_socket.py b/tests/support/peer_socket.py index 14f2f86..768e015 100644 --- a/tests/support/peer_socket.py +++ b/tests/support/peer_socket.py @@ -1,15 +1,15 @@ # pylint: disable=locally-disabled, missing-class-docstring, missing-function-docstring, redefined-outer-name, too-few-public-methods, missing-module-docstring import asyncio -import betterproto +import betterproto from websockets import client from websockets.exceptions import ConnectionClosedOK from tests.support.protos.jellyfish import ( PeerMessage, - PeerMessageAuthRequest, PeerMessageAuthenticated, + PeerMessageAuthRequest, ) diff --git a/tests/support/webhook_notifier.py b/tests/support/webhook_notifier.py index 8c1c078..730f91d 100644 --- a/tests/support/webhook_notifier.py +++ b/tests/support/webhook_notifier.py @@ -1,6 +1,7 @@ # pylint: disable=locally-disabled, missing-class-docstring, missing-function-docstring, redefined-outer-name, too-few-public-methods, missing-module-docstring, global-statement -from flask import Flask, request, Response +from flask import Flask, Response, request + from jellyfish import receive_json app = Flask(__name__) diff --git a/tests/test_notifier.py b/tests/test_notifier.py index 519a207..3b1a8a3 100644 --- a/tests/test_notifier.py +++ b/tests/test_notifier.py @@ -1,28 +1,26 @@ # pylint: disable=locally-disabled, missing-class-docstring, missing-function-docstring, redefined-outer-name, too-few-public-methods, missing-module-docstring -import os import asyncio +import os import socket import time from multiprocessing import Process, Queue -import requests import pytest +import requests -from jellyfish import Notifier, RoomApi, PeerOptionsWebRTC +from jellyfish import Notifier, PeerOptionsWebRTC, RoomApi from jellyfish.events import ( - ServerMessageRoomCreated, - ServerMessageRoomDeleted, + ServerMessageMetricsReport, ServerMessagePeerConnected, ServerMessagePeerDisconnected, - ServerMessageMetricsReport, + ServerMessageRoomCreated, + ServerMessageRoomDeleted, ) - -from tests.support.peer_socket import PeerSocket from tests.support.asyncio_utils import assert_events, assert_metrics, cancel +from tests.support.peer_socket import PeerSocket from tests.support.webhook_notifier import run_server - HOST = "jellyfish" if os.getenv("DOCKER_TEST") == "TRUE" else "localhost" SERVER_ADDRESS = f"{HOST}:5002" SERVER_API_TOKEN = "development" @@ -86,7 +84,11 @@ def room_api(): @pytest.fixture def notifier(): - return Notifier(server_address=SERVER_ADDRESS, server_api_token=SERVER_API_TOKEN) + notifier = Notifier( + server_address=SERVER_ADDRESS, server_api_token=SERVER_API_TOKEN + ) + + return notifier class TestReceivingNotifications: diff --git a/tests/test_recording_api.py b/tests/test_recording_api.py index 30b1fe4..6993b6f 100644 --- a/tests/test_recording_api.py +++ b/tests/test_recording_api.py @@ -5,8 +5,7 @@ import pytest from jellyfish import RecordingApi -from jellyfish import NotFoundException - +from jellyfish.errors import NotFoundError HOST = "jellyfish" if os.getenv("DOCKER_TEST") == "TRUE" else "localhost" SERVER_ADDRESS = f"{HOST}:5002" @@ -28,5 +27,5 @@ def test_valid(self, recording_api: RecordingApi): class TestDelete: def test_invalid_recording(self, recording_api: RecordingApi): - with pytest.raises(NotFoundException): + with pytest.raises(NotFoundError): recording_api.delete("invalid-id") diff --git a/tests/test_room_api.py b/tests/test_room_api.py index 14142d0..773e208 100644 --- a/tests/test_room_api.py +++ b/tests/test_room_api.py @@ -5,14 +5,29 @@ import pytest -from jellyfish import RoomApi, RoomConfig -from jellyfish import Room -from jellyfish import ComponentOptionsRTSP, ComponentOptionsHLS, PeerOptionsWebRTC - -from jellyfish import ValidationError - -from jellyfish import UnauthorizedException, NotFoundException, BadRequestException - +from jellyfish import ( + ComponentHLS, + ComponentOptionsHLS, + ComponentOptionsHLSSubscribeMode, + ComponentOptionsRTSP, + ComponentPropertiesHLS, + ComponentPropertiesHLSSubscribeMode, + ComponentPropertiesRTSP, + ComponentRTSP, + Peer, + PeerOptionsWebRTC, + PeerStatus, + Room, + RoomApi, + RoomConfig, + RoomConfigVideoCodec, +) +from jellyfish.errors import ( + BadRequestError, + NotFoundError, + ServiceUnavailableError, + UnauthorizedError, +) HOST = "jellyfish" if os.getenv("DOCKER_TEST") == "TRUE" else "localhost" SERVER_ADDRESS = f"{HOST}:5002" @@ -20,14 +35,10 @@ MAX_PEERS = 10 CODEC_H264 = "h264" -PEER_WEBRTC = "webrtc" - -COMPONENT_HLS = "hls" -COMPONENT_RTSP = "rtsp" HLS_OPTIONS = ComponentOptionsHLS() RTSP_OPTIONS = ComponentOptionsRTSP( - sourceUri="rtsp://ef36c6dff23ecc5bbe311cc880d95dc8.se:2137/does/not/matter" + source_uri="rtsp://ef36c6dff23ecc5bbe311cc880d95dc8.se:2137/does/not/matter" ) @@ -35,7 +46,7 @@ class TestAuthentication: def test_invalid_token(self): room_api = RoomApi(server_address=SERVER_ADDRESS, server_api_token="invalid") - with pytest.raises(UnauthorizedException): + with pytest.raises(UnauthorizedError): room_api.create_room() def test_valid_token(self): @@ -70,7 +81,7 @@ def test_no_params(self, room_api): assert room == Room( components=[], - config=RoomConfig(max_peers=None, video_codec=None), + config=RoomConfig(max_peers=None, video_codec=None, webhook_url=None), id=room.id, peers=[], ) @@ -78,22 +89,30 @@ def test_no_params(self, room_api): assert room in room_api.get_all_rooms() def test_valid_params(self, room_api): - _, room = room_api.create_room(max_peers=MAX_PEERS, video_codec=CODEC_H264) + _, room = room_api.create_room( + max_peers=MAX_PEERS, video_codec=RoomConfigVideoCodec(CODEC_H264) + ) assert room == Room( components=[], - config=RoomConfig(max_peers=MAX_PEERS, video_codec=CODEC_H264), + config=RoomConfig( + max_peers=MAX_PEERS, + video_codec=RoomConfigVideoCodec(CODEC_H264), + webhook_url=None, + ), id=room.id, peers=[], ) assert room in room_api.get_all_rooms() def test_invalid_max_peers(self, room_api): - with pytest.raises(ValidationError): - room_api.create_room(max_peers="10", video_codec=CODEC_H264) + with pytest.raises(BadRequestError): + room_api.create_room( + max_peers="10", video_codec=CODEC_H264, webhook_url=None + ) def test_invalid_video_codec(self, room_api): - with pytest.raises(ValidationError): + with pytest.raises(ValueError): room_api.create_room(max_peers=MAX_PEERS, video_codec="h420") @@ -105,7 +124,7 @@ def test_valid(self, room_api): assert room not in room_api.get_all_rooms() def test_invalid(self, room_api): - with pytest.raises(NotFoundException): + with pytest.raises(NotFoundError): room_api.delete_room("invalid_id") @@ -126,11 +145,11 @@ def test_valid(self, room_api: RoomApi): components=[], peers=[], id=room.id, - config=RoomConfig(maxPeers=None, videoCodec=None), + config=RoomConfig(max_peers=None, video_codec=None, webhook_url=None), ) == room_api.get_room(room.id) def test_invalid(self, room_api: RoomApi): - with pytest.raises(NotFoundException): + with pytest.raises(NotFoundError): room_api.get_room("invalid_id") @@ -140,16 +159,32 @@ def test_with_options_hls(self, room_api: RoomApi): room_api.add_component(room.id, options=HLS_OPTIONS) - component = room_api.get_room(room.id).components[0].actual_instance + component = room_api.get_room(room.id).components[0] + + properties = ComponentPropertiesHLS( + low_latency=False, + persistent=False, + playable=False, + subscribe_mode=ComponentPropertiesHLSSubscribeMode("auto"), + target_window_duration=None, + ) + properties.additional_properties = {"s3": None} + + component_hls = ComponentHLS(id=component.id, type="hls", properties=properties) - assert component.type == COMPONENT_HLS + assert component == component_hls def test_with_options_rtsp(self, room_api: RoomApi): _, room = room_api.create_room(video_codec=CODEC_H264) room_api.add_component(room.id, options=RTSP_OPTIONS) - component = room_api.get_room(room.id).components[0].actual_instance - assert component.type == COMPONENT_RTSP + component = room_api.get_room(room.id).components[0] + + component_rtsp = ComponentRTSP( + id=component.id, type="rtsp", properties=ComponentPropertiesRTSP() + ) + + assert component == component_rtsp def test_invalid_type(self, room_api: RoomApi): _, room = room_api.create_room(video_codec=CODEC_H264) @@ -161,7 +196,7 @@ def test_invalid_type(self, room_api: RoomApi): class TestDeleteComponent: def test_valid_component(self, room_api: RoomApi): _, room = room_api.create_room(video_codec=CODEC_H264) - component = room_api.add_component(room.id, options=HLS_OPTIONS).actual_instance + component = room_api.add_component(room.id, options=HLS_OPTIONS) room_api.delete_component(room.id, component.id) assert [] == room_api.get_room(room.id).components @@ -169,7 +204,7 @@ def test_valid_component(self, room_api: RoomApi): def test_invalid_component(self, room_api: RoomApi): _, room = room_api.create_room() - with pytest.raises(NotFoundException): + with pytest.raises(NotFoundError): room_api.delete_component(room.id, "invalid_id") @@ -177,21 +212,23 @@ class TestHLSSubscribe: def test_valid_subscription(self, room_api: RoomApi): _, room = room_api.create_room(video_codec=CODEC_H264) _ = room_api.add_component( - room.id, options=ComponentOptionsHLS(subscribe_mode="manual") + room.id, + options=ComponentOptionsHLS( + subscribe_mode=ComponentOptionsHLSSubscribeMode("manual") + ), ) assert room_api.hls_subscribe(room.id, ["track-id"]) is None def test_invalid_subscription(self, room_api: RoomApi): _, room = room_api.create_room(video_codec=CODEC_H264) _ = room_api.add_component(room.id, options=HLS_OPTIONS) - with pytest.raises(BadRequestException): + with pytest.raises(BadRequestError): room_api.hls_subscribe(room.id, ["track-id"]) class TestAddPeer: - def _assert_peer_created(self, room_api, peer, room_id): - assert peer.status == "disconnected" - assert peer.type == PEER_WEBRTC + def _assert_peer_created(self, room_api, webrtc_peer, room_id): + peer = Peer(id=webrtc_peer.id, type="webrtc", status=PeerStatus("disconnected")) room = room_api.get_room(room_id) assert peer in room.peers @@ -200,7 +237,7 @@ def test_with_specified_options(self, room_api: RoomApi): _, room = room_api.create_room() _token, peer = room_api.add_peer( - room.id, options=PeerOptionsWebRTC(enableSimulcast=True) + room.id, options=PeerOptionsWebRTC(enable_simulcast=True) ) self._assert_peer_created(room_api, peer, room.id) @@ -212,12 +249,22 @@ def test_default_options(self, room_api: RoomApi): self._assert_peer_created(room_api, peer, room.id) + def test_peer_limit_reached(self, room_api: RoomApi): + _, room = room_api.create_room(max_peers=1) + + _token, peer = room_api.add_peer(room.id, options=PeerOptionsWebRTC()) + + self._assert_peer_created(room_api, peer, room.id) + + with pytest.raises(ServiceUnavailableError): + room_api.add_peer(room.id, options=PeerOptionsWebRTC()) + class TestDeletePeer: def test_valid(self, room_api: RoomApi): _, room = room_api.create_room() _, peer = room_api.add_peer( - room.id, options=PeerOptionsWebRTC(enableSimulcast=True) + room.id, options=PeerOptionsWebRTC(enable_simulcast=True) ) room_api.delete_peer(room.id, peer.id) @@ -227,5 +274,5 @@ def test_valid(self, room_api: RoomApi): def test_invalid(self, room_api: RoomApi): _, room = room_api.create_room() - with pytest.raises(NotFoundException): + with pytest.raises(NotFoundError): room_api.delete_peer(room.id, peer_id="invalid_peer_id")