Skip to content

Commit 693023c

Browse files
committed
Fix the compatibility issue with boto3
1 parent 44d1ca2 commit 693023c

File tree

3 files changed

+183
-178
lines changed

3 files changed

+183
-178
lines changed

src/sns_extended_client/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
from .session import SNSExtendedClientSession
44

5-
# Monkey patch to use our Session object instead of boto3's
6-
boto3.session.Session = SNSExtendedClientSession
5+
setattr(boto3.session, "Session", SNSExtendedClientSession)
76

87
# Now take care of the reference in the boto3.__init__ module
98
setattr(boto3, "Session", SNSExtendedClientSession)
109

1110
# Now ensure that even the default session is our SNSExtendedClientSession
1211
if boto3.DEFAULT_SESSION:
13-
boto3.setup_default_session()
12+
boto3.setup_default_session()

src/sns_extended_client/session.py

Lines changed: 90 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
from uuid import uuid4
33

44
import boto3
5+
56
import botocore.session
6-
from boto3 import resource
7+
8+
import logging
9+
logger = logging.getLogger("sns_extended_client.client")
10+
logger.setLevel(logging.WARNING)
711

812
from .exceptions import MissingPayloadOffloadingResource, SNSExtendedClientException
913

@@ -85,23 +89,6 @@ def _set_use_legacy_attribute(self, use_legacy_attribute: bool):
8589
setattr(self, "__use_legacy_attribute", use_legacy_attribute)
8690

8791

88-
def _delete_s3(self):
89-
if hasattr(self, "__s3"):
90-
del self.__s3
91-
92-
93-
def _get_s3(self):
94-
s3 = getattr(self, "__s3", None)
95-
if not s3:
96-
s3 = resource("s3")
97-
self.s3 = s3
98-
return s3
99-
100-
101-
def _set_s3(self, s3):
102-
setattr(self, "__s3", s3)
103-
104-
10592
def _is_large_message(self, attributes: dict, encoded_body: bytes):
10693
total = 0
10794
for key, value in attributes.items():
@@ -147,14 +134,6 @@ def _get_s3_key(self, message_attributes: dict):
147134
return str(uuid4())
148135

149136

150-
def _create_s3_put_object_params(self, encoded_body: bytes):
151-
return {
152-
"ACL": "private",
153-
"Body": encoded_body,
154-
"ContentLength": len(encoded_body),
155-
}
156-
157-
158137
def _create_reserved_message_attribute_value(self, encoded_body_size_string):
159138
return {"DataType": "Number", "StringValue": encoded_body_size_string}
160139

@@ -197,9 +176,7 @@ def _make_payload(self, message_attributes: dict, message_body, message_structur
197176

198177
s3_key = self._get_s3_key(message_attributes)
199178

200-
self.s3.Object(self.large_payload_support, s3_key).put(
201-
**self._create_s3_put_object_params(encoded_body)
202-
)
179+
self.s3_client.put_object(Bucket=self.large_payload_support, Key=s3_key, Body=encoded_body)
203180

204181
message_body = dumps(
205182
[
@@ -211,53 +188,6 @@ def _make_payload(self, message_attributes: dict, message_body, message_structur
211188
return message_attributes, message_body
212189

213190

214-
def _add_custom_attributes(class_attributes: dict):
215-
class_attributes["large_payload_support"] = property(
216-
_get_large_payload_support,
217-
_set_large_payload_support,
218-
_delete_large_payload_support,
219-
)
220-
class_attributes["message_size_threshold"] = property(
221-
_get_message_size_threshold,
222-
_set_message_size_threshold,
223-
_delete_messsage_size_threshold,
224-
)
225-
class_attributes["always_through_s3"] = property(
226-
_get_always_through_s3,
227-
_set_always_through_s3,
228-
_delete_always_through_s3,
229-
)
230-
class_attributes["use_legacy_attribute"] = property(
231-
_get_use_legacy_attribute,
232-
_set_use_legacy_attribute,
233-
_delete_use_legacy_attribute,
234-
)
235-
class_attributes["s3"] = property(_get_s3, _set_s3, _delete_s3)
236-
237-
class_attributes["_create_s3_put_object_params"] = _create_s3_put_object_params
238-
class_attributes[
239-
"_create_reserved_message_attribute_value"
240-
] = _create_reserved_message_attribute_value
241-
class_attributes["_is_large_message"] = _is_large_message
242-
class_attributes["_make_payload"] = _make_payload
243-
class_attributes["_get_s3_key"] = _get_s3_key
244-
class_attributes["_check_size_of_message_attributes"] = _check_size_of_message_attributes
245-
class_attributes["_check_message_attributes"] = _check_message_attributes
246-
class_attributes["publish"] = _publish_decorator(class_attributes["publish"])
247-
248-
249-
def _add_client_custom_attributes(base_classes, **kwargs):
250-
_add_custom_attributes(kwargs["class_attributes"])
251-
252-
253-
def _add_topic_resource_custom_attributes(class_attributes, **kwargs):
254-
_add_custom_attributes(class_attributes)
255-
256-
257-
def _add_platform_endpoint_resource_custom_attributes(class_attributes, **kwargs):
258-
_add_custom_attributes(class_attributes)
259-
260-
261191
def _publish_decorator(func):
262192
def _publish(self, **kwargs):
263193
if (
@@ -270,14 +200,39 @@ def _publish(self, **kwargs):
270200
kwargs["MessageAttributes"], kwargs["Message"] = self._make_payload(
271201
kwargs.get("MessageAttributes", {}),
272202
kwargs["Message"],
273-
kwargs.get("MessageStructure", None),
203+
kwargs.get("MessageStructure",None),
274204
)
275205
return func(self, **kwargs)
276206

277207
return _publish
278208

279209

210+
280211
class SNSExtendedClientSession(boto3.session.Session):
212+
213+
"""
214+
A session stores configuration state and allows you to create service
215+
clients and resources. SNSExtendedClientSession extends the functionality
216+
of the boto3 Session object by using the .register event functionality.
217+
218+
:type aws_access_key_id: string
219+
:param aws_access_key_id: AWS access key ID
220+
:type aws_secret_access_key: string
221+
:param aws_secret_access_key: AWS secret access key
222+
:type aws_session_token: string
223+
:param aws_session_token: AWS temporary session token
224+
:type region_name: string
225+
:param region_name: Default region when creating new connections
226+
:type botocore_session: botocore.session.Session
227+
:param botocore_session: Use this Botocore session instead of creating
228+
a new default one.
229+
:type profile_name: string
230+
:param profile_name: The name of a profile to use. If not given, then
231+
the default profile is used.
232+
233+
"""
234+
235+
281236
def __init__(
282237
self,
283238
aws_access_key_id=None,
@@ -288,31 +243,78 @@ def __init__(
288243
profile_name=None,
289244
):
290245
if botocore_session is None:
291-
botocore_session = botocore.session.get_session()
246+
self._session = botocore.session.get_session()
247+
else:
248+
self._session = botocore_session
292249

293-
user_agent_header = self.__class__.__name__
250+
self.add_custom_user_agent()
294251

295-
# Attaching SNSExtendedClient Session to the HTTP headers
296-
if botocore_session.user_agent_extra:
297-
botocore_session.user_agent_extra += " " + user_agent_header
298-
else:
299-
botocore_session.user_agent_extra = user_agent_header
252+
300253

301254
super().__init__(
302255
aws_access_key_id=aws_access_key_id,
303256
aws_secret_access_key=aws_secret_access_key,
304257
aws_session_token=aws_session_token,
305258
region_name=region_name,
306-
botocore_session=botocore_session,
259+
botocore_session=self._session,
307260
profile_name=profile_name,
308261
)
309262

310-
self.events.register("creating-client-class.sns", _add_client_custom_attributes)
263+
# Adding Additional attributes for sns Client, Topic and PlatformEndpoint Objects
264+
self.events.register("creating-client-class.sns", self.add_custom_attributes)
311265
self.events.register(
312266
"creating-resource-class.sns.Topic",
313-
_add_topic_resource_custom_attributes,
267+
self.add_custom_attributes,
314268
)
315269
self.events.register(
316270
"creating-resource-class.sns.PlatformEndpoint",
317-
_add_platform_endpoint_resource_custom_attributes,
271+
self.add_custom_attributes,
272+
)
273+
274+
def add_custom_user_agent(self):
275+
# Attaching SNSExtendedClient Session to the HTTP headers
276+
277+
user_agent_header = self.__class__.__name__
278+
279+
if self._session.user_agent_extra:
280+
self._session.user_agent_extra += " " + user_agent_header
281+
else:
282+
self._session.user_agent_extra = user_agent_header
283+
284+
def add_custom_attributes(self,class_attributes,**kwargs):
285+
286+
287+
class_attributes["large_payload_support"] = property(
288+
_get_large_payload_support,
289+
_set_large_payload_support,
290+
_delete_large_payload_support,
291+
)
292+
class_attributes["message_size_threshold"] = property(
293+
_get_message_size_threshold,
294+
_set_message_size_threshold,
295+
_delete_messsage_size_threshold,
296+
)
297+
class_attributes["always_through_s3"] = property(
298+
_get_always_through_s3,
299+
_set_always_through_s3,
300+
_delete_always_through_s3,
301+
)
302+
class_attributes["use_legacy_attribute"] = property(
303+
_get_use_legacy_attribute,
304+
_set_use_legacy_attribute,
305+
_delete_use_legacy_attribute,
318306
)
307+
class_attributes["s3_client"] = super().client("s3")
308+
309+
class_attributes[
310+
"_create_reserved_message_attribute_value"
311+
] = _create_reserved_message_attribute_value
312+
class_attributes["_is_large_message"] = _is_large_message
313+
class_attributes["_make_payload"] = _make_payload
314+
class_attributes["_get_s3_key"] = _get_s3_key
315+
316+
# Adding the S3 client to the object
317+
318+
class_attributes["_check_size_of_message_attributes"] = _check_size_of_message_attributes
319+
class_attributes["_check_message_attributes"] = _check_message_attributes
320+
class_attributes["publish"] = _publish_decorator(class_attributes["publish"])

0 commit comments

Comments
 (0)