1111from aws_durable_execution_sdk_python_testing .exceptions import (
1212 InvalidParameterValueException ,
1313)
14- from aws_durable_execution_sdk_python_testing .web . serialization import (
14+ from aws_durable_execution_sdk_python_testing .serialization import (
1515 JSONSerializer ,
1616 AwsRestJsonDeserializer ,
1717 AwsRestJsonSerializer ,
18+ SimthyDateTimeEncoder ,
19+ datetime_object_hook ,
1820)
1921
2022
@@ -40,12 +42,10 @@ def test_aws_rest_json_serializer_should_initialize_and_serialize_data():
4042 )
4143
4244
43- @patch ("aws_durable_execution_sdk_python_testing.web.serialization.create_serializer" )
44- @patch ("aws_durable_execution_sdk_python_testing.web.serialization.ServiceModel" )
45- @patch (
46- "aws_durable_execution_sdk_python_testing.web.serialization.botocore.loaders.Loader"
47- )
48- @patch ("aws_durable_execution_sdk_python_testing.web.serialization.os.path.dirname" )
45+ @patch ("aws_durable_execution_sdk_python_testing.serialization.create_serializer" )
46+ @patch ("aws_durable_execution_sdk_python_testing.serialization.ServiceModel" )
47+ @patch ("aws_durable_execution_sdk_python_testing.serialization.botocore.loaders.Loader" )
48+ @patch ("aws_durable_execution_sdk_python_testing.serialization.os.path.dirname" )
4949def test_aws_rest_json_serializer_should_create_serializer_with_boto_components (
5050 mock_dirname ,
5151 mock_loader_class ,
@@ -90,7 +90,7 @@ def test_aws_rest_json_serializer_should_create_serializer_with_boto_components(
9090 mock_service_model .operation_model .assert_called_once_with (operation_name )
9191
9292
93- @patch ("aws_durable_execution_sdk_python_testing.web. serialization.create_serializer" )
93+ @patch ("aws_durable_execution_sdk_python_testing.serialization.create_serializer" )
9494def test_aws_rest_json_serializer_should_raise_serialization_error_when_create_fails (
9595 mock_create_serializer ,
9696):
@@ -222,12 +222,10 @@ def test_aws_rest_json_deserializer_should_initialize_and_deserialize_data():
222222 mock_parser .parse .assert_called_once_with (expected_response_dict , mock_output_shape )
223223
224224
225- @patch ("aws_durable_execution_sdk_python_testing.web.serialization.create_parser" )
226- @patch ("aws_durable_execution_sdk_python_testing.web.serialization.ServiceModel" )
227- @patch (
228- "aws_durable_execution_sdk_python_testing.web.serialization.botocore.loaders.Loader"
229- )
230- @patch ("aws_durable_execution_sdk_python_testing.web.serialization.os.path.dirname" )
225+ @patch ("aws_durable_execution_sdk_python_testing.serialization.create_parser" )
226+ @patch ("aws_durable_execution_sdk_python_testing.serialization.ServiceModel" )
227+ @patch ("aws_durable_execution_sdk_python_testing.serialization.botocore.loaders.Loader" )
228+ @patch ("aws_durable_execution_sdk_python_testing.serialization.os.path.dirname" )
231229def test_aws_rest_json_deserializer_should_create_deserializer_with_boto_components (
232230 mock_dirname ,
233231 mock_loader_class ,
@@ -274,7 +272,7 @@ def test_aws_rest_json_deserializer_should_create_deserializer_with_boto_compone
274272 mock_service_model .operation_model .assert_called_once_with (operation_name )
275273
276274
277- @patch ("aws_durable_execution_sdk_python_testing.web. serialization.create_parser" )
275+ @patch ("aws_durable_execution_sdk_python_testing.serialization.create_parser" )
278276def test_aws_rest_json_deserializer_should_raise_serialization_error_when_create_fails (
279277 mock_create_parser ,
280278):
@@ -574,3 +572,108 @@ def test_serialize_multiple_datetimes():
574572 expected = b'{"start":1735689600.0,"end":1767225599.0}'
575573
576574 assert result == expected
575+
576+
577+ def test_smithy_datetime_encoder_converts_datetime_to_milliseconds ():
578+ """Test that SimthyDateTimeEncoder converts datetime to millisecond timestamps."""
579+ encoder = SimthyDateTimeEncoder ()
580+ dt = datetime (2025 , 11 , 5 , 16 , 30 , 9 , 895000 , tzinfo = timezone .utc )
581+
582+ result = encoder .default (dt )
583+ expected = int (dt .timestamp () * 1000 )
584+
585+ assert result == expected
586+ assert result == 1762360209895
587+
588+
589+ def test_smithy_datetime_encoder_handles_non_datetime_objects ():
590+ """Test that SimthyDateTimeEncoder delegates to parent for non-datetime objects."""
591+ encoder = SimthyDateTimeEncoder ()
592+
593+ # Should delegate to parent's default method for non-datetime objects
594+ with pytest .raises (TypeError ):
595+ encoder .default (object ())
596+
597+
598+ def test_smithy_datetime_encoder_in_json_dumps ():
599+ """Test SimthyDateTimeEncoder when used with json.dumps."""
600+ dt = datetime (2025 , 11 , 5 , 16 , 30 , 9 , 895000 , tzinfo = timezone .utc )
601+ data = {"timestamp" : dt }
602+
603+ result = json .dumps (data , cls = SimthyDateTimeEncoder )
604+ expected = '{"timestamp": 1762360209895}'
605+
606+ assert result == expected
607+
608+
609+ def test_smithy_datetime_encoder_precision ():
610+ """Test that SimthyDateTimeEncoder maintains millisecond precision."""
611+ encoder = SimthyDateTimeEncoder ()
612+ dt = datetime (2025 , 11 , 5 , 16 , 30 , 9 , 123456 , tzinfo = timezone .utc )
613+
614+ result = encoder .default (dt )
615+ expected = int (dt .timestamp () * 1000 )
616+
617+ assert result == expected
618+ assert result == 1762360209123
619+
620+
621+ def test_datetime_object_hook_converts_timestamp_fields ():
622+ """Test that datetime_object_hook converts timestamp fields to datetime objects."""
623+ from datetime import UTC
624+
625+ obj = {
626+ "user_timestamp" : 1762360209 ,
627+ "created_time" : 1735689600.0 ,
628+ "lastModifiedTimestamp" : 1767225599 ,
629+ "endTime" : 1762360209.895 ,
630+ }
631+
632+ result = datetime_object_hook (obj )
633+
634+ assert isinstance (result ["user_timestamp" ], datetime )
635+ assert isinstance (result ["created_time" ], datetime )
636+ assert isinstance (result ["lastModifiedTimestamp" ], datetime )
637+ assert isinstance (result ["endTime" ], datetime )
638+ assert result ["user_timestamp" ].tzinfo == UTC
639+
640+
641+ def test_datetime_object_hook_preserves_non_timestamp_fields ():
642+ """Test that datetime_object_hook preserves fields that don't match timestamp patterns."""
643+ obj = {"name" : "test" , "count" : 42 , "price" : 19.99 , "active" : True }
644+
645+ result = datetime_object_hook (obj )
646+
647+ assert result == obj
648+ assert result ["name" ] == "test"
649+ assert result ["count" ] == 42
650+ assert result ["price" ] == 19.99
651+ assert result ["active" ] is True
652+
653+
654+ def test_datetime_object_hook_handles_non_dict_objects ():
655+ """Test that datetime_object_hook returns non-dict objects unchanged."""
656+ assert datetime_object_hook ("string" ) == "string"
657+ assert datetime_object_hook (42 ) == 42
658+ assert datetime_object_hook ([1 , 2 , 3 ]) == [1 , 2 , 3 ]
659+ assert datetime_object_hook (None ) is None
660+
661+
662+ def test_datetime_object_hook_mixed_field_types ():
663+ """Test datetime_object_hook with mixed field types including nested structures."""
664+ obj = {
665+ "event_timestamp" : 1762360209 ,
666+ "metadata" : {"created_time" : 1735689600 , "description" : "test event" },
667+ "tags" : ["important" , "user-action" ],
668+ "count" : 1 ,
669+ }
670+
671+ result = datetime_object_hook (obj )
672+
673+ assert isinstance (result ["event_timestamp" ], datetime )
674+ assert result ["metadata" ] == {
675+ "created_time" : 1735689600 ,
676+ "description" : "test event" ,
677+ }
678+ assert result ["tags" ] == ["important" , "user-action" ]
679+ assert result ["count" ] == 1
0 commit comments