-
-
Notifications
You must be signed in to change notification settings - Fork 114
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
Feature request: add a new disambiguation strategy #317
Comments
I agree we should add a new disambiguation strategy based on tagged unions (the nomenclature is a little fuzzy here since there are a lot of terms being used in slightly different contexts). Like you said, the idea would be to inject a piece of data into the payload during unstructuring, and to use that piece during structuring. I think we should be very flexible in what that piece of data is, probably allowing the user to pass in a callable or a dictionary when creating the strategy, and a default class when that piece of data is not present. Could be the class name, the fully qualified class name, maybe a classvar on each of the classes, maybe a hardcoded mapping. We also need to be able to customize the key under which this piece of data is being stored. I think this would be super useful to have. The current default strategy is very simple, since cattrs aims for simple defaults. We also can't change the default strategy for backwards compatibility reasons I think. But new strategies should be easily pluggable by the user. The default strategy only works with fields with no defaults because it's not safe to do otherwise in a general sense. Say you have two classes: @define
class A:
a: int = 0
@define
class B:
b: int = 0 And you get a payload of Keep in mind cattrs doesn't assume it's being used at both ends; we need to be able to structure unions from third parties, and third parties often omit optional keys from payloads. We can get the tagged union support in before the next release, no worries. |
Thanks for taking the time to make a detailed answer.
Agreed. I was starting to implement a subset of the features you mentioned but I thought I went a little overboard. I reduced the scope in my initial implementation by just giving the choice of the key name to add in the payload. One difficulty I had is how to transfer all those options down and up the stack to reach the disambiguation generator function. I am eager to see your customize method, it sounds promising with respect to those kind of issues.
Agreed and this is what I have implemented. The alternate strategy is opt-in and not the default.
Thanks that is some context I was missing. It makes sense. |
Hi, I've got a PR with the tagged union strategy here: #318 There's a way to apply this to the include_subclasses strategy easily, I think. Let me know what you think. |
I did not test on my use case yet, but the documentation and the features that you propose are definitely well in line with what I would need. |
I think this is complete? |
Description
As mentioned in the tips for handling unions in the documentation, one easy way to resolve the union is to incorporate the type name as an additional key during the destructuring / structuring process. I would like to add a disambiguation function of this nature because the need is even more pressing when you deal with subclasses.
At the moment the union resolving strategy is based on unique fields of
attrs
classes that do not have defaults. It is actually quite easy in the subclassing union type context to get into the situation where one (or all) of the classes participating in the union have unique fields but with defaults. I think that the type name strategy is a good alternative.I am wondering the following:
_cattrs_omit_if_default=True
argument ofmake_dict_unstructure_fn
?type_disambiguation
branch of my fork but I am waiting to have the subclasses API settled (re:customize
method ofConverter
) before sending this new PR.@Tinche thoughts?
The text was updated successfully, but these errors were encountered: