Skip to content

Commit 9614eae

Browse files
committed
chore: fixed serialiser for enums, added url builder
1 parent 550250b commit 9614eae

12 files changed

+118
-109
lines changed

sendgrid/__init__.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from .helpers.endpoints import * # noqa
1919
from .helpers.mail import * # noqa
2020
from .helpers.stats import * # noqa
21-
from .helpers.eventwebhook import * # noqa
21+
from .helpers.eventwebhook import * # noqa
2222
from .sendgrid import SendGridAPIClient # noqa
2323
from .twilio_email import TwilioEmailAPIClient # noqa
24-
from .version import __version__

sendgrid/base/__init__.py

-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
import os
2-
import platform
3-
41
# __init__.py
5-

sendgrid/base/auth_strategy.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
2-
3-
# Handle different of authentications, Currently sendgrid authenticate using apikey.
1+
# Handle different of authentications, Currently sendgrid authenticate using apikey.
42
# class AuthStrategy:
53
# def authenticate(self):
64
# print('Not yet implemented')
7-
#
8-
#
5+
#
6+
#
97
# class ApiKeyAuthStrategy(AuthStrategy):
108
# def __init__(self, api_key):
119
# self.api_key = api_key
1210
# print('init ApiKeyAuthStrategy')
1311
# def authenticate(self, api_key):
14-
# print(f"Authenticating {api_key} using Token Authentication.")
12+
# print(f"Authenticating {api_key} using Token Authentication.")

sendgrid/base/client_base.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
class ClientBase:
22

33
def __init__(self):
4-
print('Creating ClientBase class')
4+
print("Creating ClientBase class")
55

66
def request(self):
7-
print('Making request')
8-
9-
7+
print("Making request")

sendgrid/base/url_builder.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
def build_url(url: str, region: str) -> str:
2+
base_url = "https://api.sendgrid.com"
3+
4+
if region and isinstance(region, str):
5+
new_url = f"https://api.{region}.sendgrid.com"
6+
else:
7+
new_url = base_url
8+
9+
# Ensure that there's a '/' before appending the url
10+
if not new_url.endswith('/'):
11+
new_url += '/'
12+
13+
new_url += url.lstrip('/')
14+
15+
return new_url
16+

sendgrid/client.py

+20-19
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,33 @@
1-
import os
2-
import platform
3-
from typing import Dict, List, MutableMapping, Optional, Tuple
4-
from urllib.parse import urlparse, urlunparse
5-
import json
1+
from typing import List, Optional
62
from sendgrid.http.http_client import SendgridHttpClient, HttpClient
73
from sendgrid.http.request import Request
8-
9-
4+
from sendgrid.base.url_builder import build_url
105

116
# class AuthStrategy:
127
# def authenticate(self):
138
# pass
14-
#
15-
#
9+
#
10+
#
1611
# class ApiKeyAuthStrategy(AuthStrategy):
1712
# def __init__(self, api_key):
1813
# self.api_key = api_key
19-
#
14+
#
2015
# def authenticate(
2116
# self,
2217
# headers: Optional[Dict[str, str]] = None
2318
# ):
2419
# headers["Authorization"] = f"Bearer {self.api_key}"
25-
#
20+
#
21+
2622

2723
class Client:
2824
def __init__(
29-
self,
30-
api_key: str,
31-
region: Optional[str] = None,
32-
edge: Optional[str] = None,
33-
http_client: Optional[HttpClient] = None,
34-
user_agent_extensions: Optional[List[str]] = None
25+
self,
26+
api_key: str,
27+
region: Optional[str] = None,
28+
edge: Optional[str] = None,
29+
http_client: Optional[HttpClient] = None,
30+
user_agent_extensions: Optional[List[str]] = None,
3531
):
3632
self.api_key = api_key
3733
self.region = region
@@ -40,7 +36,12 @@ def __init__(
4036
self.http_client: SendgridHttpClient = SendgridHttpClient()
4137

4238
def send(self, request: Request):
39+
url = build_url(request.url, self.region)
4340
response = self.http_client.request(
44-
method='POST', url=request.url, data=request.data, headers=request.headers, api_key=self.api_key
41+
method=request.method,
42+
url=url,
43+
data=request.data,
44+
headers=request.headers,
45+
api_key=self.api_key,
4546
)
46-
return response
47+
return response

sendgrid/converters/serialize.py

+16-7
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@
55

66
def to_serializable(obj):
77
if isinstance(obj, list):
8-
return [to_serializable(item) for item in obj if item is not None] # Remove None from lists
8+
return [
9+
to_serializable(item) for item in obj if item is not None
10+
] # Remove None from lists
911
elif isinstance(obj, dict):
10-
return {key: to_serializable(value) for key, value in obj.items() if
11-
value is not None} # Remove None from dicts
12-
elif hasattr(obj, 'to_dict'):
12+
return {
13+
key: to_serializable(value)
14+
for key, value in obj.items()
15+
if value is not None
16+
} # Remove None from dicts
17+
elif hasattr(obj, "to_dict"):
1318
return obj.to_dict()
1419
elif isinstance(obj, Enum):
15-
return obj.name
20+
return obj.value
1621
else:
1722
return obj
1823

@@ -23,12 +28,16 @@ def from_serializable(data, cls=None):
2328
If `cls` is provided, it will instantiate the class using the dictionary values.
2429
"""
2530
if isinstance(data, list):
26-
return [from_serializable(item, cls) for item in data] # Recursively handle lists
31+
return [
32+
from_serializable(item, cls) for item in data
33+
] # Recursively handle lists
2734
elif isinstance(data, dict):
2835
if cls:
2936
# If a class is provided, instantiate it using the dictionary
3037
return cls(**{key: from_serializable(value) for key, value in data.items()})
3138
else:
32-
return {key: from_serializable(value) for key, value in data.items()} # Recursively handle dicts
39+
return {
40+
key: from_serializable(value) for key, value in data.items()
41+
} # Recursively handle dicts
3342
else:
3443
return data # Return primitive types as is

sendgrid/http/__init__.py

-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
11

2-
from logging import Logger
3-
from typing import Any, Dict, Optional, Tuple
4-
from urllib.parse import urlencode
5-

sendgrid/http/http_client.py

+40-38
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ def __init__(self, logger: Logger, is_async: bool, timeout: Optional[float] = No
3030
"""
3131

3232
def request(
33-
self,
34-
method: str,
35-
uri: str,
36-
params: Optional[Dict[str, object]] = None,
37-
data: Optional[Dict[str, object]] = None,
38-
headers: Optional[Dict[str, str]] = None,
39-
auth: Optional[Tuple[str, str]] = None,
40-
timeout: Optional[float] = None,
41-
allow_redirects: bool = False,
33+
self,
34+
method: str,
35+
uri: str,
36+
params: Optional[Dict[str, object]] = None,
37+
data: Optional[Dict[str, object]] = None,
38+
headers: Optional[Dict[str, str]] = None,
39+
auth: Optional[Tuple[str, str]] = None,
40+
timeout: Optional[float] = None,
41+
allow_redirects: bool = False,
4242
) -> Response:
4343
"""
4444
Make an HTTP request.
@@ -84,15 +84,15 @@ class AsyncHttpClient(HttpClient):
8484
"""
8585

8686
async def request(
87-
self,
88-
method: str,
89-
uri: str,
90-
params: Optional[Dict[str, object]] = None,
91-
data: Optional[Dict[str, object]] = None,
92-
headers: Optional[Dict[str, str]] = None,
93-
auth: Optional[Tuple[str, str]] = None,
94-
timeout: Optional[float] = None,
95-
allow_redirects: bool = False,
87+
self,
88+
method: str,
89+
uri: str,
90+
params: Optional[Dict[str, object]] = None,
91+
data: Optional[Dict[str, object]] = None,
92+
headers: Optional[Dict[str, str]] = None,
93+
auth: Optional[Tuple[str, str]] = None,
94+
timeout: Optional[float] = None,
95+
allow_redirects: bool = False,
9696
) -> Response:
9797
"""
9898
Make an asynchronous HTTP request.
@@ -106,13 +106,13 @@ class SendgridHttpClient(HttpClient):
106106
"""
107107

108108
def __init__(
109-
self,
110-
pool_connections: bool = True,
111-
request_hooks: Optional[Dict[str, object]] = None,
112-
timeout: Optional[float] = None,
113-
logger: logging.Logger = _logger,
114-
proxy: Optional[Dict[str, str]] = None,
115-
max_retries: Optional[int] = None,
109+
self,
110+
pool_connections: bool = True,
111+
request_hooks: Optional[Dict[str, object]] = None,
112+
timeout: Optional[float] = None,
113+
logger: logging.Logger = _logger,
114+
proxy: Optional[Dict[str, str]] = None,
115+
max_retries: Optional[int] = None,
116116
):
117117
"""
118118
Constructor for the TwilioHttpClient
@@ -136,20 +136,20 @@ def __init__(
136136
self.proxy = proxy if proxy else {}
137137

138138
def request(
139-
self,
140-
method: str,
141-
url: str,
142-
api_key: str = None,
143-
params: Optional[Dict[str, object]] = None,
144-
data: Optional[Dict[str, object]] = None,
145-
headers: Optional[Dict[str, str]] = None,
146-
timeout: Optional[float] = None,
147-
allow_redirects: bool = False,
139+
self,
140+
method: str,
141+
url: str,
142+
api_key: str = None,
143+
params: Optional[Dict[str, object]] = None,
144+
data: Optional[Dict[str, object]] = None,
145+
headers: Optional[Dict[str, str]] = None,
146+
timeout: Optional[float] = None,
147+
allow_redirects: bool = False,
148148
) -> Response:
149149
"""
150150
Make an HTTP Request with parameters provided.
151151
152-
:param api_key:
152+
:param api_key:
153153
:param method: The HTTP method to use
154154
:param url: The URL to request
155155
:param params: Query parameters to append to the URL
@@ -167,7 +167,9 @@ def request(
167167
raise ValueError(timeout)
168168

169169
headers["Authorization"] = f"Bearer {api_key}"
170-
#auth.authenticate()
170+
# Currently supporting 'application/json' content type
171+
headers["Content-Type"] = "application/json"
172+
# auth.authenticate()
171173
kwargs = {
172174
"method": method.upper(),
173175
"url": url,
@@ -185,7 +187,7 @@ def request(
185187
session = self.session or Session()
186188
request = Request(**kwargs)
187189
self._test_only_last_request = Request(**kwargs)
188-
190+
189191
prepped_request = session.prepare_request(request)
190192

191193
settings = session.merge_environment_settings(
@@ -196,7 +198,7 @@ def request(
196198
prepped_request,
197199
allow_redirects=allow_redirects,
198200
timeout=timeout,
199-
**settings
201+
**settings,
200202
)
201203
print(response)
202204
print(response.status_code)

sendgrid/http/request.py

+14-14
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ class Match(Enum):
99

1010
class Request(object):
1111
def __init__(
12-
self,
13-
method: Union[str, Match] = Match.ANY,
14-
url: Union[str, Match] = Match.ANY,
15-
auth: Union[Tuple[str, str], Match] = Match.ANY,
16-
params: Union[Dict[str, str], Match] = Match.ANY,
17-
data: Union[Dict[str, str], Match] = Match.ANY,
18-
headers: Union[Dict[str, str], Match] = Match.ANY,
19-
**kwargs: Any
12+
self,
13+
method: Union[str, Match] = Match.ANY,
14+
url: Union[str, Match] = Match.ANY,
15+
auth: Union[Tuple[str, str], Match] = Match.ANY,
16+
params: Union[Dict[str, str], Match] = Match.ANY,
17+
data: Union[Dict[str, str], Match] = Match.ANY,
18+
headers: Union[Dict[str, str], Match] = Match.ANY,
19+
**kwargs: Any
2020
):
2121
self.method = method
2222
if method and method is not Match.ANY:
@@ -43,12 +43,12 @@ def __eq__(self, other) -> bool:
4343
return False
4444

4545
return (
46-
self.attribute_equal(self.method, other.method)
47-
and self.attribute_equal(self.url, other.url)
48-
and self.attribute_equal(self.auth, other.auth)
49-
and self.attribute_equal(self.params, other.params)
50-
and self.attribute_equal(self.data, other.data)
51-
and self.attribute_equal(self.headers, other.headers)
46+
self.attribute_equal(self.method, other.method)
47+
and self.attribute_equal(self.url, other.url)
48+
and self.attribute_equal(self.auth, other.auth)
49+
and self.attribute_equal(self.params, other.params)
50+
and self.attribute_equal(self.data, other.data)
51+
and self.attribute_equal(self.headers, other.headers)
5252
)
5353

5454
def __str__(self) -> str:

sendgrid/http/response.py

+5-10
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ class HTTPStatus:
99

1010
class Response(object):
1111
def __init__(
12-
self,
13-
status_code: int,
14-
text: str,
15-
headers: Optional[Any] = None,
12+
self,
13+
status_code: int,
14+
text: str,
15+
headers: Optional[Any] = None,
1616
):
1717
self.content = text
1818
self.headers = headers
@@ -32,12 +32,7 @@ def __str__(self) -> str:
3232

3333

3434
class ApiResponse(object):
35-
def __init__(
36-
self,
37-
status_code,
38-
model,
39-
headers
40-
):
35+
def __init__(self, status_code, model, headers):
4136
self.status_code = status_code
4237
self.model = model
4338
self.headers = headers

sendgrid/utility/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,3 @@ def parse_response(self, response: Response) -> Any:
1010
raise self.exception(response, "Unable to create record")
1111

1212
return json.loads(response.text)
13-

0 commit comments

Comments
 (0)