-
-
Notifications
You must be signed in to change notification settings - Fork 111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Respect type annotation for containers #129
Comments
Ah, I see your issue. Historically, the semantics of unstructuring were inherited from A neat benefit of this is also that unstructure hooks can be very simple, for example if you want to stringify something while unstructuring, you just register the There's also the problem of backwards compatibility to take into consideration. I agree having a type parameter in there is useful. The initial motivating case for |
Thanks for your answer, however if I now introduce @define
class HasSequenceOfA:
sequence_of_a: MutableSequence[A] and do print(converter.unstructure(HasSequenceOfA(b))) I still only get
Am I missing something? |
Hm, I was mistaken. Let me see if I can fix this in the next couple of days. |
I think I have the solution in https://github.com/Tinche/cattrs/tree/fix-unstuct-iterable-type |
This has been merged into master! |
Awesome, I'll give it a spin over the weekend |
Just tested this out. Seems to work on |
This is what I used: c = cattrs.GenConverter()
@attr.define
class A:
a: int
@attr.define
class B:
a: int
@attr.define
class C:
f: Optional[Union[A, B]]
c.register_unstructure_hook(
Union[A, B],
lambda o: {"_type": o.__class__.__name__, **c.unstructure(o)},
)
c.register_structure_hook(
Union[A, B], lambda o, t: c.structure(o, A if o["_type"] == "A" else B)
)
inst = C(A(1))
unstructured = c.unstructure(inst)
assert unstructured["f"]["_type"] == "A"
assert c.structure(unstructured, C) == inst |
Unions are a little special, but they should work. Will take a look. |
@pattonw Actually I see the issue. |
Hmm, this doesn't work either. But this also doesn't seem like an ergonomic way of writing this hook. c = cattrs.GenConverter()
@attr.define
class A:
a: int
@attr.define
class B:
a: int
@attr.define
class C:
f: Optional[Union[A, B]]
c.register_unstructure_hook(
Union[A, B, None],
lambda o: {"_type": o.__class__.__name__, **c.unstructure(o)}
if o is not None
else None,
)
c.register_structure_hook(
Union[A, B, None],
lambda o, t: c.structure(
o, eval(o["_type"]) if o is not None else None
),
)
inst = C(A(1))
unstructured = c.unstructure(inst)
assert unstructured["f"]["_type"] == "A"
assert c.structure(unstructured, C) == inst |
This works:
The reason your example doesn't work is interesting. As I mentioned, the Python interpreter evaluates
but this isn't:
Anyway, I can fix this by using |
Note that in 3.10 the Optional and Union types are going to basically deprecated, so you'll be writing |
Pushed a change to master that makes |
Description
If I see it correctly, support for generics exist. However, containers can also be generic and in combination with Protocols we could do neat things.
In a way, this leads me to a question: Why do unstructure hooks not also take an optional
cls
argument with the annotated type?What I Did
The text was updated successfully, but these errors were encountered: