8
8
import pytest
9
9
from botocore import stub
10
10
from botocore .config import Config
11
- from pydantic import BaseModel
12
11
from pytest import FixtureRequest
13
12
from pytest_mock import MockerFixture
14
13
32
31
IdempotencyInconsistentStateError ,
33
32
IdempotencyInvalidStatusError ,
34
33
IdempotencyKeyError ,
35
- IdempotencyModelTypeError ,
36
34
IdempotencyNoSerializationModelError ,
37
35
IdempotencyPersistenceLayerError ,
38
36
IdempotencyValidationError ,
47
45
from aws_lambda_powertools .utilities .idempotency .serialization .dataclass import (
48
46
DataclassSerializer ,
49
47
)
50
- from aws_lambda_powertools .utilities .idempotency .serialization .pydantic import (
51
- PydanticSerializer ,
52
- )
53
48
from aws_lambda_powertools .utilities .validation import envelopes , validator
54
49
from aws_lambda_powertools .warnings import PowertoolsUserWarning
55
50
from tests .functional .idempotency .utils import (
61
56
from tests .functional .utils import json_serialize , load_event
62
57
63
58
TABLE_NAME = "TEST_TABLE"
64
- TESTS_MODULE_PREFIX = "test-func.tests.functional.idempotency.test_idempotency"
59
+ TESTS_MODULE_PREFIX = "test-func.tests.functional.idempotency._boto3. test_idempotency"
65
60
66
61
67
62
def get_dataclasses_lib ():
@@ -1315,106 +1310,6 @@ def record_handler(record):
1315
1310
assert from_dict_called is False , "in case response is None, from_dict should not be called"
1316
1311
1317
1312
1318
- @pytest .mark .parametrize ("output_serializer_type" , ["explicit" , "deduced" ])
1319
- def test_idempotent_function_serialization_pydantic (output_serializer_type : str ):
1320
- # GIVEN
1321
- config = IdempotencyConfig (use_local_cache = True )
1322
- mock_event = {"customer_id" : "fake" , "transaction_id" : "fake-id" }
1323
- idempotency_key = f"{ TESTS_MODULE_PREFIX } .test_idempotent_function_serialization_pydantic.<locals>.collect_payment#{ hash_idempotency_key (mock_event )} " # noqa E501
1324
- persistence_layer = MockPersistenceLayer (expected_idempotency_key = idempotency_key )
1325
-
1326
- class PaymentInput (BaseModel ):
1327
- customer_id : str
1328
- transaction_id : str
1329
-
1330
- class PaymentOutput (BaseModel ):
1331
- customer_id : str
1332
- transaction_id : str
1333
-
1334
- if output_serializer_type == "explicit" :
1335
- output_serializer = PydanticSerializer (
1336
- model = PaymentOutput ,
1337
- )
1338
- else :
1339
- output_serializer = PydanticSerializer
1340
-
1341
- @idempotent_function (
1342
- data_keyword_argument = "payment" ,
1343
- persistence_store = persistence_layer ,
1344
- config = config ,
1345
- output_serializer = output_serializer ,
1346
- )
1347
- def collect_payment (payment : PaymentInput ) -> PaymentOutput :
1348
- return PaymentOutput (** payment .dict ())
1349
-
1350
- # WHEN
1351
- payment = PaymentInput (** mock_event )
1352
- first_call : PaymentOutput = collect_payment (payment = payment )
1353
- assert first_call .customer_id == payment .customer_id
1354
- assert first_call .transaction_id == payment .transaction_id
1355
- assert isinstance (first_call , PaymentOutput )
1356
- second_call : PaymentOutput = collect_payment (payment = payment )
1357
- assert isinstance (second_call , PaymentOutput )
1358
- assert second_call .customer_id == payment .customer_id
1359
- assert second_call .transaction_id == payment .transaction_id
1360
-
1361
-
1362
- def test_idempotent_function_serialization_pydantic_failure_no_return_type ():
1363
- # GIVEN
1364
- config = IdempotencyConfig (use_local_cache = True )
1365
- mock_event = {"customer_id" : "fake" , "transaction_id" : "fake-id" }
1366
- idempotency_key = f"{ TESTS_MODULE_PREFIX } .test_idempotent_function_serialization_pydantic_failure_no_return_type.<locals>.collect_payment#{ hash_idempotency_key (mock_event )} " # noqa E501
1367
- persistence_layer = MockPersistenceLayer (expected_idempotency_key = idempotency_key )
1368
-
1369
- class PaymentInput (BaseModel ):
1370
- customer_id : str
1371
- transaction_id : str
1372
-
1373
- class PaymentOutput (BaseModel ):
1374
- customer_id : str
1375
- transaction_id : str
1376
-
1377
- idempotent_function_decorator = idempotent_function (
1378
- data_keyword_argument = "payment" ,
1379
- persistence_store = persistence_layer ,
1380
- config = config ,
1381
- output_serializer = PydanticSerializer ,
1382
- )
1383
- with pytest .raises (IdempotencyNoSerializationModelError , match = "No serialization model was supplied" ):
1384
-
1385
- @idempotent_function_decorator
1386
- def collect_payment (payment : PaymentInput ):
1387
- return PaymentOutput (** payment .dict ())
1388
-
1389
-
1390
- def test_idempotent_function_serialization_pydantic_failure_bad_type ():
1391
- # GIVEN
1392
- config = IdempotencyConfig (use_local_cache = True )
1393
- mock_event = {"customer_id" : "fake" , "transaction_id" : "fake-id" }
1394
- idempotency_key = f"{ TESTS_MODULE_PREFIX } .test_idempotent_function_serialization_pydantic_failure_no_return_type.<locals>.collect_payment#{ hash_idempotency_key (mock_event )} " # noqa E501
1395
- persistence_layer = MockPersistenceLayer (expected_idempotency_key = idempotency_key )
1396
-
1397
- class PaymentInput (BaseModel ):
1398
- customer_id : str
1399
- transaction_id : str
1400
-
1401
- class PaymentOutput (BaseModel ):
1402
- customer_id : str
1403
- transaction_id : str
1404
-
1405
- idempotent_function_decorator = idempotent_function (
1406
- data_keyword_argument = "payment" ,
1407
- persistence_store = persistence_layer ,
1408
- config = config ,
1409
- output_serializer = PydanticSerializer ,
1410
- )
1411
- with pytest .raises (IdempotencyModelTypeError , match = "Model type is not inherited from pydantic BaseModel" ):
1412
-
1413
- @idempotent_function_decorator
1414
- def collect_payment (payment : PaymentInput ) -> dict :
1415
- return PaymentOutput (** payment .dict ())
1416
-
1417
-
1418
1313
@pytest .mark .parametrize ("output_serializer_type" , ["explicit" , "deduced" ])
1419
1314
def test_idempotent_function_serialization_dataclass (output_serializer_type : str ):
1420
1315
# GIVEN
@@ -1493,37 +1388,6 @@ def collect_payment(payment: PaymentInput):
1493
1388
return PaymentOutput (** payment .dict ())
1494
1389
1495
1390
1496
- def test_idempotent_function_serialization_dataclass_failure_bad_type ():
1497
- # GIVEN
1498
- dataclasses = get_dataclasses_lib ()
1499
- config = IdempotencyConfig (use_local_cache = True )
1500
- mock_event = {"customer_id" : "fake" , "transaction_id" : "fake-id" }
1501
- idempotency_key = f"{ TESTS_MODULE_PREFIX } .test_idempotent_function_serialization_pydantic_failure_no_return_type.<locals>.collect_payment#{ hash_idempotency_key (mock_event )} " # noqa E501
1502
- persistence_layer = MockPersistenceLayer (expected_idempotency_key = idempotency_key )
1503
-
1504
- @dataclasses .dataclass
1505
- class PaymentInput :
1506
- customer_id : str
1507
- transaction_id : str
1508
-
1509
- @dataclasses .dataclass
1510
- class PaymentOutput :
1511
- customer_id : str
1512
- transaction_id : str
1513
-
1514
- idempotent_function_decorator = idempotent_function (
1515
- data_keyword_argument = "payment" ,
1516
- persistence_store = persistence_layer ,
1517
- config = config ,
1518
- output_serializer = PydanticSerializer ,
1519
- )
1520
- with pytest .raises (IdempotencyModelTypeError , match = "Model type is not inherited from pydantic BaseModel" ):
1521
-
1522
- @idempotent_function_decorator
1523
- def collect_payment (payment : PaymentInput ) -> dict :
1524
- return PaymentOutput (** payment .dict ())
1525
-
1526
-
1527
1391
def test_idempotent_function_arbitrary_args_kwargs ():
1528
1392
# Scenario to validate we can use idempotent_function with a function
1529
1393
# with an arbitrary number of args and kwargs
@@ -1804,24 +1668,6 @@ class Foo:
1804
1668
assert as_dict == expected_result
1805
1669
1806
1670
1807
- def test_idempotent_function_pydantic ():
1808
- # Scenario _prepare_data should convert a pydantic to a dict
1809
- class Foo (BaseModel ):
1810
- name : str
1811
-
1812
- expected_result = {"name" : "Bar" }
1813
- data = Foo (name = "Bar" )
1814
- as_dict = _prepare_data (data )
1815
- assert as_dict == data .dict ()
1816
- assert as_dict == expected_result
1817
-
1818
-
1819
- @pytest .mark .parametrize ("data" , [None , "foo" , ["foo" ], 1 , True , {}])
1820
- def test_idempotent_function_other (data ):
1821
- # All other data types should be left as is
1822
- assert _prepare_data (data ) == data
1823
-
1824
-
1825
1671
def test_idempotent_function_dataclass_with_jmespath ():
1826
1672
# GIVEN
1827
1673
dataclasses = get_dataclasses_lib ()
@@ -1847,29 +1693,6 @@ def collect_payment(payment: Payment):
1847
1693
assert result == payment .transaction_id
1848
1694
1849
1695
1850
- def test_idempotent_function_pydantic_with_jmespath ():
1851
- # GIVEN
1852
- config = IdempotencyConfig (event_key_jmespath = "transaction_id" , use_local_cache = True )
1853
- mock_event = {"customer_id" : "fake" , "transaction_id" : "fake-id" }
1854
- idempotency_key = f"{ TESTS_MODULE_PREFIX } .test_idempotent_function_pydantic_with_jmespath.<locals>.collect_payment#{ hash_idempotency_key (mock_event ['transaction_id' ])} " # noqa E501
1855
- persistence_layer = MockPersistenceLayer (expected_idempotency_key = idempotency_key )
1856
-
1857
- class Payment (BaseModel ):
1858
- customer_id : str
1859
- transaction_id : str
1860
-
1861
- @idempotent_function (data_keyword_argument = "payment" , persistence_store = persistence_layer , config = config )
1862
- def collect_payment (payment : Payment ):
1863
- return payment .transaction_id
1864
-
1865
- # WHEN
1866
- payment = Payment (** mock_event )
1867
- result = collect_payment (payment = payment )
1868
-
1869
- # THEN idempotency key assertion happens at MockPersistenceLayer
1870
- assert result == payment .transaction_id
1871
-
1872
-
1873
1696
@pytest .mark .parametrize ("idempotency_config" , [{"use_local_cache" : False }], indirect = True )
1874
1697
def test_idempotent_lambda_compound_already_completed (
1875
1698
idempotency_config : IdempotencyConfig ,
0 commit comments