1+ from typing import Any
12from typing import List
23from typing import Optional
34
5+ from cryptojwt .utils import as_bytes
46from cryptojwt .utils import importer
57from cryptojwt .utils import qualified_name
68
911
1012class ImpExp :
1113 parameter = {}
14+ special_load_dump = {}
15+ init_args = []
1216
1317 def __init__ (self ):
1418 pass
1519
16- def _dump (self , cls , item , exclude_attributes : Optional [List [str ]] = None ) -> dict :
17- if cls in [None , "" , [], {}]:
18- val = item
20+ def dump_attr (self , cls , item , exclude_attributes : Optional [List [str ]] = None ) -> dict :
21+ if cls in [None , 0 , "" , [], {}, bool , b'' ]:
22+ if cls == b'' :
23+ val = as_bytes (item )
24+ else :
25+ val = item
1926 elif isinstance (item , Message ):
2027 val = {qualified_name (item .__class__ ): item .to_dict ()}
2128 elif cls == object :
2229 val = qualified_name (item )
2330 elif isinstance (cls , list ):
24- val = [self ._dump (cls [0 ], v , exclude_attributes ) for v in item ]
31+ val = [self .dump_attr (cls [0 ], v , exclude_attributes ) for v in item ]
2532 else :
2633 val = item .dump (exclude_attributes = exclude_attributes )
2734
@@ -31,42 +38,98 @@ def dump(self, exclude_attributes: Optional[List[str]] = None) -> dict:
3138 _exclude_attributes = exclude_attributes or []
3239 info = {}
3340 for attr , cls in self .parameter .items ():
34- if attr in _exclude_attributes :
41+ if attr in _exclude_attributes or attr in self . special_load_dump :
3542 continue
3643
3744 item = getattr (self , attr , None )
3845 if item is None :
3946 continue
4047
41- info [attr ] = self ._dump (cls , item , exclude_attributes )
48+ info [attr ] = self .dump_attr (cls , item , exclude_attributes )
49+
50+ for attr , d in self .special_load_dump .items ():
51+ item = getattr (self , attr , None )
52+ if item :
53+ info [attr ] = d ["dump" ](item , exclude_attributes = exclude_attributes )
4254
4355 return info
4456
45- def _local_adjustments (self ):
57+ def local_load_adjustments (self , ** kwargs ):
4658 pass
4759
48- def _load (self , cls , item ):
49- if cls in [None , "" , [], {}]:
50- val = item
60+ def load_attr (
61+ self ,
62+ cls : Any ,
63+ item : dict ,
64+ init_args : Optional [dict ] = None ,
65+ load_args : Optional [dict ] = None ,
66+ ) -> Any :
67+ if load_args :
68+ _kwargs = {"load_args" : load_args }
69+ _load_args = load_args
70+ else :
71+ _kwargs = {}
72+ _load_args = {}
73+
74+ if init_args :
75+ _kwargs ["init_args" ] = init_args
76+
77+ if cls in [None , 0 , "" , [], {}, bool , b'' ]:
78+ if cls == b'' :
79+ val = as_bytes (item )
80+ else :
81+ val = item
5182 elif cls == object :
5283 val = importer (item )
5384 elif isinstance (cls , list ):
54- val = [cls [0 ]().load (v ) for v in item ]
85+ if isinstance (cls [0 ], str ):
86+ _cls = importer (cls [0 ])
87+ else :
88+ _cls = cls [0 ]
89+
90+ if issubclass (_cls , ImpExp ) and init_args :
91+ _args = {k : v for k , v in init_args .items () if k in _cls .init_args }
92+ else :
93+ _args = {}
94+
95+ val = [_cls (** _args ).load (v , ** _kwargs ) for v in item ]
5596 elif issubclass (cls , Message ):
56- val = cls ().from_dict (item )
97+ _cls_name = list (item .keys ())[0 ]
98+ _cls = importer (_cls_name )
99+ val = _cls ().from_dict (item [_cls_name ])
57100 else :
58- val = cls ().load (item )
101+ if issubclass (cls , ImpExp ) and init_args :
102+ _args = {k : v for k , v in init_args .items () if k in cls .init_args }
103+ else :
104+ _args = {}
105+
106+ val = cls (** _args ).load (item , ** _kwargs )
59107
60108 return val
61109
62- def load (self , item : dict ):
110+ def load (self , item : dict , init_args : Optional [dict ] = None , load_args : Optional [dict ] = None ):
111+
112+ if load_args :
113+ _kwargs = {"load_args" : load_args }
114+ _load_args = load_args
115+ else :
116+ _kwargs = {}
117+ _load_args = {}
118+
119+ if init_args :
120+ _kwargs ["init_args" ] = init_args
121+
63122 for attr , cls in self .parameter .items ():
64- if attr not in item :
123+ if attr not in item or attr in self . special_load_dump :
65124 continue
66125
67- setattr (self , attr , self ._load (cls , item [attr ]))
126+ setattr (self , attr , self .load_attr (cls , item [attr ], ** _kwargs ))
127+
128+ for attr , func in self .special_load_dump .items ():
129+ if attr in item :
130+ setattr (self , attr , func ["load" ](item [attr ], ** _kwargs ))
68131
69- self ._local_adjustments ( )
132+ self .local_load_adjustments ( ** _load_args )
70133 return self
71134
72135 def flush (self ):
@@ -78,6 +141,10 @@ def flush(self):
78141 for attr , cls in self .parameter .items ():
79142 if cls is None :
80143 setattr (self , attr , None )
144+ elif cls == 0 :
145+ setattr (self , attr , 0 )
146+ elif cls is bool :
147+ setattr (self , attr , False )
81148 elif cls == "" :
82149 setattr (self , attr , "" )
83150 elif cls == []:
0 commit comments