1+ import json
2+ import re
13import pytest
24from enum import Enum
35from unittest import TestCase
@@ -380,4 +382,79 @@ class An_Class(Type_Safe):
380382 assert An_Class (an_dict = {'A' : 42 }).json () == { 'an_dict' : { 'A' : 42 }} # FIXED
381383 assert An_Class .from_json (An_Class (an_dict = {'A' : 42 }).json ()).obj () == __ (an_dict = __ (A = 42 )) # FIXED
382384 assert An_Class .from_json ({ 'an_dict' : { An_Enum .A : 42 }} ).obj () == __ (an_dict = __ (A = 42 )) #
383- assert An_Class .from_json ({ 'an_dict' : { 'A' : 42 }} ).obj () == __ (an_dict = __ (A = 42 )) #
385+ assert An_Class .from_json ({ 'an_dict' : { 'A' : 42 }} ).obj () == __ (an_dict = __ (A = 42 )) #
386+
387+ def test__regression__nested_dict_enum_keys__obj_vs_json_inconsistency (self ):
388+ """
389+ BUG: .obj() and .json() are inconsistent for nested Dict with Enum keys.
390+ .json() uses enum.value, .obj() uses transformed enum.name
391+ """
392+ class Status (str , Enum ):
393+ ACTIVE = 'active'
394+ INACTIVE = 'inactive'
395+
396+ class Container (Type_Safe ):
397+ nested : Dict [str , Dict [Status , int ]]
398+
399+ container = Container (nested = {'key' : {Status .ACTIVE : 100 }})
400+
401+ # .json() uses enum VALUE
402+ assert container .json () == {'nested' : {'key' : {'active' : 100 }}}
403+
404+ # BUG: .obj() should also use 'active' but uses 'Status_ACTIVE'
405+ #assert container.obj() == __(nested=__(key=__(Status_ACTIVE=100))) # BUG Current behavior
406+ #assert container.obj() != __(nested=__(key=__(active=100))) # BUG Expected behavior
407+ assert container .obj () == __ (nested = __ (key = __ (active = 100 ))) # FIXED
408+
409+ # assert container.json() == {'nested': {'key': {Status.ACTIVE: 100}}} # BUG
410+ # error_message = ("assert {'nested': {'key': {<Status.ACTIVE: 'active'>: 100}}} == {}\n \n "
411+ # "Left contains 1 more item:\n "
412+ # "{'nested': {'key': {<Status.ACTIVE: 'active'>: 100}}}\n \n "
413+ # "Full diff:\n - {}\n + {\n + 'nested': {\n + 'key': "
414+ # "{\n + <Status.ACTIVE: 'active'>: 100,\n + },\n + "
415+ # "},\n + }") # BUG
416+ assert container .json () == {'nested' : {'key' : {Status .ACTIVE : 100 }}} # this works due to auto conversion of enum into it's string value
417+ assert container .json () == {'nested' : {'key' : {'active' : 100 }}} # FIXED: this is what we wanted to happen
418+ error_message = ("assert {'nested': {'key': {'active': 100}}} == {}\n \n "
419+ "Left contains 1 more item:\n "
420+ "{'nested': {'key': {'active': 100}}}\n \n " # FIXED: now we get the 'active' string (instead of the Enum representation)
421+ "Full diff:\n - {}\n + {\n + 'nested': "
422+ "{\n + 'key': {\n + "
423+ "'active': 100,\n + },\n + },\n + }" )
424+ with pytest .raises (AssertionError , match = re .escape (error_message )):
425+ assert container .json () == {} # FIXED this is the error message we should get
426+
427+ error_message_2 = 'assert __(nested=__(key=__(active=100))) == __()\n '
428+ with pytest .raises (AssertionError , match = re .escape (error_message_2 )):
429+ assert container .obj () == __ ()
430+
431+ # couple more edge cases tests
432+ json_str = json .dumps (container .json ())
433+ assert json_str == '{"nested": {"key": {"active": 100}}}'
434+ assert json .loads (json_str ) == {'nested' : {'key' : {'active' : 100 }}}
435+
436+ container2 = Container (nested = {'key' : {Status .ACTIVE : 100 , Status .INACTIVE : 50 }})
437+ assert container2 .json () == {'nested' : {'key' : {'active' : 100 , 'inactive' : 50 }}}
438+ assert container2 .obj () == __ (nested = __ (key = __ (active = 100 , inactive = 50 )))
439+
440+ # Test round-trip consistency
441+ container3 = Container .from_json (container .json ())
442+ assert container3 .json () == container .json ()
443+ assert container3 .obj () == container .obj ()
444+
445+ def test__regression__simple_dict_enum_keys__now__works_correctly (self ):
446+
447+ class Status (str , Enum ):
448+ ACTIVE = 'active'
449+ INACTIVE = 'inactive'
450+
451+ class SimpleContainer (Type_Safe ):
452+ data : Dict [Status , int ]
453+
454+ simple = SimpleContainer (data = {Status .ACTIVE : 100 })
455+
456+ # Single-level Dict works correctly - uses enum value
457+ assert simple .json () == {'data' : {'active' : 100 }} # ✓ Correct
458+
459+ # And it's JSON-serializable
460+ assert json .dumps (simple .json ()) == '{"data": {"active": 100}}' # ✓ Works
0 commit comments