finalsa-common-models 2.0.3__py3-none-any.whl → 2.1.0__py3-none-any.whl
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.
- finalsa/common/models/__init__.py +10 -0
- finalsa/common/models/exceptions/__init__.py +5 -0
- finalsa/common/models/exceptions/base_domain_exception.py +43 -0
- finalsa/common/models/models/__init__.py +4 -0
- finalsa/common/models/models/pagination.py +99 -0
- {finalsa_common_models-2.0.3.dist-info → finalsa_common_models-2.1.0.dist-info}/METADATA +3 -3
- finalsa_common_models-2.1.0.dist-info/RECORD +12 -0
- {finalsa_common_models-2.0.3.dist-info → finalsa_common_models-2.1.0.dist-info}/WHEEL +1 -1
- finalsa_common_models-2.0.3.dist-info/RECORD +0 -9
- {finalsa_common_models-2.0.3.dist-info → finalsa_common_models-2.1.0.dist-info}/licenses/LICENSE.md +0 -0
|
@@ -3,12 +3,18 @@ from finalsa.common.models.models import (
|
|
|
3
3
|
AsyncMeta,
|
|
4
4
|
Authorization,
|
|
5
5
|
HttpMeta,
|
|
6
|
+
PaginationMeta,
|
|
7
|
+
PaginationRequest,
|
|
8
|
+
PaginationResponse,
|
|
6
9
|
SqsReponse,
|
|
7
10
|
parse_sns_message_attributes,
|
|
8
11
|
parse_sqs_message_attributes,
|
|
9
12
|
to_sqs_message_attributes,
|
|
10
13
|
to_sns_message_attributes,
|
|
11
14
|
)
|
|
15
|
+
from finalsa.common.models.exceptions import (
|
|
16
|
+
BaseDomainException,
|
|
17
|
+
)
|
|
12
18
|
|
|
13
19
|
|
|
14
20
|
__all__ = [
|
|
@@ -16,9 +22,13 @@ __all__ = [
|
|
|
16
22
|
"AsyncMeta",
|
|
17
23
|
"Authorization",
|
|
18
24
|
"HttpMeta",
|
|
25
|
+
"PaginationMeta",
|
|
26
|
+
"PaginationRequest",
|
|
27
|
+
"PaginationResponse",
|
|
19
28
|
"SqsReponse",
|
|
20
29
|
"parse_sns_message_attributes",
|
|
21
30
|
"parse_sqs_message_attributes",
|
|
22
31
|
"to_sqs_message_attributes",
|
|
23
32
|
"to_sns_message_attributes",
|
|
33
|
+
"BaseDomainException",
|
|
24
34
|
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
import functools
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def from_camel_case_to_snake_case(name: str) -> str:
|
|
6
|
+
"""
|
|
7
|
+
Convert a camelCase string to snake_case.
|
|
8
|
+
"""
|
|
9
|
+
if not name:
|
|
10
|
+
return name
|
|
11
|
+
result = []
|
|
12
|
+
for char in name:
|
|
13
|
+
if char.isupper():
|
|
14
|
+
if result:
|
|
15
|
+
result.append('_')
|
|
16
|
+
result.append(char.lower())
|
|
17
|
+
else:
|
|
18
|
+
result.append(char)
|
|
19
|
+
return ''.join(result)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BaseDomainException(Exception):
|
|
23
|
+
response_code = 500
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
@property
|
|
27
|
+
@functools.lru_cache(maxsize=None)
|
|
28
|
+
def __class_name__(cls):
|
|
29
|
+
return from_camel_case_to_snake_case(cls.__name__)
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
message: str,
|
|
34
|
+
response_code: Optional[int] = 500,
|
|
35
|
+
name: Optional[str] = None
|
|
36
|
+
) -> None:
|
|
37
|
+
super().__init__(message)
|
|
38
|
+
self.message = message
|
|
39
|
+
self.response_code = response_code
|
|
40
|
+
if name is None:
|
|
41
|
+
self.name = self.__class_name__
|
|
42
|
+
else:
|
|
43
|
+
self.name = name
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
from .functions import parse_sns_message_attributes, parse_sqs_message_attributes, to_sqs_message_attributes, to_sns_message_attributes
|
|
2
2
|
from .sqs_response import SqsReponse
|
|
3
3
|
from .meta import Meta, AsyncMeta, Authorization, HttpMeta
|
|
4
|
+
from .pagination import PaginationMeta, PaginationRequest, PaginationResponse
|
|
4
5
|
|
|
5
6
|
__all__ = [
|
|
6
7
|
"Meta",
|
|
7
8
|
"AsyncMeta",
|
|
8
9
|
"Authorization",
|
|
9
10
|
"HttpMeta",
|
|
11
|
+
"PaginationMeta",
|
|
12
|
+
"PaginationRequest",
|
|
13
|
+
"PaginationResponse",
|
|
10
14
|
"SqsReponse",
|
|
11
15
|
"parse_sns_message_attributes",
|
|
12
16
|
"parse_sqs_message_attributes",
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from typing import Any, Dict, Generic, Optional, Sequence, TypeVar
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
ItemT = TypeVar("ItemT")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PaginationRequest(BaseModel):
|
|
10
|
+
"""Represents the pagination related query params for HTTP GET requests."""
|
|
11
|
+
|
|
12
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
13
|
+
|
|
14
|
+
limit: Optional[int] = Field(
|
|
15
|
+
default=None,
|
|
16
|
+
gt=0,
|
|
17
|
+
description="Maximum number of elements to evaluate in a single page.",
|
|
18
|
+
)
|
|
19
|
+
exclusive_start_key: Optional[Dict[str, Any]] = Field(
|
|
20
|
+
default=None,
|
|
21
|
+
alias="from",
|
|
22
|
+
description="DynamoDB ExclusiveStartKey encoded in the request.",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class PaginationMeta(BaseModel):
|
|
27
|
+
"""Generic metadata that can be attached to a paginated response."""
|
|
28
|
+
|
|
29
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
30
|
+
|
|
31
|
+
total: int
|
|
32
|
+
approx_pages: int
|
|
33
|
+
limit: Optional[int] = None
|
|
34
|
+
from_: Optional[int] = Field(default=None, alias="from")
|
|
35
|
+
to: Optional[int] = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class PaginationResponse(BaseModel, Generic[ItemT]):
|
|
39
|
+
"""
|
|
40
|
+
Generic response wrapper for paginated HTTP GET endpoints.
|
|
41
|
+
|
|
42
|
+
The model keeps track of the DynamoDB ExclusiveStartKey used to fetch
|
|
43
|
+
the current page and the LastEvaluatedKey required to fetch the next one.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
47
|
+
|
|
48
|
+
items: Sequence[ItemT]
|
|
49
|
+
count: int = Field(
|
|
50
|
+
description="Number of elements returned in the current page.",
|
|
51
|
+
)
|
|
52
|
+
limit: Optional[int] = Field(
|
|
53
|
+
default=None, description="Limit applied when retrieving this page."
|
|
54
|
+
)
|
|
55
|
+
exclusive_start_key: Optional[Dict[str, Any]] = Field(
|
|
56
|
+
default=None,
|
|
57
|
+
alias="from",
|
|
58
|
+
description="ExclusiveStartKey used to produce the current page.",
|
|
59
|
+
)
|
|
60
|
+
last_evaluated_key: Optional[Dict[str, Any]] = Field(
|
|
61
|
+
default=None,
|
|
62
|
+
alias="end",
|
|
63
|
+
description="DynamoDB LastEvaluatedKey to request the next page.",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
@model_validator(mode="before")
|
|
67
|
+
@classmethod
|
|
68
|
+
def ensure_count(cls, data: Any) -> Any:
|
|
69
|
+
"""
|
|
70
|
+
Automatically populate count when only items are provided.
|
|
71
|
+
|
|
72
|
+
This makes it easier to build the response from raw query results.
|
|
73
|
+
"""
|
|
74
|
+
if isinstance(data, dict) and "count" not in data and "items" in data:
|
|
75
|
+
try:
|
|
76
|
+
data["count"] = len(data["items"])
|
|
77
|
+
except TypeError:
|
|
78
|
+
# When items is not sized we let validation handle the error later.
|
|
79
|
+
pass
|
|
80
|
+
return data
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def from_items(
|
|
84
|
+
cls,
|
|
85
|
+
items: Sequence[ItemT],
|
|
86
|
+
*,
|
|
87
|
+
limit: Optional[int] = None,
|
|
88
|
+
exclusive_start_key: Optional[Dict[str, Any]] = None,
|
|
89
|
+
last_evaluated_key: Optional[Dict[str, Any]] = None,
|
|
90
|
+
) -> "PaginationResponse[ItemT]":
|
|
91
|
+
"""
|
|
92
|
+
Helper constructor that infers the count from the provided collection.
|
|
93
|
+
"""
|
|
94
|
+
return cls(
|
|
95
|
+
items=items,
|
|
96
|
+
limit=limit,
|
|
97
|
+
exclusive_start_key=exclusive_start_key,
|
|
98
|
+
last_evaluated_key=last_evaluated_key,
|
|
99
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: finalsa-common-models
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Common models for Finalsa
|
|
5
5
|
Project-URL: Homepage, https://github.com/finalsa/finalsa-common-models
|
|
6
6
|
Author-email: Luis Jimenez <luis@finalsa.com>
|
|
@@ -28,8 +28,8 @@ License: MIT License
|
|
|
28
28
|
License-File: LICENSE.md
|
|
29
29
|
Keywords: common,finalsa,models
|
|
30
30
|
Requires-Python: >=3.10
|
|
31
|
-
Requires-Dist: orjson>=3.
|
|
32
|
-
Requires-Dist: pydantic>=2.11.
|
|
31
|
+
Requires-Dist: orjson>=3.11.2
|
|
32
|
+
Requires-Dist: pydantic>=2.11.7
|
|
33
33
|
Requires-Dist: python-dateutil>=2.9.0.post0
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
finalsa/common/models/__init__.py,sha256=SaAY7c6ysgKh5ycS-3avCVty6croZXQS4BHLORDGq6A,728
|
|
2
|
+
finalsa/common/models/exceptions/__init__.py,sha256=Gu9bclVmdSnNTXhcRrVICkCzQK9HT0xRCr0zRvrXJE8,96
|
|
3
|
+
finalsa/common/models/exceptions/base_domain_exception.py,sha256=SWp6B41nfAxQyOF2X9SlwRMB7z4z_NS4lvSdO7PPkaA,1027
|
|
4
|
+
finalsa/common/models/models/__init__.py,sha256=kiHCRA5pZwIDXfAryWO7ir1SGHUlwNtDclD6B26KIpo,619
|
|
5
|
+
finalsa/common/models/models/functions.py,sha256=vKUrhl3AVfnYBqqKYpZbZevrBpUx7ywqhtU3KKPqWUE,2983
|
|
6
|
+
finalsa/common/models/models/meta.py,sha256=VKBmzkBs1W6so9bmTXO5kIIQ2f3MzrTdZhz4bHG1FsQ,711
|
|
7
|
+
finalsa/common/models/models/pagination.py,sha256=EFTcHbhR62wl9Kf9pfZWhV2sO1ZhIQorxZhcZTsC0n0,3097
|
|
8
|
+
finalsa/common/models/models/sqs_response.py,sha256=GKkDyWYeYEUCRHp2H8MjxvzFuwWL1ngzpf5zILhVUNg,2258
|
|
9
|
+
finalsa_common_models-2.1.0.dist-info/METADATA,sha256=o745pBBx6OQ5vJdP2TURTcYfTQsLV-H9rpEm0Msr5m4,3053
|
|
10
|
+
finalsa_common_models-2.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
11
|
+
finalsa_common_models-2.1.0.dist-info/licenses/LICENSE.md,sha256=yqzhfnTBr2S4lUBx-yibVPOIXRUDPrSUN9-_7AsC6OU,1084
|
|
12
|
+
finalsa_common_models-2.1.0.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
finalsa/common/models/__init__.py,sha256=cJQBAlbwE0zC6yaqPPD4XsQjxBbg5uR--WpNIPro0Tw,487
|
|
2
|
-
finalsa/common/models/models/__init__.py,sha256=idkn9Md7ApwVAelmOh7sd1V5Qa2V9AqwqpkMbXhY2_A,468
|
|
3
|
-
finalsa/common/models/models/functions.py,sha256=vKUrhl3AVfnYBqqKYpZbZevrBpUx7ywqhtU3KKPqWUE,2983
|
|
4
|
-
finalsa/common/models/models/meta.py,sha256=VKBmzkBs1W6so9bmTXO5kIIQ2f3MzrTdZhz4bHG1FsQ,711
|
|
5
|
-
finalsa/common/models/models/sqs_response.py,sha256=GKkDyWYeYEUCRHp2H8MjxvzFuwWL1ngzpf5zILhVUNg,2258
|
|
6
|
-
finalsa_common_models-2.0.3.dist-info/METADATA,sha256=SO0_gLyS-7nRStPN3y-DGsKmYXnFwJc3YRMjXhszAhI,3054
|
|
7
|
-
finalsa_common_models-2.0.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
8
|
-
finalsa_common_models-2.0.3.dist-info/licenses/LICENSE.md,sha256=yqzhfnTBr2S4lUBx-yibVPOIXRUDPrSUN9-_7AsC6OU,1084
|
|
9
|
-
finalsa_common_models-2.0.3.dist-info/RECORD,,
|
{finalsa_common_models-2.0.3.dist-info → finalsa_common_models-2.1.0.dist-info}/licenses/LICENSE.md
RENAMED
|
File without changes
|