reach_commons 0.18.22__tar.gz → 0.18.24__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {reach_commons-0.18.22 → reach_commons-0.18.24}/PKG-INFO +6 -4
- {reach_commons-0.18.22 → reach_commons-0.18.24}/README.md +25 -25
- {reach_commons-0.18.22 → reach_commons-0.18.24}/pyproject.toml +40 -40
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_aws/dynamo_db.py +5 -3
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_aws/kms.py +3 -3
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_aws/sqs.py +75 -35
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/__init__.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/app_logging/__init__.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/app_logging/http_logger.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/app_logging/log_deprecated_endpoints.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/app_logging/logger.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/app_logging/logging_config.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/clients/__init__.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/clients/event_processor.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/clients/hubspot.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/clients/outscraper.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/clients/reach_data_bridge.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/clients/reach_ops_api.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/mongo/__init__.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/mongo/customer_persistence.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/mongo/customer_persistence_async.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/mongo/validation/__init__.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_aws/__init__.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_aws/commons.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_aws/exceptions.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_aws/firehose.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_aws/s3.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/reach_base_model.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/redis_manager.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/sms_smart_encoding.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/utils.py +0 -0
- {reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/validations.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: reach_commons
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.24
|
|
4
4
|
Summary: Reach Commons is a versatile utility library designed to streamline and enhance development workflows within the Reach ecosystem.
|
|
5
5
|
License: MIT
|
|
6
|
-
Author:
|
|
7
|
-
Author-email:
|
|
6
|
+
Author: Engineering
|
|
7
|
+
Author-email: engineering@getreach.ai
|
|
8
8
|
Requires-Python: >=3.8,<4.0
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
@@ -14,6 +14,8 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
19
|
Requires-Dist: curlify (==3.0.0)
|
|
18
20
|
Requires-Dist: fastapi (>=0.115.5)
|
|
19
21
|
Requires-Dist: pydantic (>=2.9.2)
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
# reach_commons
|
|
2
|
-
|
|
3
|
-
## Description
|
|
4
|
-
|
|
5
|
-
`reach_commons` is a Python library that provides various classes and utilities to assist developers in their projects. This library aims to simplify and streamline processes by offering reusable components that can be easily integrated into various Python applications.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
Install `reach_commons` using pip:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
pip install reach_commons
|
|
13
|
-
|
|
14
|
-
from reach_commons.api_client_v2 import ReachApiGatewayV2
|
|
15
|
-
|
|
16
|
-
api_gateway = ReachApiGatewayV2(
|
|
17
|
-
base_url=os.environ["api_gateway_v2_endpoint"],
|
|
18
|
-
access_token=os.environ["event_processor_token"],
|
|
19
|
-
)
|
|
20
|
-
response = api_gateway.stripe_create_booking_guarantee(
|
|
21
|
-
business_id=business_id, booking_price=booking_price
|
|
22
|
-
)
|
|
23
|
-
{
|
|
24
|
-
"statusCode": stripe_customer.status_code,
|
|
25
|
-
"body": json.dumps(response.json()),
|
|
1
|
+
# reach_commons
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
`reach_commons` is a Python library that provides various classes and utilities to assist developers in their projects. This library aims to simplify and streamline processes by offering reusable components that can be easily integrated into various Python applications.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Install `reach_commons` using pip:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install reach_commons
|
|
13
|
+
|
|
14
|
+
from reach_commons.api_client_v2 import ReachApiGatewayV2
|
|
15
|
+
|
|
16
|
+
api_gateway = ReachApiGatewayV2(
|
|
17
|
+
base_url=os.environ["api_gateway_v2_endpoint"],
|
|
18
|
+
access_token=os.environ["event_processor_token"],
|
|
19
|
+
)
|
|
20
|
+
response = api_gateway.stripe_create_booking_guarantee(
|
|
21
|
+
business_id=business_id, booking_price=booking_price
|
|
22
|
+
)
|
|
23
|
+
{
|
|
24
|
+
"statusCode": stripe_customer.status_code,
|
|
25
|
+
"body": json.dumps(response.json()),
|
|
26
26
|
}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
# isort .; black .; poetry build; poetry publish
|
|
2
|
-
[tool.poetry]
|
|
3
|
-
name = "reach_commons"
|
|
4
|
-
version = "0.18.
|
|
5
|
-
description = "Reach Commons is a versatile utility library designed to streamline and enhance development workflows within the Reach ecosystem."
|
|
6
|
-
authors = ["
|
|
7
|
-
license = "MIT"
|
|
8
|
-
readme = "README.md"
|
|
9
|
-
|
|
10
|
-
classifiers = [
|
|
11
|
-
"Programming Language :: Python :: 3",
|
|
12
|
-
"License :: OSI Approved :: MIT License",
|
|
13
|
-
"Operating System :: OS Independent",
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
[tool.poetry.dependencies]
|
|
17
|
-
python = "^3.8"
|
|
18
|
-
#pip = "23.3.1"
|
|
19
|
-
setuptools = "70.0.0"
|
|
20
|
-
wheel = "0.41.2"
|
|
21
|
-
twine = "4.0.2"
|
|
22
|
-
curlify = "3.0.0"
|
|
23
|
-
pydantic = ">=2.9.2"
|
|
24
|
-
fastapi = ">=0.115.5"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
[tool.poetry.dev-dependencies]
|
|
28
|
-
black = "23.10.0"
|
|
29
|
-
isort = "5.12.0"
|
|
30
|
-
requests = "2.31.0"
|
|
31
|
-
boto3 = "1.28.68"
|
|
32
|
-
botocore = "^1.31.68"
|
|
33
|
-
redis = "^4.1.3"
|
|
34
|
-
pydantic-settings = "2.3.1"
|
|
35
|
-
jsonschema = "4.23.0"
|
|
36
|
-
motor = "3.6.0"
|
|
37
|
-
pymongo = "4.9.2"
|
|
38
|
-
|
|
39
|
-
[build-system]
|
|
40
|
-
requires = ["poetry-core>=1.0.0"]
|
|
1
|
+
# isort .; black .; poetry build; poetry publish
|
|
2
|
+
[tool.poetry]
|
|
3
|
+
name = "reach_commons"
|
|
4
|
+
version = "0.18.24"
|
|
5
|
+
description = "Reach Commons is a versatile utility library designed to streamline and enhance development workflows within the Reach ecosystem."
|
|
6
|
+
authors = ["Engineering <engineering@getreach.ai>"]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Programming Language :: Python :: 3",
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Operating System :: OS Independent",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[tool.poetry.dependencies]
|
|
17
|
+
python = "^3.8"
|
|
18
|
+
#pip = "23.3.1"
|
|
19
|
+
setuptools = "70.0.0"
|
|
20
|
+
wheel = "0.41.2"
|
|
21
|
+
twine = "4.0.2"
|
|
22
|
+
curlify = "3.0.0"
|
|
23
|
+
pydantic = ">=2.9.2"
|
|
24
|
+
fastapi = ">=0.115.5"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
[tool.poetry.dev-dependencies]
|
|
28
|
+
black = "23.10.0"
|
|
29
|
+
isort = "5.12.0"
|
|
30
|
+
requests = "2.31.0"
|
|
31
|
+
boto3 = "1.28.68"
|
|
32
|
+
botocore = "^1.31.68"
|
|
33
|
+
redis = "^4.1.3"
|
|
34
|
+
pydantic-settings = "2.3.1"
|
|
35
|
+
jsonschema = "4.23.0"
|
|
36
|
+
motor = "3.6.0"
|
|
37
|
+
pymongo = "4.9.2"
|
|
38
|
+
|
|
39
|
+
[build-system]
|
|
40
|
+
requires = ["poetry-core>=1.0.0"]
|
|
41
41
|
build-backend = "poetry.core.masonry.api"
|
|
@@ -174,9 +174,11 @@ class BusinessReviewsCommonQueries:
|
|
|
174
174
|
Item={
|
|
175
175
|
"PK": f"business#{business_id}",
|
|
176
176
|
"SK": "info",
|
|
177
|
-
"created_at":
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
"created_at": (
|
|
178
|
+
created_at_isoformat
|
|
179
|
+
if created_at_isoformat
|
|
180
|
+
else datetime.utcnow().isoformat()
|
|
181
|
+
),
|
|
180
182
|
**filtered_info,
|
|
181
183
|
},
|
|
182
184
|
ConditionExpression="attribute_not_exists(PK) AND attribute_not_exists(SK)",
|
|
@@ -97,9 +97,9 @@ class KMSClient(BaseKMSClient):
|
|
|
97
97
|
ciphertext = self.client.encrypt(
|
|
98
98
|
KeyId=key_alias,
|
|
99
99
|
Plaintext=bytes(data_to_encrypt, encoding="utf8"),
|
|
100
|
-
EncryptionContext=
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
EncryptionContext=(
|
|
101
|
+
{"CustomContext": f"{custom_context}"} if custom_context else None
|
|
102
|
+
),
|
|
103
103
|
)
|
|
104
104
|
encrypted = base64.b64encode(ciphertext["CiphertextBlob"])
|
|
105
105
|
except ClientError as exc:
|
|
@@ -4,7 +4,6 @@ from decimal import Decimal
|
|
|
4
4
|
from functools import cached_property
|
|
5
5
|
|
|
6
6
|
import boto3
|
|
7
|
-
import requests
|
|
8
7
|
from botocore.exceptions import ClientError
|
|
9
8
|
|
|
10
9
|
from reach_commons.app_logging.logger import get_reach_logger
|
|
@@ -147,6 +146,81 @@ class SQSClient(BaseSQSClient):
|
|
|
147
146
|
|
|
148
147
|
return True
|
|
149
148
|
|
|
149
|
+
def _get_visible_messages_count(self) -> int:
|
|
150
|
+
try:
|
|
151
|
+
resp = self.client.get_queue_attributes(
|
|
152
|
+
QueueUrl=self.topic_name,
|
|
153
|
+
AttributeNames=["ApproximateNumberOfMessages"],
|
|
154
|
+
)
|
|
155
|
+
return int(resp["Attributes"].get("ApproximateNumberOfMessages", 0))
|
|
156
|
+
except ClientError as exc:
|
|
157
|
+
self.logger.error(
|
|
158
|
+
"error_fetching_queue_attributes, topic_name=%s, error=%s",
|
|
159
|
+
self.topic_name,
|
|
160
|
+
str(exc),
|
|
161
|
+
)
|
|
162
|
+
# If there's an error, return 0 so as not to block the caller.
|
|
163
|
+
return 0
|
|
164
|
+
|
|
165
|
+
def publish_with_capacity_guard(
|
|
166
|
+
self,
|
|
167
|
+
message_data: dict,
|
|
168
|
+
max_capacity: int,
|
|
169
|
+
delay_seconds: int = 60,
|
|
170
|
+
message_attributes: dict = None,
|
|
171
|
+
) -> dict:
|
|
172
|
+
"""
|
|
173
|
+
Attempts to publish a message while enforcing an approximate queue capacity limit.
|
|
174
|
+
|
|
175
|
+
Behavior:
|
|
176
|
+
- If the queue is below `max_capacity`, the message is published normally.
|
|
177
|
+
- If the queue is at or above `max_capacity`, the message is NOT published.
|
|
178
|
+
|
|
179
|
+
Returns a dict with:
|
|
180
|
+
- posted: bool -> whether the message was actually published
|
|
181
|
+
- visible_count: int -> ApproximateNumberOfMessages at publication time
|
|
182
|
+
- max_capacity: int -> the capacity threshold used
|
|
183
|
+
|
|
184
|
+
Example:
|
|
185
|
+
sqs = SQSClient(topic_name="<enviroment>-messages-queue")
|
|
186
|
+
|
|
187
|
+
Result = sqs.publish_with_capacity_guard(
|
|
188
|
+
message_data={"foo": "bar"},
|
|
189
|
+
max_capacity=100_000,
|
|
190
|
+
delay_seconds=30,
|
|
191
|
+
message_attributes={"service_name": "TestClient"},
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
if not Result["posted"]:
|
|
195
|
+
print("Queue is over capacity:", Result)
|
|
196
|
+
"""
|
|
197
|
+
visible_count = self._get_visible_messages_count()
|
|
198
|
+
|
|
199
|
+
if visible_count >= max_capacity:
|
|
200
|
+
self.logger.warning(
|
|
201
|
+
"queue_over_capacity, topic_name=%s, visible=%s, max_capacity=%s",
|
|
202
|
+
self.topic_name,
|
|
203
|
+
visible_count,
|
|
204
|
+
max_capacity,
|
|
205
|
+
)
|
|
206
|
+
return {
|
|
207
|
+
"posted": False,
|
|
208
|
+
"visible_count": visible_count,
|
|
209
|
+
"max_capacity": max_capacity,
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
self.publish(
|
|
213
|
+
message_data=message_data,
|
|
214
|
+
delay_seconds=delay_seconds,
|
|
215
|
+
message_attributes=message_attributes,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
"posted": True,
|
|
220
|
+
"visible_count": visible_count,
|
|
221
|
+
"max_capacity": max_capacity,
|
|
222
|
+
}
|
|
223
|
+
|
|
150
224
|
|
|
151
225
|
class MessageFilter:
|
|
152
226
|
"""
|
|
@@ -234,15 +308,6 @@ class HubspotSQSNotifier(SQSClient):
|
|
|
234
308
|
logger=logger,
|
|
235
309
|
topic_name=f"{env}-{self.TOPIC_NAME}",
|
|
236
310
|
)
|
|
237
|
-
self.env = env
|
|
238
|
-
|
|
239
|
-
@cached_property
|
|
240
|
-
def lambda_client(self):
|
|
241
|
-
session = boto3.Session(
|
|
242
|
-
region_name=self.region_name,
|
|
243
|
-
profile_name=self.profile_name,
|
|
244
|
-
)
|
|
245
|
-
return session.client("lambda")
|
|
246
311
|
|
|
247
312
|
def send_message(
|
|
248
313
|
self, object_name, object_id, secondary_object_id=None, delay_seconds=60
|
|
@@ -283,30 +348,6 @@ class HubspotSQSNotifier(SQSClient):
|
|
|
283
348
|
return delay_seconds
|
|
284
349
|
|
|
285
350
|
def notify_business_change(self, business_id, delay_seconds=60):
|
|
286
|
-
try:
|
|
287
|
-
resp = requests.get(
|
|
288
|
-
"https://asoekaw.free.beeceptor.com/processing/eligibility",
|
|
289
|
-
timeout=10,
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
data = resp.json()
|
|
293
|
-
|
|
294
|
-
if data.get("allowed", False):
|
|
295
|
-
repeat = int(data.get("repeat", 1))
|
|
296
|
-
for _ in range(repeat):
|
|
297
|
-
self.lambda_client.invoke(
|
|
298
|
-
FunctionName=f"{self.env}-nightly-lambda",
|
|
299
|
-
InvocationType="Event",
|
|
300
|
-
Payload=json.dumps(
|
|
301
|
-
{
|
|
302
|
-
"event": "hourly_15",
|
|
303
|
-
"override_status": True,
|
|
304
|
-
}
|
|
305
|
-
).encode("utf-8"),
|
|
306
|
-
)
|
|
307
|
-
except Exception:
|
|
308
|
-
pass
|
|
309
|
-
|
|
310
351
|
return self.send_message(
|
|
311
352
|
object_name="business_change",
|
|
312
353
|
object_id=business_id,
|
|
@@ -538,7 +579,6 @@ class POSApiPullerSQSNotifier(SQSClient):
|
|
|
538
579
|
logger=logger,
|
|
539
580
|
topic_name=f"{env}-{self.TOPIC_NAME}",
|
|
540
581
|
)
|
|
541
|
-
self.env = env
|
|
542
582
|
|
|
543
583
|
def notify_for_send_message(
|
|
544
584
|
self,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reach_commons-0.18.22 → reach_commons-0.18.24}/reach_commons/mongo/customer_persistence_async.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|