Skip to content
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

feat: templatize api, endpoint init files #403

Conversation

p1-ra
Copy link
Contributor

@p1-ra p1-ra commented Apr 30, 2021

This PR add the api and endpoint init.py file as template. I had specifics needs for it, may be useful for others.

BR.

@p1-ra p1-ra force-pushed the feat/templatize-api-endpoint-init-files branch from 4093e72 to e0e8302 Compare April 30, 2021 14:33
@codecov
Copy link

codecov bot commented Apr 30, 2021

Codecov Report

Merging #403 (ae18d84) into main (f1caadc) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #403   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           47        47           
  Lines         1558      1563    +5     
=========================================
+ Hits          1558      1563    +5     
Impacted Files Coverage Δ
openapi_python_client/__init__.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f1caadc...ae18d84. Read the comment docs.

Comment on lines 249 to 244
package_name=self.package_name,
endpoint_collections_by_tag=endpoint_collections_by_tag,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you're passing these params because you need them, but for a developer working on just openapi-python-client it looks like these are not needed and might get removed at some point. I suggest either adding a note here or, better yet, a custom template in the end to end tests which uses them so we can see why they're there.

Copy link
Contributor Author

@p1-ra p1-ra May 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I followed your recommendation:

  • eda38ed Add new custom template tests, I had to change a little bit how the expected diff was handled:

    • Instead of a dict of {filename: content} it now use a dict of {file path: content}, to be able to handle files that have the same name but are defined at different paths
    • Since I've added a custom template sample, directly hardcoding the expected content seems to become a bad idea. That's why I propose to introduce the custom-templates-golden-record which contains all expected diff when using custom templates

    96fcdd6 add the custom-templates-golden-record generation to the regen task

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We used to generate a complete golden-record for custom to compare as well but code reviews got really burdensome since the same content would effectively change twice and it didn't add much value. At a glance, it looks like you've set it up to only generate the specific files we're interested in so that should be a good middleground between the two approaches (generate everything vs generate nothing). I'll take a deeper look later on, thanks!

@p1-ra p1-ra force-pushed the feat/templatize-api-endpoint-init-files branch 2 times, most recently from b7de1ed to 96fcdd6 Compare May 3, 2021 14:36
{%- for part in name -%}
{{ '_' if not loop.first and part in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' and (loop.index - last_snakize.at) > 1 and not last_snakize.update({'at': loop.index}) }}{{ part | lower }}
{%- endfor -%}
{% endmacro %}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this macro will render wrong names module__enpoint_func with extra underscore.
@dbanty whouldn't it be nice to expose utils methods to jinja templates?

by just adding to Project class

        self.env.globals.update(snake_case=snake_case, pascal_case=pascal_case)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably? I don't use custom templates at all and they aren't considered stable, I just mostly approve other folks' contributions for now so they can do what they need. If having those available in custom templates would be useful to you then we can totally pass them through. I think in the primary templates though we don't do any string transformations, it's all done in the Python parsing code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it will be nice to have, best I thinks will be to make https://github.com/triaxtec/openapi-python-client/blob/main/openapi_python_client/utils.py accessible to jinja.

Copy link
Contributor Author

@p1-ra p1-ra May 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've introduce the change in 95df40f and updated the custom template sample in b9a67e1

@p1-ra p1-ra force-pushed the feat/templatize-api-endpoint-init-files branch 3 times, most recently from 9a5cf23 to 2715dbf Compare May 6, 2021 07:38
Copy link
Contributor

@tsotnikov tsotnikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@p1-ra very good job!

Please take a look at #431, (my bad 😅, I did not notice this PR and tried to implement same thing) maybe some test ideas could be useful, like this one:

dircmp already does cmpfiles internally and stores the same result in diff_files and funny_files. Reference: https://github.com/python/cpython/blob/main/Lib/filecmp.py#L186
So it just need some parsing to retrieve the result recursively from the subdirectories.

endpoint_init_path = tag_dir / "__init__.py"
endpoint_init_template = self.env.get_template("endpoint_init.py.jinja")
endpoint_init_path.write_text(
endpoint_init_template.render(package_name=self.package_name, tag=tag, endpoints=collection.endpoints),
Copy link
Contributor

@tsotnikov tsotnikov May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EndpointCollection does already have a tag attribute so it would be cleaner to pass the object:

Suggested change
endpoint_init_template.render(package_name=self.package_name, tag=tag, endpoints=collection.endpoints),
endpoint_init_template.render(package_name=self.package_name, endpoint_collection=collection),

And about the package_name, probably not really needed as a relative import always can be done. If we do pass it, maybe we would also need to pass it also to endpoint_module.py.jinja template also for consistency (Note that I am not against passing it, just a thought) (Edit: nevermind, I see in the examples that you use it for other purposes in addition to imports, like for generating a class name)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed resolved in cdd304c

Regarding the package_name I do have specific needs for it, so definitly prefer to keep it indeed 😁
I've made a change, package metadata are now wildly available in all templates 77acd25

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review other template rendering in this file where package_name is passed.
Also I see some renders with description and version instead of package_description and package_version so that could be unified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, normalized on d1120f2

I've also wildly spread the project metadata vars to all template

Copy link
Contributor Author

@p1-ra p1-ra May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbanty what do you thinks about it? We are including a breaking change here by renaming {version, description} to {package_version, package_description}.

Imo, package_X kind of make more sense if we spread them accross all templates

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template API is not stable, so I don't care too much about breaking changes to it 😅. So I'm good with adding some clarity / consistency.

api_init_path.write_text(
api_init_template.render(
package_name=self.package_name,
endpoint_collections_by_tag=endpoint_collections_by_tag,
Copy link
Contributor

@tsotnikov tsotnikov May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest passing endpoint_collections_by_tag in the dictionary form instead of a list (after doing .items()) for two reasons:

  1. Naming may be confusing as self.openapi.endpoint_collections_by_tag is dictionary but in the template endpoint_collections_by_tag is a list.
  2. It is more flexible and allows easily looping on unique tags

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, resolved in cdd304c

@@ -12,7 +12,10 @@
def _compare_directories(
record: Path,
test_subject: Path,
expected_differences: Optional[Dict[str, str]] = None,
expected_differences: Optional[
Dict[str, str]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be Optional[Dict[Path,str]]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, resolved in b541e01

@p1-ra p1-ra force-pushed the feat/templatize-api-endpoint-init-files branch 2 times, most recently from 77acd25 to d1120f2 Compare May 20, 2021 12:15
tsotnikov
tsotnikov previously approved these changes May 20, 2021
Copy link
Collaborator

@dbanty dbanty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, great work! Glad to see so much thought being put into the templates by the community 💜. I have a couple suggestions, mostly around making the e2e tests a bit cleaner (IMO). I tested locally and my changes all passed, but I could have messed something up pasting into GitHub so let me know if you have any issues (or fundamentally disagree with the changes). Thank you!!

end_to_end_tests/test_end_to_end.py Outdated Show resolved Hide resolved
end_to_end_tests/test_end_to_end.py Show resolved Hide resolved
end_to_end_tests/test_end_to_end.py Outdated Show resolved Hide resolved
end_to_end_tests/test_end_to_end.py Outdated Show resolved Hide resolved
end_to_end_tests/test_end_to_end.py Show resolved Hide resolved
end_to_end_tests/test_end_to_end.py Show resolved Hide resolved
end_to_end_tests/test_end_to_end.py Outdated Show resolved Hide resolved
openapi_python_client/__init__.py Outdated Show resolved Hide resolved
@dbanty dbanty added this to the 0.10.0 milestone May 24, 2021
ramnes and others added 2 commits June 2, 2021 08:17
…r complex types (openapi-generators#372). Thanks @csymeonides-mf!

* fix: Detect File fields correctly

* fix: Optional File field caused missing import error

* fix: Non-string multipart fields must be stringified

* chore: Reformat

* fix: Put non-file fields as tuples in the files dict

* refactor: Avoid runtime type checks

* fix: Declaring types is necessary

* fix: Remove dead code

* fix: Non-JSON non-file multipart props need to be text/plain

* refactor: Avoid breaking change

Co-authored-by: Constantinos Symeonides <constantinos.symeonides@mindfoundry.ai>
@p1-ra p1-ra dismissed stale reviews from tsotnikov via b2f3891 June 9, 2021 13:58
@p1-ra p1-ra force-pushed the feat/templatize-api-endpoint-init-files branch from d3ee968 to ae18d84 Compare June 9, 2021 14:14
@p1-ra
Copy link
Contributor Author

p1-ra commented Jun 9, 2021

I've merged your suggestions and rebased on top of current main branch @dbanty

@dbanty
Copy link
Collaborator

dbanty commented Jun 28, 2021

@p1-ra I had to rebase on main again because of some history changes with the 0.9.2 release. So I copied this to #442 and merged, thanks!

@dbanty dbanty closed this Jun 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants