-
-
Notifications
You must be signed in to change notification settings - Fork 118
Implementing Generic Structuring Support #51
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
Conversation
I reworked a few things as I continued testing. My changes broke unstructuring since it used the same multi function dispatching strategy. The changes limit the impact to only structuring now and pretty much limited only to the converters in terms of changes. I think I need to fix converting from tuples still but this is more what I envision would be required long run to implement this feature. We could in theory not make this a breaking change by inspecting how many arguments the function takes. Because the converters object is global I don't like the idea of making |
I'd be interested in seeing this make it in, though clearly the tests need to be fixed and the use of static typing needs to be changed to be backwards-compatible with old versions of Python. Is |
There is an issue where when you have nested generics mappings were being generated when they really needed the upper level mapping. @attrs(auto_attribs=True) class M(Generic[Q]): m: Q @attrs(auto_attribs=True) class N(Generic[P]): n: P data2 = { "n": { "m": "test" } } this provides a good example where the issue can occur
Moved away from using dunders where possible and use typing methods
When working with thousands of files, attrs does some stuff in the background that causes massive iteration looking for a unique file name. This way we can just cache our results bypassing this uniqueness
This is extremely rough and a first pass, it is a proof of concept to see if this is a direction that cattrs is willing to take or not. A working concept with this code can be found below.
Right now when when you want to structure a generic it informs you to register a hook. From what I have found, to do this you have to register a call for every instance of your generic and you have to manually define how to build the object.
when you are talking multiple layers down, numerous different instances of the objects, this can become a tedious thing to maintain, especially when you are dealing with "simple" objects in terms of their structuring and destructuring are all ready supported if they were concrete types from the beginning.
To handle generics I tried a couple different ways to implement this as purely an external addon, but I found it was impossible to get it right without injecting code into
MultiStrategyDispatch
to handle TypeVars.I also tried to not use lambdas but I found in every function block for the mutlifunction dispatcher I had to insert the:
This is why I added the lambdas. Mappings was needed in a few handlers list
_structure_list
which means I had to pass it around to all the different functions so all methods signatures needed to be modified.make_class
was needed because of thelru_cache
as all parameters needed to be hashable and this was the best way I could come up with doing it.This is my attempt to address the problem. This is a breaking change, and I know 1.0.0 is on the horizon, but I personally think this is a worth while change to make. There are a few cleanup tasks that need to be done, documentation would need updating and I have not even looked at the unit tests yet. But I wanted to get some direction on if this is something worth pursuing and could be merged in.
I have only tested on python 3.7 so there is likely some other things that need fixing to support other versions.