Using several factories simultaneously
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
Research direction
Start by reproducing the example and tracing register_unstructure_hook_factory, unstructure, and make_dict_unstructure_fn to understand how predicates and factories are selected. Determine whether the requested composition is supported by the existing API or needs a design decision. Done means Base, Sub, and SubSub produce the three expected dictionaries with type, is_sub, and renamed fields applied together.
Written by the indexing model from the issue text.
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, thetypefield should be always present. - Both
subandsubsubare of typeSub, meaning I want to get their additionalis_subfield. - Finally,
subsubhas 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 🙃
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 159
- Avg merge
- 12h 21m
- Merged PRs (30d)
- 6
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from python-attrs/cattrs
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
python-attrs/cattrs#761 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
python-attrs/cattrs#513 · 4 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
python-attrs/cattrs#779 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 85/100
python-attrs/cattrs#774 ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
python-attrs/cattrs#746 · 2 comments ·
All issues in python-attrs/cattrs
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100