Open a-akshat opened 1 month ago
i tested with python-flask in the latest master and don't see TypedDict
in the auto-generated models so looks like you're using a customized version/template somehow
i also tested with python client generator and couldn't repeat the issue, which means id
is correctly annotated with the type Optional[str]
@wing328 yes you are right, we use a customized templates for our use case.
Also, please note that this template worked with openapi spec 3.0.3 and latest version of the generator
Here is the model customized template that produces the TypedDict
{{/parent}}
{{! Simple object types get an Enum- or TypedDict-base representation: }}
{{^parent}}
{{#isEnum}}
class {{classname}}({{#isString}}str, {{/isString}}enum.Enum):
{{#allowableValues}}
{{#enumVars}}
{{name}} = {{{value}}}
{{/enumVars}}
{{/allowableValues}}
{{/isEnum}}
{{^isEnum}}
class {{classname}}(TypedDict):
{{#vars}}
{{name}}: {{> field_type}}
{{/vars}}
{{/isEnum}}
{{/parent}}
{{/vendorExtensions.x-python-imports}}
{{/model}}
{{/models}}
field_type.mustache:
{{#isNullable}}Optional[{{/isNullable}}{{#isDateTime}}Union[datetime, DateTimeProxy]{{/isDateTime}}{{^isDateTime}}{{dataType}}{{/isDateTime}}{{#isNullable}}]{{/isNullable}}
Do you recommend using the python generator instead of python flask for the models? https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/python/model_generic.mustache
"vars" : [ {
"openApiType" : "string",
"baseName" : "id",
"getter" : "getId",
"setter" : "setId",
"dataType" : "str",
"datatypeWithEnum" : "str",
"name" : "id",
"defaultValueWithParam" : " = data.id;",
"baseType" : "str",
"example" : "''",
"jsonSchema" : "{\r\n \"nullable\" : true,\r\n \"type\" : \"string\"\r\n}",
"exclusiveMinimum" : false,
"exclusiveMaximum" : false,
"required" : false,
"deprecated" : false,
"hasMoreNonReadOnly" : false,
"isPrimitiveType" : true,
"isModel" : false,
"isContainer" : false,
"isString" : true,
"isNumeric" : false,
"isInteger" : false,
"isShort" : false,
"isLong" : false,
"isUnboundedInteger" : false,
"isNumber" : false,
"isFloat" : false,
"isDouble" : false,
"isDecimal" : false,
"isByteArray" : false,
"isBinary" : false,
"isFile" : false,
"isBoolean" : false,
"isDate" : false,
"isDateTime" : false,
"isUuid" : false,
"isUri" : false,
"isEmail" : false,
"isPassword" : false,
"isNull" : false,
"isVoid" : false,
"isFreeFormObject" : false,
"isAnyType" : false,
"isArray" : false,
"isMap" : false,
"isOptional" : false,
"isEnum" : false,
"isInnerEnum" : false,
"isEnumRef" : false,
"isReadOnly" : false,
"isWriteOnly" : false,
"isNullable" : true,
using --global-property debugModels
in CLI, isNullable
is correctly set to true so no idea why it's not working in your use cases with customized templates.
@wing328 thank you for pointing me towards the debugModels option it makes things clearer.
I can confirm that isNullable is not set on the UserResponse
{
"importPath" : "from api.v5.generated.models.user_response import UserResponse",
"pyImports" : [ ],
"model" : {
"interfaces" : [ "BaseUser" ],
"anyOf" : [ ],
"oneOf" : [ ],
"allOf" : [ "BaseUser" ],
"name" : "UserResponse",
**"schemaName" : "UserResponse",
"classname" : "UserResponse",**
"classVarName" : "user_response",
"modelJson" : "{\n \"allOf\" : [ {\n \"$ref\" : \"#/components/schemas/BaseUser\"\n }, {\n \"properties\" : {\n \"email\" : {\n \"type\" : \"string\",\n \"description\" : \"The email of the user\"\n }\n }\n } ]\n}",
"dataType" : "BaseUser",
"classFilename" : "user_response",
"isAlias" : false,
"isString" : false,
"isInteger" : false,
"isLong" : false,
"isNumber" : false,
"isNumeric" : false,
"isFloat" : false,
"isDouble" : false,
"isDate" : false,
"isDateTime" : false,
"isDecimal" : false,
"isShort" : false,
"isUnboundedInteger" : false,
"isPrimitiveType" : false,
"isBoolean" : false,
"isFreeFormObject" : false,
"additionalPropertiesIsAnyType" : false,
"vars" : [ {
"openApiType" : "string",
"baseName" : "id",
"getter" : "getId",
"setter" : "setId",
"dataType" : "str",
"datatypeWithEnum" : "str",
"name" : "id",
"defaultValueWithParam" : " = data.id;",
"baseType" : "str",
"title" : "id",
"example" : "''",
"jsonSchema" : "{\n \"title\" : \"id\"\n}",
"exclusiveMinimum" : false,
"exclusiveMaximum" : false,
"required" : false,
"deprecated" : false,
"hasMoreNonReadOnly" : false,
"isPrimitiveType" : true,
"isModel" : false,
"isContainer" : false,
"isString" : true,
"isNumeric" : false,
"isInteger" : false,
"isShort" : false,
"isLong" : false,
"isUnboundedInteger" : false,
"isNumber" : false,
"isFloat" : false,
"isDouble" : false,
"isDecimal" : false,
"isByteArray" : false,
"isBinary" : false,
"isFile" : false,
"isBoolean" : false,
"isDate" : false,
"isDateTime" : false,
"isUuid" : false,
"isUri" : false,
"isEmail" : false,
"isPassword" : false,
"isNull" : false,
"isVoid" : false,
"isFreeFormObject" : false,
"isAnyType" : false,
"isArray" : false,
"isMap" : false,
"isOptional" : false,
"isEnum" : false,
"isInnerEnum" : false,
"isEnumRef" : false,
"isReadOnly" : false,
"isWriteOnly" : false,
**"isNullable" : false,**
"isSelfReference" : false,
"isCircularReference" : false,
"isDiscriminator" : false,
"isNew" : false,
"isOverridden" : false,
"vars" : [ ],
"requiredVars" : [ ],
"vendorExtensions" : {
"x-py-typing" : "Optional[StrictStr] = None"
},
"hasValidation" : false,
"isInherited" : false,
"nameInCamelCase" : "id",
"nameInPascalCase" : "Id",
"nameInSnakeCase" : "ID",
"uniqueItems" : false,
"isXmlAttribute" : false,
"isXmlWrapped" : false,
"additionalPropertiesIsAnyType" : false,
"hasVars" : false,
"hasRequired" : false,
"hasDiscriminatorWithNonEmptyMapping" : false,
"hasMultipleTypes" : false,
"schemaIsFromAdditionalProperties" : false,
"isBooleanSchemaTrue" : false,
"isBooleanSchemaFalse" : false,
"isEnumOrRef" : false,
"datatype" : "str",
"exclusiveMaximum" : false,
"hasItems" : false
}
Is it possible that you might be looking at BaseUser
?
Btw, I found a workaround, there is a vendor extension that can be used to mark a property nullable. x-nullable: true propagates isNullable as true to its children. Let me know if this is not the intended use-case.
Description
Currently, we use openapi spec 3.0.3 with openapi-generator version 5.4.0 and we are planning to migrate to openapi spec 3.1.0 with the latest generator version.
While migrating to 3.1.0 I see that nullable is not supported anymore and we use the isNullable value to set our generated model instance variable to Optional as follows:
{{#isNullable}}Optional[{{/isNullable}}{{#isDateTime}}Union[datetime, DateTimeProxy]{{/isDateTime}}{{^isDateTime}}{{dataType}}{{/isDateTime}}{{#isNullable}}]{{/isNullable}}
I noticed that with the new version of the generator and openapi spec 3.1.0 when we set a property as "null" this constraint is not inherited by the child schema in the model generated. Here is a simple example:
Openapi spec 3.1.0:
Model generated: base_user.py
user_response.py
Notice how the
id : Optional[str]
is not the same as parent in the child schema. This worked as expected with 3.0.3 and the new version of the generator as well. So makes me wonder if the 3.1.0 spec isNullable property is propagated to the child schema.Please let me know if there is a way I can resolve this as we want to utilize the great features in 3.1.0 without breaking our client code.
openapi-generator version
7.8.0
OpenAPI declaration file content or url
Command line used for generation
openapi-generator-cli generate --input-spec spec/bundle.yaml --config openapi-generator.yaml --output ../..
Note: the openapi-generator.yaml config file is straightforward and no options are enabled in it.