aws-python-helper 1.9.1__tar.gz → 1.9.3__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.
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/PKG-INFO +1 -1
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/model_query/base.py +4 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/sns/publisher.py +11 -7
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper.egg-info/PKG-INFO +1 -1
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper.egg-info/SOURCES.txt +2 -1
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/pyproject.toml +1 -1
- aws_python_helper-1.9.3/tests/test_sns_publisher.py +125 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/README.md +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/auth_middleware.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/auth_validators.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/base.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/dispatcher.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/exceptions.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/fetcher.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/handler.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/context/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/context/session.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/context/state_validator.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/database/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/database/database_proxy.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/database/external_database_proxy.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/database/external_mongo_manager.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/database/mongo_manager.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/fargate/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/fargate/executor.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/fargate/fetcher.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/fargate/handler.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/fargate/task_base.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/invoker/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/invoker/api_client.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/invoker/exceptions.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/invoker/lambda_invoker.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/lambda_standalone/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/lambda_standalone/base.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/lambda_standalone/fetcher.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/lambda_standalone/handler.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/model_index_sync/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/model_index_sync/base.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/model_query/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/monitoring/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/monitoring/run.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/permissions/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/permissions/catalog.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/repository/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/repository/audit.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/repository/base.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/sns/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/sqs/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/sqs/consumer_base.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/sqs/fetcher.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/sqs/handler.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/utils/__init__.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/utils/json_encoder.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/utils/response.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/utils/serializer.py +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper.egg-info/dependency_links.txt +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper.egg-info/requires.txt +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper.egg-info/top_level.txt +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/setup.cfg +0 -0
- {aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/tests/test_audit_stamp.py +0 -0
|
@@ -88,6 +88,10 @@ class _ModelQuerySchema(BaseModel):
|
|
|
88
88
|
model_config = ConfigDict(extra="ignore", arbitrary_types_allowed=True)
|
|
89
89
|
|
|
90
90
|
collection: str
|
|
91
|
+
# La base donde buscar. Estaba documentada como parámetro pero no declarada,
|
|
92
|
+
# y `extra="ignore"` la descartaba en silencio: la consulta terminaba en la
|
|
93
|
+
# base del estado de la sesión y devolvía vacío sin error.
|
|
94
|
+
database: Optional[str] = None
|
|
91
95
|
filter: Optional[dict] = None
|
|
92
96
|
pipeline: Optional[list] = None
|
|
93
97
|
fields: Optional[dict] = None
|
|
@@ -276,13 +276,18 @@ class SNSPublisher(ABC):
|
|
|
276
276
|
|
|
277
277
|
return formatted
|
|
278
278
|
|
|
279
|
-
def _format_message(
|
|
279
|
+
def _format_message(
|
|
280
|
+
self, message: Dict[str, Any], index: Optional[int] = None
|
|
281
|
+
) -> Dict[str, Any]:
|
|
280
282
|
"""
|
|
281
283
|
Formats the message for SNS
|
|
282
|
-
|
|
284
|
+
|
|
283
285
|
Args:
|
|
284
286
|
message: Message to format
|
|
285
|
-
|
|
287
|
+
index: Position inside a batch. `publish_batch` needs an `Id` per
|
|
288
|
+
entry; plain `publish` does not take one at all, so a single
|
|
289
|
+
message leaves it out.
|
|
290
|
+
|
|
286
291
|
Returns:
|
|
287
292
|
Formatted message
|
|
288
293
|
"""
|
|
@@ -305,10 +310,9 @@ class SNSPublisher(ABC):
|
|
|
305
310
|
session_json = self._serialize_message(session_dict)
|
|
306
311
|
attributes['session'] = base64.b64encode(session_json.encode('utf-8')).decode('utf-8')
|
|
307
312
|
|
|
308
|
-
params = {
|
|
309
|
-
|
|
310
|
-
'
|
|
311
|
-
}
|
|
313
|
+
params: Dict[str, Any] = {'Message': content}
|
|
314
|
+
if index is not None:
|
|
315
|
+
params['Id'] = str(index)
|
|
312
316
|
|
|
313
317
|
# Add subject if exists
|
|
314
318
|
if subject:
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""What the publisher must hand to boto3.
|
|
2
|
+
|
|
3
|
+
Runs on its own, no dependencies:
|
|
4
|
+
|
|
5
|
+
python tests/test_sns_publisher.py
|
|
6
|
+
|
|
7
|
+
These exist because a single publish crashed in production with
|
|
8
|
+
`_format_message() missing 1 required positional argument: 'index'`. Every test
|
|
9
|
+
until then mocked `publish` itself, so the code that builds the boto3 call was
|
|
10
|
+
never executed — the mock was above the bug.
|
|
11
|
+
|
|
12
|
+
So here the fake is the **boto3 client**, not the publisher: everything the
|
|
13
|
+
publisher actually does runs.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
22
|
+
|
|
23
|
+
from aws_python_helper.sns.publisher import MAX_BATCH_ENTRIES, SNSPublisher # noqa: E402
|
|
24
|
+
|
|
25
|
+
failures = []
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def check(label, condition, detail=""):
|
|
29
|
+
print(f" {'ok ' if condition else 'FAIL'} {label}{' ' + detail if detail else ''}")
|
|
30
|
+
if not condition:
|
|
31
|
+
failures.append(label)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class FakeSNS:
|
|
35
|
+
"""Se queja igual que boto3 ante un parámetro que SNS no acepta."""
|
|
36
|
+
|
|
37
|
+
VALID_PUBLISH = {"TopicArn", "Message", "Subject", "MessageAttributes",
|
|
38
|
+
"MessageStructure", "MessageDeduplicationId", "MessageGroupId"}
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
self.published = []
|
|
42
|
+
self.batches = []
|
|
43
|
+
|
|
44
|
+
def publish(self, **kwargs):
|
|
45
|
+
extra = set(kwargs) - self.VALID_PUBLISH
|
|
46
|
+
if extra:
|
|
47
|
+
raise TypeError(f"Unknown parameter in input: {sorted(extra)}")
|
|
48
|
+
self.published.append(kwargs)
|
|
49
|
+
return {"MessageId": f"m{len(self.published)}"}
|
|
50
|
+
|
|
51
|
+
def publish_batch(self, TopicArn, PublishBatchRequestEntries):
|
|
52
|
+
if len(PublishBatchRequestEntries) > MAX_BATCH_ENTRIES:
|
|
53
|
+
raise Exception("TooManyEntriesInBatchRequest")
|
|
54
|
+
for entry in PublishBatchRequestEntries:
|
|
55
|
+
if "Id" not in entry:
|
|
56
|
+
raise Exception("An entry in a batch needs an Id")
|
|
57
|
+
self.batches.append(PublishBatchRequestEntries)
|
|
58
|
+
return {"Successful": [{"MessageId": f"b{i}"} for i in range(len(PublishBatchRequestEntries))],
|
|
59
|
+
"Failed": []}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class Publisher(SNSPublisher):
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def publisher():
|
|
67
|
+
p = Publisher("arn:aws:sns:us-east-2:1:Topic-dev")
|
|
68
|
+
p._sns_client = FakeSNS()
|
|
69
|
+
return p
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def main():
|
|
73
|
+
print("a single message")
|
|
74
|
+
p = publisher()
|
|
75
|
+
result = await p.publish({"content": {"run_id": "abc", "status": "launched"}})
|
|
76
|
+
sent = p._sns_client.published[0]
|
|
77
|
+
check("it publishes", len(p._sns_client.published) == 1)
|
|
78
|
+
check("no Id, which publish does not accept", "Id" not in sent)
|
|
79
|
+
check("the body travels", json.loads(sent["Message"])["run_id"] == "abc")
|
|
80
|
+
check("returns the message id", result == "m1")
|
|
81
|
+
|
|
82
|
+
print("\na single message with attributes and subject")
|
|
83
|
+
p = publisher()
|
|
84
|
+
await p.publish({
|
|
85
|
+
"content": {"x": 1},
|
|
86
|
+
"attributes": {"service": "business"},
|
|
87
|
+
"subject": "hello",
|
|
88
|
+
})
|
|
89
|
+
sent = p._sns_client.published[0]
|
|
90
|
+
check("subject", sent.get("Subject") == "hello")
|
|
91
|
+
check("attributes", "MessageAttributes" in sent)
|
|
92
|
+
|
|
93
|
+
print("\na batch")
|
|
94
|
+
p = publisher()
|
|
95
|
+
ok, failed = await p.publish([{"content": {"n": i}} for i in range(188)])
|
|
96
|
+
check("split into tens", len(p._sns_client.batches) == 19,
|
|
97
|
+
f"batches={len(p._sns_client.batches)}")
|
|
98
|
+
check("none over the limit", all(len(b) <= MAX_BATCH_ENTRIES for b in p._sns_client.batches))
|
|
99
|
+
check("every entry has an Id", all("Id" in e for b in p._sns_client.batches for e in b))
|
|
100
|
+
check("ids unique inside each call",
|
|
101
|
+
all(len({e["Id"] for e in b}) == len(b) for b in p._sns_client.batches))
|
|
102
|
+
check("all reported published", len(ok) == 188 and not failed)
|
|
103
|
+
|
|
104
|
+
print("\na batch of one still goes as a batch")
|
|
105
|
+
p = publisher()
|
|
106
|
+
await p.publish([{"content": {"n": 1}}])
|
|
107
|
+
check("one call", len(p._sns_client.batches) == 1)
|
|
108
|
+
check("nothing through publish()", not p._sns_client.published)
|
|
109
|
+
|
|
110
|
+
print("\na message with no content is refused, not sent")
|
|
111
|
+
p = publisher()
|
|
112
|
+
try:
|
|
113
|
+
await p.publish({"attributes": {"service": "business"}})
|
|
114
|
+
check("raises", False)
|
|
115
|
+
except ValueError:
|
|
116
|
+
check("raises", True)
|
|
117
|
+
check("nothing published", not p._sns_client.published)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
asyncio.run(main())
|
|
121
|
+
|
|
122
|
+
if failures:
|
|
123
|
+
print(f"\n{len(failures)} failed: {failures}")
|
|
124
|
+
raise SystemExit(1)
|
|
125
|
+
print("\nall good")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/auth_middleware.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/api/auth_validators.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
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/context/state_validator.py
RENAMED
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/database/database_proxy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/database/mongo_manager.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
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/invoker/lambda_invoker.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/lambda_standalone/__init__.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/lambda_standalone/base.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/lambda_standalone/fetcher.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/lambda_standalone/handler.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/model_index_sync/__init__.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/model_index_sync/base.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/model_query/__init__.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/monitoring/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/permissions/__init__.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/permissions/catalog.py
RENAMED
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper/repository/__init__.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
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.9.1 → aws_python_helper-1.9.3}/aws_python_helper.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|