-
-
Notifications
You must be signed in to change notification settings - Fork 16
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
Refactor/reduce code duplication in plugins #31
base: refactored
Are you sure you want to change the base?
Refactor/reduce code duplication in plugins #31
Conversation
The duplicated methods per type `style style_XXX_class`, `generate_XXX` and `reference_XXX` were abstracted into a BaseTypeRegistry class. Provided a specific XXXTypeRegistry for every required type and added it as an attribute to the ClassRegistry.
Made generate_enums a "private" method of EnumsPlugin. Decoupled value parsing and code generation, by moving the generation of Ast-Elements into a separate class.
Changed the generation of deprecation-reasons to print the deprecation reason after `DEPRECATED` instead of the field description.
Separated ast-generation to static class. Streamlined control flow inside generate_input_annotation.
A centralized ast-generator module should make the reuse of repeating structures easier and hide the actual code-generation from plugin-developers. Optimized imports
Added tests for ObjectsPlugin that include primitive types and nested object types
The issue is described in the doctstring to ObjectTypeTestCaseGenerator.make_test_cases_union_field_value()
This partially duplicated old tests in test_mro/test_multiple_inheritance
Fixed bug in ObjectsPlugin._generate_type_body (introduced in last commit) that broke forward references by referencing the wrong "parent" in the subsequent call to generate_object_field_annotation. Added union method to the AnnotationAstGenerator. Refactored last method calls in ClassRegistry that slipped through during the first refactoring.
Great work! I especially appreciate the "TypeAstGenerator" efforts. That should easily translate to the other plugins as well, and I could see this potentially extend to having a "pure dataclass" or "attrs" version to allow support for generation other than pydantic. Great stuff! I see we are also becoming fully object-oriented ;) Personally I am not sure if that is really increasing readability (e.g one-line functions like "_type_has_description"). But I am not too hard set on this. I am just wondering how well it will translate to more recursive plugins like fragments or operations (in terms of readability)? Registration would be something that i would feel like should be handled by the plugin itself, but yes, maybe through composition of a 'Filter mixin' implementing "skip_type", according to some config parameters like - type: enums.Enums.Plugin
filter:
whitelist: 'regex' That would maybe also justify defining config values directly in the plugin instead of a dedicated configclass. Again great work! Thanks a lot for putting so much work in it! |
Whats your idea where styling should be placed? Closer to the ast generation itself? |
I personally really like the idea, of directly passing the GraphQL-Core-Types to the Ast-Generator and make it an implementation detail of the generator what comes out. Therefore, the stylers could / should be given to the ast-generator as a dependency. But I'm not sure if that leads to difficulties when the styled-names are referenced ... |
Well, I really think separating meaning and implementation improves the "thinkability" a lot. Even if it leads to more LoC. The difference between:
Compared to a simple Does it have a description? Anyways, the main point was to put this method into a shared base class. BTW, I'm not sure anymore if the base- |
What is the purpose of If we take away styling - as this is a separate concern and should be a separate class then - there is not much left. I can figure out:
Did I miss something? And one thought to the forward references: |
No thats about it for ClassRegistry ;)
This I think would be interesting, even going so far as to say that maybe it should be
And then according to the AstFactory an element like this.
And these would then be registered in the Registy? |
I agree, there are definitely some benefits! And with a composition to TypePluginMixin I am now completely on board 😝 |
Would you be willing to continue on this PR until we have the transition of all plugins to be merged? Or do you feel it would be good to already preliminary merge? |
I could imagine that, but I can't promise that I will get to it (focusing on the ariadne-plugin until now). Keep in mind, that you are also able to push to this branch (in my fork), as it is a fork of your project. As an alternative, we could merge this PR into a feature-branch in the main repo - to ease collaboration. |
Hi @j-riebe , sorry for the late reply, i was knocked out cold by covid and the brain fog is just lifting :D There is some mature deadlines heading my way so I will probably not be able to work on migrating the other plugins for now, but I agree that a feature branch would be a good idea. |
And TemplateNode is back... |
@jhnnsrs I think its time, that you take a look at this.
The PR contains the refactoring of EnumsPlugin, InputsPlugin and ObjectsPlugin.
I mainly focused on breaking down the large functions into smaller methods of each Plugin.
Some code duplication is eliminated, the remaining similarities should be pretty obvious by now (as a preparation for the next refactoring iteration).
There is a new module
ast_generators
that contains all concrete AST-Generation logic that was (duplicated a lot) in every plugin before.I have the feeling, that there also should be a stricter separation between the concerns:
Currently, each plugin does almost everything.
Only the styling is somehow part of the ClassRegistry, were it shouldn't belong IMHO.
Also, have a look at this test
tests/plugins/test_objects.py::make_test_cases_union_field_value