Skip to content
Closed
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 @@ -871,13 +871,13 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
pydanticImports.add("Field");
pydanticImports.add("StrictStr");
pydanticImports.add("ValidationError");
pydanticImports.add("validator");
pydanticImports.add(usePydanticV2 ? "field_validator" : "validator");
} else if (!model.anyOf.isEmpty()) { // anyOF
codegenProperties = model.getComposedSchemas().getAnyOf();
pydanticImports.add("Field");
pydanticImports.add("StrictStr");
pydanticImports.add("ValidationError");
pydanticImports.add("validator");
pydanticImports.add(usePydanticV2 ? "field_validator" : "validator");
} else { // typical model
codegenProperties = model.vars;

Expand Down Expand Up @@ -1110,7 +1110,7 @@ private String getPydanticType(CodegenParameter cp,
fieldCustomization.add("min_length=" + cp.getMinLength());
}
if (cp.getPattern() != null) {
pydanticImports.add("validator");
pydanticImports.add(usePydanticV2 ? "field_validator" : "validator");
// use validator instead as regex doesn't support flags, e.g. IGNORECASE
//fieldCustomization.add(String.format(Locale.ROOT, "regex=r'%s'", cp.getPattern()));
}
Expand Down Expand Up @@ -1229,7 +1229,7 @@ private String getPydanticType(CodegenParameter cp,
fieldCustomization.add("max_length=" + cp.getMaxLength());
}
if (cp.getPattern() != null) {
pydanticImports.add("validator");
pydanticImports.add(usePydanticV2 ? "field_validator" : "validator");
// use validator instead as regex doesn't support flags, e.g. IGNORECASE
//fieldCustomization.add(Locale.ROOT, String.format(Locale.ROOT, "regex=r'%s'", cp.getPattern()));
}
Expand Down Expand Up @@ -1347,7 +1347,7 @@ private String getPydanticType(CodegenProperty cp,
}

if (cp.isEnum) {
pydanticImports.add("validator");
pydanticImports.add(usePydanticV2 ? "field_validator" : "validator");
}

/* comment out the following since Literal requires python 3.8
Expand Down Expand Up @@ -1397,7 +1397,7 @@ private String getPydanticType(CodegenProperty cp,
fieldCustomization.add("min_length=" + cp.getMinLength());
}
if (cp.getPattern() != null) {
pydanticImports.add("validator");
pydanticImports.add(usePydanticV2 ? "field_validator" : "validator");
// use validator instead as regex doesn't support flags, e.g. IGNORECASE
//fieldCustomization.add(Locale.ROOT, String.format(Locale.ROOT, "regex=r'%s'", cp.getPattern()));
}
Expand Down Expand Up @@ -1516,7 +1516,7 @@ private String getPydanticType(CodegenProperty cp,
fieldCustomization.add("max_length=" + cp.getMaxLength());
}
if (cp.getPattern() != null) {
pydanticImports.add("validator");
pydanticImports.add(usePydanticV2 ? "field_validator" : "validator");
// use validator instead as regex doesn't support flags, e.g. IGNORECASE
//fieldCustomization.add(Locale.ROOT, String.format(Locale.ROOT, "regex=r'%s'", cp.getPattern()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,8 @@ from pprint import pprint
{{#vendorExtensions.x-py-postponed-example-imports}}
{{{.}}}
{{/vendorExtensions.x-py-postponed-example-imports}}
{{classname}}.update_forward_refs()
try:
{{classname}}.{{#usePydanticV2}}model_rebuild{{/usePydanticV2}}{{^usePydanticV2}}update_forward_refs{{/usePydanticV2}}()

@fa0311 fa0311 Sep 26, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

should use .model_rebuild(raise_errors=False) instead of try.
However, this is a stopgap measure and in practice should be implemented without using raise_errors.
I spent a lot of time trying to rebuild without raise_errors, but couldn't come up with a good solution.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we can remove the usePydanticV2 switch the template and the java class as python client generator now only supports pydantic v2.

except Exception:
pass
{{/vendorExtensions.x-py-postponed-example-imports.size}}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{vendorExtensions.x-py-name}}: {{{vendorExtensions.x-py-typing}}}
{{/composedSchemas.anyOf}}
if TYPE_CHECKING:
actual_instance: Union[{{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}]
actual_instance: Union[{{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}{{#isNullable}}, None{{/isNullable}}]
else:
actual_instance: Any
actual_instance: Any = None
{{^usePydanticV2}}
any_of_schemas: List[str] = Field({{#lambda.uppercase}}{{{classname}}}{{/lambda.uppercase}}_ANY_OF_SCHEMAS, const=True)
{{/usePydanticV2}}
Expand All @@ -50,14 +50,6 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
class Config:
validate_assignment = True
{{/usePydanticV2}}
{{#discriminator}}

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}}
{{/children}}
}
{{/discriminator}}

def __init__(self, *args, **kwargs) -> None:
if args:
Expand All @@ -66,17 +58,24 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
if kwargs:
raise ValueError("If a position argument is used, keyword arguments cannot be used.")
super().__init__(actual_instance=args[0])
else:
elif kwargs:
super().__init__(**kwargs)
else:
super().__init__(actual_instance=None)

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

{{/isNullable}}
instance = {{{classname}}}.construct()
instance = {{{classname}}}.{{#usePydanticV2}}model_construct{{/usePydanticV2}}{{^usePydanticV2}}construct{{/usePydanticV2}}()
error_messages = []
{{#composedSchemas.anyOf}}
# validate data type: {{{dataType}}}
Expand All @@ -88,20 +87,11 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
error_messages.append(str(e))
{{/isContainer}}
{{^isContainer}}
{{#isPrimitiveType}}
try:
instance.{{vendorExtensions.x-py-name}} = v
return v
except (ValidationError, ValueError) as e:
error_messages.append(str(e))
{{/isPrimitiveType}}
{{^isPrimitiveType}}
if not isinstance(v, {{{dataType}}}):
error_messages.append(f"Error! Input type `{type(v)}` is not `{{{dataType}}}`")
else:
return v

{{/isPrimitiveType}}
{{/isContainer}}
{{/composedSchemas.anyOf}}
if error_messages:
Expand All @@ -117,7 +107,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
@classmethod
def from_json(cls, json_str: str) -> {{{classname}}}:
"""Returns the object represented by the json string"""
instance = {{{classname}}}.construct()
instance = {{{classname}}}.{{#usePydanticV2}}model_construct{{/usePydanticV2}}{{^usePydanticV2}}construct{{/usePydanticV2}}()
{{#isNullable}}
if json_str is None:
return instance
Expand Down Expand Up @@ -189,11 +179,14 @@ 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())
return pprint.pformat(self.{{#usePydanticV2}}model_dump{{/usePydanticV2}}{{^usePydanticV2}}dict{{/usePydanticV2}}())

{{#vendorExtensions.x-py-postponed-model-imports.size}}
{{#vendorExtensions.x-py-postponed-model-imports}}
{{{.}}}
{{/vendorExtensions.x-py-postponed-model-imports}}
{{classname}}.update_forward_refs()
try:
{{classname}}.{{#usePydanticV2}}model_rebuild{{/usePydanticV2}}{{^usePydanticV2}}update_forward_refs{{/usePydanticV2}}()
except Exception:
pass
{{/vendorExtensions.x-py-postponed-model-imports.size}}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{#isAdditionalPropertiesTrue}}
additional_properties: Dict[str, Any] = {}
{{/isAdditionalPropertiesTrue}}
__properties = [{{#allVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/allVars}}]
{{#vars}}
{{#vendorExtensions.x-regex}}

{{#usePydanticV2}}
@field_validator('{{{name}}}')
{{/usePydanticV2}}
{{^usePydanticV2}}
@validator('{{{name}}}')
{{/usePydanticV2}}
def {{{name}}}_validate_regular_expression(cls, value):
"""Validates the regular expression"""
{{^required}}
Expand All @@ -45,7 +49,12 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{/vendorExtensions.x-regex}}
{{#isEnum}}

{{#usePydanticV2}}
@field_validator('{{{name}}}')
{{/usePydanticV2}}
{{^usePydanticV2}}
@validator('{{{name}}}')
{{/usePydanticV2}}
def {{{name}}}_validate_enum(cls, value):
"""Validates the enum"""
{{^required}}
Expand Down Expand Up @@ -89,33 +98,25 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{#hasChildren}}
{{#discriminator}}
# JSON field name that stores the object type
__discriminator_property_name = '{{discriminator.propertyBaseName}}'

{{#mappedModels}}
{{#-first}}
# discriminator mappings
__discriminator_value_class_map = {
{{/-first}}
'{{{mappingName}}}': '{{{modelName}}}'{{^-last}},{{/-last}}
{{#-last}}
}

@classmethod
def get_discriminator_value(cls, obj: dict) -> str:
"""Returns the discriminator value (object type) of the data"""
discriminator_value = obj[cls.__discriminator_property_name]
discriminator_value = obj['{{discriminator.propertyBaseName}}']
discriminator_value_class_map = {
{{#mappedModels}}'{{{mappingName}}}': '{{{modelName}}}'{{^-last}},{{/-last}}{{/mappedModels}}
}

if discriminator_value:
return cls.__discriminator_value_class_map.get(discriminator_value)
return discriminator_value_class_map.get(discriminator_value)
else:
return None
{{/-last}}
{{/mappedModels}}

{{/discriminator}}
{{/hasChildren}}
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.dict(by_alias=True))
return pprint.pformat(self.{{#usePydanticV2}}model_dump{{/usePydanticV2}}{{^usePydanticV2}}dict{{/usePydanticV2}}(by_alias=True))

def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
Expand All @@ -128,7 +129,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}

def to_dict(self):
"""Returns the dictionary representation of the model using alias"""
_dict = self.dict(by_alias=True,
_dict = self.{{#usePydanticV2}}model_dump{{/usePydanticV2}}{{^usePydanticV2}}dict{{/usePydanticV2}}(by_alias=True,
exclude={
{{#vendorExtensions.x-py-readonly}}
"{{{.}}}",
Expand Down Expand Up @@ -216,7 +217,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{#isNullable}}
# 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__:
if self.{{name}} is None and "{{{name}}}" in self.{{#usePydanticV2}}model_fields_set{{/usePydanticV2}}{{^usePydanticV2}}__fields_set__{{/usePydanticV2}}:
_dict['{{{baseName}}}'] = None

{{/isNullable}}
Expand All @@ -230,32 +231,35 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{#discriminator}}
# look up the object type based on discriminator mapping
object_type = cls.get_discriminator_value(obj)
discriminator_value_class_map = {
{{#mappedModels}}'{{{mappingName}}}': '{{{modelName}}}'{{^-last}},{{/-last}}{{/mappedModels}}
}
if object_type:
klass = globals()[object_type]
return klass.from_dict(obj)
else:
raise ValueError("{{{classname}}} failed to lookup discriminator value from " +
json.dumps(obj) + ". Discriminator property name: " + cls.__discriminator_property_name +
", mapping: " + json.dumps(cls.__discriminator_value_class_map))
json.dumps(obj) + ". Discriminator property name: " + '{{discriminator.propertyBaseName}}' +
", mapping: " + json.dumps(discriminator_value_class_map))
{{/discriminator}}
{{/hasChildren}}
{{^hasChildren}}
if obj is None:
return None

if not isinstance(obj, dict):
return {{{classname}}}.parse_obj(obj)
return {{{classname}}}.{{#usePydanticV2}}model_validate{{/usePydanticV2}}{{^usePydanticV2}}parse_obj{{/usePydanticV2}}(obj)

{{#disallowAdditionalPropertiesIfNotPresent}}
{{^isAdditionalPropertiesTrue}}
# raise errors for additional fields in the input
for _key in obj.keys():
if _key not in cls.__properties:
if _key not in [{{#allVars}}"{{{baseName}}}"{{^-last}}, {{/-last}}{{/allVars}}]:
raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + obj)

{{/isAdditionalPropertiesTrue}}
{{/disallowAdditionalPropertiesIfNotPresent}}
_obj = {{{classname}}}.parse_obj({
_obj = {{{classname}}}.{{#usePydanticV2}}model_validate{{/usePydanticV2}}{{^usePydanticV2}}parse_obj{{/usePydanticV2}}({
{{#allVars}}
{{#isContainer}}
{{#isArray}}
Expand Down Expand Up @@ -354,7 +358,7 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{#isAdditionalPropertiesTrue}}
# store additional fields in additional_properties
for _key in obj.keys():
if _key not in cls.__properties:
if _key not in [{{#allVars}}"{{{baseName}}}"{{^-last}}, {{/-last}}{{/allVars}}]:
_obj.additional_properties[_key] = obj.get(_key)

{{/isAdditionalPropertiesTrue}}
Expand All @@ -365,5 +369,8 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
{{#vendorExtensions.x-py-postponed-model-imports}}
{{{.}}}
{{/vendorExtensions.x-py-postponed-model-imports}}
{{classname}}.update_forward_refs()
try:
{{classname}}.{{#usePydanticV2}}model_rebuild{{/usePydanticV2}}{{^usePydanticV2}}update_forward_refs{{/usePydanticV2}}()
except Exception:
pass
{{/vendorExtensions.x-py-postponed-model-imports.size}}
Loading