Skip to content

"openapi.models" and "openapi.enums" aren't usable in custom templates #1188

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

Closed
eli-bl opened this issue Jan 7, 2025 · 1 comment · Fixed by #1189 or #1232
Closed

"openapi.models" and "openapi.enums" aren't usable in custom templates #1188

eli-bl opened this issue Jan 7, 2025 · 1 comment · Fixed by #1189 or #1232

Comments

@eli-bl
Copy link
Collaborator

eli-bl commented Jan 7, 2025

Describe the bug
Among the global Jinja variables set by openapi-python-client is openapi, which is an instance of GeneratorData. That class's attributes include models: Iterator[ModelProperty] and enums: Iterator[Union[EnumProperty, LiteralEnumProperty]].

One might expect that a custom template, for instance models_init.py.jinja, could iterate over those. As far as I can tell, there is no other way for a custom template to find out what all the models and enums are. However, trying to do this never works; the template receives what looks like an empty iterator for both openapi.models and openapi.enums.

I believe the problem is that these iterators have already been iterated, by Project._build_models(), before any custom templates are rendered. They are being set to generator expressions, e.g. models = (prop for prop in schemas.classes_by_name.values() if isinstance(prop, ModelProperty)), rather than list-comprehensions, so once the values have all been run through they can't be restarted.

OpenAPI Spec File
This isn't dependent on the contents of the API spec, but you can reproduce it by adding the following models_init.py.jinja file in end_to_end_tests/test_custom_templates and running pdm regen:

# Should see a list of model class names here
{% for model in openapi.models %}
# {{ model.class_info.name }}
{% endfor %}
# Should see a list of enum class names here
{% for enum in openapi.enums %}
# {{ enum.class_info.name }}
{% endfor %}

The output in models/__init__.py will not show any class names.

Desktop (please complete the following information):

  • OS: macOS 14.7.1
  • Python Version: 3.9.20
  • openapi-python-client version: 0.23.0
@chassing
Copy link

I also want to use openapi.models in a custom template and discovered this bug.

github-merge-queue bot pushed a commit that referenced this issue Mar 22, 2025
Resolves #1188.

The change is simply to store a list, rather than a generator
expression.

The new `models_init.py.jinja` template in the end-to-end tests shows
that this now works. Without the fix in `openapi.py`, this template is
rendered with nothing under the `Using "openapi.models"` and `Using
"openapi.enums"` headings.

This fix is somewhat important for our use case, because we need to put
some code in `models/__init__.py` that is aware of what the model class
names and modules are. Without the fix, the only way to get this would
be to iterate over `imports`, which gives you strings like `from
.module_name import ClassName`, and then parse those strings, which is
workable but pretty clunky.
@knope-bot knope-bot bot mentioned this issue Mar 22, 2025
github-merge-queue bot pushed a commit that referenced this issue Mar 22, 2025
> [!IMPORTANT]
> Merging this pull request will create this release

## Fixes

### Make lists of models and enums work correctly in custom templates

Lists of model and enum classes should be available to custom templates
via the Jinja
variables `openapi.models` and `openapi.enums`, but these were being
passed in a way that made
them always appear empty. This has been fixed so a custom template can
now iterate over them.

Closes #1188.

Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com.>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants