From 5ade1775efae9dd866260046c0abe8f6a3fe3f4b Mon Sep 17 00:00:00 2001 From: m-standfuss <52842887+m-standfuss@users.noreply.github.com> Date: Thu, 22 Feb 2024 12:05:59 -0700 Subject: [PATCH 1/5] Adding decimal to template for Python generator --- .../src/main/resources/python/api_client.mustache | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/openapi-generator/src/main/resources/python/api_client.mustache b/modules/openapi-generator/src/main/resources/python/api_client.mustache index c27b6b77564b..54fb7b6473f7 100644 --- a/modules/openapi-generator/src/main/resources/python/api_client.mustache +++ b/modules/openapi-generator/src/main/resources/python/api_client.mustache @@ -5,6 +5,7 @@ import datetime from dateutil.parser import parse from enum import Enum +import decimal import json import mimetypes import os @@ -58,6 +59,7 @@ class ApiClient: 'bool': bool, 'date': datetime.date, 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, 'object': object, } _pool = None @@ -343,6 +345,7 @@ class ApiClient: If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. @@ -364,6 +367,8 @@ class ApiClient: ) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) elif isinstance(obj, dict): obj_dict = obj @@ -438,6 +443,8 @@ class ApiClient: return self.__deserialize_date(data) elif klass == datetime.datetime: return self.__deserialize_datetime(data) + elif klass == decimal.Decimal: + return decimal.Decimal(data) elif issubclass(klass, Enum): return self.__deserialize_enum(data, klass) else: From 0b848e3873534b8695471950896c1b977108f548 Mon Sep 17 00:00:00 2001 From: m-standfuss Date: Fri, 19 Jul 2024 15:36:07 -0600 Subject: [PATCH 2/5] Rerunning the build steps --- .../openapi_client/api_client.py | 7 +++++++ .../client/echo_api/python/openapi_client/api_client.py | 7 +++++++ .../petstore/python-aiohttp/petstore_api/api_client.py | 7 +++++++ .../client/petstore/python/petstore_api/api_client.py | 7 +++++++ 4 files changed, 28 insertions(+) diff --git a/samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/api_client.py b/samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/api_client.py index feef534a2f26..c6fa28de3197 100644 --- a/samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/api_client.py +++ b/samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/api_client.py @@ -16,6 +16,7 @@ import datetime from dateutil.parser import parse from enum import Enum +import decimal import json import mimetypes import os @@ -67,6 +68,7 @@ class ApiClient: 'bool': bool, 'date': datetime.date, 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, 'object': object, } _pool = None @@ -339,6 +341,7 @@ def sanitize_for_serialization(self, obj): If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. @@ -364,6 +367,8 @@ def sanitize_for_serialization(self, obj): ) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) elif isinstance(obj, dict): obj_dict = obj @@ -455,6 +460,8 @@ def __deserialize(self, data, klass): return self.__deserialize_date(data) elif klass == datetime.datetime: return self.__deserialize_datetime(data) + elif klass == decimal.Decimal: + return decimal.Decimal(data) elif issubclass(klass, Enum): return self.__deserialize_enum(data, klass) else: diff --git a/samples/client/echo_api/python/openapi_client/api_client.py b/samples/client/echo_api/python/openapi_client/api_client.py index feef534a2f26..c6fa28de3197 100644 --- a/samples/client/echo_api/python/openapi_client/api_client.py +++ b/samples/client/echo_api/python/openapi_client/api_client.py @@ -16,6 +16,7 @@ import datetime from dateutil.parser import parse from enum import Enum +import decimal import json import mimetypes import os @@ -67,6 +68,7 @@ class ApiClient: 'bool': bool, 'date': datetime.date, 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, 'object': object, } _pool = None @@ -339,6 +341,7 @@ def sanitize_for_serialization(self, obj): If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. @@ -364,6 +367,8 @@ def sanitize_for_serialization(self, obj): ) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) elif isinstance(obj, dict): obj_dict = obj @@ -455,6 +460,8 @@ def __deserialize(self, data, klass): return self.__deserialize_date(data) elif klass == datetime.datetime: return self.__deserialize_datetime(data) + elif klass == decimal.Decimal: + return decimal.Decimal(data) elif issubclass(klass, Enum): return self.__deserialize_enum(data, klass) else: diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/api_client.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/api_client.py index 302e5dac53c6..db57dd1827b6 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/api_client.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/api_client.py @@ -15,6 +15,7 @@ import datetime from dateutil.parser import parse from enum import Enum +import decimal import json import mimetypes import os @@ -66,6 +67,7 @@ class ApiClient: 'bool': bool, 'date': datetime.date, 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, 'object': object, } _pool = None @@ -341,6 +343,7 @@ def sanitize_for_serialization(self, obj): If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. @@ -366,6 +369,8 @@ def sanitize_for_serialization(self, obj): ) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) elif isinstance(obj, dict): obj_dict = obj @@ -457,6 +462,8 @@ def __deserialize(self, data, klass): return self.__deserialize_date(data) elif klass == datetime.datetime: return self.__deserialize_datetime(data) + elif klass == decimal.Decimal: + return decimal.Decimal(data) elif issubclass(klass, Enum): return self.__deserialize_enum(data, klass) else: diff --git a/samples/openapi3/client/petstore/python/petstore_api/api_client.py b/samples/openapi3/client/petstore/python/petstore_api/api_client.py index 9ab0756d53b4..cb831d0de813 100755 --- a/samples/openapi3/client/petstore/python/petstore_api/api_client.py +++ b/samples/openapi3/client/petstore/python/petstore_api/api_client.py @@ -15,6 +15,7 @@ import datetime from dateutil.parser import parse from enum import Enum +import decimal import json import mimetypes import os @@ -66,6 +67,7 @@ class ApiClient: 'bool': bool, 'date': datetime.date, 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, 'object': object, } _pool = None @@ -338,6 +340,7 @@ def sanitize_for_serialization(self, obj): If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. @@ -363,6 +366,8 @@ def sanitize_for_serialization(self, obj): ) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) elif isinstance(obj, dict): obj_dict = obj @@ -454,6 +459,8 @@ def __deserialize(self, data, klass): return self.__deserialize_date(data) elif klass == datetime.datetime: return self.__deserialize_datetime(data) + elif klass == decimal.Decimal: + return decimal.Decimal(data) elif issubclass(klass, Enum): return self.__deserialize_enum(data, klass) else: From 8180d8768c5bfee9efed90715f0a2738868bb100 Mon Sep 17 00:00:00 2001 From: m-standfuss Date: Mon, 22 Jul 2024 09:55:35 -0600 Subject: [PATCH 3/5] Add tests for decimal serialization and deserialization. --- .../python-pydantic-v1/tests/test_api_client.py | 8 ++++++-- .../petstore/python/tests/test_deserialization.py | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py index 9205f4ed998b..daa1a23c9b32 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py @@ -9,12 +9,11 @@ $ pytest """ -import os -import time import atexit import weakref import unittest from dateutil.parser import parse +from decimal import Decimal import petstore_api import petstore_api.configuration @@ -156,6 +155,11 @@ def test_sanitize_for_serialization(self): result = self.api_client.sanitize_for_serialization(data) self.assertEqual(result, "1997-07-16T19:20:30.450000+01:00") + # decimal + data = Decimal("1.0") + result = self.api_client.sanitize_for_serialization(data) + self.assertEquals(result, "1.0") + # list data = [1] result = self.api_client.sanitize_for_serialization(data) diff --git a/samples/openapi3/client/petstore/python/tests/test_deserialization.py b/samples/openapi3/client/petstore/python/tests/test_deserialization.py index 8fd654e4bb74..11b2955015ac 100644 --- a/samples/openapi3/client/petstore/python/tests/test_deserialization.py +++ b/samples/openapi3/client/petstore/python/tests/test_deserialization.py @@ -14,6 +14,7 @@ import time import unittest import datetime +from decimal import Decimal import pytest as pytest @@ -130,6 +131,15 @@ def test_deserialize_datetime(self): deserialized = self.deserialize(response, "datetime", 'application/json') self.assertTrue(isinstance(deserialized, datetime.datetime)) + def test_deserialize_decimal(self): + """ deserialize decimal """ + data = 1.1 + response = json.dumps(data) + + deserialized = self.deserialize(response, "decimal", 'application/json') + self.assertTrue(isinstance(deserialized, Decimal)) + self.assertEqual(deserialized, Decimal(1.1)) + def test_deserialize_pet(self): """ deserialize pet """ data = { From 3724025e0def4b2713a85d623df7dcbb4afcfe1a Mon Sep 17 00:00:00 2001 From: m-standfuss Date: Mon, 22 Jul 2024 10:47:45 -0600 Subject: [PATCH 4/5] Move test to python not legacy pydantic sample --- .../petstore/python-pydantic-v1/tests/test_api_client.py | 6 ------ .../client/petstore/python/tests/test_api_client.py | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py index daa1a23c9b32..d92c78554617 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py @@ -13,7 +13,6 @@ import weakref import unittest from dateutil.parser import parse -from decimal import Decimal import petstore_api import petstore_api.configuration @@ -155,11 +154,6 @@ def test_sanitize_for_serialization(self): result = self.api_client.sanitize_for_serialization(data) self.assertEqual(result, "1997-07-16T19:20:30.450000+01:00") - # decimal - data = Decimal("1.0") - result = self.api_client.sanitize_for_serialization(data) - self.assertEquals(result, "1.0") - # list data = [1] result = self.api_client.sanitize_for_serialization(data) diff --git a/samples/openapi3/client/petstore/python/tests/test_api_client.py b/samples/openapi3/client/petstore/python/tests/test_api_client.py index e80bc1352963..b444f326c675 100644 --- a/samples/openapi3/client/petstore/python/tests/test_api_client.py +++ b/samples/openapi3/client/petstore/python/tests/test_api_client.py @@ -10,6 +10,7 @@ """ import unittest +from decimal import Decimal from enum import Enum from dateutil.parser import parse @@ -180,6 +181,11 @@ def test_sanitize_for_serialization_datetime(self): result = self.api_client.sanitize_for_serialization(data) self.assertEqual(result, "1997-07-16T19:20:30.450000+01:00") + def test_sanitize_for_serialization_decimal(self): + data = Decimal("1.0") + result = self.api_client.sanitize_for_serialization(data) + self.assertEquals(result, "1.0") + def test_sanitize_for_serialization_list_enum(self): class EnumSerialization(int, Enum): NUMBER_0 = 0 From bc0195ca9c5d0fef5737c3ea7d9431b1df237102 Mon Sep 17 00:00:00 2001 From: m-standfuss Date: Mon, 22 Jul 2024 12:25:07 -0600 Subject: [PATCH 5/5] readd old imports --- .../client/petstore/python-pydantic-v1/tests/test_api_client.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py index d92c78554617..9205f4ed998b 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/tests/test_api_client.py @@ -9,6 +9,8 @@ $ pytest """ +import os +import time import atexit import weakref import unittest