From f139c090e555007beb195d57f95d58e263d8a9f6 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 5 Sep 2022 11:03:57 -0700 Subject: [PATCH] [python-experimental] adds and uses regex patterns for json + filename detection (#13357) * Unit test sample regenerated * Reverts version files --- .../python-experimental/README.handlebars | 2 +- .../python-experimental/api_client.handlebars | 33 ++++++++++--------- .../python-experimental/README.md | 2 +- .../unit_test_api/api_client.py | 33 ++++++++++--------- .../petstore/python-experimental/README.md | 2 +- .../petstore_api/api_client.py | 33 ++++++++++--------- 6 files changed, 54 insertions(+), 51 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/python-experimental/README.handlebars b/modules/openapi-generator/src/main/resources/python-experimental/README.handlebars index a14d519a6bb..2b19aa847c6 100644 --- a/modules/openapi-generator/src/main/resources/python-experimental/README.handlebars +++ b/modules/openapi-generator/src/main/resources/python-experimental/README.handlebars @@ -21,7 +21,7 @@ Python {{generatorLanguageVersion}} v3.9 is needed so one can combine classmethod and property decorators to define object schema properties as classes -## Migration from other generators like python and python-experimental +## Migration from other generators like python and python-legacy ### Changes 1. This generator uses spec case for all (object) property names and parameter names. diff --git a/modules/openapi-generator/src/main/resources/python-experimental/api_client.handlebars b/modules/openapi-generator/src/main/resources/python-experimental/api_client.handlebars index bb361662b8d..d838a28059c 100644 --- a/modules/openapi-generator/src/main/resources/python-experimental/api_client.handlebars +++ b/modules/openapi-generator/src/main/resources/python-experimental/api_client.handlebars @@ -796,24 +796,25 @@ class ApiResponseWithoutDeserialization(ApiResponse): class JSONDetector: - @staticmethod - def _content_type_is_json(content_type: str) -> bool: - content_type_piece = content_type - if ';' in content_type: - # application/json; charset=UTF-8 - content_type_piece = content_type.split(';')[0] - elif '-' in content_type: - """ - application/json-patch+json - application/json-seq - """ - content_type_piece = content_type.split('-')[0] - if content_type_piece == 'application/json': + """ + Works for: + application/json + application/json; charset=UTF-8 + application/json-patch+json + application/geo+json + """ + __json_content_type_pattern = re.compile("application/[^+]*[+]?(json);?.*") + + @classmethod + def _content_type_is_json(cls, content_type: str) -> bool: + if cls.__json_content_type_pattern.match(content_type): return True return False class OpenApiResponse(JSONDetector): + __filename_content_disposition_pattern = re.compile('filename="(.+?)"') + def __init__( self, response_cls: typing.Type[ApiResponse] = ApiResponse, @@ -831,11 +832,11 @@ class OpenApiResponse(JSONDetector): # python must be >= 3.9 so we can pass in bytes into json.loads return json.loads(response.data) - @staticmethod - def __file_name_from_content_disposition(content_disposition: typing.Optional[str]) -> typing.Optional[str]: + @classmethod + def __file_name_from_content_disposition(cls, content_disposition: typing.Optional[str]) -> typing.Optional[str]: if content_disposition is None: return None - match = re.search('filename="(.+?)"', content_disposition) + match = cls.__filename_content_disposition_pattern.search(content_disposition) if not match: return None return match.group(1) diff --git a/samples/openapi3/client/3_0_3_unit_test/python-experimental/README.md b/samples/openapi3/client/3_0_3_unit_test/python-experimental/README.md index 101866d02ee..68f30a42213 100644 --- a/samples/openapi3/client/3_0_3_unit_test/python-experimental/README.md +++ b/samples/openapi3/client/3_0_3_unit_test/python-experimental/README.md @@ -13,7 +13,7 @@ Python >=3.9 v3.9 is needed so one can combine classmethod and property decorators to define object schema properties as classes -## Migration from other generators like python and python-experimental +## Migration from other generators like python and python-legacy ### Changes 1. This generator uses spec case for all (object) property names and parameter names. diff --git a/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/api_client.py b/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/api_client.py index c6bec775d7a..2e927d6172c 100644 --- a/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/api_client.py +++ b/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/api_client.py @@ -800,24 +800,25 @@ class ApiResponseWithoutDeserialization(ApiResponse): class JSONDetector: - @staticmethod - def _content_type_is_json(content_type: str) -> bool: - content_type_piece = content_type - if ';' in content_type: - # application/json; charset=UTF-8 - content_type_piece = content_type.split(';')[0] - elif '-' in content_type: - """ - application/json-patch+json - application/json-seq - """ - content_type_piece = content_type.split('-')[0] - if content_type_piece == 'application/json': + """ + Works for: + application/json + application/json; charset=UTF-8 + application/json-patch+json + application/geo+json + """ + __json_content_type_pattern = re.compile("application/[^+]*[+]?(json);?.*") + + @classmethod + def _content_type_is_json(cls, content_type: str) -> bool: + if cls.__json_content_type_pattern.match(content_type): return True return False class OpenApiResponse(JSONDetector): + __filename_content_disposition_pattern = re.compile('filename="(.+?)"') + def __init__( self, response_cls: typing.Type[ApiResponse] = ApiResponse, @@ -835,11 +836,11 @@ class OpenApiResponse(JSONDetector): # python must be >= 3.9 so we can pass in bytes into json.loads return json.loads(response.data) - @staticmethod - def __file_name_from_content_disposition(content_disposition: typing.Optional[str]) -> typing.Optional[str]: + @classmethod + def __file_name_from_content_disposition(cls, content_disposition: typing.Optional[str]) -> typing.Optional[str]: if content_disposition is None: return None - match = re.search('filename="(.+?)"', content_disposition) + match = cls.__filename_content_disposition_pattern.search(content_disposition) if not match: return None return match.group(1) diff --git a/samples/openapi3/client/petstore/python-experimental/README.md b/samples/openapi3/client/petstore/python-experimental/README.md index d8d33f0b471..4e49dd54c7c 100644 --- a/samples/openapi3/client/petstore/python-experimental/README.md +++ b/samples/openapi3/client/petstore/python-experimental/README.md @@ -13,7 +13,7 @@ Python >=3.9 v3.9 is needed so one can combine classmethod and property decorators to define object schema properties as classes -## Migration from other generators like python and python-experimental +## Migration from other generators like python and python-legacy ### Changes 1. This generator uses spec case for all (object) property names and parameter names. diff --git a/samples/openapi3/client/petstore/python-experimental/petstore_api/api_client.py b/samples/openapi3/client/petstore/python-experimental/petstore_api/api_client.py index 5f9314c9327..adb1288514e 100644 --- a/samples/openapi3/client/petstore/python-experimental/petstore_api/api_client.py +++ b/samples/openapi3/client/petstore/python-experimental/petstore_api/api_client.py @@ -800,24 +800,25 @@ class ApiResponseWithoutDeserialization(ApiResponse): class JSONDetector: - @staticmethod - def _content_type_is_json(content_type: str) -> bool: - content_type_piece = content_type - if ';' in content_type: - # application/json; charset=UTF-8 - content_type_piece = content_type.split(';')[0] - elif '-' in content_type: - """ - application/json-patch+json - application/json-seq - """ - content_type_piece = content_type.split('-')[0] - if content_type_piece == 'application/json': + """ + Works for: + application/json + application/json; charset=UTF-8 + application/json-patch+json + application/geo+json + """ + __json_content_type_pattern = re.compile("application/[^+]*[+]?(json);?.*") + + @classmethod + def _content_type_is_json(cls, content_type: str) -> bool: + if cls.__json_content_type_pattern.match(content_type): return True return False class OpenApiResponse(JSONDetector): + __filename_content_disposition_pattern = re.compile('filename="(.+?)"') + def __init__( self, response_cls: typing.Type[ApiResponse] = ApiResponse, @@ -835,11 +836,11 @@ class OpenApiResponse(JSONDetector): # python must be >= 3.9 so we can pass in bytes into json.loads return json.loads(response.data) - @staticmethod - def __file_name_from_content_disposition(content_disposition: typing.Optional[str]) -> typing.Optional[str]: + @classmethod + def __file_name_from_content_disposition(cls, content_disposition: typing.Optional[str]) -> typing.Optional[str]: if content_disposition is None: return None - match = re.search('filename="(.+?)"', content_disposition) + match = cls.__filename_content_disposition_pattern.search(content_disposition) if not match: return None return match.group(1)