aws-python-helper 0.37.0__tar.gz → 0.38.0__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.
Files changed (53) hide show
  1. {aws_python_helper-0.37.0/aws_python_helper.egg-info → aws_python_helper-0.38.0}/PKG-INFO +31 -2
  2. aws_python_helper-0.37.0/PKG-INFO → aws_python_helper-0.38.0/README.md +30 -21
  3. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/model_query/base.py +60 -1
  4. aws_python_helper-0.37.0/README.md → aws_python_helper-0.38.0/aws_python_helper.egg-info/PKG-INFO +50 -1
  5. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/pyproject.toml +1 -1
  6. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/__init__.py +0 -0
  7. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/api/__init__.py +0 -0
  8. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/api/auth_middleware.py +0 -0
  9. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/api/auth_validators.py +0 -0
  10. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/api/base.py +0 -0
  11. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/api/dispatcher.py +0 -0
  12. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/api/exceptions.py +0 -0
  13. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/api/fetcher.py +0 -0
  14. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/api/handler.py +0 -0
  15. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/context/__init__.py +0 -0
  16. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/context/session.py +0 -0
  17. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/context/state_validator.py +0 -0
  18. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/database/__init__.py +0 -0
  19. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/database/database_proxy.py +0 -0
  20. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/database/external_database_proxy.py +0 -0
  21. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/database/external_mongo_manager.py +0 -0
  22. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/database/mongo_manager.py +0 -0
  23. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/fargate/__init__.py +0 -0
  24. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/fargate/executor.py +0 -0
  25. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/fargate/fetcher.py +0 -0
  26. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/fargate/handler.py +0 -0
  27. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/fargate/task_base.py +0 -0
  28. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/invoker/__init__.py +0 -0
  29. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/invoker/api_client.py +0 -0
  30. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/invoker/exceptions.py +0 -0
  31. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/invoker/lambda_invoker.py +0 -0
  32. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/lambda_standalone/__init__.py +0 -0
  33. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/lambda_standalone/base.py +0 -0
  34. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/lambda_standalone/fetcher.py +0 -0
  35. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/lambda_standalone/handler.py +0 -0
  36. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/model_query/__init__.py +0 -0
  37. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/repository/__init__.py +0 -0
  38. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/repository/base.py +0 -0
  39. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/sns/__init__.py +0 -0
  40. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/sns/publisher.py +0 -0
  41. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/sqs/__init__.py +0 -0
  42. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/sqs/consumer_base.py +0 -0
  43. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/sqs/fetcher.py +0 -0
  44. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/sqs/handler.py +0 -0
  45. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/utils/__init__.py +0 -0
  46. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/utils/json_encoder.py +0 -0
  47. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/utils/response.py +0 -0
  48. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper/utils/serializer.py +0 -0
  49. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper.egg-info/SOURCES.txt +0 -0
  50. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper.egg-info/dependency_links.txt +0 -0
  51. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper.egg-info/requires.txt +0 -0
  52. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/aws_python_helper.egg-info/top_level.txt +0 -0
  53. {aws_python_helper-0.37.0 → aws_python_helper-0.38.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aws-python-helper
3
- Version: 0.37.0
3
+ Version: 0.38.0
4
4
  Summary: AWS Python Helper Framework
5
5
  Author-email: Fabian Claros <neufabiae@gmail.com>
6
6
  License-Expression: MIT
@@ -1231,6 +1231,35 @@ invoker.invoke("ServiceModelQuery-dev", payload={
1231
1231
 
1232
1232
  **Note:** `pipeline` and `fields` are mutually exclusive — the framework rejects payloads that include both.
1233
1233
 
1234
+ #### Querying by `_id`
1235
+
1236
+ ObjectId hex strings in `_id` filters are automatically coerced to `ObjectId` so callers can serialize queries as plain JSON:
1237
+
1238
+ ```python
1239
+ # Plain value
1240
+ invoker.invoke("ServiceModelQuery-dev", payload={
1241
+ "session": self.session.to_dict(),
1242
+ "collection": "orders",
1243
+ "filter": {"_id": "65f1a2b3c4d5e6f7a8b9c0d1"},
1244
+ })
1245
+
1246
+ # Operator with list
1247
+ invoker.invoke("ServiceModelQuery-dev", payload={
1248
+ "session": self.session.to_dict(),
1249
+ "collection": "orders",
1250
+ "filter": {"_id": {"$in": ["65f1...", "65f2...", "65f3..."]}},
1251
+ })
1252
+
1253
+ # 'id' is accepted as an alias for '_id'
1254
+ invoker.invoke("ServiceModelQuery-dev", payload={
1255
+ "session": self.session.to_dict(),
1256
+ "collection": "orders",
1257
+ "filter": {"id": "65f1a2b3c4d5e6f7a8b9c0d1"},
1258
+ })
1259
+ ```
1260
+
1261
+ Supported operators on `_id`: scalar (`$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`) and list (`$in`, `$nin`). The same coercion is applied to `$match` stages inside a `pipeline`. If the string is not a valid 24-char ObjectId hex, the Lambda raises a clear validation error.
1262
+
1234
1263
  ### Payload reference
1235
1264
 
1236
1265
  | Field | Type | Required | Description |
@@ -1238,7 +1267,7 @@ invoker.invoke("ServiceModelQuery-dev", payload={
1238
1267
  | `session` | `dict` | Yes | Session dict from `self.session.to_dict()` — drives state-scoped DB routing |
1239
1268
  | `collection` | `str` | Yes | Collection name (must be in `allowed_collections`) |
1240
1269
  | `pipeline` | `list` | One of | MongoDB aggregation pipeline |
1241
- | `filter` | `dict` | One of | MongoDB filter document (defaults to `{}`) |
1270
+ | `filter` | `dict` | One of | MongoDB filter document (defaults to `{}`). `_id`/`id` string values are auto-coerced to `ObjectId` |
1242
1271
  | `fields` | `dict` | No | MongoDB projection (only valid with `filter` mode) |
1243
1272
  | `limit` | `int` | No | Max documents to return |
1244
1273
  | `skip` | `int` | No | Documents to skip (default `0`) |
@@ -1,23 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: aws-python-helper
3
- Version: 0.37.0
4
- Summary: AWS Python Helper Framework
5
- Author-email: Fabian Claros <neufabiae@gmail.com>
6
- License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/fabiae/aws-python-framework
8
- Project-URL: Source Code, https://github.com/fabiae/aws-python-framework
9
- Project-URL: Bug Tracker, https://github.com/fabiae/aws-python-framework/issues
10
- Project-URL: Documentation, https://github.com/fabiae/aws-python-framework/blob/main/README.md
11
- Keywords: aws,python,framework,helper,mongodb,sqs,sns,fargate,lambda
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Operating System :: OS Independent
14
- Requires-Python: >=3.9
15
- Description-Content-Type: text/markdown
16
- Requires-Dist: motor==3.3.2
17
- Requires-Dist: pymongo==4.6.1
18
- Requires-Dist: pydantic>=2.0
19
- Requires-Dist: httpx>=0.27.0
20
-
21
1
  # AWS Python Framework
22
2
 
23
3
  Mini-framework to create REST APIs, SQS Consumers, SNS Publishers, Fargate Tasks, and Standalone Lambdas with Python in AWS Lambda.
@@ -1231,6 +1211,35 @@ invoker.invoke("ServiceModelQuery-dev", payload={
1231
1211
 
1232
1212
  **Note:** `pipeline` and `fields` are mutually exclusive — the framework rejects payloads that include both.
1233
1213
 
1214
+ #### Querying by `_id`
1215
+
1216
+ ObjectId hex strings in `_id` filters are automatically coerced to `ObjectId` so callers can serialize queries as plain JSON:
1217
+
1218
+ ```python
1219
+ # Plain value
1220
+ invoker.invoke("ServiceModelQuery-dev", payload={
1221
+ "session": self.session.to_dict(),
1222
+ "collection": "orders",
1223
+ "filter": {"_id": "65f1a2b3c4d5e6f7a8b9c0d1"},
1224
+ })
1225
+
1226
+ # Operator with list
1227
+ invoker.invoke("ServiceModelQuery-dev", payload={
1228
+ "session": self.session.to_dict(),
1229
+ "collection": "orders",
1230
+ "filter": {"_id": {"$in": ["65f1...", "65f2...", "65f3..."]}},
1231
+ })
1232
+
1233
+ # 'id' is accepted as an alias for '_id'
1234
+ invoker.invoke("ServiceModelQuery-dev", payload={
1235
+ "session": self.session.to_dict(),
1236
+ "collection": "orders",
1237
+ "filter": {"id": "65f1a2b3c4d5e6f7a8b9c0d1"},
1238
+ })
1239
+ ```
1240
+
1241
+ Supported operators on `_id`: scalar (`$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`) and list (`$in`, `$nin`). The same coercion is applied to `$match` stages inside a `pipeline`. If the string is not a valid 24-char ObjectId hex, the Lambda raises a clear validation error.
1242
+
1234
1243
  ### Payload reference
1235
1244
 
1236
1245
  | Field | Type | Required | Description |
@@ -1238,7 +1247,7 @@ invoker.invoke("ServiceModelQuery-dev", payload={
1238
1247
  | `session` | `dict` | Yes | Session dict from `self.session.to_dict()` — drives state-scoped DB routing |
1239
1248
  | `collection` | `str` | Yes | Collection name (must be in `allowed_collections`) |
1240
1249
  | `pipeline` | `list` | One of | MongoDB aggregation pipeline |
1241
- | `filter` | `dict` | One of | MongoDB filter document (defaults to `{}`) |
1250
+ | `filter` | `dict` | One of | MongoDB filter document (defaults to `{}`). `_id`/`id` string values are auto-coerced to `ObjectId` |
1242
1251
  | `fields` | `dict` | No | MongoDB projection (only valid with `filter` mode) |
1243
1252
  | `limit` | `int` | No | Max documents to return |
1244
1253
  | `skip` | `int` | No | Documents to skip (default `0`) |
@@ -25,18 +25,67 @@ Caller payload:
25
25
  "skip": 0 # optional, default 0
26
26
  }
27
27
 
28
+ ObjectId coercion:
29
+ String values for '_id' (or 'id' as alias) inside `filter` and pipeline
30
+ `$match` stages are automatically converted to bson.ObjectId. Supports
31
+ scalar operators ($eq, $ne, $gt, $gte, $lt, $lte) and list operators
32
+ ($in, $nin). A clear ValueError is raised when the string is not a valid
33
+ 24-char ObjectId hex.
34
+
35
+ {"filter": {"_id": "65f1a2b3c4d5e6f7a8b9c0d1"}}
36
+ {"filter": {"_id": {"$in": ["65f1...", "65f2..."]}}}
37
+ {"filter": {"id": "65f1a2b3c4d5e6f7a8b9c0d1"}} # 'id' is aliased to '_id'
38
+
28
39
  Response (via Lambda base run()):
29
40
  {"success": True, "data": [...]}
30
41
  """
31
42
 
32
43
  from typing import Any, List, Optional
44
+ from bson import ObjectId
33
45
  from pydantic import BaseModel, ConfigDict, model_validator
34
46
 
35
47
  from ..lambda_standalone.base import Lambda
36
48
 
37
49
 
50
+ _OBJECT_ID_SCALAR_OPERATORS = {"$eq", "$ne", "$gt", "$gte", "$lt", "$lte"}
51
+ _OBJECT_ID_LIST_OPERATORS = {"$in", "$nin"}
52
+
53
+
54
+ def _coerce_object_id(value: Any) -> Any:
55
+ """Convert a string (or operator dict) to ObjectId where applicable for an '_id' field."""
56
+ if isinstance(value, ObjectId):
57
+ return value
58
+ if isinstance(value, str):
59
+ if not ObjectId.is_valid(value):
60
+ raise ValueError(f"'_id' value '{value}' is not a valid ObjectId")
61
+ return ObjectId(value)
62
+ if isinstance(value, dict):
63
+ coerced = {}
64
+ for op, op_value in value.items():
65
+ if op in _OBJECT_ID_LIST_OPERATORS:
66
+ if not isinstance(op_value, list):
67
+ raise ValueError(f"'{op}' value for '_id' must be a list")
68
+ coerced[op] = [_coerce_object_id(v) for v in op_value]
69
+ elif op in _OBJECT_ID_SCALAR_OPERATORS:
70
+ coerced[op] = _coerce_object_id(op_value)
71
+ else:
72
+ coerced[op] = op_value
73
+ return coerced
74
+ raise ValueError(
75
+ f"Unsupported type for '_id' filter: {type(value).__name__}"
76
+ )
77
+
78
+
79
+ def _normalize_id_key(d: dict) -> None:
80
+ """Rename 'id' → '_id' (if no _id present) and coerce its value to ObjectId in-place."""
81
+ if "id" in d and "_id" not in d:
82
+ d["_id"] = d.pop("id")
83
+ if "_id" in d:
84
+ d["_id"] = _coerce_object_id(d["_id"])
85
+
86
+
38
87
  class _ModelQuerySchema(BaseModel):
39
- model_config = ConfigDict(extra="ignore")
88
+ model_config = ConfigDict(extra="ignore", arbitrary_types_allowed=True)
40
89
 
41
90
  collection: str
42
91
  filter: Optional[dict] = None
@@ -51,6 +100,16 @@ class _ModelQuerySchema(BaseModel):
51
100
  raise ValueError("'fields' cannot be used together with 'pipeline'")
52
101
  return self
53
102
 
103
+ @model_validator(mode="after")
104
+ def _normalize_object_ids(self):
105
+ if self.filter is not None:
106
+ _normalize_id_key(self.filter)
107
+ if self.pipeline is not None:
108
+ for stage in self.pipeline:
109
+ if isinstance(stage, dict) and isinstance(stage.get("$match"), dict):
110
+ _normalize_id_key(stage["$match"])
111
+ return self
112
+
54
113
 
55
114
  class ModelQueryLambda(Lambda):
56
115
  """
@@ -1,3 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: aws-python-helper
3
+ Version: 0.38.0
4
+ Summary: AWS Python Helper Framework
5
+ Author-email: Fabian Claros <neufabiae@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/fabiae/aws-python-framework
8
+ Project-URL: Source Code, https://github.com/fabiae/aws-python-framework
9
+ Project-URL: Bug Tracker, https://github.com/fabiae/aws-python-framework/issues
10
+ Project-URL: Documentation, https://github.com/fabiae/aws-python-framework/blob/main/README.md
11
+ Keywords: aws,python,framework,helper,mongodb,sqs,sns,fargate,lambda
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: motor==3.3.2
17
+ Requires-Dist: pymongo==4.6.1
18
+ Requires-Dist: pydantic>=2.0
19
+ Requires-Dist: httpx>=0.27.0
20
+
1
21
  # AWS Python Framework
2
22
 
3
23
  Mini-framework to create REST APIs, SQS Consumers, SNS Publishers, Fargate Tasks, and Standalone Lambdas with Python in AWS Lambda.
@@ -1211,6 +1231,35 @@ invoker.invoke("ServiceModelQuery-dev", payload={
1211
1231
 
1212
1232
  **Note:** `pipeline` and `fields` are mutually exclusive — the framework rejects payloads that include both.
1213
1233
 
1234
+ #### Querying by `_id`
1235
+
1236
+ ObjectId hex strings in `_id` filters are automatically coerced to `ObjectId` so callers can serialize queries as plain JSON:
1237
+
1238
+ ```python
1239
+ # Plain value
1240
+ invoker.invoke("ServiceModelQuery-dev", payload={
1241
+ "session": self.session.to_dict(),
1242
+ "collection": "orders",
1243
+ "filter": {"_id": "65f1a2b3c4d5e6f7a8b9c0d1"},
1244
+ })
1245
+
1246
+ # Operator with list
1247
+ invoker.invoke("ServiceModelQuery-dev", payload={
1248
+ "session": self.session.to_dict(),
1249
+ "collection": "orders",
1250
+ "filter": {"_id": {"$in": ["65f1...", "65f2...", "65f3..."]}},
1251
+ })
1252
+
1253
+ # 'id' is accepted as an alias for '_id'
1254
+ invoker.invoke("ServiceModelQuery-dev", payload={
1255
+ "session": self.session.to_dict(),
1256
+ "collection": "orders",
1257
+ "filter": {"id": "65f1a2b3c4d5e6f7a8b9c0d1"},
1258
+ })
1259
+ ```
1260
+
1261
+ Supported operators on `_id`: scalar (`$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`) and list (`$in`, `$nin`). The same coercion is applied to `$match` stages inside a `pipeline`. If the string is not a valid 24-char ObjectId hex, the Lambda raises a clear validation error.
1262
+
1214
1263
  ### Payload reference
1215
1264
 
1216
1265
  | Field | Type | Required | Description |
@@ -1218,7 +1267,7 @@ invoker.invoke("ServiceModelQuery-dev", payload={
1218
1267
  | `session` | `dict` | Yes | Session dict from `self.session.to_dict()` — drives state-scoped DB routing |
1219
1268
  | `collection` | `str` | Yes | Collection name (must be in `allowed_collections`) |
1220
1269
  | `pipeline` | `list` | One of | MongoDB aggregation pipeline |
1221
- | `filter` | `dict` | One of | MongoDB filter document (defaults to `{}`) |
1270
+ | `filter` | `dict` | One of | MongoDB filter document (defaults to `{}`). `_id`/`id` string values are auto-coerced to `ObjectId` |
1222
1271
  | `fields` | `dict` | No | MongoDB projection (only valid with `filter` mode) |
1223
1272
  | `limit` | `int` | No | Max documents to return |
1224
1273
  | `skip` | `int` | No | Documents to skip (default `0`) |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aws-python-helper"
7
- version = "0.37.0"
7
+ version = "0.38.0"
8
8
  description = "AWS Python Helper Framework"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"