diff --git a/modules/openapi-generator/src/main/resources/python/model_templates/methods_shared.mustache b/modules/openapi-generator/src/main/resources/python/model_templates/methods_shared.mustache index 43bcf6fd0d55..eddad2533afb 100644 --- a/modules/openapi-generator/src/main/resources/python/model_templates/methods_shared.mustache +++ b/modules/openapi-generator/src/main/resources/python/model_templates/methods_shared.mustache @@ -12,4 +12,23 @@ def __getattr__(self, attr): """get the value of an attribute using dot notation: `instance.attr`""" - return self.{{#attrNoneIfUnset}}get{{/attrNoneIfUnset}}{{^attrNoneIfUnset}}__getitem__{{/attrNoneIfUnset}}(attr) \ No newline at end of file + return self.{{#attrNoneIfUnset}}get{{/attrNoneIfUnset}}{{^attrNoneIfUnset}}__getitem__{{/attrNoneIfUnset}}(attr) + + def __copy__(self): + cls = self.__class__ + if self.get("_spec_property_naming", False): + return cls._new_from_openapi_data(**self.__dict__) + else: + return new_cls.__new__(cls, **self.__dict__) + + def __deepcopy__(self, memo): + cls = self.__class__ + + if self.get("_spec_property_naming", False): + new_inst = cls._new_from_openapi_data() + else: + new_inst = cls.__new__(cls) + + for k, v in self.__dict__.items(): + setattr(new_inst, k, deepcopy(v, memo)) + return new_inst diff --git a/modules/openapi-generator/src/main/resources/python/model_utils.mustache b/modules/openapi-generator/src/main/resources/python/model_utils.mustache index 6be57468da7a..24dd544ce056 100644 --- a/modules/openapi-generator/src/main/resources/python/model_utils.mustache +++ b/modules/openapi-generator/src/main/resources/python/model_utils.mustache @@ -1,6 +1,7 @@ {{>partial_header}} from datetime import date, datetime # noqa: F401 +from copy import deepcopy import inspect import io import os @@ -223,8 +224,13 @@ class OpenApiModel(object): self_inst = super(OpenApiModel, cls).__new__(cls) self_inst.__init__(*args, **kwargs) - new_inst = new_cls.__new__(new_cls, *args, **kwargs) - new_inst.__init__(*args, **kwargs) + if kwargs.get("_spec_property_naming", False): + # when true, implies new is from deserialization + new_inst = new_cls._new_from_openapi_data(*args, **kwargs) + else: + new_inst = new_cls.__new__(new_cls, *args, **kwargs) + new_inst.__init__(*args, **kwargs) + return new_inst diff --git a/samples/client/petstore/python/petstore_api/model_utils.py b/samples/client/petstore/python/petstore_api/model_utils.py index c9fc0cf08966..c723626fc498 100644 --- a/samples/client/petstore/python/petstore_api/model_utils.py +++ b/samples/client/petstore/python/petstore_api/model_utils.py @@ -9,6 +9,7 @@ from datetime import date, datetime # noqa: F401 +from copy import deepcopy import inspect import io import os @@ -186,6 +187,26 @@ def __getattr__(self, attr): """get the value of an attribute using dot notation: `instance.attr`""" return self.__getitem__(attr) + def __copy__(self): + cls = self.__class__ + if self.get("_spec_property_naming", False): + return cls._new_from_openapi_data(**self.__dict__) + else: + return new_cls.__new__(cls, **self.__dict__) + + def __deepcopy__(self, memo): + cls = self.__class__ + + if self.get("_spec_property_naming", False): + new_inst = cls._new_from_openapi_data() + else: + new_inst = cls.__new__(cls) + + for k, v in self.__dict__.items(): + setattr(new_inst, k, deepcopy(v, memo)) + return new_inst + + def __new__(cls, *args, **kwargs): # this function uses the discriminator to # pick a new schema/class to instantiate because a discriminator @@ -295,8 +316,13 @@ def __new__(cls, *args, **kwargs): self_inst = super(OpenApiModel, cls).__new__(cls) self_inst.__init__(*args, **kwargs) - new_inst = new_cls.__new__(new_cls, *args, **kwargs) - new_inst.__init__(*args, **kwargs) + if kwargs.get("_spec_property_naming", False): + # when true, implies new is from deserialization + new_inst = new_cls._new_from_openapi_data(*args, **kwargs) + else: + new_inst = new_cls.__new__(new_cls, *args, **kwargs) + new_inst.__init__(*args, **kwargs) + return new_inst diff --git a/samples/client/petstore/python_disallowAdditionalPropertiesIfNotPresent/petstore_api/model_utils.py b/samples/client/petstore/python_disallowAdditionalPropertiesIfNotPresent/petstore_api/model_utils.py index c9fc0cf08966..c723626fc498 100644 --- a/samples/client/petstore/python_disallowAdditionalPropertiesIfNotPresent/petstore_api/model_utils.py +++ b/samples/client/petstore/python_disallowAdditionalPropertiesIfNotPresent/petstore_api/model_utils.py @@ -9,6 +9,7 @@ from datetime import date, datetime # noqa: F401 +from copy import deepcopy import inspect import io import os @@ -186,6 +187,26 @@ def __getattr__(self, attr): """get the value of an attribute using dot notation: `instance.attr`""" return self.__getitem__(attr) + def __copy__(self): + cls = self.__class__ + if self.get("_spec_property_naming", False): + return cls._new_from_openapi_data(**self.__dict__) + else: + return new_cls.__new__(cls, **self.__dict__) + + def __deepcopy__(self, memo): + cls = self.__class__ + + if self.get("_spec_property_naming", False): + new_inst = cls._new_from_openapi_data() + else: + new_inst = cls.__new__(cls) + + for k, v in self.__dict__.items(): + setattr(new_inst, k, deepcopy(v, memo)) + return new_inst + + def __new__(cls, *args, **kwargs): # this function uses the discriminator to # pick a new schema/class to instantiate because a discriminator @@ -295,8 +316,13 @@ def __new__(cls, *args, **kwargs): self_inst = super(OpenApiModel, cls).__new__(cls) self_inst.__init__(*args, **kwargs) - new_inst = new_cls.__new__(new_cls, *args, **kwargs) - new_inst.__init__(*args, **kwargs) + if kwargs.get("_spec_property_naming", False): + # when true, implies new is from deserialization + new_inst = new_cls._new_from_openapi_data(*args, **kwargs) + else: + new_inst = new_cls.__new__(new_cls, *args, **kwargs) + new_inst.__init__(*args, **kwargs) + return new_inst diff --git a/samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py b/samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py index 3ba9a0be1c2a..023d770fe6a2 100644 --- a/samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py +++ b/samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py @@ -9,6 +9,7 @@ from datetime import date, datetime # noqa: F401 +from copy import deepcopy import inspect import io import os @@ -186,6 +187,26 @@ def __getattr__(self, attr): """get the value of an attribute using dot notation: `instance.attr`""" return self.__getitem__(attr) + def __copy__(self): + cls = self.__class__ + if self.get("_spec_property_naming", False): + return cls._new_from_openapi_data(**self.__dict__) + else: + return new_cls.__new__(cls, **self.__dict__) + + def __deepcopy__(self, memo): + cls = self.__class__ + + if self.get("_spec_property_naming", False): + new_inst = cls._new_from_openapi_data() + else: + new_inst = cls.__new__(cls) + + for k, v in self.__dict__.items(): + setattr(new_inst, k, deepcopy(v, memo)) + return new_inst + + def __new__(cls, *args, **kwargs): # this function uses the discriminator to # pick a new schema/class to instantiate because a discriminator @@ -295,8 +316,13 @@ def __new__(cls, *args, **kwargs): self_inst = super(OpenApiModel, cls).__new__(cls) self_inst.__init__(*args, **kwargs) - new_inst = new_cls.__new__(new_cls, *args, **kwargs) - new_inst.__init__(*args, **kwargs) + if kwargs.get("_spec_property_naming", False): + # when true, implies new is from deserialization + new_inst = new_cls._new_from_openapi_data(*args, **kwargs) + else: + new_inst = new_cls.__new__(new_cls, *args, **kwargs) + new_inst.__init__(*args, **kwargs) + return new_inst diff --git a/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py b/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py index cac00f27fa22..f4b73e17079a 100644 --- a/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py +++ b/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py @@ -9,6 +9,7 @@ from datetime import date, datetime # noqa: F401 +from copy import deepcopy import inspect import io import os @@ -186,6 +187,26 @@ def __getattr__(self, attr): """get the value of an attribute using dot notation: `instance.attr`""" return self.__getitem__(attr) + def __copy__(self): + cls = self.__class__ + if self.get("_spec_property_naming", False): + return cls._new_from_openapi_data(**self.__dict__) + else: + return new_cls.__new__(cls, **self.__dict__) + + def __deepcopy__(self, memo): + cls = self.__class__ + + if self.get("_spec_property_naming", False): + new_inst = cls._new_from_openapi_data() + else: + new_inst = cls.__new__(cls) + + for k, v in self.__dict__.items(): + setattr(new_inst, k, deepcopy(v, memo)) + return new_inst + + def __new__(cls, *args, **kwargs): # this function uses the discriminator to # pick a new schema/class to instantiate because a discriminator @@ -295,8 +316,13 @@ def __new__(cls, *args, **kwargs): self_inst = super(OpenApiModel, cls).__new__(cls) self_inst.__init__(*args, **kwargs) - new_inst = new_cls.__new__(new_cls, *args, **kwargs) - new_inst.__init__(*args, **kwargs) + if kwargs.get("_spec_property_naming", False): + # when true, implies new is from deserialization + new_inst = new_cls._new_from_openapi_data(*args, **kwargs) + else: + new_inst = new_cls.__new__(new_cls, *args, **kwargs) + new_inst.__init__(*args, **kwargs) + return new_inst diff --git a/samples/openapi3/client/petstore/python/petstore_api/model_utils.py b/samples/openapi3/client/petstore/python/petstore_api/model_utils.py index c9fc0cf08966..c723626fc498 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/model_utils.py +++ b/samples/openapi3/client/petstore/python/petstore_api/model_utils.py @@ -9,6 +9,7 @@ from datetime import date, datetime # noqa: F401 +from copy import deepcopy import inspect import io import os @@ -186,6 +187,26 @@ def __getattr__(self, attr): """get the value of an attribute using dot notation: `instance.attr`""" return self.__getitem__(attr) + def __copy__(self): + cls = self.__class__ + if self.get("_spec_property_naming", False): + return cls._new_from_openapi_data(**self.__dict__) + else: + return new_cls.__new__(cls, **self.__dict__) + + def __deepcopy__(self, memo): + cls = self.__class__ + + if self.get("_spec_property_naming", False): + new_inst = cls._new_from_openapi_data() + else: + new_inst = cls.__new__(cls) + + for k, v in self.__dict__.items(): + setattr(new_inst, k, deepcopy(v, memo)) + return new_inst + + def __new__(cls, *args, **kwargs): # this function uses the discriminator to # pick a new schema/class to instantiate because a discriminator @@ -295,8 +316,13 @@ def __new__(cls, *args, **kwargs): self_inst = super(OpenApiModel, cls).__new__(cls) self_inst.__init__(*args, **kwargs) - new_inst = new_cls.__new__(new_cls, *args, **kwargs) - new_inst.__init__(*args, **kwargs) + if kwargs.get("_spec_property_naming", False): + # when true, implies new is from deserialization + new_inst = new_cls._new_from_openapi_data(*args, **kwargs) + else: + new_inst = new_cls.__new__(new_cls, *args, **kwargs) + new_inst.__init__(*args, **kwargs) + return new_inst diff --git a/samples/openapi3/client/petstore/python/tests_manual/test_copy.py b/samples/openapi3/client/petstore/python/tests_manual/test_copy.py new file mode 100644 index 000000000000..35bd9a31a226 --- /dev/null +++ b/samples/openapi3/client/petstore/python/tests_manual/test_copy.py @@ -0,0 +1,34 @@ +from copy import deepcopy +import unittest +from petstore_api.model.mammal import Mammal +from petstore_api.model.triangle import Triangle + + +class TestCopy(unittest.TestCase): + """TestCopy unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testDeepCopyOneOf(self): + """test deepcopy""" + obj = deepcopy(Mammal(class_name="whale")) + assert id(deepcopy(obj)) != id(obj) + assert deepcopy(obj) == obj + + def testDeepCopyAllOf(self): + """test deepcopy""" + obj = Triangle(shape_type="Triangle", triangle_type="EquilateralTriangle", foo="blah") + assert id(deepcopy(obj)) != id(obj) + assert deepcopy(obj) == obj + + obj = Triangle._new_from_openapi_data(shape_type="Triangle", triangle_type="EquilateralTriangle", foo="blah") + assert id(deepcopy(obj)) != id(obj) + assert deepcopy(obj) == obj + + +if __name__ == '__main__': + unittest.main()