This commit is contained in:
2025-04-11 21:28:02 -03:00
parent 5b5e381191
commit 1b2ebcfb99
6 changed files with 107 additions and 62 deletions

View File

@@ -92,6 +92,7 @@ if __name__ == '__main__':
for file in tqdm(jsonl_files, desc='Processing files'):
with jsonlines.open(f'seeds/{file}') as lines:
table_name = file.removesuffix('.jsonl')
reader = jsonlines.Reader(fp)
for line in tqdm(lines, desc=f'Processing lines in {file}'):
put_item(line, table_name, dynamodb_client)

View File

@@ -12,6 +12,7 @@ from uuid import UUID
from aws_lambda_powertools import Logger
from boto3.dynamodb.types import TypeDeserializer, TypeSerializer
from botocore.exceptions import ClientError
from glom import glom
from .dateutils import now, timestamp
from .funcs import omit
@@ -58,21 +59,20 @@ if TYPE_CHECKING:
@dataclass
class ComposeKey(str):
"""Creates a composite key by joining string parts with a specified delimiter.
If a prefix is provided, it is added at the beginning of the key parts.
Example
-------
>>> ComposeKey(('abc', 'xyz'), prefix='examples', delimiter='#')
'examples#abc#xyz'
"""
keyparts: str | tuple[str, ...]
prefix: str | None = None
delimiter: str = '#'
else:
class ComposeKey(str):
"""Creates a composite key by joining string parts with a specified delimiter.
If a prefix is provided, it is added at the beginning of the key parts.
Example
-------
ComposeKey(('abc', 'xyz'), prefix='examples', delimiter='#')
"""
def __new__(
cls,
keyparts: str | tuple[str, ...],
@@ -131,17 +131,31 @@ if TYPE_CHECKING:
class SortKey(str):
sk: str
table_name: str | None = None
path_spec: str | None = None
else:
class SortKey(str):
def __new__(cls, sk: str, *, table_name: str | None = None) -> str:
def __new__(
cls,
sk: str,
*,
table_name: str | None = None,
path_spec: str | None = None,
) -> str:
return super().__new__(cls, sk)
def __init__(self, sk: str, *, table_name: str | None = None) -> None:
def __init__(
self,
sk: str,
*,
table_name: str | None = None,
path_spec: str | None = None,
) -> None:
# __init__ is used to store the parameters for later reference.
# For immutable types like str, __init__ cannot change the instance's value.
self.sk = sk
self.table_name = table_name
self.path_spec = path_spec
@dataclass
@@ -149,9 +163,9 @@ class TransactKey:
"""
Example
-------
>>> TransactKey('e9bb7dc6-c7b2-4d34-8931-d298353758ec')
... + SortKey('0')
... + SortKey('tenant')
TransactKey('e9bb7dc6-c7b2-4d34-8931-d298353758ec')
+ SortKey('0')
+ SortKey('tenant')
"""
pk: str
@@ -600,15 +614,15 @@ class DynamoDBCollection:
key: Key
Key of the item to be retrieved.
path_spec: str, optional
A path specification for nested data extraction, default is None.
A path specification for nested data extraction.
raise_on_error: bool, optional
If True, raises an exception when the item is not found, default is True.
If True, raises an exception when the item is not found.
exception_cls: Type[Exception], optional
Exception class to be used if the item is not found, default is MissingError.
Exception class to be used if the item is not found.
default: Any, optional
Default value returned if the item is not found, default is None.
Default value returned if the item is not found.
delimiter: str, optional
Delimiter used in key composition, default is '#'.
Delimiter used in key composition.
Returns
-------
@@ -647,7 +661,7 @@ class DynamoDBCollection:
key: Key
Key for the item to be inserted or updated.
ttl: int or datetime, optional
Time-to-live for the item, specified as a timestamp integer or datetime object, default is None.
Time-to-live for the item, specified as a timestamp integer or datetime object.
**kwargs
Additional data to be stored with the item.
@@ -691,11 +705,11 @@ class DynamoDBCollection:
key: Key
Key of the item to be deleted.
cond_expr: str, optional
Conditional expression for deletion, default is None.
Conditional expression for deletion.
expr_attr_names: dict, optional
Mapping of attribute names for the expression, default is None.
Mapping of attribute names for the expression.
expr_attr_values: dict, optional
Mapping of attribute values for the expression, default is None.
Mapping of attribute values for the expression.
Returns
-------
@@ -720,7 +734,10 @@ class DynamoDBCollection:
-------
**Get items using chained sort keys**
key = TransactKey('b3511b5a-cb32-4833-a373-f8223f2088d4') + SortKey('sk-1') + SortKey('sk-2')
key = (
TransactKey('b3511b5a-cb32-4833-a373-f8223f2088d4')
+ SortKey('sk-1') + SortKey('sk-2')
)
collect = DynamoDBCollection(...)
items = collect.get_items(key)
@@ -734,7 +751,6 @@ class DynamoDBCollection:
Determines whether the first nested item in the transaction result should be flattened,
i.e., extracted to serve as the primary item at the top level of the returned dict.
If True, the nested item is promoted to the top level.
The default is True.
Returns
-------
@@ -764,9 +780,11 @@ class DynamoDBCollection:
else:
head, tail = {}, items
return head | {
k: omit((PK, SK), item) for k, item in zip(sortkeys, tail) if item
}
def _getin(sk: SortKey, v: dict) -> dict:
v = omit((PK, SK), v)
return glom(v, sk.path_spec) if sk.path_spec else v
return head | {k: _getin(k, item) for k, item in zip(sortkeys, tail) if item}
def query(
self,
@@ -804,17 +822,17 @@ class DynamoDBCollection:
key: PartitionKey or KeyPair
Partition key or Key pair used for the query.
expr_attr_name: dict, optional
Additional mapping for attribute names, default is {}.
Additional mapping for attribute names.
expr_attr_values: dict, optional
Additional mapping for attribute values, default is {}.
Additional mapping for attribute values.
start_key: str, optional
Starting key for pagination, default is None.
Starting key for pagination.
filter_expr: str, optional
Filter expression for the query, default is None.
Filter expression for the query.
index_forward: bool, optional
Order of the results; True for ascending order, default is False.
Order of the results; True for ascending order.
limit: int, optional
Maximum number of items to return, default is LIMIT.
Maximum number of items to return.
Returns
-------

View File

@@ -4,8 +4,11 @@ theme:
name: "readthedocs"
plugins:
- mkdocstrings
- mkdocstrings:
handlers:
python:
options:
docstring_style: numpy
nav:
- index.md
- API reference: reference.md

View File

@@ -1,6 +1,6 @@
[project]
name = "layercake"
version = "0.2.1"
version = "0.2.5"
description = "Packages shared dependencies to optimize deployment and ensure consistency across functions."
readme = "README.md"
authors = [
@@ -23,6 +23,7 @@ dependencies = [
"meilisearch>=0.34.0",
"arnparse>=0.0.2",
"weasyprint>=65.0",
"uuid-utils>=0.10.0",
]
[dependency-groups]

View File

@@ -249,7 +249,7 @@ def test_collection_get_items(
doc = collect.get_items(
TransactKey('cJtK9SsnJhKPyxESe7g3DG')
+ SortKey('0')
+ SortKey('billing_policy')
+ SortKey('billing_policy', path_spec='payment_method')
+ SortKey('payment_policy'),
)
@@ -259,7 +259,7 @@ def test_collection_get_items(
'id': 'cJtK9SsnJhKPyxESe7g3DG',
'cnpj': '15608435000190',
'email': 'org+15608435000190@users.noreply.betaeducacao.com.br',
'billing_policy': {'billing_day': Decimal('1'), 'payment_method': 'PIX'},
'billing_policy': 'PIX',
'payment_policy': {'due_days': Decimal('90')},
}

24
layercake/uv.lock generated
View File

@@ -600,7 +600,7 @@ wheels = [
[[package]]
name = "layercake"
version = "0.2.0"
version = "0.2.4"
source = { editable = "." }
dependencies = [
{ name = "arnparse" },
@@ -617,6 +617,7 @@ dependencies = [
{ name = "pydantic-extra-types" },
{ name = "pytz" },
{ name = "requests" },
{ name = "uuid-utils" },
{ name = "weasyprint" },
]
@@ -646,6 +647,7 @@ requires-dist = [
{ name = "pydantic-extra-types", specifier = ">=2.10.3" },
{ name = "pytz", specifier = ">=2025.1" },
{ name = "requests", specifier = ">=2.32.3" },
{ name = "uuid-utils", specifier = ">=0.10.0" },
{ name = "weasyprint", specifier = ">=65.0" },
]
@@ -1277,6 +1279,26 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 },
]
[[package]]
name = "uuid-utils"
version = "0.10.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/66/0a/cbdb2eb4845dafeb632d02a18f47b02f87f2ce4f25266f5e3c017976ce89/uuid_utils-0.10.0.tar.gz", hash = "sha256:5db0e1890e8f008657ffe6ded4d9459af724ab114cfe82af1557c87545301539", size = 18828 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/44/54/9d22fa16b19e5d1676eba510f08a9c458d96e2a62ff2c8ebad64251afb18/uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d5a4508feefec62456cd6a41bcdde458d56827d908f226803b886d22a3d5e63", size = 573006 },
{ url = "https://files.pythonhosted.org/packages/08/8e/f895c6e52aa603e521fbc13b8626ba5dd99b6e2f5a55aa96ba5b232f4c53/uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:dbefc2b9113f9dfe56bdae58301a2b3c53792221410d422826f3d1e3e6555fe7", size = 292543 },
{ url = "https://files.pythonhosted.org/packages/b6/58/cc4834f377a5e97d6e184408ad96d13042308de56643b6e24afe1f6f34df/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffc49c33edf87d1ec8112a9b43e4cf55326877716f929c165a2cc307d31c73d5", size = 323340 },
{ url = "https://files.pythonhosted.org/packages/37/e3/6aeddf148f6a7dd7759621b000e8c85382ec83f52ae79b60842d1dc3ab6b/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0636b6208f69d5a4e629707ad2a89a04dfa8d1023e1999181f6830646ca048a1", size = 329653 },
{ url = "https://files.pythonhosted.org/packages/0c/00/dd6c2164ace70b7b1671d9129267df331481d7d1e5f9c5e6a564f07953f6/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bc06452856b724df9dedfc161c3582199547da54aeb81915ec2ed54f92d19b0", size = 365471 },
{ url = "https://files.pythonhosted.org/packages/b4/e7/0ab8080fcae5462a7b5e555c1cef3d63457baffb97a59b9bc7b005a3ecb1/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:263b2589111c61decdd74a762e8f850c9e4386fb78d2cf7cb4dfc537054cda1b", size = 325844 },
{ url = "https://files.pythonhosted.org/packages/73/39/52d94e9ef75b03f44b39ffc6ac3167e93e74ef4d010a93d25589d9f48540/uuid_utils-0.10.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a558db48b7096de6b4d2d2210d82bba8586a6d55f99106b03bb7d01dc5c5bcd6", size = 344389 },
{ url = "https://files.pythonhosted.org/packages/7c/29/4824566f62666238290d99c62a58e4ab2a8b9cf2eccf94cebd9b3359131e/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:807465067f3c892514230326ac71a79b28a8dfe2c88ecd2d5675fc844f3c76b5", size = 510078 },
{ url = "https://files.pythonhosted.org/packages/5e/8f/bbcc7130d652462c685f0d3bd26bb214b754215b476340885a4cb50fb89a/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:57423d4a2b9d7b916de6dbd75ba85465a28f9578a89a97f7d3e098d9aa4e5d4a", size = 515937 },
{ url = "https://files.pythonhosted.org/packages/23/f8/34e0c00f5f188604d336713e6a020fcf53b10998e8ab24735a39ab076740/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:76d8d660f18ff6b767e319b1b5f927350cd92eafa4831d7ef5b57fdd1d91f974", size = 494111 },
{ url = "https://files.pythonhosted.org/packages/1a/52/b7f0066cc90a7a9c28d54061ed195cd617fde822e5d6ac3ccc88509c3c44/uuid_utils-0.10.0-cp39-abi3-win32.whl", hash = "sha256:6c11a71489338837db0b902b75e1ba7618d5d29f05fde4f68b3f909177dbc226", size = 173520 },
{ url = "https://files.pythonhosted.org/packages/8b/15/f04f58094674d333974243fb45d2c740cf4b79186fb707168e57943c84a3/uuid_utils-0.10.0-cp39-abi3-win_amd64.whl", hash = "sha256:11c55ae64f6c0a7a0c741deae8ca2a4eaa11e9c09dbb7bec2099635696034cf7", size = 182965 },
]
[[package]]
name = "watchdog"
version = "6.0.0"