wip
This commit is contained in:
@@ -9,31 +9,49 @@ from botocore.exceptions import ClientError
|
||||
logger = Logger(__name__)
|
||||
|
||||
|
||||
def _serialize(v):
|
||||
if isinstance(v, datetime):
|
||||
return v.isoformat()
|
||||
|
||||
if isinstance(v, IPv4Address):
|
||||
return str(v)
|
||||
|
||||
if isinstance(v, (list, tuple)):
|
||||
return [_serialize(x) for x in v]
|
||||
|
||||
if isinstance(v, dict):
|
||||
return {k: _serialize(dv) for k, dv in v.items()}
|
||||
|
||||
return v
|
||||
def _serialize_python_types(obj: Any) -> str | dict | list:
|
||||
match obj:
|
||||
case datetime():
|
||||
return obj.isoformat()
|
||||
case IPv4Address():
|
||||
return str(obj)
|
||||
case list() | tuple():
|
||||
return [_serialize_python_types(v) for v in obj]
|
||||
case dict():
|
||||
return {k: _serialize_python_types(v) for k, v in obj.items()}
|
||||
case _:
|
||||
return obj
|
||||
|
||||
|
||||
def serialize(obj: dict) -> dict:
|
||||
return {k: TypeSerializer().serialize(_serialize(v)) for k, v in obj.items()}
|
||||
serializer = TypeSerializer()
|
||||
return {k: serializer.serialize(_serialize_python_types(v)) for k, v in obj.items()}
|
||||
|
||||
|
||||
def deserialize(obj: dict) -> dict:
|
||||
return {k: TypeDeserializer().deserialize(v) for k, v in obj.items()}
|
||||
deserializer = TypeDeserializer()
|
||||
return {k: deserializer.deserialize(v) for k, v in obj.items()}
|
||||
|
||||
|
||||
def Key(pk: str, sk: str) -> dict[str, str]:
|
||||
def Key(
|
||||
val: str | tuple[str, ...],
|
||||
*,
|
||||
prefix: str | None = None,
|
||||
delimiter: str = '#',
|
||||
) -> str:
|
||||
if not prefix and not isinstance(val, tuple):
|
||||
return val
|
||||
|
||||
if isinstance(val, str):
|
||||
val = (val,)
|
||||
|
||||
if prefix:
|
||||
val = (prefix,) + val
|
||||
|
||||
return delimiter.join(val)
|
||||
|
||||
|
||||
def KeyPair(pk: str, sk: str) -> dict[str, str]:
|
||||
return {
|
||||
'id': pk,
|
||||
'sk': sk,
|
||||
|
||||
@@ -4,7 +4,8 @@ from typing import TYPE_CHECKING, Annotated, Any
|
||||
|
||||
import ftfy
|
||||
from pycpfcnpj import cpfcnpj
|
||||
from pydantic import BaseModel, Field, GetCoreSchemaHandler
|
||||
from pydantic import BaseModel, Field, GetCoreSchemaHandler, GetJsonSchemaHandler
|
||||
from pydantic.json_schema import JsonSchemaValue
|
||||
from pydantic_core import CoreSchema, core_schema
|
||||
from pydantic_extra_types.payment import PaymentCardNumber
|
||||
|
||||
@@ -47,6 +48,14 @@ else:
|
||||
|
||||
return name
|
||||
|
||||
@classmethod
|
||||
def __get_pydantic_json_schema__(
|
||||
cls, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler
|
||||
) -> JsonSchemaValue:
|
||||
field_schema = handler(core_schema)
|
||||
field_schema.update(type='string', format='name')
|
||||
return field_schema
|
||||
|
||||
|
||||
class PaymentCardValidation:
|
||||
"""
|
||||
@@ -145,11 +154,9 @@ if TYPE_CHECKING:
|
||||
CnpjStr = Annotated[str, ...]
|
||||
else:
|
||||
|
||||
class CpfStr(CpfCnpj):
|
||||
...
|
||||
class CpfStr(CpfCnpj): ...
|
||||
|
||||
class CnpjStr(CpfCnpj):
|
||||
...
|
||||
class CnpjStr(CpfCnpj): ...
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
0
layercake/layercake/py.typed
Normal file
0
layercake/layercake/py.typed
Normal file
@@ -16,7 +16,7 @@ dependencies = [
|
||||
"glom>=24.11.0",
|
||||
"orjson>=3.10.15",
|
||||
"pycpfcnpj>=1.8",
|
||||
"pydantic>=2.10.6",
|
||||
"pydantic[email]>=2.10.6",
|
||||
"pydantic-extra-types>=2.10.3",
|
||||
"pytz>=2025.1",
|
||||
"shortuuid>=1.0.13",
|
||||
|
||||
@@ -1,7 +1,40 @@
|
||||
from datetime import datetime
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
import pytest
|
||||
from botocore.exceptions import ClientError
|
||||
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, TransactItems
|
||||
from layercake.dynamodb import (
|
||||
DynamoDBPersistenceLayer,
|
||||
Key,
|
||||
KeyPair,
|
||||
TransactItems,
|
||||
serialize,
|
||||
)
|
||||
|
||||
|
||||
def test_serialize():
|
||||
assert serialize(
|
||||
{
|
||||
'id': '123',
|
||||
'sk': 'abc',
|
||||
'date': datetime.fromisoformat('2025-03-20T18:29:10.713994'),
|
||||
'ip': IPv4Address('127.0.0.1'),
|
||||
}
|
||||
) == {
|
||||
'id': {'S': '123'},
|
||||
'sk': {'S': 'abc'},
|
||||
'date': {'S': '2025-03-20T18:29:10.713994'},
|
||||
'ip': {'S': '127.0.0.1'},
|
||||
}
|
||||
|
||||
|
||||
def test_key():
|
||||
assert Key(('122', 'abc'), prefix='schedules') == 'schedules#122#abc'
|
||||
|
||||
|
||||
def test_keypair():
|
||||
assert KeyPair('123', 'abc') == {'id': '123', 'sk': 'abc'}
|
||||
|
||||
|
||||
def test_transact_write_items(dynamodb_client):
|
||||
@@ -33,5 +66,6 @@ def test_transact_write_items(dynamodb_client):
|
||||
},
|
||||
cond_expr='attribute_not_exists(sk)',
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError):
|
||||
user_layer.transact_write_items(transact)
|
||||
|
||||
21
layercake/tests/test_funcs.py
Normal file
21
layercake/tests/test_funcs.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from layercake.funcs import omit, pick
|
||||
|
||||
|
||||
def test_omit():
|
||||
values = {'indigo': '#4b0082', 'navy': '#000080'}
|
||||
assert omit(['indigo'], values) == {'navy': '#000080'}
|
||||
assert omit(['test'], values) == values
|
||||
|
||||
|
||||
def test_pick():
|
||||
values = {'indigo': '#4b0082', 'navy': '#000080'}
|
||||
assert pick(['navy'], values) == {'navy': '#000080'}
|
||||
assert pick(['test'], values) == {}
|
||||
|
||||
|
||||
def test_pick_default_val():
|
||||
values = {'name': 'test'}
|
||||
assert pick(['name', 'surname'], values, exclude_none=False, default=False) == {
|
||||
'name': 'test',
|
||||
'surname': False,
|
||||
}
|
||||
40
layercake/uv.lock
generated
40
layercake/uv.lock
generated
@@ -232,6 +232,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/33/cf/1f7649b8b9a3543e042d3f348e398a061923ac05b507f3f4d95f11938aa9/cryptography-44.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6", size = 3210957 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dnspython"
|
||||
version = "2.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b5/4a/263763cb2ba3816dd94b08ad3a33d5fdae34ecb856678773cc40a3605829/dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1", size = 345197 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elastic-transport"
|
||||
version = "8.17.1"
|
||||
@@ -272,6 +281,19 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/b4/5e707bca39062ba0b5227696a767db09767e5f09e869c6cb14aeb36e4b9d/elasticsearch_dsl-8.17.1-py3-none-any.whl", hash = "sha256:49ee12a6a8d43fcfc0af42b49649531a6ef228c9e4795325de27f6b309b62b6d", size = 158294 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "email-validator"
|
||||
version = "2.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "dnspython" },
|
||||
{ name = "idna" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/48/ce/13508a1ec3f8bb981ae4ca79ea40384becc868bfae97fd1c942bb3a001b1/email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7", size = 48967 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ee/bf0adb559ad3c786f12bcbc9296b3f5675f529199bef03e2df281fa1fadb/email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", size = 33521 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "face"
|
||||
version = "24.0.0"
|
||||
@@ -319,6 +341,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/a2/75fd80784ec33da8d39cf885e8811a4fbc045a90db5e336b8e345e66dbb2/glom-24.11.0-py3-none-any.whl", hash = "sha256:991db7fcb4bfa9687010aa519b7b541bbe21111e70e58fdd2d7e34bbaa2c1fbd", size = 102690 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.1.0"
|
||||
@@ -362,7 +393,7 @@ dependencies = [
|
||||
{ name = "glom" },
|
||||
{ name = "orjson" },
|
||||
{ name = "pycpfcnpj" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "pydantic", extra = ["email"] },
|
||||
{ name = "pydantic-extra-types" },
|
||||
{ name = "pytz" },
|
||||
{ name = "shortuuid" },
|
||||
@@ -385,7 +416,7 @@ requires-dist = [
|
||||
{ name = "glom", specifier = ">=24.11.0" },
|
||||
{ name = "orjson", specifier = ">=3.10.15" },
|
||||
{ name = "pycpfcnpj", specifier = ">=1.8" },
|
||||
{ name = "pydantic", specifier = ">=2.10.6" },
|
||||
{ name = "pydantic", extras = ["email"], specifier = ">=2.10.6" },
|
||||
{ name = "pydantic-extra-types", specifier = ">=2.10.3" },
|
||||
{ name = "pytz", specifier = ">=2025.1" },
|
||||
{ name = "shortuuid", specifier = ">=1.0.13" },
|
||||
@@ -491,6 +522,11 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
email = [
|
||||
{ name = "email-validator" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.27.2"
|
||||
|
||||
Reference in New Issue
Block a user