diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0a8d9b5..8fef266 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,9 +14,6 @@ stages: - pip install -r test-requirements.txt - pytest --cov=messente_api -pytest-3.7: - extends: .pytest - image: python:3.7-alpine pytest-3.8: extends: .pytest image: python:3.8-alpine @@ -29,3 +26,6 @@ pytest-3.10: pytest-3.11: extends: .pytest image: python:3.11-alpine +pytest-3.12: + extends: .pytest + image: python:3.12-alpine diff --git a/.openapi-generator/VERSION b/.openapi-generator/VERSION index 93c8dda..b23eb27 100644 --- a/.openapi-generator/VERSION +++ b/.openapi-generator/VERSION @@ -1 +1 @@ -7.6.0 +7.11.0 diff --git a/.travis.yml b/.travis.yml index d5c5482..d62debc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,14 @@ language: python -dist: jammy python: - - 3.10 + - "3.9" script: - echo "skipping tests" + +deploy: + provider: pypi + user: messente + password: + secure: T6b+hfVKTyJUUprT/7c6+nuEpqjENHWbZ5OrFLq/fo0N++aUgB7/VgsY7L2U9vmuog2xf34Di0C66fe/Tmy5czc+iXbwSnS6uP0aJk6dnERrdhiarUHgsDq4/txx59qYXZfelCO38M54GBPAlDzVp5/ONocbOrrJUPnt++0t/ocwbq2x5m6RSycJCEBWjxkBuLclrIkUvI+0IgJl/CXUro2OeVUg4J7rrwI68XAKAZF2SOQm/V3Ak30ax7CE2XFScVSvfz2g5kJbvtamFwdPRAwA5ThU4q6TDlL49DEblZCSKzAwOTkKkIkjFY5m6PPkNnxFAEsBjRyU5tl+T1pPvM0Gd/AY3lBXruRbU8SmGJgZbz59q1SQ1NRm5gHKpFEQ0kwWJvEJMOwRDLH16nFY4XX15ffVWFqw8Pkaso6NV6RTRVFTV3rVY2YPa1ili2QvkHYjejMZRDG+13MR+gJGWbjU2Uql3kj/QbIBFMyzXcfbLSpdn65KkzI5Svvzl/CsBZ0NsXIhH8rRsK464bZUuDY7qLbNca4IxARZRb2jH9C3Zas4kjJzl9J5TjkZTc8HTl+5PB8k+XsBaPSa1BvGvS3YEpQF6mVOr/SkQGX/yMV/WcmZJekSaWVrgdt5twPlfah0bwfKx60FKJqQYP2+2HeoA56UPrwSGT5ocz0wQC8= + on: + tags: true diff --git a/docs/Channel.md b/docs/Channel.md index df2de02..d68f603 100644 --- a/docs/Channel.md +++ b/docs/Channel.md @@ -2,10 +2,15 @@ Defines the delivery channel -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `SMS` (value: `'sms'`) + +* `VIBER` (value: `'viber'`) + +* `WHATSAPP` (value: `'whatsapp'`) + +* `TELEGRAM` (value: `'telegram'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ErrorCodeOmnichannel.md b/docs/ErrorCodeOmnichannel.md index e5ab361..3db4861 100644 --- a/docs/ErrorCodeOmnichannel.md +++ b/docs/ErrorCodeOmnichannel.md @@ -2,10 +2,21 @@ Matches the following error title. This field is a constant * 101 - Not found * 102 - Forbidden * 103 - Unauthorized * 104 - Internal Server Error * 105 - Invalid data * 106 - Missing data * 107 - Method not allowed -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `ENUM_101` (value: `'101'`) + +* `ENUM_102` (value: `'102'`) + +* `ENUM_103` (value: `'103'`) + +* `ENUM_104` (value: `'104'`) + +* `ENUM_105` (value: `'105'`) + +* `ENUM_106` (value: `'106'`) + +* `ENUM_107` (value: `'107'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ErrorCodeOmnichannelMachine.md b/docs/ErrorCodeOmnichannelMachine.md index 685614c..ecf6635 100644 --- a/docs/ErrorCodeOmnichannelMachine.md +++ b/docs/ErrorCodeOmnichannelMachine.md @@ -2,10 +2,31 @@ Machine-readable error code, 'null' when the message has not been processed yet Matches the following meanings * 0 - No error * 1 - Delivery failure * 2 - Sending message expired * 3 - Invalid number * 4 - Error crediting account * 5 - Invalid number format * 6 - Too many identical messages * 7 - Sender name not allowed * 8 - Operator blacklisted * 9 - Unroutable * 10 - Seen * 999 - General temporary error -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `NUMBER_0` (value: `0`) + +* `NUMBER_1` (value: `1`) + +* `NUMBER_2` (value: `2`) + +* `NUMBER_3` (value: `3`) + +* `NUMBER_4` (value: `4`) + +* `NUMBER_5` (value: `5`) + +* `NUMBER_6` (value: `6`) + +* `NUMBER_7` (value: `7`) + +* `NUMBER_8` (value: `8`) + +* `NUMBER_9` (value: `9`) + +* `NUMBER_10` (value: `10`) + +* `NUMBER_999` (value: `999`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ErrorCodePhonebook.md b/docs/ErrorCodePhonebook.md index e283497..ba8c76f 100644 --- a/docs/ErrorCodePhonebook.md +++ b/docs/ErrorCodePhonebook.md @@ -2,10 +2,19 @@ Matches the following error title. This field is a constant * 201 - Invalid data * 202 - Unauthorized * 203 - Missing resource * 204 - Conflict * 244 - Client error * 205 - General error -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `ENUM_201` (value: `'201'`) + +* `ENUM_202` (value: `'202'`) + +* `ENUM_203` (value: `'203'`) + +* `ENUM_204` (value: `'204'`) + +* `ENUM_244` (value: `'244'`) + +* `ENUM_205` (value: `'205'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ErrorCodeStatistics.md b/docs/ErrorCodeStatistics.md index ca5a123..f1c541e 100644 --- a/docs/ErrorCodeStatistics.md +++ b/docs/ErrorCodeStatistics.md @@ -2,10 +2,15 @@ Matches the following error title. This field is a constant * 100 - Client Error * 103 - Unauthorized * 104 - Invalid data * 105 - Internal Server Error -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `ENUM_100` (value: `'100'`) + +* `ENUM_103` (value: `'103'`) + +* `ENUM_104` (value: `'104'`) + +* `ENUM_105` (value: `'105'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ErrorTitleOmnichannel.md b/docs/ErrorTitleOmnichannel.md index 11637b6..a13fe52 100644 --- a/docs/ErrorTitleOmnichannel.md +++ b/docs/ErrorTitleOmnichannel.md @@ -2,10 +2,21 @@ Textual value which corresponds to an error code -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `NOT_FOUND` (value: `'Not found'`) + +* `FORBIDDEN` (value: `'Forbidden'`) + +* `UNAUTHORIZED` (value: `'Unauthorized'`) + +* `INVALID_DATA` (value: `'Invalid data'`) + +* `INTERNAL_SERVER_ERROR` (value: `'Internal Server Error'`) + +* `MISSING_DATA` (value: `'Missing data'`) + +* `METHOD_NOT_ALLOWED` (value: `'Method not allowed'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ErrorTitlePhonebook.md b/docs/ErrorTitlePhonebook.md index 50aa279..04bacbf 100644 --- a/docs/ErrorTitlePhonebook.md +++ b/docs/ErrorTitlePhonebook.md @@ -2,10 +2,19 @@ Textual value which corresponds to an error code -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `INVALID_DATA` (value: `'Invalid data'`) + +* `UNAUTHORIZED` (value: `'Unauthorized'`) + +* `MISSING_RESOURCE` (value: `'Missing resource'`) + +* `CONFLICT` (value: `'Conflict'`) + +* `CLIENT_ERROR` (value: `'Client error'`) + +* `GENERAL_ERROR` (value: `'General error'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/Priority.md b/docs/Priority.md index 79d4cac..780e7d7 100644 --- a/docs/Priority.md +++ b/docs/Priority.md @@ -2,10 +2,13 @@ Set the priority of the message. Messages are processed starting with in highest priority queue first and lowest priority queue last. This for example allows to prioritize OTP messages over marketing traffic. -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `LOW` (value: `'low'`) + +* `REGULAR` (value: `'regular'`) + +* `HIGH` (value: `'high'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/Status.md b/docs/Status.md index dc13fd4..abc9e74 100644 --- a/docs/Status.md +++ b/docs/Status.md @@ -2,10 +2,29 @@ The human-readable equivalent for this field is contained in \"error\". This value is *null* if the message is still being processed -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `ACK` (value: `'ACK'`) + +* `DELIVRD` (value: `'DELIVRD'`) + +* `UNDELIV` (value: `'UNDELIV'`) + +* `FAILED` (value: `'FAILED'`) + +* `UNKNOWN` (value: `'UNKNOWN'`) + +* `ACCEPTD` (value: `'ACCEPTD'`) + +* `REJECTD` (value: `'REJECTD'`) + +* `DELETED` (value: `'DELETED'`) + +* `EXPIRED` (value: `'EXPIRED'`) + +* `NACK` (value: `'NACK'`) + +* `SEEN` (value: `'SEEN'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/TextStore.md b/docs/TextStore.md index 00f7e41..4e0f698 100644 --- a/docs/TextStore.md +++ b/docs/TextStore.md @@ -2,10 +2,13 @@ Whether to store message content as is (plaintext), as a hashed value (sha256) or not at all (nostore) -## Properties +## Enum -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- +* `NOSTORE` (value: `'nostore'`) + +* `PLAINTEXT` (value: `'plaintext'`) + +* `SHA256` (value: `'sha256'`) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/messente_api/api/blacklist_api.py b/messente_api/api/blacklist_api.py index 77eaed4..5e42b04 100644 --- a/messente_api/api/blacklist_api.py +++ b/messente_api/api/blacklist_api.py @@ -261,7 +261,9 @@ def _add_to_blacklist_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -274,11 +276,12 @@ def _add_to_blacklist_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: @@ -538,7 +541,9 @@ def _delete_from_blacklist_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -551,11 +556,12 @@ def _delete_from_blacklist_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -783,7 +789,9 @@ def _fetch_blacklist_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -794,11 +802,12 @@ def _fetch_blacklist_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -1045,7 +1054,9 @@ def _is_blacklisted_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -1058,11 +1069,12 @@ def _is_blacklisted_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting diff --git a/messente_api/api/bulk_messaging_api.py b/messente_api/api/bulk_messaging_api.py index 40145a2..1578baa 100644 --- a/messente_api/api/bulk_messaging_api.py +++ b/messente_api/api/bulk_messaging_api.py @@ -258,7 +258,9 @@ def _send_bulk_omnimessage_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -271,11 +273,12 @@ def _send_bulk_omnimessage_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: diff --git a/messente_api/api/contacts_api.py b/messente_api/api/contacts_api.py index d6978b3..fc7df08 100644 --- a/messente_api/api/contacts_api.py +++ b/messente_api/api/contacts_api.py @@ -281,7 +281,9 @@ def _add_contact_to_group_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -296,11 +298,12 @@ def _add_contact_to_group_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -547,7 +550,9 @@ def _create_contact_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -560,11 +565,12 @@ def _create_contact_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: @@ -824,7 +830,9 @@ def _delete_contact_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -837,11 +845,12 @@ def _delete_contact_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -1088,7 +1097,9 @@ def _fetch_contact_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -1101,11 +1112,12 @@ def _fetch_contact_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -1352,7 +1364,9 @@ def _fetch_contact_groups_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -1365,11 +1379,12 @@ def _fetch_contact_groups_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -1614,7 +1629,9 @@ def _fetch_contacts_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -1629,11 +1646,12 @@ def _fetch_contacts_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -1893,7 +1911,9 @@ def _remove_contact_from_group_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -1908,11 +1928,12 @@ def _remove_contact_from_group_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -2172,7 +2193,9 @@ def _update_contact_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -2187,11 +2210,12 @@ def _update_contact_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: diff --git a/messente_api/api/delivery_report_api.py b/messente_api/api/delivery_report_api.py index 98b0a9e..c964c38 100644 --- a/messente_api/api/delivery_report_api.py +++ b/messente_api/api/delivery_report_api.py @@ -257,7 +257,9 @@ def _retrieve_delivery_report_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -270,11 +272,12 @@ def _retrieve_delivery_report_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting diff --git a/messente_api/api/groups_api.py b/messente_api/api/groups_api.py index cc9e1bb..f928af7 100644 --- a/messente_api/api/groups_api.py +++ b/messente_api/api/groups_api.py @@ -259,7 +259,9 @@ def _create_group_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -272,11 +274,12 @@ def _create_group_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: @@ -533,7 +536,9 @@ def _delete_group_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -546,11 +551,12 @@ def _delete_group_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -794,7 +800,9 @@ def _fetch_group_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -807,11 +815,12 @@ def _fetch_group_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -1039,7 +1048,9 @@ def _fetch_groups_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -1050,11 +1061,12 @@ def _fetch_groups_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -1314,7 +1326,9 @@ def _update_group_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -1329,11 +1343,12 @@ def _update_group_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: diff --git a/messente_api/api/number_lookup_api.py b/messente_api/api/number_lookup_api.py index 826d25e..3d511a6 100644 --- a/messente_api/api/number_lookup_api.py +++ b/messente_api/api/number_lookup_api.py @@ -261,7 +261,9 @@ def _fetch_info_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -274,11 +276,12 @@ def _fetch_info_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: diff --git a/messente_api/api/omnimessage_api.py b/messente_api/api/omnimessage_api.py index 9831daf..cd0d7a5 100644 --- a/messente_api/api/omnimessage_api.py +++ b/messente_api/api/omnimessage_api.py @@ -259,7 +259,9 @@ def _cancel_scheduled_message_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -272,11 +274,12 @@ def _cancel_scheduled_message_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -520,7 +523,9 @@ def _send_omnimessage_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -533,11 +538,12 @@ def _send_omnimessage_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: diff --git a/messente_api/api/statistics_api.py b/messente_api/api/statistics_api.py index d03a668..563149b 100644 --- a/messente_api/api/statistics_api.py +++ b/messente_api/api/statistics_api.py @@ -264,7 +264,9 @@ def _create_statistics_report_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -277,11 +279,12 @@ def _create_statistics_report_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # set the HTTP header `Content-Type` if _content_type: diff --git a/messente_api/api_client.py b/messente_api/api_client.py index 10c316b..6d6e0be 100644 --- a/messente_api/api_client.py +++ b/messente_api/api_client.py @@ -16,6 +16,7 @@ import datetime from dateutil.parser import parse from enum import Enum +import decimal import json import mimetypes import os @@ -67,6 +68,7 @@ class ApiClient: 'bool': bool, 'date': datetime.date, 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, 'object': object, } _pool = None @@ -228,7 +230,7 @@ def param_serialize( body = self.sanitize_for_serialization(body) # request url - if _host is None: + if _host is None or self.configuration.ignore_operation_servers: url = self.configuration.host + resource_path else: # use server/host defined in path or operation instead @@ -315,10 +317,7 @@ def response_deserialize( match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type) encoding = match.group(1) if match else "utf-8" response_text = response_data.data.decode(encoding) - if response_type in ["bytearray", "str"]: - return_data = self.__deserialize_primitive(response_text, response_type) - else: - return_data = self.deserialize(response_text, response_type) + return_data = self.deserialize(response_text, response_type, content_type) finally: if not 200 <= response_data.status <= 299: raise ApiException.from_response( @@ -342,6 +341,7 @@ def sanitize_for_serialization(self, obj): If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. @@ -367,6 +367,8 @@ def sanitize_for_serialization(self, obj): ) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) elif isinstance(obj, dict): obj_dict = obj @@ -386,21 +388,35 @@ def sanitize_for_serialization(self, obj): for key, val in obj_dict.items() } - def deserialize(self, response_text, response_type): + def deserialize(self, response_text: str, response_type: str, content_type: Optional[str]): """Deserializes response into an object. :param response: RESTResponse object to be deserialized. :param response_type: class literal for deserialized object, or string of class name. + :param content_type: content type of response. :return: deserialized object. """ # fetch data from response object - try: - data = json.loads(response_text) - except ValueError: + if content_type is None: + try: + data = json.loads(response_text) + except ValueError: + data = response_text + elif re.match(r'^application/(json|[\w!#$&.+-^_]+\+json)\s*(;|$)', content_type, re.IGNORECASE): + if response_text == "": + data = "" + else: + data = json.loads(response_text) + elif re.match(r'^text\/[a-z.+-]+\s*(;|$)', content_type, re.IGNORECASE): data = response_text + else: + raise ApiException( + status=0, + reason="Unsupported content type: {0}".format(content_type) + ) return self.__deserialize(data, response_type) @@ -444,6 +460,8 @@ def __deserialize(self, data, klass): return self.__deserialize_date(data) elif klass == datetime.datetime: return self.__deserialize_datetime(data) + elif klass == decimal.Decimal: + return decimal.Decimal(data) elif issubclass(klass, Enum): return self.__deserialize_enum(data, klass) else: @@ -500,7 +518,7 @@ def parameters_to_url_query(self, params, collection_formats): if k in collection_formats: collection_format = collection_formats[k] if collection_format == 'multi': - new_params.extend((k, str(value)) for value in v) + new_params.extend((k, quote(str(value))) for value in v) else: if collection_format == 'ssv': delimiter = ' ' @@ -518,7 +536,10 @@ def parameters_to_url_query(self, params, collection_formats): return "&".join(["=".join(map(str, item)) for item in new_params]) - def files_parameters(self, files: Dict[str, Union[str, bytes]]): + def files_parameters( + self, + files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]], + ): """Builds form parameters. :param files: File parameters. @@ -533,6 +554,12 @@ def files_parameters(self, files: Dict[str, Union[str, bytes]]): elif isinstance(v, bytes): filename = k filedata = v + elif isinstance(v, tuple): + filename, filedata = v + elif isinstance(v, list): + for file_param in v: + params.extend(self.files_parameters({k: file_param})) + continue else: raise ValueError("Unsupported file value") mimetype = ( diff --git a/messente_api/configuration.py b/messente_api/configuration.py index 1ba45fc..5e62018 100644 --- a/messente_api/configuration.py +++ b/messente_api/configuration.py @@ -14,14 +14,16 @@ import copy +import http.client as httplib import logging from logging import FileHandler import multiprocessing import sys -from typing import Optional +from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict +from typing_extensions import NotRequired, Self + import urllib3 -import http.client as httplib JSON_SCHEMA_VALIDATION_KEYWORDS = { 'multipleOf', 'maximum', 'exclusiveMaximum', @@ -29,10 +31,114 @@ 'minLength', 'pattern', 'maxItems', 'minItems' } +ServerVariablesT = Dict[str, str] + +GenericAuthSetting = TypedDict( + "GenericAuthSetting", + { + "type": str, + "in": str, + "key": str, + "value": str, + }, +) + + +OAuth2AuthSetting = TypedDict( + "OAuth2AuthSetting", + { + "type": Literal["oauth2"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +APIKeyAuthSetting = TypedDict( + "APIKeyAuthSetting", + { + "type": Literal["api_key"], + "in": str, + "key": str, + "value": Optional[str], + }, +) + + +BasicAuthSetting = TypedDict( + "BasicAuthSetting", + { + "type": Literal["basic"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": Optional[str], + }, +) + + +BearerFormatAuthSetting = TypedDict( + "BearerFormatAuthSetting", + { + "type": Literal["bearer"], + "in": Literal["header"], + "format": Literal["JWT"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +BearerAuthSetting = TypedDict( + "BearerAuthSetting", + { + "type": Literal["bearer"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +HTTPSignatureAuthSetting = TypedDict( + "HTTPSignatureAuthSetting", + { + "type": Literal["http-signature"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": None, + }, +) + + +AuthSettings = TypedDict( + "AuthSettings", + { + "basicAuth": BasicAuthSetting, + }, + total=False, +) + + +class HostSettingVariable(TypedDict): + description: str + default_value: str + enum_values: List[str] + + +class HostSetting(TypedDict): + url: str + description: str + variables: NotRequired[Dict[str, HostSettingVariable]] + + class Configuration: """This class contains various settings of the API client. :param host: Base url. + :param ignore_operation_servers + Boolean to ignore operation servers for the API client. + Config will use `host` as the base url regardless of the operation servers. :param api_key: Dict to store API key(s). Each entry in the dict specifies an API key. The dict key is the name of the security scheme in the OAS specification. @@ -55,6 +161,7 @@ class Configuration: values before. :param ssl_ca_cert: str - the path to a file of concatenated CA certificates in PEM format. + :param retries: Number of retries for API requests. :Example: @@ -75,16 +182,26 @@ class Configuration: """ - _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, - ) -> None: + _default: ClassVar[Optional[Self]] = None + + def __init__( + self, + host: Optional[str]=None, + api_key: Optional[Dict[str, str]]=None, + api_key_prefix: Optional[Dict[str, str]]=None, + username: Optional[str]=None, + password: Optional[str]=None, + access_token: Optional[str]=None, + server_index: Optional[int]=None, + server_variables: Optional[ServerVariablesT]=None, + server_operation_index: Optional[Dict[int, int]]=None, + server_operation_variables: Optional[Dict[int, ServerVariablesT]]=None, + ignore_operation_servers: bool=False, + ssl_ca_cert: Optional[str]=None, + retries: Optional[int] = None, + *, + debug: Optional[bool] = None, + ) -> None: """Constructor """ self._base_path = "https://api.messente.com/v1" if host is None else host @@ -98,6 +215,9 @@ def __init__(self, host=None, self.server_operation_variables = server_operation_variables or {} """Default server variables """ + self.ignore_operation_servers = ignore_operation_servers + """Ignore operation servers + """ self.temp_folder_path = None """Temp file folder for downloading files """ @@ -141,7 +261,10 @@ def __init__(self, host=None, self.logger_file = None """Debug file location """ - self.debug = False + if debug is not None: + self.debug = debug + else: + self.__debug = False """Debug switch """ @@ -184,7 +307,7 @@ def __init__(self, host=None, self.safe_chars_for_path_param = '' """Safe chars for path_param """ - self.retries = None + self.retries = retries """Adding retries to override urllib3 default value 3 """ # Enable client side validation @@ -202,7 +325,7 @@ def __init__(self, host=None, """date format """ - def __deepcopy__(self, memo): + def __deepcopy__(self, memo: Dict[int, Any]) -> Self: cls = self.__class__ result = cls.__new__(cls) memo[id(self)] = result @@ -216,11 +339,11 @@ def __deepcopy__(self, memo): result.debug = self.debug return result - def __setattr__(self, name, value): + def __setattr__(self, name: str, value: Any) -> None: object.__setattr__(self, name, value) @classmethod - def set_default(cls, default): + def set_default(cls, default: Optional[Self]) -> None: """Set default instance of configuration. It stores default configuration, which can be @@ -231,7 +354,7 @@ def set_default(cls, default): cls._default = default @classmethod - def get_default_copy(cls): + def get_default_copy(cls) -> Self: """Deprecated. Please use `get_default` instead. Deprecated. Please use `get_default` instead. @@ -241,7 +364,7 @@ def get_default_copy(cls): return cls.get_default() @classmethod - def get_default(cls): + def get_default(cls) -> Self: """Return the default configuration. This method returns newly created, based on default constructor, @@ -251,11 +374,11 @@ def get_default(cls): :return: The configuration object. """ if cls._default is None: - cls._default = Configuration() + cls._default = cls() return cls._default @property - def logger_file(self): + def logger_file(self) -> Optional[str]: """The logger file. If the logger_file is None, then add stream handler and remove file @@ -267,7 +390,7 @@ def logger_file(self): return self.__logger_file @logger_file.setter - def logger_file(self, value): + def logger_file(self, value: Optional[str]) -> None: """The logger file. If the logger_file is None, then add stream handler and remove file @@ -286,7 +409,7 @@ def logger_file(self, value): logger.addHandler(self.logger_file_handler) @property - def debug(self): + def debug(self) -> bool: """Debug status :param value: The debug status, True or False. @@ -295,7 +418,7 @@ def debug(self): return self.__debug @debug.setter - def debug(self, value): + def debug(self, value: bool) -> None: """Debug status :param value: The debug status, True or False. @@ -317,7 +440,7 @@ def debug(self, value): httplib.HTTPConnection.debuglevel = 0 @property - def logger_format(self): + def logger_format(self) -> str: """The logger format. The logger_formatter will be updated when sets logger_format. @@ -328,7 +451,7 @@ def logger_format(self): return self.__logger_format @logger_format.setter - def logger_format(self, value): + def logger_format(self, value: str) -> None: """The logger format. The logger_formatter will be updated when sets logger_format. @@ -339,7 +462,7 @@ def logger_format(self, value): self.__logger_format = value self.logger_formatter = logging.Formatter(self.__logger_format) - def get_api_key_with_prefix(self, identifier, alias=None): + def get_api_key_with_prefix(self, identifier: str, alias: Optional[str]=None) -> Optional[str]: """Gets API key (with prefix if set). :param identifier: The identifier of apiKey. @@ -356,7 +479,9 @@ def get_api_key_with_prefix(self, identifier, alias=None): else: return key - def get_basic_auth_token(self): + return None + + def get_basic_auth_token(self) -> Optional[str]: """Gets HTTP basic authentication header (string). :return: The token for basic HTTP authentication. @@ -371,12 +496,12 @@ def get_basic_auth_token(self): basic_auth=username + ':' + password ).get('authorization') - def auth_settings(self): + def auth_settings(self)-> AuthSettings: """Gets Auth Settings dict for api client. :return: The Auth Settings information dict. """ - auth = {} + auth: AuthSettings = {} if self.username is not None and self.password is not None: auth['basicAuth'] = { 'type': 'basic', @@ -386,7 +511,7 @@ def auth_settings(self): } return auth - def to_debug_report(self): + def to_debug_report(self) -> str: """Gets the essential information for debugging. :return: The report for debugging. @@ -398,7 +523,7 @@ def to_debug_report(self): "SDK Package Version: 2.3.0".\ format(env=sys.platform, pyversion=sys.version) - def get_host_settings(self): + def get_host_settings(self) -> List[HostSetting]: """Gets an array of host settings :return: An array of host settings @@ -410,7 +535,12 @@ def get_host_settings(self): } ] - def get_host_from_settings(self, index, variables=None, servers=None): + def get_host_from_settings( + self, + index: Optional[int], + variables: Optional[ServerVariablesT]=None, + servers: Optional[List[HostSetting]]=None, + ) -> str: """Gets host URL based on the index and variables :param index: array index of the host settings :param variables: hash of variable and the corresponding value @@ -450,12 +580,12 @@ def get_host_from_settings(self, index, variables=None, servers=None): return url @property - def host(self): + def host(self) -> str: """Return generated host.""" return self.get_host_from_settings(self.server_index, variables=self.server_variables) @host.setter - def host(self, value): + def host(self, value: str) -> None: """Fix base path.""" self._base_path = value self.server_index = None diff --git a/messente_api/exceptions.py b/messente_api/exceptions.py index eb290f9..61d56b7 100644 --- a/messente_api/exceptions.py +++ b/messente_api/exceptions.py @@ -151,6 +151,13 @@ def from_response( if http_resp.status == 404: raise NotFoundException(http_resp=http_resp, body=body, data=data) + # Added new conditions for 409 and 422 + if http_resp.status == 409: + raise ConflictException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 422: + raise UnprocessableEntityException(http_resp=http_resp, body=body, data=data) + if 500 <= http_resp.status <= 599: raise ServiceException(http_resp=http_resp, body=body, data=data) raise ApiException(http_resp=http_resp, body=body, data=data) @@ -189,6 +196,16 @@ class ServiceException(ApiException): pass +class ConflictException(ApiException): + """Exception for HTTP 409 Conflict.""" + pass + + +class UnprocessableEntityException(ApiException): + """Exception for HTTP 422 Unprocessable Entity.""" + pass + + def render_path(path_to_item): """Returns a string representation of a path""" result = "" diff --git a/messente_api/models/bulk_omni_message_create_success_response.py b/messente_api/models/bulk_omni_message_create_success_response.py index 16c6c91..42e2bc1 100644 --- a/messente_api/models/bulk_omni_message_create_success_response.py +++ b/messente_api/models/bulk_omni_message_create_success_response.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in messages (list) _items = [] if self.messages: - for _item in self.messages: - if _item: - _items.append(_item.to_dict()) + for _item_messages in self.messages: + if _item_messages: + _items.append(_item_messages.to_dict()) _dict['messages'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/bulk_omnimessage.py b/messente_api/models/bulk_omnimessage.py index 706f6e0..b776dce 100644 --- a/messente_api/models/bulk_omnimessage.py +++ b/messente_api/models/bulk_omnimessage.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in messages (list) _items = [] if self.messages: - for _item in self.messages: - if _item: - _items.append(_item.to_dict()) + for _item_messages in self.messages: + if _item_messages: + _items.append(_item_messages.to_dict()) _dict['messages'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/contact_list_envelope.py b/messente_api/models/contact_list_envelope.py index a35024c..b5e8349 100644 --- a/messente_api/models/contact_list_envelope.py +++ b/messente_api/models/contact_list_envelope.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in contacts (list) _items = [] if self.contacts: - for _item in self.contacts: - if _item: - _items.append(_item.to_dict()) + for _item_contacts in self.contacts: + if _item_contacts: + _items.append(_item_contacts.to_dict()) _dict['contacts'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/delivery_report_response.py b/messente_api/models/delivery_report_response.py index a83524d..2278ec9 100644 --- a/messente_api/models/delivery_report_response.py +++ b/messente_api/models/delivery_report_response.py @@ -78,9 +78,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in statuses (list) _items = [] if self.statuses: - for _item in self.statuses: - if _item: - _items.append(_item.to_dict()) + for _item_statuses in self.statuses: + if _item_statuses: + _items.append(_item_statuses.to_dict()) _dict['statuses'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/error_number_lookup.py b/messente_api/models/error_number_lookup.py index fff2e09..69c6e12 100644 --- a/messente_api/models/error_number_lookup.py +++ b/messente_api/models/error_number_lookup.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in errors (list) _items = [] if self.errors: - for _item in self.errors: - if _item: - _items.append(_item.to_dict()) + for _item_errors in self.errors: + if _item_errors: + _items.append(_item_errors.to_dict()) _dict['errors'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/error_omnichannel.py b/messente_api/models/error_omnichannel.py index a6c948a..7a9ae7e 100644 --- a/messente_api/models/error_omnichannel.py +++ b/messente_api/models/error_omnichannel.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in errors (list) _items = [] if self.errors: - for _item in self.errors: - if _item: - _items.append(_item.to_dict()) + for _item_errors in self.errors: + if _item_errors: + _items.append(_item_errors.to_dict()) _dict['errors'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/error_phonebook.py b/messente_api/models/error_phonebook.py index 9d20681..82402e4 100644 --- a/messente_api/models/error_phonebook.py +++ b/messente_api/models/error_phonebook.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in errors (list) _items = [] if self.errors: - for _item in self.errors: - if _item: - _items.append(_item.to_dict()) + for _item_errors in self.errors: + if _item_errors: + _items.append(_item_errors.to_dict()) _dict['errors'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/error_statistics.py b/messente_api/models/error_statistics.py index 55e88b8..abc39e9 100644 --- a/messente_api/models/error_statistics.py +++ b/messente_api/models/error_statistics.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in errors (list) _items = [] if self.errors: - for _item in self.errors: - if _item: - _items.append(_item.to_dict()) + for _item_errors in self.errors: + if _item_errors: + _items.append(_item_errors.to_dict()) _dict['errors'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/group_list_envelope.py b/messente_api/models/group_list_envelope.py index f06d764..b76551e 100644 --- a/messente_api/models/group_list_envelope.py +++ b/messente_api/models/group_list_envelope.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in groups (list) _items = [] if self.groups: - for _item in self.groups: - if _item: - _items.append(_item.to_dict()) + for _item_groups in self.groups: + if _item_groups: + _items.append(_item_groups.to_dict()) _dict['groups'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/omni_message_create_success_response.py b/messente_api/models/omni_message_create_success_response.py index a434674..1d5cabb 100644 --- a/messente_api/models/omni_message_create_success_response.py +++ b/messente_api/models/omni_message_create_success_response.py @@ -78,9 +78,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in messages (list) _items = [] if self.messages: - for _item in self.messages: - if _item: - _items.append(_item.to_dict()) + for _item_messages in self.messages: + if _item_messages: + _items.append(_item_messages.to_dict()) _dict['messages'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/omnimessage.py b/messente_api/models/omnimessage.py index 00bc489..4b54c4d 100644 --- a/messente_api/models/omnimessage.py +++ b/messente_api/models/omnimessage.py @@ -84,9 +84,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in messages (list) _items = [] if self.messages: - for _item in self.messages: - if _item: - _items.append(_item.to_dict()) + for _item_messages in self.messages: + if _item_messages: + _items.append(_item_messages.to_dict()) _dict['messages'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/statistics_report_success.py b/messente_api/models/statistics_report_success.py index 7561991..7a7584d 100644 --- a/messente_api/models/statistics_report_success.py +++ b/messente_api/models/statistics_report_success.py @@ -76,9 +76,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in reports (list) _items = [] if self.reports: - for _item in self.reports: - if _item: - _items.append(_item.to_dict()) + for _item_reports in self.reports: + if _item_reports: + _items.append(_item_reports.to_dict()) _dict['reports'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/sync_number_lookup_success.py b/messente_api/models/sync_number_lookup_success.py index 7b07d16..fce7146 100644 --- a/messente_api/models/sync_number_lookup_success.py +++ b/messente_api/models/sync_number_lookup_success.py @@ -77,9 +77,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in result (list) _items = [] if self.result: - for _item in self.result: - if _item: - _items.append(_item.to_dict()) + for _item_result in self.result: + if _item_result: + _items.append(_item_result.to_dict()) _dict['result'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/whats_app_component.py b/messente_api/models/whats_app_component.py index 26c0454..97d362c 100644 --- a/messente_api/models/whats_app_component.py +++ b/messente_api/models/whats_app_component.py @@ -79,9 +79,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in parameters (list) _items = [] if self.parameters: - for _item in self.parameters: - if _item: - _items.append(_item.to_dict()) + for _item_parameters in self.parameters: + if _item_parameters: + _items.append(_item_parameters.to_dict()) _dict['parameters'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/models/whats_app_template.py b/messente_api/models/whats_app_template.py index 79dece3..3e79767 100644 --- a/messente_api/models/whats_app_template.py +++ b/messente_api/models/whats_app_template.py @@ -82,9 +82,9 @@ def to_dict(self) -> Dict[str, Any]: # 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()) + for _item_components in self.components: + if _item_components: + _items.append(_item_components.to_dict()) _dict['components'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: diff --git a/messente_api/rest.py b/messente_api/rest.py index 9979215..e61780e 100644 --- a/messente_api/rest.py +++ b/messente_api/rest.py @@ -226,7 +226,7 @@ def request( headers=headers, preload_content=False ) - elif headers['Content-Type'] == 'text/plain' and isinstance(body, bool): + elif headers['Content-Type'].startswith('text/') and isinstance(body, bool): request_body = "true" if body else "false" r = self.pool_manager.request( method, diff --git a/pyproject.toml b/pyproject.toml index c98b034..ec17b3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,19 +10,20 @@ keywords = ["OpenAPI", "OpenAPI-Generator", "Messente API"] include = ["messente_api/py.typed"] [tool.poetry.dependencies] -python = "^3.7" +python = "^3.8" -urllib3 = ">= 1.25.3" -python-dateutil = ">=2.8.2" -pydantic = ">=2" -typing-extensions = ">=4.7.1" +urllib3 = ">= 1.25.3, < 3.0.0" +python-dateutil = ">= 2.8.2" +pydantic = ">= 2" +typing-extensions = ">= 4.7.1" [tool.poetry.dev-dependencies] -pytest = ">=7.2.1" -tox = ">=3.9.0" -flake8 = ">=4.0.0" -types-python-dateutil = ">=2.8.19.14" -mypy = "1.4.1" +pytest = ">= 7.2.1" +pytest-cov = ">= 2.8.1" +tox = ">= 3.9.0" +flake8 = ">= 4.0.0" +types-python-dateutil = ">= 2.8.19.14" +mypy = ">= 1.5" [build-system] @@ -48,7 +49,7 @@ warn_unused_ignores = true ## Getting these passing should be easy strict_equality = true -strict_concatenate = true +extra_checks = true ## Strongly recommend enabling this one as soon as you can check_untyped_defs = true @@ -69,3 +70,20 @@ disallow_any_generics = true # ### This one can be tricky to get passing if you use a lot of untyped libraries #warn_return_any = true + +[[tool.mypy.overrides]] +module = [ + "messente_api.configuration", +] +warn_unused_ignores = true +strict_equality = true +extra_checks = true +check_untyped_defs = true +disallow_subclassing_any = true +disallow_untyped_decorators = true +disallow_any_generics = true +disallow_untyped_calls = true +disallow_incomplete_defs = true +disallow_untyped_defs = true +no_implicit_reexport = true +warn_return_any = true diff --git a/requirements.txt b/requirements.txt index cc85509..67f7f68 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ -python_dateutil >= 2.5.3 -setuptools >= 21.0.0 -urllib3 >= 1.25.3, < 2.1.0 +urllib3 >= 1.25.3, < 3.0.0 +python_dateutil >= 2.8.2 pydantic >= 2 typing-extensions >= 4.7.1 diff --git a/setup.py b/setup.py index 7da0a8b..681c78f 100644 --- a/setup.py +++ b/setup.py @@ -23,10 +23,10 @@ # http://pypi.python.org/pypi/setuptools NAME = "messente-api" VERSION = "2.3.0" -PYTHON_REQUIRES = ">=3.7" +PYTHON_REQUIRES = ">= 3.8" REQUIRES = [ - "urllib3 >= 1.25.3, < 2.1.0", - "python-dateutil", + "urllib3 >= 1.25.3, < 3.0.0", + "python-dateutil >= 2.8.2", "pydantic >= 2", "typing-extensions >= 4.7.1", ] @@ -48,4 +48,4 @@ [Messente](https://messente.com) is a global provider of messaging and user verification services. * Send and receive SMS, Viber, WhatsApp and Telegram messages. * Manage contacts and groups. * Fetch detailed info about phone numbers. * Blacklist phone numbers to make sure you're not sending any unwanted messages. Messente builds [tools](https://messente.com/documentation) to help organizations connect their services to people anywhere in the world. """, # noqa: E501 package_data={"messente_api": ["py.typed"]}, -) +) \ No newline at end of file diff --git a/test-requirements.txt b/test-requirements.txt index 8e6d8cb..e98555c 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,5 +1,6 @@ -pytest~=7.1.3 -pytest-cov>=2.8.1 -pytest-randomly>=3.12.0 -mypy>=1.4.1 -types-python-dateutil>=2.8.19 +pytest >= 7.2.1 +pytest-cov >= 2.8.1 +tox >= 3.9.0 +flake8 >= 4.0.0 +types-python-dateutil >= 2.8.19.14 +mypy >= 1.5