Skip to content

Commit 52715b2

Browse files
authored
Add web rtc channel (#63)
* Added payload models * Added generate_token method * Added tests for save_application body * Added save_application method * Added get_applications method * Added get_application method * Added delete_application * Added update_application * Corrected regex issue with unicode characters * Added aditional test cases * Updated README.md * Added first integration tests * Changed integration tests * Added additional tests * Added tests for update application endpoint * Added tests for delete application endpoind * Added tests for unsupported cases * Added dependency to requirements/dev.txt * Added header methods for post and delete * Changed tests cases parameters * Changed README.md * Changed README.md v2 * Added regex==2022.3.15 to setup.cfg, tox.ini and common.txt * Updated pull request with review suggestions * Moved validate_path_parameter to Channel class
1 parent 2f86b0a commit 52715b2

31 files changed

+1150
-92
lines changed

README.md

Lines changed: 16 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# infobip-api-python-sdk
22
Python client for Infobip's API channels.
33

4+
# Supported channels
5+
- Whatsapp -> [Docs](https://www.infobip.com/docs/api#channels/whatsapp)
6+
- WebRTC -> [Docs](https://www.infobip.com/docs/api#channels/webrtc/)
7+
- MMS -> [Docs](https://www.infobip.com/docs/api#channels/mms)
8+
49
#### Table of contents:
510

611
- [General Info](#general-info)
@@ -9,10 +14,6 @@ Python client for Infobip's API channels.
914
- [Code example](#code-example)
1015
- [Testing](#testing)
1116
- [Enable pre-commit hooks](#enable-pre-commit-hooks)
12-
- [Generating distribution package](#generating-distribution-package)
13-
- [Uploading distribution package on TestPyPI](#uploading-distribution-package-on-testpypi-for-testing-purposes)
14-
- [Installing your newly uploaded package](#installing-your-newly-uploaded-package)
15-
1617

1718
## General Info
1819

@@ -27,7 +28,7 @@ Published under [MIT License](LICENSE).
2728
## Installation
2829

2930
Install the library by using the following command:
30-
```
31+
```bash
3132
pip install infobip-api-python-sdk
3233
```
3334

@@ -38,21 +39,21 @@ If you don't already have one, you can create a free trial account [here](https:
3839
In this example we will show how to send WhatsApp text message.
3940
First step is to import necessary channel, in this case WhatsApp channel.
4041

41-
```
42+
```python
4243
from infobip_channels import WhatsAppChannel
4344
```
4445

4546
Now you can create instance of `WhatsAppChannel` with your `base_url` and `api_key`.
4647

47-
```
48+
```python
4849
c = WhatsAppChannel.from_auth_params({
4950
"base_url": "<your_base_url>",
5051
"api_key": "<your_api_key>"
5152
})
5253
```
5354
After that you can access all the methods from `WhatsAppChannel`.
5455
To send text message you can use `send_text_message` method and add correct payload:
55-
```
56+
```python
5657
response = c.send_text_message(
5758
{
5859
"from": "<WhatsApp sender number from your Infobib account>",
@@ -69,89 +70,38 @@ response = c.send_text_message(
6970
## Testing
7071
To run tests position yourself in the project's root while your virtual environment
7172
is active and run:
72-
```
73+
```bash
7374
python -m pytest
7475
```
7576

7677
## Enable pre-commit hooks
7778
To enable pre-commit hooks run:
78-
```
79+
```bash
7980
pip install -r requirements/dev.txt
8081
```
8182
You will need to install pre-commit hooks
8283
Using homebrew:
83-
```
84+
```bash
8485
brew install pre-commit
8586
```
8687
Using conda (via conda-forge):
87-
```
88+
```bash
8889
conda install -c conda-forge pre-commit
8990
```
9091
To check installation run:
91-
```
92+
```bash
9293
pre-commit --version
9394
```
9495
If installation was successful you will see version number.
9596
You can find the Pre-commit configuration in `.pre-commit-config.yaml`.
9697
Install the git hook scripts:
97-
```
98+
```bash
9899
pre-commit install
99100
```
100101
Run against all files:
101-
```
102+
```bash
102103
pre-commit run --all-files
103104
```
104105
If setup was successful pre-commit will run on every commit.
105106
Every time you clone a project that uses pre-commit, running `pre-commit install`
106107
should be the first thing you do.
107-
108-
109-
## Generating distribution package
110-
Make sure you have the latest version of PyPA's
111-
[build](https://packaging.python.org/en/latest/key_projects/#build) installed:
112-
```
113-
python -m pip install --upgrade build
114-
```
115-
After installation check `setup.cfg` file for metadata.
116-
Name and version are used for file generation.
117-
Make sure that you appropriately change version before build.
118-
Update the `version` in the `setup.cfg` file to the desired one.
119-
120-
Now run this command from the same directory where pyproject.toml is located:
121-
```
122-
python -m build
123-
```
124-
125-
This command should generate two files in the `dist` directory:
126-
```
127-
dist/
128-
infobip_channels-x.y.z-py3-none-any.whl
129-
infobip-channels-x.y.z.tar.gz
130-
```
131-
132-
133-
## Uploading distribution package on TestPyPI (for testing purposes)
134-
First thing to do is create an account on TestPyPI and acquire an API token.
135-
To upload the distribution package, you can use
136-
[twine](https://packaging.python.org/en/latest/key_projects/#twine):
137-
```
138-
python -m pip install --upgrade twine
139-
```
140-
141-
Once installed, run Twine to upload all the archives under dist:
142-
```
143-
python -m twine upload --repository testpypi dist/*
144-
```
145-
146-
You will be prompted for a username and password. For the username, use *\_\_token\_\_*.
147-
For the password, use the token value, including the pypi- prefix.
148-
149-
150-
## Installing your newly uploaded package
151-
To test the newly uploaded package, create a virtual environment and download the
152-
package:
153-
```
154-
pip install --extra-index-url https://test.pypi.org/simple/ infobip-channels==x.y.z
155-
```
156-
157-
After that, create a test script or import the library in a shell and try it out.

infobip_channels/core/channel.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
PostHeaders,
1313
ResponseBase,
1414
)
15+
from infobip_channels.web_rtc.models.path_parameters.core import PathParameter
1516

1617

1718
class Channel(ABC):
@@ -114,6 +115,24 @@ def convert_model_to_dict(
114115
"""
115116
return model.dict(by_alias=by_alias, exclude_unset=exclude_unset, **kwargs)
116117

118+
@staticmethod
119+
def validate_path_parameter(
120+
parameter: Union[PathParameter, Dict], parameter_type: Type[PathParameter]
121+
) -> PathParameter:
122+
"""
123+
Validate path parameter by trying to instantiate the provided class and
124+
extract valid path parameter.
125+
126+
:param parameter: Path parameter to validate
127+
:param parameter_type: Type of path parameter
128+
:return: Class instance corresponding to the provided parameter type
129+
"""
130+
return (
131+
parameter
132+
if isinstance(parameter, parameter_type)
133+
else parameter_type(**parameter)
134+
)
135+
117136
@staticmethod
118137
def validate_message_body(
119138
message: Union[MessageBodyBase, Dict],
@@ -135,11 +154,18 @@ def _construct_response(
135154
response_class = self._get_custom_response_class(
136155
raw_response, *args, **kwargs
137156
)
157+
158+
response_json = raw_response.json()
159+
if type(response_json) is list:
160+
raw_response_data = {"list": response_json}
161+
else:
162+
raw_response_data = response_json
163+
138164
return response_class(
139165
**{
140166
"status_code": raw_response.status_code,
141167
"raw_response": raw_response,
142-
**raw_response.json(),
168+
**raw_response_data,
143169
}
144170
)
145171

infobip_channels/core/http_client.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
from infobip_channels.core.models import (
66
Authentication,
7+
DeleteHeaders,
78
GetHeaders,
89
PostHeaders,
10+
PutHeaders,
911
RequestHeaders,
1012
)
1113

@@ -18,16 +20,21 @@ def __init__(
1820
auth: Authentication,
1921
post_headers: RequestHeaders = None,
2022
get_headers: RequestHeaders = None,
23+
put_headers: RequestHeaders = None,
24+
delete_headers: RequestHeaders = None,
2125
):
22-
"""Create an instance of the _HttpClient class with the provided authentication
23-
model instance. Get and post headers can optionally be provided, otherwise
24-
default instances will be created for both. These headers will be used as
25-
defaults in the get and post methods, unless new values are sent through method
26-
arguments.
26+
"""Create an instance of the _HttpClient class with the provided
27+
authentication model instance. Headers can optionally be provided, otherwise
28+
default instances will be created. These headers will be used as defaults in
29+
the HTTP methods, unless new values are sent through method arguments.
2730
"""
2831
self.auth = auth
2932
self.post_headers = post_headers or PostHeaders(authorization=self.auth.api_key)
3033
self.get_headers = get_headers or GetHeaders(authorization=self.auth.api_key)
34+
self.put_headers = put_headers or PutHeaders(authorization=self.auth.api_key)
35+
self.delete_headers = delete_headers or DeleteHeaders(
36+
authorization=self.auth.api_key
37+
)
3138

3239
def post(
3340
self, endpoint: str, body: Union[Dict, bytes], headers: RequestHeaders = None
@@ -53,7 +60,6 @@ def get(
5360
self, endpoint: str, headers: RequestHeaders = None, params: Dict = None
5461
) -> requests.Response:
5562
"""Send an HTTP get request to base_url + endpoint.
56-
5763
:param endpoint: Which endpoint to hit
5864
:param headers: Request headers
5965
:param params: Dictionary of query parameters
@@ -63,3 +69,31 @@ def get(
6369
url = self.auth.base_url + endpoint
6470

6571
return requests.get(url=url, headers=headers.dict(by_alias=True), params=params)
72+
73+
def put(
74+
self, endpoint: str, body: Dict, headers: RequestHeaders = None
75+
) -> requests.Response:
76+
"""Send an HTTP put request to base_url + endpoint.
77+
78+
:param endpoint: Which endpoint to hit
79+
:param headers: Request headers
80+
:param body: Body to send with the request
81+
:return: Received response
82+
"""
83+
headers = headers or self.put_headers
84+
url = self.auth.base_url + endpoint
85+
86+
return requests.put(url=url, json=body, headers=headers.dict(by_alias=True))
87+
88+
def delete(
89+
self, endpoint: str, headers: RequestHeaders = None
90+
) -> requests.Response:
91+
"""Send an HTTP delete request to base_url + endpoint.
92+
93+
:param endpoint: Which endpoint to hit
94+
:return: Received response
95+
"""
96+
headers = headers or self.delete_headers
97+
url = self.auth.base_url + endpoint
98+
99+
return requests.delete(url=url, headers=headers.dict(by_alias=True))

infobip_channels/core/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ class PostHeaders(RequestHeaders):
9696
content_type: Optional[str] = "application/json"
9797

9898

99+
class PutHeaders(RequestHeaders):
100+
content_type: Optional[str] = "application/json"
101+
102+
103+
class DeleteHeaders(RequestHeaders):
104+
pass
105+
106+
99107
class PathParameter(CamelCaseModel):
100108
sender: str
101109

infobip_channels/web_rtc/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)