-
-
Notifications
You must be signed in to change notification settings - Fork 120
Open
Description
Hi @Tinche, my previous issue was basically pointless but I'm now getting closer to the heart of my problem. While I think I understand how regular hooks can be composed, it's not quite clear to me how somethign similar can be achieved using predicates/factories.
In essence, it would help me to better understand how hooks/predicates/factories interplay and how it is possible to "activate" certain customizations at once. The problem that I get with factories is that only ever one of them is active. Here a little example what I mean:
import cattrs
from attrs import define
converter = cattrs.Converter()
@define
class Base:
x: int = 0
@define
class Sub(Base):
y: int = 1
@define
class SubSub(Sub):
z: int = 1
@define
class Container:
contains: Base
@converter.register_unstructure_hook
def some_special_configuration(obj: SubSub) -> dict:
fn = cattrs.gen.make_dict_unstructure_fn(
SubSub, converter, x=cattrs.override(rename="renamed")
)
return fn(obj)
@converter.register_unstructure_hook_factory(lambda c: c is Base)
def add_type(_):
def hook(obj):
hook = cattrs.gen.make_dict_unstructure_fn(type(obj), converter)
return {"type": obj.__class__.__name__, **hook(obj)}
return hook
@converter.register_unstructure_hook_factory(lambda c: issubclass(c, Sub))
def indicate_if_sub(_):
def hook(obj):
hook = cattrs.gen.make_dict_unstructure_fn(type(obj), converter)
return {"is_sub": obj.__class__.__name__, **hook(obj)}
return hook
contains_base = Container(Base())
contains_sub = Container(Sub())
contains_subsub = Container(SubSub())
print(converter.unstructure(contains_base))
print(converter.unstructure(contains_sub))
print(converter.unstructure(contains_subsub))
Gives:
{'contains': {'type': 'Base', 'x': 0}}
{'contains': {'type': 'Sub', 'x': 0, 'y': 1}}
{'contains': {'type': 'SubSub', 'x': 0, 'y': 1, 'z': 1}}
How can I change the logic such that all rules are "active" at the same time, that is:
- Because everything is unstructured as
Base
, thetype
field should be always present. - Both
sub
andsubsub
are of typeSub
, meaning I want to get their additionalis_sub
field. - Finally,
subsub
has a special renaming that should be considered.
So what I want is rather:
{'contains': {'type': 'Base', 'x': 0}}
{'contains': {'type': 'Sub', 'is_sub': 'Sub', 'x': 0, 'y': 1}}
{'contains': {'type': 'SubSub', 'is_sub': 'SubSub', 'renamed': 0, 'y': 1, 'z': 1}}
I'd really appreciate if you could point me to the right track 🙃
Metadata
Metadata
Assignees
Labels
No labels