forked from loafle/openapi-generator-original
Python-exp remove codegemodel mutation, allow mixed OneOf types (#6797)
* Stops converting primitive models into object models, adds ComposedSchemas with mixed type * Samples update for python-exp
This commit is contained in:
@@ -1960,10 +1960,10 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
/**
|
||||
* Return a string representation of the schema type, resolving aliasing and references if necessary.
|
||||
*
|
||||
* @param schema
|
||||
* @param schema input
|
||||
* @return the string representation of the schema type.
|
||||
*/
|
||||
private String getSingleSchemaType(Schema schema) {
|
||||
protected String getSingleSchemaType(Schema schema) {
|
||||
Schema unaliasSchema = ModelUtils.unaliasSchema(this.openAPI, schema, importMapping);
|
||||
|
||||
if (StringUtils.isNotBlank(unaliasSchema.get$ref())) { // reference to another definition/schema
|
||||
|
||||
@@ -423,6 +423,7 @@ public class PythonClientExperimentalCodegen extends PythonClientCodegen {
|
||||
CodegenProperty modelProperty = fromProperty("value", modelSchema);
|
||||
|
||||
// import complex type from additional properties
|
||||
// TODO can I remove this? DOes it exist in defaultcodegen?
|
||||
if (cm.additionalPropertiesType != null && modelProperty.items != null && modelProperty.items.complexType != null) {
|
||||
cm.imports.add(modelProperty.items.complexType);
|
||||
}
|
||||
@@ -800,9 +801,11 @@ public class PythonClientExperimentalCodegen extends PythonClientCodegen {
|
||||
public CodegenModel fromModel(String name, Schema schema) {
|
||||
// we have a custom version of this function so we can produce
|
||||
// models for components whose type != object and which have validations and enums
|
||||
// this ensures that endpoint (operation) responses with validations and enums
|
||||
// will generate models, and when those endpoint responses are received in python
|
||||
// the response is cast as a model, and the model will validate the response using the enums and validations
|
||||
// this ensures that:
|
||||
// - endpoint (operation) responses with validations and type!=(object or array)
|
||||
// - oneOf $ref components with validations and type!=(object or array)
|
||||
// when endpoints receive payloads of these models
|
||||
// that they will be converted into instances of these models
|
||||
Map<String, String> propertyToModelName = new HashMap<String, String>();
|
||||
Map<String, Schema> propertiesMap = schema.getProperties();
|
||||
if (propertiesMap != null) {
|
||||
@@ -820,7 +823,7 @@ public class PythonClientExperimentalCodegen extends PythonClientCodegen {
|
||||
continue;
|
||||
}
|
||||
CodegenProperty modelProperty = fromProperty("_fake_name", refSchema);
|
||||
if (modelProperty.isEnum == false && modelProperty.hasValidation == false) {
|
||||
if (modelProperty.isEnum == true || modelProperty.hasValidation == false) {
|
||||
continue;
|
||||
}
|
||||
String modelName = ModelUtils.getSimpleRef(ref);
|
||||
@@ -828,37 +831,111 @@ public class PythonClientExperimentalCodegen extends PythonClientCodegen {
|
||||
}
|
||||
}
|
||||
CodegenModel result = super.fromModel(name, schema);
|
||||
|
||||
// have oneOf point to the correct model
|
||||
if (ModelUtils.isComposedSchema(schema)) {
|
||||
ComposedSchema cs = (ComposedSchema) schema;
|
||||
Map<String, Integer> importCounts = new HashMap<String, Integer>();
|
||||
List<Schema> oneOfSchemas = cs.getOneOf();
|
||||
if (oneOfSchemas != null) {
|
||||
for (int i = 0; i < oneOfSchemas.size(); i++) {
|
||||
Schema oneOfSchema = oneOfSchemas.get(i);
|
||||
String languageType = getTypeDeclaration(oneOfSchema);
|
||||
String ref = oneOfSchema.get$ref();
|
||||
if (ref == null) {
|
||||
Integer currVal = importCounts.getOrDefault(languageType, 0);
|
||||
importCounts.put(languageType, currVal+1);
|
||||
continue;
|
||||
}
|
||||
Schema refSchema = ModelUtils.getReferencedSchema(this.openAPI, oneOfSchema);
|
||||
String refType = refSchema.getType();
|
||||
if (refType == null || refType.equals("object")) {
|
||||
Integer currVal = importCounts.getOrDefault(languageType, 0);
|
||||
importCounts.put(languageType, currVal+1);
|
||||
continue;
|
||||
}
|
||||
|
||||
CodegenProperty modelProperty = fromProperty("_oneOfSchema", refSchema);
|
||||
if (modelProperty.isEnum == true) {
|
||||
Integer currVal = importCounts.getOrDefault(languageType, 0);
|
||||
importCounts.put(languageType, currVal+1);
|
||||
continue;
|
||||
}
|
||||
|
||||
languageType = getTypeDeclaration(refSchema);
|
||||
if (modelProperty.hasValidation == false) {
|
||||
Integer currVal = importCounts.getOrDefault(languageType, 0);
|
||||
importCounts.put(languageType, currVal+1);
|
||||
continue;
|
||||
}
|
||||
Integer currVal = importCounts.getOrDefault(languageType, 0);
|
||||
importCounts.put(languageType, currVal);
|
||||
String modelName = toModelName(ModelUtils.getSimpleRef(ref));
|
||||
result.imports.add(modelName);
|
||||
result.oneOf.add(modelName);
|
||||
currVal = importCounts.getOrDefault(modelName, 0);
|
||||
importCounts.put(modelName, currVal+1);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, Integer> entry : importCounts.entrySet()) {
|
||||
String importName = entry.getKey();
|
||||
Integer importCount = entry.getValue();
|
||||
if (importCount == 0) {
|
||||
result.oneOf.remove(importName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use this to store the model name like Cat
|
||||
// we can't use result.name because that is used to lookup models in the spec
|
||||
// we can't use result.classname because that stores cat.Cat
|
||||
// we can't use result.classVarName because that stores the variable for making example instances
|
||||
result.unescapedDescription = simpleModelName(name);
|
||||
|
||||
// make non-object type models have one property so we can use it to store enums and validations
|
||||
if (result.isAlias || result.isEnum || result.isArrayModel) {
|
||||
Schema modelSchema = ModelUtils.getSchema(this.openAPI, result.name);
|
||||
CodegenProperty modelProperty = fromProperty("value", modelSchema);
|
||||
if (modelProperty.isEnum == true || modelProperty.hasValidation == true || result.isArrayModel) {
|
||||
// these models are non-object models with enums and/or validations
|
||||
// add a single property to the model so we can have a way to access validations
|
||||
result.isAlias = true;
|
||||
modelProperty.required = true;
|
||||
List<CodegenProperty> theProperties = Arrays.asList(modelProperty);
|
||||
result.setAllVars(theProperties);
|
||||
result.setVars(theProperties);
|
||||
result.setRequiredVars(theProperties);
|
||||
// post process model properties
|
||||
if (result.vars != null) {
|
||||
for (CodegenProperty prop : result.vars) {
|
||||
postProcessModelProperty(result, prop);
|
||||
}
|
||||
// this block handles models which have the python base class ModelSimple
|
||||
// which are responsible for storing validations, enums, and an unnamed value
|
||||
Schema modelSchema = ModelUtils.getSchema(this.openAPI, result.name);
|
||||
CodegenProperty modelProperty = fromProperty("_value", modelSchema);
|
||||
|
||||
// import complex type from additional properties
|
||||
if (result.additionalPropertiesType != null && modelProperty.items != null && modelProperty.items.complexType != null) {
|
||||
result.imports.add(modelProperty.items.complexType);
|
||||
}
|
||||
|
||||
Boolean isPythonModelSimpleModel = (result.isEnum || result.isArrayModel || result.isAlias && modelProperty.hasValidation);
|
||||
if (isPythonModelSimpleModel) {
|
||||
// In python, classes which inherit from our ModelSimple class store one value,
|
||||
// like a str, int, list and extra data about that value like validations and enums
|
||||
|
||||
if (result.isEnum) {
|
||||
// if there is only one allowed value then we know that it should be set, so value is optional
|
||||
// -> hasRequired = false
|
||||
// if there are more than one allowed value then value is positional and required so
|
||||
// -> hasRequired = true
|
||||
ArrayList values = (ArrayList) result.allowableValues.get("values");
|
||||
if (values != null && values.size() > 1) {
|
||||
result.hasRequired = true;
|
||||
}
|
||||
|
||||
if (modelProperty.defaultValue != null && result.defaultValue == null) {
|
||||
result.defaultValue = modelProperty.defaultValue;
|
||||
}
|
||||
} else {
|
||||
if (result.isArrayModel && modelProperty.dataType != null && result.dataType == null) {
|
||||
// needed for array models with complex types
|
||||
result.dataType = modelProperty.dataType;
|
||||
result.arrayModelType = getPythonClassName(result.arrayModelType);
|
||||
}
|
||||
|
||||
if (result.defaultValue == null) {
|
||||
result.hasRequired = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set regex values, before it was only done on model.vars
|
||||
// fix all property references to non-object models, make those properties non-primitive and
|
||||
// fix all property references to ModelSimple models, make those properties non-primitive and
|
||||
// set their dataType and complexType to the model name, so documentation will refer to the correct model
|
||||
// set regex values, before it was only done on model.vars
|
||||
// NOTE: this is done for models of type != object which are not enums and have validations
|
||||
ArrayList<List<CodegenProperty>> listOfLists = new ArrayList<List<CodegenProperty>>();
|
||||
listOfLists.add(result.vars);
|
||||
listOfLists.add(result.allVars);
|
||||
@@ -883,6 +960,7 @@ public class PythonClientExperimentalCodegen extends PythonClientCodegen {
|
||||
result.imports.add(modelName);
|
||||
}
|
||||
}
|
||||
|
||||
// if a class has a property of type self, remove the self import from imports
|
||||
if (result.imports.contains(result.classname)) {
|
||||
result.imports.remove(result.classname);
|
||||
@@ -895,6 +973,60 @@ public class PythonClientExperimentalCodegen extends PythonClientCodegen {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the OpenAPI type for the property. Use getAlias to handle $ref of primitive type
|
||||
* We have a custom version of this function because for composed schemas we also want to return the model name
|
||||
* In DefaultCodegen.java it returns a name built off of individual allOf/anyOf/oneOf which is not what
|
||||
* python-experimental needs. Python-experimental needs the name of the composed schema
|
||||
*
|
||||
* @param schema property schema
|
||||
* @return string presentation of the type
|
||||
**/
|
||||
@SuppressWarnings("static-method")
|
||||
@Override
|
||||
public String getSchemaType(Schema schema) {
|
||||
if (schema instanceof ComposedSchema) { // composed schema
|
||||
Schema unaliasSchema = ModelUtils.unaliasSchema(this.openAPI, schema, importMapping);
|
||||
String ref = unaliasSchema.get$ref();
|
||||
if (ref != null) {
|
||||
String schemaName = ModelUtils.getSimpleRef(unaliasSchema.get$ref());
|
||||
if (StringUtils.isNotEmpty(schemaName) && importMapping.containsKey(schemaName)) {
|
||||
return schemaName;
|
||||
}
|
||||
return getAlias(schemaName);
|
||||
} else {
|
||||
// we may have be processing the component schema rather than a schema with a $ref
|
||||
// to a component schema
|
||||
// so loop through component schemas and use the found one's name if we match
|
||||
Map<String, Schema> schemas = ModelUtils.getSchemas(openAPI);
|
||||
for (String thisSchemaName : schemas.keySet()) {
|
||||
Schema thisSchema = schemas.get(thisSchemaName);
|
||||
if (!ModelUtils.isComposedSchema(thisSchema)) {
|
||||
continue;
|
||||
}
|
||||
if (thisSchema == unaliasSchema) {
|
||||
if (importMapping.containsKey(thisSchemaName)) {
|
||||
return thisSchemaName;
|
||||
}
|
||||
return getAlias(thisSchemaName);
|
||||
}
|
||||
}
|
||||
LOGGER.warn("Error obtaining the datatype from ref:" + unaliasSchema.get$ref() + ". Default to 'object'");
|
||||
return "object";
|
||||
}
|
||||
}
|
||||
String openAPIType = getSingleSchemaType(schema);
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
String type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
return toModelName(openAPIType);
|
||||
}
|
||||
return openAPIType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the type declaration of the property
|
||||
*
|
||||
|
||||
@@ -33,17 +33,22 @@ from {{packageName}}.model_utils import ( # noqa: F401
|
||||
|
||||
|
||||
{{^interfaces}}
|
||||
{{#isAlias}}
|
||||
{{> python-experimental/model_templates/model_simple }}
|
||||
{{/isAlias}}
|
||||
{{^isAlias}}
|
||||
{{#isArrayModel}}
|
||||
{{> python-experimental/model_templates/model_simple }}
|
||||
{{/isArrayModel}}
|
||||
{{^isArrayModel}}
|
||||
{{> python-experimental/model_templates/model_normal }}
|
||||
{{/isArrayModel}}
|
||||
{{#isEnum}}
|
||||
{{> python-experimental/model_templates/model_simple }}
|
||||
{{/isEnum}}
|
||||
{{#isAlias}}
|
||||
{{> python-experimental/model_templates/model_simple }}
|
||||
{{/isAlias}}
|
||||
{{^isArrayModel}}
|
||||
{{^isEnum}}
|
||||
{{^isAlias}}
|
||||
{{> python-experimental/model_templates/model_normal }}
|
||||
{{/isAlias}}
|
||||
{{/isEnum}}
|
||||
{{/isArrayModel}}
|
||||
{{/interfaces}}
|
||||
{{#interfaces}}
|
||||
{{#-last}}
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
{{#isEnum}}
|
||||
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}{{#allowableValues}}{{#defaultValue}}, {{/defaultValue}} must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}}
|
||||
{{/isEnum}}
|
||||
{{#isAlias}}
|
||||
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}
|
||||
{{/isAlias}}
|
||||
{{#isArrayModel}}
|
||||
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}}{{#arrayModelType}}[**{{dataType}}**]({{arrayModelType}}.md){{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}
|
||||
{{/isArrayModel}}
|
||||
{{#requiredVars}}
|
||||
{{^defaultValue}}
|
||||
**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}}
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
allowed_values = {
|
||||
{{#isEnum}}
|
||||
('value',): {
|
||||
{{#isNullable}}
|
||||
'None': None,
|
||||
{{/isNullable}}
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
'{{name}}': {{{value}}},
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
},
|
||||
{{/isEnum}}
|
||||
{{#requiredVars}}
|
||||
{{#isEnum}}
|
||||
('{{name}}',): {
|
||||
@@ -30,70 +42,24 @@
|
||||
}
|
||||
|
||||
validations = {
|
||||
{{#isAlias}}
|
||||
{{^isEnum}}
|
||||
{{^isArrayModel}}
|
||||
('value',): {
|
||||
{{> python-experimental/model_templates/validations }}
|
||||
{{/isArrayModel}}
|
||||
{{/isEnum}}
|
||||
{{/isAlias}}
|
||||
{{#requiredVars}}
|
||||
{{#hasValidation}}
|
||||
('{{name}}',): {
|
||||
{{#maxLength}}
|
||||
'max_length': {{maxLength}},
|
||||
{{/maxLength}}
|
||||
{{#minLength}}
|
||||
'min_length': {{minLength}},
|
||||
{{/minLength}}
|
||||
{{#maxItems}}
|
||||
'max_items': {{maxItems}},
|
||||
{{/maxItems}}
|
||||
{{#minItems}}
|
||||
'min_items': {{minItems}},
|
||||
{{/minItems}}
|
||||
{{#maximum}}
|
||||
{{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},
|
||||
{{/maximum}}
|
||||
{{#minimum}}
|
||||
{{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},
|
||||
{{/minimum}}
|
||||
{{#pattern}}
|
||||
'regex': {
|
||||
'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}}
|
||||
{{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}}
|
||||
},
|
||||
{{/pattern}}
|
||||
{{#multipleOf}}
|
||||
'multiple_of': {{multipleOf}},
|
||||
{{/multipleOf}}
|
||||
},
|
||||
{{> python-experimental/model_templates/validations }}
|
||||
{{/hasValidation}}
|
||||
{{/requiredVars}}
|
||||
{{#optionalVars}}
|
||||
{{#hasValidation}}
|
||||
('{{name}}',): {
|
||||
{{#maxLength}}
|
||||
'max_length': {{maxLength}},
|
||||
{{/maxLength}}
|
||||
{{#minLength}}
|
||||
'min_length': {{minLength}},
|
||||
{{/minLength}}
|
||||
{{#maxItems}}
|
||||
'max_items': {{maxItems}},
|
||||
{{/maxItems}}
|
||||
{{#minItems}}
|
||||
'min_items': {{minItems}},
|
||||
{{/minItems}}
|
||||
{{#maximum}}
|
||||
{{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},
|
||||
{{/maximum}}
|
||||
{{#minimum}}
|
||||
{{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},
|
||||
{{/minimum}}
|
||||
{{#pattern}}
|
||||
'regex': {
|
||||
'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}}
|
||||
{{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}}
|
||||
},
|
||||
{{/pattern}}
|
||||
{{#multipleOf}}
|
||||
'multiple_of': {{multipleOf}},
|
||||
{{/multipleOf}}
|
||||
},
|
||||
{{> python-experimental/model_templates/validations }}
|
||||
{{/hasValidation}}
|
||||
{{/optionalVars}}
|
||||
}
|
||||
@@ -113,6 +79,15 @@
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
{{#isAlias}}
|
||||
'value': ({{{dataType}}},),
|
||||
{{/isAlias}}
|
||||
{{#isEnum}}
|
||||
'value': ({{{dataType}}},),
|
||||
{{/isEnum}}
|
||||
{{#isArrayModel}}
|
||||
'value': ({{{dataType}}},),
|
||||
{{/isArrayModel}}
|
||||
{{#requiredVars}}
|
||||
'{{name}}': ({{{dataType}}},), # noqa: E501
|
||||
{{/requiredVars}}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
will be type checked and a TypeError will be
|
||||
raised if the wrong type is input.
|
||||
Defaults to True
|
||||
_path_to_item (tuple/list): This is a list of keys or values to
|
||||
drill down to the model in received_data
|
||||
when deserializing a response
|
||||
_spec_property_naming (bool): True if the variable names in the input data
|
||||
are serialized names, as specified in the OpenAPI document.
|
||||
False if the variable names in the input data
|
||||
are pythonic names, e.g. snake case (default)
|
||||
_configuration (Configuration): the instance to use when
|
||||
deserializing a file_type parameter.
|
||||
If passed, type conversion is attempted
|
||||
If omitted no type conversion is done.
|
||||
_visited_composed_classes (tuple): This stores a tuple of
|
||||
classes that we have traveled through so that
|
||||
if we see that class again we will not use its
|
||||
discriminator again.
|
||||
When traveling through a discriminator, the
|
||||
composed schema that is
|
||||
is traveled through is added to this set.
|
||||
For example if Animal has a discriminator
|
||||
petType and we pass in "Dog", and the class Dog
|
||||
allOf includes Animal, we move through Animal
|
||||
once using the discriminator, and pick Dog.
|
||||
Then in Dog, we will make an instance of the
|
||||
Animal class but this time we won't travel
|
||||
through its discriminator because we passed in
|
||||
_visited_composed_classes = (Animal,)
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
{{> python-experimental/model_templates/method_init_shared }}
|
||||
|
||||
{{#isEnum}}
|
||||
self.value = value
|
||||
{{/isEnum}}
|
||||
{{#requiredVars}}
|
||||
self.{{name}} = {{name}}
|
||||
{{/requiredVars}}
|
||||
|
||||
@@ -19,36 +19,7 @@
|
||||
{{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501
|
||||
{{/defaultValue}}
|
||||
{{/requiredVars}}
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
will be type checked and a TypeError will be
|
||||
raised if the wrong type is input.
|
||||
Defaults to True
|
||||
_path_to_item (tuple/list): This is a list of keys or values to
|
||||
drill down to the model in received_data
|
||||
when deserializing a response
|
||||
_spec_property_naming (bool): True if the variable names in the input data
|
||||
are serialized names, as specified in the OpenAPI document.
|
||||
False if the variable names in the input data
|
||||
are pythonic names, e.g. snake case (default)
|
||||
_configuration (Configuration): the instance to use when
|
||||
deserializing a file_type parameter.
|
||||
If passed, type conversion is attempted
|
||||
If omitted no type conversion is done.
|
||||
_visited_composed_classes (tuple): This stores a tuple of
|
||||
classes that we have traveled through so that
|
||||
if we see that class again we will not use its
|
||||
discriminator again.
|
||||
When traveling through a discriminator, the
|
||||
composed schema that is
|
||||
is traveled through is added to this set.
|
||||
For example if Animal has a discriminator
|
||||
petType and we pass in "Dog", and the class Dog
|
||||
allOf includes Animal, we move through Animal
|
||||
once using the discriminator, and pick Dog.
|
||||
Then in Dog, we will make an instance of the
|
||||
Animal class but this time we won't travel
|
||||
through its discriminator because we passed in
|
||||
_visited_composed_classes = (Animal,)
|
||||
{{> python-experimental/model_templates/docstring_init_required_kwargs }}
|
||||
{{#optionalVars}}
|
||||
{{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501
|
||||
{{/optionalVars}}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
required_properties = set([
|
||||
'_data_store',
|
||||
'_check_type',
|
||||
'_spec_property_naming',
|
||||
'_path_to_item',
|
||||
'_configuration',
|
||||
'_visited_composed_classes',
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self{{#hasRequired}}, value{{/hasRequired}}, *args, **kwargs):
|
||||
"""{{classname}} - a model defined in OpenAPI
|
||||
|
||||
{{#hasRequired}}
|
||||
Args:
|
||||
value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501
|
||||
|
||||
{{/hasRequired}}
|
||||
Keyword Args:
|
||||
{{^hasRequired}}
|
||||
value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501
|
||||
{{/hasRequired}}
|
||||
{{> python-experimental/model_templates/docstring_init_required_kwargs }}
|
||||
"""
|
||||
|
||||
{{^hasRequired}}
|
||||
if 'value' in kwargs:
|
||||
value = kwargs.pop('value')
|
||||
elif args:
|
||||
args = list(args)
|
||||
value = args.pop(0)
|
||||
else:
|
||||
value = {{{defaultValue}}}
|
||||
{{/hasRequired}}
|
||||
_check_type = kwargs.pop('_check_type', True)
|
||||
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||
_configuration = kwargs.pop('_configuration', None)
|
||||
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||
|
||||
if args:
|
||||
raise ApiTypeError(
|
||||
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||
args,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
self._data_store = {}
|
||||
self._check_type = _check_type
|
||||
self._spec_property_naming = _spec_property_naming
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
self.value = value
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
@@ -15,4 +15,4 @@ class {{unescapedDescription}}(ModelSimple):
|
||||
|
||||
_composed_schemas = None
|
||||
|
||||
{{> python-experimental/model_templates/method_init_normal}}
|
||||
{{> python-experimental/model_templates/method_init_simple}}
|
||||
@@ -0,0 +1,28 @@
|
||||
{{#maxLength}}
|
||||
'max_length': {{maxLength}},
|
||||
{{/maxLength}}
|
||||
{{#minLength}}
|
||||
'min_length': {{minLength}},
|
||||
{{/minLength}}
|
||||
{{#maxItems}}
|
||||
'max_items': {{maxItems}},
|
||||
{{/maxItems}}
|
||||
{{#minItems}}
|
||||
'min_items': {{minItems}},
|
||||
{{/minItems}}
|
||||
{{#maximum}}
|
||||
{{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},
|
||||
{{/maximum}}
|
||||
{{#minimum}}
|
||||
{{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},
|
||||
{{/minimum}}
|
||||
{{#pattern}}
|
||||
'regex': {
|
||||
'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}}
|
||||
{{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}}
|
||||
},
|
||||
{{/pattern}}
|
||||
{{#multipleOf}}
|
||||
'multiple_of': {{multipleOf}},
|
||||
{{/multipleOf}}
|
||||
},
|
||||
@@ -54,6 +54,58 @@ class cached_property(object):
|
||||
return result
|
||||
|
||||
|
||||
PRIMITIVE_TYPES = (list, float, int, bool, datetime, date, str, file_type)
|
||||
|
||||
def allows_single_value_input(cls):
|
||||
"""
|
||||
This function returns True if the input composed schema model or any
|
||||
descendant model allows a value only input
|
||||
This is true for cases where oneOf contains items like:
|
||||
oneOf:
|
||||
- float
|
||||
- NumberWithValidation
|
||||
- StringEnum
|
||||
- ArrayModel
|
||||
- null
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if (
|
||||
issubclass(cls, ModelSimple) or
|
||||
cls in PRIMITIVE_TYPES
|
||||
):
|
||||
return True
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return False
|
||||
return any(allows_single_value_input(c) for c in cls._composed_schemas['oneOf'])
|
||||
return False
|
||||
|
||||
def composed_model_input_classes(cls):
|
||||
"""
|
||||
This function returns a list of the possible models that can be accepted as
|
||||
inputs.
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if issubclass(cls, ModelSimple) or cls in PRIMITIVE_TYPES:
|
||||
return [cls]
|
||||
elif issubclass(cls, ModelNormal):
|
||||
if cls.discriminator is None:
|
||||
return [cls]
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return []
|
||||
if cls.discriminator is None:
|
||||
input_classes = []
|
||||
for c in cls._composed_schemas['oneOf']:
|
||||
input_classes.extend(composed_model_input_classes(c))
|
||||
return input_classes
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
return []
|
||||
|
||||
|
||||
class OpenApiModel(object):
|
||||
"""The base class for all OpenAPIModels"""
|
||||
|
||||
@@ -66,9 +118,17 @@ class OpenApiModel(object):
|
||||
# pick a new schema/class to instantiate because a discriminator
|
||||
# propertyName value was passed in
|
||||
|
||||
if len(args) == 1 and args[0] is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if arg is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
|
||||
if issubclass(cls, ModelComposed) and allows_single_value_input(cls):
|
||||
model_kwargs = {}
|
||||
oneof_instance = get_oneof_instance(cls, model_kwargs, kwargs, model_arg=arg)
|
||||
return oneof_instance
|
||||
|
||||
|
||||
visited_composed_classes = kwargs.get('_visited_composed_classes', ())
|
||||
if (
|
||||
@@ -241,6 +301,10 @@ UPCONVERSION_TYPE_PAIRS = (
|
||||
(int, float), # A float may be serialized as an integer, e.g. '3' is a valid serialized float.
|
||||
(list, ModelComposed),
|
||||
(dict, ModelComposed),
|
||||
(str, ModelComposed),
|
||||
(int, ModelComposed),
|
||||
(float, ModelComposed),
|
||||
(list, ModelComposed),
|
||||
(list, ModelNormal),
|
||||
(dict, ModelNormal),
|
||||
(str, ModelSimple),
|
||||
@@ -619,20 +683,53 @@ def remove_uncoercible(required_types_classes, current_item, spec_property_namin
|
||||
results_classes.append(required_type_class)
|
||||
return results_classes
|
||||
|
||||
def get_discriminated_classes(cls):
|
||||
"""
|
||||
Returns all the classes that a discriminator converts to
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
possible_classes = []
|
||||
key = list(cls.discriminator.keys())[0]
|
||||
if is_type_nullable(cls):
|
||||
possible_classes.append(cls)
|
||||
for discr_cls in cls.discriminator[key].values():
|
||||
if hasattr(discr_cls, 'discriminator') and discr_cls.discriminator is not None:
|
||||
possible_classes.extend(get_discriminated_classes(discr_cls))
|
||||
else:
|
||||
possible_classes.append(discr_cls)
|
||||
return possible_classes
|
||||
|
||||
def get_required_type_classes(required_types_mixed):
|
||||
|
||||
def get_possible_classes(cls, from_server_context):
|
||||
# TODO: lru_cache this
|
||||
possible_classes = [cls]
|
||||
if from_server_context:
|
||||
return possible_classes
|
||||
if hasattr(cls, 'discriminator') and cls.discriminator is not None:
|
||||
possible_classes = []
|
||||
possible_classes.extend(get_discriminated_classes(cls))
|
||||
elif issubclass(cls, ModelComposed):
|
||||
possible_classes.extend(composed_model_input_classes(cls))
|
||||
return possible_classes
|
||||
|
||||
|
||||
def get_required_type_classes(required_types_mixed, spec_property_naming):
|
||||
"""Converts the tuple required_types into a tuple and a dict described
|
||||
below
|
||||
|
||||
Args:
|
||||
required_types_mixed (tuple/list): will contain either classes or
|
||||
instance of list or dict
|
||||
spec_property_naming (bool): if True these values came from the
|
||||
server, and we use the data types in our endpoints.
|
||||
If False, we are client side and we need to include
|
||||
oneOf and discriminator classes inside the data types in our endpoints
|
||||
|
||||
Returns:
|
||||
(valid_classes, dict_valid_class_to_child_types_mixed):
|
||||
valid_classes (tuple): the valid classes that the current item
|
||||
should be
|
||||
dict_valid_class_to_child_types_mixed (doct):
|
||||
dict_valid_class_to_child_types_mixed (dict):
|
||||
valid_class (class): this is the key
|
||||
child_types_mixed (list/dict/tuple): describes the valid child
|
||||
types
|
||||
@@ -650,7 +747,7 @@ def get_required_type_classes(required_types_mixed):
|
||||
valid_classes.append(dict)
|
||||
child_req_types_by_current_type[dict] = required_type[str]
|
||||
else:
|
||||
valid_classes.append(required_type)
|
||||
valid_classes.extend(get_possible_classes(required_type, spec_property_naming))
|
||||
return tuple(valid_classes), child_req_types_by_current_type
|
||||
|
||||
|
||||
@@ -803,7 +900,7 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
"""Deserializes model_data to model instance.
|
||||
|
||||
Args:
|
||||
model_data (list/dict): data to instantiate the model
|
||||
model_data (int/str/float/bool/none_type/list/dict): data to instantiate the model
|
||||
model_class (OpenApiModel): the model class
|
||||
path_to_item (list): path to the model in the received data
|
||||
check_type (bool): whether to check the data tupe for the values in
|
||||
@@ -829,14 +926,14 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
_spec_property_naming=spec_property_naming)
|
||||
|
||||
if issubclass(model_class, ModelSimple):
|
||||
instance = model_class(value=model_data, **kw_args)
|
||||
return instance
|
||||
if isinstance(model_data, list):
|
||||
instance = model_class(*model_data, **kw_args)
|
||||
return model_class(model_data, **kw_args)
|
||||
elif isinstance(model_data, list):
|
||||
return model_class(*model_data, **kw_args)
|
||||
if isinstance(model_data, dict):
|
||||
kw_args.update(model_data)
|
||||
instance = model_class(**kw_args)
|
||||
return instance
|
||||
return model_class(**kw_args)
|
||||
elif isinstance(model_data, PRIMITIVE_TYPES):
|
||||
return model_class(model_data, **kw_args)
|
||||
|
||||
|
||||
def deserialize_file(response_data, configuration, content_disposition=None):
|
||||
@@ -1019,7 +1116,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
Raises:
|
||||
ApiTypeError
|
||||
"""
|
||||
results = get_required_type_classes(required_types_mixed)
|
||||
results = get_required_type_classes(required_types_mixed, spec_property_naming)
|
||||
valid_classes, child_req_types_by_current_type = results
|
||||
|
||||
input_class_simple = get_simple_class(input_value)
|
||||
@@ -1256,7 +1353,7 @@ def get_allof_instances(self, model_args, constant_args):
|
||||
return composed_instances
|
||||
|
||||
|
||||
def get_oneof_instance(self, model_args, constant_args):
|
||||
def get_oneof_instance(cls, model_kwargs, constant_kwargs, model_arg=None):
|
||||
"""
|
||||
Find the oneOf schema that matches the input data (e.g. payload).
|
||||
If exactly one schema matches the input data, an instance of that schema
|
||||
@@ -1264,25 +1361,33 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
If zero or more than one schema match the input data, an exception is raised.
|
||||
In OAS 3.x, the payload MUST, by validation, match exactly one of the
|
||||
schemas described by oneOf.
|
||||
|
||||
Args:
|
||||
self: the class we are handling
|
||||
model_args (dict): var_name to var_value
|
||||
cls: the class we are handling
|
||||
model_kwargs (dict): var_name to var_value
|
||||
The input data, e.g. the payload that must match a oneOf schema
|
||||
in the OpenAPI document.
|
||||
constant_args (dict): var_name to var_value
|
||||
constant_kwargs (dict): var_name to var_value
|
||||
args that every model requires, including configuration, server
|
||||
and path to item.
|
||||
|
||||
Kwargs:
|
||||
model_arg: (int, float, bool, str, date, datetime, ModelSimple, None):
|
||||
the value to assign to a primitive class or ModelSimple class
|
||||
Notes:
|
||||
- this is only passed in when oneOf includes types which are not object
|
||||
- None is used to suppress handling of model_arg, nullable models are handled in __new__
|
||||
|
||||
Returns
|
||||
oneof_instance (instance)
|
||||
"""
|
||||
if len(self._composed_schemas['oneOf']) == 0:
|
||||
if len(cls._composed_schemas['oneOf']) == 0:
|
||||
return None
|
||||
|
||||
oneof_instances = []
|
||||
# Iterate over each oneOf schema and determine if the input data
|
||||
# matches the oneOf schemas.
|
||||
for oneof_class in self._composed_schemas['oneOf']:
|
||||
for oneof_class in cls._composed_schemas['oneOf']:
|
||||
# The composed oneOf schema allows the 'null' type and the input data
|
||||
# is the null value. This is a OAS >= 3.1 feature.
|
||||
if oneof_class is none_type:
|
||||
@@ -1290,28 +1395,45 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
# none_type deserialization is handled in the __new__ method
|
||||
continue
|
||||
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_args, oneof_class)
|
||||
single_value_input = allows_single_value_input(oneof_class)
|
||||
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
if not single_value_input:
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_kwargs, oneof_class)
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_kwargs)
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_args)
|
||||
try:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
if not single_value_input:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
else:
|
||||
if issubclass(oneof_class, ModelSimple):
|
||||
oneof_instance = oneof_class(model_arg, **constant_kwargs)
|
||||
elif oneof_class in PRIMITIVE_TYPES:
|
||||
oneof_instance = validate_and_convert_types(
|
||||
model_arg,
|
||||
(oneof_class,),
|
||||
constant_kwargs['_path_to_item'],
|
||||
constant_kwargs['_spec_property_naming'],
|
||||
constant_kwargs['_check_type'],
|
||||
configuration=constant_kwargs['_configuration']
|
||||
)
|
||||
oneof_instances.append(oneof_instance)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -1319,13 +1441,13 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. None "
|
||||
"of the oneOf schemas matched the input data." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
elif len(oneof_instances) > 1:
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. Multiple "
|
||||
"oneOf schemas matched the inputs, but a max of one is allowed." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
return oneof_instances[0]
|
||||
|
||||
@@ -1465,7 +1587,7 @@ def validate_get_composed_info(constant_args, model_args, self):
|
||||
composed_instances = []
|
||||
allof_instances = get_allof_instances(self, model_args, constant_args)
|
||||
composed_instances.extend(allof_instances)
|
||||
oneof_instance = get_oneof_instance(self, model_args, constant_args)
|
||||
oneof_instance = get_oneof_instance(self.__class__, model_args, constant_args)
|
||||
if oneof_instance is not None:
|
||||
composed_instances.append(oneof_instance)
|
||||
anyof_instances = get_anyof_instances(self, model_args, constant_args)
|
||||
|
||||
@@ -270,7 +270,7 @@ public class PythonClientExperimentalTest {
|
||||
Assert.assertEquals(cm.classname, "sample.Sample");
|
||||
Assert.assertEquals(cm.classVarName, "sample");
|
||||
Assert.assertEquals(cm.description, "an array model");
|
||||
Assert.assertEquals(cm.vars.size(), 1); // there is one value for Childer definition
|
||||
Assert.assertEquals(cm.vars.size(), 0); // the array model has no vars
|
||||
Assert.assertEquals(cm.parent, "list");
|
||||
Assert.assertEquals(cm.imports.size(), 1);
|
||||
Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("children.Children")).size(), 1);
|
||||
@@ -292,7 +292,7 @@ public class PythonClientExperimentalTest {
|
||||
Assert.assertEquals(cm.description, "a map model");
|
||||
Assert.assertEquals(cm.vars.size(), 0);
|
||||
Assert.assertEquals(cm.parent, null);
|
||||
Assert.assertEquals(cm.imports.size(), 0);
|
||||
Assert.assertEquals(cm.imports.size(), 1);
|
||||
}
|
||||
|
||||
@Test(description = "parse date and date-time example value")
|
||||
|
||||
@@ -905,6 +905,26 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AnimalFarm'
|
||||
x-codegen-request-body-name: body
|
||||
/fake/refs/composed_one_of_number_with_validations:
|
||||
post:
|
||||
tags:
|
||||
- fake
|
||||
description: Test serialization of object with $refed properties
|
||||
operationId: ComposedOneOfNumberWithValidations
|
||||
requestBody:
|
||||
description: Input model
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ComposedOneOfNumberWithValidations'
|
||||
required: false
|
||||
responses:
|
||||
'200':
|
||||
description: Output model
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ComposedOneOfNumberWithValidations'
|
||||
/fake/refs/object_model_with_ref_props:
|
||||
post:
|
||||
tags:
|
||||
@@ -1837,6 +1857,14 @@ components:
|
||||
type: number
|
||||
minimum: 10
|
||||
maximum: 20
|
||||
ComposedOneOfNumberWithValidations:
|
||||
description: this is a model that allows payloads of type object or number
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/NumberWithValidations'
|
||||
- $ref: '#/components/schemas/Animal'
|
||||
- type: 'null'
|
||||
- type: string
|
||||
format: date
|
||||
Number:
|
||||
type: number
|
||||
String:
|
||||
@@ -2188,4 +2216,4 @@ components:
|
||||
type: string
|
||||
default: '2010-01-01T10:10:10.000111+01:00'
|
||||
example: '2010-01-01T10:10:10.000111+01:00'
|
||||
format: date-time
|
||||
format: date-time
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**value** | **str** | | defaults to '-efg'
|
||||
**value** | **str** | | if omitted the server will use the default value of '-efg', must be one of ["_abc", "-efg", "(xyz)", ]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**value** | **str** | |
|
||||
**value** | **str** | | must be one of ["placed", "approved", "delivered", ]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class AnimalFarm(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': ([animal.Animal],), # noqa: E501
|
||||
'value': ([animal.Animal],),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,11 +102,11 @@ class AnimalFarm(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, value, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""animal_farm.AnimalFarm - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value ([animal.Animal]):
|
||||
value ([animal.Animal]): # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -163,13 +163,13 @@ class AnimalFarm(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -81,7 +81,7 @@ class EnumClass(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (str,), # noqa: E501
|
||||
'value': (str,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,13 +102,13 @@ class EnumClass(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""enum_class.EnumClass - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (str): if omitted the server will use the default value of '-efg', must be one of ["_abc", "-efg", "(xyz)", ] # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
value (str): defaults to '-efg', must be one of ["_abc", "-efg", "(xyz)", ] # noqa: E501
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
will be type checked and a TypeError will be
|
||||
raised if the wrong type is input.
|
||||
@@ -141,7 +141,6 @@ class EnumClass(ModelSimple):
|
||||
_visited_composed_classes = (Animal,)
|
||||
"""
|
||||
|
||||
value = kwargs.get('value', '-efg')
|
||||
_check_type = kwargs.pop('_check_type', True)
|
||||
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||
@@ -164,13 +163,13 @@ class EnumClass(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -80,7 +80,7 @@ class NumberWithValidations(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (float,), # noqa: E501
|
||||
'value': (float,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -101,11 +101,11 @@ class NumberWithValidations(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, value, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""number_with_validations.NumberWithValidations - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (float):
|
||||
value (float): # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -162,13 +162,13 @@ class NumberWithValidations(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -81,7 +81,7 @@ class StringEnum(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (str,), # noqa: E501
|
||||
'value': (str,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,11 +102,11 @@ class StringEnum(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, value, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""string_enum.StringEnum - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (str):
|
||||
value (str):, must be one of ["placed", "approved", "delivered", ] # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -163,13 +163,13 @@ class StringEnum(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -62,6 +62,58 @@ class cached_property(object):
|
||||
return result
|
||||
|
||||
|
||||
PRIMITIVE_TYPES = (list, float, int, bool, datetime, date, str, file_type)
|
||||
|
||||
def allows_single_value_input(cls):
|
||||
"""
|
||||
This function returns True if the input composed schema model or any
|
||||
descendant model allows a value only input
|
||||
This is true for cases where oneOf contains items like:
|
||||
oneOf:
|
||||
- float
|
||||
- NumberWithValidation
|
||||
- StringEnum
|
||||
- ArrayModel
|
||||
- null
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if (
|
||||
issubclass(cls, ModelSimple) or
|
||||
cls in PRIMITIVE_TYPES
|
||||
):
|
||||
return True
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return False
|
||||
return any(allows_single_value_input(c) for c in cls._composed_schemas['oneOf'])
|
||||
return False
|
||||
|
||||
def composed_model_input_classes(cls):
|
||||
"""
|
||||
This function returns a list of the possible models that can be accepted as
|
||||
inputs.
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if issubclass(cls, ModelSimple) or cls in PRIMITIVE_TYPES:
|
||||
return [cls]
|
||||
elif issubclass(cls, ModelNormal):
|
||||
if cls.discriminator is None:
|
||||
return [cls]
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return []
|
||||
if cls.discriminator is None:
|
||||
input_classes = []
|
||||
for c in cls._composed_schemas['oneOf']:
|
||||
input_classes.extend(composed_model_input_classes(c))
|
||||
return input_classes
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
return []
|
||||
|
||||
|
||||
class OpenApiModel(object):
|
||||
"""The base class for all OpenAPIModels"""
|
||||
|
||||
@@ -138,9 +190,17 @@ class OpenApiModel(object):
|
||||
# pick a new schema/class to instantiate because a discriminator
|
||||
# propertyName value was passed in
|
||||
|
||||
if len(args) == 1 and args[0] is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if arg is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
|
||||
if issubclass(cls, ModelComposed) and allows_single_value_input(cls):
|
||||
model_kwargs = {}
|
||||
oneof_instance = get_oneof_instance(cls, model_kwargs, kwargs, model_arg=arg)
|
||||
return oneof_instance
|
||||
|
||||
|
||||
visited_composed_classes = kwargs.get('_visited_composed_classes', ())
|
||||
if (
|
||||
@@ -508,6 +568,10 @@ UPCONVERSION_TYPE_PAIRS = (
|
||||
(int, float), # A float may be serialized as an integer, e.g. '3' is a valid serialized float.
|
||||
(list, ModelComposed),
|
||||
(dict, ModelComposed),
|
||||
(str, ModelComposed),
|
||||
(int, ModelComposed),
|
||||
(float, ModelComposed),
|
||||
(list, ModelComposed),
|
||||
(list, ModelNormal),
|
||||
(dict, ModelNormal),
|
||||
(str, ModelSimple),
|
||||
@@ -886,20 +950,53 @@ def remove_uncoercible(required_types_classes, current_item, spec_property_namin
|
||||
results_classes.append(required_type_class)
|
||||
return results_classes
|
||||
|
||||
def get_discriminated_classes(cls):
|
||||
"""
|
||||
Returns all the classes that a discriminator converts to
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
possible_classes = []
|
||||
key = list(cls.discriminator.keys())[0]
|
||||
if is_type_nullable(cls):
|
||||
possible_classes.append(cls)
|
||||
for discr_cls in cls.discriminator[key].values():
|
||||
if hasattr(discr_cls, 'discriminator') and discr_cls.discriminator is not None:
|
||||
possible_classes.extend(get_discriminated_classes(discr_cls))
|
||||
else:
|
||||
possible_classes.append(discr_cls)
|
||||
return possible_classes
|
||||
|
||||
def get_required_type_classes(required_types_mixed):
|
||||
|
||||
def get_possible_classes(cls, from_server_context):
|
||||
# TODO: lru_cache this
|
||||
possible_classes = [cls]
|
||||
if from_server_context:
|
||||
return possible_classes
|
||||
if hasattr(cls, 'discriminator') and cls.discriminator is not None:
|
||||
possible_classes = []
|
||||
possible_classes.extend(get_discriminated_classes(cls))
|
||||
elif issubclass(cls, ModelComposed):
|
||||
possible_classes.extend(composed_model_input_classes(cls))
|
||||
return possible_classes
|
||||
|
||||
|
||||
def get_required_type_classes(required_types_mixed, spec_property_naming):
|
||||
"""Converts the tuple required_types into a tuple and a dict described
|
||||
below
|
||||
|
||||
Args:
|
||||
required_types_mixed (tuple/list): will contain either classes or
|
||||
instance of list or dict
|
||||
spec_property_naming (bool): if True these values came from the
|
||||
server, and we use the data types in our endpoints.
|
||||
If False, we are client side and we need to include
|
||||
oneOf and discriminator classes inside the data types in our endpoints
|
||||
|
||||
Returns:
|
||||
(valid_classes, dict_valid_class_to_child_types_mixed):
|
||||
valid_classes (tuple): the valid classes that the current item
|
||||
should be
|
||||
dict_valid_class_to_child_types_mixed (doct):
|
||||
dict_valid_class_to_child_types_mixed (dict):
|
||||
valid_class (class): this is the key
|
||||
child_types_mixed (list/dict/tuple): describes the valid child
|
||||
types
|
||||
@@ -917,7 +1014,7 @@ def get_required_type_classes(required_types_mixed):
|
||||
valid_classes.append(dict)
|
||||
child_req_types_by_current_type[dict] = required_type[str]
|
||||
else:
|
||||
valid_classes.append(required_type)
|
||||
valid_classes.extend(get_possible_classes(required_type, spec_property_naming))
|
||||
return tuple(valid_classes), child_req_types_by_current_type
|
||||
|
||||
|
||||
@@ -1070,7 +1167,7 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
"""Deserializes model_data to model instance.
|
||||
|
||||
Args:
|
||||
model_data (list/dict): data to instantiate the model
|
||||
model_data (int/str/float/bool/none_type/list/dict): data to instantiate the model
|
||||
model_class (OpenApiModel): the model class
|
||||
path_to_item (list): path to the model in the received data
|
||||
check_type (bool): whether to check the data tupe for the values in
|
||||
@@ -1096,14 +1193,14 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
_spec_property_naming=spec_property_naming)
|
||||
|
||||
if issubclass(model_class, ModelSimple):
|
||||
instance = model_class(value=model_data, **kw_args)
|
||||
return instance
|
||||
if isinstance(model_data, list):
|
||||
instance = model_class(*model_data, **kw_args)
|
||||
return model_class(model_data, **kw_args)
|
||||
elif isinstance(model_data, list):
|
||||
return model_class(*model_data, **kw_args)
|
||||
if isinstance(model_data, dict):
|
||||
kw_args.update(model_data)
|
||||
instance = model_class(**kw_args)
|
||||
return instance
|
||||
return model_class(**kw_args)
|
||||
elif isinstance(model_data, PRIMITIVE_TYPES):
|
||||
return model_class(model_data, **kw_args)
|
||||
|
||||
|
||||
def deserialize_file(response_data, configuration, content_disposition=None):
|
||||
@@ -1286,7 +1383,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
Raises:
|
||||
ApiTypeError
|
||||
"""
|
||||
results = get_required_type_classes(required_types_mixed)
|
||||
results = get_required_type_classes(required_types_mixed, spec_property_naming)
|
||||
valid_classes, child_req_types_by_current_type = results
|
||||
|
||||
input_class_simple = get_simple_class(input_value)
|
||||
@@ -1523,7 +1620,7 @@ def get_allof_instances(self, model_args, constant_args):
|
||||
return composed_instances
|
||||
|
||||
|
||||
def get_oneof_instance(self, model_args, constant_args):
|
||||
def get_oneof_instance(cls, model_kwargs, constant_kwargs, model_arg=None):
|
||||
"""
|
||||
Find the oneOf schema that matches the input data (e.g. payload).
|
||||
If exactly one schema matches the input data, an instance of that schema
|
||||
@@ -1531,25 +1628,33 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
If zero or more than one schema match the input data, an exception is raised.
|
||||
In OAS 3.x, the payload MUST, by validation, match exactly one of the
|
||||
schemas described by oneOf.
|
||||
|
||||
Args:
|
||||
self: the class we are handling
|
||||
model_args (dict): var_name to var_value
|
||||
cls: the class we are handling
|
||||
model_kwargs (dict): var_name to var_value
|
||||
The input data, e.g. the payload that must match a oneOf schema
|
||||
in the OpenAPI document.
|
||||
constant_args (dict): var_name to var_value
|
||||
constant_kwargs (dict): var_name to var_value
|
||||
args that every model requires, including configuration, server
|
||||
and path to item.
|
||||
|
||||
Kwargs:
|
||||
model_arg: (int, float, bool, str, date, datetime, ModelSimple, None):
|
||||
the value to assign to a primitive class or ModelSimple class
|
||||
Notes:
|
||||
- this is only passed in when oneOf includes types which are not object
|
||||
- None is used to suppress handling of model_arg, nullable models are handled in __new__
|
||||
|
||||
Returns
|
||||
oneof_instance (instance)
|
||||
"""
|
||||
if len(self._composed_schemas['oneOf']) == 0:
|
||||
if len(cls._composed_schemas['oneOf']) == 0:
|
||||
return None
|
||||
|
||||
oneof_instances = []
|
||||
# Iterate over each oneOf schema and determine if the input data
|
||||
# matches the oneOf schemas.
|
||||
for oneof_class in self._composed_schemas['oneOf']:
|
||||
for oneof_class in cls._composed_schemas['oneOf']:
|
||||
# The composed oneOf schema allows the 'null' type and the input data
|
||||
# is the null value. This is a OAS >= 3.1 feature.
|
||||
if oneof_class is none_type:
|
||||
@@ -1557,28 +1662,45 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
# none_type deserialization is handled in the __new__ method
|
||||
continue
|
||||
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_args, oneof_class)
|
||||
single_value_input = allows_single_value_input(oneof_class)
|
||||
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
if not single_value_input:
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_kwargs, oneof_class)
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_kwargs)
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_args)
|
||||
try:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
if not single_value_input:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
else:
|
||||
if issubclass(oneof_class, ModelSimple):
|
||||
oneof_instance = oneof_class(model_arg, **constant_kwargs)
|
||||
elif oneof_class in PRIMITIVE_TYPES:
|
||||
oneof_instance = validate_and_convert_types(
|
||||
model_arg,
|
||||
(oneof_class,),
|
||||
constant_kwargs['_path_to_item'],
|
||||
constant_kwargs['_spec_property_naming'],
|
||||
constant_kwargs['_check_type'],
|
||||
configuration=constant_kwargs['_configuration']
|
||||
)
|
||||
oneof_instances.append(oneof_instance)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -1586,13 +1708,13 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. None "
|
||||
"of the oneOf schemas matched the input data." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
elif len(oneof_instances) > 1:
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. Multiple "
|
||||
"oneOf schemas matched the inputs, but a max of one is allowed." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
return oneof_instances[0]
|
||||
|
||||
@@ -1732,7 +1854,7 @@ def validate_get_composed_info(constant_args, model_args, self):
|
||||
composed_instances = []
|
||||
allof_instances = get_allof_instances(self, model_args, constant_args)
|
||||
composed_instances.extend(allof_instances)
|
||||
oneof_instance = get_oneof_instance(self, model_args, constant_args)
|
||||
oneof_instance = get_oneof_instance(self.__class__, model_args, constant_args)
|
||||
if oneof_instance is not None:
|
||||
composed_instances.append(oneof_instance)
|
||||
anyof_instances = get_anyof_instances(self, model_args, constant_args)
|
||||
|
||||
@@ -62,6 +62,58 @@ class cached_property(object):
|
||||
return result
|
||||
|
||||
|
||||
PRIMITIVE_TYPES = (list, float, int, bool, datetime, date, str, file_type)
|
||||
|
||||
def allows_single_value_input(cls):
|
||||
"""
|
||||
This function returns True if the input composed schema model or any
|
||||
descendant model allows a value only input
|
||||
This is true for cases where oneOf contains items like:
|
||||
oneOf:
|
||||
- float
|
||||
- NumberWithValidation
|
||||
- StringEnum
|
||||
- ArrayModel
|
||||
- null
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if (
|
||||
issubclass(cls, ModelSimple) or
|
||||
cls in PRIMITIVE_TYPES
|
||||
):
|
||||
return True
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return False
|
||||
return any(allows_single_value_input(c) for c in cls._composed_schemas['oneOf'])
|
||||
return False
|
||||
|
||||
def composed_model_input_classes(cls):
|
||||
"""
|
||||
This function returns a list of the possible models that can be accepted as
|
||||
inputs.
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if issubclass(cls, ModelSimple) or cls in PRIMITIVE_TYPES:
|
||||
return [cls]
|
||||
elif issubclass(cls, ModelNormal):
|
||||
if cls.discriminator is None:
|
||||
return [cls]
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return []
|
||||
if cls.discriminator is None:
|
||||
input_classes = []
|
||||
for c in cls._composed_schemas['oneOf']:
|
||||
input_classes.extend(composed_model_input_classes(c))
|
||||
return input_classes
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
return []
|
||||
|
||||
|
||||
class OpenApiModel(object):
|
||||
"""The base class for all OpenAPIModels"""
|
||||
|
||||
@@ -138,9 +190,17 @@ class OpenApiModel(object):
|
||||
# pick a new schema/class to instantiate because a discriminator
|
||||
# propertyName value was passed in
|
||||
|
||||
if len(args) == 1 and args[0] is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if arg is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
|
||||
if issubclass(cls, ModelComposed) and allows_single_value_input(cls):
|
||||
model_kwargs = {}
|
||||
oneof_instance = get_oneof_instance(cls, model_kwargs, kwargs, model_arg=arg)
|
||||
return oneof_instance
|
||||
|
||||
|
||||
visited_composed_classes = kwargs.get('_visited_composed_classes', ())
|
||||
if (
|
||||
@@ -508,6 +568,10 @@ UPCONVERSION_TYPE_PAIRS = (
|
||||
(int, float), # A float may be serialized as an integer, e.g. '3' is a valid serialized float.
|
||||
(list, ModelComposed),
|
||||
(dict, ModelComposed),
|
||||
(str, ModelComposed),
|
||||
(int, ModelComposed),
|
||||
(float, ModelComposed),
|
||||
(list, ModelComposed),
|
||||
(list, ModelNormal),
|
||||
(dict, ModelNormal),
|
||||
(str, ModelSimple),
|
||||
@@ -886,20 +950,53 @@ def remove_uncoercible(required_types_classes, current_item, spec_property_namin
|
||||
results_classes.append(required_type_class)
|
||||
return results_classes
|
||||
|
||||
def get_discriminated_classes(cls):
|
||||
"""
|
||||
Returns all the classes that a discriminator converts to
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
possible_classes = []
|
||||
key = list(cls.discriminator.keys())[0]
|
||||
if is_type_nullable(cls):
|
||||
possible_classes.append(cls)
|
||||
for discr_cls in cls.discriminator[key].values():
|
||||
if hasattr(discr_cls, 'discriminator') and discr_cls.discriminator is not None:
|
||||
possible_classes.extend(get_discriminated_classes(discr_cls))
|
||||
else:
|
||||
possible_classes.append(discr_cls)
|
||||
return possible_classes
|
||||
|
||||
def get_required_type_classes(required_types_mixed):
|
||||
|
||||
def get_possible_classes(cls, from_server_context):
|
||||
# TODO: lru_cache this
|
||||
possible_classes = [cls]
|
||||
if from_server_context:
|
||||
return possible_classes
|
||||
if hasattr(cls, 'discriminator') and cls.discriminator is not None:
|
||||
possible_classes = []
|
||||
possible_classes.extend(get_discriminated_classes(cls))
|
||||
elif issubclass(cls, ModelComposed):
|
||||
possible_classes.extend(composed_model_input_classes(cls))
|
||||
return possible_classes
|
||||
|
||||
|
||||
def get_required_type_classes(required_types_mixed, spec_property_naming):
|
||||
"""Converts the tuple required_types into a tuple and a dict described
|
||||
below
|
||||
|
||||
Args:
|
||||
required_types_mixed (tuple/list): will contain either classes or
|
||||
instance of list or dict
|
||||
spec_property_naming (bool): if True these values came from the
|
||||
server, and we use the data types in our endpoints.
|
||||
If False, we are client side and we need to include
|
||||
oneOf and discriminator classes inside the data types in our endpoints
|
||||
|
||||
Returns:
|
||||
(valid_classes, dict_valid_class_to_child_types_mixed):
|
||||
valid_classes (tuple): the valid classes that the current item
|
||||
should be
|
||||
dict_valid_class_to_child_types_mixed (doct):
|
||||
dict_valid_class_to_child_types_mixed (dict):
|
||||
valid_class (class): this is the key
|
||||
child_types_mixed (list/dict/tuple): describes the valid child
|
||||
types
|
||||
@@ -917,7 +1014,7 @@ def get_required_type_classes(required_types_mixed):
|
||||
valid_classes.append(dict)
|
||||
child_req_types_by_current_type[dict] = required_type[str]
|
||||
else:
|
||||
valid_classes.append(required_type)
|
||||
valid_classes.extend(get_possible_classes(required_type, spec_property_naming))
|
||||
return tuple(valid_classes), child_req_types_by_current_type
|
||||
|
||||
|
||||
@@ -1070,7 +1167,7 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
"""Deserializes model_data to model instance.
|
||||
|
||||
Args:
|
||||
model_data (list/dict): data to instantiate the model
|
||||
model_data (int/str/float/bool/none_type/list/dict): data to instantiate the model
|
||||
model_class (OpenApiModel): the model class
|
||||
path_to_item (list): path to the model in the received data
|
||||
check_type (bool): whether to check the data tupe for the values in
|
||||
@@ -1096,14 +1193,14 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
_spec_property_naming=spec_property_naming)
|
||||
|
||||
if issubclass(model_class, ModelSimple):
|
||||
instance = model_class(value=model_data, **kw_args)
|
||||
return instance
|
||||
if isinstance(model_data, list):
|
||||
instance = model_class(*model_data, **kw_args)
|
||||
return model_class(model_data, **kw_args)
|
||||
elif isinstance(model_data, list):
|
||||
return model_class(*model_data, **kw_args)
|
||||
if isinstance(model_data, dict):
|
||||
kw_args.update(model_data)
|
||||
instance = model_class(**kw_args)
|
||||
return instance
|
||||
return model_class(**kw_args)
|
||||
elif isinstance(model_data, PRIMITIVE_TYPES):
|
||||
return model_class(model_data, **kw_args)
|
||||
|
||||
|
||||
def deserialize_file(response_data, configuration, content_disposition=None):
|
||||
@@ -1286,7 +1383,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
Raises:
|
||||
ApiTypeError
|
||||
"""
|
||||
results = get_required_type_classes(required_types_mixed)
|
||||
results = get_required_type_classes(required_types_mixed, spec_property_naming)
|
||||
valid_classes, child_req_types_by_current_type = results
|
||||
|
||||
input_class_simple = get_simple_class(input_value)
|
||||
@@ -1523,7 +1620,7 @@ def get_allof_instances(self, model_args, constant_args):
|
||||
return composed_instances
|
||||
|
||||
|
||||
def get_oneof_instance(self, model_args, constant_args):
|
||||
def get_oneof_instance(cls, model_kwargs, constant_kwargs, model_arg=None):
|
||||
"""
|
||||
Find the oneOf schema that matches the input data (e.g. payload).
|
||||
If exactly one schema matches the input data, an instance of that schema
|
||||
@@ -1531,25 +1628,33 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
If zero or more than one schema match the input data, an exception is raised.
|
||||
In OAS 3.x, the payload MUST, by validation, match exactly one of the
|
||||
schemas described by oneOf.
|
||||
|
||||
Args:
|
||||
self: the class we are handling
|
||||
model_args (dict): var_name to var_value
|
||||
cls: the class we are handling
|
||||
model_kwargs (dict): var_name to var_value
|
||||
The input data, e.g. the payload that must match a oneOf schema
|
||||
in the OpenAPI document.
|
||||
constant_args (dict): var_name to var_value
|
||||
constant_kwargs (dict): var_name to var_value
|
||||
args that every model requires, including configuration, server
|
||||
and path to item.
|
||||
|
||||
Kwargs:
|
||||
model_arg: (int, float, bool, str, date, datetime, ModelSimple, None):
|
||||
the value to assign to a primitive class or ModelSimple class
|
||||
Notes:
|
||||
- this is only passed in when oneOf includes types which are not object
|
||||
- None is used to suppress handling of model_arg, nullable models are handled in __new__
|
||||
|
||||
Returns
|
||||
oneof_instance (instance)
|
||||
"""
|
||||
if len(self._composed_schemas['oneOf']) == 0:
|
||||
if len(cls._composed_schemas['oneOf']) == 0:
|
||||
return None
|
||||
|
||||
oneof_instances = []
|
||||
# Iterate over each oneOf schema and determine if the input data
|
||||
# matches the oneOf schemas.
|
||||
for oneof_class in self._composed_schemas['oneOf']:
|
||||
for oneof_class in cls._composed_schemas['oneOf']:
|
||||
# The composed oneOf schema allows the 'null' type and the input data
|
||||
# is the null value. This is a OAS >= 3.1 feature.
|
||||
if oneof_class is none_type:
|
||||
@@ -1557,28 +1662,45 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
# none_type deserialization is handled in the __new__ method
|
||||
continue
|
||||
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_args, oneof_class)
|
||||
single_value_input = allows_single_value_input(oneof_class)
|
||||
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
if not single_value_input:
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_kwargs, oneof_class)
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_kwargs)
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_args)
|
||||
try:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
if not single_value_input:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
else:
|
||||
if issubclass(oneof_class, ModelSimple):
|
||||
oneof_instance = oneof_class(model_arg, **constant_kwargs)
|
||||
elif oneof_class in PRIMITIVE_TYPES:
|
||||
oneof_instance = validate_and_convert_types(
|
||||
model_arg,
|
||||
(oneof_class,),
|
||||
constant_kwargs['_path_to_item'],
|
||||
constant_kwargs['_spec_property_naming'],
|
||||
constant_kwargs['_check_type'],
|
||||
configuration=constant_kwargs['_configuration']
|
||||
)
|
||||
oneof_instances.append(oneof_instance)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -1586,13 +1708,13 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. None "
|
||||
"of the oneOf schemas matched the input data." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
elif len(oneof_instances) > 1:
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. Multiple "
|
||||
"oneOf schemas matched the inputs, but a max of one is allowed." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
return oneof_instances[0]
|
||||
|
||||
@@ -1732,7 +1854,7 @@ def validate_get_composed_info(constant_args, model_args, self):
|
||||
composed_instances = []
|
||||
allof_instances = get_allof_instances(self, model_args, constant_args)
|
||||
composed_instances.extend(allof_instances)
|
||||
oneof_instance = get_oneof_instance(self, model_args, constant_args)
|
||||
oneof_instance = get_oneof_instance(self.__class__, model_args, constant_args)
|
||||
if oneof_instance is not None:
|
||||
composed_instances.append(oneof_instance)
|
||||
anyof_instances = get_anyof_instances(self, model_args, constant_args)
|
||||
|
||||
@@ -62,6 +62,58 @@ class cached_property(object):
|
||||
return result
|
||||
|
||||
|
||||
PRIMITIVE_TYPES = (list, float, int, bool, datetime, date, str, file_type)
|
||||
|
||||
def allows_single_value_input(cls):
|
||||
"""
|
||||
This function returns True if the input composed schema model or any
|
||||
descendant model allows a value only input
|
||||
This is true for cases where oneOf contains items like:
|
||||
oneOf:
|
||||
- float
|
||||
- NumberWithValidation
|
||||
- StringEnum
|
||||
- ArrayModel
|
||||
- null
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if (
|
||||
issubclass(cls, ModelSimple) or
|
||||
cls in PRIMITIVE_TYPES
|
||||
):
|
||||
return True
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return False
|
||||
return any(allows_single_value_input(c) for c in cls._composed_schemas['oneOf'])
|
||||
return False
|
||||
|
||||
def composed_model_input_classes(cls):
|
||||
"""
|
||||
This function returns a list of the possible models that can be accepted as
|
||||
inputs.
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if issubclass(cls, ModelSimple) or cls in PRIMITIVE_TYPES:
|
||||
return [cls]
|
||||
elif issubclass(cls, ModelNormal):
|
||||
if cls.discriminator is None:
|
||||
return [cls]
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return []
|
||||
if cls.discriminator is None:
|
||||
input_classes = []
|
||||
for c in cls._composed_schemas['oneOf']:
|
||||
input_classes.extend(composed_model_input_classes(c))
|
||||
return input_classes
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
return []
|
||||
|
||||
|
||||
class OpenApiModel(object):
|
||||
"""The base class for all OpenAPIModels"""
|
||||
|
||||
@@ -138,9 +190,17 @@ class OpenApiModel(object):
|
||||
# pick a new schema/class to instantiate because a discriminator
|
||||
# propertyName value was passed in
|
||||
|
||||
if len(args) == 1 and args[0] is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if arg is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
|
||||
if issubclass(cls, ModelComposed) and allows_single_value_input(cls):
|
||||
model_kwargs = {}
|
||||
oneof_instance = get_oneof_instance(cls, model_kwargs, kwargs, model_arg=arg)
|
||||
return oneof_instance
|
||||
|
||||
|
||||
visited_composed_classes = kwargs.get('_visited_composed_classes', ())
|
||||
if (
|
||||
@@ -508,6 +568,10 @@ UPCONVERSION_TYPE_PAIRS = (
|
||||
(int, float), # A float may be serialized as an integer, e.g. '3' is a valid serialized float.
|
||||
(list, ModelComposed),
|
||||
(dict, ModelComposed),
|
||||
(str, ModelComposed),
|
||||
(int, ModelComposed),
|
||||
(float, ModelComposed),
|
||||
(list, ModelComposed),
|
||||
(list, ModelNormal),
|
||||
(dict, ModelNormal),
|
||||
(str, ModelSimple),
|
||||
@@ -886,20 +950,53 @@ def remove_uncoercible(required_types_classes, current_item, spec_property_namin
|
||||
results_classes.append(required_type_class)
|
||||
return results_classes
|
||||
|
||||
def get_discriminated_classes(cls):
|
||||
"""
|
||||
Returns all the classes that a discriminator converts to
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
possible_classes = []
|
||||
key = list(cls.discriminator.keys())[0]
|
||||
if is_type_nullable(cls):
|
||||
possible_classes.append(cls)
|
||||
for discr_cls in cls.discriminator[key].values():
|
||||
if hasattr(discr_cls, 'discriminator') and discr_cls.discriminator is not None:
|
||||
possible_classes.extend(get_discriminated_classes(discr_cls))
|
||||
else:
|
||||
possible_classes.append(discr_cls)
|
||||
return possible_classes
|
||||
|
||||
def get_required_type_classes(required_types_mixed):
|
||||
|
||||
def get_possible_classes(cls, from_server_context):
|
||||
# TODO: lru_cache this
|
||||
possible_classes = [cls]
|
||||
if from_server_context:
|
||||
return possible_classes
|
||||
if hasattr(cls, 'discriminator') and cls.discriminator is not None:
|
||||
possible_classes = []
|
||||
possible_classes.extend(get_discriminated_classes(cls))
|
||||
elif issubclass(cls, ModelComposed):
|
||||
possible_classes.extend(composed_model_input_classes(cls))
|
||||
return possible_classes
|
||||
|
||||
|
||||
def get_required_type_classes(required_types_mixed, spec_property_naming):
|
||||
"""Converts the tuple required_types into a tuple and a dict described
|
||||
below
|
||||
|
||||
Args:
|
||||
required_types_mixed (tuple/list): will contain either classes or
|
||||
instance of list or dict
|
||||
spec_property_naming (bool): if True these values came from the
|
||||
server, and we use the data types in our endpoints.
|
||||
If False, we are client side and we need to include
|
||||
oneOf and discriminator classes inside the data types in our endpoints
|
||||
|
||||
Returns:
|
||||
(valid_classes, dict_valid_class_to_child_types_mixed):
|
||||
valid_classes (tuple): the valid classes that the current item
|
||||
should be
|
||||
dict_valid_class_to_child_types_mixed (doct):
|
||||
dict_valid_class_to_child_types_mixed (dict):
|
||||
valid_class (class): this is the key
|
||||
child_types_mixed (list/dict/tuple): describes the valid child
|
||||
types
|
||||
@@ -917,7 +1014,7 @@ def get_required_type_classes(required_types_mixed):
|
||||
valid_classes.append(dict)
|
||||
child_req_types_by_current_type[dict] = required_type[str]
|
||||
else:
|
||||
valid_classes.append(required_type)
|
||||
valid_classes.extend(get_possible_classes(required_type, spec_property_naming))
|
||||
return tuple(valid_classes), child_req_types_by_current_type
|
||||
|
||||
|
||||
@@ -1070,7 +1167,7 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
"""Deserializes model_data to model instance.
|
||||
|
||||
Args:
|
||||
model_data (list/dict): data to instantiate the model
|
||||
model_data (int/str/float/bool/none_type/list/dict): data to instantiate the model
|
||||
model_class (OpenApiModel): the model class
|
||||
path_to_item (list): path to the model in the received data
|
||||
check_type (bool): whether to check the data tupe for the values in
|
||||
@@ -1096,14 +1193,14 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
_spec_property_naming=spec_property_naming)
|
||||
|
||||
if issubclass(model_class, ModelSimple):
|
||||
instance = model_class(value=model_data, **kw_args)
|
||||
return instance
|
||||
if isinstance(model_data, list):
|
||||
instance = model_class(*model_data, **kw_args)
|
||||
return model_class(model_data, **kw_args)
|
||||
elif isinstance(model_data, list):
|
||||
return model_class(*model_data, **kw_args)
|
||||
if isinstance(model_data, dict):
|
||||
kw_args.update(model_data)
|
||||
instance = model_class(**kw_args)
|
||||
return instance
|
||||
return model_class(**kw_args)
|
||||
elif isinstance(model_data, PRIMITIVE_TYPES):
|
||||
return model_class(model_data, **kw_args)
|
||||
|
||||
|
||||
def deserialize_file(response_data, configuration, content_disposition=None):
|
||||
@@ -1286,7 +1383,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
Raises:
|
||||
ApiTypeError
|
||||
"""
|
||||
results = get_required_type_classes(required_types_mixed)
|
||||
results = get_required_type_classes(required_types_mixed, spec_property_naming)
|
||||
valid_classes, child_req_types_by_current_type = results
|
||||
|
||||
input_class_simple = get_simple_class(input_value)
|
||||
@@ -1523,7 +1620,7 @@ def get_allof_instances(self, model_args, constant_args):
|
||||
return composed_instances
|
||||
|
||||
|
||||
def get_oneof_instance(self, model_args, constant_args):
|
||||
def get_oneof_instance(cls, model_kwargs, constant_kwargs, model_arg=None):
|
||||
"""
|
||||
Find the oneOf schema that matches the input data (e.g. payload).
|
||||
If exactly one schema matches the input data, an instance of that schema
|
||||
@@ -1531,25 +1628,33 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
If zero or more than one schema match the input data, an exception is raised.
|
||||
In OAS 3.x, the payload MUST, by validation, match exactly one of the
|
||||
schemas described by oneOf.
|
||||
|
||||
Args:
|
||||
self: the class we are handling
|
||||
model_args (dict): var_name to var_value
|
||||
cls: the class we are handling
|
||||
model_kwargs (dict): var_name to var_value
|
||||
The input data, e.g. the payload that must match a oneOf schema
|
||||
in the OpenAPI document.
|
||||
constant_args (dict): var_name to var_value
|
||||
constant_kwargs (dict): var_name to var_value
|
||||
args that every model requires, including configuration, server
|
||||
and path to item.
|
||||
|
||||
Kwargs:
|
||||
model_arg: (int, float, bool, str, date, datetime, ModelSimple, None):
|
||||
the value to assign to a primitive class or ModelSimple class
|
||||
Notes:
|
||||
- this is only passed in when oneOf includes types which are not object
|
||||
- None is used to suppress handling of model_arg, nullable models are handled in __new__
|
||||
|
||||
Returns
|
||||
oneof_instance (instance)
|
||||
"""
|
||||
if len(self._composed_schemas['oneOf']) == 0:
|
||||
if len(cls._composed_schemas['oneOf']) == 0:
|
||||
return None
|
||||
|
||||
oneof_instances = []
|
||||
# Iterate over each oneOf schema and determine if the input data
|
||||
# matches the oneOf schemas.
|
||||
for oneof_class in self._composed_schemas['oneOf']:
|
||||
for oneof_class in cls._composed_schemas['oneOf']:
|
||||
# The composed oneOf schema allows the 'null' type and the input data
|
||||
# is the null value. This is a OAS >= 3.1 feature.
|
||||
if oneof_class is none_type:
|
||||
@@ -1557,28 +1662,45 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
# none_type deserialization is handled in the __new__ method
|
||||
continue
|
||||
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_args, oneof_class)
|
||||
single_value_input = allows_single_value_input(oneof_class)
|
||||
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
if not single_value_input:
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_kwargs, oneof_class)
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_kwargs)
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_args)
|
||||
try:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
if not single_value_input:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
else:
|
||||
if issubclass(oneof_class, ModelSimple):
|
||||
oneof_instance = oneof_class(model_arg, **constant_kwargs)
|
||||
elif oneof_class in PRIMITIVE_TYPES:
|
||||
oneof_instance = validate_and_convert_types(
|
||||
model_arg,
|
||||
(oneof_class,),
|
||||
constant_kwargs['_path_to_item'],
|
||||
constant_kwargs['_spec_property_naming'],
|
||||
constant_kwargs['_check_type'],
|
||||
configuration=constant_kwargs['_configuration']
|
||||
)
|
||||
oneof_instances.append(oneof_instance)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -1586,13 +1708,13 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. None "
|
||||
"of the oneOf schemas matched the input data." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
elif len(oneof_instances) > 1:
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. Multiple "
|
||||
"oneOf schemas matched the inputs, but a max of one is allowed." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
return oneof_instances[0]
|
||||
|
||||
@@ -1732,7 +1854,7 @@ def validate_get_composed_info(constant_args, model_args, self):
|
||||
composed_instances = []
|
||||
allof_instances = get_allof_instances(self, model_args, constant_args)
|
||||
composed_instances.extend(allof_instances)
|
||||
oneof_instance = get_oneof_instance(self, model_args, constant_args)
|
||||
oneof_instance = get_oneof_instance(self.__class__, model_args, constant_args)
|
||||
if oneof_instance is not None:
|
||||
composed_instances.append(oneof_instance)
|
||||
anyof_instances = get_anyof_instances(self, model_args, constant_args)
|
||||
|
||||
@@ -27,6 +27,7 @@ docs/ChildCatAllOf.md
|
||||
docs/ClassModel.md
|
||||
docs/Client.md
|
||||
docs/ComplexQuadrilateral.md
|
||||
docs/ComposedOneOfNumberWithValidations.md
|
||||
docs/DanishPig.md
|
||||
docs/DefaultApi.md
|
||||
docs/Dog.md
|
||||
@@ -135,6 +136,7 @@ petstore_api/model/child_cat_all_of.py
|
||||
petstore_api/model/class_model.py
|
||||
petstore_api/model/client.py
|
||||
petstore_api/model/complex_quadrilateral.py
|
||||
petstore_api/model/composed_one_of_number_with_validations.py
|
||||
petstore_api/model/danish_pig.py
|
||||
petstore_api/model/dog.py
|
||||
petstore_api/model/dog_all_of.py
|
||||
|
||||
@@ -86,6 +86,7 @@ Class | Method | HTTP request | Description
|
||||
*FakeApi* | [**array_model**](docs/FakeApi.md#array_model) | **POST** /fake/refs/arraymodel |
|
||||
*FakeApi* | [**array_of_enums**](docs/FakeApi.md#array_of_enums) | **POST** /fake/refs/array-of-enums | Array of Enums
|
||||
*FakeApi* | [**boolean**](docs/FakeApi.md#boolean) | **POST** /fake/refs/boolean |
|
||||
*FakeApi* | [**composed_one_of_number_with_validations**](docs/FakeApi.md#composed_one_of_number_with_validations) | **POST** /fake/refs/composed_one_of_number_with_validations |
|
||||
*FakeApi* | [**fake_health_get**](docs/FakeApi.md#fake_health_get) | **GET** /fake/health | Health check endpoint
|
||||
*FakeApi* | [**number_with_validations**](docs/FakeApi.md#number_with_validations) | **POST** /fake/refs/number |
|
||||
*FakeApi* | [**object_model_with_ref_props**](docs/FakeApi.md#object_model_with_ref_props) | **POST** /fake/refs/object_model_with_ref_props |
|
||||
@@ -150,6 +151,7 @@ Class | Method | HTTP request | Description
|
||||
- [class_model.ClassModel](docs/ClassModel.md)
|
||||
- [client.Client](docs/Client.md)
|
||||
- [complex_quadrilateral.ComplexQuadrilateral](docs/ComplexQuadrilateral.md)
|
||||
- [composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations](docs/ComposedOneOfNumberWithValidations.md)
|
||||
- [danish_pig.DanishPig](docs/DanishPig.md)
|
||||
- [dog.Dog](docs/Dog.md)
|
||||
- [dog_all_of.DogAllOf](docs/DogAllOf.md)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations
|
||||
|
||||
this is a model that allows payloads of type object or number
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**class_name** | **str** | | defaults to nulltype.Null
|
||||
**color** | **str** | | [optional] if omitted the server will use the default value of 'red'
|
||||
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**value** | **str** | | defaults to '-efg'
|
||||
**value** | **str** | | if omitted the server will use the default value of '-efg', must be one of ["_abc", "-efg", "(xyz)", ]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Name | Type | Description | Notes
|
||||
**enum_string** | **str** | | [optional]
|
||||
**enum_integer** | **int** | | [optional]
|
||||
**enum_number** | **float** | | [optional]
|
||||
**string_enum** | [**string_enum.StringEnum**](StringEnum.md) | | [optional]
|
||||
**string_enum** | [**string_enum.StringEnum, none_type**](StringEnum.md) | | [optional]
|
||||
**integer_enum** | [**integer_enum.IntegerEnum**](IntegerEnum.md) | | [optional]
|
||||
**string_enum_with_default_value** | [**string_enum_with_default_value.StringEnumWithDefaultValue**](StringEnumWithDefaultValue.md) | | [optional]
|
||||
**integer_enum_with_default_value** | [**integer_enum_with_default_value.IntegerEnumWithDefaultValue**](IntegerEnumWithDefaultValue.md) | | [optional]
|
||||
|
||||
@@ -8,6 +8,7 @@ Method | HTTP request | Description
|
||||
[**array_model**](FakeApi.md#array_model) | **POST** /fake/refs/arraymodel |
|
||||
[**array_of_enums**](FakeApi.md#array_of_enums) | **POST** /fake/refs/array-of-enums | Array of Enums
|
||||
[**boolean**](FakeApi.md#boolean) | **POST** /fake/refs/boolean |
|
||||
[**composed_one_of_number_with_validations**](FakeApi.md#composed_one_of_number_with_validations) | **POST** /fake/refs/composed_one_of_number_with_validations |
|
||||
[**fake_health_get**](FakeApi.md#fake_health_get) | **GET** /fake/health | Health check endpoint
|
||||
[**number_with_validations**](FakeApi.md#number_with_validations) | **POST** /fake/refs/number |
|
||||
[**object_model_with_ref_props**](FakeApi.md#object_model_with_ref_props) | **POST** /fake/refs/object_model_with_ref_props |
|
||||
@@ -277,6 +278,70 @@ No authorization required
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **composed_one_of_number_with_validations**
|
||||
> composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations composed_one_of_number_with_validations()
|
||||
|
||||
|
||||
|
||||
Test serialization of object with $refed properties
|
||||
|
||||
### Example
|
||||
|
||||
```python
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import petstore_api
|
||||
from petstore_api.api import fake_api
|
||||
from petstore_api.model import composed_one_of_number_with_validations
|
||||
from pprint import pprint
|
||||
# Defining the host is optional and defaults to http://petstore.swagger.io:80/v2
|
||||
# See configuration.py for a list of all supported configuration parameters.
|
||||
configuration = petstore_api.Configuration(
|
||||
host = "http://petstore.swagger.io:80/v2"
|
||||
)
|
||||
|
||||
|
||||
# Enter a context with an instance of the API client
|
||||
with petstore_api.ApiClient() as api_client:
|
||||
# Create an instance of the API class
|
||||
api_instance = fake_api.FakeApi(api_client)
|
||||
composed_one_of_number_with_validations_composed_one_of_number_with_validations = composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations() # composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations | Input model (optional)
|
||||
|
||||
# example passing only required values which don't have defaults set
|
||||
# and optional values
|
||||
try:
|
||||
api_response = api_instance.composed_one_of_number_with_validations(composed_one_of_number_with_validations_composed_one_of_number_with_validations=composed_one_of_number_with_validations_composed_one_of_number_with_validations)
|
||||
pprint(api_response)
|
||||
except petstore_api.ApiException as e:
|
||||
print("Exception when calling FakeApi->composed_one_of_number_with_validations: %s\n" % e)
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**composed_one_of_number_with_validations_composed_one_of_number_with_validations** | [**composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations**](ComposedOneOfNumberWithValidations.md)| Input model | [optional]
|
||||
|
||||
### Return type
|
||||
|
||||
[**composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations**](ComposedOneOfNumberWithValidations.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
No authorization required
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: application/json
|
||||
|
||||
### HTTP response details
|
||||
| Status code | Description | Response headers |
|
||||
|-------------|-------------|------------------|
|
||||
**200** | Output model | - |
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **fake_health_get**
|
||||
> health_check_result.HealthCheckResult fake_health_get()
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**value** | **int** | |
|
||||
**value** | **int** | | must be one of [0, 1, 2, ]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**value** | **int** | | defaults to 0
|
||||
**value** | **int** | | defaults to 0, must be one of [0, ]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**value** | **int** | | defaults to 0
|
||||
**value** | **int** | | if omitted the server will use the default value of 0, must be one of [0, 1, 2, ]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**value** | **str, none_type** | |
|
||||
**value** | **str** | | must be one of ["placed", "approved", "delivered", ]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**value** | **str** | | defaults to 'placed'
|
||||
**value** | **str** | | if omitted the server will use the default value of 'placed', must be one of ["placed", "approved", "delivered", ]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ from petstore_api.model_utils import ( # noqa: F401
|
||||
from petstore_api.model import additional_properties_with_array_of_enums
|
||||
from petstore_api.model import animal_farm
|
||||
from petstore_api.model import array_of_enums
|
||||
from petstore_api.model import composed_one_of_number_with_validations
|
||||
from petstore_api.model import health_check_result
|
||||
from petstore_api.model import number_with_validations
|
||||
from petstore_api.model import object_model_with_ref_props
|
||||
@@ -500,6 +501,118 @@ class FakeApi(object):
|
||||
callable=__boolean
|
||||
)
|
||||
|
||||
def __composed_one_of_number_with_validations(
|
||||
self,
|
||||
**kwargs
|
||||
):
|
||||
"""composed_one_of_number_with_validations # noqa: E501
|
||||
|
||||
Test serialization of object with $refed properties # noqa: E501
|
||||
This method makes a synchronous HTTP request by default. To make an
|
||||
asynchronous HTTP request, please pass async_req=True
|
||||
|
||||
>>> thread = api.composed_one_of_number_with_validations(async_req=True)
|
||||
>>> result = thread.get()
|
||||
|
||||
|
||||
Keyword Args:
|
||||
composed_one_of_number_with_validations_composed_one_of_number_with_validations (composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations): Input model. [optional]
|
||||
_return_http_data_only (bool): response data without head status
|
||||
code and headers. Default is True.
|
||||
_preload_content (bool): if False, the urllib3.HTTPResponse object
|
||||
will be returned without reading/decoding response data.
|
||||
Default is True.
|
||||
_request_timeout (float/tuple): timeout setting for this request. If one
|
||||
number provided, it will be total request timeout. It can also
|
||||
be a pair (tuple) of (connection, read) timeouts.
|
||||
Default is None.
|
||||
_check_input_type (bool): specifies if type checking
|
||||
should be done one the data sent to the server.
|
||||
Default is True.
|
||||
_check_return_type (bool): specifies if type checking
|
||||
should be done one the data received from the server.
|
||||
Default is True.
|
||||
_host_index (int/None): specifies the index of the server
|
||||
that we want to use.
|
||||
Default is read from the configuration.
|
||||
async_req (bool): execute request asynchronously
|
||||
|
||||
Returns:
|
||||
composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations
|
||||
If the method is called asynchronously, returns the request
|
||||
thread.
|
||||
"""
|
||||
kwargs['async_req'] = kwargs.get(
|
||||
'async_req', False
|
||||
)
|
||||
kwargs['_return_http_data_only'] = kwargs.get(
|
||||
'_return_http_data_only', True
|
||||
)
|
||||
kwargs['_preload_content'] = kwargs.get(
|
||||
'_preload_content', True
|
||||
)
|
||||
kwargs['_request_timeout'] = kwargs.get(
|
||||
'_request_timeout', None
|
||||
)
|
||||
kwargs['_check_input_type'] = kwargs.get(
|
||||
'_check_input_type', True
|
||||
)
|
||||
kwargs['_check_return_type'] = kwargs.get(
|
||||
'_check_return_type', True
|
||||
)
|
||||
kwargs['_host_index'] = kwargs.get('_host_index')
|
||||
return self.call_with_http_info(**kwargs)
|
||||
|
||||
self.composed_one_of_number_with_validations = Endpoint(
|
||||
settings={
|
||||
'response_type': (composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations,),
|
||||
'auth': [],
|
||||
'endpoint_path': '/fake/refs/composed_one_of_number_with_validations',
|
||||
'operation_id': 'composed_one_of_number_with_validations',
|
||||
'http_method': 'POST',
|
||||
'servers': None,
|
||||
},
|
||||
params_map={
|
||||
'all': [
|
||||
'composed_one_of_number_with_validations_composed_one_of_number_with_validations',
|
||||
],
|
||||
'required': [],
|
||||
'nullable': [
|
||||
],
|
||||
'enum': [
|
||||
],
|
||||
'validation': [
|
||||
]
|
||||
},
|
||||
root_map={
|
||||
'validations': {
|
||||
},
|
||||
'allowed_values': {
|
||||
},
|
||||
'openapi_types': {
|
||||
'composed_one_of_number_with_validations_composed_one_of_number_with_validations':
|
||||
(composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations,),
|
||||
},
|
||||
'attribute_map': {
|
||||
},
|
||||
'location_map': {
|
||||
'composed_one_of_number_with_validations_composed_one_of_number_with_validations': 'body',
|
||||
},
|
||||
'collection_format_map': {
|
||||
}
|
||||
},
|
||||
headers_map={
|
||||
'accept': [
|
||||
'application/json'
|
||||
],
|
||||
'content_type': [
|
||||
'application/json'
|
||||
]
|
||||
},
|
||||
api_client=api_client,
|
||||
callable=__composed_one_of_number_with_validations
|
||||
)
|
||||
|
||||
def __fake_health_get(
|
||||
self,
|
||||
**kwargs
|
||||
|
||||
@@ -81,7 +81,7 @@ class AnimalFarm(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': ([animal.Animal],), # noqa: E501
|
||||
'value': ([animal.Animal],),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,11 +102,11 @@ class AnimalFarm(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, value, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""animal_farm.AnimalFarm - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value ([animal.Animal]):
|
||||
value ([animal.Animal]): # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -163,13 +163,13 @@ class AnimalFarm(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -81,7 +81,7 @@ class ArrayOfEnums(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': ([string_enum.StringEnum, none_type],), # noqa: E501
|
||||
'value': ([string_enum.StringEnum, none_type],),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,11 +102,11 @@ class ArrayOfEnums(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, value, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""array_of_enums.ArrayOfEnums - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value ([string_enum.StringEnum, none_type]):
|
||||
value ([string_enum.StringEnum, none_type]): # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -163,13 +163,13 @@ class ArrayOfEnums(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
OpenAPI Petstore
|
||||
|
||||
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
|
||||
|
||||
The version of the OpenAPI document: 1.0.0
|
||||
Generated by: https://openapi-generator.tech
|
||||
"""
|
||||
|
||||
|
||||
from __future__ import absolute_import
|
||||
import re # noqa: F401
|
||||
import sys # noqa: F401
|
||||
|
||||
import six # noqa: F401
|
||||
import nulltype # noqa: F401
|
||||
|
||||
from petstore_api.model_utils import ( # noqa: F401
|
||||
ApiTypeError,
|
||||
ModelComposed,
|
||||
ModelNormal,
|
||||
ModelSimple,
|
||||
cached_property,
|
||||
change_keys_js_to_python,
|
||||
convert_js_args_to_python_args,
|
||||
date,
|
||||
datetime,
|
||||
file_type,
|
||||
int,
|
||||
none_type,
|
||||
str,
|
||||
validate_get_composed_info,
|
||||
)
|
||||
try:
|
||||
from petstore_api.model import animal
|
||||
except ImportError:
|
||||
animal = sys.modules[
|
||||
'petstore_api.model.animal']
|
||||
try:
|
||||
from petstore_api.model import number_with_validations
|
||||
except ImportError:
|
||||
number_with_validations = sys.modules[
|
||||
'petstore_api.model.number_with_validations']
|
||||
|
||||
|
||||
class ComposedOneOfNumberWithValidations(ModelComposed):
|
||||
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||
Ref: https://openapi-generator.tech
|
||||
|
||||
Do not edit the class manually.
|
||||
|
||||
Attributes:
|
||||
allowed_values (dict): The key is the tuple path to the attribute
|
||||
and the for var_name this is (var_name,). The value is a dict
|
||||
with a capitalized key describing the allowed value and an allowed
|
||||
value. These dicts store the allowed enum values.
|
||||
attribute_map (dict): The key is attribute name
|
||||
and the value is json key in definition.
|
||||
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||
variable value to the discriminator class name.
|
||||
validations (dict): The key is the tuple path to the attribute
|
||||
and the for var_name this is (var_name,). The value is a dict
|
||||
that stores validations for max_length, min_length, max_items,
|
||||
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||
inclusive_minimum, and regex.
|
||||
additional_properties_type (tuple): A tuple of classes accepted
|
||||
as additional properties values.
|
||||
"""
|
||||
|
||||
allowed_values = {
|
||||
}
|
||||
|
||||
validations = {
|
||||
}
|
||||
|
||||
additional_properties_type = (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||
|
||||
_nullable = False
|
||||
|
||||
@cached_property
|
||||
def openapi_types():
|
||||
"""
|
||||
This must be a class method so a model may have properties that are
|
||||
of type self, this ensures that we don't create a cyclic import
|
||||
|
||||
Returns
|
||||
openapi_types (dict): The key is attribute name
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'class_name': (str,), # noqa: E501
|
||||
'color': (str,), # noqa: E501
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def discriminator():
|
||||
return None
|
||||
|
||||
attribute_map = {
|
||||
'class_name': 'className', # noqa: E501
|
||||
'color': 'color', # noqa: E501
|
||||
}
|
||||
|
||||
required_properties = set([
|
||||
'_data_store',
|
||||
'_check_type',
|
||||
'_spec_property_naming',
|
||||
'_path_to_item',
|
||||
'_configuration',
|
||||
'_visited_composed_classes',
|
||||
'_composed_instances',
|
||||
'_var_name_to_model_instances',
|
||||
'_additional_properties_model_instances',
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, *args, **kwargs): # noqa: E501
|
||||
"""composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
|
||||
Keyword Args:
|
||||
class_name (str): defaults to nulltype.Null # noqa: E501
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
will be type checked and a TypeError will be
|
||||
raised if the wrong type is input.
|
||||
Defaults to True
|
||||
_path_to_item (tuple/list): This is a list of keys or values to
|
||||
drill down to the model in received_data
|
||||
when deserializing a response
|
||||
_spec_property_naming (bool): True if the variable names in the input data
|
||||
are serialized names, as specified in the OpenAPI document.
|
||||
False if the variable names in the input data
|
||||
are pythonic names, e.g. snake case (default)
|
||||
_configuration (Configuration): the instance to use when
|
||||
deserializing a file_type parameter.
|
||||
If passed, type conversion is attempted
|
||||
If omitted no type conversion is done.
|
||||
_visited_composed_classes (tuple): This stores a tuple of
|
||||
classes that we have traveled through so that
|
||||
if we see that class again we will not use its
|
||||
discriminator again.
|
||||
When traveling through a discriminator, the
|
||||
composed schema that is
|
||||
is traveled through is added to this set.
|
||||
For example if Animal has a discriminator
|
||||
petType and we pass in "Dog", and the class Dog
|
||||
allOf includes Animal, we move through Animal
|
||||
once using the discriminator, and pick Dog.
|
||||
Then in Dog, we will make an instance of the
|
||||
Animal class but this time we won't travel
|
||||
through its discriminator because we passed in
|
||||
_visited_composed_classes = (Animal,)
|
||||
color (str): [optional] if omitted the server will use the default value of 'red' # noqa: E501
|
||||
"""
|
||||
|
||||
class_name = kwargs.get('class_name', nulltype.Null)
|
||||
_check_type = kwargs.pop('_check_type', True)
|
||||
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||
_configuration = kwargs.pop('_configuration', None)
|
||||
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||
|
||||
if args:
|
||||
raise ApiTypeError(
|
||||
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||
args,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
self._data_store = {}
|
||||
self._check_type = _check_type
|
||||
self._spec_property_naming = _spec_property_naming
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
constant_args = {
|
||||
'_check_type': _check_type,
|
||||
'_path_to_item': _path_to_item,
|
||||
'_spec_property_naming': _spec_property_naming,
|
||||
'_configuration': _configuration,
|
||||
'_visited_composed_classes': self._visited_composed_classes,
|
||||
}
|
||||
required_args = {
|
||||
'class_name': class_name,
|
||||
}
|
||||
# remove args whose value is Null because they are unset
|
||||
required_arg_names = list(required_args.keys())
|
||||
for required_arg_name in required_arg_names:
|
||||
if required_args[required_arg_name] is nulltype.Null:
|
||||
del required_args[required_arg_name]
|
||||
model_args = {}
|
||||
model_args.update(required_args)
|
||||
model_args.update(kwargs)
|
||||
composed_info = validate_get_composed_info(
|
||||
constant_args, model_args, self)
|
||||
self._composed_instances = composed_info[0]
|
||||
self._var_name_to_model_instances = composed_info[1]
|
||||
self._additional_properties_model_instances = composed_info[2]
|
||||
unused_args = composed_info[3]
|
||||
|
||||
for var_name, var_value in required_args.items():
|
||||
setattr(self, var_name, var_value)
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name in unused_args and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
not self._additional_properties_model_instances:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
|
||||
@cached_property
|
||||
def _composed_schemas():
|
||||
# we need this here to make our import statements work
|
||||
# we must store _composed_schemas in here so the code is only run
|
||||
# when we invoke this method. If we kept this at the class
|
||||
# level we would get an error beause the class level
|
||||
# code would be run when this module is imported, and these composed
|
||||
# classes don't exist yet because their module has not finished
|
||||
# loading
|
||||
return {
|
||||
'anyOf': [
|
||||
],
|
||||
'allOf': [
|
||||
],
|
||||
'oneOf': [
|
||||
animal.Animal,
|
||||
date,
|
||||
none_type,
|
||||
number_with_validations.NumberWithValidations,
|
||||
],
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class EnumClass(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (str,), # noqa: E501
|
||||
'value': (str,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,13 +102,13 @@ class EnumClass(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""enum_class.EnumClass - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (str): if omitted the server will use the default value of '-efg', must be one of ["_abc", "-efg", "(xyz)", ] # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
value (str): defaults to '-efg', must be one of ["_abc", "-efg", "(xyz)", ] # noqa: E501
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
will be type checked and a TypeError will be
|
||||
raised if the wrong type is input.
|
||||
@@ -141,7 +141,6 @@ class EnumClass(ModelSimple):
|
||||
_visited_composed_classes = (Animal,)
|
||||
"""
|
||||
|
||||
value = kwargs.get('value', '-efg')
|
||||
_check_type = kwargs.pop('_check_type', True)
|
||||
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||
@@ -164,13 +163,13 @@ class EnumClass(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -127,7 +127,7 @@ class EnumTest(ModelNormal):
|
||||
'enum_string': (str,), # noqa: E501
|
||||
'enum_integer': (int,), # noqa: E501
|
||||
'enum_number': (float,), # noqa: E501
|
||||
'string_enum': (string_enum.StringEnum,), # noqa: E501
|
||||
'string_enum': (string_enum.StringEnum, none_type,), # noqa: E501
|
||||
'integer_enum': (integer_enum.IntegerEnum,), # noqa: E501
|
||||
'string_enum_with_default_value': (string_enum_with_default_value.StringEnumWithDefaultValue,), # noqa: E501
|
||||
'integer_enum_with_default_value': (integer_enum_with_default_value.IntegerEnumWithDefaultValue,), # noqa: E501
|
||||
@@ -202,7 +202,7 @@ class EnumTest(ModelNormal):
|
||||
enum_string (str): [optional] # noqa: E501
|
||||
enum_integer (int): [optional] # noqa: E501
|
||||
enum_number (float): [optional] # noqa: E501
|
||||
string_enum (string_enum.StringEnum): [optional] # noqa: E501
|
||||
string_enum (string_enum.StringEnum, none_type): [optional] # noqa: E501
|
||||
integer_enum (integer_enum.IntegerEnum): [optional] # noqa: E501
|
||||
string_enum_with_default_value (string_enum_with_default_value.StringEnumWithDefaultValue): [optional] # noqa: E501
|
||||
integer_enum_with_default_value (integer_enum_with_default_value.IntegerEnumWithDefaultValue): [optional] # noqa: E501
|
||||
|
||||
@@ -81,7 +81,7 @@ class IntegerEnum(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (int,), # noqa: E501
|
||||
'value': (int,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,11 +102,11 @@ class IntegerEnum(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, value, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""integer_enum.IntegerEnum - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (int):
|
||||
value (int):, must be one of [0, 1, 2, ] # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -163,13 +163,13 @@ class IntegerEnum(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -79,7 +79,7 @@ class IntegerEnumOneValue(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (int,), # noqa: E501
|
||||
'value': (int,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -100,11 +100,9 @@ class IntegerEnumOneValue(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""integer_enum_one_value.IntegerEnumOneValue - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
|
||||
Keyword Args:
|
||||
value (int): defaults to 0, must be one of [0, ] # noqa: E501
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -139,7 +137,13 @@ class IntegerEnumOneValue(ModelSimple):
|
||||
_visited_composed_classes = (Animal,)
|
||||
"""
|
||||
|
||||
value = kwargs.get('value', 0)
|
||||
if 'value' in kwargs:
|
||||
value = kwargs.pop('value')
|
||||
elif args:
|
||||
args = list(args)
|
||||
value = args.pop(0)
|
||||
else:
|
||||
value = 0
|
||||
_check_type = kwargs.pop('_check_type', True)
|
||||
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||
@@ -162,13 +166,13 @@ class IntegerEnumOneValue(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -81,7 +81,7 @@ class IntegerEnumWithDefaultValue(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (int,), # noqa: E501
|
||||
'value': (int,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,13 +102,13 @@ class IntegerEnumWithDefaultValue(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""integer_enum_with_default_value.IntegerEnumWithDefaultValue - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (int): if omitted the server will use the default value of 0, must be one of [0, 1, 2, ] # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
value (int): defaults to 0, must be one of [0, 1, 2, ] # noqa: E501
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
will be type checked and a TypeError will be
|
||||
raised if the wrong type is input.
|
||||
@@ -141,7 +141,6 @@ class IntegerEnumWithDefaultValue(ModelSimple):
|
||||
_visited_composed_classes = (Animal,)
|
||||
"""
|
||||
|
||||
value = kwargs.get('value', 0)
|
||||
_check_type = kwargs.pop('_check_type', True)
|
||||
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||
@@ -164,13 +163,13 @@ class IntegerEnumWithDefaultValue(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -80,7 +80,7 @@ class NumberWithValidations(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (float,), # noqa: E501
|
||||
'value': (float,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -101,11 +101,11 @@ class NumberWithValidations(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, value, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""number_with_validations.NumberWithValidations - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (float):
|
||||
value (float): # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -162,13 +162,13 @@ class NumberWithValidations(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -82,7 +82,7 @@ class StringEnum(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (str, none_type,), # noqa: E501
|
||||
'value': (str,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -103,11 +103,11 @@ class StringEnum(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, value, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""string_enum.StringEnum - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (str, none_type):
|
||||
value (str):, must be one of ["placed", "approved", "delivered", ] # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
@@ -164,13 +164,13 @@ class StringEnum(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -81,7 +81,7 @@ class StringEnumWithDefaultValue(ModelSimple):
|
||||
and the value is attribute type.
|
||||
"""
|
||||
return {
|
||||
'value': (str,), # noqa: E501
|
||||
'value': (str,),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -102,13 +102,13 @@ class StringEnumWithDefaultValue(ModelSimple):
|
||||
])
|
||||
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self, *args, **kwargs): # noqa: E501
|
||||
def __init__(self, value, *args, **kwargs):
|
||||
"""string_enum_with_default_value.StringEnumWithDefaultValue - a model defined in OpenAPI
|
||||
|
||||
Args:
|
||||
value (str): if omitted the server will use the default value of 'placed', must be one of ["placed", "approved", "delivered", ] # noqa: E501
|
||||
|
||||
Keyword Args:
|
||||
value (str): defaults to 'placed', must be one of ["placed", "approved", "delivered", ] # noqa: E501
|
||||
_check_type (bool): if True, values for parameters in openapi_types
|
||||
will be type checked and a TypeError will be
|
||||
raised if the wrong type is input.
|
||||
@@ -141,7 +141,6 @@ class StringEnumWithDefaultValue(ModelSimple):
|
||||
_visited_composed_classes = (Animal,)
|
||||
"""
|
||||
|
||||
value = kwargs.get('value', 'placed')
|
||||
_check_type = kwargs.pop('_check_type', True)
|
||||
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||
@@ -164,13 +163,13 @@ class StringEnumWithDefaultValue(ModelSimple):
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
|
||||
self.value = value
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if var_name not in self.attribute_map and \
|
||||
self._configuration is not None and \
|
||||
self._configuration.discard_unknown_keys and \
|
||||
self.additional_properties_type is None:
|
||||
# discard variable.
|
||||
continue
|
||||
setattr(self, var_name, var_value)
|
||||
if kwargs:
|
||||
raise ApiTypeError(
|
||||
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||
kwargs,
|
||||
self.__class__.__name__,
|
||||
),
|
||||
path_to_item=_path_to_item,
|
||||
valid_classes=(self.__class__,),
|
||||
)
|
||||
|
||||
@@ -62,6 +62,58 @@ class cached_property(object):
|
||||
return result
|
||||
|
||||
|
||||
PRIMITIVE_TYPES = (list, float, int, bool, datetime, date, str, file_type)
|
||||
|
||||
def allows_single_value_input(cls):
|
||||
"""
|
||||
This function returns True if the input composed schema model or any
|
||||
descendant model allows a value only input
|
||||
This is true for cases where oneOf contains items like:
|
||||
oneOf:
|
||||
- float
|
||||
- NumberWithValidation
|
||||
- StringEnum
|
||||
- ArrayModel
|
||||
- null
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if (
|
||||
issubclass(cls, ModelSimple) or
|
||||
cls in PRIMITIVE_TYPES
|
||||
):
|
||||
return True
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return False
|
||||
return any(allows_single_value_input(c) for c in cls._composed_schemas['oneOf'])
|
||||
return False
|
||||
|
||||
def composed_model_input_classes(cls):
|
||||
"""
|
||||
This function returns a list of the possible models that can be accepted as
|
||||
inputs.
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
if issubclass(cls, ModelSimple) or cls in PRIMITIVE_TYPES:
|
||||
return [cls]
|
||||
elif issubclass(cls, ModelNormal):
|
||||
if cls.discriminator is None:
|
||||
return [cls]
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
elif issubclass(cls, ModelComposed):
|
||||
if not cls._composed_schemas['oneOf']:
|
||||
return []
|
||||
if cls.discriminator is None:
|
||||
input_classes = []
|
||||
for c in cls._composed_schemas['oneOf']:
|
||||
input_classes.extend(composed_model_input_classes(c))
|
||||
return input_classes
|
||||
else:
|
||||
return get_discriminated_classes(cls)
|
||||
return []
|
||||
|
||||
|
||||
class OpenApiModel(object):
|
||||
"""The base class for all OpenAPIModels"""
|
||||
|
||||
@@ -138,9 +190,17 @@ class OpenApiModel(object):
|
||||
# pick a new schema/class to instantiate because a discriminator
|
||||
# propertyName value was passed in
|
||||
|
||||
if len(args) == 1 and args[0] is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if arg is None and is_type_nullable(cls):
|
||||
# The input data is the 'null' value and the type is nullable.
|
||||
return None
|
||||
|
||||
if issubclass(cls, ModelComposed) and allows_single_value_input(cls):
|
||||
model_kwargs = {}
|
||||
oneof_instance = get_oneof_instance(cls, model_kwargs, kwargs, model_arg=arg)
|
||||
return oneof_instance
|
||||
|
||||
|
||||
visited_composed_classes = kwargs.get('_visited_composed_classes', ())
|
||||
if (
|
||||
@@ -508,6 +568,10 @@ UPCONVERSION_TYPE_PAIRS = (
|
||||
(int, float), # A float may be serialized as an integer, e.g. '3' is a valid serialized float.
|
||||
(list, ModelComposed),
|
||||
(dict, ModelComposed),
|
||||
(str, ModelComposed),
|
||||
(int, ModelComposed),
|
||||
(float, ModelComposed),
|
||||
(list, ModelComposed),
|
||||
(list, ModelNormal),
|
||||
(dict, ModelNormal),
|
||||
(str, ModelSimple),
|
||||
@@ -886,20 +950,53 @@ def remove_uncoercible(required_types_classes, current_item, spec_property_namin
|
||||
results_classes.append(required_type_class)
|
||||
return results_classes
|
||||
|
||||
def get_discriminated_classes(cls):
|
||||
"""
|
||||
Returns all the classes that a discriminator converts to
|
||||
TODO: lru_cache this
|
||||
"""
|
||||
possible_classes = []
|
||||
key = list(cls.discriminator.keys())[0]
|
||||
if is_type_nullable(cls):
|
||||
possible_classes.append(cls)
|
||||
for discr_cls in cls.discriminator[key].values():
|
||||
if hasattr(discr_cls, 'discriminator') and discr_cls.discriminator is not None:
|
||||
possible_classes.extend(get_discriminated_classes(discr_cls))
|
||||
else:
|
||||
possible_classes.append(discr_cls)
|
||||
return possible_classes
|
||||
|
||||
def get_required_type_classes(required_types_mixed):
|
||||
|
||||
def get_possible_classes(cls, from_server_context):
|
||||
# TODO: lru_cache this
|
||||
possible_classes = [cls]
|
||||
if from_server_context:
|
||||
return possible_classes
|
||||
if hasattr(cls, 'discriminator') and cls.discriminator is not None:
|
||||
possible_classes = []
|
||||
possible_classes.extend(get_discriminated_classes(cls))
|
||||
elif issubclass(cls, ModelComposed):
|
||||
possible_classes.extend(composed_model_input_classes(cls))
|
||||
return possible_classes
|
||||
|
||||
|
||||
def get_required_type_classes(required_types_mixed, spec_property_naming):
|
||||
"""Converts the tuple required_types into a tuple and a dict described
|
||||
below
|
||||
|
||||
Args:
|
||||
required_types_mixed (tuple/list): will contain either classes or
|
||||
instance of list or dict
|
||||
spec_property_naming (bool): if True these values came from the
|
||||
server, and we use the data types in our endpoints.
|
||||
If False, we are client side and we need to include
|
||||
oneOf and discriminator classes inside the data types in our endpoints
|
||||
|
||||
Returns:
|
||||
(valid_classes, dict_valid_class_to_child_types_mixed):
|
||||
valid_classes (tuple): the valid classes that the current item
|
||||
should be
|
||||
dict_valid_class_to_child_types_mixed (doct):
|
||||
dict_valid_class_to_child_types_mixed (dict):
|
||||
valid_class (class): this is the key
|
||||
child_types_mixed (list/dict/tuple): describes the valid child
|
||||
types
|
||||
@@ -917,7 +1014,7 @@ def get_required_type_classes(required_types_mixed):
|
||||
valid_classes.append(dict)
|
||||
child_req_types_by_current_type[dict] = required_type[str]
|
||||
else:
|
||||
valid_classes.append(required_type)
|
||||
valid_classes.extend(get_possible_classes(required_type, spec_property_naming))
|
||||
return tuple(valid_classes), child_req_types_by_current_type
|
||||
|
||||
|
||||
@@ -1070,7 +1167,7 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
"""Deserializes model_data to model instance.
|
||||
|
||||
Args:
|
||||
model_data (list/dict): data to instantiate the model
|
||||
model_data (int/str/float/bool/none_type/list/dict): data to instantiate the model
|
||||
model_class (OpenApiModel): the model class
|
||||
path_to_item (list): path to the model in the received data
|
||||
check_type (bool): whether to check the data tupe for the values in
|
||||
@@ -1096,14 +1193,14 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
_spec_property_naming=spec_property_naming)
|
||||
|
||||
if issubclass(model_class, ModelSimple):
|
||||
instance = model_class(value=model_data, **kw_args)
|
||||
return instance
|
||||
if isinstance(model_data, list):
|
||||
instance = model_class(*model_data, **kw_args)
|
||||
return model_class(model_data, **kw_args)
|
||||
elif isinstance(model_data, list):
|
||||
return model_class(*model_data, **kw_args)
|
||||
if isinstance(model_data, dict):
|
||||
kw_args.update(model_data)
|
||||
instance = model_class(**kw_args)
|
||||
return instance
|
||||
return model_class(**kw_args)
|
||||
elif isinstance(model_data, PRIMITIVE_TYPES):
|
||||
return model_class(model_data, **kw_args)
|
||||
|
||||
|
||||
def deserialize_file(response_data, configuration, content_disposition=None):
|
||||
@@ -1286,7 +1383,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
Raises:
|
||||
ApiTypeError
|
||||
"""
|
||||
results = get_required_type_classes(required_types_mixed)
|
||||
results = get_required_type_classes(required_types_mixed, spec_property_naming)
|
||||
valid_classes, child_req_types_by_current_type = results
|
||||
|
||||
input_class_simple = get_simple_class(input_value)
|
||||
@@ -1523,7 +1620,7 @@ def get_allof_instances(self, model_args, constant_args):
|
||||
return composed_instances
|
||||
|
||||
|
||||
def get_oneof_instance(self, model_args, constant_args):
|
||||
def get_oneof_instance(cls, model_kwargs, constant_kwargs, model_arg=None):
|
||||
"""
|
||||
Find the oneOf schema that matches the input data (e.g. payload).
|
||||
If exactly one schema matches the input data, an instance of that schema
|
||||
@@ -1531,25 +1628,33 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
If zero or more than one schema match the input data, an exception is raised.
|
||||
In OAS 3.x, the payload MUST, by validation, match exactly one of the
|
||||
schemas described by oneOf.
|
||||
|
||||
Args:
|
||||
self: the class we are handling
|
||||
model_args (dict): var_name to var_value
|
||||
cls: the class we are handling
|
||||
model_kwargs (dict): var_name to var_value
|
||||
The input data, e.g. the payload that must match a oneOf schema
|
||||
in the OpenAPI document.
|
||||
constant_args (dict): var_name to var_value
|
||||
constant_kwargs (dict): var_name to var_value
|
||||
args that every model requires, including configuration, server
|
||||
and path to item.
|
||||
|
||||
Kwargs:
|
||||
model_arg: (int, float, bool, str, date, datetime, ModelSimple, None):
|
||||
the value to assign to a primitive class or ModelSimple class
|
||||
Notes:
|
||||
- this is only passed in when oneOf includes types which are not object
|
||||
- None is used to suppress handling of model_arg, nullable models are handled in __new__
|
||||
|
||||
Returns
|
||||
oneof_instance (instance)
|
||||
"""
|
||||
if len(self._composed_schemas['oneOf']) == 0:
|
||||
if len(cls._composed_schemas['oneOf']) == 0:
|
||||
return None
|
||||
|
||||
oneof_instances = []
|
||||
# Iterate over each oneOf schema and determine if the input data
|
||||
# matches the oneOf schemas.
|
||||
for oneof_class in self._composed_schemas['oneOf']:
|
||||
for oneof_class in cls._composed_schemas['oneOf']:
|
||||
# The composed oneOf schema allows the 'null' type and the input data
|
||||
# is the null value. This is a OAS >= 3.1 feature.
|
||||
if oneof_class is none_type:
|
||||
@@ -1557,28 +1662,45 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
# none_type deserialization is handled in the __new__ method
|
||||
continue
|
||||
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_args, oneof_class)
|
||||
single_value_input = allows_single_value_input(oneof_class)
|
||||
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
if not single_value_input:
|
||||
# transform js keys from input data to python keys in fixed_model_args
|
||||
fixed_model_args = change_keys_js_to_python(
|
||||
model_kwargs, oneof_class)
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
# Extract a dict with the properties that are declared in the oneOf schema.
|
||||
# Undeclared properties (e.g. properties that are allowed because of the
|
||||
# additionalProperties attribute in the OAS document) are not added to
|
||||
# the dict.
|
||||
kwargs = {}
|
||||
var_names = set(oneof_class.openapi_types.keys())
|
||||
for var_name in var_names:
|
||||
if var_name in fixed_model_args:
|
||||
kwargs[var_name] = fixed_model_args[var_name]
|
||||
|
||||
# do not try to make a model with no input args
|
||||
if len(kwargs) == 0:
|
||||
continue
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_kwargs)
|
||||
|
||||
# and use it to make the instance
|
||||
kwargs.update(constant_args)
|
||||
try:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
if not single_value_input:
|
||||
oneof_instance = oneof_class(**kwargs)
|
||||
else:
|
||||
if issubclass(oneof_class, ModelSimple):
|
||||
oneof_instance = oneof_class(model_arg, **constant_kwargs)
|
||||
elif oneof_class in PRIMITIVE_TYPES:
|
||||
oneof_instance = validate_and_convert_types(
|
||||
model_arg,
|
||||
(oneof_class,),
|
||||
constant_kwargs['_path_to_item'],
|
||||
constant_kwargs['_spec_property_naming'],
|
||||
constant_kwargs['_check_type'],
|
||||
configuration=constant_kwargs['_configuration']
|
||||
)
|
||||
oneof_instances.append(oneof_instance)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -1586,13 +1708,13 @@ def get_oneof_instance(self, model_args, constant_args):
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. None "
|
||||
"of the oneOf schemas matched the input data." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
elif len(oneof_instances) > 1:
|
||||
raise ApiValueError(
|
||||
"Invalid inputs given to generate an instance of %s. Multiple "
|
||||
"oneOf schemas matched the inputs, but a max of one is allowed." %
|
||||
self.__class__.__name__
|
||||
cls.__name__
|
||||
)
|
||||
return oneof_instances[0]
|
||||
|
||||
@@ -1732,7 +1854,7 @@ def validate_get_composed_info(constant_args, model_args, self):
|
||||
composed_instances = []
|
||||
allof_instances = get_allof_instances(self, model_args, constant_args)
|
||||
composed_instances.extend(allof_instances)
|
||||
oneof_instance = get_oneof_instance(self, model_args, constant_args)
|
||||
oneof_instance = get_oneof_instance(self.__class__, model_args, constant_args)
|
||||
if oneof_instance is not None:
|
||||
composed_instances.append(oneof_instance)
|
||||
anyof_instances = get_anyof_instances(self, model_args, constant_args)
|
||||
|
||||
@@ -35,6 +35,7 @@ from petstore_api.model.child_cat_all_of import ChildCatAllOf
|
||||
from petstore_api.model.class_model import ClassModel
|
||||
from petstore_api.model.client import Client
|
||||
from petstore_api.model.complex_quadrilateral import ComplexQuadrilateral
|
||||
from petstore_api.model.composed_one_of_number_with_validations import ComposedOneOfNumberWithValidations
|
||||
from petstore_api.model.danish_pig import DanishPig
|
||||
from petstore_api.model.dog import Dog
|
||||
from petstore_api.model.dog_all_of import DogAllOf
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
OpenAPI Petstore
|
||||
|
||||
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
|
||||
|
||||
The version of the OpenAPI document: 1.0.0
|
||||
Generated by: https://openapi-generator.tech
|
||||
"""
|
||||
|
||||
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import petstore_api
|
||||
try:
|
||||
from petstore_api.model import animal
|
||||
except ImportError:
|
||||
animal = sys.modules[
|
||||
'petstore_api.model.animal']
|
||||
from petstore_api.model.composed_one_of_number_with_validations import ComposedOneOfNumberWithValidations
|
||||
|
||||
|
||||
class TestComposedOneOfNumberWithValidations(unittest.TestCase):
|
||||
"""ComposedOneOfNumberWithValidations unit test stubs"""
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def testComposedOneOfNumberWithValidations(self):
|
||||
"""Test ComposedOneOfNumberWithValidations"""
|
||||
# we can make an instance that stores float data
|
||||
inst = ComposedOneOfNumberWithValidations(10.0)
|
||||
from petstore_api.model import number_with_validations
|
||||
assert isinstance(inst, number_with_validations.NumberWithValidations)
|
||||
# we can make an instance that stores object (dict) data
|
||||
inst = ComposedOneOfNumberWithValidations(class_name="Cat", color="black")
|
||||
assert isinstance(inst, ComposedOneOfNumberWithValidations)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -118,7 +118,7 @@ class TestDrawing(unittest.TestCase):
|
||||
"Required value type is {} and passed type was {} at {}")
|
||||
with self.assertRaisesRegexp(
|
||||
petstore_api.ApiTypeError,
|
||||
err_msg.format("main_shape", "Shape", "NoneType", "\['main_shape'\]")
|
||||
err_msg.format("main_shape", "one of \[ComplexQuadrilateral, EquilateralTriangle, IsoscelesTriangle, ScaleneTriangle, SimpleQuadrilateral\]", "NoneType", "\['main_shape'\]")
|
||||
):
|
||||
inst = Drawing(
|
||||
# 'main_shape' has type 'Shape', which is a oneOf [triangle, quadrilateral]
|
||||
|
||||
@@ -142,7 +142,6 @@ class TestFakeApi(unittest.TestCase):
|
||||
assert isinstance(response, array_of_enums.ArrayOfEnums)
|
||||
assert response.value == value
|
||||
|
||||
|
||||
def test_number_with_validations(self):
|
||||
"""Test case for number_with_validations
|
||||
|
||||
@@ -173,6 +172,44 @@ class TestFakeApi(unittest.TestCase):
|
||||
assert endpoint.openapi_types['body'] == (object_model_with_ref_props.ObjectModelWithRefProps,)
|
||||
assert endpoint.settings['response_type'] == (object_model_with_ref_props.ObjectModelWithRefProps,)
|
||||
|
||||
def test_composed_one_of_number_with_validations(self):
|
||||
"""Test case for composed_one_of_number_with_validations
|
||||
|
||||
"""
|
||||
from petstore_api.model import animal, composed_one_of_number_with_validations, number_with_validations
|
||||
endpoint = self.api.composed_one_of_number_with_validations
|
||||
assert endpoint.openapi_types['composed_one_of_number_with_validations_composed_one_of_number_with_validations'] == (
|
||||
composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations,)
|
||||
assert endpoint.settings['response_type'] == (
|
||||
composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations,)
|
||||
|
||||
# serialization + deserialization works
|
||||
num_with_validations = number_with_validations.NumberWithValidations(10.0)
|
||||
cat_in_composed = composed_one_of_number_with_validations.ComposedOneOfNumberWithValidations(
|
||||
class_name="Cat", color="black"
|
||||
)
|
||||
import datetime
|
||||
date = datetime.date(1970, 1, 1)
|
||||
body_value_simple = [
|
||||
(num_with_validations, 10.0),
|
||||
(cat_in_composed, {"className": "Cat", "color": "black"}),
|
||||
(None, None),
|
||||
(date, '1970-01-01'),
|
||||
]
|
||||
for (body, value_simple) in body_value_simple:
|
||||
with patch.object(RESTClientObject, 'request') as mock_method:
|
||||
mock_method.return_value = self.mock_response(value_simple)
|
||||
|
||||
response = endpoint(composed_one_of_number_with_validations_composed_one_of_number_with_validations=body)
|
||||
self.assert_request_called_with(
|
||||
mock_method,
|
||||
'http://petstore.swagger.io:80/v2/fake/refs/composed_one_of_number_with_validations',
|
||||
value_simple
|
||||
)
|
||||
|
||||
assert isinstance(response, body.__class__)
|
||||
assert response == body
|
||||
|
||||
def test_string(self):
|
||||
"""Test case for string
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ class TestIntegerEnumOneValue(unittest.TestCase):
|
||||
model = IntegerEnumOneValue()
|
||||
assert model.value == 0, "With only one option, the value is assigned automatically"
|
||||
|
||||
model = IntegerEnumOneValue(0)
|
||||
assert model.value == 0, "We can also pass in the value as a positional arg"
|
||||
|
||||
model = IntegerEnumOneValue(value=0)
|
||||
assert model.value == 0, "We can also pass in the value as a named argument"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user