@@ -986,6 +986,120 @@ def encode_decimal(obj):
986986 api .unregister_encoder (encode_decimal )
987987
988988
989+ def test_custom_encoders_with_parent_and_sort_keys ():
990+ """Test that custom encoders can receive _parent and _sort_keys parameters."""
991+ import decimal
992+
993+ parent_captured = None
994+ sort_keys_captured = None
995+
996+ @api .register_encoder
997+ def encode_decimal_with_context (obj , _parent = None , _sort_keys = False ):
998+ nonlocal parent_captured , sort_keys_captured
999+ if isinstance (obj , decimal .Decimal ):
1000+ parent_captured = _parent
1001+ sort_keys_captured = _sort_keys
1002+ return api .float_ (str (obj ))
1003+ raise TypeError
1004+
1005+ # Test with default parameters
1006+ result = api .item (decimal .Decimal ("1.23" ))
1007+ assert result .as_string () == "1.23"
1008+ assert parent_captured is None
1009+ assert sort_keys_captured is False
1010+
1011+ # Test with custom parent and sort_keys
1012+ parent_captured = None
1013+ sort_keys_captured = None
1014+ table = api .table ()
1015+ result = item (decimal .Decimal ("4.56" ), _parent = table , _sort_keys = True )
1016+ assert result .as_string () == "4.56"
1017+ assert parent_captured is table
1018+ assert sort_keys_captured is True
1019+
1020+ api .unregister_encoder (encode_decimal_with_context )
1021+
1022+
1023+ def test_custom_encoders_backward_compatibility ():
1024+ """Test that old-style custom encoders still work without modification."""
1025+ import decimal
1026+
1027+ @api .register_encoder
1028+ def encode_decimal_old_style (obj ):
1029+ # Old style encoder - only accepts obj parameter
1030+ if isinstance (obj , decimal .Decimal ):
1031+ return api .float_ (str (obj ))
1032+ raise TypeError
1033+
1034+ # Should work exactly as before
1035+ result = api .item (decimal .Decimal ("2.34" ))
1036+ assert result .as_string () == "2.34"
1037+
1038+ # Should work when called from item() with extra parameters
1039+ table = api .table ()
1040+ result = item (decimal .Decimal ("5.67" ), _parent = table , _sort_keys = True )
1041+ assert result .as_string () == "5.67"
1042+
1043+ api .unregister_encoder (encode_decimal_old_style )
1044+
1045+
1046+ def test_custom_encoders_with_kwargs ():
1047+ """Test that custom encoders can use **kwargs to accept additional parameters."""
1048+ import decimal
1049+
1050+ kwargs_captured = None
1051+
1052+ @api .register_encoder
1053+ def encode_decimal_with_kwargs (obj , ** kwargs ):
1054+ nonlocal kwargs_captured
1055+ if isinstance (obj , decimal .Decimal ):
1056+ kwargs_captured = kwargs
1057+ return api .float_ (str (obj ))
1058+ raise TypeError
1059+
1060+ # Test with parent and sort_keys passed as kwargs
1061+ table = api .table ()
1062+ result = item (decimal .Decimal ("7.89" ), _parent = table , _sort_keys = True )
1063+ assert result .as_string () == "7.89"
1064+ assert kwargs_captured == {"_parent" : table , "_sort_keys" : True }
1065+
1066+ api .unregister_encoder (encode_decimal_with_kwargs )
1067+
1068+
1069+ def test_custom_encoders_for_complex_objects ():
1070+ """Test custom encoders that need to encode nested structures."""
1071+
1072+ class CustomDict :
1073+ def __init__ (self , data ):
1074+ self .data = data
1075+
1076+ @api .register_encoder
1077+ def encode_custom_dict (obj , _parent = None , _sort_keys = False ):
1078+ if isinstance (obj , CustomDict ):
1079+ # Create a table and use item() to convert nested values
1080+ table = api .table ()
1081+ for key , value in obj .data .items ():
1082+ # Pass along _parent and _sort_keys when converting nested values
1083+ table [key ] = item (value , _parent = table , _sort_keys = _sort_keys )
1084+ return table
1085+ raise TypeError
1086+
1087+ # Test with nested structure
1088+ custom_obj = CustomDict ({"a" : 1 , "b" : {"c" : 2 , "d" : 3 }})
1089+ result = item (custom_obj , _sort_keys = True )
1090+
1091+ # Should properly format as a table with sorted keys
1092+ expected = """a = 1
1093+
1094+ [b]
1095+ c = 2
1096+ d = 3
1097+ """
1098+ assert result .as_string () == expected
1099+
1100+ api .unregister_encoder (encode_custom_dict )
1101+
1102+
9891103def test_no_extra_minus_sign ():
9901104 doc = parse ("a = -1" )
9911105 assert doc .as_string () == "a = -1"
0 commit comments