Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,23 @@ private String getPydanticType(CodegenParameter cp,
}

if (cp.isArray) {
typingImports.add("List");
return String.format(Locale.ROOT, "List[%s]", getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports));
if (cp.maxItems != null || cp.minItems != null) {
String maxOrMinItems = "";
if (cp.maxItems != null) {
maxOrMinItems += String.format(Locale.ROOT, ", max_items=%d", cp.maxItems);
}
if (cp.minItems != null) {
maxOrMinItems += String.format(Locale.ROOT, ", min_items=%d", cp.minItems);
}
pydanticImports.add("conlist");
return String.format(Locale.ROOT, "conlist(%s%s)",
getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports),
maxOrMinItems);

} else {
typingImports.add("List");
return String.format(Locale.ROOT, "List[%s]", getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports));
}
} else if (cp.isMap) {
typingImports.add("Dict");
return String.format(Locale.ROOT, "Dict[str, %s]", getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports));
Expand Down Expand Up @@ -638,8 +653,22 @@ private String getPydanticType(CodegenProperty cp,
return String.format(Locale.ROOT, "%sEnum", cp.nameInCamelCase);
} else*/
if (cp.isArray) {
typingImports.add("List");
return String.format(Locale.ROOT, "List[%s]", getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports));
if (cp.maxItems != null || cp.minItems != null) {
String maxOrMinItems = "";
if (cp.maxItems != null) {
maxOrMinItems += String.format(Locale.ROOT, ", max_items=%d", cp.maxItems);
}
if (cp.minItems != null) {
maxOrMinItems += String.format(Locale.ROOT, ", min_items=%d", cp.minItems);
}
pydanticImports.add("conlist");
return String.format(Locale.ROOT, "conlist(%s%s)",
getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports),
maxOrMinItems);
} else {
typingImports.add("List");
return String.format(Locale.ROOT, "List[%s]", getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports));
}
} else if (cp.isMap) {
typingImports.add("Dict");
return String.format(Locale.ROOT, "Dict[str, %s]", getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports));
Expand Down Expand Up @@ -1077,9 +1106,9 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {

// setup x-py-name for each oneOf/anyOf schema
if (!model.oneOf.isEmpty()) { // oneOf
cp.vendorExtensions.put("x-py-name", String.format(Locale.ROOT, "__oneof_schema_%d", property_count++));
cp.vendorExtensions.put("x-py-name", String.format(Locale.ROOT, "oneof_schema_%d_validator", property_count++));
} else if (!model.anyOf.isEmpty()) { // anyOf
cp.vendorExtensions.put("x-py-name", String.format(Locale.ROOT, "__anyof_schema_%d", property_count++));
cp.vendorExtensions.put("x-py-name", String.format(Locale.ROOT, "anyof_schema_%d_validator", property_count++));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations
from inspect import getfullargspec
import json
import pprint
import re # noqa: F401
{{#vendorExtensions.x-py-datetime-imports}}{{#-first}}from datetime import{{/-first}} {{{.}}}{{^-last}},{{/-last}}{{/vendorExtensions.x-py-datetime-imports}}
Expand Down Expand Up @@ -39,14 +40,38 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}

@validator('actual_instance')
def actual_instance_must_validate_anyof(cls, v):
{{#isNullable}}
if v is None:
return v

{{/isNullable}}
instance = cls()
error_messages = []
{{#composedSchemas.anyOf}}
# validate data type: {{{dataType}}}
if type(v) is not {{^isPrimitiveType}}{{/isPrimitiveType}}{{{dataType}}}:
{{#isContainer}}
try:
instance.{{vendorExtensions.x-py-name}} = v
return v
except ValidationError as e:
error_messages.append(str(e))
{{/isContainer}}
{{^isContainer}}
{{#isPrimitiveType}}
try:
instance.{{vendorExtensions.x-py-name}} = v
return v
except ValidationError as e:
error_messages.append(str(e))
{{/isPrimitiveType}}
{{^isPrimitiveType}}
if type(v) is not {{{dataType}}}:
error_messages.append(f"Error! Input type `{type(v)}` is not `{{{dataType}}}`")
else:
return v

{{/isPrimitiveType}}
{{/isContainer}}
{{/composedSchemas.anyOf}}
if error_messages:
# no match
Expand All @@ -58,8 +83,36 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
def from_json(cls, json_str: str) -> {{{classname}}}:
"""Returns the object represented by the json string"""
instance = cls()
{{#isNullable}}
if json_str is None:
return instance

{{/isNullable}}
error_messages = []
{{#composedSchemas.anyOf}}
{{#isContainer}}
# deserialize data into {{{dataType}}}
try:
# validation
instance.{{vendorExtensions.x-py-name}} = json.loads(json_str)
# assign value to actual_instance
instance.actual_instance = instance.{{vendorExtensions.x-py-name}}
return instance
except ValidationError as e:
error_messages.append(str(e))
{{/isContainer}}
{{^isContainer}}
{{#isPrimitiveType}}
# deserialize data into {{{dataType}}}
try:
# validation
instance.{{vendorExtensions.x-py-name}} = json.loads(json_str)
# assign value to actual_instance
instance.actual_instance = instance.{{vendorExtensions.x-py-name}}
return instance
except ValidationError as e:
error_messages.append(str(e))
{{/isPrimitiveType}}
{{^isPrimitiveType}}
# {{vendorExtensions.x-py-name}}: {{{vendorExtensions.x-py-typing}}}
try:
Expand All @@ -68,6 +121,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
except ValidationError as e:
error_messages.append(str(e))
{{/isPrimitiveType}}
{{/isContainer}}
{{/composedSchemas.anyOf}}

if error_messages:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations
from inspect import getfullargspec
import pprint
import json
import pprint
import re # noqa: F401
{{#vendorExtensions.x-py-datetime-imports}}{{#-first}}from datetime import{{/-first}} {{{.}}}{{^-last}},{{/-last}}{{/vendorExtensions.x-py-datetime-imports}}
{{#vendorExtensions.x-py-typing-imports}}{{#-first}}from typing import{{/-first}} {{{.}}}{{^-last}},{{/-last}}{{/vendorExtensions.x-py-typing-imports}}
Expand Down Expand Up @@ -40,15 +40,39 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}

@validator('actual_instance')
def actual_instance_must_validate_oneof(cls, v):
{{#isNullable}}
if v is None:
return v

{{/isNullable}}
instance = cls()
error_messages = []
match = 0
{{#composedSchemas.oneOf}}
# validate data type: {{{dataType}}}
if type(v) is not {{^isPrimitiveType}}{{/isPrimitiveType}}{{{dataType}}}:
{{#isContainer}}
try:
instance.{{vendorExtensions.x-py-name}} = v
match += 1
except ValidationError as e:
error_messages.append(str(e))
{{/isContainer}}
{{^isContainer}}
{{#isPrimitiveType}}
try:
instance.{{vendorExtensions.x-py-name}} = v
match += 1
except ValidationError as e:
error_messages.append(str(e))
{{/isPrimitiveType}}
{{^isPrimitiveType}}
if type(v) is not {{{dataType}}}:
error_messages.append(f"Error! Input type `{type(v)}` is not `{{{dataType}}}`")
else:
match += 1

{{/isPrimitiveType}}
{{/isContainer}}
{{/composedSchemas.oneOf}}
if match > 1:
# more than 1 match
Expand All @@ -67,6 +91,11 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
def from_json(cls, json_str: str) -> {{{classname}}}:
"""Returns the object represented by the json string"""
instance = cls()
{{#isNullable}}
if json_str is None:
return instance

{{/isNullable}}
error_messages = []
match = 0

Expand All @@ -89,6 +118,29 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{/discriminator}}
{{/useOneOfDiscriminatorLookup}}
{{#composedSchemas.oneOf}}
{{#isContainer}}
# deserialize data into {{{dataType}}}
try:
# validation
instance.{{vendorExtensions.x-py-name}} = json.loads(json_str)
# assign value to actual_instance
instance.actual_instance = instance.{{vendorExtensions.x-py-name}}
match += 1
except ValidationError as e:
error_messages.append(str(e))
{{/isContainer}}
{{^isContainer}}
{{#isPrimitiveType}}
# deserialize data into {{{dataType}}}
try:
# validation
instance.{{vendorExtensions.x-py-name}} = json.loads(json_str)
# assign value to actual_instance
instance.actual_instance = instance.{{vendorExtensions.x-py-name}}
match += 1
except ValidationError as e:
error_messages.append(str(e))
{{/isPrimitiveType}}
{{^isPrimitiveType}}
# deserialize data into {{{dataType}}}
try:
Expand All @@ -97,6 +149,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
except ValidationError as e:
error_messages.append(str(e))
{{/isPrimitiveType}}
{{/isContainer}}
{{/composedSchemas.oneOf}}

if match > 1:
Expand Down Expand Up @@ -125,7 +178,3 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
def to_str(self) -> str:
"""Returns the string representation of the actual instance"""
return pprint.pformat(self.dict())




Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ class RESTResponse(io.IOBase):

def getheaders(self):
"""Returns a dictionary of the response headers."""
return self.urllib3_response.getheaders()
return self.urllib3_response.headers

def getheader(self, name, default=None):
"""Returns a given response header."""
return self.urllib3_response.getheader(name, default)
return self.urllib3_response.headers.get(name, default)


class RESTClientObject(object):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2035,3 +2035,41 @@ components:
type: string
self_ref:
$ref: '#/components/schemas/Self-Reference-Model'
RgbColor:
description: RGB three element array with values 0-255.
type: array
items:
type: integer
minimum: 0
maximum: 255
minItems: 3
maxItems: 3
RgbaColor:
description: RGBA four element array with values 0-255.
type: array
items:
type: integer
minimum: 0
maximum: 255
minItems: 4
maxItems: 4
HexColor:
description: 'Hex color string, such as #00FF00.'
type: string
pattern: ^#(?:[0-9a-fA-F]{3}){1,2}$
minLength: 7
maxLength: 7
Color:
nullable: true
description: RGB array, RGBA array, or hex string.
oneOf:
- $ref: '#/components/schemas/RgbColor'
- $ref: '#/components/schemas/RgbaColor'
- $ref: '#/components/schemas/HexColor'
#- type: "null"
AnyOfColor:
description: Any of RGB array, RGBA array, or hex string.
anyOf:
- $ref: '#/components/schemas/RgbColor'
- $ref: '#/components/schemas/RgbaColor'
- $ref: '#/components/schemas/HexColor'
4 changes: 2 additions & 2 deletions samples/client/echo_api/python-nextgen/openapi_client/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ def __init__(self, resp):

def getheaders(self):
"""Returns a dictionary of the response headers."""
return self.urllib3_response.getheaders()
return self.urllib3_response.headers

def getheader(self, name, default=None):
"""Returns a given response header."""
return self.urllib3_response.getheader(name, default)
return self.urllib3_response.headers.get(name, default)


class RESTClientObject(object):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ docs/AdditionalPropertiesClass.md
docs/AllOfWithSingleRef.md
docs/Animal.md
docs/AnotherFakeApi.md
docs/AnyOfColor.md
docs/AnyOfPig.md
docs/ApiResponse.md
docs/ArrayOfArrayOfNumberOnly.md
Expand All @@ -19,6 +20,7 @@ docs/CatAllOf.md
docs/Category.md
docs/ClassModel.md
docs/Client.md
docs/Color.md
docs/DanishPig.md
docs/DefaultApi.md
docs/DeprecatedObject.md
Expand Down Expand Up @@ -83,6 +85,7 @@ petstore_api/models/__init__.py
petstore_api/models/additional_properties_class.py
petstore_api/models/all_of_with_single_ref.py
petstore_api/models/animal.py
petstore_api/models/any_of_color.py
petstore_api/models/any_of_pig.py
petstore_api/models/api_response.py
petstore_api/models/array_of_array_of_number_only.py
Expand All @@ -95,6 +98,7 @@ petstore_api/models/cat_all_of.py
petstore_api/models/category.py
petstore_api/models/class_model.py
petstore_api/models/client.py
petstore_api/models/color.py
petstore_api/models/danish_pig.py
petstore_api/models/deprecated_object.py
petstore_api/models/dog.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ Class | Method | HTTP request | Description
- [AdditionalPropertiesClass](docs/AdditionalPropertiesClass.md)
- [AllOfWithSingleRef](docs/AllOfWithSingleRef.md)
- [Animal](docs/Animal.md)
- [AnyOfColor](docs/AnyOfColor.md)
- [AnyOfPig](docs/AnyOfPig.md)
- [ApiResponse](docs/ApiResponse.md)
- [ArrayOfArrayOfNumberOnly](docs/ArrayOfArrayOfNumberOnly.md)
Expand All @@ -142,6 +143,7 @@ Class | Method | HTTP request | Description
- [Category](docs/Category.md)
- [ClassModel](docs/ClassModel.md)
- [Client](docs/Client.md)
- [Color](docs/Color.md)
- [DanishPig](docs/DanishPig.md)
- [DeprecatedObject](docs/DeprecatedObject.md)
- [Dog](docs/Dog.md)
Expand Down
Loading