python-experimental updates ancestor + adds descendant discriminator tests (#6417)

* Updates comments in new method

* Adds missing line in model_utils.py

* Removes biology examples, adds ParentPet ancestor example + test, adds Pig schemas

* Updates comment and var names in get_discriminator_class, adds testMammal test

* Updates comment
This commit is contained in:
Justin Black 2020-05-27 20:33:43 -07:00 committed by GitHub
parent dc48cfdf74
commit a017f3a892
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 867 additions and 518 deletions

View File

@ -83,26 +83,22 @@ class OpenApiModel(object):
cls.discriminator is None or cls.discriminator is None or
cls in visited_composed_classes cls in visited_composed_classes
): ):
# This openapi schema (cls) does not have a discriminator # Use case 1: this openapi schema (cls) does not have a discriminator
# Or we have already visited this class before and are sure that we # Use case 2: we have already visited this class before and are sure that we
# want to instantiate it this time. # want to instantiate it this time. We have visited this class deserializing
# a payload with a discriminator. During that process we traveled through
# this class but did not make an instance of it. Now we are making an
# instance of a composed class which contains cls in it, so this time make an instance of cls.
# #
# If we are making an instance of a composed schema Descendent # Here's an example of use case 2: If Animal has a discriminator
# which allOf includes Ancestor, then Ancestor contains # petType and we pass in "Dog", and the class Dog
# a discriminator that includes Descendent. # allOf includes Animal, we move through Animal
# So if we make an instance of Descendent, we have to make an # once using the discriminator, and pick Dog.
# instance of Ancestor to hold the allOf properties. # Then in the composed schema dog Dog, we will make an instance of the
# This code detects that use case and makes the instance of Ancestor # Animal class (because Dal has allOf: Animal) but this time we won't travel
# For example: # through Animal's discriminator because we passed in
# When making an instance of Dog, _visited_composed_classes = (Dog,) # _visited_composed_classes = (Animal,)
# then we make an instance of Animal to include in dog._composed_instances
# so when we are here, cls is Animal
# cls.discriminator != None
# cls not in _visited_composed_classes
# new_cls = Dog
# but we know we know that we already have Dog
# because it is in visited_composed_classes
# so make Animal here
return super(OpenApiModel, cls).__new__(cls) return super(OpenApiModel, cls).__new__(cls)
# Get the name and value of the discriminator property. # Get the name and value of the discriminator property.
@ -141,7 +137,22 @@ class OpenApiModel(object):
) )
if new_cls in visited_composed_classes: if new_cls in visited_composed_classes:
# if we are coming from the chosen new_cls use cls instead # if we are making an instance of a composed schema Descendent
# which allOf includes Ancestor, then Ancestor contains
# a discriminator that includes Descendent.
# So if we make an instance of Descendent, we have to make an
# instance of Ancestor to hold the allOf properties.
# This code detects that use case and makes the instance of Ancestor
# For example:
# When making an instance of Dog, _visited_composed_classes = (Dog,)
# then we make an instance of Animal to include in dog._composed_instances
# so when we are here, cls is Animal
# cls.discriminator != None
# cls not in _visited_composed_classes
# new_cls = Dog
# but we know we know that we already have Dog
# because it is in visited_composed_classes
# so make Animal here
return super(OpenApiModel, cls).__new__(cls) return super(OpenApiModel, cls).__new__(cls)
oneof_anyof_child = new_cls in oneof_anyof_classes oneof_anyof_child = new_cls in oneof_anyof_classes
@ -766,18 +777,20 @@ def get_discriminator_class(model_class,
used_model_class = class_name_to_discr_class.get(discr_value) used_model_class = class_name_to_discr_class.get(discr_value)
if used_model_class is None: if used_model_class is None:
# We didn't find a discriminated class in class_name_to_discr_class. # We didn't find a discriminated class in class_name_to_discr_class.
# So look in the ancestor or descendant discriminators
# The discriminator mapping may exist in a descendant (anyOf, oneOf) # The discriminator mapping may exist in a descendant (anyOf, oneOf)
# or ancestor (allOf). # or ancestor (allOf).
# Ancestor example: in the "Dog -> Mammal -> Chordate -> Animal" # Ancestor example: in the GrandparentAnimal -> ParentPet -> ChildCat
# hierarchy, the discriminator mappings may be defined at any level # hierarchy, the discriminator mappings may be defined at any level
# in the hieararchy. # in the hierarchy.
# Descendant example: a schema is oneOf[Plant, Mammal], and each # Descendant example: mammal -> whale/zebra/Pig -> BasquePig/DanishPig
# oneOf child may itself be an allOf with some arbitrary hierarchy, # if we try to make BasquePig from mammal, we need to travel through
# and a graph traversal is required to find the discriminator. # the oneOf descendant discriminators to find BasquePig
composed_children = model_class._composed_schemas.get('oneOf', ()) + \ descendant_classes = model_class._composed_schemas.get('oneOf', ()) + \
model_class._composed_schemas.get('anyOf', ()) + \ model_class._composed_schemas.get('anyOf', ())
model_class._composed_schemas.get('allOf', ()) ancestor_classes = model_class._composed_schemas.get('allOf', ())
for cls in composed_children: possible_classes = descendant_classes + ancestor_classes
for cls in possible_classes:
# Check if the schema has inherited discriminators. # Check if the schema has inherited discriminators.
if hasattr(cls, 'discriminator') and cls.discriminator is not None: if hasattr(cls, 'discriminator') and cls.discriminator is not None:
used_model_class = get_discriminator_class( used_model_class = get_discriminator_class(

View File

@ -1833,11 +1833,9 @@ components:
oneOf: oneOf:
- $ref: '#/components/schemas/whale' - $ref: '#/components/schemas/whale'
- $ref: '#/components/schemas/zebra' - $ref: '#/components/schemas/zebra'
- $ref: '#/components/schemas/Pig'
discriminator: discriminator:
propertyName: className propertyName: className
mapping:
whale: '#/components/schemas/whale'
zebra: '#/components/schemas/zebra'
whale: whale:
type: object type: object
properties: properties:
@ -1862,6 +1860,26 @@ components:
type: string type: string
required: required:
- className - className
Pig:
oneOf:
- $ref: '#/components/schemas/BasquePig'
- $ref: '#/components/schemas/DanishPig'
discriminator:
propertyName: className
BasquePig:
type: object
properties:
className:
type: string
required:
- className
DanishPig:
type: object
properties:
className:
type: string
required:
- className
gmFruit: gmFruit:
properties: properties:
color: color:
@ -1992,26 +2010,23 @@ components:
allOf: allOf:
- $ref: '#/components/schemas/ShapeInterface' - $ref: '#/components/schemas/ShapeInterface'
- $ref: '#/components/schemas/QuadrilateralInterface' - $ref: '#/components/schemas/QuadrilateralInterface'
# The following hierarchy is used to test discriminators GrandparentAnimal:
# that require recursive lookups.
biology.Chordate:
type: object type: object
discriminator:
propertyName: className
required: required:
- className - pet_type
properties: properties:
className: pet_type:
type: string type: string
biology.Reptile: discriminator:
propertyName: pet_type
ParentPet:
type: object
allOf: allOf:
- $ref: '#/components/schemas/biology.Chordate' - $ref: '#/components/schemas/GrandparentAnimal'
biology.Mammal: ChildCat:
allOf: allOf:
- $ref: '#/components/schemas/biology.Chordate' - $ref: '#/components/schemas/ParentPet'
biology.Primate: - type: object
allOf: properties:
- $ref: '#/components/schemas/biology.Mammal' name:
biology.Hominid: type: string
allOf:
- $ref: '#/components/schemas/biology.Primate'

View File

@ -155,26 +155,22 @@ class OpenApiModel(object):
cls.discriminator is None or cls.discriminator is None or
cls in visited_composed_classes cls in visited_composed_classes
): ):
# This openapi schema (cls) does not have a discriminator # Use case 1: this openapi schema (cls) does not have a discriminator
# Or we have already visited this class before and are sure that we # Use case 2: we have already visited this class before and are sure that we
# want to instantiate it this time. # want to instantiate it this time. We have visited this class deserializing
# a payload with a discriminator. During that process we traveled through
# this class but did not make an instance of it. Now we are making an
# instance of a composed class which contains cls in it, so this time make an instance of cls.
# #
# If we are making an instance of a composed schema Descendent # Here's an example of use case 2: If Animal has a discriminator
# which allOf includes Ancestor, then Ancestor contains # petType and we pass in "Dog", and the class Dog
# a discriminator that includes Descendent. # allOf includes Animal, we move through Animal
# So if we make an instance of Descendent, we have to make an # once using the discriminator, and pick Dog.
# instance of Ancestor to hold the allOf properties. # Then in the composed schema dog Dog, we will make an instance of the
# This code detects that use case and makes the instance of Ancestor # Animal class (because Dal has allOf: Animal) but this time we won't travel
# For example: # through Animal's discriminator because we passed in
# When making an instance of Dog, _visited_composed_classes = (Dog,) # _visited_composed_classes = (Animal,)
# then we make an instance of Animal to include in dog._composed_instances
# so when we are here, cls is Animal
# cls.discriminator != None
# cls not in _visited_composed_classes
# new_cls = Dog
# but we know we know that we already have Dog
# because it is in visited_composed_classes
# so make Animal here
return super(OpenApiModel, cls).__new__(cls) return super(OpenApiModel, cls).__new__(cls)
# Get the name and value of the discriminator property. # Get the name and value of the discriminator property.
@ -213,7 +209,22 @@ class OpenApiModel(object):
) )
if new_cls in visited_composed_classes: if new_cls in visited_composed_classes:
# if we are coming from the chosen new_cls use cls instead # if we are making an instance of a composed schema Descendent
# which allOf includes Ancestor, then Ancestor contains
# a discriminator that includes Descendent.
# So if we make an instance of Descendent, we have to make an
# instance of Ancestor to hold the allOf properties.
# This code detects that use case and makes the instance of Ancestor
# For example:
# When making an instance of Dog, _visited_composed_classes = (Dog,)
# then we make an instance of Animal to include in dog._composed_instances
# so when we are here, cls is Animal
# cls.discriminator != None
# cls not in _visited_composed_classes
# new_cls = Dog
# but we know we know that we already have Dog
# because it is in visited_composed_classes
# so make Animal here
return super(OpenApiModel, cls).__new__(cls) return super(OpenApiModel, cls).__new__(cls)
oneof_anyof_child = new_cls in oneof_anyof_classes oneof_anyof_child = new_cls in oneof_anyof_classes
@ -1033,18 +1044,20 @@ def get_discriminator_class(model_class,
used_model_class = class_name_to_discr_class.get(discr_value) used_model_class = class_name_to_discr_class.get(discr_value)
if used_model_class is None: if used_model_class is None:
# We didn't find a discriminated class in class_name_to_discr_class. # We didn't find a discriminated class in class_name_to_discr_class.
# So look in the ancestor or descendant discriminators
# The discriminator mapping may exist in a descendant (anyOf, oneOf) # The discriminator mapping may exist in a descendant (anyOf, oneOf)
# or ancestor (allOf). # or ancestor (allOf).
# Ancestor example: in the "Dog -> Mammal -> Chordate -> Animal" # Ancestor example: in the GrandparentAnimal -> ParentPet -> ChildCat
# hierarchy, the discriminator mappings may be defined at any level # hierarchy, the discriminator mappings may be defined at any level
# in the hieararchy. # in the hierarchy.
# Descendant example: a schema is oneOf[Plant, Mammal], and each # Descendant example: mammal -> whale/zebra/Pig -> BasquePig/DanishPig
# oneOf child may itself be an allOf with some arbitrary hierarchy, # if we try to make BasquePig from mammal, we need to travel through
# and a graph traversal is required to find the discriminator. # the oneOf descendant discriminators to find BasquePig
composed_children = model_class._composed_schemas.get('oneOf', ()) + \ descendant_classes = model_class._composed_schemas.get('oneOf', ()) + \
model_class._composed_schemas.get('anyOf', ()) + \ model_class._composed_schemas.get('anyOf', ())
model_class._composed_schemas.get('allOf', ()) ancestor_classes = model_class._composed_schemas.get('allOf', ())
for cls in composed_children: possible_classes = descendant_classes + ancestor_classes
for cls in possible_classes:
# Check if the schema has inherited discriminators. # Check if the schema has inherited discriminators.
if hasattr(cls, 'discriminator') and cls.discriminator is not None: if hasattr(cls, 'discriminator') and cls.discriminator is not None:
used_model_class = get_discriminator_class( used_model_class = get_discriminator_class(

View File

@ -14,18 +14,17 @@ docs/ArrayOfNumberOnly.md
docs/ArrayTest.md docs/ArrayTest.md
docs/Banana.md docs/Banana.md
docs/BananaReq.md docs/BananaReq.md
docs/BiologyChordate.md docs/BasquePig.md
docs/BiologyHominid.md
docs/BiologyMammal.md
docs/BiologyPrimate.md
docs/BiologyReptile.md
docs/Capitalization.md docs/Capitalization.md
docs/Cat.md docs/Cat.md
docs/CatAllOf.md docs/CatAllOf.md
docs/Category.md docs/Category.md
docs/ChildCat.md
docs/ChildCatAllOf.md
docs/ClassModel.md docs/ClassModel.md
docs/Client.md docs/Client.md
docs/ComplexQuadrilateral.md docs/ComplexQuadrilateral.md
docs/DanishPig.md
docs/DefaultApi.md docs/DefaultApi.md
docs/Dog.md docs/Dog.md
docs/DogAllOf.md docs/DogAllOf.md
@ -43,6 +42,7 @@ docs/FormatTest.md
docs/Fruit.md docs/Fruit.md
docs/FruitReq.md docs/FruitReq.md
docs/GmFruit.md docs/GmFruit.md
docs/GrandparentAnimal.md
docs/HasOnlyReadOnly.md docs/HasOnlyReadOnly.md
docs/HealthCheckResult.md docs/HealthCheckResult.md
docs/InlineObject.md docs/InlineObject.md
@ -69,8 +69,10 @@ docs/OuterEnum.md
docs/OuterEnumDefaultValue.md docs/OuterEnumDefaultValue.md
docs/OuterEnumInteger.md docs/OuterEnumInteger.md
docs/OuterEnumIntegerDefaultValue.md docs/OuterEnumIntegerDefaultValue.md
docs/ParentPet.md
docs/Pet.md docs/Pet.md
docs/PetApi.md docs/PetApi.md
docs/Pig.md
docs/Quadrilateral.md docs/Quadrilateral.md
docs/QuadrilateralInterface.md docs/QuadrilateralInterface.md
docs/ReadOnlyFirst.md docs/ReadOnlyFirst.md
@ -115,18 +117,17 @@ petstore_api/models/array_of_number_only.py
petstore_api/models/array_test.py petstore_api/models/array_test.py
petstore_api/models/banana.py petstore_api/models/banana.py
petstore_api/models/banana_req.py petstore_api/models/banana_req.py
petstore_api/models/biology_chordate.py petstore_api/models/basque_pig.py
petstore_api/models/biology_hominid.py
petstore_api/models/biology_mammal.py
petstore_api/models/biology_primate.py
petstore_api/models/biology_reptile.py
petstore_api/models/capitalization.py petstore_api/models/capitalization.py
petstore_api/models/cat.py petstore_api/models/cat.py
petstore_api/models/cat_all_of.py petstore_api/models/cat_all_of.py
petstore_api/models/category.py petstore_api/models/category.py
petstore_api/models/child_cat.py
petstore_api/models/child_cat_all_of.py
petstore_api/models/class_model.py petstore_api/models/class_model.py
petstore_api/models/client.py petstore_api/models/client.py
petstore_api/models/complex_quadrilateral.py petstore_api/models/complex_quadrilateral.py
petstore_api/models/danish_pig.py
petstore_api/models/dog.py petstore_api/models/dog.py
petstore_api/models/dog_all_of.py petstore_api/models/dog_all_of.py
petstore_api/models/drawing.py petstore_api/models/drawing.py
@ -141,6 +142,7 @@ petstore_api/models/format_test.py
petstore_api/models/fruit.py petstore_api/models/fruit.py
petstore_api/models/fruit_req.py petstore_api/models/fruit_req.py
petstore_api/models/gm_fruit.py petstore_api/models/gm_fruit.py
petstore_api/models/grandparent_animal.py
petstore_api/models/has_only_read_only.py petstore_api/models/has_only_read_only.py
petstore_api/models/health_check_result.py petstore_api/models/health_check_result.py
petstore_api/models/inline_object.py petstore_api/models/inline_object.py
@ -167,7 +169,9 @@ petstore_api/models/outer_enum.py
petstore_api/models/outer_enum_default_value.py petstore_api/models/outer_enum_default_value.py
petstore_api/models/outer_enum_integer.py petstore_api/models/outer_enum_integer.py
petstore_api/models/outer_enum_integer_default_value.py petstore_api/models/outer_enum_integer_default_value.py
petstore_api/models/parent_pet.py
petstore_api/models/pet.py petstore_api/models/pet.py
petstore_api/models/pig.py
petstore_api/models/quadrilateral.py petstore_api/models/quadrilateral.py
petstore_api/models/quadrilateral_interface.py petstore_api/models/quadrilateral_interface.py
petstore_api/models/read_only_first.py petstore_api/models/read_only_first.py

View File

@ -133,18 +133,17 @@ Class | Method | HTTP request | Description
- [array_test.ArrayTest](docs/ArrayTest.md) - [array_test.ArrayTest](docs/ArrayTest.md)
- [banana.Banana](docs/Banana.md) - [banana.Banana](docs/Banana.md)
- [banana_req.BananaReq](docs/BananaReq.md) - [banana_req.BananaReq](docs/BananaReq.md)
- [biology_chordate.BiologyChordate](docs/BiologyChordate.md) - [basque_pig.BasquePig](docs/BasquePig.md)
- [biology_hominid.BiologyHominid](docs/BiologyHominid.md)
- [biology_mammal.BiologyMammal](docs/BiologyMammal.md)
- [biology_primate.BiologyPrimate](docs/BiologyPrimate.md)
- [biology_reptile.BiologyReptile](docs/BiologyReptile.md)
- [capitalization.Capitalization](docs/Capitalization.md) - [capitalization.Capitalization](docs/Capitalization.md)
- [cat.Cat](docs/Cat.md) - [cat.Cat](docs/Cat.md)
- [cat_all_of.CatAllOf](docs/CatAllOf.md) - [cat_all_of.CatAllOf](docs/CatAllOf.md)
- [category.Category](docs/Category.md) - [category.Category](docs/Category.md)
- [child_cat.ChildCat](docs/ChildCat.md)
- [child_cat_all_of.ChildCatAllOf](docs/ChildCatAllOf.md)
- [class_model.ClassModel](docs/ClassModel.md) - [class_model.ClassModel](docs/ClassModel.md)
- [client.Client](docs/Client.md) - [client.Client](docs/Client.md)
- [complex_quadrilateral.ComplexQuadrilateral](docs/ComplexQuadrilateral.md) - [complex_quadrilateral.ComplexQuadrilateral](docs/ComplexQuadrilateral.md)
- [danish_pig.DanishPig](docs/DanishPig.md)
- [dog.Dog](docs/Dog.md) - [dog.Dog](docs/Dog.md)
- [dog_all_of.DogAllOf](docs/DogAllOf.md) - [dog_all_of.DogAllOf](docs/DogAllOf.md)
- [drawing.Drawing](docs/Drawing.md) - [drawing.Drawing](docs/Drawing.md)
@ -159,6 +158,7 @@ Class | Method | HTTP request | Description
- [fruit.Fruit](docs/Fruit.md) - [fruit.Fruit](docs/Fruit.md)
- [fruit_req.FruitReq](docs/FruitReq.md) - [fruit_req.FruitReq](docs/FruitReq.md)
- [gm_fruit.GmFruit](docs/GmFruit.md) - [gm_fruit.GmFruit](docs/GmFruit.md)
- [grandparent_animal.GrandparentAnimal](docs/GrandparentAnimal.md)
- [has_only_read_only.HasOnlyReadOnly](docs/HasOnlyReadOnly.md) - [has_only_read_only.HasOnlyReadOnly](docs/HasOnlyReadOnly.md)
- [health_check_result.HealthCheckResult](docs/HealthCheckResult.md) - [health_check_result.HealthCheckResult](docs/HealthCheckResult.md)
- [inline_object.InlineObject](docs/InlineObject.md) - [inline_object.InlineObject](docs/InlineObject.md)
@ -185,7 +185,9 @@ Class | Method | HTTP request | Description
- [outer_enum_default_value.OuterEnumDefaultValue](docs/OuterEnumDefaultValue.md) - [outer_enum_default_value.OuterEnumDefaultValue](docs/OuterEnumDefaultValue.md)
- [outer_enum_integer.OuterEnumInteger](docs/OuterEnumInteger.md) - [outer_enum_integer.OuterEnumInteger](docs/OuterEnumInteger.md)
- [outer_enum_integer_default_value.OuterEnumIntegerDefaultValue](docs/OuterEnumIntegerDefaultValue.md) - [outer_enum_integer_default_value.OuterEnumIntegerDefaultValue](docs/OuterEnumIntegerDefaultValue.md)
- [parent_pet.ParentPet](docs/ParentPet.md)
- [pet.Pet](docs/Pet.md) - [pet.Pet](docs/Pet.md)
- [pig.Pig](docs/Pig.md)
- [quadrilateral.Quadrilateral](docs/Quadrilateral.md) - [quadrilateral.Quadrilateral](docs/Quadrilateral.md)
- [quadrilateral_interface.QuadrilateralInterface](docs/QuadrilateralInterface.md) - [quadrilateral_interface.QuadrilateralInterface](docs/QuadrilateralInterface.md)
- [read_only_first.ReadOnlyFirst](docs/ReadOnlyFirst.md) - [read_only_first.ReadOnlyFirst](docs/ReadOnlyFirst.md)

View File

@ -1,4 +1,4 @@
# biology_mammal.BiologyMammal # basque_pig.BasquePig
## Properties ## Properties
Name | Type | Description | Notes Name | Type | Description | Notes

View File

@ -0,0 +1,11 @@
# child_cat.ChildCat
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**pet_type** | **str** | |
**name** | **str** | | [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)

View File

@ -0,0 +1,10 @@
# child_cat_all_of.ChildCatAllOf
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | | [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)

View File

@ -1,4 +1,4 @@
# biology_reptile.BiologyReptile # danish_pig.DanishPig
## Properties ## Properties
Name | Type | Description | Notes Name | Type | Description | Notes

View File

@ -1,9 +1,9 @@
# biology_chordate.BiologyChordate # grandparent_animal.GrandparentAnimal
## Properties ## Properties
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**class_name** | **str** | | **pet_type** | **str** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -1,9 +1,9 @@
# biology_primate.BiologyPrimate # parent_pet.ParentPet
## Properties ## Properties
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**class_name** | **str** | | **pet_type** | **str** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -1,4 +1,4 @@
# biology_hominid.BiologyHominid # pig.Pig
## Properties ## Properties
Name | Type | Description | Notes Name | Type | Description | Notes

View File

@ -51,18 +51,17 @@ from petstore_api.models.array_of_number_only import ArrayOfNumberOnly
from petstore_api.models.array_test import ArrayTest from petstore_api.models.array_test import ArrayTest
from petstore_api.models.banana import Banana from petstore_api.models.banana import Banana
from petstore_api.models.banana_req import BananaReq from petstore_api.models.banana_req import BananaReq
from petstore_api.models.biology_chordate import BiologyChordate from petstore_api.models.basque_pig import BasquePig
from petstore_api.models.biology_hominid import BiologyHominid
from petstore_api.models.biology_mammal import BiologyMammal
from petstore_api.models.biology_primate import BiologyPrimate
from petstore_api.models.biology_reptile import BiologyReptile
from petstore_api.models.capitalization import Capitalization from petstore_api.models.capitalization import Capitalization
from petstore_api.models.cat import Cat from petstore_api.models.cat import Cat
from petstore_api.models.cat_all_of import CatAllOf from petstore_api.models.cat_all_of import CatAllOf
from petstore_api.models.category import Category from petstore_api.models.category import Category
from petstore_api.models.child_cat import ChildCat
from petstore_api.models.child_cat_all_of import ChildCatAllOf
from petstore_api.models.class_model import ClassModel from petstore_api.models.class_model import ClassModel
from petstore_api.models.client import Client from petstore_api.models.client import Client
from petstore_api.models.complex_quadrilateral import ComplexQuadrilateral from petstore_api.models.complex_quadrilateral import ComplexQuadrilateral
from petstore_api.models.danish_pig import DanishPig
from petstore_api.models.dog import Dog from petstore_api.models.dog import Dog
from petstore_api.models.dog_all_of import DogAllOf from petstore_api.models.dog_all_of import DogAllOf
from petstore_api.models.drawing import Drawing from petstore_api.models.drawing import Drawing
@ -77,6 +76,7 @@ from petstore_api.models.format_test import FormatTest
from petstore_api.models.fruit import Fruit from petstore_api.models.fruit import Fruit
from petstore_api.models.fruit_req import FruitReq from petstore_api.models.fruit_req import FruitReq
from petstore_api.models.gm_fruit import GmFruit from petstore_api.models.gm_fruit import GmFruit
from petstore_api.models.grandparent_animal import GrandparentAnimal
from petstore_api.models.has_only_read_only import HasOnlyReadOnly from petstore_api.models.has_only_read_only import HasOnlyReadOnly
from petstore_api.models.health_check_result import HealthCheckResult from petstore_api.models.health_check_result import HealthCheckResult
from petstore_api.models.inline_object import InlineObject from petstore_api.models.inline_object import InlineObject
@ -103,7 +103,9 @@ from petstore_api.models.outer_enum import OuterEnum
from petstore_api.models.outer_enum_default_value import OuterEnumDefaultValue from petstore_api.models.outer_enum_default_value import OuterEnumDefaultValue
from petstore_api.models.outer_enum_integer import OuterEnumInteger from petstore_api.models.outer_enum_integer import OuterEnumInteger
from petstore_api.models.outer_enum_integer_default_value import OuterEnumIntegerDefaultValue from petstore_api.models.outer_enum_integer_default_value import OuterEnumIntegerDefaultValue
from petstore_api.models.parent_pet import ParentPet
from petstore_api.models.pet import Pet from petstore_api.models.pet import Pet
from petstore_api.models.pig import Pig
from petstore_api.models.quadrilateral import Quadrilateral from petstore_api.models.quadrilateral import Quadrilateral
from petstore_api.models.quadrilateral_interface import QuadrilateralInterface from petstore_api.models.quadrilateral_interface import QuadrilateralInterface
from petstore_api.models.read_only_first import ReadOnlyFirst from petstore_api.models.read_only_first import ReadOnlyFirst

View File

@ -155,26 +155,22 @@ class OpenApiModel(object):
cls.discriminator is None or cls.discriminator is None or
cls in visited_composed_classes cls in visited_composed_classes
): ):
# This openapi schema (cls) does not have a discriminator # Use case 1: this openapi schema (cls) does not have a discriminator
# Or we have already visited this class before and are sure that we # Use case 2: we have already visited this class before and are sure that we
# want to instantiate it this time. # want to instantiate it this time. We have visited this class deserializing
# a payload with a discriminator. During that process we traveled through
# this class but did not make an instance of it. Now we are making an
# instance of a composed class which contains cls in it, so this time make an instance of cls.
# #
# If we are making an instance of a composed schema Descendent # Here's an example of use case 2: If Animal has a discriminator
# which allOf includes Ancestor, then Ancestor contains # petType and we pass in "Dog", and the class Dog
# a discriminator that includes Descendent. # allOf includes Animal, we move through Animal
# So if we make an instance of Descendent, we have to make an # once using the discriminator, and pick Dog.
# instance of Ancestor to hold the allOf properties. # Then in the composed schema dog Dog, we will make an instance of the
# This code detects that use case and makes the instance of Ancestor # Animal class (because Dal has allOf: Animal) but this time we won't travel
# For example: # through Animal's discriminator because we passed in
# When making an instance of Dog, _visited_composed_classes = (Dog,) # _visited_composed_classes = (Animal,)
# then we make an instance of Animal to include in dog._composed_instances
# so when we are here, cls is Animal
# cls.discriminator != None
# cls not in _visited_composed_classes
# new_cls = Dog
# but we know we know that we already have Dog
# because it is in visited_composed_classes
# so make Animal here
return super(OpenApiModel, cls).__new__(cls) return super(OpenApiModel, cls).__new__(cls)
# Get the name and value of the discriminator property. # Get the name and value of the discriminator property.
@ -213,7 +209,22 @@ class OpenApiModel(object):
) )
if new_cls in visited_composed_classes: if new_cls in visited_composed_classes:
# if we are coming from the chosen new_cls use cls instead # if we are making an instance of a composed schema Descendent
# which allOf includes Ancestor, then Ancestor contains
# a discriminator that includes Descendent.
# So if we make an instance of Descendent, we have to make an
# instance of Ancestor to hold the allOf properties.
# This code detects that use case and makes the instance of Ancestor
# For example:
# When making an instance of Dog, _visited_composed_classes = (Dog,)
# then we make an instance of Animal to include in dog._composed_instances
# so when we are here, cls is Animal
# cls.discriminator != None
# cls not in _visited_composed_classes
# new_cls = Dog
# but we know we know that we already have Dog
# because it is in visited_composed_classes
# so make Animal here
return super(OpenApiModel, cls).__new__(cls) return super(OpenApiModel, cls).__new__(cls)
oneof_anyof_child = new_cls in oneof_anyof_classes oneof_anyof_child = new_cls in oneof_anyof_classes
@ -1033,18 +1044,20 @@ def get_discriminator_class(model_class,
used_model_class = class_name_to_discr_class.get(discr_value) used_model_class = class_name_to_discr_class.get(discr_value)
if used_model_class is None: if used_model_class is None:
# We didn't find a discriminated class in class_name_to_discr_class. # We didn't find a discriminated class in class_name_to_discr_class.
# So look in the ancestor or descendant discriminators
# The discriminator mapping may exist in a descendant (anyOf, oneOf) # The discriminator mapping may exist in a descendant (anyOf, oneOf)
# or ancestor (allOf). # or ancestor (allOf).
# Ancestor example: in the "Dog -> Mammal -> Chordate -> Animal" # Ancestor example: in the GrandparentAnimal -> ParentPet -> ChildCat
# hierarchy, the discriminator mappings may be defined at any level # hierarchy, the discriminator mappings may be defined at any level
# in the hieararchy. # in the hierarchy.
# Descendant example: a schema is oneOf[Plant, Mammal], and each # Descendant example: mammal -> whale/zebra/Pig -> BasquePig/DanishPig
# oneOf child may itself be an allOf with some arbitrary hierarchy, # if we try to make BasquePig from mammal, we need to travel through
# and a graph traversal is required to find the discriminator. # the oneOf descendant discriminators to find BasquePig
composed_children = model_class._composed_schemas.get('oneOf', ()) + \ descendant_classes = model_class._composed_schemas.get('oneOf', ()) + \
model_class._composed_schemas.get('anyOf', ()) + \ model_class._composed_schemas.get('anyOf', ())
model_class._composed_schemas.get('allOf', ()) ancestor_classes = model_class._composed_schemas.get('allOf', ())
for cls in composed_children: possible_classes = descendant_classes + ancestor_classes
for cls in possible_classes:
# Check if the schema has inherited discriminators. # Check if the schema has inherited discriminators.
if hasattr(cls, 'discriminator') and cls.discriminator is not None: if hasattr(cls, 'discriminator') and cls.discriminator is not None:
used_model_class = get_discriminator_class( used_model_class = get_discriminator_class(

View File

@ -32,29 +32,9 @@ from petstore_api.model_utils import ( # noqa: F401
str, str,
validate_get_composed_info, validate_get_composed_info,
) )
try:
from petstore_api.models import biology_hominid
except ImportError:
biology_hominid = sys.modules[
'petstore_api.models.biology_hominid']
try:
from petstore_api.models import biology_mammal
except ImportError:
biology_mammal = sys.modules[
'petstore_api.models.biology_mammal']
try:
from petstore_api.models import biology_primate
except ImportError:
biology_primate = sys.modules[
'petstore_api.models.biology_primate']
try:
from petstore_api.models import biology_reptile
except ImportError:
biology_reptile = sys.modules[
'petstore_api.models.biology_reptile']
class BiologyChordate(ModelNormal): class BasquePig(ModelNormal):
"""NOTE: This class is auto generated by OpenAPI Generator. """NOTE: This class is auto generated by OpenAPI Generator.
Ref: https://openapi-generator.tech Ref: https://openapi-generator.tech
@ -102,15 +82,7 @@ class BiologyChordate(ModelNormal):
@cached_property @cached_property
def discriminator(): def discriminator():
val = { return None
'biology.Hominid': biology_hominid.BiologyHominid,
'biology.Mammal': biology_mammal.BiologyMammal,
'biology.Primate': biology_primate.BiologyPrimate,
'biology.Reptile': biology_reptile.BiologyReptile,
}
if not val:
return None
return {'class_name': val}
attribute_map = { attribute_map = {
'class_name': 'className', # noqa: E501 'class_name': 'className', # noqa: E501
@ -129,7 +101,7 @@ class BiologyChordate(ModelNormal):
@convert_js_args_to_python_args @convert_js_args_to_python_args
def __init__(self, class_name, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501 def __init__(self, class_name, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
"""biology_chordate.BiologyChordate - a model defined in OpenAPI """basque_pig.BasquePig - a model defined in OpenAPI
Args: Args:
class_name (str): class_name (str):

View File

@ -1,224 +0,0 @@
# 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
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.models import biology_chordate
except ImportError:
biology_chordate = sys.modules[
'petstore_api.models.biology_chordate']
try:
from petstore_api.models import biology_hominid
except ImportError:
biology_hominid = sys.modules[
'petstore_api.models.biology_hominid']
try:
from petstore_api.models import biology_primate
except ImportError:
biology_primate = sys.modules[
'petstore_api.models.biology_primate']
class BiologyMammal(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 = None
@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
}
@cached_property
def discriminator():
val = {
'biology.Hominid': biology_hominid.BiologyHominid,
'biology.Primate': biology_primate.BiologyPrimate,
}
if not val:
return None
return {'class_name': val}
attribute_map = {
'class_name': 'className', # 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, class_name, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
"""biology_mammal.BiologyMammal - a model defined in OpenAPI
Args:
class_name (str):
Keyword Args:
_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,)
"""
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': [
biology_chordate.BiologyChordate,
],
'oneOf': [
],
}

View File

@ -33,13 +33,18 @@ from petstore_api.model_utils import ( # noqa: F401
validate_get_composed_info, validate_get_composed_info,
) )
try: try:
from petstore_api.models import biology_primate from petstore_api.models import child_cat_all_of
except ImportError: except ImportError:
biology_primate = sys.modules[ child_cat_all_of = sys.modules[
'petstore_api.models.biology_primate'] 'petstore_api.models.child_cat_all_of']
try:
from petstore_api.models import parent_pet
except ImportError:
parent_pet = sys.modules[
'petstore_api.models.parent_pet']
class BiologyHominid(ModelComposed): class ChildCat(ModelComposed):
"""NOTE: This class is auto generated by OpenAPI Generator. """NOTE: This class is auto generated by OpenAPI Generator.
Ref: https://openapi-generator.tech Ref: https://openapi-generator.tech
@ -82,7 +87,8 @@ class BiologyHominid(ModelComposed):
and the value is attribute type. and the value is attribute type.
""" """
return { return {
'class_name': (str,), # noqa: E501 'pet_type': (str,), # noqa: E501
'name': (str,), # noqa: E501
} }
@cached_property @cached_property
@ -91,10 +97,11 @@ class BiologyHominid(ModelComposed):
} }
if not val: if not val:
return None return None
return {'class_name': val} return {'pet_type': val}
attribute_map = { attribute_map = {
'class_name': 'className', # noqa: E501 'pet_type': 'pet_type', # noqa: E501
'name': 'name', # noqa: E501
} }
required_properties = set([ required_properties = set([
@ -110,11 +117,11 @@ class BiologyHominid(ModelComposed):
]) ])
@convert_js_args_to_python_args @convert_js_args_to_python_args
def __init__(self, class_name, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501 def __init__(self, pet_type, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
"""biology_hominid.BiologyHominid - a model defined in OpenAPI """child_cat.ChildCat - a model defined in OpenAPI
Args: Args:
class_name (str): pet_type (str):
Keyword Args: Keyword Args:
_check_type (bool): if True, values for parameters in openapi_types _check_type (bool): if True, values for parameters in openapi_types
@ -147,6 +154,7 @@ class BiologyHominid(ModelComposed):
Animal class but this time we won't travel Animal class but this time we won't travel
through its discriminator because we passed in through its discriminator because we passed in
_visited_composed_classes = (Animal,) _visited_composed_classes = (Animal,)
name (str): [optional] # noqa: E501
""" """
self._data_store = {} self._data_store = {}
@ -164,7 +172,7 @@ class BiologyHominid(ModelComposed):
'_visited_composed_classes': self._visited_composed_classes, '_visited_composed_classes': self._visited_composed_classes,
} }
required_args = { required_args = {
'class_name': class_name, 'pet_type': pet_type,
} }
# remove args whose value is Null because they are unset # remove args whose value is Null because they are unset
required_arg_names = list(required_args.keys()) required_arg_names = list(required_args.keys())
@ -205,7 +213,8 @@ class BiologyHominid(ModelComposed):
'anyOf': [ 'anyOf': [
], ],
'allOf': [ 'allOf': [
biology_primate.BiologyPrimate, child_cat_all_of.ChildCatAllOf,
parent_pet.ParentPet,
], ],
'oneOf': [ 'oneOf': [
], ],

View File

@ -0,0 +1,154 @@
# 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
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,
)
class ChildCatAllOf(ModelNormal):
"""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 = None
@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 {
'name': (str,), # noqa: E501
}
@cached_property
def discriminator():
return None
attribute_map = {
'name': 'name', # noqa: E501
}
_composed_schemas = {}
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, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
"""child_cat_all_of.ChildCatAllOf - a model defined in OpenAPI
Keyword Args:
_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,)
name (str): [optional] # noqa: E501
"""
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__,)
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)

View File

@ -0,0 +1,157 @@
# 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
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,
)
class DanishPig(ModelNormal):
"""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 = None
@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
}
@cached_property
def discriminator():
return None
attribute_map = {
'class_name': 'className', # noqa: E501
}
_composed_schemas = {}
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, class_name, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
"""danish_pig.DanishPig - a model defined in OpenAPI
Args:
class_name (str):
Keyword Args:
_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,)
"""
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.class_name = class_name
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)

View File

@ -0,0 +1,173 @@
# 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
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.models import child_cat
except ImportError:
child_cat = sys.modules[
'petstore_api.models.child_cat']
try:
from petstore_api.models import parent_pet
except ImportError:
parent_pet = sys.modules[
'petstore_api.models.parent_pet']
class GrandparentAnimal(ModelNormal):
"""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 = None
@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 {
'pet_type': (str,), # noqa: E501
}
@cached_property
def discriminator():
val = {
'ChildCat': child_cat.ChildCat,
'ParentPet': parent_pet.ParentPet,
}
if not val:
return None
return {'pet_type': val}
attribute_map = {
'pet_type': 'pet_type', # noqa: E501
}
_composed_schemas = {}
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, pet_type, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
"""grandparent_animal.GrandparentAnimal - a model defined in OpenAPI
Args:
pet_type (str):
Keyword Args:
_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,)
"""
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.pet_type = pet_type
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)

View File

@ -32,6 +32,11 @@ from petstore_api.model_utils import ( # noqa: F401
str, str,
validate_get_composed_info, validate_get_composed_info,
) )
try:
from petstore_api.models import pig
except ImportError:
pig = sys.modules[
'petstore_api.models.pig']
try: try:
from petstore_api.models import whale from petstore_api.models import whale
except ImportError: except ImportError:
@ -101,6 +106,7 @@ class Mammal(ModelComposed):
@cached_property @cached_property
def discriminator(): def discriminator():
val = { val = {
'Pig': pig.Pig,
'whale': whale.Whale, 'whale': whale.Whale,
'zebra': zebra.Zebra, 'zebra': zebra.Zebra,
} }
@ -228,6 +234,7 @@ class Mammal(ModelComposed):
'allOf': [ 'allOf': [
], ],
'oneOf': [ 'oneOf': [
pig.Pig,
whale.Whale, whale.Whale,
zebra.Zebra, zebra.Zebra,
], ],

View File

@ -33,13 +33,18 @@ from petstore_api.model_utils import ( # noqa: F401
validate_get_composed_info, validate_get_composed_info,
) )
try: try:
from petstore_api.models import biology_chordate from petstore_api.models import child_cat
except ImportError: except ImportError:
biology_chordate = sys.modules[ child_cat = sys.modules[
'petstore_api.models.biology_chordate'] 'petstore_api.models.child_cat']
try:
from petstore_api.models import grandparent_animal
except ImportError:
grandparent_animal = sys.modules[
'petstore_api.models.grandparent_animal']
class BiologyReptile(ModelComposed): class ParentPet(ModelComposed):
"""NOTE: This class is auto generated by OpenAPI Generator. """NOTE: This class is auto generated by OpenAPI Generator.
Ref: https://openapi-generator.tech Ref: https://openapi-generator.tech
@ -82,19 +87,20 @@ class BiologyReptile(ModelComposed):
and the value is attribute type. and the value is attribute type.
""" """
return { return {
'class_name': (str,), # noqa: E501 'pet_type': (str,), # noqa: E501
} }
@cached_property @cached_property
def discriminator(): def discriminator():
val = { val = {
'ChildCat': child_cat.ChildCat,
} }
if not val: if not val:
return None return None
return {'class_name': val} return {'pet_type': val}
attribute_map = { attribute_map = {
'class_name': 'className', # noqa: E501 'pet_type': 'pet_type', # noqa: E501
} }
required_properties = set([ required_properties = set([
@ -110,11 +116,11 @@ class BiologyReptile(ModelComposed):
]) ])
@convert_js_args_to_python_args @convert_js_args_to_python_args
def __init__(self, class_name, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501 def __init__(self, pet_type, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
"""biology_reptile.BiologyReptile - a model defined in OpenAPI """parent_pet.ParentPet - a model defined in OpenAPI
Args: Args:
class_name (str): pet_type (str):
Keyword Args: Keyword Args:
_check_type (bool): if True, values for parameters in openapi_types _check_type (bool): if True, values for parameters in openapi_types
@ -164,7 +170,7 @@ class BiologyReptile(ModelComposed):
'_visited_composed_classes': self._visited_composed_classes, '_visited_composed_classes': self._visited_composed_classes,
} }
required_args = { required_args = {
'class_name': class_name, 'pet_type': pet_type,
} }
# remove args whose value is Null because they are unset # remove args whose value is Null because they are unset
required_arg_names = list(required_args.keys()) required_arg_names = list(required_args.keys())
@ -205,7 +211,7 @@ class BiologyReptile(ModelComposed):
'anyOf': [ 'anyOf': [
], ],
'allOf': [ 'allOf': [
biology_chordate.BiologyChordate, grandparent_animal.GrandparentAnimal,
], ],
'oneOf': [ 'oneOf': [
], ],

View File

@ -33,18 +33,18 @@ from petstore_api.model_utils import ( # noqa: F401
validate_get_composed_info, validate_get_composed_info,
) )
try: try:
from petstore_api.models import biology_hominid from petstore_api.models import basque_pig
except ImportError: except ImportError:
biology_hominid = sys.modules[ basque_pig = sys.modules[
'petstore_api.models.biology_hominid'] 'petstore_api.models.basque_pig']
try: try:
from petstore_api.models import biology_mammal from petstore_api.models import danish_pig
except ImportError: except ImportError:
biology_mammal = sys.modules[ danish_pig = sys.modules[
'petstore_api.models.biology_mammal'] 'petstore_api.models.danish_pig']
class BiologyPrimate(ModelComposed): class Pig(ModelComposed):
"""NOTE: This class is auto generated by OpenAPI Generator. """NOTE: This class is auto generated by OpenAPI Generator.
Ref: https://openapi-generator.tech Ref: https://openapi-generator.tech
@ -93,7 +93,8 @@ class BiologyPrimate(ModelComposed):
@cached_property @cached_property
def discriminator(): def discriminator():
val = { val = {
'biology.Hominid': biology_hominid.BiologyHominid, 'BasquePig': basque_pig.BasquePig,
'DanishPig': danish_pig.DanishPig,
} }
if not val: if not val:
return None return None
@ -117,7 +118,7 @@ class BiologyPrimate(ModelComposed):
@convert_js_args_to_python_args @convert_js_args_to_python_args
def __init__(self, class_name, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501 def __init__(self, class_name, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
"""biology_primate.BiologyPrimate - a model defined in OpenAPI """pig.Pig - a model defined in OpenAPI
Args: Args:
class_name (str): class_name (str):
@ -211,8 +212,9 @@ class BiologyPrimate(ModelComposed):
'anyOf': [ 'anyOf': [
], ],
'allOf': [ 'allOf': [
biology_mammal.BiologyMammal,
], ],
'oneOf': [ 'oneOf': [
basque_pig.BasquePig,
danish_pig.DanishPig,
], ],
} }

View File

@ -17,8 +17,8 @@ import unittest
import petstore_api import petstore_api
class TestBiologyMammal(unittest.TestCase): class TestBasquePig(unittest.TestCase):
"""BiologyMammal unit test stubs""" """BasquePig unit test stubs"""
def setUp(self): def setUp(self):
pass pass
@ -26,10 +26,10 @@ class TestBiologyMammal(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def testBiologyMammal(self): def testBasquePig(self):
"""Test BiologyMammal""" """Test BasquePig"""
# FIXME: construct object with mandatory attributes with example values # FIXME: construct object with mandatory attributes with example values
# model = petstore_api.BiologyMammal() # noqa: E501 # model = petstore_api.BasquePig() # noqa: E501
pass pass

View File

@ -17,8 +17,8 @@ import unittest
import petstore_api import petstore_api
class TestBiologyReptile(unittest.TestCase): class TestChildCat(unittest.TestCase):
"""BiologyReptile unit test stubs""" """ChildCat unit test stubs"""
def setUp(self): def setUp(self):
pass pass
@ -26,10 +26,10 @@ class TestBiologyReptile(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def testBiologyReptile(self): def testChildCat(self):
"""Test BiologyReptile""" """Test ChildCat"""
# FIXME: construct object with mandatory attributes with example values # FIXME: construct object with mandatory attributes with example values
# model = petstore_api.BiologyReptile() # noqa: E501 # model = petstore_api.ChildCat() # noqa: E501
pass pass

View File

@ -17,8 +17,8 @@ import unittest
import petstore_api import petstore_api
class TestBiologyHominid(unittest.TestCase): class TestChildCatAllOf(unittest.TestCase):
"""BiologyHominid unit test stubs""" """ChildCatAllOf unit test stubs"""
def setUp(self): def setUp(self):
pass pass
@ -26,10 +26,10 @@ class TestBiologyHominid(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def testBiologyHominid(self): def testChildCatAllOf(self):
"""Test BiologyHominid""" """Test ChildCatAllOf"""
# FIXME: construct object with mandatory attributes with example values # FIXME: construct object with mandatory attributes with example values
# model = petstore_api.BiologyHominid() # noqa: E501 # model = petstore_api.ChildCatAllOf() # noqa: E501
pass pass

View File

@ -17,8 +17,8 @@ import unittest
import petstore_api import petstore_api
class TestBiologyPrimate(unittest.TestCase): class TestDanishPig(unittest.TestCase):
"""BiologyPrimate unit test stubs""" """DanishPig unit test stubs"""
def setUp(self): def setUp(self):
pass pass
@ -26,10 +26,10 @@ class TestBiologyPrimate(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def testBiologyPrimate(self): def testDanishPig(self):
"""Test BiologyPrimate""" """Test DanishPig"""
# FIXME: construct object with mandatory attributes with example values # FIXME: construct object with mandatory attributes with example values
# model = petstore_api.BiologyPrimate() # noqa: E501 # model = petstore_api.DanishPig() # noqa: E501
pass pass

View File

@ -17,8 +17,8 @@ import unittest
import petstore_api import petstore_api
class TestBiologyChordate(unittest.TestCase): class TestGrandparentAnimal(unittest.TestCase):
"""BiologyChordate unit test stubs""" """GrandparentAnimal unit test stubs"""
def setUp(self): def setUp(self):
pass pass
@ -26,10 +26,10 @@ class TestBiologyChordate(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def testBiologyChordate(self): def testGrandparentAnimal(self):
"""Test BiologyChordate""" """Test GrandparentAnimal"""
# FIXME: construct object with mandatory attributes with example values # FIXME: construct object with mandatory attributes with example values
# model = petstore_api.BiologyChordate() # noqa: E501 # model = petstore_api.GrandparentAnimal() # noqa: E501
pass pass

View File

@ -28,9 +28,10 @@ class TestMammal(unittest.TestCase):
def testMammal(self): def testMammal(self):
"""Test Mammal""" """Test Mammal"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.Mammal() # noqa: E501 # tests that we can make a BasquePig by traveling through descendant discriminator in Pig
pass model = petstore_api.Mammal(class_name="BasquePig")
assert isinstance(model, petstore_api.BasquePig)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -0,0 +1,39 @@
# 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 unittest
import petstore_api
class TestParentPet(unittest.TestCase):
"""ParentPet unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def testParentPet(self):
"""Test ParentPet"""
# test that we can make a ParentPet from a ParentPet
# which requires that we travel back through ParentPet's allOf descendant
# GrandparentAnimal, and we use the descendant's discriminator to make ParentPet
model = petstore_api.ParentPet(pet_type="ParentPet")
assert isinstance(model, petstore_api.ParentPet)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,37 @@
# 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 unittest
import petstore_api
class TestPig(unittest.TestCase):
"""Pig unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def testPig(self):
"""Test Pig"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.Pig() # noqa: E501
pass
if __name__ == '__main__':
unittest.main()

View File

@ -1,67 +0,0 @@
# coding: utf-8
"""
Run the tests.
$ pip install nose (optional)
$ cd OpenAPIPetstore-python
$ nosetests -v
"""
from __future__ import absolute_import
import unittest
import petstore_api
class TestChordates(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def testChordateDeserializationAndDiscriminator(self):
"""Test Chordates deserialization
It should be possible to create instances from anywhere
in the animal class hierarchy, as long as the discriminator
value is valid. Internally, the get_discriminator_class()
function may need to call itself recursively to traverse
the composed hierarchy.
These unit tests would not work if get_discriminator_class
did not call itself recursively.
"""
inst = petstore_api.BiologyChordate(
class_name="biology.Mammal",
)
assert isinstance(inst, petstore_api.BiologyMammal)
inst = petstore_api.BiologyChordate(
class_name="biology.Primate",
)
assert isinstance(inst, petstore_api.BiologyPrimate)
inst = petstore_api.BiologyChordate(
class_name="biology.Reptile",
)
assert isinstance(inst, petstore_api.BiologyReptile)
inst = petstore_api.BiologyChordate(
class_name="biology.Hominid",
)
assert isinstance(inst, petstore_api.BiologyHominid)
def testMammalDeserializationAndDiscriminator(self):
"""Test Chordates deserialization"""
inst = petstore_api.BiologyMammal(
class_name="biology.Hominid",
)
assert isinstance(inst, petstore_api.BiologyHominid)
def testHominidDeserializationAndDiscriminator(self):
inst = petstore_api.BiologyHominid(
class_name="biology.Hominid",
)
assert isinstance(inst, petstore_api.BiologyHominid)