diff --git a/.circleci/config.yml b/.circleci/config.yml index f721389..3512303 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,10 +16,13 @@ jobs: - checkout - run: name: Install project dependencies - command: poetry install --no-ansi + command: poetry install --no-ansi --with=dev - run: name: Lint - command: ./pylint.sh + command: poetry run lint + - run: + name: Check code formatting + command: poetry run check_format - persist_to_workspace: root: ~/project paths: @@ -29,7 +32,7 @@ jobs: executor: machine_executor_amd64 steps: - checkout - - run: docker compose -f docker-compose-test.yaml run test + - run: docker compose -f docker-compose-test.yaml up test --exit-code-from test workflows: diff --git a/README.md b/README.md index e750420..999d2d5 100644 --- a/README.md +++ b/README.md @@ -91,16 +91,20 @@ asyncio.run(test_notifier()) ## Testing -You can test the SDK against a local instance of Jellyfish by running +You can test the SDK by running ```console -pytest +poetry run ci_test ``` -Make sure to use the default configuration for Jellyfish - -Alternatively you can test using Docker +## Format&Lint +You can format code by running ```console -docker-compose -f docker-compose-test.yaml run test +poetry run format +``` + +You can check linter by running +``` +poetry run lint ``` ## Copyright and License diff --git a/docker-compose-test.yaml b/docker-compose-test.yaml index 65c13c7..76d8442 100644 --- a/docker-compose-test.yaml +++ b/docker-compose-test.yaml @@ -25,25 +25,17 @@ services: - "5002:5002" - "49999:49999" - "50000-50050:50000-50050/udp" - networks: - - network test: + container_name: test image: cimg/python:3.8 - command: sh -c "cd /app && \ - poetry config virtualenvs.in-project false && \ - poetry install --no-ansi && \ - poetry run pytest -s" + command: sh -c "cd /app && \ poetry config virtualenvs.in-project false && \ poetry install --no-ansi && \ poetry run pytest -s" environment: DOCKER_TEST: "TRUE" + ports: + - "5000:5000" volumes: - .:/app - networks: - - network depends_on: jellyfish: condition: service_healthy - -networks: - network: - driver: bridge diff --git a/jellyfish/__init__.py b/jellyfish/__init__.py index cf0366f..30b31d6 100644 --- a/jellyfish/__init__.py +++ b/jellyfish/__init__.py @@ -8,25 +8,52 @@ # API from jellyfish._room_api import RoomApi -from jellyfish._notifier import Notifier +from jellyfish._ws_notifier import Notifier +from jellyfish._webhook_notifier import receive_json # Models from jellyfish._openapi_client import ( - Room, RoomConfig, Peer, Component, ComponentHLS, ComponentRTSP, ComponentOptions, - ComponentOptionsRTSP, ComponentOptionsHLS, PeerOptionsWebRTC) + Room, + RoomConfig, + Peer, + Component, + ComponentHLS, + ComponentRTSP, + ComponentOptions, + ComponentOptionsRTSP, + ComponentOptionsHLS, + PeerOptionsWebRTC, +) # Server Messages from jellyfish import events # Exceptions from jellyfish._openapi_client.exceptions import ( - UnauthorizedException, NotFoundException, BadRequestException) + UnauthorizedException, + NotFoundException, + BadRequestException, +) __all__ = [ - 'RoomApi', 'Notifier', 'Room', 'Peer', 'Component', 'ComponentHLS', 'ComponentRTSP', - 'ComponentOptionsHLS', 'RoomConfig', 'ComponentOptions', 'ComponentOptionsRTSP', - 'PeerOptionsWebRTC', 'events', 'UnauthorizedException', 'NotFoundException', - 'BadRequestException'] + "RoomApi", + "Notifier", + "receive_json", + "Room", + "Peer", + "Component", + "ComponentHLS", + "ComponentRTSP", + "ComponentOptionsHLS", + "RoomConfig", + "ComponentOptions", + "ComponentOptionsRTSP", + "PeerOptionsWebRTC", + "events", + "UnauthorizedException", + "NotFoundException", + "BadRequestException", +] __docformat__ = "restructuredtext" diff --git a/jellyfish/_openapi_client/__init__.py b/jellyfish/_openapi_client/__init__.py index f60f531..d521219 100644 --- a/jellyfish/_openapi_client/__init__.py +++ b/jellyfish/_openapi_client/__init__.py @@ -33,7 +33,9 @@ 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_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 @@ -44,13 +46,19 @@ 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_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.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 +from jellyfish._openapi_client.models.room_create_details_response import ( + RoomCreateDetailsResponse, +) +from jellyfish._openapi_client.models.room_create_details_response_data import ( + RoomCreateDetailsResponseData, +) from jellyfish._openapi_client.models.room_details_response import RoomDetailsResponse from jellyfish._openapi_client.models.rooms_listing_response import RoomsListingResponse diff --git a/jellyfish/_openapi_client/api/__init__.py b/jellyfish/_openapi_client/api/__init__.py index 2ac59d4..5820a27 100644 --- a/jellyfish/_openapi_client/api/__init__.py +++ b/jellyfish/_openapi_client/api/__init__.py @@ -3,4 +3,3 @@ # import apis into api package from jellyfish._openapi_client.api.default_api import DefaultApi from jellyfish._openapi_client.api.room_api import RoomApi - diff --git a/jellyfish/_openapi_client/api/default_api.py b/jellyfish/_openapi_client/api/default_api.py index da0ec25..772c03e 100644 --- a/jellyfish/_openapi_client/api/default_api.py +++ b/jellyfish/_openapi_client/api/default_api.py @@ -27,7 +27,7 @@ from jellyfish._openapi_client.api_response import ApiResponse from jellyfish._openapi_client.exceptions import ( # noqa: F401 ApiTypeError, - ApiValueError + ApiValueError, ) @@ -44,7 +44,26 @@ def __init__(self, api_client=None): self.api_client = api_client @validate_arguments - def jellyfish_web_hls_controller_index(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 + def jellyfish_web_hls_controller_index( + 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 """Send file # noqa: E501 This method makes a synchronous HTTP request by default. To make an @@ -76,13 +95,36 @@ def jellyfish_web_hls_controller_index(self, room_id : Annotated[StrictStr, Fiel returns the request thread. :rtype: str """ - kwargs['_return_http_data_only'] = True - if '_preload_content' in kwargs: - raise ValueError("Error! Please call the jellyfish_web_hls_controller_index_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data") - return self.jellyfish_web_hls_controller_index_with_http_info(room_id, filename, range, hls_msn, hls_part, hls_skip, **kwargs) # noqa: E501 + kwargs["_return_http_data_only"] = True + if "_preload_content" in kwargs: + raise ValueError( + "Error! Please call the jellyfish_web_hls_controller_index_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" + ) + return self.jellyfish_web_hls_controller_index_with_http_info( + room_id, filename, range, hls_msn, hls_part, hls_skip, **kwargs + ) # noqa: E501 @validate_arguments - def jellyfish_web_hls_controller_index_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 + def jellyfish_web_hls_controller_index_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 """Send file # noqa: E501 This method makes a synchronous HTTP request by default. To make an @@ -106,7 +148,7 @@ def jellyfish_web_hls_controller_index_with_http_info(self, room_id : Annotated[ :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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -131,61 +173,60 @@ def jellyfish_web_hls_controller_index_with_http_info(self, room_id : Annotated[ _params = locals() _all_params = [ - 'room_id', - 'filename', - 'range', - 'hls_msn', - 'hls_part', - 'hls_skip' + "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' + "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(): + for _key, _val in _params["kwargs"].items(): if _key not in _all_params: raise ApiTypeError( "Got an unexpected keyword argument '%s'" " to method jellyfish_web_hls_controller_index" % _key ) _params[_key] = _val - del _params['kwargs'] + 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'] + 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_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_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)) + 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'] + _header_params = dict(_params.get("_headers", {})) + if _params["range"]: + _header_params["range"] = _params["range"] # process the form parameters _form_params = [] @@ -193,19 +234,21 @@ def jellyfish_web_hls_controller_index_with_http_info(self, room_id : Annotated[ # 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 + _header_params["Accept"] = self.api_client.select_header_accept( + ["application/json"] + ) # noqa: E501 # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = { - '200': "str", - '404': "Error", + "200": "str", + "404": "Error", } return self.api_client.call_api( - '/hls/{room_id}/{filename}', 'GET', + "/hls/{room_id}/{filename}", + "GET", _path_params, _query_params, _header_params, @@ -214,9 +257,10 @@ def jellyfish_web_hls_controller_index_with_http_info(self, room_id : Annotated[ 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'), + 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')) + _request_auth=_params.get("_request_auth"), + ) diff --git a/jellyfish/_openapi_client/api/room_api.py b/jellyfish/_openapi_client/api/room_api.py index 021e067..d8ef113 100644 --- a/jellyfish/_openapi_client/api/room_api.py +++ b/jellyfish/_openapi_client/api/room_api.py @@ -23,10 +23,14 @@ 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.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_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 @@ -34,7 +38,7 @@ from jellyfish._openapi_client.api_response import ApiResponse from jellyfish._openapi_client.exceptions import ( # noqa: F401 ApiTypeError, - ApiValueError + ApiValueError, ) @@ -51,7 +55,14 @@ def __init__(self, api_client=None): 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 + 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 @@ -75,13 +86,24 @@ def add_component(self, room_id : Annotated[StrictStr, Field(..., description="R 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 + 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 + 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 @@ -97,7 +119,7 @@ def add_component_with_http_info(self, room_id : Annotated[StrictStr, Field(..., :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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -121,75 +143,74 @@ def add_component_with_http_info(self, room_id : Annotated[StrictStr, Field(..., _params = locals() - _all_params = [ - 'room_id', - 'add_component_request' - ] + _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' + "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(): + 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'] + del _params["kwargs"] _collection_formats = {} # process the path parameters _path_params = {} - if _params['room_id']: - _path_params['room_id'] = _params['room_id'] - + 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', {})) + _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'] + 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 + _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'])) + _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 + _header_params["Content-Type"] = _content_types_list # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = { - '201': "ComponentDetailsResponse", - '400': "Error", - '401': "Error", - '404': "Error", + "201": "ComponentDetailsResponse", + "400": "Error", + "401": "Error", + "404": "Error", } return self.api_client.call_api( - '/room/{room_id}/component', 'POST', + "/room/{room_id}/component", + "POST", _path_params, _query_params, _header_params, @@ -198,15 +219,23 @@ def add_component_with_http_info(self, room_id : Annotated[StrictStr, Field(..., 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'), + 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')) + _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 + 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 @@ -230,13 +259,24 @@ def add_peer(self, room_id : Annotated[StrictStr, Field(..., description="Room i 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 + 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 + 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 @@ -252,7 +292,7 @@ def add_peer_with_http_info(self, room_id : Annotated[StrictStr, Field(..., desc :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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -276,76 +316,75 @@ def add_peer_with_http_info(self, room_id : Annotated[StrictStr, Field(..., desc _params = locals() - _all_params = [ - 'room_id', - 'add_peer_request' - ] + _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' + "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(): + 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'] + del _params["kwargs"] _collection_formats = {} # process the path parameters _path_params = {} - if _params['room_id']: - _path_params['room_id'] = _params['room_id'] - + 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', {})) + _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'] + 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 + _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'])) + _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 + _header_params["Content-Type"] = _content_types_list # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = { - '201': "PeerDetailsResponse", - '400': "Error", - '401': "Error", - '404': "Error", - '503': "Error", + "201": "PeerDetailsResponse", + "400": "Error", + "401": "Error", + "404": "Error", + "503": "Error", } return self.api_client.call_api( - '/room/{room_id}/peer', 'POST', + "/room/{room_id}/peer", + "POST", _path_params, _query_params, _header_params, @@ -354,15 +393,22 @@ def add_peer_with_http_info(self, room_id : Annotated[StrictStr, Field(..., desc 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'), + 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')) + _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 + 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 @@ -384,13 +430,21 @@ def create_room(self, room_config : Annotated[Optional[RoomConfig], Field(descri 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") + 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 + 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 @@ -404,7 +458,7 @@ def create_room_with_http_info(self, room_config : Annotated[Optional[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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -428,30 +482,28 @@ def create_room_with_http_info(self, room_config : Annotated[Optional[RoomConfig _params = locals() - _all_params = [ - 'room_config' - ] + _all_params = ["room_config"] _all_params.extend( [ - 'async_req', - '_return_http_data_only', - '_preload_content', - '_request_timeout', - '_request_auth', - '_content_type', - '_headers' + "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(): + 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'] + del _params["kwargs"] _collection_formats = {} @@ -461,37 +513,40 @@ def create_room_with_http_info(self, room_config : Annotated[Optional[RoomConfig # process the query parameters _query_params = [] # process the header parameters - _header_params = dict(_params.get('_headers', {})) + _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'] + 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 + _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'])) + _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 + _header_params["Content-Type"] = _content_types_list # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = { - '201': "RoomCreateDetailsResponse", - '400': "Error", - '401': "Error", + "201": "RoomCreateDetailsResponse", + "400": "Error", + "401": "Error", } return self.api_client.call_api( - '/room', 'POST', + "/room", + "POST", _path_params, _query_params, _header_params, @@ -500,15 +555,21 @@ def create_room_with_http_info(self, room_config : Annotated[Optional[RoomConfig 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'), + 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')) + _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 + 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 @@ -532,13 +593,20 @@ def delete_component(self, room_id : Annotated[StrictStr, Field(..., description 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") + 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 + 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 @@ -554,7 +622,7 @@ def delete_component_with_http_info(self, room_id : Annotated[StrictStr, Field(. :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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -578,63 +646,61 @@ def delete_component_with_http_info(self, room_id : Annotated[StrictStr, Field(. _params = locals() - _all_params = [ - 'room_id', - 'id' - ] + _all_params = ["room_id", "id"] _all_params.extend( [ - 'async_req', - '_return_http_data_only', - '_preload_content', - '_request_timeout', - '_request_auth', - '_content_type', - '_headers' + "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(): + 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'] + 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'] + 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', {})) + _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 + _header_params["Accept"] = self.api_client.select_header_accept( + ["application/json"] + ) # noqa: E501 # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = {} return self.api_client.call_api( - '/room/{room_id}/component/{id}', 'DELETE', + "/room/{room_id}/component/{id}", + "DELETE", _path_params, _query_params, _header_params, @@ -643,15 +709,21 @@ def delete_component_with_http_info(self, room_id : Annotated[StrictStr, Field(. 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'), + 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')) + _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 + 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 @@ -675,13 +747,20 @@ def delete_peer(self, room_id : Annotated[StrictStr, Field(..., description="Roo 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") + 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 + 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 @@ -697,7 +776,7 @@ def delete_peer_with_http_info(self, room_id : Annotated[StrictStr, Field(..., d :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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -721,63 +800,61 @@ def delete_peer_with_http_info(self, room_id : Annotated[StrictStr, Field(..., d _params = locals() - _all_params = [ - 'room_id', - 'id' - ] + _all_params = ["room_id", "id"] _all_params.extend( [ - 'async_req', - '_return_http_data_only', - '_preload_content', - '_request_timeout', - '_request_auth', - '_content_type', - '_headers' + "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(): + 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'] + 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'] + 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', {})) + _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 + _header_params["Accept"] = self.api_client.select_header_accept( + ["application/json"] + ) # noqa: E501 # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = {} return self.api_client.call_api( - '/room/{room_id}/peer/{id}', 'DELETE', + "/room/{room_id}/peer/{id}", + "DELETE", _path_params, _query_params, _header_params, @@ -786,15 +863,18 @@ def delete_peer_with_http_info(self, room_id : Annotated[StrictStr, Field(..., d 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'), + 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')) + _request_auth=_params.get("_request_auth"), + ) @validate_arguments - def delete_room(self, room_id : Annotated[StrictStr, Field(..., description="Room id")], **kwargs) -> None: # noqa: E501 + 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 @@ -816,13 +896,17 @@ def delete_room(self, room_id : Annotated[StrictStr, Field(..., description="Roo 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") + 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 + 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 @@ -836,7 +920,7 @@ def delete_room_with_http_info(self, room_id : Annotated[StrictStr, Field(..., d :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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -860,59 +944,58 @@ def delete_room_with_http_info(self, room_id : Annotated[StrictStr, Field(..., d _params = locals() - _all_params = [ - 'room_id' - ] + _all_params = ["room_id"] _all_params.extend( [ - 'async_req', - '_return_http_data_only', - '_preload_content', - '_request_timeout', - '_request_auth', - '_content_type', - '_headers' + "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(): + 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'] + del _params["kwargs"] _collection_formats = {} # process the path parameters _path_params = {} - if _params['room_id']: - _path_params['room_id'] = _params['room_id'] - + 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', {})) + _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 + _header_params["Accept"] = self.api_client.select_header_accept( + ["application/json"] + ) # noqa: E501 # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = {} return self.api_client.call_api( - '/room/{room_id}', 'DELETE', + "/room/{room_id}", + "DELETE", _path_params, _query_params, _header_params, @@ -921,12 +1004,13 @@ def delete_room_with_http_info(self, room_id : Annotated[StrictStr, Field(..., d 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'), + 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')) + _request_auth=_params.get("_request_auth"), + ) @validate_arguments def get_all_rooms(self, **kwargs) -> RoomsListingResponse: # noqa: E501 @@ -949,9 +1033,11 @@ def get_all_rooms(self, **kwargs) -> RoomsListingResponse: # noqa: E501 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") + 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 @@ -967,7 +1053,7 @@ def get_all_rooms_with_http_info(self, **kwargs) -> ApiResponse: # noqa: E501 :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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -991,29 +1077,28 @@ def get_all_rooms_with_http_info(self, **kwargs) -> ApiResponse: # noqa: E501 _params = locals() - _all_params = [ - ] + _all_params = [] _all_params.extend( [ - 'async_req', - '_return_http_data_only', - '_preload_content', - '_request_timeout', - '_request_auth', - '_content_type', - '_headers' + "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(): + 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'] + del _params["kwargs"] _collection_formats = {} @@ -1023,26 +1108,28 @@ def get_all_rooms_with_http_info(self, **kwargs) -> ApiResponse: # noqa: E501 # process the query parameters _query_params = [] # process the header parameters - _header_params = dict(_params.get('_headers', {})) + _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 + _header_params["Accept"] = self.api_client.select_header_accept( + ["application/json"] + ) # noqa: E501 # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = { - '200': "RoomsListingResponse", - '401': "Error", + "200": "RoomsListingResponse", + "401": "Error", } return self.api_client.call_api( - '/room', 'GET', + "/room", + "GET", _path_params, _query_params, _header_params, @@ -1051,15 +1138,18 @@ def get_all_rooms_with_http_info(self, **kwargs) -> ApiResponse: # noqa: E501 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'), + 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')) + _request_auth=_params.get("_request_auth"), + ) @validate_arguments - def get_room(self, room_id : Annotated[StrictStr, Field(..., description="Room ID")], **kwargs) -> RoomDetailsResponse: # noqa: E501 + 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 @@ -1081,13 +1171,17 @@ def get_room(self, room_id : Annotated[StrictStr, Field(..., description="Room I 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") + 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 + 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 @@ -1101,7 +1195,7 @@ def get_room_with_http_info(self, room_id : Annotated[StrictStr, Field(..., desc :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 + be set to none and raw_data will store the HTTP response body without reading/decoding. Default is True. :type _preload_content: bool, optional @@ -1125,63 +1219,62 @@ def get_room_with_http_info(self, room_id : Annotated[StrictStr, Field(..., desc _params = locals() - _all_params = [ - 'room_id' - ] + _all_params = ["room_id"] _all_params.extend( [ - 'async_req', - '_return_http_data_only', - '_preload_content', - '_request_timeout', - '_request_auth', - '_content_type', - '_headers' + "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(): + 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'] + del _params["kwargs"] _collection_formats = {} # process the path parameters _path_params = {} - if _params['room_id']: - _path_params['room_id'] = _params['room_id'] - + 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', {})) + _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 + _header_params["Accept"] = self.api_client.select_header_accept( + ["application/json"] + ) # noqa: E501 # authentication setting - _auth_settings = ['authorization'] # noqa: E501 + _auth_settings = ["authorization"] # noqa: E501 _response_types_map = { - '200': "RoomDetailsResponse", - '401': "Error", - '404': "Error", + "200": "RoomDetailsResponse", + "401": "Error", + "404": "Error", } return self.api_client.call_api( - '/room/{room_id}', 'GET', + "/room/{room_id}", + "GET", _path_params, _query_params, _header_params, @@ -1190,9 +1283,10 @@ def get_room_with_http_info(self, room_id : Annotated[StrictStr, Field(..., desc 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'), + 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')) + _request_auth=_params.get("_request_auth"), + ) diff --git a/jellyfish/_openapi_client/api_client.py b/jellyfish/_openapi_client/api_client.py index ef9d380..029df4d 100644 --- a/jellyfish/_openapi_client/api_client.py +++ b/jellyfish/_openapi_client/api_client.py @@ -49,19 +49,25 @@ class ApiClient(object): 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, + "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): + 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() @@ -74,7 +80,7 @@ def __init__(self, configuration=None, header_name=None, header_value=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.user_agent = "OpenAPI-Generator/1.0.0/python" self.client_side_validation = configuration.client_side_validation def __enter__(self): @@ -88,13 +94,13 @@ def close(self): self._pool.close() self._pool.join() self._pool = None - if hasattr(atexit, 'unregister'): + 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. + avoids instantiating unused threadpool for blocking clients. """ if self._pool is None: atexit.register(self.close) @@ -104,16 +110,15 @@ def pool(self): @property def user_agent(self): """User agent for this API client""" - return self.default_headers['User-Agent'] + return self.default_headers["User-Agent"] @user_agent.setter def user_agent(self, value): - self.default_headers['User-Agent'] = 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 @@ -141,50 +146,64 @@ def set_default(cls, default): 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): - + 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 + 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)) + 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) + 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) + "{%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 = 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) + header_params, + query_params, + auth_settings, + resource_path, + method, + body, + request_auth=_request_auth, + ) # body if body: @@ -200,56 +219,60 @@ def __call_api( # 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_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, + method, + url, query_params=query_params, headers=header_params, - post_params=post_params, body=body, + post_params=post_params, + body=body, _preload_content=_preload_content, - _request_timeout=_request_timeout) + _request_timeout=_request_timeout, + ) except ApiException as e: if e.body: - e.body = e.body.decode('utf-8') + e.body = e.body.decode("utf-8") raise e self.last_response = response_data - return_data = None # assuming derialization is not needed + 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 + 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) + 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. @@ -270,11 +293,9 @@ def sanitize_for_serialization(self, obj): elif isinstance(obj, self.PRIMITIVE_TYPES): return obj elif isinstance(obj, list): - return [self.sanitize_for_serialization(sub_obj) - for sub_obj in obj] + 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) + return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() @@ -288,8 +309,9 @@ def sanitize_for_serialization(self, obj): # model definition for request. obj_dict = obj.to_dict() - return {key: self.sanitize_for_serialization(val) - for key, val in obj_dict.items()} + 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. @@ -325,15 +347,13 @@ def __deserialize(self, data, klass): 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("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()} + 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: @@ -352,13 +372,26 @@ def __deserialize(self, data, klass): 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): + 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. @@ -401,80 +434,122 @@ def call_api(self, resource_path, method, 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): + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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`," @@ -491,22 +566,23 @@ def parameters_to_tuples(self, params, collection_formats): new_params = [] if collection_formats is None: collection_formats = {} - for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501 + 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': + 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 = '|' + 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))) + delimiter = "," + new_params.append((k, delimiter.join(str(value) for value in v))) else: new_params.append((k, v)) return new_params @@ -521,7 +597,9 @@ def parameters_to_url_query(self, params, collection_formats): new_params = [] if collection_formats is None: collection_formats = {} - for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501 + 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): @@ -531,19 +609,20 @@ def parameters_to_url_query(self, params, collection_formats): if k in collection_formats: collection_format = collection_formats[k] - if collection_format == 'multi': + 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 = '|' + if collection_format == "ssv": + delimiter = " " + elif collection_format == "tsv": + delimiter = "\t" + elif collection_format == "pipes": + delimiter = "|" else: # csv is the default - delimiter = ',' + delimiter = "," new_params.append( - (k, delimiter.join(quote(str(value)) for value in v))) + (k, delimiter.join(quote(str(value)) for value in v)) + ) else: new_params.append((k, quote(str(v)))) @@ -563,13 +642,14 @@ def files_parameters(self, files=None): continue file_names = v if type(v) is list else [v] for n in file_names: - with open(n, 'rb') as f: + 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])])) + mimetype = ( + mimetypes.guess_type(filename)[0] + or "application/octet-stream" + ) + params.append(tuple([k, tuple([filename, filedata, mimetype])])) return params @@ -583,7 +663,7 @@ def select_header_accept(self, accepts): return for accept in accepts: - if re.search('json', accept, re.IGNORECASE): + if re.search("json", accept, re.IGNORECASE): return accept return accepts[0] @@ -598,14 +678,21 @@ def select_header_content_type(self, content_types): return None for content_type in content_types: - if re.search('json', content_type, re.IGNORECASE): + 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): + 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. @@ -622,21 +709,21 @@ def update_params_for_auth(self, headers, queries, auth_settings, return if request_auth: - self._apply_auth_params(headers, queries, - resource_path, method, body, - 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) + 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): + 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. @@ -647,17 +734,15 @@ def _apply_auth_params(self, headers, queries, 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'])) + 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`' - ) + raise ApiValueError("Authentication token must be in `query` or `header`") def __deserialize_file(self, response): """Deserializes body to file @@ -674,8 +759,9 @@ def __deserialize_file(self, response): content_disposition = response.getheader("Content-Disposition") if content_disposition: - filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', - content_disposition).group(1) + 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: @@ -717,8 +803,7 @@ def __deserialize_date(self, string): return string except ValueError: raise rest.ApiException( - status=0, - reason="Failed to parse `{0}` as date object".format(string) + status=0, reason="Failed to parse `{0}` as date object".format(string) ) def __deserialize_datetime(self, string): @@ -736,10 +821,7 @@ def __deserialize_datetime(self, string): except ValueError: raise rest.ApiException( status=0, - reason=( - "Failed to parse `{0}` as datetime object" - .format(string) - ) + reason=("Failed to parse `{0}` as datetime object".format(string)), ) def __deserialize_model(self, data, klass): diff --git a/jellyfish/_openapi_client/api_response.py b/jellyfish/_openapi_client/api_response.py index d81c2ff..0af0a2d 100644 --- a/jellyfish/_openapi_client/api_response.py +++ b/jellyfish/_openapi_client/api_response.py @@ -4,21 +4,22 @@ 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") + 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): + def __init__(self, status_code=None, headers=None, data=None, raw_data=None): self.status_code = status_code self.headers = headers self.data = data diff --git a/jellyfish/_openapi_client/configuration.py b/jellyfish/_openapi_client/configuration.py index fe2a878..0d45d5c 100644 --- a/jellyfish/_openapi_client/configuration.py +++ b/jellyfish/_openapi_client/configuration.py @@ -20,11 +20,19 @@ from jellyfish._openapi_client.exceptions import ApiValueError JSON_SCHEMA_VALIDATION_KEYWORDS = { - 'multipleOf', 'maximum', 'exclusiveMaximum', - 'minimum', 'exclusiveMinimum', 'maxLength', - 'minLength', 'pattern', 'maxItems', 'minItems' + "multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "maxItems", + "minItems", } + class Configuration(object): """This class contains various settings of the API client. @@ -56,16 +64,21 @@ class Configuration(object): _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 - """ + 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 """ @@ -108,7 +121,7 @@ def __init__(self, host=None, """ 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' + self.logger_format = "%(asctime)s %(levelname)s %(message)s" """Log format """ self.logger_stream_handler = None @@ -160,7 +173,7 @@ def __init__(self, host=None, self.proxy_headers = None """Proxy headers """ - self.safe_chars_for_path_param = '' + self.safe_chars_for_path_param = "" """Safe chars for path_param """ self.retries = None @@ -186,7 +199,7 @@ def __deepcopy__(self, memo): result = cls.__new__(cls) memo[id(self)] = result for k, v in self.__dict__.items(): - if k not in ('logger', 'logger_file_handler'): + 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) @@ -327,7 +340,9 @@ def get_api_key_with_prefix(self, identifier, alias=None): """ 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) + 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: @@ -346,9 +361,9 @@ def get_basic_auth_token(self): password = "" if self.password is not None: password = self.password - return urllib3.util.make_headers( - basic_auth=username + ':' + password - ).get('authorization') + return urllib3.util.make_headers(basic_auth=username + ":" + password).get( + "authorization" + ) def auth_settings(self): """Gets Auth Settings dict for api client. @@ -357,11 +372,11 @@ def auth_settings(self): """ auth = {} if self.access_token is not None: - auth['authorization'] = { - 'type': 'bearer', - 'in': 'header', - 'key': 'Authorization', - 'value': 'Bearer ' + self.access_token + auth["authorization"] = { + "type": "bearer", + "in": "header", + "key": "Authorization", + "value": "Bearer " + self.access_token, } return auth @@ -370,12 +385,13 @@ def to_debug_report(self): :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) + 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 @@ -384,8 +400,8 @@ def get_host_settings(self): """ return [ { - 'url': "", - 'description': "No description provided", + "url": "", + "description": "No description provided", } ] @@ -407,22 +423,22 @@ def get_host_from_settings(self, index, variables=None, servers=None): except IndexError: raise ValueError( "Invalid index {0} when selecting the host settings. " - "Must be less than {1}".format(index, len(servers))) + "Must be less than {1}".format(index, len(servers)) + ) - url = server['url'] + 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']) + 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']: + 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'])) + variable_name, variables[variable_name], variable["enum_values"] + ) + ) url = url.replace("{" + variable_name + "}", used_value) @@ -431,7 +447,9 @@ def get_host_from_settings(self, index, variables=None, servers=None): @property def host(self): """Return generated host.""" - return self.get_host_from_settings(self.server_index, variables=self.server_variables) + return self.get_host_from_settings( + self.server_index, variables=self.server_variables + ) @host.setter def host(self, value): diff --git a/jellyfish/_openapi_client/exceptions.py b/jellyfish/_openapi_client/exceptions.py index 0ff8add..3a6c92c 100644 --- a/jellyfish/_openapi_client/exceptions.py +++ b/jellyfish/_openapi_client/exceptions.py @@ -15,9 +15,8 @@ class OpenApiException(Exception): class ApiTypeError(OpenApiException, TypeError): - def __init__(self, msg, path_to_item=None, valid_classes=None, - key_type=None): - """ Raises an exception for TypeErrors + 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 @@ -98,7 +97,6 @@ def __init__(self, msg, path_to_item=None): class ApiException(OpenApiException): - def __init__(self, status=None, reason=None, http_resp=None): if http_resp: self.status = http_resp.status @@ -113,42 +111,37 @@ def __init__(self, status=None, reason=None, http_resp=None): def __str__(self): """Custom error messages for exception""" - error_message = "({0})\n"\ - "Reason: {1}\n".format(self.status, self.reason) + 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) + 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): +class BadRequestException(ApiException): def __init__(self, status=None, reason=None, http_resp=None): super(BadRequestException, self).__init__(status, reason, http_resp) -class NotFoundException(ApiException): +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) diff --git a/jellyfish/_openapi_client/models/__init__.py b/jellyfish/_openapi_client/models/__init__.py index 4605292..a7774d9 100644 --- a/jellyfish/_openapi_client/models/__init__.py +++ b/jellyfish/_openapi_client/models/__init__.py @@ -15,7 +15,9 @@ 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_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 @@ -26,13 +28,19 @@ 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_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.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 +from jellyfish._openapi_client.models.room_create_details_response import ( + RoomCreateDetailsResponse, +) +from jellyfish._openapi_client.models.room_create_details_response_data import ( + RoomCreateDetailsResponseData, +) from jellyfish._openapi_client.models.room_details_response import RoomDetailsResponse from jellyfish._openapi_client.models.rooms_listing_response import RoomsListingResponse diff --git a/jellyfish/_openapi_client/models/add_component_request.py b/jellyfish/_openapi_client/models/add_component_request.py index 35456c4..50d2544 100644 --- a/jellyfish/_openapi_client/models/add_component_request.py +++ b/jellyfish/_openapi_client/models/add_component_request.py @@ -20,16 +20,19 @@ 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 @@ -48,13 +51,10 @@ def from_json(cls, json_str: str) -> AddComponentRequest: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["options"] = self.options.to_dict() return _dict @classmethod @@ -66,10 +66,12 @@ def from_dict(cls, obj: dict) -> AddComponentRequest: 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") - }) + _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_request.py b/jellyfish/_openapi_client/models/add_peer_request.py index c9e0dac..5e6453d 100644 --- a/jellyfish/_openapi_client/models/add_peer_request.py +++ b/jellyfish/_openapi_client/models/add_peer_request.py @@ -16,20 +16,22 @@ 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 @@ -48,13 +50,10 @@ def from_json(cls, json_str: str) -> AddPeerRequest: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["options"] = self.options.to_dict() return _dict @classmethod @@ -66,10 +65,12 @@ def from_dict(cls, obj: dict) -> AddPeerRequest: 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") - }) + _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 index 82ebcf7..72413b0 100644 --- a/jellyfish/_openapi_client/models/component.py +++ b/jellyfish/_openapi_client/models/component.py @@ -25,10 +25,12 @@ COMPONENT_ONE_OF_SCHEMAS = ["ComponentHLS", "ComponentRTSP"] + class Component(BaseModel): """ Describes component """ + # data type: ComponentHLS oneof_schema_1_validator: Optional[ComponentHLS] = None # data type: ComponentRTSP @@ -42,40 +44,53 @@ class Component(BaseModel): class Config: validate_assignment = True - discriminator_value_class_map = { - } + 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`") + 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.") + 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') + @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`") + 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`") + 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)) + 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)) + raise ValueError( + "No match found when setting `actual_instance` in Component with oneOf schemas: ComponentHLS, ComponentRTSP. Details: " + + ", ".join(error_messages) + ) else: return v @@ -93,7 +108,9 @@ def from_json(cls, json_str: str) -> Component: # 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.") + raise ValueError( + "Failed to lookup data type from the field `type` in the input." + ) # check if data type is `ComponentHLS` if _data_type == "ComponentHLS": @@ -130,10 +147,16 @@ def from_json(cls, json_str: str) -> Component: 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)) + 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)) + raise ValueError( + "No match found when deserializing the JSON string into Component with oneOf schemas: ComponentHLS, ComponentRTSP. Details: " + + ", ".join(error_messages) + ) else: return instance @@ -163,5 +186,3 @@ def to_dict(self) -> dict: 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 b49de9e..5cac9bf 100644 --- a/jellyfish/_openapi_client/models/component_details_response.py +++ b/jellyfish/_openapi_client/models/component_details_response.py @@ -16,19 +16,21 @@ import json - from pydantic import BaseModel, Field from jellyfish._openapi_client.models.component import Component + class ComponentDetailsResponse(BaseModel): """ Response containing component details """ + data: Component = Field(...) __properties = ["data"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -47,13 +49,10 @@ def from_json(cls, json_str: str) -> ComponentDetailsResponse: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["data"] = self.data.to_dict() return _dict @classmethod @@ -65,9 +64,11 @@ def from_dict(cls, obj: dict) -> ComponentDetailsResponse: if not isinstance(obj, dict): return ComponentDetailsResponse.parse_obj(obj) - _obj = ComponentDetailsResponse.parse_obj({ - "data": Component.from_dict(obj.get("data")) if obj.get("data") is not None else None - }) + _obj = ComponentDetailsResponse.parse_obj( + { + "data": Component.from_dict(obj.get("data")) + if obj.get("data") is not None + else None + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/component_hls.py b/jellyfish/_openapi_client/models/component_hls.py index a5ae3bb..acedabe 100644 --- a/jellyfish/_openapi_client/models/component_hls.py +++ b/jellyfish/_openapi_client/models/component_hls.py @@ -16,14 +16,15 @@ import json - from pydantic import BaseModel, Field, StrictStr from jellyfish._openapi_client.models.component_metadata_hls import ComponentMetadataHLS + class ComponentHLS(BaseModel): """ Describes HLS component """ + id: StrictStr = Field(..., description="Assigned component ID") metadata: ComponentMetadataHLS = Field(...) type: StrictStr = Field(..., description="Component type") @@ -31,6 +32,7 @@ class ComponentHLS(BaseModel): class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -49,13 +51,10 @@ def from_json(cls, json_str: str) -> ComponentHLS: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["metadata"] = self.metadata.to_dict() return _dict @classmethod @@ -67,11 +66,13 @@ def from_dict(cls, obj: dict) -> ComponentHLS: if not isinstance(obj, dict): return ComponentHLS.parse_obj(obj) - _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") - }) + _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 - - diff --git a/jellyfish/_openapi_client/models/component_metadata_hls.py b/jellyfish/_openapi_client/models/component_metadata_hls.py index e0b0a1d..6ecdbe5 100644 --- a/jellyfish/_openapi_client/models/component_metadata_hls.py +++ b/jellyfish/_openapi_client/models/component_metadata_hls.py @@ -16,19 +16,34 @@ import json +from typing import Optional +from pydantic import BaseModel, Field, StrictBool, StrictInt -from pydantic import BaseModel, Field, StrictBool class ComponentMetadataHLS(BaseModel): """ Metadata specific to the HLS component """ - low_latency: StrictBool = Field(..., alias="lowLatency", description="Whether the component uses LL-HLS") - playable: StrictBool = Field(..., description="Whether the generated HLS playlist is playable") - __properties = ["lowLatency", "playable"] + + 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" + ) + target_window_duration: Optional[StrictInt] = Field( + ..., + alias="targetWindowDuration", + description="Duration of stream available for viewer", + ) + __properties = ["lowLatency", "persistent", "playable", "targetWindowDuration"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -47,10 +62,15 @@ def from_json(cls, json_str: str) -> ComponentMetadataHLS: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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 @@ -62,10 +82,12 @@ def from_dict(cls, obj: dict) -> ComponentMetadataHLS: if not isinstance(obj, dict): return ComponentMetadataHLS.parse_obj(obj) - _obj = ComponentMetadataHLS.parse_obj({ - "low_latency": obj.get("lowLatency"), - "playable": obj.get("playable") - }) + _obj = ComponentMetadataHLS.parse_obj( + { + "low_latency": obj.get("lowLatency"), + "persistent": obj.get("persistent"), + "playable": obj.get("playable"), + "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 index 1ed403d..26e3dda 100644 --- a/jellyfish/_openapi_client/models/component_options.py +++ b/jellyfish/_openapi_client/models/component_options.py @@ -25,10 +25,12 @@ 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 @@ -45,34 +47,48 @@ class Config: 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`") + 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.") + 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') + @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`") + 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`") + 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)) + 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)) + raise ValueError( + "No match found when setting `actual_instance` in ComponentOptions with oneOf schemas: ComponentOptionsHLS, ComponentOptionsRTSP. Details: " + + ", ".join(error_messages) + ) else: return v @@ -102,10 +118,16 @@ def from_json(cls, json_str: str) -> ComponentOptions: 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)) + 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)) + raise ValueError( + "No match found when deserializing the JSON string into ComponentOptions with oneOf schemas: ComponentOptionsHLS, ComponentOptionsRTSP. Details: " + + ", ".join(error_messages) + ) else: return instance @@ -135,5 +157,3 @@ def to_dict(self) -> dict: 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_hls.py b/jellyfish/_openapi_client/models/component_options_hls.py index 97f8046..102b891 100644 --- a/jellyfish/_openapi_client/models/component_options_hls.py +++ b/jellyfish/_openapi_client/models/component_options_hls.py @@ -17,17 +17,30 @@ from typing import Optional -from pydantic import BaseModel, Field, StrictBool +from pydantic import BaseModel, Field, StrictBool, StrictInt + 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") - __properties = ["lowLatency"] + + 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" + ) + target_window_duration: Optional[StrictInt] = Field( + None, + alias="targetWindowDuration", + description="Duration of stream available for viewer", + ) + __properties = ["lowLatency", "persistent", "targetWindowDuration"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -46,10 +59,15 @@ def from_json(cls, json_str: str) -> ComponentOptionsHLS: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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 @@ -61,9 +79,15 @@ def from_dict(cls, obj: dict) -> ComponentOptionsHLS: 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 - }) + _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, + "target_window_duration": obj.get("targetWindowDuration"), + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/component_options_rtsp.py b/jellyfish/_openapi_client/models/component_options_rtsp.py index a42ec20..7f6983f 100644 --- a/jellyfish/_openapi_client/models/component_options_rtsp.py +++ b/jellyfish/_openapi_client/models/component_options_rtsp.py @@ -19,19 +19,44 @@ 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"] + + 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 @@ -50,10 +75,7 @@ def from_json(cls, json_str: str) -> ComponentOptionsRTSP: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) return _dict @classmethod @@ -65,13 +87,21 @@ def from_dict(cls, obj: dict) -> ComponentOptionsRTSP: if not isinstance(obj, dict): return ComponentOptionsRTSP.parse_obj(obj) - _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") - }) + _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"), + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/component_rtsp.py b/jellyfish/_openapi_client/models/component_rtsp.py index 3e1d352..dc6797c 100644 --- a/jellyfish/_openapi_client/models/component_rtsp.py +++ b/jellyfish/_openapi_client/models/component_rtsp.py @@ -19,17 +19,22 @@ from typing import Any, Dict from pydantic import BaseModel, Field, StrictStr + class ComponentRTSP(BaseModel): """ Describes RTSP component """ + id: StrictStr = Field(..., description="Assigned component ID") - metadata: Dict[str, Any] = Field(..., description="Metadata specific to the RTSP component") + metadata: Dict[str, Any] = Field( + ..., description="Metadata specific to the RTSP component" + ) type: StrictStr = Field(..., description="Component type") __properties = ["id", "metadata", "type"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -48,10 +53,7 @@ def from_json(cls, json_str: str) -> ComponentRTSP: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) return _dict @classmethod @@ -63,11 +65,11 @@ def from_dict(cls, obj: dict) -> ComponentRTSP: if not isinstance(obj, dict): return ComponentRTSP.parse_obj(obj) - _obj = ComponentRTSP.parse_obj({ - "id": obj.get("id"), - "metadata": obj.get("metadata"), - "type": obj.get("type") - }) + _obj = ComponentRTSP.parse_obj( + { + "id": obj.get("id"), + "metadata": obj.get("metadata"), + "type": obj.get("type"), + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/error.py b/jellyfish/_openapi_client/models/error.py index 31975e8..cdb9dcc 100644 --- a/jellyfish/_openapi_client/models/error.py +++ b/jellyfish/_openapi_client/models/error.py @@ -16,18 +16,20 @@ import json - from pydantic import BaseModel, Field, StrictStr + 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 @@ -46,10 +48,7 @@ def from_json(cls, json_str: str) -> Error: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) return _dict @classmethod @@ -61,9 +60,5 @@ def from_dict(cls, obj: dict) -> Error: if not isinstance(obj, dict): return Error.parse_obj(obj) - _obj = Error.parse_obj({ - "errors": obj.get("errors") - }) + _obj = Error.parse_obj({"errors": obj.get("errors")}) return _obj - - diff --git a/jellyfish/_openapi_client/models/hls_skip.py b/jellyfish/_openapi_client/models/hls_skip.py index 9d51496..ce51cf2 100644 --- a/jellyfish/_openapi_client/models/hls_skip.py +++ b/jellyfish/_openapi_client/models/hls_skip.py @@ -16,9 +16,6 @@ from aenum import Enum, no_arg - - - class HlsSkip(str, Enum): """ Is delta manifest requested @@ -27,11 +24,9 @@ class HlsSkip(str, Enum): """ allowed enum values """ - TRUE = 'true' + 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 658ef42..3a8e8ac 100644 --- a/jellyfish/_openapi_client/models/peer.py +++ b/jellyfish/_openapi_client/models/peer.py @@ -16,14 +16,15 @@ import json - from pydantic import BaseModel, Field, StrictStr from jellyfish._openapi_client.models.peer_status import PeerStatus + class Peer(BaseModel): """ Describes peer status """ + id: StrictStr = Field(..., description="Assigned peer id") status: PeerStatus = Field(...) type: StrictStr = Field(..., description="Peer type") @@ -31,6 +32,7 @@ class Peer(BaseModel): class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -49,10 +51,7 @@ def from_json(cls, json_str: str) -> Peer: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) return _dict @classmethod @@ -64,11 +63,7 @@ def from_dict(cls, obj: dict) -> Peer: if not isinstance(obj, dict): return Peer.parse_obj(obj) - _obj = Peer.parse_obj({ - "id": obj.get("id"), - "status": obj.get("status"), - "type": obj.get("type") - }) + _obj = Peer.parse_obj( + {"id": obj.get("id"), "status": obj.get("status"), "type": obj.get("type")} + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/peer_details_response.py b/jellyfish/_openapi_client/models/peer_details_response.py index 7ec121c..ec905a1 100644 --- a/jellyfish/_openapi_client/models/peer_details_response.py +++ b/jellyfish/_openapi_client/models/peer_details_response.py @@ -16,19 +16,23 @@ import json - from pydantic import BaseModel, Field -from jellyfish._openapi_client.models.peer_details_response_data import PeerDetailsResponseData +from jellyfish._openapi_client.models.peer_details_response_data import ( + PeerDetailsResponseData, +) + class PeerDetailsResponse(BaseModel): """ Response containing peer details and their token """ + data: PeerDetailsResponseData = Field(...) __properties = ["data"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -47,13 +51,10 @@ def from_json(cls, json_str: str) -> PeerDetailsResponse: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["data"] = self.data.to_dict() return _dict @classmethod @@ -65,9 +66,11 @@ def from_dict(cls, obj: dict) -> PeerDetailsResponse: if not isinstance(obj, dict): return PeerDetailsResponse.parse_obj(obj) - _obj = PeerDetailsResponse.parse_obj({ - "data": PeerDetailsResponseData.from_dict(obj.get("data")) if obj.get("data") is not None else None - }) + _obj = PeerDetailsResponse.parse_obj( + { + "data": PeerDetailsResponseData.from_dict(obj.get("data")) + if obj.get("data") is not None + else None + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/peer_details_response_data.py b/jellyfish/_openapi_client/models/peer_details_response_data.py index db3e5e1..2923e15 100644 --- a/jellyfish/_openapi_client/models/peer_details_response_data.py +++ b/jellyfish/_openapi_client/models/peer_details_response_data.py @@ -16,20 +16,24 @@ import json - from pydantic import BaseModel, Field, StrictStr from jellyfish._openapi_client.models.peer import Peer + class PeerDetailsResponseData(BaseModel): """ PeerDetailsResponseData """ + peer: Peer = Field(...) - token: StrictStr = Field(..., description="Token for authorizing websocket connection") + token: StrictStr = Field( + ..., description="Token for authorizing websocket connection" + ) __properties = ["peer", "token"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -48,13 +52,10 @@ def from_json(cls, json_str: str) -> PeerDetailsResponseData: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["peer"] = self.peer.to_dict() return _dict @classmethod @@ -66,10 +67,12 @@ def from_dict(cls, obj: dict) -> PeerDetailsResponseData: if not isinstance(obj, dict): return PeerDetailsResponseData.parse_obj(obj) - _obj = PeerDetailsResponseData.parse_obj({ - "peer": Peer.from_dict(obj.get("peer")) if obj.get("peer") is not None else None, - "token": obj.get("token") - }) + _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 - - diff --git a/jellyfish/_openapi_client/models/peer_options.py b/jellyfish/_openapi_client/models/peer_options.py index 7d62065..6f3caf2 100644 --- a/jellyfish/_openapi_client/models/peer_options.py +++ b/jellyfish/_openapi_client/models/peer_options.py @@ -24,10 +24,12 @@ PEEROPTIONS_ONE_OF_SCHEMAS = ["PeerOptionsWebRTC"] + class PeerOptions(BaseModel): """ Peer-specific options """ + # data type: PeerOptionsWebRTC oneof_schema_1_validator: Optional[PeerOptionsWebRTC] = None if TYPE_CHECKING: @@ -42,29 +44,41 @@ class Config: 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`") + 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.") + 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') + @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`") + 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)) + 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)) + raise ValueError( + "No match found when setting `actual_instance` in PeerOptions with oneOf schemas: PeerOptionsWebRTC. Details: " + + ", ".join(error_messages) + ) else: return v @@ -88,10 +102,16 @@ def from_json(cls, json_str: str) -> PeerOptions: 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)) + 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)) + raise ValueError( + "No match found when deserializing the JSON string into PeerOptions with oneOf schemas: PeerOptionsWebRTC. Details: " + + ", ".join(error_messages) + ) else: return instance @@ -121,5 +141,3 @@ def to_dict(self) -> dict: 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 e51f45f..c58f889 100644 --- a/jellyfish/_openapi_client/models/peer_options_web_rtc.py +++ b/jellyfish/_openapi_client/models/peer_options_web_rtc.py @@ -19,15 +19,20 @@ from typing import Optional from pydantic import BaseModel, Field, StrictBool + class PeerOptionsWebRTC(BaseModel): """ Options specific to the WebRTC peer """ - enable_simulcast: Optional[StrictBool] = Field(True, alias="enableSimulcast", description="Enables the peer to use simulcast") + + enable_simulcast: Optional[StrictBool] = Field( + True, alias="enableSimulcast", description="Enables the peer to use simulcast" + ) __properties = ["enableSimulcast"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -46,10 +51,7 @@ def from_json(cls, json_str: str) -> PeerOptionsWebRTC: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) return _dict @classmethod @@ -61,9 +63,11 @@ def from_dict(cls, obj: dict) -> PeerOptionsWebRTC: 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 - }) + _obj = PeerOptionsWebRTC.parse_obj( + { + "enable_simulcast": obj.get("enableSimulcast") + if obj.get("enableSimulcast") is not None + else True + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/peer_status.py b/jellyfish/_openapi_client/models/peer_status.py index fc9fc11..d43864f 100644 --- a/jellyfish/_openapi_client/models/peer_status.py +++ b/jellyfish/_openapi_client/models/peer_status.py @@ -16,9 +16,6 @@ from aenum import Enum, no_arg - - - class PeerStatus(str, Enum): """ Informs about the peer status @@ -27,12 +24,10 @@ class PeerStatus(str, Enum): """ allowed enum values """ - CONNECTED = 'connected' - DISCONNECTED = 'disconnected' + 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)) - - diff --git a/jellyfish/_openapi_client/models/room.py b/jellyfish/_openapi_client/models/room.py index f776caa..1f81b37 100644 --- a/jellyfish/_openapi_client/models/room.py +++ b/jellyfish/_openapi_client/models/room.py @@ -22,10 +22,12 @@ from jellyfish._openapi_client.models.peer import Peer from jellyfish._openapi_client.models.room_config import RoomConfig + class Room(BaseModel): """ Description of the room state """ + components: conlist(Component) = Field(...) config: RoomConfig = Field(...) id: StrictStr = Field(..., description="Room ID") @@ -34,6 +36,7 @@ class Room(BaseModel): class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -52,27 +55,24 @@ def from_json(cls, json_str: str) -> Room: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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 + _dict["components"] = _items # override the default output from pydantic by calling `to_dict()` of config if self.config: - _dict['config'] = self.config.to_dict() + _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 + _dict["peers"] = _items return _dict @classmethod @@ -84,12 +84,20 @@ def from_dict(cls, obj: dict) -> Room: if not isinstance(obj, dict): return Room.parse_obj(obj) - _obj = Room.parse_obj({ - "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 - }) + _obj = Room.parse_obj( + { + "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, + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/room_config.py b/jellyfish/_openapi_client/models/room_config.py index bc00f7e..d17ba5a 100644 --- a/jellyfish/_openapi_client/models/room_config.py +++ b/jellyfish/_openapi_client/models/room_config.py @@ -19,26 +19,42 @@ from typing import Optional from pydantic import BaseModel, Field, StrictStr, conint, validator + class RoomConfig(BaseModel): """ Room configuration """ - 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") - __properties = ["maxPeers", "videoCodec"] - @validator('video_codec') + 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"] + + @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'): + if value not in ("h264", "vp8"): raise ValueError("must be one of enum values ('h264', 'vp8')") return value class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -57,19 +73,21 @@ def from_json(cls, json_str: str) -> RoomConfig: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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 + _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 + _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 @@ -82,10 +100,11 @@ def from_dict(cls, obj: dict) -> RoomConfig: if not isinstance(obj, dict): return RoomConfig.parse_obj(obj) - _obj = RoomConfig.parse_obj({ - "max_peers": obj.get("maxPeers"), - "video_codec": obj.get("videoCodec") - }) + _obj = RoomConfig.parse_obj( + { + "max_peers": obj.get("maxPeers"), + "video_codec": obj.get("videoCodec"), + "webhook_url": obj.get("webhookUrl"), + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/room_create_details_response.py b/jellyfish/_openapi_client/models/room_create_details_response.py index 9e65296..d31ac50 100644 --- a/jellyfish/_openapi_client/models/room_create_details_response.py +++ b/jellyfish/_openapi_client/models/room_create_details_response.py @@ -16,19 +16,23 @@ import json - from pydantic import BaseModel, Field -from jellyfish._openapi_client.models.room_create_details_response_data import RoomCreateDetailsResponseData +from jellyfish._openapi_client.models.room_create_details_response_data import ( + RoomCreateDetailsResponseData, +) + class RoomCreateDetailsResponse(BaseModel): """ Response containing room details """ + data: RoomCreateDetailsResponseData = Field(...) __properties = ["data"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -47,13 +51,10 @@ def from_json(cls, json_str: str) -> RoomCreateDetailsResponse: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["data"] = self.data.to_dict() return _dict @classmethod @@ -65,9 +66,11 @@ def from_dict(cls, obj: dict) -> RoomCreateDetailsResponse: if not isinstance(obj, dict): return RoomCreateDetailsResponse.parse_obj(obj) - _obj = RoomCreateDetailsResponse.parse_obj({ - "data": RoomCreateDetailsResponseData.from_dict(obj.get("data")) if obj.get("data") is not None else None - }) + _obj = RoomCreateDetailsResponse.parse_obj( + { + "data": RoomCreateDetailsResponseData.from_dict(obj.get("data")) + if obj.get("data") is not None + else None + } + ) return _obj - - 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 411c56e..3c886fc 100644 --- a/jellyfish/_openapi_client/models/room_create_details_response_data.py +++ b/jellyfish/_openapi_client/models/room_create_details_response_data.py @@ -16,20 +16,25 @@ import json - from pydantic import BaseModel, Field, StrictStr from jellyfish._openapi_client.models.room import Room + class RoomCreateDetailsResponseData(BaseModel): """ RoomCreateDetailsResponseData """ - 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.") + + 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"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -48,13 +53,10 @@ def from_json(cls, json_str: str) -> RoomCreateDetailsResponseData: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["room"] = self.room.to_dict() return _dict @classmethod @@ -66,10 +68,12 @@ def from_dict(cls, obj: dict) -> RoomCreateDetailsResponseData: if not isinstance(obj, dict): return RoomCreateDetailsResponseData.parse_obj(obj) - _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 - }) + _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 - - diff --git a/jellyfish/_openapi_client/models/room_details_response.py b/jellyfish/_openapi_client/models/room_details_response.py index 90fb331..85c4135 100644 --- a/jellyfish/_openapi_client/models/room_details_response.py +++ b/jellyfish/_openapi_client/models/room_details_response.py @@ -16,19 +16,21 @@ import json - from pydantic import BaseModel, Field from jellyfish._openapi_client.models.room import Room + class RoomDetailsResponse(BaseModel): """ Response containing room details """ + data: Room = Field(...) __properties = ["data"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -47,13 +49,10 @@ def from_json(cls, json_str: str) -> RoomDetailsResponse: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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() + _dict["data"] = self.data.to_dict() return _dict @classmethod @@ -65,9 +64,11 @@ def from_dict(cls, obj: dict) -> RoomDetailsResponse: if not isinstance(obj, dict): return RoomDetailsResponse.parse_obj(obj) - _obj = RoomDetailsResponse.parse_obj({ - "data": Room.from_dict(obj.get("data")) if obj.get("data") is not None else None - }) + _obj = RoomDetailsResponse.parse_obj( + { + "data": Room.from_dict(obj.get("data")) + if obj.get("data") is not None + else None + } + ) return _obj - - diff --git a/jellyfish/_openapi_client/models/rooms_listing_response.py b/jellyfish/_openapi_client/models/rooms_listing_response.py index 7289352..4467c10 100644 --- a/jellyfish/_openapi_client/models/rooms_listing_response.py +++ b/jellyfish/_openapi_client/models/rooms_listing_response.py @@ -20,15 +20,18 @@ from pydantic import BaseModel, Field, conlist from jellyfish._openapi_client.models.room import Room + class RoomsListingResponse(BaseModel): """ Response containing list of all rooms """ + data: conlist(Room) = Field(...) __properties = ["data"] class Config: """Pydantic configuration""" + allow_population_by_field_name = True validate_assignment = True @@ -47,17 +50,14 @@ def from_json(cls, json_str: str) -> RoomsListingResponse: def to_dict(self): """Returns the dictionary representation of the model using alias""" - _dict = self.dict(by_alias=True, - exclude={ - }, - exclude_none=True) + _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 + _dict["data"] = _items return _dict @classmethod @@ -69,9 +69,11 @@ def from_dict(cls, obj: dict) -> RoomsListingResponse: if not isinstance(obj, dict): return RoomsListingResponse.parse_obj(obj) - _obj = RoomsListingResponse.parse_obj({ - "data": [Room.from_dict(_item) for _item in obj.get("data")] if obj.get("data") is not None else None - }) + _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 - - diff --git a/jellyfish/_openapi_client/rest.py b/jellyfish/_openapi_client/rest.py index 188095f..fbd7734 100644 --- a/jellyfish/_openapi_client/rest.py +++ b/jellyfish/_openapi_client/rest.py @@ -19,14 +19,21 @@ from urllib.parse import urlencode, quote_plus import urllib3 -from jellyfish._openapi_client.exceptions import ApiException, UnauthorizedException, ForbiddenException, NotFoundException, ServiceException, ApiValueError, BadRequestException +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 @@ -43,7 +50,6 @@ def getheader(self, name, default=None): 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 @@ -59,17 +65,18 @@ def __init__(self, configuration, pools_size=4, maxsize=None): addition_pool_args = {} if configuration.assert_hostname is not None: - addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501 + addition_pool_args[ + "assert_hostname" + ] = configuration.assert_hostname # noqa: E501 if configuration.retries is not None: - addition_pool_args['retries'] = configuration.retries + addition_pool_args["retries"] = configuration.retries if configuration.tls_server_name: - addition_pool_args['server_hostname'] = 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 + addition_pool_args["socket_options"] = configuration.socket_options if maxsize is None: if configuration.connection_pool_maxsize is not None: @@ -101,9 +108,17 @@ def __init__(self, configuration, pools_size=4, maxsize=None): **addition_pool_args ) - def request(self, method, url, query_params=None, headers=None, - body=None, post_params=None, _preload_content=True, - _request_timeout=None): + 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 @@ -123,8 +138,7 @@ def request(self, method, url, query_params=None, headers=None, (connection, read) timeouts. """ method = method.upper() - assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', - 'PATCH', 'OPTIONS'] + assert method in ["GET", "HEAD", "DELETE", "POST", "PUT", "PATCH", "OPTIONS"] if post_params and body: raise ApiValueError( @@ -139,59 +153,70 @@ def request(self, method, url, query_params=None, headers=None, timeout = None if _request_timeout: - if isinstance(_request_timeout, (int,float)): # noqa: E501,F821 + 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): + elif isinstance(_request_timeout, tuple) and len(_request_timeout) == 2: timeout = urllib3.Timeout( - connect=_request_timeout[0], read=_request_timeout[1]) + connect=_request_timeout[0], read=_request_timeout[1] + ) try: # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` - if method in ['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): + 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, + method, + url, body=request_body, preload_content=_preload_content, timeout=timeout, - headers=headers) - elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + headers=headers, + ) + elif ( + headers["Content-Type"] == "application/x-www-form-urlencoded" + ): # noqa: E501 r = self.pool_manager.request( - method, url, + method, + url, fields=post_params, encode_multipart=False, preload_content=_preload_content, timeout=timeout, - headers=headers) - elif headers['Content-Type'] == 'multipart/form-data': + 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'] + del headers["Content-Type"] r = self.pool_manager.request( - method, url, + method, + url, fields=post_params, encode_multipart=True, preload_content=_preload_content, timeout=timeout, - headers=headers) + 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, + method, + url, body=request_body, preload_content=_preload_content, timeout=timeout, - headers=headers) + headers=headers, + ) else: # Cannot generate the request from given parameters msg = """Cannot prepare a request message for provided @@ -200,11 +225,14 @@ def request(self, method, url, query_params=None, headers=None, 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) + 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) @@ -235,67 +263,139 @@ def request(self, method, url, query_params=None, headers=None, 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) + 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/_room_api.py b/jellyfish/_room_api.py index 81927ab..5957c18 100644 --- a/jellyfish/_room_api.py +++ b/jellyfish/_room_api.py @@ -1,41 +1,55 @@ -''' +""" 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, ComponentOptionsHLS, ComponentOptionsRTSP, Room, RoomConfig, Peer) + AddPeerRequest, + AddComponentRequest, + PeerOptions, + PeerOptionsWebRTC, + Component, + ComponentOptions, + ComponentOptionsHLS, + ComponentOptionsRTSP, + Room, + RoomConfig, + Peer, +) class RoomApi: - '''Allows for managing rooms''' - - def __init__(self, - server_address: str = 'localhost:5002', - server_api_token: str = 'development', - secure: bool = False): - ''' + """Allows for managing rooms""" + + def __init__( + self, + server_address: str = "localhost:5002", + server_api_token: str = "development", + secure: bool = False, + ): + """ 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' + protocol = "https" if secure else "http" self._configuration = jellyfish_api.Configuration( - host=f'{protocol}://{server_address}', - access_token=server_api_token + host=f"{protocol}://{server_address}", access_token=server_api_token ) self._api_client = jellyfish_api.ApiClient(self._configuration) self._room_api = jellyfish_api.RoomApi(self._api_client) def create_room( - self, max_peers: int = None, video_codec: Literal['h264', 'vp8'] = None) -> ( - str, Room): - ''' + self, + max_peers: int = None, + video_codec: Literal["h264", "vp8"] = None, + webhook_url: str = None, + ) -> (str, Room): + """ Creates a new room Returns a tuple (`jellyfish_address`, `Room`) - the address of the Jellyfish @@ -44,38 +58,40 @@ def create_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. - ''' - room_config = RoomConfig(maxPeers=max_peers, videoCodec=video_codec) + """ + room_config = RoomConfig( + maxPeers=max_peers, videoCodec=video_codec, webhook_url=webhook_url + ) resp = self._room_api.create_room(room_config) return (resp.data.jellyfish_address, resp.data.room) def delete_room(self, room_id: str) -> None: - '''Deletes a room''' + """Deletes a room""" return self._room_api.delete_room(room_id) def get_all_rooms(self) -> list: - '''Returns list of all rooms ''' + """Returns list of all rooms""" return self._room_api.get_all_rooms().data def get_room(self, room_id: str) -> Room: - '''Returns room with the given id''' + """Returns room with the given id""" return self._room_api.get_room(room_id).data def add_peer(self, room_id: str, options: PeerOptionsWebRTC) -> (str, Peer): - ''' + """ Creates peer in the room 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` - ''' + to Jellyfish and the new `Peer` + """ - peer_type = 'webrtc' + peer_type = "webrtc" options = PeerOptions(options) request = AddPeerRequest(type=peer_type, options=options) @@ -83,20 +99,23 @@ def add_peer(self, room_id: str, options: PeerOptionsWebRTC) -> (str, Peer): return (resp.data.token, resp.data.peer) def delete_peer(self, room_id: str, peer_id: str) -> None: - '''Deletes peer''' + """Deletes peer""" return self._room_api.delete_peer(room_id, peer_id) - def add_component(self, room_id: str, options: Union - [ComponentOptionsHLS, ComponentOptionsRTSP]) -> Component: - '''Creates component in the room''' + def add_component( + self, room_id: str, options: Union[ComponentOptionsHLS, ComponentOptionsRTSP] + ) -> Component: + """Creates component in the room""" if isinstance(options, ComponentOptionsHLS): - component_type = 'hls' + component_type = "hls" elif isinstance(options, ComponentOptionsRTSP): - component_type = 'rtsp' + component_type = "rtsp" else: - raise ValueError('options must be either ComponentOptionsHLS or ComponentOptionsRTSP') + raise ValueError( + "options must be either ComponentOptionsHLS or ComponentOptionsRTSP" + ) options = ComponentOptions(options) request = AddComponentRequest(type=component_type, options=options) @@ -104,6 +123,6 @@ def add_component(self, room_id: str, options: Union return self._room_api.add_component(room_id, request).data def delete_component(self, room_id: str, component_id: str) -> None: - '''Deletes component''' + """Deletes component""" return self._room_api.delete_component(room_id, component_id) diff --git a/jellyfish/_webhook_notifier.py b/jellyfish/_webhook_notifier.py new file mode 100644 index 0000000..d4e2d6d --- /dev/null +++ b/jellyfish/_webhook_notifier.py @@ -0,0 +1,21 @@ +""" +Module defining a function allowing decoding received webhook +notification from jellyfish to notification structs. +""" + +from typing import Any, Dict + +import betterproto + +from jellyfish.events import ServerMessage + + +def receive_json(json: Dict) -> Any: + """ + Transform received json notification to adequate notification instance. + """ + msg = json["notification"] + msg = bytes(msg, "utf-8") + message = ServerMessage().parse(msg) + _which, message = betterproto.which_one_of(message, "content") + return message diff --git a/jellyfish/_notifier.py b/jellyfish/_ws_notifier.py similarity index 76% rename from jellyfish/_notifier.py rename to jellyfish/_ws_notifier.py index da85946..de46ee9 100644 --- a/jellyfish/_notifier.py +++ b/jellyfish/_ws_notifier.py @@ -1,6 +1,6 @@ -''' +""" Notifier listening to WebSocket events -''' +""" import asyncio from typing import Callable, Any @@ -11,27 +11,34 @@ from websockets.exceptions import ConnectionClosed from jellyfish.events import ( - ServerMessage, ServerMessageAuthRequest, ServerMessageAuthenticated, - ServerMessageSubscribeRequest, ServerMessageEventType, ServerMessageSubscribeResponse, - ServerMessageMetricsReport) + ServerMessage, + ServerMessageAuthRequest, + ServerMessageAuthenticated, + ServerMessageSubscribeRequest, + ServerMessageEventType, + ServerMessageSubscribeResponse, + ServerMessageMetricsReport, +) class Notifier: - ''' + """ Allows for receiving WebSocket messages from Jellyfish. - ''' - - def __init__(self, - server_address: str = 'localhost:5002', - server_api_token: str = 'development', - secure: bool = False): - ''' + """ + + def __init__( + self, + server_address: str = "localhost:5002", + server_api_token: str = "development", + secure: bool = False, + ): + """ Create Notifier instance, providing the jellyfish address and api token. Set secure to `True` for `wss` and `False` for `ws` connection (default). - ''' + """ - protocol = 'wss' if secure else 'ws' - self._server_address = f'{protocol}://{server_address}/socket/server/websocket' + protocol = "wss" if secure else "ws" + self._server_address = f"{protocol}://{server_address}/socket/server/websocket" self._server_api_token = server_api_token self._websocket = None self._ready = False @@ -42,22 +49,22 @@ def __init__(self, self._metrics_handler: Callable = None def on_server_notification(self, handler: Callable[[Any], None]): - ''' + """ Decorator used for defining handler for ServerNotifications i.e. all messages other than `ServerMessageMetricsReport`. - ''' + """ self._notification_handler = handler return handler def on_metrics(self, handler: Callable[[ServerMessageMetricsReport], None]): - ''' + """ Decorator used for defining handler for `ServerMessageMetricsReport`. - ''' + """ self._metrics_handler = handler return handler async def connect(self): - ''' + """ A coroutine which connects Notifier to Jellyfish and listens for all incoming messages from the Jellyfish. @@ -68,7 +75,7 @@ async def connect(self): The handlers have to be defined before calling `connect`, otherwise the messages won't be received. - ''' + """ async with client.connect(self._server_address) as websocket: try: self._websocket = websocket @@ -76,10 +83,13 @@ async def connect(self): if self._notification_handler: await self._subscribe_event( - event=ServerMessageEventType.EVENT_TYPE_SERVER_NOTIFICATION) + event=ServerMessageEventType.EVENT_TYPE_SERVER_NOTIFICATION + ) if self._metrics_handler: - await self._subscribe_event(event=ServerMessageEventType.EVENT_TYPE_METRICS) + await self._subscribe_event( + event=ServerMessageEventType.EVENT_TYPE_METRICS + ) self._ready = True if self._ready_event: @@ -90,11 +100,11 @@ async def connect(self): self._websocket = None async def wait_ready(self) -> True: - ''' + """ Waits until the notifier is connected and authenticated to Jellyfish. If already connected, returns `True` immediately. - ''' + """ if self._ready: return True @@ -104,26 +114,28 @@ async def wait_ready(self) -> True: await self._ready_event.wait() async def _authenticate(self): - msg = ServerMessage(auth_request=ServerMessageAuthRequest(token=self._server_api_token)) + msg = ServerMessage( + auth_request=ServerMessageAuthRequest(token=self._server_api_token) + ) await self._websocket.send(bytes(msg)) try: message = await self._websocket.recv() except ConnectionClosed as exception: - if 'invalid token' in str(exception): - raise RuntimeError('Invalid server_api_token') from exception + if "invalid token" in str(exception): + raise RuntimeError("Invalid server_api_token") from exception raise message = ServerMessage().parse(message) - _type, message = betterproto.which_one_of(message, 'content') + _type, message = betterproto.which_one_of(message, "content") assert isinstance(message, ServerMessageAuthenticated) async def _receive_loop(self): while True: message = await self._websocket.recv() message = ServerMessage().parse(message) - _which, message = betterproto.which_one_of(message, 'content') + _which, message = betterproto.which_one_of(message, "content") if isinstance(message, ServerMessageMetricsReport): self._metrics_handler(message) diff --git a/jellyfish/events/__init__.py b/jellyfish/events/__init__.py index 39b8239..05e4b01 100644 --- a/jellyfish/events/__init__.py +++ b/jellyfish/events/__init__.py @@ -1,21 +1,38 @@ -''' +""" Server events being sent Jellyfish -''' +""" # Private messages from jellyfish.events._protos.jellyfish import ( - ServerMessage, ServerMessageAuthenticated, ServerMessageAuthRequest, ServerMessageEventType, - ServerMessageSubscribeResponse, ServerMessageSubscribeRequest) + ServerMessage, + ServerMessageAuthenticated, + ServerMessageAuthRequest, + ServerMessageEventType, + ServerMessageSubscribeResponse, + ServerMessageSubscribeRequest, +) # Exported messages from jellyfish.events._protos.jellyfish import ( - ServerMessageComponentCrashed, ServerMessageHlsPlayable, - ServerMessageMetricsReport, ServerMessagePeerCrashed, ServerMessagePeerConnected, - ServerMessagePeerDisconnected, ServerMessageRoomCrashed, ServerMessageRoomDeleted, - ServerMessageRoomCreated) + ServerMessageComponentCrashed, + ServerMessageHlsPlayable, + ServerMessageMetricsReport, + ServerMessagePeerCrashed, + ServerMessagePeerConnected, + ServerMessagePeerDisconnected, + ServerMessageRoomCrashed, + ServerMessageRoomDeleted, + ServerMessageRoomCreated, +) __all__ = [ - 'ServerMessageComponentCrashed', 'ServerMessageHlsPlayable', - 'ServerMessageMetricsReport', 'ServerMessagePeerCrashed', 'ServerMessagePeerConnected', - 'ServerMessagePeerDisconnected', 'ServerMessageRoomCrashed', 'ServerMessageRoomDeleted', - 'ServerMessageRoomCreated'] + "ServerMessageComponentCrashed", + "ServerMessageHlsPlayable", + "ServerMessageMetricsReport", + "ServerMessagePeerCrashed", + "ServerMessagePeerConnected", + "ServerMessagePeerDisconnected", + "ServerMessageRoomCrashed", + "ServerMessageRoomDeleted", + "ServerMessageRoomCreated", +] diff --git a/jellyfish/events/_protos/jellyfish.py b/jellyfish/events/_protos/jellyfish.py deleted file mode 100644 index 63307e2..0000000 --- a/jellyfish/events/_protos/jellyfish.py +++ /dev/null @@ -1,125 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: protos/jellyfish/server_notifications.proto -# plugin: python-betterproto -from dataclasses import dataclass - -import betterproto - - -class ServerMessageEventType(betterproto.Enum): - EVENT_TYPE_UNSPECIFIED = 0 - EVENT_TYPE_SERVER_NOTIFICATION = 1 - EVENT_TYPE_METRICS = 2 - - -@dataclass -class ServerMessage(betterproto.Message): - room_crashed: "ServerMessageRoomCrashed" = betterproto.message_field( - 1, group="content" - ) - peer_connected: "ServerMessagePeerConnected" = betterproto.message_field( - 2, group="content" - ) - peer_disconnected: "ServerMessagePeerDisconnected" = betterproto.message_field( - 3, group="content" - ) - peer_crashed: "ServerMessagePeerCrashed" = betterproto.message_field( - 4, group="content" - ) - component_crashed: "ServerMessageComponentCrashed" = betterproto.message_field( - 5, group="content" - ) - authenticated: "ServerMessageAuthenticated" = betterproto.message_field( - 6, group="content" - ) - auth_request: "ServerMessageAuthRequest" = betterproto.message_field( - 7, group="content" - ) - subscribe_request: "ServerMessageSubscribeRequest" = betterproto.message_field( - 8, group="content" - ) - subscribe_response: "ServerMessageSubscribeResponse" = betterproto.message_field( - 9, group="content" - ) - room_created: "ServerMessageRoomCreated" = betterproto.message_field( - 10, group="content" - ) - room_deleted: "ServerMessageRoomDeleted" = betterproto.message_field( - 11, group="content" - ) - metrics_report: "ServerMessageMetricsReport" = betterproto.message_field( - 12, group="content" - ) - hls_playable: "ServerMessageHlsPlayable" = betterproto.message_field( - 13, group="content" - ) - - -@dataclass -class ServerMessageRoomCrashed(betterproto.Message): - room_id: str = betterproto.string_field(1) - - -@dataclass -class ServerMessagePeerConnected(betterproto.Message): - room_id: str = betterproto.string_field(1) - peer_id: str = betterproto.string_field(2) - - -@dataclass -class ServerMessagePeerDisconnected(betterproto.Message): - room_id: str = betterproto.string_field(1) - peer_id: str = betterproto.string_field(2) - - -@dataclass -class ServerMessagePeerCrashed(betterproto.Message): - room_id: str = betterproto.string_field(1) - peer_id: str = betterproto.string_field(2) - - -@dataclass -class ServerMessageComponentCrashed(betterproto.Message): - room_id: str = betterproto.string_field(1) - component_id: str = betterproto.string_field(2) - - -@dataclass -class ServerMessageAuthenticated(betterproto.Message): - pass - - -@dataclass -class ServerMessageAuthRequest(betterproto.Message): - token: str = betterproto.string_field(1) - - -@dataclass -class ServerMessageSubscribeRequest(betterproto.Message): - event_type: "ServerMessageEventType" = betterproto.enum_field(1) - - -@dataclass -class ServerMessageSubscribeResponse(betterproto.Message): - event_type: "ServerMessageEventType" = betterproto.enum_field(1) - - -@dataclass -class ServerMessageRoomCreated(betterproto.Message): - room_id: str = betterproto.string_field(1) - - -@dataclass -class ServerMessageRoomDeleted(betterproto.Message): - room_id: str = betterproto.string_field(1) - - -@dataclass -class ServerMessageMetricsReport(betterproto.Message): - metrics: str = betterproto.string_field(1) - - -@dataclass -class ServerMessageHlsPlayable(betterproto.Message): - room_id: str = betterproto.string_field(1) - component_id: str = betterproto.string_field(2) diff --git a/poetry.lock b/poetry.lock index a7c1a3b..bf38a58 100644 --- a/poetry.lock +++ b/poetry.lock @@ -58,12 +58,192 @@ files = [ ] [package.dependencies] +black = {version = ">=19.3b0", optional = true, markers = "extra == \"compiler\""} grpclib = ">=0.4.1,<0.5.0" +isort = {version = ">=5.11.5,<6.0.0", optional = true, markers = "extra == \"compiler\""} +jinja2 = {version = ">=3.0.3", optional = true, markers = "extra == \"compiler\""} python-dateutil = ">=2.8,<3.0" [package.extras] compiler = ["black (>=19.3b0)", "isort (>=5.11.5,<6.0.0)", "jinja2 (>=3.0.3)"] +[[package]] +name = "black" +version = "23.10.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.10.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:f8dc7d50d94063cdfd13c82368afd8588bac4ce360e4224ac399e769d6704e98"}, + {file = "black-23.10.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:f20ff03f3fdd2fd4460b4f631663813e57dc277e37fb216463f3b907aa5a9bdd"}, + {file = "black-23.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3d9129ce05b0829730323bdcb00f928a448a124af5acf90aa94d9aba6969604"}, + {file = "black-23.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:960c21555be135c4b37b7018d63d6248bdae8514e5c55b71e994ad37407f45b8"}, + {file = "black-23.10.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:30b78ac9b54cf87bcb9910ee3d499d2bc893afd52495066c49d9ee6b21eee06e"}, + {file = "black-23.10.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:0e232f24a337fed7a82c1185ae46c56c4a6167fb0fe37411b43e876892c76699"}, + {file = "black-23.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31946ec6f9c54ed7ba431c38bc81d758970dd734b96b8e8c2b17a367d7908171"}, + {file = "black-23.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:c870bee76ad5f7a5ea7bd01dc646028d05568d33b0b09b7ecfc8ec0da3f3f39c"}, + {file = "black-23.10.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:6901631b937acbee93c75537e74f69463adaf34379a04eef32425b88aca88a23"}, + {file = "black-23.10.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:481167c60cd3e6b1cb8ef2aac0f76165843a374346aeeaa9d86765fe0dd0318b"}, + {file = "black-23.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f74892b4b836e5162aa0452393112a574dac85e13902c57dfbaaf388e4eda37c"}, + {file = "black-23.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:47c4510f70ec2e8f9135ba490811c071419c115e46f143e4dce2ac45afdcf4c9"}, + {file = "black-23.10.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:76baba9281e5e5b230c9b7f83a96daf67a95e919c2dfc240d9e6295eab7b9204"}, + {file = "black-23.10.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:a3c2ddb35f71976a4cfeca558848c2f2f89abc86b06e8dd89b5a65c1e6c0f22a"}, + {file = "black-23.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db451a3363b1e765c172c3fd86213a4ce63fb8524c938ebd82919bf2a6e28c6a"}, + {file = "black-23.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:7fb5fc36bb65160df21498d5a3dd330af8b6401be3f25af60c6ebfe23753f747"}, + {file = "black-23.10.0-py3-none-any.whl", hash = "sha256:e223b731a0e025f8ef427dd79d8cd69c167da807f5710add30cdf131f13dd62e"}, + {file = "black-23.10.0.tar.gz", hash = "sha256:31b9f87b277a68d0e99d2905edae08807c007973eaa609da5f0c62def6b7c0bd"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "blinker" +version = "1.6.3" +description = "Fast, simple object-to-object and broadcast signaling" +optional = false +python-versions = ">=3.7" +files = [ + {file = "blinker-1.6.3-py3-none-any.whl", hash = "sha256:296320d6c28b006eb5e32d4712202dbcdcbf5dc482da298c2f44881c43884aaa"}, + {file = "blinker-1.6.3.tar.gz", hash = "sha256:152090d27c1c5c722ee7e48504b02d76502811ce02e1523553b4cf8c8b3d3a8d"}, +] + +[[package]] +name = "certifi" +version = "2023.7.22" +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"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, + {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + [[package]] name = "colorama" version = "0.4.6" @@ -103,6 +283,29 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "flask" +version = "3.0.0" +description = "A simple framework for building complex web applications." +optional = false +python-versions = ">=3.8" +files = [ + {file = "flask-3.0.0-py3-none-any.whl", hash = "sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638"}, + {file = "flask-3.0.0.tar.gz", hash = "sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58"}, +] + +[package.dependencies] +blinker = ">=1.6.2" +click = ">=8.1.3" +importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} +itsdangerous = ">=2.1.2" +Jinja2 = ">=3.1.2" +Werkzeug = ">=3.0.0" + +[package.extras] +async = ["asgiref (>=3.2)"] +dotenv = ["python-dotenv"] + [[package]] name = "grpclib" version = "0.4.6" @@ -157,6 +360,36 @@ files = [ {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, ] +[[package]] +name = "idna" +version = "3.4" +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"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.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"}, +] + +[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"] +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"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -185,6 +418,17 @@ 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" +description = "Safely pass data to untrusted environments and back." +optional = false +python-versions = ">=3.7" +files = [ + {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, + {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, +] + [[package]] name = "jinja2" version = "3.1.2" @@ -410,6 +654,17 @@ files = [ {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, ] +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + [[package]] name = "packaging" version = "23.2" @@ -421,6 +676,17 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + [[package]] name = "pdoc" version = "14.1.0" @@ -443,13 +709,13 @@ dev = ["black", "hypothesis", "mypy", "pygments (>=2.14.0)", "pytest", "pytest-c [[package]] name = "platformdirs" -version = "3.10.0" +version = "3.11.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, - {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, + {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, + {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, ] [package.extras] @@ -620,6 +886,27 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + [[package]] name = "six" version = "1.16.0" @@ -666,17 +953,17 @@ files = [ [[package]] name = "urllib3" -version = "1.26.16" +version = "1.26.18" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, - {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, + {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, + {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] @@ -759,6 +1046,23 @@ files = [ {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"}, ] +[[package]] +name = "werkzeug" +version = "3.0.0" +description = "The comprehensive WSGI web application library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "werkzeug-3.0.0-py3-none-any.whl", hash = "sha256:cbb2600f7eabe51dbc0502f58be0b3e1b96b893b05695ea2b35b43d4de2d9962"}, + {file = "werkzeug-3.0.0.tar.gz", hash = "sha256:3ffff4dcc32db52ef3cc94dff3000a3c2846890f3a5a51800a27b909c5e770f0"}, +] + +[package.dependencies] +MarkupSafe = ">=2.1.1" + +[package.extras] +watchdog = ["watchdog (>=2.3)"] + [[package]] name = "wheel" version = "0.41.2" @@ -857,7 +1161,22 @@ files = [ {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, ] +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "17535ed556dda51c20b5213388608d635ea12b12f63e159c35c1336b1552165d" +content-hash = "f8cfb92007668cf04d9b2fc268cd2df81043a37e8648b0578944fb72c0049ffe" diff --git a/pylint.sh b/pylint.sh deleted file mode 100755 index 9e30c68..0000000 --- a/pylint.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -poetry run pylint --rcfile=pylintrc jellyfish tests diff --git a/pyproject.toml b/pyproject.toml index 5baaad0..7cf6807 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,11 +21,21 @@ betterproto = "2.0.0b6" [tool.poetry.group.dev.dependencies] pdoc = "^14.1.0" pylint = "^2.17.6" +betterproto = { version = "= 2.0.0b6", extras = ["compiler"] } +black = "^23.10.0" [tool.poetry.group.test.dependencies] pytest = "^7.4.2" pytest-asyncio = "^0.21.1" +flask = "^3.0.0" +requests = "^2.31.0" [build-system] 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" diff --git a/test_commands.py b/test_commands.py new file mode 100644 index 0000000..829be55 --- /dev/null +++ b/test_commands.py @@ -0,0 +1,29 @@ +import os +import sys + + +def check_exit_code(command): + command_exit_code = os.system(command) + if command_exit_code != 0: + sys.exit(command_exit_code >> 8) + + +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" + ) + 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 .") + + +def run_linter(): + check_exit_code("poetry run pylint --rcfile=pylintrc jellyfish tests") diff --git a/tests/support/asyncio_utils.py b/tests/support/asyncio_utils.py index acf10d4..f0844f9 100644 --- a/tests/support/asyncio_utils.py +++ b/tests/support/asyncio_utils.py @@ -4,7 +4,7 @@ from jellyfish import Notifier -ASSERTION_TIMEOUT = 2. +ASSERTION_TIMEOUT = 2.0 async def assert_events(notifier: Notifier, event_checks: list): @@ -31,7 +31,8 @@ def handle_message(message): await asyncio.wait_for(success_event.wait(), ASSERTION_TIMEOUT) except asyncio.exceptions.TimeoutError as exc: raise asyncio.exceptions.TimeoutError( - f"{message_checks[0]} hasn't been received within timeout") from exc + f"{message_checks[0]} hasn't been received within timeout" + ) from exc async def cancel(task): diff --git a/tests/support/peer_socket.py b/tests/support/peer_socket.py index b7abf5c..14f2f86 100644 --- a/tests/support/peer_socket.py +++ b/tests/support/peer_socket.py @@ -7,7 +7,10 @@ from websockets.exceptions import ConnectionClosedOK from tests.support.protos.jellyfish import ( - PeerMessage, PeerMessageAuthRequest, PeerMessageAuthenticated) + PeerMessage, + PeerMessageAuthRequest, + PeerMessageAuthenticated, +) class PeerSocket: @@ -18,8 +21,9 @@ def __init__(self, server_address): self._ready_event = None async def connect(self, token): - async with client.connect(f'ws://{self._server_address}/socket/peer/websocket') \ - as websocket: + async with client.connect( + f"ws://{self._server_address}/socket/peer/websocket" + ) as websocket: msg = PeerMessage(auth_request=PeerMessageAuthRequest(token=token)) await websocket.send(bytes(msg)) @@ -30,7 +34,7 @@ async def connect(self, token): message = PeerMessage().parse(message) - _type, message = betterproto.which_one_of(message, 'content') + _type, message = betterproto.which_one_of(message, "content") assert isinstance(message, PeerMessageAuthenticated) self._ready = True diff --git a/tests/support/protos/jellyfish.py b/tests/support/protos/jellyfish.py deleted file mode 100644 index 67176f5..0000000 --- a/tests/support/protos/jellyfish.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: protos/jellyfish/peer_notifications.proto -# plugin: python-betterproto -from dataclasses import dataclass - -import betterproto - - -@dataclass -class PeerMessage(betterproto.Message): - authenticated: "PeerMessageAuthenticated" = betterproto.message_field( - 1, group="content" - ) - auth_request: "PeerMessageAuthRequest" = betterproto.message_field( - 2, group="content" - ) - media_event: "PeerMessageMediaEvent" = betterproto.message_field(3, group="content") - - -@dataclass -class PeerMessageAuthenticated(betterproto.Message): - pass - - -@dataclass -class PeerMessageAuthRequest(betterproto.Message): - token: str = betterproto.string_field(1) - - -@dataclass -class PeerMessageMediaEvent(betterproto.Message): - data: str = betterproto.string_field(1) diff --git a/tests/support/webhook_notifier.py b/tests/support/webhook_notifier.py new file mode 100644 index 0000000..8c1c078 --- /dev/null +++ b/tests/support/webhook_notifier.py @@ -0,0 +1,27 @@ +# 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 jellyfish import receive_json + +app = Flask(__name__) +DATA_QUEUE = None + + +@app.route("/", methods=["GET"]) +def respond_default(): + return Response(status=200) + + +@app.route("/webhook", methods=["POST"]) +def respond_root(): + json = request.get_json() + json = receive_json(json) + DATA_QUEUE.put(json) + + return Response(status=200) + + +def run_server(queue): + global DATA_QUEUE + DATA_QUEUE = queue + app.run(port=5000, host="0.0.0.0", use_reloader=False, debug=False, threaded=True) diff --git a/tests/test_notifier.py b/tests/test_notifier.py index ebe9170..519a207 100644 --- a/tests/test_notifier.py +++ b/tests/test_notifier.py @@ -2,28 +2,63 @@ import os import asyncio +import socket +import time +from multiprocessing import Process, Queue +import requests import pytest from jellyfish import Notifier, RoomApi, PeerOptionsWebRTC -from jellyfish.events import (ServerMessageRoomCreated, ServerMessageRoomDeleted, - ServerMessagePeerConnected, ServerMessagePeerDisconnected, - ServerMessageMetricsReport) +from jellyfish.events import ( + ServerMessageRoomCreated, + ServerMessageRoomDeleted, + ServerMessagePeerConnected, + ServerMessagePeerDisconnected, + ServerMessageMetricsReport, +) from tests.support.peer_socket import PeerSocket from tests.support.asyncio_utils import assert_events, assert_metrics, cancel +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' +HOST = "jellyfish" if os.getenv("DOCKER_TEST") == "TRUE" else "localhost" +SERVER_ADDRESS = f"{HOST}:5002" +SERVER_API_TOKEN = "development" +WEBHOOK_ADDRESS = "test" if os.getenv("DOCKER_TEST") == "TRUE" else "localhost" +WEBHOOK_URL = f"http://{WEBHOOK_ADDRESS}:5000/webhook" +queue = Queue() + + +@pytest.fixture(scope="session", autouse=True) +def start_server(): + flask_process = Process(target=run_server, args=(queue,)) + flask_process.start() + + timeout = 60 # wait maximum of 60 seconds + while True: + try: + response = requests.get(f"http://{WEBHOOK_ADDRESS}:5000/", timeout=1_000) + if response.status_code == 200: # Or another condition + break + except (requests.ConnectionError, socket.error): + time.sleep(1) # wait for 1 second before trying again + timeout -= 1 + if timeout == 0: + pytest.fail("Server did not start in the expected time") + + yield # This is where the testing happens. + + flask_process.terminate() class TestConnectingToServer: @pytest.mark.asyncio async def test_valid_credentials(self): - notifier = Notifier(server_address=SERVER_ADDRESS, - server_api_token=SERVER_API_TOKEN) + notifier = Notifier( + server_address=SERVER_ADDRESS, server_api_token=SERVER_API_TOKEN + ) notifier_task = asyncio.create_task(notifier.connect()) await notifier.wait_ready() @@ -34,8 +69,9 @@ async def test_valid_credentials(self): @pytest.mark.asyncio async def test_invalid_credentials(self): - notifier = Notifier(server_address=SERVER_ADDRESS, - server_api_token='wrong_token') + notifier = Notifier( + server_address=SERVER_ADDRESS, server_api_token="wrong_token" + ) task = asyncio.create_task(notifier.connect()) @@ -56,33 +92,72 @@ def notifier(): class TestReceivingNotifications: @pytest.mark.asyncio async def test_room_created_deleted(self, room_api: RoomApi, notifier: Notifier): + event_checks = [ServerMessageRoomCreated, ServerMessageRoomDeleted] + assert_task = asyncio.create_task(assert_events(notifier, event_checks.copy())) + + notifier_task = asyncio.create_task(notifier.connect()) + await notifier.wait_ready() + + _, room = room_api.create_room(webhook_url=WEBHOOK_URL) + + room_api.delete_room(room.id) + + await assert_task + await cancel(notifier_task) + + for event in event_checks: + self.assert_event(event) + + @pytest.mark.asyncio + async def test_peer_connected_disconnected( + self, room_api: RoomApi, notifier: Notifier + ): event_checks = [ ServerMessageRoomCreated, - ServerMessageRoomDeleted + ServerMessagePeerConnected, + ServerMessagePeerDisconnected, + ServerMessageRoomDeleted, ] - assert_task = asyncio.create_task(assert_events(notifier, event_checks)) + assert_task = asyncio.create_task(assert_events(notifier, event_checks.copy())) notifier_task = asyncio.create_task(notifier.connect()) await notifier.wait_ready() - _, room = room_api.create_room() + _, room = room_api.create_room(webhook_url=WEBHOOK_URL) + + peer_token, peer = room_api.add_peer(room.id, options=PeerOptionsWebRTC()) + + peer_socket = PeerSocket(server_address=SERVER_ADDRESS) + peer_task = asyncio.create_task(peer_socket.connect(peer_token)) + + await peer_socket.wait_ready() + + room_api.delete_peer(room.id, peer.id) + room_api.delete_room(room.id) await assert_task + await cancel(peer_task) await cancel(notifier_task) + for event in event_checks: + self.assert_event(event) + @pytest.mark.asyncio - async def test_peer_connected_disconnected(self, room_api: RoomApi, notifier: Notifier): + async def test_peer_connected_room_deleted( + self, room_api: RoomApi, notifier: Notifier + ): event_checks = [ + ServerMessageRoomCreated, ServerMessagePeerConnected, - ServerMessagePeerDisconnected + ServerMessageRoomDeleted, ] - assert_task = asyncio.create_task(assert_events(notifier, event_checks)) + assert_task = asyncio.create_task(assert_events(notifier, event_checks.copy())) notifier_task = asyncio.create_task(notifier.connect()) await notifier.wait_ready() - _, room = room_api.create_room() + _, room = room_api.create_room(webhook_url=WEBHOOK_URL) peer_token, _peer = room_api.add_peer(room.id, options=PeerOptionsWebRTC()) peer_socket = PeerSocket(server_address=SERVER_ADDRESS) @@ -96,6 +171,13 @@ async def test_peer_connected_disconnected(self, room_api: RoomApi, notifier: No await cancel(peer_task) await cancel(notifier_task) + for event in event_checks: + self.assert_event(event) + + def assert_event(self, event): + data = queue.get(timeout=2.5) + assert data == event or isinstance(data, event) + class TestReceivingMetrics: @pytest.mark.asyncio @@ -108,7 +190,9 @@ async def test_metrics_with_one_peer(self, room_api: RoomApi, notifier: Notifier await peer_socket.wait_ready() - assert_task = asyncio.create_task(assert_metrics(notifier, [ServerMessageMetricsReport])) + assert_task = asyncio.create_task( + assert_metrics(notifier, [ServerMessageMetricsReport]) + ) notifier_task = asyncio.create_task(notifier.connect()) await assert_task diff --git a/tests/test_room_api.py b/tests/test_room_api.py index d230c6d..fda6b3f 100644 --- a/tests/test_room_api.py +++ b/tests/test_room_api.py @@ -14,31 +14,34 @@ from jellyfish import UnauthorizedException, NotFoundException -HOST = 'jellyfish' if os.getenv('DOCKER_TEST') == 'TRUE' else 'localhost' -SERVER_ADDRESS = f'{HOST}:5002' -SERVER_API_TOKEN = 'development' +HOST = "jellyfish" if os.getenv("DOCKER_TEST") == "TRUE" else "localhost" +SERVER_ADDRESS = f"{HOST}:5002" +SERVER_API_TOKEN = "development" MAX_PEERS = 10 -CODEC_H264 = 'h264' -PEER_WEBRTC = 'webrtc' +CODEC_H264 = "h264" +PEER_WEBRTC = "webrtc" -COMPONENT_HLS = 'hls' -COMPONENT_RTSP = 'rtsp' +COMPONENT_HLS = "hls" +COMPONENT_RTSP = "rtsp" HLS_OPTIONS = ComponentOptionsHLS() RTSP_OPTIONS = ComponentOptionsRTSP( - sourceUri='rtsp://ef36c6dff23ecc5bbe311cc880d95dc8.se:2137/does/not/matter') + sourceUri="rtsp://ef36c6dff23ecc5bbe311cc880d95dc8.se:2137/does/not/matter" +) class TestAuthentication: def test_invalid_token(self): - room_api = RoomApi(server_address=SERVER_ADDRESS, server_api_token='invalid') + room_api = RoomApi(server_address=SERVER_ADDRESS, server_api_token="invalid") with pytest.raises(UnauthorizedException): room_api.create_room() def test_valid_token(self): - room_api = RoomApi(server_address=SERVER_ADDRESS, server_api_token=SERVER_API_TOKEN) + room_api = RoomApi( + server_address=SERVER_ADDRESS, server_api_token=SERVER_API_TOKEN + ) _, room = room_api.create_room() @@ -65,16 +68,24 @@ class TestCreateRoom: def test_no_params(self, room_api): _, room = room_api.create_room() - assert room == Room(components=[], config=RoomConfig(max_peers=None, video_codec=None), - id=room.id, peers=[]) + assert room == Room( + components=[], + config=RoomConfig(max_peers=None, video_codec=None), + id=room.id, + peers=[], + ) 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) - assert room == Room(components=[], config=RoomConfig( - max_peers=MAX_PEERS, video_codec=CODEC_H264), id=room.id, peers=[]) + assert room == Room( + components=[], + config=RoomConfig(max_peers=MAX_PEERS, video_codec=CODEC_H264), + id=room.id, + peers=[], + ) assert room in room_api.get_all_rooms() def test_invalid_max_peers(self, room_api): @@ -111,8 +122,12 @@ class TestGetRoom: def test_valid(self, room_api: RoomApi): _, room = room_api.create_room() - assert Room(components=[], peers=[], id=room.id, config=RoomConfig( - maxPeers=None, videoCodec=None)) == room_api.get_room(room.id) + assert Room( + components=[], + peers=[], + id=room.id, + config=RoomConfig(maxPeers=None, videoCodec=None), + ) == room_api.get_room(room.id) def test_invalid(self, room_api: RoomApi): with pytest.raises(NotFoundException): @@ -155,12 +170,12 @@ def test_invalid_component(self, room_api: RoomApi): _, room = room_api.create_room() with pytest.raises(NotFoundException): - room_api.delete_component(room.id, 'invalid_id') + room_api.delete_component(room.id, "invalid_id") class TestAddPeer: def _assert_peer_created(self, room_api, peer, room_id): - assert peer.status == 'disconnected' + assert peer.status == "disconnected" assert peer.type == PEER_WEBRTC room = room_api.get_room(room_id) @@ -169,7 +184,9 @@ def _assert_peer_created(self, room_api, peer, room_id): 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)) + _token, peer = room_api.add_peer( + room.id, options=PeerOptionsWebRTC(enableSimulcast=True) + ) self._assert_peer_created(room_api, peer, room.id) @@ -184,7 +201,9 @@ def test_default_options(self, room_api: RoomApi): 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)) + _, peer = room_api.add_peer( + room.id, options=PeerOptionsWebRTC(enableSimulcast=True) + ) room_api.delete_peer(room.id, peer.id) @@ -194,4 +213,4 @@ def test_invalid(self, room_api: RoomApi): _, room = room_api.create_room() with pytest.raises(NotFoundException): - room_api.delete_peer(room.id, peer_id='invalid_peer_id') + room_api.delete_peer(room.id, peer_id="invalid_peer_id")