diff --git a/sinch/core/adapters/asyncio_http_adapter.py b/sinch/core/adapters/asyncio_http_adapter.py index a34d6613..458b1c55 100644 --- a/sinch/core/adapters/asyncio_http_adapter.py +++ b/sinch/core/adapters/asyncio_http_adapter.py @@ -17,13 +17,18 @@ async def request(self, endpoint: HTTPEndpoint) -> SinchBaseModel: f" to URL: {request_data_with_auth.url}" ) + if request_data_with_auth.auth: + auth_data = aiohttp.BasicAuth(request_data_with_auth.auth[0], request_data_with_auth.auth[1]) + else: + auth_data = None + async with aiohttp.ClientSession() as session: async with session.request( method=request_data_with_auth.http_method, headers=request_data_with_auth.headers, url=request_data_with_auth.url, data=request_data_with_auth.request_body, - auth=request_data_with_auth.auth, + auth=auth_data, params=request_data_with_auth.query_params, timeout=aiohttp.ClientTimeout( total=self.sinch.configuration.connection_timeout diff --git a/sinch/core/adapters/requests_http_transport.py b/sinch/core/adapters/requests_http_transport.py index e2a37a72..3b389a60 100644 --- a/sinch/core/adapters/requests_http_transport.py +++ b/sinch/core/adapters/requests_http_transport.py @@ -1,5 +1,6 @@ import requests import json +from typing import cast from sinch.core.ports.http_transport import HTTPTransport, HttpRequest from sinch.core.endpoint import HTTPEndpoint from sinch.core.models.http_response import HTTPResponse @@ -14,7 +15,7 @@ def __init__(self, sinch: ClientBase): def request(self, endpoint: HTTPEndpoint) -> SinchBaseModel: request_data: HttpRequest = self.prepare_request(endpoint) - request_data_with_auth: HttpRequest = self.authenticate(endpoint, request_data) + request_data_with_auth = cast(HttpRequest, self.authenticate(endpoint, request_data)) self.sinch.configuration.logger.debug( f"Sync HTTP {request_data_with_auth.http_method} call with headers:" @@ -41,11 +42,11 @@ def request(self, endpoint: HTTPEndpoint) -> SinchBaseModel: f"and body: {response_body} from URL: {request_data_with_auth.url}" ) - return self.handle_response( + return cast(SinchBaseModel, self.handle_response( endpoint=endpoint, http_response=HTTPResponse( status_code=response.status_code, body=response_body, headers=dict(response.headers) ) - ) + )) diff --git a/sinch/core/endpoint.py b/sinch/core/endpoint.py index 0b36d4ec..9415bcfb 100644 --- a/sinch/core/endpoint.py +++ b/sinch/core/endpoint.py @@ -1,7 +1,6 @@ from abc import ABC, abstractmethod from sinch.core.models.http_response import HTTPResponse -from sinch.core.models.http_request import HttpRequest -from sinch.core.models.base_model import SinchBaseModel +from sinch.core.models.base_model import SinchBaseModel, SinchRequestBaseModel from sinch.core.enums import HTTPAuthentication, HTTPMethod from typing import TYPE_CHECKING @@ -13,8 +12,10 @@ class HTTPEndpoint(ABC): ENDPOINT_URL: str HTTP_METHOD: HTTPMethod HTTP_AUTHENTICATION: HTTPAuthentication + project_id: str + request_data: SinchRequestBaseModel - def __init__(self, project_id: str, request_data: 'HttpRequest'): + def __init__(self, project_id: str, request_data: SinchRequestBaseModel): pass def build_url(self, sinch: 'ClientBase') -> str: diff --git a/sinch/core/models/http_request.py b/sinch/core/models/http_request.py index d824e42a..12a9f747 100644 --- a/sinch/core/models/http_request.py +++ b/sinch/core/models/http_request.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from typing import Optional @dataclass @@ -9,4 +10,4 @@ class HttpRequest: http_method: str request_body: dict query_params: dict - auth: str + auth: Optional[tuple[str, str]] diff --git a/sinch/core/models/pagination.py b/sinch/core/models/pagination.py new file mode 100644 index 00000000..b1f5c468 --- /dev/null +++ b/sinch/core/models/pagination.py @@ -0,0 +1,25 @@ +from dataclasses import dataclass + +from sinch.core.models.base_model import SinchRequestBaseModel, SinchBaseModel + + +@dataclass +class TokenPaginatedRequest(SinchRequestBaseModel): + page_token: str + + +@dataclass +class IntPaginatedRequest(SinchRequestBaseModel): + page: int + page_size: int + + +@dataclass +class TokenPaginatedResponse(SinchBaseModel): + next_page_token: str + + +@dataclass +class IntPaginatedResponse(SinchBaseModel): + page: int + page_size: int diff --git a/sinch/core/pagination.py b/sinch/core/pagination.py index ff4495e8..f045cc97 100644 --- a/sinch/core/pagination.py +++ b/sinch/core/pagination.py @@ -1,7 +1,14 @@ from abc import ABC, abstractmethod from sinch.core.endpoint import HTTPEndpoint -from sinch.core.models.http_response import HTTPResponse -from typing import TYPE_CHECKING, Union +from typing import TYPE_CHECKING, Union, cast, Coroutine, Any +from sinch.core.models.base_model import SinchBaseModel +from sinch.core.models.pagination import ( + TokenPaginatedRequest, + TokenPaginatedResponse, + IntPaginatedRequest, + IntPaginatedResponse +) + if TYPE_CHECKING: from sinch.core.clients.sinch_client_base import ClientBase @@ -21,7 +28,12 @@ class Paginator(ABC): if paginated_response.has_next_page: paginated_response = paginated_response.next_page() """ - def __init__(self, sinch: 'ClientBase', endpoint: HTTPEndpoint, result: HTTPResponse): + def __init__( + self, + sinch: 'ClientBase', + endpoint: HTTPEndpoint, + result: Union[TokenPaginatedResponse, IntPaginatedResponse] + ): self._sinch = sinch self.result = result self.endpoint = endpoint @@ -36,7 +48,7 @@ def auto_paging_iter(self) -> Union['PageIterator', 'AsyncPageIterator']: pass @abstractmethod - def next_page(self) -> 'Paginator': + def next_page(self) -> Union['Paginator', Coroutine[Any, Any, 'Paginator']]: pass @abstractmethod @@ -45,7 +57,11 @@ def _calculate_next_page(self) -> None: @classmethod @abstractmethod - def _initialize(cls, sinch: 'ClientBase', endpoint: HTTPEndpoint) -> 'Paginator': + def _initialize( + cls, + sinch: 'ClientBase', + endpoint: HTTPEndpoint + ) -> Union['Paginator', Coroutine[Any, Any, 'Paginator']]: pass @@ -58,7 +74,10 @@ def __iter__(self) -> 'PageIterator': def __next__(self) -> Paginator: if self.paginator.has_next_page: - return self.paginator.next_page() + return cast( + Paginator, + self.paginator.next_page() + ) else: raise StopIteration @@ -70,14 +89,18 @@ def __init__(self, paginator: Paginator): def __aiter__(self) -> 'AsyncPageIterator': return self - async def __anext__(self): + async def __anext__(self) -> Paginator: if self.paginator.has_next_page: - return await self.paginator.next_page() + return await cast( + Coroutine[Any, Any, Paginator], + self.paginator.next_page() + ) else: raise StopAsyncIteration class IntBasedPaginator(Paginator): + result: IntPaginatedResponse __doc__ = Paginator.__doc__ def _calculate_next_page(self) -> None: @@ -86,27 +109,39 @@ def _calculate_next_page(self) -> None: else: self.has_next_page = False - def next_page(self): - self.endpoint.request_data.page += 1 - self.result = self._sinch.configuration.transport.request(self.endpoint) + def next_page(self) -> Union['Paginator', Coroutine[Any, Any, 'Paginator']]: + cast(IntPaginatedRequest, self.endpoint.request_data).page += 1 + self.result = cast( + IntPaginatedResponse, + self._sinch.configuration.transport.request(self.endpoint) + ) self._calculate_next_page() return self - def auto_paging_iter(self) -> PageIterator: + def auto_paging_iter(self) -> Union['PageIterator', 'AsyncPageIterator']: return PageIterator(self) @classmethod - def _initialize(cls, sinch: 'ClientBase', endpoint: HTTPEndpoint) -> 'IntBasedPaginator': + def _initialize( + cls, + sinch: 'ClientBase', + endpoint: HTTPEndpoint + ) -> Union['Paginator', Coroutine[Any, Any, 'Paginator']]: + result = sinch.configuration.transport.request(endpoint) - return cls(sinch, endpoint, result) + return cls(sinch, endpoint, cast(IntPaginatedResponse, result)) class AsyncIntBasedPaginator(IntBasedPaginator): __doc__ = IntBasedPaginator.__doc__ - - async def next_page(self) -> 'AsyncIntBasedPaginator': - self.endpoint.request_data.page += 1 - self.result = await self._sinch.configuration.transport.request(self.endpoint) + result: IntPaginatedResponse + + async def next_page(self) -> 'Paginator': + cast(IntPaginatedRequest, self.endpoint.request_data).page += 1 + self.result = await cast( + Coroutine[Any, Any, IntPaginatedResponse], + self._sinch.configuration.transport.request(self.endpoint) + ) self._calculate_next_page() return self @@ -114,13 +149,17 @@ def auto_paging_iter(self) -> AsyncPageIterator: return AsyncPageIterator(self) @classmethod - async def _initialize(cls, sinch: 'ClientBase', endpoint: HTTPEndpoint) -> 'AsyncIntBasedPaginator': - result = await sinch.configuration.transport.request(endpoint) + async def _initialize(cls, sinch: 'ClientBase', endpoint: HTTPEndpoint) -> 'Paginator': + result = await cast( + Coroutine[Any, Any, IntPaginatedResponse], + sinch.configuration.transport.request(endpoint) + ) return cls(sinch, endpoint, result) class TokenBasedPaginator(Paginator): __doc__ = Paginator.__doc__ + result: TokenPaginatedResponse def _calculate_next_page(self) -> None: if self.result.next_page_token: @@ -128,27 +167,36 @@ def _calculate_next_page(self) -> None: else: self.has_next_page = False - def next_page(self) -> 'TokenBasedPaginator': - self.endpoint.request_data.page_token = self.result.next_page_token - self.result = self._sinch.configuration.transport.request(self.endpoint) + def next_page(self) -> Union['TokenBasedPaginator', Coroutine[Any, Any, 'AsyncTokenBasedPaginator']]: + cast(TokenPaginatedRequest, self.endpoint.request_data).page_token = self.result.next_page_token + self.result = cast(TokenPaginatedResponse, self._sinch.configuration.transport.request(self.endpoint)) self._calculate_next_page() return self - def auto_paging_iter(self) -> PageIterator: + def auto_paging_iter(self) -> Union[PageIterator, AsyncPageIterator]: return PageIterator(self) @classmethod - def _initialize(cls, sinch: 'ClientBase', endpoint: HTTPEndpoint) -> 'TokenBasedPaginator': + def _initialize( + cls, + sinch: 'ClientBase', + endpoint: HTTPEndpoint + ) -> Union['Paginator', Coroutine[Any, Any, 'Paginator']]: + result = sinch.configuration.transport.request(endpoint) - return cls(sinch, endpoint, result) + return cls(sinch, endpoint, cast(TokenPaginatedResponse, result)) class AsyncTokenBasedPaginator(TokenBasedPaginator): __doc__ = TokenBasedPaginator.__doc__ + result: TokenPaginatedResponse async def next_page(self) -> 'AsyncTokenBasedPaginator': - self.endpoint.request_data.page_token = self.result.next_page_token - self.result = await self._sinch.configuration.transport.request(self.endpoint) + cast(TokenPaginatedRequest, self.endpoint.request_data).page_token = self.result.next_page_token + self.result = await cast( + Coroutine[Any, Any, TokenPaginatedResponse], + self._sinch.configuration.transport.request(self.endpoint) + ) self._calculate_next_page() return self @@ -157,5 +205,8 @@ def auto_paging_iter(self) -> AsyncPageIterator: @classmethod async def _initialize(cls, sinch: 'ClientBase', endpoint: HTTPEndpoint) -> 'AsyncTokenBasedPaginator': - result = await sinch.configuration.transport.request(endpoint) + result = await cast( + Coroutine[Any, Any, TokenPaginatedResponse], + sinch.configuration.transport.request(endpoint) + ) return cls(sinch, endpoint, result) diff --git a/sinch/core/ports/http_transport.py b/sinch/core/ports/http_transport.py index a3358675..6766e666 100644 --- a/sinch/core/ports/http_transport.py +++ b/sinch/core/ports/http_transport.py @@ -1,6 +1,5 @@ -import aiohttp from abc import ABC, abstractmethod -from typing import Optional, TYPE_CHECKING, Union, Any, Coroutine +from typing import TYPE_CHECKING, Union, Any, Coroutine, cast from sinch.core.endpoint import HTTPEndpoint from sinch.core.models.http_request import HttpRequest from sinch.core.models.http_response import HTTPResponse @@ -20,7 +19,12 @@ def __init__(self, sinch: 'ClientBase'): def request(self, endpoint: HTTPEndpoint) -> Union[SinchBaseModel, Coroutine[Any, Any, SinchBaseModel]]: pass - def authenticate(self, endpoint: HTTPEndpoint, request_data: HttpRequest) -> HttpRequest: + def authenticate( + self, + endpoint: HTTPEndpoint, + request_data: HttpRequest + ) -> Union[HttpRequest, Coroutine[Any, Any, HttpRequest]]: + if endpoint.HTTP_AUTHENTICATION == HTTPAuthentication.BASIC.value: request_data.auth = (self.sinch.configuration.key_id, self.sinch.configuration.key_secret) else: @@ -46,14 +50,18 @@ def prepare_request(self, endpoint: HTTPEndpoint) -> HttpRequest: http_method=endpoint.HTTP_METHOD.value, request_body=endpoint.request_body(), query_params=url_query_params, - auth=() + auth=None ) - def handle_response(self, endpoint: HTTPEndpoint, http_response: HTTPResponse) -> SinchBaseModel: + def handle_response( + self, + endpoint: HTTPEndpoint, + http_response: HTTPResponse + ) -> Union[SinchBaseModel, Coroutine[Any, Any, SinchBaseModel]]: if http_response.status_code == 401: self.sinch.configuration.token_manager.handle_invalid_token(http_response) if self.sinch.configuration.token_manager.token_state == TokenState.EXPIRED: - return self.request(endpoint=endpoint) + return self.request(endpoint=endpoint) # type: ignore return endpoint.handle_response(http_response) @@ -61,7 +69,7 @@ def handle_response(self, endpoint: HTTPEndpoint, http_response: HTTPResponse) - class AsyncHTTPTransport(HTTPTransport): async def authenticate(self, endpoint: HTTPEndpoint, request_data: HttpRequest) -> HttpRequest: if endpoint.HTTP_AUTHENTICATION == HTTPAuthentication.BASIC: - request_data.auth = aiohttp.BasicAuth(self.sinch.configuration.key_id, self.sinch.configuration.key_secret) + request_data.auth = (self.sinch.configuration.key_id, self.sinch.configuration.key_secret) else: request_data.auth = None @@ -78,6 +86,6 @@ async def handle_response(self, endpoint: HTTPEndpoint, http_response: HTTPRespo if http_response.status_code == 401: self.sinch.configuration.token_manager.handle_invalid_token(http_response) if self.sinch.configuration.token_manager.token_state == TokenState.EXPIRED: - return await self.request(endpoint=endpoint) + return await cast(Coroutine[Any, Any, SinchBaseModel], self.request(endpoint=endpoint)) return endpoint.handle_response(http_response) diff --git a/sinch/core/token_manager.py b/sinch/core/token_manager.py index 4cbc7098..2c5a656d 100644 --- a/sinch/core/token_manager.py +++ b/sinch/core/token_manager.py @@ -1,11 +1,12 @@ from enum import Enum from abc import ABC, abstractmethod -from typing import Optional, TYPE_CHECKING, Union, Any, Coroutine +from typing import Optional, TYPE_CHECKING, Union, Any, Coroutine, cast from sinch.domains.authentication.models.authentication import OAuthToken from sinch.domains.authentication.endpoints.oauth import OAuthEndpoint from sinch.core.exceptions import ValidationException from sinch.core.models.http_response import HTTPResponse +from sinch.core.models.base_model import SinchBaseModel if TYPE_CHECKING: from sinch.core.clients.sinch_client_base import ClientBase @@ -52,7 +53,7 @@ def get_auth_token(self) -> Optional[OAuthToken]: if self.token: return self.token - auth_response = self.sinch.configuration.transport.request(OAuthEndpoint()) + auth_response = cast(SinchBaseModel, self.sinch.configuration.transport.request(OAuthEndpoint())) self.token = OAuthToken(**auth_response.as_dict()) self.token_state = TokenState.VALID @@ -64,7 +65,10 @@ async def get_auth_token(self) -> Optional[OAuthToken]: if self.token: return self.token - auth_response = await self.sinch.configuration.transport.request(OAuthEndpoint()) + auth_response = await cast( + Coroutine[Any, Any, SinchBaseModel], + self.sinch.configuration.transport.request(OAuthEndpoint()) + ) self.token = OAuthToken(**auth_response.as_dict()) self.token_state = TokenState.VALID diff --git a/sinch/domains/conversation/__init__.py b/sinch/domains/conversation/__init__.py index 62f823dd..bd995e6b 100644 --- a/sinch/domains/conversation/__init__.py +++ b/sinch/domains/conversation/__init__.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Optional from sinch.core.pagination import TokenBasedPaginator, AsyncTokenBasedPaginator @@ -174,14 +174,14 @@ def send( app_id: str, recipient: dict, message: dict, - callback_url: str = None, + callback_url: Optional[str] = None, channel_priority_order: list = None, - channel_properties: dict = None, - message_metadata: str = None, - conversation_metadata: dict = None, - queue: str = None, - ttl: str = None, - processing_strategy: str = None + channel_properties: Optional[dict] = None, + message_metadata: Optional[str] = None, + conversation_metadata: Optional[dict] = None, + queue: Optional[str] = None, + ttl: Optional[str] = None, + processing_strategy: Optional[str] = None ) -> SendConversationMessageResponse: return self._sinch.configuration.transport.request( SendConversationMessageEndpoint( @@ -205,7 +205,7 @@ def send( def get( self, message_id: str, - messages_source: str = None + messages_source: Optional[str] = None ) -> GetConversationMessageResponse: return self._sinch.configuration.transport.request( GetConversationMessageEndpoint( @@ -220,7 +220,7 @@ def get( def delete( self, message_id: str, - messages_source: str = None + messages_source: Optional[str] = None ) -> DeleteConversationMessageResponse: return self._sinch.configuration.transport.request( DeleteConversationMessageEndpoint( @@ -234,15 +234,15 @@ def delete( def list( self, - conversation_id: str = None, - contact_id: str = None, - app_id: str = None, - page_size: int = None, - page_token: str = None, - view: str = None, - messages_source: str = None, - only_recipient_originated: bool = None - ) -> ListConversationMessagesResponse: + conversation_id: Optional[str] = None, + contact_id: Optional[str] = None, + app_id: Optional[str] = None, + page_size: Optional[bool] = None, + page_token: Optional[str] = None, + view: Optional[str] = None, + messages_source: Optional[str] = None, + only_recipient_originated: Optional[bool] = None + ) -> TokenBasedPaginator: return TokenBasedPaginator._initialize( sinch=self._sinch, endpoint=ListConversationMessagesEndpoint( @@ -264,15 +264,15 @@ def list( class ConversationMessageWithAsyncPagination(ConversationMessage): async def list( self, - conversation_id: str = None, - contact_id: str = None, - app_id: str = None, - page_size: int = None, - page_token: str = None, - view: str = None, - messages_source: str = None, - only_recipient_originated: bool = None - ) -> ListConversationMessagesResponse: + conversation_id: Optional[str] = None, + contact_id: Optional[str] = None, + app_id: Optional[str] = None, + page_size: Optional[bool] = None, + page_token: Optional[str] = None, + view: Optional[str] = None, + messages_source: Optional[str] = None, + only_recipient_originated: Optional[bool] = None + ) -> AsyncTokenBasedPaginator: return await AsyncTokenBasedPaginator._initialize( sinch=self._sinch, endpoint=ListConversationMessagesEndpoint( @@ -299,10 +299,10 @@ def create( self, display_name: str, channel_credentials: list, - conversation_metadata_report_view: str = None, - retention_policy: dict = None, - dispatch_retention_policy: dict = None, - processing_mode: str = None + conversation_metadata_report_view: Optional[str] = None, + retention_policy: Optional[dict] = None, + dispatch_retention_policy: Optional[dict] = None, + processing_mode: Optional[str] = None ) -> CreateConversationAppResponse: """ Creates a new Conversation API app with one or more configured channels. @@ -397,13 +397,13 @@ def __init__(self, sinch): def update( self, contact_id: str, - channel_identities: List[SinchConversationChannelIdentities] = None, - language: str = None, - display_name: str = None, - email: str = None, - external_id: str = None, - metadata: str = None, - channel_priority: list = None + channel_identities: Optional[List[SinchConversationChannelIdentities]] = None, + language: Optional[str] = None, + display_name: Optional[str] = None, + email: Optional[str] = None, + external_id: Optional[str] = None, + metadata: Optional[str] = None, + channel_priority: Optional[list] = None ) -> UpdateConversationContactResponse: """ Updates an existing Conversation API contact with new configuration options defined in the request. @@ -429,11 +429,11 @@ def create( self, channel_identities: List[SinchConversationChannelIdentities], language: str, - display_name: str = None, - email: str = None, - external_id: str = None, - metadata: str = None, - channel_priority: list = None + display_name: Optional[str] = None, + email: Optional[str] = None, + external_id: Optional[str] = None, + metadata: Optional[str] = None, + channel_priority: Optional[list] = None ) -> CreateConversationContactResponse: """ Creates a new Conversation API contact. @@ -483,12 +483,12 @@ def get(self, contact_id: str) -> GetConversationContactResponse: def list( self, - page_size: int = None, - page_token: str = None, - external_id: str = None, - channel: str = None, - identity: str = None - ) -> ListConversationContactsResponse: + page_size: Optional[bool] = None, + page_token: Optional[str] = None, + external_id: Optional[str] = None, + channel: Optional[str] = None, + identity: Optional[str] = None + ) -> TokenBasedPaginator: """ Lists all Conversation API contacts for the project identified by the project_id. Returns the information as an array of contact objects in the response. @@ -511,7 +511,7 @@ def merge( self, source_id: str, destination_id: str, - strategy: str = None + strategy: Optional[str] = None ) -> MergeConversationContactsResponse: """ Merges two existing Conversation API contacts. @@ -557,12 +557,12 @@ def get_channel_profile( class ConversationContactWithAsyncPagination(ConversationContact): async def list( self, - page_size: int = None, - page_token: str = None, - external_id: str = None, - channel: str = None, - identity: str = None - ) -> ListConversationContactsResponse: + page_size: Optional[bool] = None, + page_token: Optional[str] = None, + external_id: Optional[str] = None, + channel: Optional[str] = None, + identity: Optional[str] = None + ) -> AsyncTokenBasedPaginator: return await AsyncTokenBasedPaginator._initialize( sinch=self._sinch, endpoint=ListContactsEndpoint( @@ -587,10 +587,10 @@ def send( app_id: str, recipient: dict, event: dict, - callback_url: str = None, - channel_priority_order: str = None, - event_metadata: str = None, - queue: str = None + callback_url: Optional[str] = None, + channel_priority_order: Optional[str] = None, + event_metadata: Optional[str] = None, + queue: Optional[str] = None ) -> SendConversationEventResponse: return self._sinch.configuration.transport.request( SendEventEndpoint( @@ -617,8 +617,8 @@ def transcode_message( app_id: str, app_message: dict, channels: list, - from_: str = None, - to: str = None + from_: Optional[str] = None, + to: Optional[str] = None ) -> TranscodeConversationMessageResponse: return self._sinch.configuration.transport.request( TranscodeMessageEndpoint( @@ -643,8 +643,8 @@ def register( app_id: str, channels: list, recipient: dict, - request_id: str = None, - processing_strategy: str = None + request_id: Optional[str] = None, + processing_strategy: Optional[str] = None ) -> RegisterConversationOptInResponse: return self._sinch.configuration.transport.request( RegisterOptInEndpoint( @@ -669,8 +669,8 @@ def register( app_id: str, channels: list, recipient: dict, - request_id: str = None, - processing_strategy: str = None + request_id: Optional[str] = None, + processing_strategy: Optional[str] = None ) -> RegisterConversationOptOutResponse: return self._sinch.configuration.transport.request( RegisterOptOutEndpoint( @@ -694,7 +694,7 @@ def query( self, app_id: str, recipient: dict, - request_id: str = None + request_id: Optional[str] = None ) -> QueryConversationCapabilityResponse: return self._sinch.configuration.transport.request( CapabilityQueryEndpoint( @@ -716,11 +716,11 @@ def create( self, translations: list, default_translation: str, - channel: str = None, - create_time: str = None, - description: str = None, - id: str = None, - update_time: str = None + channel: Optional[str] = None, + create_time: Optional[str] = None, + description: Optional[str] = None, + id: Optional[str] = None, + update_time: Optional[str] = None ) -> CreateConversationTemplateResponse: return self._sinch.configuration.transport.request( CreateTemplateEndpoint( @@ -759,12 +759,12 @@ def update( template_id: str, translations: list, default_translation: str, - id: str = None, - update_mask: str = None, - channel: str = None, - create_time: str = None, - description: str = None, - update_time: str = None + id: Optional[str] = None, + update_mask: Optional[str] = None, + channel: Optional[str] = None, + create_time: Optional[str] = None, + description: Optional[str] = None, + update_time: Optional[str] = None ) -> UpdateConversationTemplateResponse: return self._sinch.configuration.transport.request( UpdateTemplateEndpoint( @@ -803,9 +803,9 @@ def create( app_id: str, target: str, triggers: list, - client_credentials: dict = None, - secret: str = None, - target_type: str = None + client_credentials: Optional[dict] = None, + secret: Optional[str] = None, + target_type: Optional[str] = None ) -> CreateWebhookResponse: return self._sinch.configuration.transport.request( CreateWebhookEndpoint( @@ -827,10 +827,10 @@ def update( app_id: str, target: str, triggers: list, - update_mask: str = None, - client_credentials: dict = None, - secret: str = None, - target_type: str = None + update_mask: Optional[str] = None, + client_credentials: Optional[dict] = None, + secret: Optional[str] = None, + target_type: Optional[str] = None ) -> UpdateWebhookResponse: return self._sinch.configuration.transport.request( UpdateWebhookEndpoint( @@ -885,13 +885,13 @@ def __init__(self, sinch): def create( self, - id: str = None, - metadata: str = None, - conversation_metadata: dict = None, - contact_id: str = None, - app_id: str = None, - active_channel: str = None, - active: bool = None, + id: Optional[str] = None, + metadata: Optional[str] = None, + conversation_metadata: Optional[dict] = None, + contact_id: Optional[str] = None, + app_id: Optional[str] = None, + active_channel: Optional[str] = None, + active: Optional[bool] = None, ) -> SinchCreateConversationResponse: return self._sinch.configuration.transport.request( CreateConversationEndpoint( @@ -911,11 +911,11 @@ def create( def list( self, only_active: bool, - page_size: int = None, - page_token: str = None, - app_id: str = None, - contact_id: str = None - ) -> SinchListConversationsResponse: + page_size: Optional[bool] = None, + page_token: Optional[str] = None, + app_id: Optional[str] = None, + contact_id: Optional[str] = None + ) -> TokenBasedPaginator: return TokenBasedPaginator._initialize( sinch=self._sinch, endpoint=ListConversationsEndpoint( @@ -953,14 +953,14 @@ def delete(self, conversation_id: str) -> SinchDeleteConversationResponse: def update( self, conversation_id: str, - update_mask: str = None, - metadata_update_strategy: str = None, - metadata: str = None, - conversation_metadata: dict = None, - contact_id: str = None, - app_id: str = None, - active_channel: str = None, - active: bool = None + update_mask: Optional[str] = None, + metadata_update_strategy: Optional[str] = None, + metadata: Optional[str] = None, + conversation_metadata: Optional[dict] = None, + contact_id: Optional[str] = None, + app_id: Optional[str] = None, + active_channel: Optional[str] = None, + active: Optional[bool] = None ) -> SinchUpdateConversationResponse: return self._sinch.configuration.transport.request( UpdateConversationEndpoint( @@ -992,13 +992,13 @@ def stop(self, conversation_id: str) -> SinchStopConversationResponse: def inject_message_to_conversation( self, conversation_id: str, - accept_time: str = None, - app_message: dict = None, - channel_identity: dict = None, - contact_id: str = None, - contact_message: dict = None, - direction: str = None, - metadata: str = None + accept_time: Optional[str] = None, + app_message: Optional[dict] = None, + channel_identity: Optional[dict] = None, + contact_id: Optional[str] = None, + contact_message: Optional[dict] = None, + direction: Optional[str] = None, + metadata: Optional[str] = None ) -> SinchInjectMessageResponse: return self._sinch.configuration.transport.request( InjectMessageToConversationEndpoint( @@ -1021,11 +1021,11 @@ class ConversationConversationWithAsyncPagination(ConversationConversation): async def list( self, only_active: bool, - page_size: int = None, - page_token: str = None, - app_id: str = None, - contact_id: str = None - ) -> SinchListConversationsResponse: + page_size: Optional[bool] = None, + page_token: Optional[str] = None, + app_id: Optional[str] = None, + contact_id: Optional[str] = None + ) -> AsyncTokenBasedPaginator: return await AsyncTokenBasedPaginator._initialize( sinch=self._sinch, endpoint=ListConversationsEndpoint( diff --git a/sinch/domains/numbers/__init__.py b/sinch/domains/numbers/__init__.py index 3b2673f1..5a950ae4 100644 --- a/sinch/domains/numbers/__init__.py +++ b/sinch/domains/numbers/__init__.py @@ -1,3 +1,4 @@ +from typing import Optional from sinch.core.pagination import TokenBasedPaginator, AsyncTokenBasedPaginator from sinch.domains.numbers.endpoints.available.search_for_number import SearchForNumberEndpoint from sinch.domains.numbers.endpoints.available.list_available_numbers import AvailableNumbersEndpoint @@ -39,10 +40,10 @@ def list( self, region_code: str, number_type: str, - number_pattern: str = None, - number_search_pattern: str = None, - capabilities: list = None, - page_size: int = None + number_pattern: Optional[str] = None, + number_search_pattern: Optional[str] = None, + capabilities: Optional[list] = None, + page_size: Optional[int] = None ) -> ListAvailableNumbersResponse: """ Search for available virtual numbers using a variety of parameters to filter results. @@ -65,8 +66,8 @@ def list( def activate( self, phone_number: str, - sms_configuration: dict = None, - voice_configuration: dict = None + sms_configuration: Optional[dict] = None, + voice_configuration: Optional[dict] = None ) -> ActivateNumberResponse: """ Activate a virtual number to use with SMS products, Voice products, or both. @@ -87,11 +88,11 @@ def rent_any( self, region_code: str, type_: str, - number_pattern: str = None, - capabilities: list = None, - sms_configuration: dict = None, - voice_configuration: dict = None, - callback_url: str = None + number_pattern: Optional[str] = None, + capabilities: Optional[list] = None, + sms_configuration: Optional[dict] = None, + voice_configuration: Optional[dict] = None, + callback_url: Optional[str] = None ) -> RentAnyNumberRequest: return self._sinch.configuration.transport.request( RentAnyNumberEndpoint( @@ -131,12 +132,12 @@ def list( self, region_code: str, number_type: str, - number_pattern: str = None, - number_search_pattern: str = None, - capabilities: list = None, - page_size: int = None, - page_token: str = None - ) -> ListActiveNumbersResponse: + number_pattern: Optional[str] = None, + number_search_pattern: Optional[str] = None, + capabilities: Optional[list] = None, + page_size: Optional[int] = None, + page_token: Optional[str] = None + ) -> TokenBasedPaginator: """ Search for all active virtual numbers associated with a certain project. For additional documentation, see https://www.sinch.com and visit our developer portal. @@ -159,11 +160,11 @@ def list( def update( self, - phone_number: str = None, - display_name: str = None, - sms_configuration: dict = None, - voice_configuration: dict = None, - app_id: str = None + phone_number: Optional[str] = None, + display_name: Optional[str] = None, + sms_configuration: Optional[dict] = None, + voice_configuration: Optional[dict] = None, + app_id: Optional[str] = None ) -> UpdateNumberConfigurationResponse: """ Make updates to the configuration of your virtual number. @@ -217,12 +218,12 @@ async def list( self, region_code: str, number_type: str, - number_pattern: str = None, - number_search_pattern: str = None, - capabilities: list = None, - page_size: int = None, - page_token: str = None - ) -> ListActiveNumbersResponse: + number_pattern: Optional[str] = None, + number_search_pattern: Optional[str] = None, + capabilities: Optional[list] = None, + page_size: Optional[int] = None, + page_token: Optional[str] = None + ) -> AsyncTokenBasedPaginator: return await AsyncTokenBasedPaginator._initialize( sinch=self._sinch, endpoint=ListActiveNumbersEndpoint( @@ -246,8 +247,8 @@ def __init__(self, sinch): def list( self, - number_type: str = None, - number_types: list = None + number_type: Optional[str] = None, + number_types: Optional[list] = None ) -> ListAvailableRegionsResponse: """ Lists all regions for numbers provided using the project ID. diff --git a/sinch/domains/numbers/models/active/requests.py b/sinch/domains/numbers/models/active/requests.py index 6af5b046..538a1e1a 100644 --- a/sinch/domains/numbers/models/active/requests.py +++ b/sinch/domains/numbers/models/active/requests.py @@ -1,17 +1,17 @@ from dataclasses import dataclass from sinch.core.models.base_model import SinchRequestBaseModel +from sinch.core.models.pagination import TokenPaginatedRequest @dataclass -class ListActiveNumbersRequest(SinchRequestBaseModel): +class ListActiveNumbersRequest(TokenPaginatedRequest): region_code: str number_type: str page_size: int capabilities: list number_search_pattern: str number_pattern: str - page_token: str @dataclass diff --git a/sinch/domains/sms/__init__.py b/sinch/domains/sms/__init__.py index ac3a39e0..f2279882 100644 --- a/sinch/domains/sms/__init__.py +++ b/sinch/domains/sms/__init__.py @@ -1,3 +1,4 @@ +from typing import Optional from sinch.core.pagination import IntBasedPaginator from sinch.core.pagination import AsyncIntBasedPaginator @@ -101,13 +102,13 @@ def __init__(self, sinch): def list( self, page: int = 0, - start_date: str = None, - end_date: str = None, - status: str = None, - code: str = None, - page_size: int = None, - client_reference: str = None - ) -> ListSMSDeliveryReportsResponse: + start_date: Optional[str] = None, + end_date: Optional[str] = None, + status: Optional[str] = None, + code: Optional[str] = None, + page_size: Optional[int] = None, + client_reference: Optional[str] = None + ) -> IntBasedPaginator: return IntBasedPaginator._initialize( sinch=self._sinch, endpoint=ListDeliveryReportsEndpoint( @@ -127,9 +128,9 @@ def list( def get_for_batch( self, batch_id: str, - type_: str = None, - code: list = None, - status: list = None + type_: Optional[str] = None, + code: Optional[list] = None, + status: Optional[list] = None ) -> GetSMSDeliveryReportForBatchResponse: return self._sinch.configuration.transport.request( GetDeliveryReportForBatchEndpoint( @@ -163,13 +164,13 @@ class SMSDeliveryReportsWithAsyncPagination(SMSDeliveryReports): async def list( self, page: int = 0, - start_date: str = None, - end_date: str = None, - status: str = None, - code: str = None, - page_size: int = None, - client_reference: str = None - ) -> ListSMSDeliveryReportsResponse: + start_date: Optional[str] = None, + end_date: Optional[str] = None, + status: Optional[str] = None, + code: Optional[str] = None, + page_size: Optional[int] = None, + client_reference: Optional[str] = None + ) -> AsyncIntBasedPaginator: return await AsyncIntBasedPaginator._initialize( sinch=self._sinch, endpoint=ListDeliveryReportsEndpoint( @@ -194,12 +195,12 @@ def __init__(self, sinch): def list( self, page: int = 0, - start_date: str = None, - to: str = None, - end_date: str = None, - page_size: int = None, - client_reference: str = None - ) -> SinchListInboundMessagesResponse: + start_date: Optional[str] = None, + to: Optional[str] = None, + end_date: Optional[str] = None, + page_size: Optional[int] = None, + client_reference: Optional[str] = None + ) -> IntBasedPaginator: return IntBasedPaginator._initialize( sinch=self._sinch, endpoint=ListInboundMessagesEndpoint( @@ -230,12 +231,12 @@ class SMSInboundsWithAsyncPagination(SMSInbounds): async def list( self, page: int = 0, - start_date: str = None, - to: str = None, - end_date: str = None, - page_size: int = None, - client_reference: str = None - ) -> SinchListInboundMessagesResponse: + start_date: Optional[str] = None, + to: Optional[str] = None, + end_date: Optional[str] = None, + page_size: Optional[int] = None, + client_reference: Optional[str] = None + ) -> AsyncIntBasedPaginator: return await AsyncIntBasedPaginator._initialize( sinch=self._sinch, endpoint=ListInboundMessagesEndpoint( @@ -261,19 +262,19 @@ def send( body: str, delivery_report: str, to: list, - from_: str = None, - parameters: dict = None, - type_: str = None, - send_at: str = None, - expire_at: str = None, - callback_url: str = None, - client_reference: str = None, - feedback_enabled: bool = None, - flash_message: bool = None, - truncate_concat: bool = None, - max_number_of_message_parts: int = None, - from_ton: int = None, - from_npi: int = None + from_: Optional[str] = None, + parameters: Optional[dict] = None, + type_: Optional[str] = None, + send_at: Optional[str] = None, + expire_at: Optional[str] = None, + callback_url: Optional[str] = None, + client_reference: Optional[str] = None, + feedback_enabled: Optional[bool] = None, + flash_message: Optional[bool] = None, + truncate_concat: Optional[bool] = None, + max_number_of_message_parts: Optional[int] = None, + from_ton: Optional[int] = None, + from_npi: Optional[int] = None ) -> SendSMSBatchResponse: return self._sinch.configuration.transport.request( SendBatchSMSEndpoint( @@ -302,12 +303,12 @@ def send( def list( self, page: int = 0, - page_size: int = None, - from_s: str = None, - start_date: str = None, - end_date: str = None, - client_reference: str = None - ) -> ListSMSBatchesResponse: + page_size: Optional[int] = None, + from_s: Optional[str] = None, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + client_reference: Optional[str] = None + ) -> IntBasedPaginator: return IntBasedPaginator._initialize( sinch=self._sinch, endpoint=ListSMSBatchesEndpoint( @@ -337,19 +338,19 @@ def send_dry_run( self, to: str, body: str, - per_recipient: bool = None, - number_of_recipients: int = None, - from_: str = None, - type_: str = None, - udh: str = None, - delivery_report: str = None, - send_at: str = None, - expire_at: str = None, - callback_url: str = None, - flash_message: bool = None, - parameters: dict = None, - client_reference: str = None, - max_number_of_message_parts: int = None + per_recipient: Optional[bool] = None, + number_of_recipients: Optional[int] = None, + from_: Optional[str] = None, + type_: Optional[str] = None, + udh: Optional[str] = None, + delivery_report: Optional[str] = None, + send_at: Optional[str] = None, + expire_at: Optional[str] = None, + callback_url: Optional[str] = None, + flash_message: Optional[bool] = None, + parameters: Optional[dict] = None, + client_reference: Optional[str] = None, + max_number_of_message_parts: Optional[int] = None ) -> SendSMSBatchDryRunResponse: return self._sinch.configuration.transport.request( SendBatchSMSDryRunEndpoint( @@ -387,14 +388,14 @@ def cancel(self, batch_id: str) -> CancelSMSBatchResponse: def update( self, batch_id: str, - to_add: list = None, - to_remove: list = None, - from_: str = None, - body: str = None, - delivery_report: str = None, - send_at: str = None, - expire_at: str = None, - callback_url: str = None, + to_add: Optional[list] = None, + to_remove: Optional[list] = None, + from_: Optional[str] = None, + body: Optional[str] = None, + delivery_report: Optional[str] = None, + send_at: Optional[str] = None, + expire_at: Optional[str] = None, + callback_url: Optional[str] = None, ) -> UpdateSMSBatchResponse: return self._sinch.configuration.transport.request( UpdateBatchSMSEndpoint( @@ -418,17 +419,17 @@ def replace( batch_id: str, to: str, body: str, - from_: str = None, - type_: str = None, - udh: str = None, - delivery_report: str = None, - send_at: str = None, - expire_at: str = None, - callback_url: str = None, - flash_message: bool = None, - parameters: dict = None, - client_reference: str = None, - max_number_of_message_parts: int = None + from_: Optional[str] = None, + type_: Optional[str] = None, + udh: Optional[str] = None, + delivery_report: Optional[str] = None, + send_at: Optional[str] = None, + expire_at: Optional[str] = None, + callback_url: Optional[str] = None, + flash_message: Optional[bool] = None, + parameters: Optional[dict] = None, + client_reference: Optional[str] = None, + max_number_of_message_parts: Optional[int] = None ) -> ReplaceSMSBatchResponse: return self._sinch.configuration.transport.request( ReplaceBatchSMSEndpoint( @@ -472,11 +473,11 @@ class SMSBatchesWithAsyncPagination(SMSBatches): async def list( self, page: int = 0, - page_size: int = None, - from_s: str = None, - start_date: str = None, - end_date: str = None, - client_reference: str = None + page_size: Optional[int] = None, + from_s: Optional[str] = None, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + client_reference: Optional[str] = None ) -> ListSMSBatchesResponse: return await AsyncIntBasedPaginator._initialize( sinch=self._sinch, @@ -501,9 +502,9 @@ def __init__(self, sinch): def create( self, name: str, - members: list = None, - child_groups: list = None, - auto_update: dict = None + members: Optional[list] = None, + child_groups: Optional[list] = None, + auto_update: Optional[dict] = None ) -> CreateSMSGroupResponse: return self._sinch.configuration.transport.request( CreateSMSGroupEndpoint( @@ -521,7 +522,7 @@ def list( self, page=0, page_size=None - ) -> SinchListSMSGroupResponse: + ) -> IntBasedPaginator: return IntBasedPaginator._initialize( sinch=self._sinch, endpoint=ListSMSGroupEndpoint( @@ -575,12 +576,12 @@ def get_group_phone_numbers( def update( self, group_id: str, - name: str = None, - add: list = None, - remove: list = None, - add_from_group: str = None, - remove_from_group: str = None, - auto_update: dict = None + name: Optional[str] = None, + add: Optional[list] = None, + remove: Optional[list] = None, + add_from_group: Optional[str] = None, + remove_from_group: Optional[str] = None, + auto_update: Optional[dict] = None ) -> UpdateSMSGroupResponse: return self._sinch.configuration.transport.request( UpdateSMSGroupEndpoint( @@ -601,7 +602,7 @@ def replace( self, group_id: str, members: list, - name: str = None + name: Optional[str] = None ) -> ReplaceSMSGroupResponse: return self._sinch.configuration.transport.request( ReplaceSMSGroupEndpoint( diff --git a/sinch/domains/sms/endpoints/batches/send_batch_dry_run.py b/sinch/domains/sms/endpoints/batches/send_batch_dry_run.py index 7daefedc..5ce54822 100644 --- a/sinch/domains/sms/endpoints/batches/send_batch_dry_run.py +++ b/sinch/domains/sms/endpoints/batches/send_batch_dry_run.py @@ -13,7 +13,7 @@ class SendBatchSMSDryRunEndpoint(SMSEndpoint): def __init__(self, project_id: str, request_data: BatchDryRunRequest): super(SendBatchSMSDryRunEndpoint, self).__init__(project_id, request_data) self.project_id = project_id - self.request_data = request_data + self.request_data: BatchDryRunRequest = request_data def build_url(self, sinch) -> str: return self.ENDPOINT_URL.format(