-
-
Notifications
You must be signed in to change notification settings - Fork 113
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
Support ForwardRef #215
base: main
Are you sure you want to change the base?
Support ForwardRef #215
Conversation
These test all kinds of subtleties of ForwardRefs and their (automatic, semiautomatic or manual) resolution. As dataclasses, attrs classes and type aliases behave slightly different and, in addition to that, behave differently with respect to PEP 563 (the delayed evaluation of type hints) the tests are quite extensive. A critical test-case is also whether resolution works across modules, i.e. whether ForwardRefs are handled correctly when they are imported from another module. Correct operation in any of the above cases cannot be taken for granted
Thanks for putting in work on this. The hooks are obviously fine. The issue is that this introduces |
Hmm, but what is the alternative? Not supporting dataclasses would not be very useful - at least not for me. In fact, you already do resolve dataclasses in cattr. It is the One could simplify the new |
I understand your concern regarding mantainability. However I would argue having a more symmetric way of handling dataclasses and attrs classes is cleaner and needs less maintenance effort. For instance: One can get rid of |
Could it also be that in a428272 cattr/gen.py and cattrs/gen.py are accentially swapped? |
You make a couple of good points, so let's discuss further. (The cattr -> cattrs move isn't accidental, it's on purpose. I think all new code will be going into the cattrs namespace, and existing code will be migrating there over time. The old packages will still have aliases so no backwards compatibility break.) The On a higher level, here's the philosophy of cattrs: attrs is simply a better library than dataclasses, and one of its advantages is that the maintainers of attrs (I'm one of them) choose to implement and maintain Now that you see where I'm coming from, you say you're forced to use dataclasses and I'm sympathetic to this use case. So let's discuss to see what we can accomplish without cattrs implementing One of the options is you implementing Also, didn't you mention ForwardRefs can resolve themselves in newer Python versions? Presumably via |
The primary reason to implement Perhaps let me first expand on what functionality is needed:
The original idea was to concentrate all So now let me try to address your specific concerns: I see several options:
So if we do 1 & 3 and possibly 4, the resolve_types would have the dataclasses handling removed and not be exported. It would not generate an error when called for datacasses and work for type aliases as well. [1]: Even though these types are not (yet) supported by cattrs, the user might still register a hook for them and expect child ForwardRefs to work. |
Could you elaborate on that? |
This adds ForwardRef support to cattr (See #201).
ForwardRefs in classes
Recursive classes
Recursive type aliases. (Note: Even with PEP 563 we need ForwardRefs here)
Recursive type aliases, across modules. (Needs explicit ForwardRef resolution, though. This is a Python limitation)
Manual registration (this worked before, but is still supported.) This PR also fixes TypeError when registering ForwardRefs in python 3.10.2 #206)
Specifically, the PR does
Add hooks for ForwardRef (this equires ForwardRefs to be in resolved state, otherwise an error is generated)
Ensure that ForwardRef are resolved for registered types, whenever it is possible to resolve them without context information. (Essentially this is done by a call
get_type_hints
on the type containing the ForwardRef).For this a new function
resolve_types
was added which is systematically used. It basically does the same thing asattrs.resolve_types
but works for all types (attrs classes, dataclasses and type aliases).ForwardRefs are now registered with direct dispatch and no longer singledispatch. This is to work around TypeError when registering ForwardRefs in python 3.10.2 #206.