-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocs_ex08_converters.py
More file actions
59 lines (45 loc) · 1.6 KB
/
docs_ex08_converters.py
File metadata and controls
59 lines (45 loc) · 1.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from ducktools.classbuilder import (
add_methods,
get_fields,
make_unified_gatherer,
print_generated_code,
GeneratedCode,
MethodMaker,
)
from ducktools.classbuilder.prefab import attribute, Attribute, Prefab
class ConverterAttribute(Attribute):
converter = attribute(default=None)
# This makes the internal field instances into `ConverterAttribute` instead of `Attribute`
# which would be the default for `prefab`
gatherer = make_unified_gatherer(field_type=ConverterAttribute)
def setattr_generator(cls, funcname="__setattr__"):
fields = get_fields(cls)
converters = {}
for k, v in fields.items():
if conv := getattr(v, "converter", None):
converters[k] = conv
globs = {
"_converters": converters,
"_object_setattr": object.__setattr__,
}
code = (
f"def {funcname}(self, name, value):\n"
f" if conv := _converters.get(name):\n"
f" _object_setattr(self, name, conv(value))\n"
f" else:\n"
f" _object_setattr(self, name, value)\n"
)
return GeneratedCode(code, globs)
setattr_maker = MethodMaker("__setattr__", setattr_generator)
extra_methods = {setattr_maker}
class ConverterClass(Prefab, gatherer=gatherer):
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
add_methods(cls, extra_methods)
if __name__ == "__main__":
class ConverterEx(ConverterClass):
unconverted: str
converted: int = ConverterAttribute(converter=int)
ex = ConverterEx("42", "42")
print(ex)
print_generated_code(ConverterEx)