Skip to content

Conversation

@padznich
Copy link

@padznich padznich commented Dec 30, 2025

for Python 3.11+
anyOf / allOf Root model based
StrEnum, IntEnum

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • File the PR against the correct branch: master (upcoming 7.x.0 minor release - breaking changes with fallbacks), 8.0.x (breaking changes without fallbacks)
  • If your PR solves a reported issue, reference it using GitHub's linking syntax (e.g., having "fixes #123" present in the PR description)
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

@cbornet
@tomplus
@krjakbrjak
@fa0311
@multani


Summary by cubic

Modernizes the Python generator for 3.11+ by adopting Pydantic v2 APIs and RootModel-based unions for anyOf/oneOf. Adds StrEnum/IntEnum, simplifies serialization, and updates client/header handling for urllib3 v2.

  • New Features

    • anyOf/oneOf now use RootModel[Union[...]] with optional discriminator.
    • String and integer enums generate StrEnum/IntEnum.
    • Switch to Pydantic v2 methods (model_validate, model_dump, model_validate_json, model_dump_json).
    • Cleaner exceptions with unified body/data output.
    • ApiClient uses getheader/getheaders and model_validate for deserialization.
  • Migration

    • Requires Python 3.11+; urllib3 >= 2.1.0.
    • Replace:
      • from_json → model_validate_json
      • to_json → model_dump_json(by_alias=True, exclude_unset=True)
      • from_dict → model_validate
      • to_dict → model_dump(by_alias=True)
    • anyOf/oneOf values are on .root.
    • ApiClient now calls klass.model_validate(data); response headers use getheaders() (list of pairs) instead of a mapping. Adjust code that reads headers accordingly.

Written for commit cbb6665. Summary will update on new commits.

for Python 3.11+
anyOf / allOf Root model based
StrEnum, IntEnum
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

6 issues found across 9 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="modules/openapi-generator/src/main/resources/python/pyproject.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/python/pyproject.mustache:64">
P2: Inconsistent template variable: poetry1 section uses `{{#asyncio}}` for aiohttp dependencies (line 38), but the non-poetry section uses `{{#async}}` (line 64). These should use the same template variable for consistent behavior across both output formats.</violation>

<violation number="2" location="modules/openapi-generator/src/main/resources/python/pyproject.mustache:64">
P1: Missing httpx dependency in non-poetry section. The `{{#httpx}}` block was removed from the `{{^poetry1}}` dependencies array, but it still exists in the `{{#poetry1}}` section. Projects using httpx with the modern pyproject.toml format will fail at runtime due to missing dependency.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/python/model_generic.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/python/model_generic.mustache:34">
P1: Missing field definition for array enum types. When `isEnum=true` AND `isArray=true`, no field is rendered because the `{{^isArray}}` block is skipped but there&#39;s no `{{#isArray}}` handler. Consider adding a fallback or explicit array enum handling.</violation>

<violation number="2" location="modules/openapi-generator/src/main/resources/python/model_generic.mustache:39">
P2: Single-value enum Literal always uses string quoting. For integer enums (IntEnum mentioned in PR), `Literal[&#39;{{{.}}}&#39;]` will produce `Literal[&#39;1&#39;]` instead of `Literal[1]`. Consider using conditional quoting based on the enum type or using `{{{.}}}` without quotes.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/python/model_doc.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/python/model_doc.mustache:24">
P1: `model_dump_json()` is an instance method in Pydantic v2 and must be called on the instance variable, not the class. This code will fail at runtime with a `TypeError`.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/python/model_anyof.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/python/model_anyof.mustache:13">
P2: Redundant imports: `Literal` and `Union` are imported from both `typing` and `typing_extensions`. Since this is for Python 3.11+, these are already available in `typing`. The `typing_extensions` import should only include `Self` (or be removed entirely since `Self` is also in `typing` for 3.11+).</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

"httpx (>=0.28.1)",
{{/httpx}}
{{#asyncio}}
{{#async}}
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P2: Inconsistent template variable: poetry1 section uses {{#asyncio}} for aiohttp dependencies (line 38), but the non-poetry section uses {{#async}} (line 64). These should use the same template variable for consistent behavior across both output formats.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/python/pyproject.mustache, line 64:

<comment>Inconsistent template variable: poetry1 section uses `{{#asyncio}}` for aiohttp dependencies (line 38), but the non-poetry section uses `{{#async}}` (line 64). These should use the same template variable for consistent behavior across both output formats.</comment>

<file context>
@@ -58,20 +56,15 @@ lazy-imports = &quot;&gt;= 1, &lt; 2&quot;
-  &quot;httpx (&gt;=0.28.1)&quot;,
-{{/httpx}}
-{{#asyncio}}
+{{#async}}
   &quot;aiohttp (&gt;=3.8.4)&quot;,
   &quot;aiohttp-retry (&gt;=2.8.3)&quot;,
</file context>
Suggested change
{{#async}}
{{#asyncio}}
Fix with Cubic

{{/poetry1}}
keywords = ["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"]
{{#poetry1}}
include = ["{{packageName}}/py.typed"]
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P1: Missing httpx dependency in non-poetry section. The {{#httpx}} block was removed from the {{^poetry1}} dependencies array, but it still exists in the {{#poetry1}} section. Projects using httpx with the modern pyproject.toml format will fail at runtime due to missing dependency.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/python/pyproject.mustache, line 64:

<comment>Missing httpx dependency in non-poetry section. The `{{#httpx}}` block was removed from the `{{^poetry1}}` dependencies array, but it still exists in the `{{#poetry1}}` section. Projects using httpx with the modern pyproject.toml format will fail at runtime due to missing dependency.</comment>

<file context>
@@ -58,20 +56,15 @@ lazy-imports = &quot;&gt;= 1, &lt; 2&quot;
-  &quot;httpx (&gt;=0.28.1)&quot;,
-{{/httpx}}
-{{#asyncio}}
+{{#async}}
   &quot;aiohttp (&gt;=3.8.4)&quot;,
   &quot;aiohttp-retry (&gt;=2.8.3)&quot;,
</file context>
Suggested change
include = ["{{packageName}}/py.typed"]
{{#httpx}}
"httpx (>=0.28.1)",
{{/httpx}}
{{#async}}
Fix with Cubic

{{#-first}}
{{#-last}}
{{! Single value enum - use Literal }}
{{name}}: Literal['{{{.}}}'] = Field(
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P2: Single-value enum Literal always uses string quoting. For integer enums (IntEnum mentioned in PR), Literal['{{{.}}}'] will produce Literal['1'] instead of Literal[1]. Consider using conditional quoting based on the enum type or using {{{.}}} without quotes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/python/model_generic.mustache, line 39:

<comment>Single-value enum Literal always uses string quoting. For integer enums (IntEnum mentioned in PR), `Literal[&#39;{{{.}}}&#39;]` will produce `Literal[&#39;1&#39;]` instead of `Literal[1]`. Consider using conditional quoting based on the enum type or using `{{{.}}}` without quotes.</comment>

<file context>
@@ -28,7 +29,33 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
+          {{#-first}}
+            {{#-last}}
+              {{! Single value enum - use Literal }}
+    {{name}}: Literal[&#39;{{{.}}}&#39;] = Field(
+        {{#required}}...{{/required}}{{^required}}None{{/required}},
+        description=&quot;{{description}}{{^description}}{{{name}}} of the {{classname}}{{/description}}&quot;
</file context>
Fix with Cubic

{{#vars}}
{{#isEnum}}
{{#allowableValues}}
{{^isArray}}
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P1: Missing field definition for array enum types. When isEnum=true AND isArray=true, no field is rendered because the {{^isArray}} block is skipped but there's no {{#isArray}} handler. Consider adding a fallback or explicit array enum handling.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/python/model_generic.mustache, line 34:

<comment>Missing field definition for array enum types. When `isEnum=true` AND `isArray=true`, no field is rendered because the `{{^isArray}}` block is skipped but there&#39;s no `{{#isArray}}` handler. Consider adding a fallback or explicit array enum handling.</comment>

<file context>
@@ -28,7 +29,33 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
 {{#vars}}
+  {{#isEnum}}
+    {{#allowableValues}}
+      {{^isArray}}
+        {{#values}}
+          {{#-first}}
</file context>
Fix with Cubic

{{#lambda.snakecase}}{{classname}}{{/lambda.snakecase}}_instance = {{classname}}.model_validate_json(json)
# print the JSON string representation of the object
print({{classname}}.to_json())
print({{classname}}.model_dump_json(by_alias=True, exclude_unset=True))
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P1: model_dump_json() is an instance method in Pydantic v2 and must be called on the instance variable, not the class. This code will fail at runtime with a TypeError.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/python/model_doc.mustache, line 24:

<comment>`model_dump_json()` is an instance method in Pydantic v2 and must be called on the instance variable, not the class. This code will fail at runtime with a `TypeError`.</comment>

<file context>
@@ -19,14 +19,14 @@ from {{modelPackage}}.{{#lambda.snakecase}}{{classname}}{{/lambda.snakecase}} im
+{{#lambda.snakecase}}{{classname}}{{/lambda.snakecase}}_instance = {{classname}}.model_validate_json(json)
 # print the JSON string representation of the object
-print({{classname}}.to_json())
+print({{classname}}.model_dump_json(by_alias=True, exclude_unset=True))
 
 # convert the object into a dict
</file context>
Suggested change
print({{classname}}.model_dump_json(by_alias=True, exclude_unset=True))
print({{#lambda.snakecase}}{{classname}}{{/lambda.snakecase}}_instance.model_dump_json(by_alias=True, exclude_unset=True))
Fix with Cubic

from typing_extensions import Literal, Self
from pydantic import Field
from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict, Literal
from typing_extensions import Literal, Self, Union
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P2: Redundant imports: Literal and Union are imported from both typing and typing_extensions. Since this is for Python 3.11+, these are already available in typing. The typing_extensions import should only include Self (or be removed entirely since Self is also in typing for 3.11+).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/python/model_anyof.mustache, line 13:

<comment>Redundant imports: `Literal` and `Union` are imported from both `typing` and `typing_extensions`. Since this is for Python 3.11+, these are already available in `typing`. The `typing_extensions` import should only include `Self` (or be removed entirely since `Self` is also in `typing` for 3.11+).</comment>

<file context>
@@ -9,169 +9,32 @@ import re  # noqa: F401
-from typing_extensions import Literal, Self
-from pydantic import Field
+from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict, Literal
+from typing_extensions import Literal, Self, Union
+from pydantic import Field, RootModel
 
</file context>
Suggested change
from typing_extensions import Literal, Self, Union
from typing_extensions import Self
Fix with Cubic

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.

1 participant