Skip to content

Commit cbc006a

Browse files
authored
Adds memoization and deserialization through 2 or more discriminators (#6124)
* Adds cached_property decorator, adds feature to move through n discriminators * Adds v3 sample with 2 discriminators * Adds tests of Shape, Tringle, and Quadrilateral traveling through 2 discriminators * Adds test_deserialization.py:test_deserialize_shape * Simplifes XTriangle sample spec schemas * Simplifies Shape schema definition, updates go+python-experimental samples * Fixes python-experimental test_dog tests * Separates off python-experimental spec
1 parent e4cbaa7 commit cbc006a

179 files changed

Lines changed: 8339 additions & 947 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bin/openapi3/python-experimental-petstore.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fi
2828
# if you've executed sbt assembly previously it will use that instead.
2929
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
3030
#yaml="modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml"
31-
yaml="modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml"
31+
yaml="modules/openapi-generator/src/test/resources/3_0/python-experimental/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml"
3232
ags="generate -t modules/openapi-generator/src/main/resources/python -i $yaml -g python-experimental -o samples/openapi3/client/petstore/python-experimental/ --additional-properties packageName=petstore_api $@"
3333

3434
java $JAVA_OPTS -jar $executable $ags

modules/openapi-generator/src/main/resources/python/python-experimental/model.mustache

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ from {{packageName}}.model_utils import ( # noqa: F401
1313
ModelComposed,
1414
ModelNormal,
1515
ModelSimple,
16+
cached_property,
17+
change_keys_js_to_python,
18+
convert_js_args_to_python_args,
1619
date,
1720
datetime,
1821
file_type,

modules/openapi-generator/src/main/resources/python/python-experimental/model_templates/classvars.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494

9595
additional_properties_type = {{#additionalPropertiesType}}({{{additionalPropertiesType}}},) # noqa: E501{{/additionalPropertiesType}}{{^additionalPropertiesType}}None{{/additionalPropertiesType}}
9696

97-
@staticmethod
97+
@cached_property
9898
def openapi_types():
9999
"""
100100
This must be a class method so a model may have properties that are
@@ -113,7 +113,7 @@
113113
{{/optionalVars}}
114114
}
115115

116-
@staticmethod
116+
@cached_property
117117
def discriminator():
118118
{{^discriminator}}return None{{/discriminator}}{{#discriminator}}val = {
119119
{{#mappedModels}}

modules/openapi-generator/src/main/resources/python/python-experimental/model_templates/method_discriminator.mustache

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
@classmethod
2-
def get_discriminator_class(cls, from_server, data):
2+
def get_discriminator_class(cls, data):
33
"""Returns the child class specified by the discriminator"""
4-
discriminator = cls.discriminator()
4+
discriminator = cls.discriminator
55
discr_propertyname_py = list(discriminator.keys())[0]
66
discr_propertyname_js = cls.attribute_map[discr_propertyname_py]
7-
if from_server:
7+
if discr_propertyname_js in data:
88
class_name = data[discr_propertyname_js]
99
else:
1010
class_name = data[discr_propertyname_py]

modules/openapi-generator/src/main/resources/python/python-experimental/model_templates/method_init_composed.mustache

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
'_from_server',
55
'_path_to_item',
66
'_configuration',
7+
'_visited_composed_classes',
78
'_composed_instances',
89
'_var_name_to_model_instances',
910
'_additional_properties_model_instances',
@@ -16,6 +17,7 @@
1617
'_path_to_item': _path_to_item,
1718
'_from_server': _from_server,
1819
'_configuration': _configuration,
20+
'_visited_composed_classes': self._visited_composed_classes,
1921
}
2022
required_args = {
2123
{{#requiredVars}}

modules/openapi-generator/src/main/resources/python/python-experimental/model_templates/method_init_normal.mustache

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
'_from_server',
55
'_path_to_item',
66
'_configuration',
7+
'_visited_composed_classes',
78
])
89

910
{{> python-experimental/model_templates/method_init_shared }}

modules/openapi-generator/src/main/resources/python/python-experimental/model_templates/method_init_shared.mustache

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, **kwargs): # noqa: E501
1+
@convert_js_args_to_python_args
2+
def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
23
"""{{classname}} - a model defined in OpenAPI
34

45
{{#requiredVars}}
@@ -31,6 +32,21 @@
3132
deserializing a file_type parameter.
3233
If passed, type conversion is attempted
3334
If omitted no type conversion is done.
35+
_visited_composed_classes (tuple): This stores a tuple of
36+
classes that we have traveled through so that
37+
if we see that class again we will not use its
38+
discriminator again.
39+
When traveling through a discriminator, the
40+
composed schema that is
41+
is traveled through is added to this set.
42+
For example if Animal has a discriminator
43+
petType and we pass in "Dog", and the class Dog
44+
allOf includes Animal, we move through Animal
45+
once using the discriminator, and pick Dog.
46+
Then in Dog, we will make an instance of the
47+
Animal class but this time we won't travel
48+
through its discriminator because we passed in
49+
_visited_composed_classes = (Animal,)
3450
{{#optionalVars}}
3551
{{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501
3652
{{/optionalVars}}
@@ -40,4 +56,5 @@
4056
self._check_type = _check_type
4157
self._from_server = _from_server
4258
self._path_to_item = _path_to_item
43-
self._configuration = _configuration
59+
self._configuration = _configuration
60+
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)

modules/openapi-generator/src/main/resources/python/python-experimental/model_templates/method_set_attribute.mustache

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
path_to_item.extend(self._path_to_item)
77
path_to_item.append(name)
88

9-
openapi_types = self.openapi_types()
10-
if name in openapi_types:
11-
required_types_mixed = openapi_types[name]
9+
if name in self.openapi_types:
10+
required_types_mixed = self.openapi_types[name]
1211
elif self.additional_properties_type is None:
1312
raise ApiKeyError(
1413
"{0} has no key '{1}'".format(type(self).__name__, name),

modules/openapi-generator/src/main/resources/python/python-experimental/model_templates/model_composed.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class {{unescapedDescription}}(ModelComposed):
2626

2727
{{> python-experimental/model_templates/method_init_composed }}
2828

29-
@staticmethod
29+
@cached_property
3030
def _composed_schemas():
3131
# we need this here to make our import statements work
3232
# we must store _composed_schemas in here so the code is only run

modules/openapi-generator/src/main/resources/python/python-experimental/model_templates/model_normal.mustache

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ class {{unescapedDescription}}(ModelNormal):
2424
{{/optionalVars}}
2525
}
2626

27-
@staticmethod
28-
def _composed_schemas():
29-
return None
27+
_composed_schemas = {}
3028

3129
{{> python-experimental/model_templates/method_init_normal}}{{#discriminator}}
3230

0 commit comments

Comments
 (0)