@@ -45,9 +45,11 @@ <h1 class="title">Module <code>serde.de</code></h1>
45
45
parts of pyserde.
46
46
"""
47
47
import abc
48
+ import functools
48
49
from dataclasses import dataclass, fields, is_dataclass
49
50
from typing import Any, Dict, List, Optional, Tuple, Type, Union
50
51
52
+ import jinja2
51
53
import stringcase
52
54
53
55
from .compat import assert_type, is_dict, is_list, is_opt, is_tuple, is_union, iter_types, type_args, typename
@@ -95,8 +97,8 @@ <h1 class="title">Module <code>serde.de</code></h1>
95
97
def wrap(cls) -> Type:
96
98
if not hasattr(cls, HIDDEN_NAME):
97
99
setattr(cls, HIDDEN_NAME, Hidden())
98
- cls = de_func(cls, FROM_ITER, args_from_iter (cls))
99
- cls = de_func(cls, FROM_DICT, args_from_dict (cls, case=rename_all))
100
+ cls = de_func(cls, FROM_ITER, render_from_iter (cls))
101
+ cls = de_func(cls, FROM_DICT, render_from_dict (cls, case=rename_all))
100
102
return cls
101
103
102
104
if _cls is None:
@@ -131,7 +133,7 @@ <h1 class="title">Module <code>serde.de</code></h1>
131
133
"""
132
134
133
135
@abc.abstractclassmethod
134
- def deserialize(self , data, **opts):
136
+ def deserialize(cls , data, **opts):
135
137
"""
136
138
deserialize `data` into an object typically `dict`, `list` or `tuple`.
137
139
@@ -180,7 +182,7 @@ <h1 class="title">Module <code>serde.de</code></h1>
180
182
>>>
181
183
"""
182
184
if de:
183
- o = de() .deserialize(o, **opts)
185
+ o = de.deserialize(o, **opts)
184
186
if o is None:
185
187
v = None
186
188
if is_deserializable(c):
@@ -439,12 +441,32 @@ <h1 class="title">Module <code>serde.de</code></h1>
439
441
return s
440
442
441
443
442
- def de_func(cls: Type[T], funcname: str, params: str) -> Type[T]:
444
+ def render_from_iter(cls: Type) -> str:
445
+ template = """
446
+ def {{func}}(data):
447
+ return cls({{cls|args}})
443
448
"""
444
- Generate function to deserialize into an instance of `deserialize` class.
449
+
450
+ env = jinja2.Environment(loader=jinja2.DictLoader({'iter': template}))
451
+ env.filters.update({'args': args_from_iter})
452
+ return env.get_template('iter').render(func=FROM_ITER, cls=cls)
453
+
454
+
455
+ def render_from_dict(cls: Type, case: Optional[str] = None) -> str:
456
+ template = """
457
+ def {{func}}(data):
458
+ return cls({{cls|args}})
445
459
"""
446
- body = f'def {funcname}(data):\n' f' return cls({params})'
447
460
461
+ env = jinja2.Environment(loader=jinja2.DictLoader({'dict': template}))
462
+ env.filters.update({'args': functools.partial(args_from_dict, case=case)})
463
+ return env.get_template('dict').render(func=FROM_DICT, cls=cls)
464
+
465
+
466
+ def de_func(cls: Type[T], func: str, code: str) -> Type[T]:
467
+ """
468
+ Generate function to deserialize into an instance of `deserialize` class.
469
+ """
448
470
# Collect types to be used in the `exec` scope.
449
471
g: Dict[str, Any] = globals().copy()
450
472
for typ in iter_types(cls):
@@ -458,11 +480,11 @@ <h1 class="title">Module <code>serde.de</code></h1>
458
480
g['NoneType'] = type(None)
459
481
460
482
# Generate deserialize function.
461
- code = gen(body , g, cls=cls)
462
- setattr(cls, funcname , staticmethod(g[funcname ]))
483
+ code = gen(code , g, cls=cls)
484
+ setattr(cls, func , staticmethod(g[func ]))
463
485
if SETTINGS['debug']:
464
486
hidden = getattr(cls, HIDDEN_NAME)
465
- hidden.code[funcname ] = code
487
+ hidden.code[func ] = code
466
488
467
489
return cls</ code > </ pre >
468
490
</ details >
@@ -690,8 +712,8 @@ <h2 class="section-title" id="header-functions">Functions</h2>
690
712
def wrap(cls) -> Type:
691
713
if not hasattr(cls, HIDDEN_NAME):
692
714
setattr(cls, HIDDEN_NAME, Hidden())
693
- cls = de_func(cls, FROM_ITER, args_from_iter (cls))
694
- cls = de_func(cls, FROM_DICT, args_from_dict (cls, case=rename_all))
715
+ cls = de_func(cls, FROM_ITER, render_from_iter (cls))
716
+ cls = de_func(cls, FROM_DICT, render_from_dict (cls, case=rename_all))
695
717
return cls
696
718
697
719
if _cls is None:
@@ -778,7 +800,7 @@ <h3 id="containers">Containers</h3>
778
800
>>>
779
801
"""
780
802
if de:
781
- o = de() .deserialize(o, **opts)
803
+ o = de.deserialize(o, **opts)
782
804
if o is None:
783
805
v = None
784
806
if is_deserializable(c):
@@ -872,7 +894,7 @@ <h2 class="section-title" id="header-classes">Classes</h2>
872
894
"""
873
895
874
896
@abc.abstractclassmethod
875
- def deserialize(self , data, **opts):
897
+ def deserialize(cls , data, **opts):
876
898
"""
877
899
deserialize `data` into an object typically `dict`, `list` or `tuple`.
878
900
@@ -883,10 +905,10 @@ <h2 class="section-title" id="header-classes">Classes</h2>
883
905
</ details >
884
906
< h3 > Subclasses</ h3 >
885
907
< ul class ="hlist ">
908
+ < li > < a title ="serde.toml.TomlDeserializer " href ="toml.html#serde.toml.TomlDeserializer "> TomlDeserializer</ a > </ li >
886
909
< li > < a title ="serde.msgpack.MsgPackDeserializer " href ="msgpack.html#serde.msgpack.MsgPackDeserializer "> MsgPackDeserializer</ a > </ li >
887
910
< li > < a title ="serde.yaml.YamlDeserializer " href ="yaml.html#serde.yaml.YamlDeserializer "> YamlDeserializer</ a > </ li >
888
911
< li > < a title ="serde.json.JsonDeserializer " href ="json.html#serde.json.JsonDeserializer "> JsonDeserializer</ a > </ li >
889
- < li > < a title ="serde.toml.TomlDeserializer " href ="toml.html#serde.toml.TomlDeserializer "> TomlDeserializer</ a > </ li >
890
912
</ ul >
891
913
< h3 > Static methods</ h3 >
892
914
< dl >
@@ -901,7 +923,7 @@ <h3>Static methods</h3>
901
923
< details class ="source ">
902
924
< summary > Source code</ summary >
903
925
< pre > < code class ="python "> @abc.abstractclassmethod
904
- def deserialize(self , data, **opts):
926
+ def deserialize(cls , data, **opts):
905
927
"""
906
928
deserialize `data` into an object typically `dict`, `list` or `tuple`.
907
929
0 commit comments