diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index 05e8d60fac88..c23b7d9310a3 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -520,6 +520,7 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, public static final String X_PY_EXAMPLE_IMPORT = "x-py-example-import"; public static final String X_PY_FASTAPI_EXAMPLE = "x-py-fastapi-example"; public static final String X_PY_NAME = "x-py-name"; + public static final String X_PY_WIRE_NAME_LITERAL = "x-py-wire-name-literal"; public static final String X_PY_ENUM_TYPE = "x-py-enum-type"; public static final String X_PY_READONLY = "x-py-readonly"; public static final String X_PY_MODEL_IMPORTS = "x-py-model-imports"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java index 510cf09b44c7..a9a2f8d65a77 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java @@ -17,6 +17,8 @@ package org.openapitools.codegen.languages; import com.github.curiousoddman.rgxgen.RgxGen; +import com.google.common.collect.ImmutableMap; +import com.samskivert.mustache.Mustache; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.media.Schema; @@ -731,11 +733,7 @@ protected String toPythonLiteral(Object value) { } protected String toPythonStringLiteral(String value) { - try { - return Json.mapper().writeValueAsString(value); - } catch (Exception e) { - return "\"" + escapeUnsafeCharacters(value) + "\""; - } + return PythonStringUtils.toPythonStringLiteral(value); } @Override @@ -920,6 +918,11 @@ public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.PYTHON; } + @Override + protected ImmutableMap.Builder addMustacheLambdas() { + return PythonStringUtils.addMustacheLambdas(super.addMustacheLambdas()); + } + @Override public Map postProcessAllModels(Map objs) { final Map processed = super.postProcessAllModels(objs); @@ -1422,6 +1425,9 @@ public void postProcessParameter(CodegenParameter parameter) { @Override public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + property.vendorExtensions.put( + X_PY_WIRE_NAME_LITERAL, + toPythonStringLiteral(property.baseName)); postProcessPattern(property.pattern, property.vendorExtensions); if (property.isArray) { @@ -2238,7 +2244,7 @@ private String finalizeType(CodegenProperty cp, PythonType pt) { // field if (cp.baseName != null && !cp.baseName.equals(cp.name)) { // base name not the same as name - pt.annotate("alias", cp.baseName); + pt.annotate("alias", toPythonStringLiteral(cp.baseName), false); } String example = toPythonExample(cp); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonPydanticV1Codegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonPydanticV1Codegen.java index 297044bfc609..4d54eed54ea2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonPydanticV1Codegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonPydanticV1Codegen.java @@ -17,6 +17,8 @@ package org.openapitools.codegen.languages; import com.github.curiousoddman.rgxgen.RgxGen; +import com.google.common.collect.ImmutableMap; +import com.samskivert.mustache.Mustache; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; @@ -775,6 +777,11 @@ protected static String dropDots(String str) { return str.replaceAll("\\.", "_"); } + @Override + protected ImmutableMap.Builder addMustacheLambdas() { + return PythonStringUtils.addMustacheLambdas(super.addMustacheLambdas()); + } + @Override public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.PYTHON; @@ -907,7 +914,7 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) { // field if (cp.baseName != null && !cp.baseName.equals(cp.name)) { // base name not the same as name - fields.add(String.format(Locale.ROOT, "alias=\"%s\"", cp.baseName)); + fields.add("alias=" + PythonStringUtils.toPythonStringLiteral(cp.baseName)); } if (!StringUtils.isEmpty(cp.description)) { // has description @@ -1880,6 +1887,9 @@ public void postProcessParameter(CodegenParameter parameter) { @Override public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + property.vendorExtensions.put( + X_PY_WIRE_NAME_LITERAL, + PythonStringUtils.toPythonStringLiteral(property.baseName)); postProcessPattern(property.pattern, property.vendorExtensions); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonStringUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonStringUtils.java new file mode 100644 index 000000000000..a2929b085513 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonStringUtils.java @@ -0,0 +1,51 @@ +/* + * Copyright 2026 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.languages; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.collect.ImmutableMap; +import com.samskivert.mustache.Mustache; +import io.swagger.v3.core.util.Json; + +public final class PythonStringUtils { + private PythonStringUtils() {} + + public static String toPythonStringLiteral(String value) { + try { + return Json.mapper().writeValueAsString(value); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Failed to encode Python string literal", e); + } + } + + public static String toPythonSingleQuotedStringLiteral(String value) { + String doubleQuoted = toPythonStringLiteral(value); + String contents = doubleQuoted.substring(1, doubleQuoted.length() - 1) + .replace("\\\"", "\"") + .replace("'", "\\'"); + return "'" + contents + "'"; + } + + public static ImmutableMap.Builder addMustacheLambdas( + ImmutableMap.Builder lambdas) { + return lambdas + .put("pythonStringLiteral", (fragment, writer) -> + writer.write(toPythonStringLiteral(fragment.execute()))) + .put("pythonSingleQuotedStringLiteral", (fragment, writer) -> + writer.write(toPythonSingleQuotedStringLiteral(fragment.execute()))); + } +} diff --git a/modules/openapi-generator/src/main/resources/python-pydantic-v1/model_generic.mustache b/modules/openapi-generator/src/main/resources/python-pydantic-v1/model_generic.mustache index 6ac505ab55ec..1d59990d6cac 100644 --- a/modules/openapi-generator/src/main/resources/python-pydantic-v1/model_generic.mustache +++ b/modules/openapi-generator/src/main/resources/python-pydantic-v1/model_generic.mustache @@ -32,7 +32,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#isAdditionalPropertiesTrue}} additional_properties: Dict[str, Any] = {} {{/isAdditionalPropertiesTrue}} - __properties = [{{#allVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/allVars}}] + __properties = [{{#allVars}}{{{vendorExtensions.x-py-wire-name-literal}}}{{^-last}}, {{/-last}}{{/allVars}}] {{#vars}} {{#vendorExtensions.x-regex}} @@ -93,14 +93,14 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#hasChildren}} {{#discriminator}} # JSON field name that stores the object type - __discriminator_property_name = '{{discriminator.propertyBaseName}}' + __discriminator_property_name = {{#lambda.pythonSingleQuotedStringLiteral}}{{{discriminator.propertyBaseName}}}{{/lambda.pythonSingleQuotedStringLiteral}} {{#mappedModels}} {{#-first}} # discriminator mappings __discriminator_value_class_map = { {{/-first}} - '{{{mappingName}}}': '{{{modelName}}}'{{^-last}},{{/-last}} + {{#lambda.pythonSingleQuotedStringLiteral}}{{{mappingName}}}{{/lambda.pythonSingleQuotedStringLiteral}}: '{{{modelName}}}'{{^-last}},{{/-last}} {{#-last}} } @@ -156,7 +156,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} _items.append( [_inner_item.to_dict() for _inner_item in _item if _inner_item is not None] ) - _dict['{{{baseName}}}'] = _items + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items {{/items.isArray}} {{#items.isMap}} # override the default output from pydantic by calling `to_dict()` of each item in {{{name}}} (list of map) @@ -167,7 +167,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} _items.append( {_inner_key: _inner_value.to_dict() for _inner_key, _inner_value in _item.items() if _inner_value is not None} ) - _dict['{{{baseName}}}'] = _items + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items {{/items.isMap}} {{/items.items.isPrimitiveType}} {{/items.isContainer}} @@ -180,7 +180,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} for _item in self.{{{name}}}: if _item: _items.append(_item.to_dict()) - _dict['{{{baseName}}}'] = _items + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items {{/items.isEnumOrRef}} {{/items.isPrimitiveType}} {{/items.isContainer}} @@ -197,7 +197,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} _field_dict_of_array[_key] = [ _item.to_dict() for _item in self.{{{name}}}[_key] ] - _dict['{{{baseName}}}'] = _field_dict_of_array + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict_of_array {{/items.isArray}} {{#items.isMap}} # override the default output from pydantic by calling `to_dict()` of each value in {{{name}}} (dict of dict) @@ -208,7 +208,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} _field_dict_of_dict[_key] = { _inner_key: _inner_value.to_dict() for _inner_key, _inner_value in _value.items() if _inner_value is not None } - _dict['{{{baseName}}}'] = _field_dict_of_dict + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict_of_dict {{/items.isMap}} {{/items.items.isPrimitiveType}} {{/items.isContainer}} @@ -221,7 +221,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} for _key in self.{{{name}}}: if self.{{{name}}}[_key]: _field_dict[_key] = self.{{{name}}}[_key].to_dict() - _dict['{{{baseName}}}'] = _field_dict + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict {{/items.isEnumOrRef}} {{/items.isPrimitiveType}} {{/items.isContainer}} @@ -232,7 +232,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{^isEnumOrRef}} # override the default output from pydantic by calling `to_dict()` of {{{name}}} if self.{{{name}}}: - _dict['{{{baseName}}}'] = self.{{{name}}}.to_dict() + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = self.{{{name}}}.to_dict() {{/isEnumOrRef}} {{/isPrimitiveType}} {{/isContainer}} @@ -249,7 +249,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} # set to None if {{{name}}} (nullable) is None # and __fields_set__ contains the field if self.{{name}} is None and "{{{name}}}" in self.__fields_set__: - _dict['{{{baseName}}}'] = None + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = None {{/isNullable}} {{/allVars}} @@ -293,34 +293,34 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#isArray}} {{#items.isContainer}} {{#items.items.isPrimitiveType}} - "{{{name}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + "{{{name}}}": obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.items.isPrimitiveType}} {{^items.items.isPrimitiveType}} {{#items.isArray}} "{{{name}}}": [ [{{{items.items.dataType}}}.from_dict(_inner_item) for _inner_item in _item] - for _item in obj.get("{{{baseName}}}") - ] if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + for _item in obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) + ] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isArray}} {{#items.isMap}} "{{{name}}}": [ {_inner_key: {{{items.items.dataType}}}.from_dict(_inner_value) for _inner_key, _inner_value in _item.items()} - for _item in obj.get("{{{baseName}}}") - ] if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + for _item in obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) + ] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isMap}} {{/items.items.isPrimitiveType}} {{/items.isContainer}} {{^items.isContainer}} {{^items.isPrimitiveType}} {{#items.isEnumOrRef}} - "{{{name}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + "{{{name}}}": obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.isEnumOrRef}} {{^items.isEnumOrRef}} - "{{{name}}}": [{{{items.dataType}}}.from_dict(_item) for _item in obj.get("{{{baseName}}}")] if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + "{{{name}}}": [{{{items.dataType}}}.from_dict(_item) for _item in obj.get({{{vendorExtensions.x-py-wire-name-literal}}})] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isEnumOrRef}} {{/items.isPrimitiveType}} {{#items.isPrimitiveType}} - "{{{name}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + "{{{name}}}": obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.isPrimitiveType}} {{/items.isContainer}} {{/isArray}} @@ -331,52 +331,52 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#items.isMap}} "{{{name}}}": { _k: {_ik: {{{items.items.dataType}}}.from_dict(_iv) for _ik, _iv in _v.items()} if _v is not None else None - for _k, _v in obj["{{{baseName}}}"].items() + for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() } - if obj.get("{{{baseName}}}") is not None + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isMap}} {{#items.isArray}} "{{{name}}}": { _k: [{{{items.items.dataType}}}.from_dict(_item) for _item in _v] if _v is not None else None - for _k, _v in obj["{{{baseName}}}"].items() + for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() } - if obj.get("{{{baseName}}}") is not None + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isArray}} {{/items.isContainer}} {{^items.isContainer}} "{{{name}}}": { - _k: {{{items.dataType}}}.from_dict(_v) for _k, _v in obj["{{{baseName}}}"].items() + _k: {{{items.dataType}}}.from_dict(_v) for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() } - if obj.get("{{{baseName}}}") is not None + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isContainer}} {{/items.isEnumOrRef}} {{#items.isEnumOrRef}} - "{{{name}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + "{{{name}}}": obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.isEnumOrRef}} {{/items.isPrimitiveType}} {{#items.isPrimitiveType}} - "{{{name}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + "{{{name}}}": obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.isPrimitiveType}} {{/isMap}} {{/isContainer}} {{^isContainer}} {{^isPrimitiveType}} {{^isEnumOrRef}} - "{{{name}}}": {{{dataType}}}.from_dict(obj.get("{{{baseName}}}")) if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + "{{{name}}}": {{{dataType}}}.from_dict(obj.get({{{vendorExtensions.x-py-wire-name-literal}}})) if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/isEnumOrRef}} {{#isEnumOrRef}} - "{{{name}}}": obj.get("{{{baseName}}}"){{#defaultValue}} if obj.get("{{baseName}}") is not None else {{{defaultValue}}}{{/defaultValue}}{{^-last}},{{/-last}} + "{{{name}}}": obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{#defaultValue}} if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else {{{defaultValue}}}{{/defaultValue}}{{^-last}},{{/-last}} {{/isEnumOrRef}} {{/isPrimitiveType}} {{#isPrimitiveType}} {{#defaultValue}} - "{{{name}}}": obj.get("{{{baseName}}}") if obj.get("{{{baseName}}}") is not None else {{{defaultValue}}}{{^-last}},{{/-last}} + "{{{name}}}": obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else {{{defaultValue}}}{{^-last}},{{/-last}} {{/defaultValue}} {{^defaultValue}} - "{{{name}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + "{{{name}}}": obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/defaultValue}} {{/isPrimitiveType}} {{/isContainer}} diff --git a/modules/openapi-generator/src/main/resources/python-pydantic-v1/model_oneof.mustache b/modules/openapi-generator/src/main/resources/python-pydantic-v1/model_oneof.mustache index 2f23bade3418..f9ffd2a8a5de 100644 --- a/modules/openapi-generator/src/main/resources/python-pydantic-v1/model_oneof.mustache +++ b/modules/openapi-generator/src/main/resources/python-pydantic-v1/model_oneof.mustache @@ -34,7 +34,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} discriminator_value_class_map = { {{#children}} - '{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}},{{/-last}} + {{#lambda.pythonSingleQuotedStringLiteral}}{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}{{/lambda.pythonSingleQuotedStringLiteral}}: '{{{classname}}}'{{^-last}},{{/-last}} {{/children}} } {{/discriminator}} @@ -114,13 +114,14 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#mappedModels}} {{#-first}} # use oneOf discriminator to lookup the data type - _data_type = json.loads(json_str).get("{{{propertyBaseName}}}") + _discriminator_property = {{#lambda.pythonStringLiteral}}{{{propertyBaseName}}}{{/lambda.pythonStringLiteral}} + _data_type = json.loads(json_str).get(_discriminator_property) if not _data_type: - raise ValueError("Failed to lookup data type from the field `{{{propertyBaseName}}}` in the input.") + raise ValueError(f"Failed to lookup data type from the field `{_discriminator_property}` in the input.") {{/-first}} # check if data type is `{{{modelName}}}` - if _data_type == "{{{mappingName}}}": + if _data_type == {{#lambda.pythonStringLiteral}}{{{mappingName}}}{{/lambda.pythonStringLiteral}}: instance.actual_instance = {{{modelName}}}.from_json(json_str) return instance diff --git a/modules/openapi-generator/src/main/resources/python/model_generic.mustache b/modules/openapi-generator/src/main/resources/python/model_generic.mustache index 1b9d0f7d3fd8..c0dc0db2c966 100644 --- a/modules/openapi-generator/src/main/resources/python/model_generic.mustache +++ b/modules/openapi-generator/src/main/resources/python/model_generic.mustache @@ -34,7 +34,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#isAdditionalPropertiesTrue}} additional_properties: Dict[str, Any] = {} {{/isAdditionalPropertiesTrue}} - __properties: ClassVar[List[str]] = [{{#allVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/allVars}}] + __properties: ClassVar[List[str]] = [{{#allVars}}{{{vendorExtensions.x-py-wire-name-literal}}}{{^-last}}, {{/-last}}{{/allVars}}] {{#vars}} {{#vendorExtensions.x-regex}} @@ -108,11 +108,11 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#hasChildren}} {{#discriminator}} # JSON field name that stores the object type - __discriminator_property_name: ClassVar[str] = '{{discriminator.propertyBaseName}}' + __discriminator_property_name: ClassVar[str] = {{#lambda.pythonSingleQuotedStringLiteral}}{{{discriminator.propertyBaseName}}}{{/lambda.pythonSingleQuotedStringLiteral}} # discriminator mappings __discriminator_value_class_map: ClassVar[Dict[str, str]] = { - {{#mappedModels}}'{{{mappingName}}}': '{{{modelName}}}'{{^-last}},{{/-last}}{{/mappedModels}} + {{#mappedModels}}{{#lambda.pythonSingleQuotedStringLiteral}}{{{mappingName}}}{{/lambda.pythonSingleQuotedStringLiteral}}: '{{{modelName}}}'{{^-last}},{{/-last}}{{/mappedModels}} } @classmethod @@ -182,7 +182,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} _items.append( [_inner_item.to_dict() for _inner_item in _item_{{{name}}} if _inner_item is not None] ) - _dict['{{{baseName}}}'] = _items + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items {{/items.items.isPrimitiveType}} {{/items.isArray}} {{#items.isMap}} @@ -195,7 +195,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} _items.append( {_inner_key: _inner_value.to_dict() for _inner_key, _inner_value in _item_{{{name}}}.items()} ) - _dict['{{{baseName}}}'] = _items + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items {{/items.items.isPrimitiveType}} {{/items.isMap}} {{^items.isArray}} @@ -208,7 +208,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} for _item_{{{name}}} in self.{{{name}}}: if _item_{{{name}}}: _items.append(_item_{{{name}}}.to_dict()) - _dict['{{{baseName}}}'] = _items + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items {{/items.isEnumOrRef}} {{/items.isPrimitiveType}} {{/items.isMap}} @@ -225,7 +225,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} _field_dict_of_array[_key_{{{name}}}] = [ _item.to_dict() for _item in self.{{{name}}}[_key_{{{name}}}] ] - _dict['{{{baseName}}}'] = _field_dict_of_array + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict_of_array {{/items.items.isPrimitiveType}} {{/items.isArray}} {{#items.isMap}} @@ -238,7 +238,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} _field_dict_of_dict[_key_{{{name}}}] = { _key: _value.to_dict() for _key, _value in _value_{{{name}}}.items() } - _dict['{{{baseName}}}'] = _field_dict_of_dict + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict_of_dict {{/items.items.isPrimitiveType}} {{/items.isMap}} {{^items.isMap}} @@ -251,7 +251,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} for _key_{{{name}}} in self.{{{name}}}: if self.{{{name}}}[_key_{{{name}}}]: _field_dict[_key_{{{name}}}] = self.{{{name}}}[_key_{{{name}}}].to_dict() - _dict['{{{baseName}}}'] = _field_dict + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict {{/items.isEnumOrRef}} {{/items.isPrimitiveType}} {{/items.isArray}} @@ -263,7 +263,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{^isEnumOrRef}} # override the default output from pydantic by calling `to_dict()` of {{{name}}} if self.{{{name}}}: - _dict['{{{baseName}}}'] = self.{{{name}}}.to_dict() + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = self.{{{name}}}.to_dict() {{/isEnumOrRef}} {{/isPrimitiveType}} {{/isContainer}} @@ -280,7 +280,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} # set to None if {{{name}}} (nullable) is None # and model_fields_set contains the field if self.{{name}} is None and "{{{name}}}" in self.model_fields_set: - _dict['{{{baseName}}}'] = None + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = None {{/isNullable}} {{/allVars}} @@ -329,38 +329,38 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#items.isContainer}} {{#items.isArray}} {{#items.items.isPrimitiveType}} - "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.items.isPrimitiveType}} {{^items.items.isPrimitiveType}} - "{{{baseName}}}": [ + {{{vendorExtensions.x-py-wire-name-literal}}}: [ [{{{items.items.dataType}}}.from_dict(_inner_item) for _inner_item in _item] - for _item in obj["{{{baseName}}}"] - ] if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + for _item in obj[{{{vendorExtensions.x-py-wire-name-literal}}}] + ] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.items.isPrimitiveType}} {{/items.isArray}} {{#items.isMap}} {{#items.items.isPrimitiveType}} - "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.items.isPrimitiveType}} {{^items.items.isPrimitiveType}} - "{{{baseName}}}": [ + {{{vendorExtensions.x-py-wire-name-literal}}}: [ {_inner_key: {{{items.items.dataType}}}.from_dict(_inner_value) for _inner_key, _inner_value in _item.items()} - for _item in obj["{{{baseName}}}"] - ] if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + for _item in obj[{{{vendorExtensions.x-py-wire-name-literal}}}] + ] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.items.isPrimitiveType}} {{/items.isMap}} {{/items.isContainer}} {{^items.isContainer}} {{^items.isPrimitiveType}} {{#items.isEnumOrRef}} - "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.isEnumOrRef}} {{^items.isEnumOrRef}} - "{{{baseName}}}": [{{{items.dataType}}}.from_dict(_item) for _item in obj["{{{baseName}}}"]] if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: [{{{items.dataType}}}.from_dict(_item) for _item in obj[{{{vendorExtensions.x-py-wire-name-literal}}}]] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isEnumOrRef}} {{/items.isPrimitiveType}} {{#items.isPrimitiveType}} - "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.isPrimitiveType}} {{/items.isContainer}} {{/isArray}} @@ -369,7 +369,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{^items.isEnumOrRef}} {{#items.isContainer}} {{#items.isMap}} - "{{{baseName}}}": dict( + {{{vendorExtensions.x-py-wire-name-literal}}}: dict( (_k, dict( (_ik, {{{items.items.dataType}}}.from_dict(_iv)) for _ik, _iv in _v.items() @@ -377,53 +377,53 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} if _v is not None else None ) - for _k, _v in obj["{{{baseName}}}"].items() + for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() ) - if obj.get("{{{baseName}}}") is not None + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isMap}} {{#items.isArray}} - "{{{baseName}}}": { + {{{vendorExtensions.x-py-wire-name-literal}}}: { _k: [{{{items.items.dataType}}}.from_dict(_item) for _item in _v] if _v is not None else None - for _k, _v in obj["{{{baseName}}}"].items() + for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() } - if obj.get("{{{baseName}}}") is not None + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isArray}} {{/items.isContainer}} {{^items.isContainer}} - "{{{baseName}}}": dict( + {{{vendorExtensions.x-py-wire-name-literal}}}: dict( (_k, {{{items.dataType}}}.from_dict(_v)) - for _k, _v in obj["{{{baseName}}}"].items() + for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() ) - if obj.get("{{{baseName}}}") is not None + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isContainer}} {{/items.isEnumOrRef}} {{#items.isEnumOrRef}} - "{{{baseName}}}": dict((_k, _v) for _k, _v in obj.get("{{{baseName}}}").items()) if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: dict((_k, _v) for _k, _v in obj.get({{{vendorExtensions.x-py-wire-name-literal}}}).items()) if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/items.isEnumOrRef}} {{/items.isPrimitiveType}} {{#items.isPrimitiveType}} - "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/items.isPrimitiveType}} {{/isMap}} {{/isContainer}} {{^isContainer}} {{^isPrimitiveType}} {{^isEnumOrRef}} - "{{{baseName}}}": {{{dataType}}}.from_dict(obj["{{{baseName}}}"]) if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: {{{dataType}}}.from_dict(obj[{{{vendorExtensions.x-py-wire-name-literal}}}]) if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} {{/isEnumOrRef}} {{#isEnumOrRef}} - "{{{baseName}}}": obj.get("{{{baseName}}}"){{#defaultValue}} if obj.get("{{baseName}}") is not None else {{{defaultValue}}}{{/defaultValue}}{{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{#defaultValue}} if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else {{{defaultValue}}}{{/defaultValue}}{{^-last}},{{/-last}} {{/isEnumOrRef}} {{/isPrimitiveType}} {{#isPrimitiveType}} {{#defaultValue}} - "{{{baseName}}}": obj.get("{{{baseName}}}") if obj.get("{{{baseName}}}") is not None else {{{defaultValue}}}{{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else {{{defaultValue}}}{{^-last}},{{/-last}} {{/defaultValue}} {{^defaultValue}} - "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} {{/defaultValue}} {{/isPrimitiveType}} {{/isContainer}} diff --git a/modules/openapi-generator/src/main/resources/python/model_oneof.mustache b/modules/openapi-generator/src/main/resources/python/model_oneof.mustache index 07a4d93f9ddf..88320207c196 100644 --- a/modules/openapi-generator/src/main/resources/python/model_oneof.mustache +++ b/modules/openapi-generator/src/main/resources/python/model_oneof.mustache @@ -33,7 +33,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} discriminator_value_class_map: Dict[str, str] = { {{#children}} - '{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}},{{/-last}} + {{#lambda.pythonSingleQuotedStringLiteral}}{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}{{/lambda.pythonSingleQuotedStringLiteral}}: '{{{classname}}}'{{^-last}},{{/-last}} {{/children}} } {{/discriminator}} @@ -118,13 +118,14 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} {{#mappedModels}} {{#-first}} # use oneOf discriminator to lookup the data type - _data_type = json.loads(json_str).get("{{{propertyBaseName}}}") + _discriminator_property = {{#lambda.pythonStringLiteral}}{{{propertyBaseName}}}{{/lambda.pythonStringLiteral}} + _data_type = json.loads(json_str).get(_discriminator_property) if not _data_type: - raise ValueError("Failed to lookup data type from the field `{{{propertyBaseName}}}` in the input.") + raise ValueError(f"Failed to lookup data type from the field `{_discriminator_property}` in the input.") {{/-first}} # check if data type is `{{{modelName}}}` - if _data_type == "{{{mappingName}}}": + if _data_type == {{#lambda.pythonStringLiteral}}{{{mappingName}}}{{/lambda.pythonStringLiteral}}: instance.actual_instance = {{{modelName}}}.from_json(json_str) return instance diff --git a/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml index 2c10d7d5d36c..427b2b70d7c4 100644 --- a/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml @@ -1833,11 +1833,13 @@ components: DiscriminatorAllOfSuper: type: object required: - - elementType + - 'element''"\Type' discriminator: - propertyName: elementType + propertyName: 'element''"\Type' + mapping: + "sub'\"\\kind\nvalue": '#/components/schemas/DiscriminatorAllOfSub' properties: - elementType: + 'element''"\Type': type: string DiscriminatorAllOfSub: allOf: @@ -2540,26 +2542,29 @@ components: - $ref: '#/components/schemas/BasquePig' - $ref: '#/components/schemas/DanishPig' discriminator: - propertyName: className + propertyName: 'class''"\Name' + mapping: + "basque'\"\\pig\nkind": '#/components/schemas/BasquePig' + danish: '#/components/schemas/DanishPig' BasquePig: type: object properties: - className: + 'class''"\Name': type: string color: type: string required: - - className + - 'class''"\Name' - color DanishPig: type: object properties: - className: + 'class''"\Name': type: string size: type: integer required: - - className + - 'class''"\Name' - size AnyOfPig: anyOf: @@ -2570,7 +2575,7 @@ components: properties: size: type: integer - nested_pig: + "nested_\npig": $ref: '#/components/schemas/Pig' nested_oneof_enum_string: $ref: '#/components/schemas/OneOfEnumString' diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/basque_pig.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/basque_pig.py index 9282af3ff24f..b279e5a53e14 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/basque_pig.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/basque_pig.py @@ -27,9 +27,9 @@ class BasquePig(BaseModel): """ BasquePig """ # noqa: E501 - class_name: StrictStr = Field(alias="className") + class_name: StrictStr = Field(alias="class'\"\\Name") color: StrictStr - __properties: ClassVar[List[str]] = ["className", "color"] + __properties: ClassVar[List[str]] = ["class'\"\\Name", "color"] model_config = ConfigDict( validate_by_name=True, @@ -82,7 +82,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "className": obj.get("className"), + "class'\"\\Name": obj.get("class'\"\\Name"), "color": obj.get("color") }) return _obj diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/danish_pig.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/danish_pig.py index ed51566a659e..ad3e5496cbd1 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/danish_pig.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/danish_pig.py @@ -27,9 +27,9 @@ class DanishPig(BaseModel): """ DanishPig """ # noqa: E501 - class_name: StrictStr = Field(alias="className") + class_name: StrictStr = Field(alias="class'\"\\Name") size: StrictInt - __properties: ClassVar[List[str]] = ["className", "size"] + __properties: ClassVar[List[str]] = ["class'\"\\Name", "size"] model_config = ConfigDict( validate_by_name=True, @@ -82,7 +82,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "className": obj.get("className"), + "class'\"\\Name": obj.get("class'\"\\Name"), "size": obj.get("size") }) return _obj diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/discriminator_all_of_sub.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/discriminator_all_of_sub.py index 987dae7f5c32..f5a0aa665e7f 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/discriminator_all_of_sub.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/discriminator_all_of_sub.py @@ -28,7 +28,7 @@ class DiscriminatorAllOfSub(DiscriminatorAllOfSuper): """ DiscriminatorAllOfSub """ # noqa: E501 - __properties: ClassVar[List[str]] = ["elementType"] + __properties: ClassVar[List[str]] = ["element'\"\\Type"] model_config = ConfigDict( validate_by_name=True, @@ -81,7 +81,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "elementType": obj.get("elementType") + "element'\"\\Type": obj.get("element'\"\\Type") }) return _obj diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/discriminator_all_of_super.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/discriminator_all_of_super.py index 661015629f41..ef7f96a4b4c3 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/discriminator_all_of_super.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/discriminator_all_of_super.py @@ -32,8 +32,8 @@ class DiscriminatorAllOfSuper(BaseModel): """ DiscriminatorAllOfSuper """ # noqa: E501 - element_type: StrictStr = Field(alias="elementType") - __properties: ClassVar[List[str]] = ["elementType"] + element_type: StrictStr = Field(alias="element'\"\\Type") + __properties: ClassVar[List[str]] = ["element'\"\\Type"] model_config = ConfigDict( validate_by_name=True, @@ -44,11 +44,11 @@ class DiscriminatorAllOfSuper(BaseModel): # JSON field name that stores the object type - __discriminator_property_name: ClassVar[str] = 'elementType' + __discriminator_property_name: ClassVar[str] = 'element\'"\\Type' # discriminator mappings __discriminator_value_class_map: ClassVar[Dict[str, str]] = { - 'DiscriminatorAllOfSub': 'DiscriminatorAllOfSub' + 'sub\'"\\kind\nvalue': 'DiscriminatorAllOfSub' } @classmethod diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/with_nested_one_of.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/with_nested_one_of.py index 4f2003d80cc3..c85fa5963a75 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/with_nested_one_of.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/with_nested_one_of.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, StrictInt +from pydantic import BaseModel, ConfigDict, Field, StrictInt from typing import Any, ClassVar, Dict, List, Optional from petstore_api.models.one_of_enum_string import OneOfEnumString from petstore_api.models.pig import Pig @@ -30,9 +30,9 @@ class WithNestedOneOf(BaseModel): WithNestedOneOf """ # noqa: E501 size: Optional[StrictInt] = None - nested_pig: Optional[Pig] = None + nested_pig: Optional[Pig] = Field(default=None, alias="nested_\npig") nested_oneof_enum_string: Optional[OneOfEnumString] = None - __properties: ClassVar[List[str]] = ["size", "nested_pig", "nested_oneof_enum_string"] + __properties: ClassVar[List[str]] = ["size", "nested_\npig", "nested_oneof_enum_string"] model_config = ConfigDict( validate_by_name=True, @@ -75,7 +75,7 @@ def to_dict(self) -> Dict[str, Any]: ) # override the default output from pydantic by calling `to_dict()` of nested_pig if self.nested_pig: - _dict['nested_pig'] = self.nested_pig.to_dict() + _dict['nested_\npig'] = self.nested_pig.to_dict() return _dict @classmethod @@ -89,7 +89,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "size": obj.get("size"), - "nested_pig": Pig.from_dict(obj["nested_pig"]) if obj.get("nested_pig") is not None else None, + "nested_\npig": Pig.from_dict(obj["nested_\npig"]) if obj.get("nested_\npig") is not None else None, "nested_oneof_enum_string": obj.get("nested_oneof_enum_string") }) return _obj diff --git a/samples/openapi3/client/petstore/python-aiohttp/tests/test_model.py b/samples/openapi3/client/petstore/python-aiohttp/tests/test_model.py index 0ef8d9956a78..8c51faeecb93 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/tests/test_model.py +++ b/samples/openapi3/client/petstore/python-aiohttp/tests/test_model.py @@ -75,14 +75,18 @@ def test_equal(self): self.assertFalse(self.pet1 == self.pet2) def test_oneOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new Pig new_pig = petstore_api.Pig() self.assertEqual("null", new_pig.to_json()) self.assertEqual(None, new_pig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.Pig.from_json(json_str) + p = petstore_api.Pig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -113,11 +117,20 @@ def test_oneOf(self): self.assertIn("Input should be a valid dictionary or instance of DanishPig", str(e)) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) # test nested property - nested = petstore_api.WithNestedOneOf(size = 1, nested_pig = p) - self.assertEqual(nested.to_json(), '{"size": 1, "nested_pig": {"className": "BasquePig", "color": "red"}}') + nested_wire_name = "nested_\npig" + nested = petstore_api.WithNestedOneOf.from_dict({ + "size": 1, + nested_wire_name: wire_value, + }) + assert nested is not None + self.assertEqual( + nested.to_json(), + json.dumps({"size": 1, nested_wire_name: wire_value}), + ) + self.assertEqual(nested.to_dict()[nested_wire_name], wire_value) nested_json = nested.to_json() nested2 = petstore_api.WithNestedOneOf.from_json(nested_json) @@ -125,14 +138,18 @@ def test_oneOf(self): self.assertEqual(nested2.to_json(), nested_json) def test_anyOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new AnyOfPig new_anypig = petstore_api.AnyOfPig() self.assertEqual("null", new_anypig.to_json()) self.assertEqual(None, new_anypig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.AnyOfPig.from_json(json_str) + p = petstore_api.AnyOfPig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -168,7 +185,7 @@ def test_anyOf(self): self.assertIn("Input should be a valid dictionary or instance of DanishPig", str(e)) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) def test_inheritance(self): dog = petstore_api.Dog(breed="bulldog", className="dog", color="white") diff --git a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/basque_pig.py b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/basque_pig.py index 9282af3ff24f..b279e5a53e14 100644 --- a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/basque_pig.py +++ b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/basque_pig.py @@ -27,9 +27,9 @@ class BasquePig(BaseModel): """ BasquePig """ # noqa: E501 - class_name: StrictStr = Field(alias="className") + class_name: StrictStr = Field(alias="class'\"\\Name") color: StrictStr - __properties: ClassVar[List[str]] = ["className", "color"] + __properties: ClassVar[List[str]] = ["class'\"\\Name", "color"] model_config = ConfigDict( validate_by_name=True, @@ -82,7 +82,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "className": obj.get("className"), + "class'\"\\Name": obj.get("class'\"\\Name"), "color": obj.get("color") }) return _obj diff --git a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/danish_pig.py b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/danish_pig.py index ed51566a659e..ad3e5496cbd1 100644 --- a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/danish_pig.py +++ b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/danish_pig.py @@ -27,9 +27,9 @@ class DanishPig(BaseModel): """ DanishPig """ # noqa: E501 - class_name: StrictStr = Field(alias="className") + class_name: StrictStr = Field(alias="class'\"\\Name") size: StrictInt - __properties: ClassVar[List[str]] = ["className", "size"] + __properties: ClassVar[List[str]] = ["class'\"\\Name", "size"] model_config = ConfigDict( validate_by_name=True, @@ -82,7 +82,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "className": obj.get("className"), + "class'\"\\Name": obj.get("class'\"\\Name"), "size": obj.get("size") }) return _obj diff --git a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/discriminator_all_of_sub.py b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/discriminator_all_of_sub.py index 987dae7f5c32..f5a0aa665e7f 100644 --- a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/discriminator_all_of_sub.py +++ b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/discriminator_all_of_sub.py @@ -28,7 +28,7 @@ class DiscriminatorAllOfSub(DiscriminatorAllOfSuper): """ DiscriminatorAllOfSub """ # noqa: E501 - __properties: ClassVar[List[str]] = ["elementType"] + __properties: ClassVar[List[str]] = ["element'\"\\Type"] model_config = ConfigDict( validate_by_name=True, @@ -81,7 +81,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "elementType": obj.get("elementType") + "element'\"\\Type": obj.get("element'\"\\Type") }) return _obj diff --git a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/discriminator_all_of_super.py b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/discriminator_all_of_super.py index 661015629f41..ef7f96a4b4c3 100644 --- a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/discriminator_all_of_super.py +++ b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/discriminator_all_of_super.py @@ -32,8 +32,8 @@ class DiscriminatorAllOfSuper(BaseModel): """ DiscriminatorAllOfSuper """ # noqa: E501 - element_type: StrictStr = Field(alias="elementType") - __properties: ClassVar[List[str]] = ["elementType"] + element_type: StrictStr = Field(alias="element'\"\\Type") + __properties: ClassVar[List[str]] = ["element'\"\\Type"] model_config = ConfigDict( validate_by_name=True, @@ -44,11 +44,11 @@ class DiscriminatorAllOfSuper(BaseModel): # JSON field name that stores the object type - __discriminator_property_name: ClassVar[str] = 'elementType' + __discriminator_property_name: ClassVar[str] = 'element\'"\\Type' # discriminator mappings __discriminator_value_class_map: ClassVar[Dict[str, str]] = { - 'DiscriminatorAllOfSub': 'DiscriminatorAllOfSub' + 'sub\'"\\kind\nvalue': 'DiscriminatorAllOfSub' } @classmethod diff --git a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/with_nested_one_of.py b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/with_nested_one_of.py index 4f2003d80cc3..c85fa5963a75 100644 --- a/samples/openapi3/client/petstore/python-httpx/petstore_api/models/with_nested_one_of.py +++ b/samples/openapi3/client/petstore/python-httpx/petstore_api/models/with_nested_one_of.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, StrictInt +from pydantic import BaseModel, ConfigDict, Field, StrictInt from typing import Any, ClassVar, Dict, List, Optional from petstore_api.models.one_of_enum_string import OneOfEnumString from petstore_api.models.pig import Pig @@ -30,9 +30,9 @@ class WithNestedOneOf(BaseModel): WithNestedOneOf """ # noqa: E501 size: Optional[StrictInt] = None - nested_pig: Optional[Pig] = None + nested_pig: Optional[Pig] = Field(default=None, alias="nested_\npig") nested_oneof_enum_string: Optional[OneOfEnumString] = None - __properties: ClassVar[List[str]] = ["size", "nested_pig", "nested_oneof_enum_string"] + __properties: ClassVar[List[str]] = ["size", "nested_\npig", "nested_oneof_enum_string"] model_config = ConfigDict( validate_by_name=True, @@ -75,7 +75,7 @@ def to_dict(self) -> Dict[str, Any]: ) # override the default output from pydantic by calling `to_dict()` of nested_pig if self.nested_pig: - _dict['nested_pig'] = self.nested_pig.to_dict() + _dict['nested_\npig'] = self.nested_pig.to_dict() return _dict @classmethod @@ -89,7 +89,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "size": obj.get("size"), - "nested_pig": Pig.from_dict(obj["nested_pig"]) if obj.get("nested_pig") is not None else None, + "nested_\npig": Pig.from_dict(obj["nested_\npig"]) if obj.get("nested_\npig") is not None else None, "nested_oneof_enum_string": obj.get("nested_oneof_enum_string") }) return _obj diff --git a/samples/openapi3/client/petstore/python-httpx/tests/test_model.py b/samples/openapi3/client/petstore/python-httpx/tests/test_model.py index 0ef8d9956a78..8c51faeecb93 100644 --- a/samples/openapi3/client/petstore/python-httpx/tests/test_model.py +++ b/samples/openapi3/client/petstore/python-httpx/tests/test_model.py @@ -75,14 +75,18 @@ def test_equal(self): self.assertFalse(self.pet1 == self.pet2) def test_oneOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new Pig new_pig = petstore_api.Pig() self.assertEqual("null", new_pig.to_json()) self.assertEqual(None, new_pig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.Pig.from_json(json_str) + p = petstore_api.Pig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -113,11 +117,20 @@ def test_oneOf(self): self.assertIn("Input should be a valid dictionary or instance of DanishPig", str(e)) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) # test nested property - nested = petstore_api.WithNestedOneOf(size = 1, nested_pig = p) - self.assertEqual(nested.to_json(), '{"size": 1, "nested_pig": {"className": "BasquePig", "color": "red"}}') + nested_wire_name = "nested_\npig" + nested = petstore_api.WithNestedOneOf.from_dict({ + "size": 1, + nested_wire_name: wire_value, + }) + assert nested is not None + self.assertEqual( + nested.to_json(), + json.dumps({"size": 1, nested_wire_name: wire_value}), + ) + self.assertEqual(nested.to_dict()[nested_wire_name], wire_value) nested_json = nested.to_json() nested2 = petstore_api.WithNestedOneOf.from_json(nested_json) @@ -125,14 +138,18 @@ def test_oneOf(self): self.assertEqual(nested2.to_json(), nested_json) def test_anyOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new AnyOfPig new_anypig = petstore_api.AnyOfPig() self.assertEqual("null", new_anypig.to_json()) self.assertEqual(None, new_anypig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.AnyOfPig.from_json(json_str) + p = petstore_api.AnyOfPig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -168,7 +185,7 @@ def test_anyOf(self): self.assertIn("Input should be a valid dictionary or instance of DanishPig", str(e)) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) def test_inheritance(self): dog = petstore_api.Dog(breed="bulldog", className="dog", color="white") diff --git a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/basque_pig.py b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/basque_pig.py index d61619ca2efb..6517a2ec8a68 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/basque_pig.py +++ b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/basque_pig.py @@ -27,10 +27,10 @@ class BasquePig(BaseModel): """ BasquePig """ # noqa: E501 - class_name: StrictStr = Field(alias="className") + class_name: StrictStr = Field(alias="class'\"\\Name") color: StrictStr additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["className", "color"] + __properties: ClassVar[List[str]] = ["class'\"\\Name", "color"] model_config = ConfigDict( validate_by_name=True, @@ -90,7 +90,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "className": obj.get("className"), + "class'\"\\Name": obj.get("class'\"\\Name"), "color": obj.get("color") }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/danish_pig.py b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/danish_pig.py index 0f9f43773ae7..8450424cb228 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/danish_pig.py +++ b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/danish_pig.py @@ -27,10 +27,10 @@ class DanishPig(BaseModel): """ DanishPig """ # noqa: E501 - class_name: StrictStr = Field(alias="className") + class_name: StrictStr = Field(alias="class'\"\\Name") size: StrictInt additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["className", "size"] + __properties: ClassVar[List[str]] = ["class'\"\\Name", "size"] model_config = ConfigDict( validate_by_name=True, @@ -90,7 +90,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "className": obj.get("className"), + "class'\"\\Name": obj.get("class'\"\\Name"), "size": obj.get("size") }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/discriminator_all_of_sub.py b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/discriminator_all_of_sub.py index 2250170a4633..b9d520df11e3 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/discriminator_all_of_sub.py +++ b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/discriminator_all_of_sub.py @@ -29,7 +29,7 @@ class DiscriminatorAllOfSub(DiscriminatorAllOfSuper): DiscriminatorAllOfSub """ # noqa: E501 additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["elementType"] + __properties: ClassVar[List[str]] = ["element'\"\\Type"] model_config = ConfigDict( validate_by_name=True, @@ -89,7 +89,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "elementType": obj.get("elementType") + "element'\"\\Type": obj.get("element'\"\\Type") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/discriminator_all_of_super.py b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/discriminator_all_of_super.py index 5dcc0b569e8f..912682452989 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/discriminator_all_of_super.py +++ b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/discriminator_all_of_super.py @@ -32,9 +32,9 @@ class DiscriminatorAllOfSuper(BaseModel): """ DiscriminatorAllOfSuper """ # noqa: E501 - element_type: StrictStr = Field(alias="elementType") + element_type: StrictStr = Field(alias="element'\"\\Type") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["elementType"] + __properties: ClassVar[List[str]] = ["element'\"\\Type"] model_config = ConfigDict( validate_by_name=True, @@ -45,11 +45,11 @@ class DiscriminatorAllOfSuper(BaseModel): # JSON field name that stores the object type - __discriminator_property_name: ClassVar[str] = 'elementType' + __discriminator_property_name: ClassVar[str] = 'element\'"\\Type' # discriminator mappings __discriminator_value_class_map: ClassVar[Dict[str, str]] = { - 'DiscriminatorAllOfSub': 'DiscriminatorAllOfSub' + 'sub\'"\\kind\nvalue': 'DiscriminatorAllOfSub' } @classmethod diff --git a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/pig.py b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/pig.py index 06798245b8fe..8f9306304c66 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/pig.py +++ b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/pig.py @@ -91,17 +91,18 @@ def from_json(cls, json_str: str) -> Self: match = 0 # use oneOf discriminator to lookup the data type - _data_type = json.loads(json_str).get("className") + _discriminator_property = "class'\"\\Name" + _data_type = json.loads(json_str).get(_discriminator_property) if not _data_type: - raise ValueError("Failed to lookup data type from the field `className` in the input.") + raise ValueError(f"Failed to lookup data type from the field `{_discriminator_property}` in the input.") # check if data type is `BasquePig` - if _data_type == "BasquePig": + if _data_type == "basque'\"\\pig\nkind": instance.actual_instance = BasquePig.from_json(json_str) return instance # check if data type is `DanishPig` - if _data_type == "DanishPig": + if _data_type == "danish": instance.actual_instance = DanishPig.from_json(json_str) return instance diff --git a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/with_nested_one_of.py b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/with_nested_one_of.py index d3127ac468c0..cdd98e975f82 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/with_nested_one_of.py +++ b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/with_nested_one_of.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, StrictInt +from pydantic import BaseModel, ConfigDict, Field, StrictInt from typing import Any, ClassVar, Dict, List, Optional from petstore_api.models.one_of_enum_string import OneOfEnumString from petstore_api.models.pig import Pig @@ -30,10 +30,10 @@ class WithNestedOneOf(BaseModel): WithNestedOneOf """ # noqa: E501 size: Optional[StrictInt] = None - nested_pig: Optional[Pig] = None + nested_pig: Optional[Pig] = Field(default=None, alias="nested_\npig") nested_oneof_enum_string: Optional[OneOfEnumString] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["size", "nested_pig", "nested_oneof_enum_string"] + __properties: ClassVar[List[str]] = ["size", "nested_\npig", "nested_oneof_enum_string"] model_config = ConfigDict( validate_by_name=True, @@ -78,7 +78,7 @@ def to_dict(self) -> Dict[str, Any]: ) # override the default output from pydantic by calling `to_dict()` of nested_pig if self.nested_pig: - _dict['nested_pig'] = self.nested_pig.to_dict() + _dict['nested_\npig'] = self.nested_pig.to_dict() # override the default output from pydantic by calling `to_dict()` of nested_oneof_enum_string if self.nested_oneof_enum_string: _dict['nested_oneof_enum_string'] = self.nested_oneof_enum_string.to_dict() @@ -100,7 +100,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "size": obj.get("size"), - "nested_pig": Pig.from_dict(obj["nested_pig"]) if obj.get("nested_pig") is not None else None, + "nested_\npig": Pig.from_dict(obj["nested_\npig"]) if obj.get("nested_\npig") is not None else None, "nested_oneof_enum_string": OneOfEnumString.from_dict(obj["nested_oneof_enum_string"]) if obj.get("nested_oneof_enum_string") is not None else None }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python-lazyImports/tests/test_deserialization.py b/samples/openapi3/client/petstore/python-lazyImports/tests/test_deserialization.py index a8ebc21126cd..de8a27134fcc 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/tests/test_deserialization.py +++ b/samples/openapi3/client/petstore/python-lazyImports/tests/test_deserialization.py @@ -253,8 +253,10 @@ def test_deserialize_none(self): def test_deserialize_pig(self): """ deserialize pig (oneOf) """ + wire_name = """class'"\\Name""" + mapping_value = """basque'"\\pig\nkind""" data = { - "className": "BasqueBig", + wire_name: mapping_value, "color": "white" } @@ -262,7 +264,7 @@ def test_deserialize_pig(self): deserialized = self.deserialize(response, "Pig", 'application/json') self.assertTrue(isinstance(deserialized.actual_instance, petstore_api.BasquePig)) - self.assertEqual(deserialized.actual_instance.class_name, "BasqueBig") + self.assertEqual(deserialized.actual_instance.class_name, mapping_value) self.assertEqual(deserialized.actual_instance.color, "white") def test_deserialize_animal(self): diff --git a/samples/openapi3/client/petstore/python-lazyImports/tests/test_model.py b/samples/openapi3/client/petstore/python-lazyImports/tests/test_model.py index 5daf9cf2aa5f..7648a65617cb 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/tests/test_model.py +++ b/samples/openapi3/client/petstore/python-lazyImports/tests/test_model.py @@ -212,15 +212,25 @@ def test_anyOf_array_of_integers(self): self.assertIn("Input should be less than or equal to 255", str(e)) def test_oneOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + + # Both schemas accept this payload, so only discriminator dispatch can + # select BasquePig without a multiple-match error. + mapped = petstore_api.Pig.from_json(json.dumps({**wire_value, "size": 1})) + self.assertIsInstance(mapped.actual_instance, petstore_api.BasquePig) + # test new Pig - bp = petstore_api.BasquePig.from_dict({"className": "BasquePig", "color": "red"}) + bp = petstore_api.BasquePig.from_dict(wire_value) new_pig = petstore_api.Pig() self.assertEqual("null", new_pig.to_json()) self.assertEqual(None, new_pig.actual_instance) new_pig2 = petstore_api.Pig(actual_instance=bp) - self.assertEqual('{"className": "BasquePig", "color": "red"}', new_pig2.to_json()) + self.assertEqual(wire_json, new_pig2.to_json()) new_pig3 = petstore_api.Pig(bp) - self.assertEqual('{"className": "BasquePig", "color": "red"}', new_pig3.to_json()) + self.assertEqual(wire_json, new_pig3.to_json()) try: new_pig4 = petstore_api.Pig(bp, actual_instance=bp) except ValueError as e: @@ -231,13 +241,11 @@ def test_oneOf(self): self.assertTrue("If position argument is used, only 1 is allowed to set `actual_instance`", str(e)) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.Pig.from_json(json_str) + p = petstore_api.Pig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test from_dict - json_dict = {"className": "BasquePig", "color": "red"} - p = petstore_api.Pig.from_dict(json_dict) + p = petstore_api.Pig.from_dict(wire_value) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -278,11 +286,20 @@ def test_oneOf(self): # self.assertEqual(str(e), error_message) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) # test nested property - nested = petstore_api.WithNestedOneOf(size = 1, nested_pig = p) - self.assertEqual(nested.to_json(), '{"size": 1, "nested_pig": {"className": "BasquePig", "color": "red"}}') + nested_wire_name = "nested_\npig" + nested = petstore_api.WithNestedOneOf.from_dict({ + "size": 1, + nested_wire_name: wire_value, + }) + assert nested is not None + self.assertEqual( + nested.to_json(), + json.dumps({"size": 1, nested_wire_name: wire_value}), + ) + self.assertEqual(nested.to_dict()[nested_wire_name], wire_value) nested_json = nested.to_json() nested2 = petstore_api.WithNestedOneOf.from_json(nested_json) @@ -290,19 +307,22 @@ def test_oneOf(self): self.assertEqual(nested2.to_json(), nested_json) def test_anyOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new AnyOfPig new_anypig = petstore_api.AnyOfPig() self.assertEqual("null", new_anypig.to_json()) self.assertEqual(None, new_anypig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.AnyOfPig.from_json(json_str) + p = petstore_api.AnyOfPig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test from_dict - json_dict = {"className": "BasquePig", "color": "red"} - p = petstore_api.AnyOfPig.from_dict(json_dict) + p = petstore_api.AnyOfPig.from_dict(wire_value) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -331,7 +351,7 @@ def test_anyOf(self): self.assertIn("No match found when deserializing the JSON string into AnyOfPig with anyOf schemas: BasquePig, DanishPig", str(e)) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) def test_inheritance(self): dog = petstore_api.Dog(breed="bulldog", className="dog", color="white") @@ -345,7 +365,11 @@ def test_inheritance(self): self.assertEqual(dog2.color, 'white') def test_inheritance_discriminators(self): - model = petstore_api.DiscriminatorAllOfSuper.from_dict({"elementType": "DiscriminatorAllOfSub"}) + mapping_value = """sub'"\\kind\nvalue""" + wire_name = """element'"\\Type""" + model = petstore_api.DiscriminatorAllOfSuper.from_dict( + {wire_name: mapping_value} + ) self.assertIsInstance(model, petstore_api.DiscriminatorAllOfSub) def test_list(self): diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/basque_pig.py b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/basque_pig.py index 6efcc0a9b659..95431dab1a1b 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/basque_pig.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/basque_pig.py @@ -25,9 +25,9 @@ class BasquePig(BaseModel): """ BasquePig """ - class_name: StrictStr = Field(default=..., alias="className") + class_name: StrictStr = Field(default=..., alias="class'\"\\Name") color: StrictStr = Field(...) - __properties = ["className", "color"] + __properties = ["class'\"\\Name", "color"] class Config: """Pydantic configuration""" @@ -65,7 +65,7 @@ def from_dict(cls, obj: dict) -> BasquePig: return BasquePig.parse_obj(obj) _obj = BasquePig.parse_obj({ - "class_name": obj.get("className"), + "class_name": obj.get("class'\"\\Name"), "color": obj.get("color") }) return _obj diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/danish_pig.py b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/danish_pig.py index b53aa7221874..485801aaf984 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/danish_pig.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/danish_pig.py @@ -25,9 +25,9 @@ class DanishPig(BaseModel): """ DanishPig """ - class_name: StrictStr = Field(default=..., alias="className") + class_name: StrictStr = Field(default=..., alias="class'\"\\Name") size: StrictInt = Field(...) - __properties = ["className", "size"] + __properties = ["class'\"\\Name", "size"] class Config: """Pydantic configuration""" @@ -65,7 +65,7 @@ def from_dict(cls, obj: dict) -> DanishPig: return DanishPig.parse_obj(obj) _obj = DanishPig.parse_obj({ - "class_name": obj.get("className"), + "class_name": obj.get("class'\"\\Name"), "size": obj.get("size") }) return _obj diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/discriminator_all_of_sub.py b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/discriminator_all_of_sub.py index 65d54ea8d1a6..c3abaceb8bc7 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/discriminator_all_of_sub.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/discriminator_all_of_sub.py @@ -26,7 +26,7 @@ class DiscriminatorAllOfSub(DiscriminatorAllOfSuper): """ DiscriminatorAllOfSub """ - __properties = ["elementType"] + __properties = ["element'\"\\Type"] class Config: """Pydantic configuration""" @@ -64,7 +64,7 @@ def from_dict(cls, obj: dict) -> DiscriminatorAllOfSub: return DiscriminatorAllOfSub.parse_obj(obj) _obj = DiscriminatorAllOfSub.parse_obj({ - "element_type": obj.get("elementType") + "element_type": obj.get("element'\"\\Type") }) return _obj diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/discriminator_all_of_super.py b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/discriminator_all_of_super.py index 81fb3f689e8a..fafa534cc243 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/discriminator_all_of_super.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/discriminator_all_of_super.py @@ -30,8 +30,8 @@ class DiscriminatorAllOfSuper(BaseModel): """ DiscriminatorAllOfSuper """ - element_type: StrictStr = Field(default=..., alias="elementType") - __properties = ["elementType"] + element_type: StrictStr = Field(default=..., alias="element'\"\\Type") + __properties = ["element'\"\\Type"] class Config: """Pydantic configuration""" @@ -39,11 +39,11 @@ class Config: validate_assignment = True # JSON field name that stores the object type - __discriminator_property_name = 'elementType' + __discriminator_property_name = 'element\'"\\Type' # discriminator mappings __discriminator_value_class_map = { - 'DiscriminatorAllOfSub': 'DiscriminatorAllOfSub' + 'sub\'"\\kind\nvalue': 'DiscriminatorAllOfSub' } @classmethod diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/with_nested_one_of.py b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/with_nested_one_of.py index 2fa98ce371e2..6fd79c69b5c9 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/with_nested_one_of.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/with_nested_one_of.py @@ -19,7 +19,7 @@ from typing import Optional -from pydantic import BaseModel, StrictInt +from pydantic import BaseModel, Field, StrictInt from petstore_api.models.one_of_enum_string import OneOfEnumString from petstore_api.models.pig import Pig @@ -28,9 +28,9 @@ class WithNestedOneOf(BaseModel): WithNestedOneOf """ size: Optional[StrictInt] = None - nested_pig: Optional[Pig] = None + nested_pig: Optional[Pig] = Field(default=None, alias="nested_\npig") nested_oneof_enum_string: Optional[OneOfEnumString] = None - __properties = ["size", "nested_pig", "nested_oneof_enum_string"] + __properties = ["size", "nested_\npig", "nested_oneof_enum_string"] class Config: """Pydantic configuration""" @@ -58,7 +58,7 @@ def to_dict(self): exclude_none=True) # override the default output from pydantic by calling `to_dict()` of nested_pig if self.nested_pig: - _dict['nested_pig'] = self.nested_pig.to_dict() + _dict['nested_\npig'] = self.nested_pig.to_dict() return _dict @classmethod @@ -72,7 +72,7 @@ def from_dict(cls, obj: dict) -> WithNestedOneOf: _obj = WithNestedOneOf.parse_obj({ "size": obj.get("size"), - "nested_pig": Pig.from_dict(obj.get("nested_pig")) if obj.get("nested_pig") is not None else None, + "nested_pig": Pig.from_dict(obj.get("nested_\npig")) if obj.get("nested_\npig") is not None else None, "nested_oneof_enum_string": obj.get("nested_oneof_enum_string") }) return _obj diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/tests/test_model.py b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/tests/test_model.py index e81fb1cd3601..8351c7fbd76d 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/tests/test_model.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/tests/test_model.py @@ -71,14 +71,18 @@ def test_equal(self): self.assertFalse(self.pet1 == self.pet2) def test_oneOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new Pig new_pig = petstore_api.Pig() self.assertEqual("null", new_pig.to_json()) self.assertEqual(None, new_pig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.Pig.from_json(json_str) + p = petstore_api.Pig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -109,25 +113,37 @@ def test_oneOf(self): self.assertEqual(str(e), error_message) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) # test nested property - nested = petstore_api.WithNestedOneOf(size = 1, nested_pig = p) - self.assertEqual(nested.to_json(), '{"size": 1, "nested_pig": {"className": "BasquePig", "color": "red"}}') + nested_wire_name = "nested_\npig" + nested = petstore_api.WithNestedOneOf.from_dict({ + "size": 1, + nested_wire_name: wire_value, + }) + self.assertEqual( + nested.to_json(), + json.dumps({"size": 1, nested_wire_name: wire_value}), + ) + self.assertEqual(nested.to_dict()[nested_wire_name], wire_value) nested_json = nested.to_json() nested2 = petstore_api.WithNestedOneOf.from_json(nested_json) self.assertEqual(nested2.to_json(), nested_json) def test_anyOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new AnyOfPig new_anypig = petstore_api.AnyOfPig() self.assertEqual("null", new_anypig.to_json()) self.assertEqual(None, new_anypig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.AnyOfPig.from_json(json_str) + p = petstore_api.AnyOfPig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -159,7 +175,7 @@ def test_anyOf(self): self.assertEqual(str(e), error_message) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) def test_inheritance(self): dog = petstore_api.Dog(breed="bulldog", className="dog", color="white") @@ -171,6 +187,14 @@ def test_inheritance(self): self.assertEqual(dog2.class_name, "dog") self.assertEqual(dog2.color, 'white') + def test_inheritance_discriminators(self): + mapping_value = """sub'"\\kind\nvalue""" + wire_name = """element'"\\Type""" + model = petstore_api.DiscriminatorAllOfSuper.from_dict( + {wire_name: mapping_value} + ) + self.assertIsInstance(model, petstore_api.DiscriminatorAllOfSub) + def test_list(self): # should throw exception as var_123_list should be string try: diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/basque_pig.py b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/basque_pig.py index 00c6cacbb8e8..81fa585a5ace 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/basque_pig.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/basque_pig.py @@ -25,10 +25,10 @@ class BasquePig(BaseModel): """ BasquePig """ - class_name: StrictStr = Field(default=..., alias="className") + class_name: StrictStr = Field(default=..., alias="class'\"\\Name") color: StrictStr = Field(...) additional_properties: Dict[str, Any] = {} - __properties = ["className", "color"] + __properties = ["class'\"\\Name", "color"] class Config: """Pydantic configuration""" @@ -72,7 +72,7 @@ def from_dict(cls, obj: dict) -> BasquePig: return BasquePig.parse_obj(obj) _obj = BasquePig.parse_obj({ - "class_name": obj.get("className"), + "class_name": obj.get("class'\"\\Name"), "color": obj.get("color") }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/danish_pig.py b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/danish_pig.py index 640a2efec2ad..428f59b664e2 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/danish_pig.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/danish_pig.py @@ -25,10 +25,10 @@ class DanishPig(BaseModel): """ DanishPig """ - class_name: StrictStr = Field(default=..., alias="className") + class_name: StrictStr = Field(default=..., alias="class'\"\\Name") size: StrictInt = Field(...) additional_properties: Dict[str, Any] = {} - __properties = ["className", "size"] + __properties = ["class'\"\\Name", "size"] class Config: """Pydantic configuration""" @@ -72,7 +72,7 @@ def from_dict(cls, obj: dict) -> DanishPig: return DanishPig.parse_obj(obj) _obj = DanishPig.parse_obj({ - "class_name": obj.get("className"), + "class_name": obj.get("class'\"\\Name"), "size": obj.get("size") }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/discriminator_all_of_sub.py b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/discriminator_all_of_sub.py index 271339926344..1b074318eca4 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/discriminator_all_of_sub.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/discriminator_all_of_sub.py @@ -27,7 +27,7 @@ class DiscriminatorAllOfSub(DiscriminatorAllOfSuper): DiscriminatorAllOfSub """ additional_properties: Dict[str, Any] = {} - __properties = ["elementType"] + __properties = ["element'\"\\Type"] class Config: """Pydantic configuration""" @@ -71,7 +71,7 @@ def from_dict(cls, obj: dict) -> DiscriminatorAllOfSub: return DiscriminatorAllOfSub.parse_obj(obj) _obj = DiscriminatorAllOfSub.parse_obj({ - "element_type": obj.get("elementType") + "element_type": obj.get("element'\"\\Type") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/discriminator_all_of_super.py b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/discriminator_all_of_super.py index 07b83b0f65c5..3a999265ea86 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/discriminator_all_of_super.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/discriminator_all_of_super.py @@ -30,9 +30,9 @@ class DiscriminatorAllOfSuper(BaseModel): """ DiscriminatorAllOfSuper """ - element_type: StrictStr = Field(default=..., alias="elementType") + element_type: StrictStr = Field(default=..., alias="element'\"\\Type") additional_properties: Dict[str, Any] = {} - __properties = ["elementType"] + __properties = ["element'\"\\Type"] class Config: """Pydantic configuration""" @@ -40,11 +40,11 @@ class Config: validate_assignment = True # JSON field name that stores the object type - __discriminator_property_name = 'elementType' + __discriminator_property_name = 'element\'"\\Type' # discriminator mappings __discriminator_value_class_map = { - 'DiscriminatorAllOfSub': 'DiscriminatorAllOfSub' + 'sub\'"\\kind\nvalue': 'DiscriminatorAllOfSub' } @classmethod diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/pig.py b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/pig.py index 62ae5a2a0ef7..633da3b538b1 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/pig.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/pig.py @@ -93,17 +93,18 @@ def from_json(cls, json_str: str) -> Pig: match = 0 # use oneOf discriminator to lookup the data type - _data_type = json.loads(json_str).get("className") + _discriminator_property = "class'\"\\Name" + _data_type = json.loads(json_str).get(_discriminator_property) if not _data_type: - raise ValueError("Failed to lookup data type from the field `className` in the input.") + raise ValueError(f"Failed to lookup data type from the field `{_discriminator_property}` in the input.") # check if data type is `BasquePig` - if _data_type == "BasquePig": + if _data_type == "basque'\"\\pig\nkind": instance.actual_instance = BasquePig.from_json(json_str) return instance # check if data type is `DanishPig` - if _data_type == "DanishPig": + if _data_type == "danish": instance.actual_instance = DanishPig.from_json(json_str) return instance diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/with_nested_one_of.py b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/with_nested_one_of.py index 8ec40c8eda1e..fcafb51e3dbb 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/with_nested_one_of.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/with_nested_one_of.py @@ -19,7 +19,7 @@ from typing import Any, Dict, Optional -from pydantic import BaseModel, StrictInt +from pydantic import BaseModel, Field, StrictInt from petstore_api.models.one_of_enum_string import OneOfEnumString from petstore_api.models.pig import Pig @@ -28,10 +28,10 @@ class WithNestedOneOf(BaseModel): WithNestedOneOf """ size: Optional[StrictInt] = None - nested_pig: Optional[Pig] = None + nested_pig: Optional[Pig] = Field(default=None, alias="nested_\npig") nested_oneof_enum_string: Optional[OneOfEnumString] = None additional_properties: Dict[str, Any] = {} - __properties = ["size", "nested_pig", "nested_oneof_enum_string"] + __properties = ["size", "nested_\npig", "nested_oneof_enum_string"] class Config: """Pydantic configuration""" @@ -60,7 +60,7 @@ def to_dict(self): exclude_none=True) # override the default output from pydantic by calling `to_dict()` of nested_pig if self.nested_pig: - _dict['nested_pig'] = self.nested_pig.to_dict() + _dict['nested_\npig'] = self.nested_pig.to_dict() # override the default output from pydantic by calling `to_dict()` of nested_oneof_enum_string if self.nested_oneof_enum_string: _dict['nested_oneof_enum_string'] = self.nested_oneof_enum_string.to_dict() @@ -82,7 +82,7 @@ def from_dict(cls, obj: dict) -> WithNestedOneOf: _obj = WithNestedOneOf.parse_obj({ "size": obj.get("size"), - "nested_pig": Pig.from_dict(obj.get("nested_pig")) if obj.get("nested_pig") is not None else None, + "nested_pig": Pig.from_dict(obj.get("nested_\npig")) if obj.get("nested_\npig") is not None else None, "nested_oneof_enum_string": OneOfEnumString.from_dict(obj.get("nested_oneof_enum_string")) if obj.get("nested_oneof_enum_string") is not None else None }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_deserialization.py b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_deserialization.py index c5fb68663821..9d87a3a00453 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_deserialization.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_deserialization.py @@ -245,8 +245,10 @@ def test_deserialize_none(self): def test_deserialize_pig(self): """ deserialize pig (oneOf) """ + wire_name = """class'"\\Name""" + mapping_value = """basque'"\\pig\nkind""" data = { - "className": "BasqueBig", + wire_name: mapping_value, "color": "white" } @@ -254,7 +256,7 @@ def test_deserialize_pig(self): deserialized = self.deserialize(response, "Pig") self.assertTrue(isinstance(deserialized.actual_instance, petstore_api.BasquePig)) - self.assertEqual(deserialized.actual_instance.class_name, "BasqueBig") + self.assertEqual(deserialized.actual_instance.class_name, mapping_value) self.assertEqual(deserialized.actual_instance.color, "white") def test_deserialize_animal(self): diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_model.py b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_model.py index aee61bf79d9b..bc56eba32fe8 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_model.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_model.py @@ -210,15 +210,25 @@ def test_anyOf_array_of_integers(self): self.assertEqual(p.actual_instance, '#123456') def test_oneOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + + # Both schemas accept this payload, so only discriminator dispatch can + # select BasquePig without a multiple-match error. + mapped = petstore_api.Pig.from_json(json.dumps({**wire_value, "size": 1})) + self.assertIsInstance(mapped.actual_instance, petstore_api.BasquePig) + # test new Pig - bp = petstore_api.BasquePig.from_dict({"className": "BasquePig", "color": "red"}) + bp = petstore_api.BasquePig.from_dict(wire_value) new_pig = petstore_api.Pig() self.assertEqual("null", new_pig.to_json()) self.assertEqual(None, new_pig.actual_instance) new_pig2 = petstore_api.Pig(actual_instance=bp) - self.assertEqual('{"className": "BasquePig", "color": "red"}', new_pig2.to_json()) + self.assertEqual(wire_json, new_pig2.to_json()) new_pig3 = petstore_api.Pig(bp) - self.assertEqual('{"className": "BasquePig", "color": "red"}', new_pig3.to_json()) + self.assertEqual(wire_json, new_pig3.to_json()) try: new_pig4 = petstore_api.Pig(bp, actual_instance=bp) except ValueError as e: @@ -229,13 +239,11 @@ def test_oneOf(self): self.assertTrue("If position argument is used, only 1 is allowed to set `actual_instance`", str(e)) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.Pig.from_json(json_str) + p = petstore_api.Pig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test from_dict - json_dict = {"className": "BasquePig", "color": "red"} - p = petstore_api.Pig.from_dict(json_dict) + p = petstore_api.Pig.from_dict(wire_value) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -268,30 +276,41 @@ def test_oneOf(self): # self.assertEqual(str(e), error_message) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) # test nested property - nested = petstore_api.WithNestedOneOf(size = 1, nested_pig = p) - self.assertEqual(nested.to_json(), '{"size": 1, "nested_pig": {"className": "BasquePig", "color": "red"}}') + nested_wire_name = "nested_\npig" + nested = petstore_api.WithNestedOneOf.from_dict({ + "size": 1, + nested_wire_name: wire_value, + }) + self.assertEqual( + nested.to_json(), + json.dumps({"size": 1, nested_wire_name: wire_value}), + ) + self.assertEqual(nested.to_dict()[nested_wire_name], wire_value) nested_json = nested.to_json() nested2 = petstore_api.WithNestedOneOf.from_json(nested_json) self.assertEqual(nested2.to_json(), nested_json) def test_anyOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new AnyOfPig new_anypig = petstore_api.AnyOfPig() self.assertEqual("null", new_anypig.to_json()) self.assertEqual(None, new_anypig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.AnyOfPig.from_json(json_str) + p = petstore_api.AnyOfPig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test from_dict - json_dict = {"className": "BasquePig", "color": "red"} - p = petstore_api.AnyOfPig.from_dict(json_dict) + p = petstore_api.AnyOfPig.from_dict(wire_value) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -323,10 +342,10 @@ def test_anyOf(self): self.assertEqual(str(e), error_message) # test to_dict - self.assertEqual(p.to_dict(), {'className': 'BasquePig', 'color': 'red'}) + self.assertEqual(p.to_dict(), wire_value) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) def test_inheritance(self): dog = petstore_api.Dog(breed="bulldog", className="dog", color="white") @@ -338,6 +357,14 @@ def test_inheritance(self): self.assertEqual(dog2.class_name, "dog") self.assertEqual(dog2.color, 'white') + def test_inheritance_discriminators(self): + mapping_value = """sub'"\\kind\nvalue""" + wire_name = """element'"\\Type""" + model = petstore_api.DiscriminatorAllOfSuper.from_dict( + {wire_name: mapping_value} + ) + self.assertIsInstance(model, petstore_api.DiscriminatorAllOfSub) + def test_list(self): # should throw exception as var_123_list should be string try: @@ -611,4 +638,4 @@ def test_empty_list(self): def test_single_string_item(self): value = {"b": [petstore_api.CreatureInfo(name="creature_name")]} a = petstore_api.UnnamedDictWithAdditionalModelListProperties(dict_property=value) - assert a.to_dict() == {"dictProperty": {"b": [{"name": "creature_name"}]}} \ No newline at end of file + assert a.to_dict() == {"dictProperty": {"b": [{"name": "creature_name"}]}} diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/basque_pig.py b/samples/openapi3/client/petstore/python/petstore_api/models/basque_pig.py index d61619ca2efb..6517a2ec8a68 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/basque_pig.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/basque_pig.py @@ -27,10 +27,10 @@ class BasquePig(BaseModel): """ BasquePig """ # noqa: E501 - class_name: StrictStr = Field(alias="className") + class_name: StrictStr = Field(alias="class'\"\\Name") color: StrictStr additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["className", "color"] + __properties: ClassVar[List[str]] = ["class'\"\\Name", "color"] model_config = ConfigDict( validate_by_name=True, @@ -90,7 +90,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "className": obj.get("className"), + "class'\"\\Name": obj.get("class'\"\\Name"), "color": obj.get("color") }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/danish_pig.py b/samples/openapi3/client/petstore/python/petstore_api/models/danish_pig.py index 0f9f43773ae7..8450424cb228 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/danish_pig.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/danish_pig.py @@ -27,10 +27,10 @@ class DanishPig(BaseModel): """ DanishPig """ # noqa: E501 - class_name: StrictStr = Field(alias="className") + class_name: StrictStr = Field(alias="class'\"\\Name") size: StrictInt additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["className", "size"] + __properties: ClassVar[List[str]] = ["class'\"\\Name", "size"] model_config = ConfigDict( validate_by_name=True, @@ -90,7 +90,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "className": obj.get("className"), + "class'\"\\Name": obj.get("class'\"\\Name"), "size": obj.get("size") }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/discriminator_all_of_sub.py b/samples/openapi3/client/petstore/python/petstore_api/models/discriminator_all_of_sub.py index 2250170a4633..b9d520df11e3 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/discriminator_all_of_sub.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/discriminator_all_of_sub.py @@ -29,7 +29,7 @@ class DiscriminatorAllOfSub(DiscriminatorAllOfSuper): DiscriminatorAllOfSub """ # noqa: E501 additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["elementType"] + __properties: ClassVar[List[str]] = ["element'\"\\Type"] model_config = ConfigDict( validate_by_name=True, @@ -89,7 +89,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "elementType": obj.get("elementType") + "element'\"\\Type": obj.get("element'\"\\Type") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/discriminator_all_of_super.py b/samples/openapi3/client/petstore/python/petstore_api/models/discriminator_all_of_super.py index 5dcc0b569e8f..912682452989 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/discriminator_all_of_super.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/discriminator_all_of_super.py @@ -32,9 +32,9 @@ class DiscriminatorAllOfSuper(BaseModel): """ DiscriminatorAllOfSuper """ # noqa: E501 - element_type: StrictStr = Field(alias="elementType") + element_type: StrictStr = Field(alias="element'\"\\Type") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["elementType"] + __properties: ClassVar[List[str]] = ["element'\"\\Type"] model_config = ConfigDict( validate_by_name=True, @@ -45,11 +45,11 @@ class DiscriminatorAllOfSuper(BaseModel): # JSON field name that stores the object type - __discriminator_property_name: ClassVar[str] = 'elementType' + __discriminator_property_name: ClassVar[str] = 'element\'"\\Type' # discriminator mappings __discriminator_value_class_map: ClassVar[Dict[str, str]] = { - 'DiscriminatorAllOfSub': 'DiscriminatorAllOfSub' + 'sub\'"\\kind\nvalue': 'DiscriminatorAllOfSub' } @classmethod diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/pig.py b/samples/openapi3/client/petstore/python/petstore_api/models/pig.py index 06798245b8fe..8f9306304c66 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/pig.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/pig.py @@ -91,17 +91,18 @@ def from_json(cls, json_str: str) -> Self: match = 0 # use oneOf discriminator to lookup the data type - _data_type = json.loads(json_str).get("className") + _discriminator_property = "class'\"\\Name" + _data_type = json.loads(json_str).get(_discriminator_property) if not _data_type: - raise ValueError("Failed to lookup data type from the field `className` in the input.") + raise ValueError(f"Failed to lookup data type from the field `{_discriminator_property}` in the input.") # check if data type is `BasquePig` - if _data_type == "BasquePig": + if _data_type == "basque'\"\\pig\nkind": instance.actual_instance = BasquePig.from_json(json_str) return instance # check if data type is `DanishPig` - if _data_type == "DanishPig": + if _data_type == "danish": instance.actual_instance = DanishPig.from_json(json_str) return instance diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/with_nested_one_of.py b/samples/openapi3/client/petstore/python/petstore_api/models/with_nested_one_of.py index d3127ac468c0..cdd98e975f82 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/with_nested_one_of.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/with_nested_one_of.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, StrictInt +from pydantic import BaseModel, ConfigDict, Field, StrictInt from typing import Any, ClassVar, Dict, List, Optional from petstore_api.models.one_of_enum_string import OneOfEnumString from petstore_api.models.pig import Pig @@ -30,10 +30,10 @@ class WithNestedOneOf(BaseModel): WithNestedOneOf """ # noqa: E501 size: Optional[StrictInt] = None - nested_pig: Optional[Pig] = None + nested_pig: Optional[Pig] = Field(default=None, alias="nested_\npig") nested_oneof_enum_string: Optional[OneOfEnumString] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["size", "nested_pig", "nested_oneof_enum_string"] + __properties: ClassVar[List[str]] = ["size", "nested_\npig", "nested_oneof_enum_string"] model_config = ConfigDict( validate_by_name=True, @@ -78,7 +78,7 @@ def to_dict(self) -> Dict[str, Any]: ) # override the default output from pydantic by calling `to_dict()` of nested_pig if self.nested_pig: - _dict['nested_pig'] = self.nested_pig.to_dict() + _dict['nested_\npig'] = self.nested_pig.to_dict() # override the default output from pydantic by calling `to_dict()` of nested_oneof_enum_string if self.nested_oneof_enum_string: _dict['nested_oneof_enum_string'] = self.nested_oneof_enum_string.to_dict() @@ -100,7 +100,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "size": obj.get("size"), - "nested_pig": Pig.from_dict(obj["nested_pig"]) if obj.get("nested_pig") is not None else None, + "nested_\npig": Pig.from_dict(obj["nested_\npig"]) if obj.get("nested_\npig") is not None else None, "nested_oneof_enum_string": OneOfEnumString.from_dict(obj["nested_oneof_enum_string"]) if obj.get("nested_oneof_enum_string") is not None else None }) # store additional fields in additional_properties diff --git a/samples/openapi3/client/petstore/python/tests/test_deserialization.py b/samples/openapi3/client/petstore/python/tests/test_deserialization.py index a8ebc21126cd..de8a27134fcc 100644 --- a/samples/openapi3/client/petstore/python/tests/test_deserialization.py +++ b/samples/openapi3/client/petstore/python/tests/test_deserialization.py @@ -253,8 +253,10 @@ def test_deserialize_none(self): def test_deserialize_pig(self): """ deserialize pig (oneOf) """ + wire_name = """class'"\\Name""" + mapping_value = """basque'"\\pig\nkind""" data = { - "className": "BasqueBig", + wire_name: mapping_value, "color": "white" } @@ -262,7 +264,7 @@ def test_deserialize_pig(self): deserialized = self.deserialize(response, "Pig", 'application/json') self.assertTrue(isinstance(deserialized.actual_instance, petstore_api.BasquePig)) - self.assertEqual(deserialized.actual_instance.class_name, "BasqueBig") + self.assertEqual(deserialized.actual_instance.class_name, mapping_value) self.assertEqual(deserialized.actual_instance.color, "white") def test_deserialize_animal(self): diff --git a/samples/openapi3/client/petstore/python/tests/test_model.py b/samples/openapi3/client/petstore/python/tests/test_model.py index 5daf9cf2aa5f..7648a65617cb 100644 --- a/samples/openapi3/client/petstore/python/tests/test_model.py +++ b/samples/openapi3/client/petstore/python/tests/test_model.py @@ -212,15 +212,25 @@ def test_anyOf_array_of_integers(self): self.assertIn("Input should be less than or equal to 255", str(e)) def test_oneOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + + # Both schemas accept this payload, so only discriminator dispatch can + # select BasquePig without a multiple-match error. + mapped = petstore_api.Pig.from_json(json.dumps({**wire_value, "size": 1})) + self.assertIsInstance(mapped.actual_instance, petstore_api.BasquePig) + # test new Pig - bp = petstore_api.BasquePig.from_dict({"className": "BasquePig", "color": "red"}) + bp = petstore_api.BasquePig.from_dict(wire_value) new_pig = petstore_api.Pig() self.assertEqual("null", new_pig.to_json()) self.assertEqual(None, new_pig.actual_instance) new_pig2 = petstore_api.Pig(actual_instance=bp) - self.assertEqual('{"className": "BasquePig", "color": "red"}', new_pig2.to_json()) + self.assertEqual(wire_json, new_pig2.to_json()) new_pig3 = petstore_api.Pig(bp) - self.assertEqual('{"className": "BasquePig", "color": "red"}', new_pig3.to_json()) + self.assertEqual(wire_json, new_pig3.to_json()) try: new_pig4 = petstore_api.Pig(bp, actual_instance=bp) except ValueError as e: @@ -231,13 +241,11 @@ def test_oneOf(self): self.assertTrue("If position argument is used, only 1 is allowed to set `actual_instance`", str(e)) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.Pig.from_json(json_str) + p = petstore_api.Pig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test from_dict - json_dict = {"className": "BasquePig", "color": "red"} - p = petstore_api.Pig.from_dict(json_dict) + p = petstore_api.Pig.from_dict(wire_value) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -278,11 +286,20 @@ def test_oneOf(self): # self.assertEqual(str(e), error_message) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) # test nested property - nested = petstore_api.WithNestedOneOf(size = 1, nested_pig = p) - self.assertEqual(nested.to_json(), '{"size": 1, "nested_pig": {"className": "BasquePig", "color": "red"}}') + nested_wire_name = "nested_\npig" + nested = petstore_api.WithNestedOneOf.from_dict({ + "size": 1, + nested_wire_name: wire_value, + }) + assert nested is not None + self.assertEqual( + nested.to_json(), + json.dumps({"size": 1, nested_wire_name: wire_value}), + ) + self.assertEqual(nested.to_dict()[nested_wire_name], wire_value) nested_json = nested.to_json() nested2 = petstore_api.WithNestedOneOf.from_json(nested_json) @@ -290,19 +307,22 @@ def test_oneOf(self): self.assertEqual(nested2.to_json(), nested_json) def test_anyOf(self): + mapping_value = """basque'"\\pig\nkind""" + wire_name = """class'"\\Name""" + wire_value = {wire_name: mapping_value, "color": "red"} + wire_json = json.dumps(wire_value) + # test new AnyOfPig new_anypig = petstore_api.AnyOfPig() self.assertEqual("null", new_anypig.to_json()) self.assertEqual(None, new_anypig.actual_instance) # test from_json - json_str = '{"className": "BasquePig", "color": "red"}' - p = petstore_api.AnyOfPig.from_json(json_str) + p = petstore_api.AnyOfPig.from_json(wire_json) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test from_dict - json_dict = {"className": "BasquePig", "color": "red"} - p = petstore_api.AnyOfPig.from_dict(json_dict) + p = petstore_api.AnyOfPig.from_dict(wire_value) self.assertIsInstance(p.actual_instance, petstore_api.BasquePig) # test init @@ -331,7 +351,7 @@ def test_anyOf(self): self.assertIn("No match found when deserializing the JSON string into AnyOfPig with anyOf schemas: BasquePig, DanishPig", str(e)) # test to_json - self.assertEqual(p.to_json(), '{"className": "BasquePig", "color": "red"}') + self.assertEqual(p.to_json(), wire_json) def test_inheritance(self): dog = petstore_api.Dog(breed="bulldog", className="dog", color="white") @@ -345,7 +365,11 @@ def test_inheritance(self): self.assertEqual(dog2.color, 'white') def test_inheritance_discriminators(self): - model = petstore_api.DiscriminatorAllOfSuper.from_dict({"elementType": "DiscriminatorAllOfSub"}) + mapping_value = """sub'"\\kind\nvalue""" + wire_name = """element'"\\Type""" + model = petstore_api.DiscriminatorAllOfSuper.from_dict( + {wire_name: mapping_value} + ) self.assertIsInstance(model, petstore_api.DiscriminatorAllOfSub) def test_list(self):