Skip to content

Python sdk anyof allof root model#22955

Open
padznich wants to merge 12 commits intoOpenAPITools:masterfrom
padznich:python-sdk-anyof-allof-root-model
Open

Python sdk anyof allof root model#22955
padznich wants to merge 12 commits intoOpenAPITools:masterfrom
padznich:python-sdk-anyof-allof-root-model

Conversation

@padznich
Copy link
Contributor

@padznich padznich commented Feb 12, 2026

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.

Summary by cubic

Moves Python anyOf/oneOf models to Pydantic v2 RootModel with Union typing for simpler validation/serialization and secures file downloads by stripping paths from Content-Disposition. Also adds integer enum support to rust-server via serde_repr and updates sample dependencies (qs/body-parser/express/axios).

  • New Features

    • Python: anyOf/oneOf models now generate as RootModel[Union[...]] using Pydantic v2 APIs.
    • Python: Enum typing improved (single-value enums use Literal); examples/docs use model_validate_json/model_dump_json.
    • Security: Content-Disposition filenames are sanitized with os.path.basename.
    • Rust (server): Integer enums serialize with serde_repr; Cargo adds serde_repr only when needed.
  • Migration

    • Replace from_json → model_validate_json, to_json → model_dump_json, to_dict → model_dump.
    • Composed models no longer expose actual_instance or schema helper sets; access the inner value via .root.
    • Regenerate docs/samples and update any pinned references if you’ve vendored generated code.

Written for commit 45f1a7f. Summary will update on new commits.

Copy link
Contributor

@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.

10 issues found across 103 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

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/model_anyof.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/python/model_anyof.mustache:55">
P3: `to_dict` is annotated to return `Dict[str, Any]` but `RootModel.model_dump` returns the root value directly (which may be a primitive or list). This type hint is incorrect for AnyOf root models.</violation>
</file>

<file name="docs/generators/typescript-axios.md">

<violation number="1" location="docs/generators/typescript-axios.md:23">
P2: Documentation now lists axiosVersion default as ^1.6.1, but the generator still defaults to ^1.13.5, so the docs are inconsistent with actual behavior.</violation>
</file>

<file name="docs/generators/typescript-angular.md">

<violation number="1" location="docs/generators/typescript-angular.md:14">
P2: Documentation now claims Angular 9.x–20.x and default ngVersion 20.0.0, but the generator still defaults to 21.0.0 and advertises 9.x–21.x. This is a regression that misdocuments supported versions.</violation>
</file>

<file name="docs/generators/jaxrs-cxf-client.md">

<violation number="1" location="docs/generators/jaxrs-cxf-client.md:36">
P2: Documentation for jaxrs-cxf-client drops configuration options that are still supported by the Java codegen, making the docs inaccurate for users.</violation>
</file>

<file name="docs/generators/kotlin-server.md">

<violation number="1" location="docs/generators/kotlin-server.md:265">
P2: Kotlin server generator supports Polymorphism/allOf/oneOf, but the updated docs now mark these as unsupported, which is inaccurate and a regression in the feature matrix.</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:162">
P2: from_dict no longer uses discriminator mappings, so polymorphic parent models won’t resolve to the correct child type during deserialization.</violation>

<violation number="2" location="modules/openapi-generator/src/main/resources/python/model_generic.mustache:175">
P2: readOnly fields are no longer excluded from to_dict output, causing a regression that can serialize server-managed fields into requests.</violation>

<violation number="3" location="modules/openapi-generator/src/main/resources/python/model_generic.mustache:175">
P2: `to_dict` no longer flattens `additional_properties` into the root dict; it now returns `model_dump` directly, which will serialize extra properties under an `additional_properties` key and break OpenAPI additionalProperties JSON shape.</violation>
</file>

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

<violation number="1" location="modules/openapi-generator/src/main/resources/python/model_oneof.mustache:20">
P2: Discriminator mappings are no longer supported; replacing `discriminator_value_class_map` with a string discriminator breaks OpenAPI `discriminator.mapping` cases where mapping values don’t match subtype Literal fields.</violation>

<violation number="2" location="modules/openapi-generator/src/main/resources/python/model_oneof.mustache:53">
P2: `to_dict` is annotated to return `Dict[str, Any]`, but for `RootModel` `model_dump()` returns the root value directly (which may be a primitive or list), so the type hint is incorrect for oneOf schemas allowing non-object types.</violation>
</file>

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

raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + _key)
def to_dict(self) -> Dict[str, Any]:
"""Returns the dict representation of the actual instance"""
return self.model_dump(by_alias=True)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 12, 2026

Choose a reason for hiding this comment

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

P2: readOnly fields are no longer excluded from to_dict output, causing a regression that can serialize server-managed fields into requests.

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 175:

<comment>readOnly fields are no longer excluded from to_dict output, causing a regression that can serialize server-managed fields into requests.</comment>

<file context>
@@ -121,278 +156,28 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
-                raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + _key)
+    def to_dict(self) -> Dict[str, Any]:
+        """Returns the dict representation of the actual instance"""
+        return self.model_dump(by_alias=True)
 
-        {{/isAdditionalPropertiesTrue}}
</file context>
Fix with Cubic

raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + _key)
def to_dict(self) -> Dict[str, Any]:
"""Returns the dict representation of the actual instance"""
return self.model_dump(by_alias=True)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 12, 2026

Choose a reason for hiding this comment

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

P2: to_dict no longer flattens additional_properties into the root dict; it now returns model_dump directly, which will serialize extra properties under an additional_properties key and break OpenAPI additionalProperties JSON shape.

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 175:

<comment>`to_dict` no longer flattens `additional_properties` into the root dict; it now returns `model_dump` directly, which will serialize extra properties under an `additional_properties` key and break OpenAPI additionalProperties JSON shape.</comment>

<file context>
@@ -121,278 +156,28 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
-                raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + _key)
+    def to_dict(self) -> Dict[str, Any]:
+        """Returns the dict representation of the actual instance"""
+        return self.model_dump(by_alias=True)
 
-        {{/isAdditionalPropertiesTrue}}
</file context>
Suggested change
return self.model_dump(by_alias=True)
_dict = self.model_dump(by_alias=True{{#isAdditionalPropertiesTrue}}, exclude={"additional_properties"}{{/isAdditionalPropertiesTrue}})
{{#isAdditionalPropertiesTrue}}
if self.additional_properties:
_dict.update(self.additional_properties)
{{/isAdditionalPropertiesTrue}}
return _dict
Fix with Cubic

return self.model_dump_json(by_alias=True, exclude_none=True)

def to_dict(self) -> Optional[Union[Dict[str, Any], {{#anyOf}}{{.}}{{^-last}}, {{/-last}}{{/anyOf}}]]:
def to_dict(self) -> Dict[str, Any]:
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 12, 2026

Choose a reason for hiding this comment

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

P3: to_dict is annotated to return Dict[str, Any] but RootModel.model_dump returns the root value directly (which may be a primitive or list). This type hint is incorrect for AnyOf root models.

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 55:

<comment>`to_dict` is annotated to return `Dict[str, Any]` but `RootModel.model_dump` returns the root value directly (which may be a primitive or list). This type hint is incorrect for AnyOf root models.</comment>

<file context>
@@ -11,167 +9,57 @@ import re  # noqa: F401
+        return self.model_dump_json(by_alias=True, exclude_none=True)
 
-    def to_dict(self) -> Optional[Union[Dict[str, Any], {{#anyOf}}{{.}}{{^-last}}, {{/-last}}{{/anyOf}}]]:
+    def to_dict(self) -> Dict[str, Any]:
         """Returns the dict representation of the actual instance"""
-        if self.actual_instance is None:
</file context>
Suggested change
def to_dict(self) -> Dict[str, Any]:
def to_dict(self) -> Any:
Fix with Cubic

@wing328
Copy link
Member

wing328 commented Feb 12, 2026

looks like your PR is not based on the latest master

can you please file a new one based on the latest master or merge the latest master into your branch (and update both samples and docs)?

@wing328
Copy link
Member

wing328 commented Feb 12, 2026

cc @cbornet (2017/09) @tomplus (2018/10) @krjakbrjak (2023/02) @fa0311 (2023/10) @multani (2023/10)

@padznich padznich force-pushed the python-sdk-anyof-allof-root-model branch from 8a5c698 to bdbe53c Compare February 12, 2026 14:09
@wing328
Copy link
Member

wing328 commented Feb 13, 2026

i've filed #22963 with updated samples but some tests failed.

can you please review those CI test failure?

dependabot bot and others added 8 commits February 13, 2026 14:04
Bumps [qs](https://github.com/ljharb/qs), [body-parser](https://github.com/expressjs/body-parser) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `qs` from 6.11.0 to 6.14.2
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](ljharb/qs@v6.11.0...v6.14.2)

Updates `body-parser` from 1.20.2 to 1.20.4
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](expressjs/body-parser@1.20.2...1.20.4)

Updates `express` from 4.18.2 to 4.22.1
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/v4.22.1/History.md)
- [Commits](expressjs/express@4.18.2...v4.22.1)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.2
  dependency-type: indirect
- dependency-name: body-parser
  dependency-version: 1.20.4
  dependency-type: indirect
- dependency-name: express
  dependency-version: 4.22.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ools#22915)

* Support for integer enums in rust-server

* Support integer enums in rust-server using serde-repr
Bumps [qs](https://github.com/ljharb/qs) from 6.14.1 to 6.14.2.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](ljharb/qs@v6.14.1...v6.14.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [qs](https://github.com/ljharb/qs) from 6.14.1 to 6.14.2.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](ljharb/qs@v6.14.1...v6.14.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…enAPITools#22966)

Bumps [qs](https://github.com/ljharb/qs) from 6.14.1 to 6.14.2.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](ljharb/qs@v6.14.1...v6.14.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [qs](https://github.com/ljharb/qs) from 6.14.0 to 6.14.2.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](ljharb/qs@v6.14.0...v6.14.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [axios](https://github.com/axios/axios) from 1.7.7 to 1.13.5.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.7.7...v1.13.5)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.13.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
to_json() formatting
Copy link
Contributor

@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.

9 issues found across 22 files (changes from recent commits).

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="samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs">

<violation number="1" location="samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs:134">
P2: Enabling Vec<Animal> header conversions for the client feature exposes a broken round‑trip: objects serialize as comma‑separated key/value pairs, Vec joins them with commas, and deserialization splits on commas and feeds fragments to `Animal::from_str`, which expects a full key/value sequence. This makes valid‑looking client headers fail to parse.</violation>
</file>

<file name="samples/server/petstore/rust-server-deprecated/output/rust-server-test/src/models.rs">

<violation number="1" location="samples/server/petstore/rust-server-deprecated/output/rust-server-test/src/models.rs:138">
P2: Enabling client-side Vec<ANullableContainer> header conversions exposes broken serialization: each element serializes to comma-separated key/value pairs, but deserialization splits the header on commas and tries to parse each fragment as a full object, so parsing fails for any nontrivial struct values.</violation>
</file>

<file name="samples/server/petstore/rust-server/output/multipart-v3/src/models.rs">

<violation number="1" location="samples/server/petstore/rust-server/output/multipart-v3/src/models.rs:145">
P2: Enabling client-side Vec<MultipartRequestObjectField> header parsing exposes a broken round‑trip: objects are comma-joined but the parser splits on every comma and then tries to parse each fragment as a full object, which fails for serialized key/value pairs.</violation>
</file>

<file name="samples/server/petstore/rust-server/output/no-example-v3/src/models.rs">

<violation number="1" location="samples/server/petstore/rust-server/output/no-example-v3/src/models.rs:125">
P2: Enabling client builds for Vec<OpGetRequest> header parsing exposes a broken comma-splitting deserializer: each OpGetRequest serializes with commas, so splitting the header by ',' fragments the object string and causes OpGetRequest::from_str to fail.</violation>
</file>

<file name="samples/server/petstore/rust-server-deprecated/output/multipart-v3/src/models.rs">

<violation number="1" location="samples/server/petstore/rust-server-deprecated/output/multipart-v3/src/models.rs:140">
P2: Enabling the Vec<MultipartRelatedRequest> header conversion for the client feature exposes a broken deserializer: it splits the header on every comma and feeds fragments into MultipartRelatedRequest::from_str, but that parser requires full key/value comma pairs. As a result, multi-item headers like "field_a,foo, field_a,bar" are split into tokens ("field_a", "foo", …) and parsing fails with "Missing value" errors, making array deserialization unusable.</violation>
</file>

<file name="samples/server/petstore/rust-server/output/openapi-v3/src/models.rs">

<violation number="1" location="samples/server/petstore/rust-server/output/openapi-v3/src/models.rs:97">
P2: Client-side Vec<AdditionalPropertiesWithNullable> header parsing uses comma-splitting even though each element’s serialization is itself comma-delimited, so list header values are ambiguous and will fail to parse correctly.</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:171">
P2: to_json now uses json.dumps on model_dump() output in python mode, which may include non-JSON-serializable types (datetime, UUID, Decimal), causing TypeError and breaking serialization for such models.</violation>
</file>

<file name="samples/server/petstore/rust-server-deprecated/output/no-example-v3/src/models.rs">

<violation number="1" location="samples/server/petstore/rust-server-deprecated/output/no-example-v3/src/models.rs:123">
P2: Enabling the client feature now exposes a Vec<OpGetRequest> header parser that splits on ',' even though OpGetRequest serialization itself uses commas. This causes deserialization to fail for any header (e.g., "property,value" is split into "property" and "value"), so client code will hit runtime errors when parsing headers.</violation>
</file>

<file name="samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs">

<violation number="1" location="samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs:131">
P2: Enabling client-side header serialization for Vec<Animal> exposes a broken encoding: Animal::to_string() already uses comma-separated key/value pairs, and Vec<Animal> joins items with commas then splits on commas when parsing. This makes array headers ambiguous/unparseable because item boundaries are indistinguishable from object fields.</violation>
</file>

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

}

#[cfg(feature = "server")]
#[cfg(any(feature = "client", feature = "server"))]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Enabling Vec header conversions for the client feature exposes a broken round‑trip: objects serialize as comma‑separated key/value pairs, Vec joins them with commas, and deserialization splits on commas and feeds fragments to Animal::from_str, which expects a full key/value sequence. This makes valid‑looking client headers fail to parse.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs, line 134:

<comment>Enabling Vec<Animal> header conversions for the client feature exposes a broken round‑trip: objects serialize as comma‑separated key/value pairs, Vec joins them with commas, and deserialization splits on commas and feeds fragments to `Animal::from_str`, which expects a full key/value sequence. This makes valid‑looking client headers fail to parse.</comment>

<file context>
@@ -131,7 +131,7 @@ impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderVal
 }
 
-#[cfg(feature = "server")]
+#[cfg(any(feature = "client", feature = "server"))]
 impl std::convert::TryFrom<header::IntoHeaderValue<Vec<AdditionalPropertiesClass>>> for hyper::header::HeaderValue {
     type Error = String;
</file context>
Fix with Cubic

}

#[cfg(feature = "server")]
#[cfg(any(feature = "client", feature = "server"))]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Enabling client-side Vec header conversions exposes broken serialization: each element serializes to comma-separated key/value pairs, but deserialization splits the header on commas and tries to parse each fragment as a full object, so parsing fails for any nontrivial struct values.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/rust-server-deprecated/output/rust-server-test/src/models.rs, line 138:

<comment>Enabling client-side Vec<ANullableContainer> header conversions exposes broken serialization: each element serializes to comma-separated key/value pairs, but deserialization splits the header on commas and tries to parse each fragment as a full object, so parsing fails for any nontrivial struct values.</comment>

<file context>
@@ -135,7 +135,7 @@ impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderVal
 }
 
-#[cfg(feature = "server")]
+#[cfg(any(feature = "client", feature = "server"))]
 impl std::convert::TryFrom<header::IntoHeaderValue<Vec<ANullableContainer>>> for hyper::header::HeaderValue {
     type Error = String;
</file context>
Fix with Cubic

}

#[cfg(feature = "server")]
#[cfg(any(feature = "client", feature = "server"))]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Enabling client-side Vec header parsing exposes a broken round‑trip: objects are comma-joined but the parser splits on every comma and then tries to parse each fragment as a full object, which fails for serialized key/value pairs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/rust-server/output/multipart-v3/src/models.rs, line 145:

<comment>Enabling client-side Vec<MultipartRequestObjectField> header parsing exposes a broken round‑trip: objects are comma-joined but the parser splits on every comma and then tries to parse each fragment as a full object, which fails for serialized key/value pairs.</comment>

<file context>
@@ -142,7 +142,7 @@ impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderVal
 }
 
-#[cfg(feature = "server")]
+#[cfg(any(feature = "client", feature = "server"))]
 impl std::convert::TryFrom<header::IntoHeaderValue<Vec<MultipartRelatedRequest>>> for hyper::header::HeaderValue {
     type Error = String;
</file context>
Fix with Cubic

}

#[cfg(feature = "server")]
#[cfg(any(feature = "client", feature = "server"))]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Enabling client builds for Vec header parsing exposes a broken comma-splitting deserializer: each OpGetRequest serializes with commas, so splitting the header by ',' fragments the object string and causes OpGetRequest::from_str to fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/rust-server/output/no-example-v3/src/models.rs, line 125:

<comment>Enabling client builds for Vec<OpGetRequest> header parsing exposes a broken comma-splitting deserializer: each OpGetRequest serializes with commas, so splitting the header by ',' fragments the object string and causes OpGetRequest::from_str to fail.</comment>

<file context>
@@ -122,7 +122,7 @@ impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderVal
 }
 
-#[cfg(feature = "server")]
+#[cfg(any(feature = "client", feature = "server"))]
 impl std::convert::TryFrom<header::IntoHeaderValue<Vec<OpGetRequest>>> for hyper::header::HeaderValue {
     type Error = String;
</file context>
Fix with Cubic

}

#[cfg(feature = "server")]
#[cfg(any(feature = "client", feature = "server"))]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Enabling the Vec header conversion for the client feature exposes a broken deserializer: it splits the header on every comma and feeds fragments into MultipartRelatedRequest::from_str, but that parser requires full key/value comma pairs. As a result, multi-item headers like "field_a,foo, field_a,bar" are split into tokens ("field_a", "foo", …) and parsing fails with "Missing value" errors, making array deserialization unusable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/rust-server-deprecated/output/multipart-v3/src/models.rs, line 140:

<comment>Enabling the Vec<MultipartRelatedRequest> header conversion for the client feature exposes a broken deserializer: it splits the header on every comma and feeds fragments into MultipartRelatedRequest::from_str, but that parser requires full key/value comma pairs. As a result, multi-item headers like "field_a,foo, field_a,bar" are split into tokens ("field_a", "foo", …) and parsing fails with "Missing value" errors, making array deserialization unusable.</comment>

<file context>
@@ -137,7 +137,7 @@ impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderVal
 }
 
-#[cfg(feature = "server")]
+#[cfg(any(feature = "client", feature = "server"))]
 impl std::convert::TryFrom<header::IntoHeaderValue<Vec<MultipartRelatedRequest>>> for hyper::header::HeaderValue {
     type Error = String;
</file context>
Fix with Cubic

}

#[cfg(feature = "server")]
#[cfg(any(feature = "client", feature = "server"))]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Client-side Vec header parsing uses comma-splitting even though each element’s serialization is itself comma-delimited, so list header values are ambiguous and will fail to parse correctly.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/rust-server/output/openapi-v3/src/models.rs, line 97:

<comment>Client-side Vec<AdditionalPropertiesWithNullable> header parsing uses comma-splitting even though each element’s serialization is itself comma-delimited, so list header values are ambiguous and will fail to parse correctly.</comment>

<file context>
@@ -94,7 +94,7 @@ impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderVal
 }
 
-#[cfg(feature = "server")]
+#[cfg(any(feature = "client", feature = "server"))]
 impl std::convert::TryFrom<header::IntoHeaderValue<Vec<AdditionalPropertiesReferencedAnyOfObject>>> for hyper::header::HeaderValue {
     type Error = String;
</file context>
Fix with Cubic

return cls.model_validate(obj)
def to_json(self) -> str:
"""Returns the JSON representation of the actual instance"""
return json.dumps(self.model_dump(by_alias=True, exclude_none=True))
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: to_json now uses json.dumps on model_dump() output in python mode, which may include non-JSON-serializable types (datetime, UUID, Decimal), causing TypeError and breaking serialization for such models.

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 171:

<comment>to_json now uses json.dumps on model_dump() output in python mode, which may include non-JSON-serializable types (datetime, UUID, Decimal), causing TypeError and breaking serialization for such models.</comment>

<file context>
@@ -168,7 +168,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
     def to_json(self) -> str:
         """Returns the JSON representation of the actual instance"""
-        return self.model_dump_json(by_alias=True, exclude_none=True)
+        return json.dumps(self.model_dump(by_alias=True, exclude_none=True))
 
     def to_dict(self) -> Dict[str, Any]:
</file context>
Suggested change
return json.dumps(self.model_dump(by_alias=True, exclude_none=True))
return self.model_dump_json(by_alias=True, exclude_none=True)
Fix with Cubic

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It changes the output
FROM:

{"id":1,"name":"test"}

TO:

{"id": 1, "name": "test"}

}

#[cfg(feature = "server")]
#[cfg(any(feature = "client", feature = "server"))]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Enabling the client feature now exposes a Vec header parser that splits on ',' even though OpGetRequest serialization itself uses commas. This causes deserialization to fail for any header (e.g., "property,value" is split into "property" and "value"), so client code will hit runtime errors when parsing headers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/rust-server-deprecated/output/no-example-v3/src/models.rs, line 123:

<comment>Enabling the client feature now exposes a Vec<OpGetRequest> header parser that splits on ',' even though OpGetRequest serialization itself uses commas. This causes deserialization to fail for any header (e.g., "property,value" is split into "property" and "value"), so client code will hit runtime errors when parsing headers.</comment>

<file context>
@@ -120,7 +120,7 @@ impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderVal
 }
 
-#[cfg(feature = "server")]
+#[cfg(any(feature = "client", feature = "server"))]
 impl std::convert::TryFrom<header::IntoHeaderValue<Vec<OpGetRequest>>> for hyper::header::HeaderValue {
     type Error = String;
</file context>
Fix with Cubic

}

#[cfg(feature = "server")]
#[cfg(any(feature = "client", feature = "server"))]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Enabling client-side header serialization for Vec exposes a broken encoding: Animal::to_string() already uses comma-separated key/value pairs, and Vec joins items with commas then splits on commas when parsing. This makes array headers ambiguous/unparseable because item boundaries are indistinguishable from object fields.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs, line 131:

<comment>Enabling client-side header serialization for Vec<Animal> exposes a broken encoding: Animal::to_string() already uses comma-separated key/value pairs, and Vec<Animal> joins items with commas then splits on commas when parsing. This makes array headers ambiguous/unparseable because item boundaries are indistinguishable from object fields.</comment>

<file context>
@@ -128,7 +128,7 @@ impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderVal
 }
 
-#[cfg(feature = "server")]
+#[cfg(any(feature = "client", feature = "server"))]
 impl std::convert::TryFrom<header::IntoHeaderValue<Vec<AdditionalPropertiesClass>>> for hyper::header::HeaderValue {
     type Error = String;
</file context>
Fix with Cubic

./mvnw clean package -DskipTests
./bin/generate-samples.sh ./bin/configs/*.yaml
./bin/utils/export_docs_generators.sh
Copy link
Contributor

@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.

20 issues found across 848 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

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="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/bird.py">

<violation number="1" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/bird.py:45">
P2: from_dict no longer rejects additional properties; model_config does not set extra='forbid', so extra fields are ignored and the disallowAdditionalPropertiesIfNotPresent sample no longer enforces the restriction.</violation>
</file>

<file name="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/default_value.py">

<violation number="1" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/default_value.py:66">
P2: Additional properties are no longer rejected because from_dict now only uses strict validation without configuring extra='forbid', removing the previous explicit check for unknown keys.</violation>

<violation number="2" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/default_value.py:75">
P2: Nullable vs optional serialization semantics regress: to_json now drops explicit None values for nullable fields, while to_dict emits null for all unset Optional fields, changing payloads from the prior OpenAPI-aware behavior.</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:39">
P2: Single-value enum uses raw enum value inside single quotes, which can generate invalid Python syntax when the enum value itself contains a single quote. Use the same enumVars/escaping logic as multi-value enums.</violation>

<violation number="2" location="modules/openapi-generator/src/main/resources/python/model_generic.mustache:162">
P2: `from_dict` now always instantiates the parent class via `model_validate` and no longer uses the discriminator mapping, so polymorphic deserialization will not return the correct subclass for `hasChildren` models.</violation>

<violation number="3" location="modules/openapi-generator/src/main/resources/python/model_generic.mustache:175">
P2: ReadOnly fields are no longer excluded from serialization in `to_dict`, so generated clients will emit read-only fields back to the server.</violation>

<violation number="4" location="modules/openapi-generator/src/main/resources/python/model_generic.mustache:175">
P2: additionalProperties handling regressed: extra JSON keys are now ignored on `model_validate` and `to_dict` no longer flattens `additional_properties`, breaking OpenAPI `additionalProperties: true` behavior.</violation>
</file>

<file name="samples/client/echo_api/python/openapi_client/models/data_query.py">

<violation number="1" location="samples/client/echo_api/python/openapi_client/models/data_query.py:48">
P2: `from_dict` now uses `strict=True`, which prevents coercion of JSON-derived date strings into `datetime` objects. Since `from_dict` is meant to validate Python dicts (often from `json.loads`) and the model has a `datetime` field (`var_date` alias `date`), strict mode will raise `ValidationError` for ISO 8601 strings. This breaks expected deserialization behavior.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/rust-server-deprecated/models.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/rust-server-deprecated/models.mustache:582">
P2: Header parsing for `Vec<{{{classname}}}>` splits on every comma before calling `FromStr`, which breaks struct parsing because struct `FromStr` expects comma-separated key/value pairs. Enabling this impl for the client feature exposes a broken header deserialization path for arrays of struct models.</violation>
</file>

<file name="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/pet.py">

<violation number="1" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/pet.py:64">
P2: `from_dict` no longer rejects additional properties because `model_validate(..., strict=True)` does not enforce `extra='forbid'`. Without `model_config` setting `extra='forbid'`, unknown fields are accepted, regressing the disallow-additional-properties behavior previously enforced.</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:55">
P2: to_dict is annotated as Dict[str, Any], but RootModel.model_dump returns the root value directly and can be a primitive or list for anyOf roots, so the annotation is incorrect for non-object schemas.</violation>
</file>

<file name="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/category.py">

<violation number="1" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/category.py:45">
P2: The updated from_dict no longer rejects unknown keys, and model_config does not set extra='forbid'. In Pydantic v2 extra fields are ignored by default, so this change disables the disallowAdditionalPropertiesIfNotPresent behavior and allows unexpected properties to pass validation.</violation>
</file>

<file name="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/tag.py">

<violation number="1" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/tag.py:45">
P2: `from_dict` now calls `model_validate(..., strict=True)` without forbidding extra fields, so additional properties are silently accepted. Pydantic’s default `extra='ignore'` allows unknown keys; `strict=True` only enforces types. This regresses the prior behavior that rejected extra fields. Restore the extra-field check or set `model_config = ConfigDict(..., extra='forbid')`.</violation>
</file>

<file name="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/number_properties_only.py">

<violation number="1" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/number_properties_only.py:47">
P2: Regression: additional properties are no longer rejected. The new from_dict only calls model_validate(strict=True) and model_config does not set extra='forbid', so extra fields are ignored by default in Pydantic v2, removing the previous explicit check for unknown keys.</violation>
</file>

<file name="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/data_query.py">

<violation number="1" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/data_query.py:48">
P2: Extra properties are no longer rejected after removing the manual additional-fields check, and model_config does not set extra='forbid'. This likely regresses the “disallow additional properties” behavior for this sample by silently accepting unexpected fields.</violation>
</file>

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

<violation number="1" location="modules/openapi-generator/src/main/resources/python/model_oneof.mustache:40">
P2: `from_dict` and `to_dict` are annotated as `Dict[str, Any]`, but RootModel oneOf roots can be primitives/lists; `model_dump()` returns the root type and `model_validate()` accepts non-dict roots. These annotations are too restrictive for non-object oneOf schemas.</violation>
</file>

<file name="samples/client/echo_api/python/openapi_client/models/default_value.py">

<violation number="1" location="samples/client/echo_api/python/openapi_client/models/default_value.py:75">
P2: to_json now always excludes None values, which drops explicitly set nullable fields from the JSON payload. This regresses the previous behavior that re-inserted nullable fields set to None via model_fields_set, so clients can no longer send null to clear values.</violation>

<violation number="2" location="samples/client/echo_api/python/openapi_client/models/default_value.py:79">
P2: to_dict now serializes all optional fields with None, which changes request payload semantics and can overwrite server-side values with nulls when used by ApiClient serialization.</violation>
</file>

<file name="samples/client/echo_api/python/openapi_client/api_client.py">

<violation number="1" location="samples/client/echo_api/python/openapi_client/api_client.py:711">
P2: The code deletes the secure mkstemp file and then uses the server-provided filename to build a predictable path in a shared temp directory. This leaves a TOCTOU/symlink race window before `open(path, "wb")`, allowing a local attacker to pre-create a symlink and force overwriting arbitrary files. Use a private temp directory (mkdtemp) or keep the secure fd rather than deleting it.</violation>
</file>

<file name="samples/client/echo_api/python/openapi_client/models/bird.py">

<violation number="1" location="samples/client/echo_api/python/openapi_client/models/bird.py:58">
P2: `to_dict` no longer excludes None values, making it inconsistent with `to_json` and potentially causing nulls to be sent in API payloads. This is a regression from the prior behavior and can change PATCH/optional field semantics.</violation>
</file>

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

return cls.from_dict(json.loads(json_str))
def from_dict(cls, obj: Dict[str, Any]) -> Self:
"""Returns the object represented by the Dict"""
return cls.model_validate(obj, strict=True)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: from_dict no longer rejects additional properties; model_config does not set extra='forbid', so extra fields are ignored and the disallowAdditionalPropertiesIfNotPresent sample no longer enforces the restriction.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/bird.py, line 45:

<comment>from_dict no longer rejects additional properties; model_config does not set extra='forbid', so extra fields are ignored and the disallowAdditionalPropertiesIfNotPresent sample no longer enforces the restriction.</comment>

<file context>
@@ -38,58 +39,27 @@ class Bird(BaseModel):
-        return cls.from_dict(json.loads(json_str))
+    def from_dict(cls, obj: Dict[str, Any]) -> Self:
+        """Returns the object represented by the Dict"""
+        return cls.model_validate(obj, strict=True)
 
-    def to_dict(self) -> Dict[str, Any]:
</file context>
Suggested change
return cls.model_validate(obj, strict=True)
if not isinstance(obj, dict):
return cls.model_validate(obj, strict=True)
for _key in obj.keys():
if _key not in cls.__properties:
raise ValueError("Error due to additional fields (not defined in Bird) in the input: " + _key)
return cls.model_validate(obj, strict=True)
Fix with Cubic

@@ -22,14 +22,18 @@
from typing import Any, ClassVar, Dict, List, Optional
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Nullable vs optional serialization semantics regress: to_json now drops explicit None values for nullable fields, while to_dict emits null for all unset Optional fields, changing payloads from the prior OpenAPI-aware behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/default_value.py, line 75:

<comment>Nullable vs optional serialization semantics regress: to_json now drops explicit None values for nullable fields, while to_dict emits null for all unset Optional fields, changing payloads from the prior OpenAPI-aware behavior.</comment>

<file context>
@@ -56,79 +60,27 @@ def array_string_enum_default_validate_enum(cls, value):
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the actual instance"""
+        return json.dumps(self.model_dump(by_alias=True, exclude_none=True))
 
     def to_dict(self) -> Dict[str, Any]:
</file context>
Fix with Cubic

@classmethod
def from_dict(cls, obj: Dict[str, Any]) -> Self:
"""Returns the object represented by the Dict"""
return cls.model_validate(obj, strict=True)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Additional properties are no longer rejected because from_dict now only uses strict validation without configuring extra='forbid', removing the previous explicit check for unknown keys.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/models/default_value.py, line 66:

<comment>Additional properties are no longer rejected because from_dict now only uses strict validation without configuring extra='forbid', removing the previous explicit check for unknown keys.</comment>

<file context>
@@ -56,79 +60,27 @@ def array_string_enum_default_validate_enum(cls, value):
+    @classmethod
+    def from_dict(cls, obj: Dict[str, Any]) -> Self:
+        """Returns the object represented by the Dict"""
+        return cls.model_validate(obj, strict=True)
 
     @classmethod
</file context>
Fix with Cubic

raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + _key)
def to_dict(self) -> Dict[str, Any]:
"""Returns the dict representation of the actual instance"""
return self.model_dump(by_alias=True)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: ReadOnly fields are no longer excluded from serialization in to_dict, so generated clients will emit read-only fields back to the server.

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 175:

<comment>ReadOnly fields are no longer excluded from serialization in `to_dict`, so generated clients will emit read-only fields back to the server.</comment>

<file context>
@@ -121,278 +156,28 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
-                raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + _key)
+    def to_dict(self) -> Dict[str, Any]:
+        """Returns the dict representation of the actual instance"""
+        return self.model_dump(by_alias=True)
 
-        {{/isAdditionalPropertiesTrue}}
</file context>
Fix with Cubic

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

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: Single-value enum uses raw enum value inside single quotes, which can generate invalid Python syntax when the enum value itself contains a single quote. Use the same enumVars/escaping logic as multi-value enums.

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 uses raw enum value inside single quotes, which can generate invalid Python syntax when the enum value itself contains a single quote. Use the same enumVars/escaping logic as multi-value enums.</comment>

<file context>
@@ -28,7 +29,41 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
+          {{#-first}}
+            {{#-last}}
+              {{! Single value enum - use Literal }}
+    {{name}}: Literal['{{{.}}}'] = Field(
+        {{#required}}...{{/required}}{{^required}}None{{/required}},
+        description="{{description}}{{^description}}{{{name}}} of the {{classname}}{{/description}}",
</file context>
Suggested change
{{name}}: Literal['{{{.}}}'] = Field(
{{name}}: Literal[{{#allowableValues}}{{#enumVars}}{{#isString}}{{{value}}}{{/isString}}{{^isString}}{{{value}}}{{/isString}}{{/enumVars}}{{/allowableValues}}] = Field(
Fix with Cubic

@classmethod
def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self:
return cls.from_json(json.dumps(obj))
def from_dict(cls, obj: Dict[str, Any]) -> Self:
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: from_dict and to_dict are annotated as Dict[str, Any], but RootModel oneOf roots can be primitives/lists; model_dump() returns the root type and model_validate() accepts non-dict roots. These annotations are too restrictive for non-object oneOf schemas.

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_oneof.mustache, line 40:

<comment>`from_dict` and `to_dict` are annotated as `Dict[str, Any]`, but RootModel oneOf roots can be primitives/lists; `model_dump()` returns the root type and `model_validate()` accepts non-dict roots. These annotations are too restrictive for non-object oneOf schemas.</comment>

<file context>
@@ -7,198 +7,56 @@ import pprint
     @classmethod
-    def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self:
-        return cls.from_json(json.dumps(obj))
+    def from_dict(cls, obj: Dict[str, Any]) -> Self:
+        """Returns the object represented by the Dict"""
+        return cls.model_validate(obj, strict=True)
</file context>
Fix with Cubic


return _dict
"""Returns the dict representation of the actual instance"""
return self.model_dump(by_alias=True)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: to_dict now serializes all optional fields with None, which changes request payload semantics and can overwrite server-side values with nulls when used by ApiClient serialization.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/python/openapi_client/models/default_value.py, line 79:

<comment>to_dict now serializes all optional fields with None, which changes request payload semantics and can overwrite server-side values with nulls when used by ApiClient serialization.</comment>

<file context>
@@ -56,74 +60,27 @@ def array_string_enum_default_validate_enum(cls, value):
-
-        return _dict
+        """Returns the dict representation of the actual instance"""
+        return self.model_dump(by_alias=True)
+
+    def to_str(self) -> str:
</file context>
Fix with Cubic


def to_json(self) -> str:
"""Returns the JSON representation of the actual instance"""
return json.dumps(self.model_dump(by_alias=True, exclude_none=True))
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: to_json now always excludes None values, which drops explicitly set nullable fields from the JSON payload. This regresses the previous behavior that re-inserted nullable fields set to None via model_fields_set, so clients can no longer send null to clear values.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/python/openapi_client/models/default_value.py, line 75:

<comment>to_json now always excludes None values, which drops explicitly set nullable fields from the JSON payload. This regresses the previous behavior that re-inserted nullable fields set to None via model_fields_set, so clients can no longer send null to clear values.</comment>

<file context>
@@ -56,74 +60,27 @@ def array_string_enum_default_validate_enum(cls, value):
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the actual instance"""
+        return json.dumps(self.model_dump(by_alias=True, exclude_none=True))
 
     def to_dict(self) -> Dict[str, Any]:
</file context>
Fix with Cubic

)
assert m is not None, "Unexpected 'content-disposition' header value"
filename = m.group(1)
filename = os.path.basename(m.group(1)) # Strip any directory traversal
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: The code deletes the secure mkstemp file and then uses the server-provided filename to build a predictable path in a shared temp directory. This leaves a TOCTOU/symlink race window before open(path, "wb"), allowing a local attacker to pre-create a symlink and force overwriting arbitrary files. Use a private temp directory (mkdtemp) or keep the secure fd rather than deleting it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/python/openapi_client/api_client.py, line 711:

<comment>The code deletes the secure mkstemp file and then uses the server-provided filename to build a predictable path in a shared temp directory. This leaves a TOCTOU/symlink race window before `open(path, "wb")`, allowing a local attacker to pre-create a symlink and force overwriting arbitrary files. Use a private temp directory (mkdtemp) or keep the secure fd rather than deleting it.</comment>

<file context>
@@ -708,7 +708,7 @@ def __deserialize_file(self, response):
             )
             assert m is not None, "Unexpected 'content-disposition' header value"
-            filename = m.group(1)
+            filename = os.path.basename(m.group(1))  # Strip any directory traversal
             path = os.path.join(os.path.dirname(path), filename)
 
</file context>
Fix with Cubic

])
def to_dict(self) -> Dict[str, Any]:
"""Returns the dict representation of the actual instance"""
return self.model_dump(by_alias=True)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 13, 2026

Choose a reason for hiding this comment

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

P2: to_dict no longer excludes None values, making it inconsistent with to_json and potentially causing nulls to be sent in API payloads. This is a regression from the prior behavior and can change PATCH/optional field semantics.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/python/openapi_client/models/bird.py, line 58:

<comment>`to_dict` no longer excludes None values, making it inconsistent with `to_json` and potentially causing nulls to be sent in API payloads. This is a regression from the prior behavior and can change PATCH/optional field semantics.</comment>

<file context>
@@ -38,53 +39,27 @@ class Bird(BaseModel):
-        ])
+    def to_dict(self) -> Dict[str, Any]:
+        """Returns the dict representation of the actual instance"""
+        return self.model_dump(by_alias=True)
 
-        _dict = self.model_dump(
</file context>
Suggested change
return self.model_dump(by_alias=True)
return self.model_dump(by_alias=True, exclude_none=True)
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.

3 participants