-
Notifications
You must be signed in to change notification settings - Fork 129
Fix handling of type var syntax and types.GenericAlias
#962
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
base: main
Are you sure you want to change the base?
Fix handling of type var syntax and types.GenericAlias
#962
Conversation
63b9a18 to
57bf7e6
Compare
|
Okay, maybe this isn't a good solution. I've discovered a slight issue with the It does not cache itself when called directly (i.g. doing Since msgspec relies on that cache being preserved, the solution as currently proposed only maintains the cache within a decoder instance, meaning that calling Note that this only affects generic types bound by a |
43d8d35 to
4285b96
Compare
|
Alright, I think I managed to find a solution. Essentially, we're now reproducing a It's basically doing typing._GenericAlias(
alias.__origin__,
alias.__origin__.__parameters__
).__getitem__(*alias.__args__)which is functionally the same as alias = typing._SpecialGenericAlias(list, 1)[int]
# this is the same as
alias = typing.List[int]I've also added some more test cases to ensure the caching works properly in all newly supported cases. |
|
Another friendly ping to @ofek for a review :) |
Fix #957.
This is a few fixes combined into one, since they were tightly coupled.
Handling of "new style" generics during type resolution
When subscribing a "new style" generic (such as
collections.abc.Mapping), it produces atypes.GenericAlias(vs. the "old style"typing._GenericAlias), which msgspec did not handle correctly during inspectionHandling of type var syntax
When dealing with builtin generics that resolve to
typing.TypeAlias, msgspec did not account for type var syntax at correctly in all cases, so type information would get lost during the conversion processType conversions on
types.GenericAliasDuring type conversion, msgspec caches certain information on the type objects themselves, if the types are complex (i.e.
Structs ordataclass-like).When decoding into a
Foo[int], msgspec will set an__msgspec_cache__attribute on theFoo[int]alias type.For
typing._GenericAlias, this work, since it has a__dict__, so you can just assign attributes to it. However,types.GenericAliasdoes not allow assigning arbitrary attributes to it.I fix this by downtyping
types.GenericAliasinto atyping._GenericAlias, when encountering a genericStructordataclasstype. This allows to keep the existing caching mechanism in place.This seemed like the most reasonable fix to me, as the other alternatives would like incur some sort of performance penalty; By storing the typing info directly on the alias, msgspec can forego maintaining a dedicated cache, making lookups very fast. It also allows to not care about invalidating a cache, since it will just be gce'd when the alias isn't referenced anymore.
One thing to not here though is that in the future,
typing._GenericAliasmight just go away (at least from the stdlib), in which case we'll have to find another way to deal with this.