From 6df6c079ee7df4127b8f625503ffcc5211574a28 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Mon, 29 Jun 2015 17:08:03 +0800 Subject: [PATCH 01/12] Support file downloading in Python codegen. --- .../languages/PythonClientCodegen.java | 1 + .../main/resources/python/api_client.mustache | 43 ++++++++++++++++--- .../resources/python/configuration.mustache | 3 +- .../src/main/resources/python/rest.mustache | 13 +++--- .../python/swagger_client/api_client.py | 43 ++++++++++++++++--- .../python/swagger_client/configuration.py | 3 +- .../petstore/python/swagger_client/rest.py | 13 +++--- .../tests/test_store_api.py | 6 +-- 8 files changed, 100 insertions(+), 25 deletions(-) rename samples/client/petstore/python/{SwaggerPetstore-python => }/tests/test_store_api.py (79%) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java index 090c0e0c3dc..c0430515201 100755 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java @@ -48,6 +48,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig typeMapping.put("date", "date"); typeMapping.put("DateTime", "datetime"); typeMapping.put("object", "object"); + typeMapping.put("file", "file"); // from https://docs.python.org/release/2.5.4/ref/keywords.html reservedWords = new HashSet( diff --git a/modules/swagger-codegen/src/main/resources/python/api_client.mustache b/modules/swagger-codegen/src/main/resources/python/api_client.mustache index e493074ba6d..87bed511c95 100644 --- a/modules/swagger-codegen/src/main/resources/python/api_client.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api_client.mustache @@ -17,6 +17,7 @@ import json import datetime import mimetypes import random +import tempfile # python 2 and python 3 compatibility library from six import iteritems @@ -96,9 +97,13 @@ class ApiClient(object): # request url url = self.host + resource_path - # perform request and return response - response_data = self.request(method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body) + if response == "file": + # perform request and return response + response_data = self.request(method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body, raw=True) + else: + response_data = self.request(method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body) # deserialize response data if response: @@ -173,6 +178,10 @@ class ApiClient(object): sub_class = match.group(2) return {k: self.deserialize(v, sub_class) for k, v in iteritems(obj)} + # handle file downloading - save response body into a tmp file and return the instance + if "file" == obj_class: + return self.download_file(obj) + if obj_class in ['int', 'float', 'dict', 'list', 'str', 'bool', 'datetime', "object"]: obj_class = eval(obj_class) else: # not a native type, must be model class @@ -228,12 +237,12 @@ class ApiClient(object): except ImportError: return string - def request(self, method, url, query_params=None, headers=None, post_params=None, body=None): + def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, raw=False): """ Perform http request using RESTClient. """ if method == "GET": - return RESTClient.GET(url, query_params=query_params, headers=headers) + return RESTClient.GET(url, query_params=query_params, headers=headers, raw=raw) elif method == "HEAD": return RESTClient.HEAD(url, query_params=query_params, headers=headers) elif method == "POST": @@ -308,3 +317,27 @@ class ApiClient(object): querys[auth_setting['key']] = auth_setting['value'] else: raise ValueError('Authentication token must be in `query` or `header`') + + def download_file(self, response): + """ + Save response body into a file in (the defined) temporary folder, using the filename + from the `Content-Disposition` header if provided, otherwise a random filename. + + :param response: RESTResponse + :return: file path + """ + fd, path = tempfile.mkstemp(dir=configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + content_disposition = response.getheader("Content-Disposition") + if content_disposition: + filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition).group(1) + path = os.path.join(os.path.dirname(path), filename) + + with open(path, "w") as f: + f.write(response.data) + + return path + + diff --git a/modules/swagger-codegen/src/main/resources/python/configuration.mustache b/modules/swagger-codegen/src/main/resources/python/configuration.mustache index d3a7093a02a..2dd1045307f 100644 --- a/modules/swagger-codegen/src/main/resources/python/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/python/configuration.mustache @@ -48,4 +48,5 @@ api_key_prefix = {} username = '' password = '' - +# Temp foloder for file download +temp_folder_path = None diff --git a/modules/swagger-codegen/src/main/resources/python/rest.mustache b/modules/swagger-codegen/src/main/resources/python/rest.mustache index 508f3d6693a..6c8f60316b3 100644 --- a/modules/swagger-codegen/src/main/resources/python/rest.mustache +++ b/modules/swagger-codegen/src/main/resources/python/rest.mustache @@ -75,7 +75,7 @@ class RESTClientObject(object): return self.pool_manager def request(self, method, url, query_params=None, headers=None, - body=None, post_params=None): + body=None, post_params=None, raw=False): """ :param method: http request method :param url: http request url @@ -128,9 +128,12 @@ class RESTClientObject(object): if r.status not in range(200, 206): raise ApiException(r) - return self.process_response(r) + return self.process_response(r, raw) - def process_response(self, response): + def process_response(self, response, raw): + if raw: + return response + # In the python 3, the response.data is bytes. # we need to decode it to string. if sys.version_info > (3,): @@ -144,8 +147,8 @@ class RESTClientObject(object): return resp - def GET(self, url, headers=None, query_params=None): - return self.request("GET", url, headers=headers, query_params=query_params) + def GET(self, url, headers=None, query_params=None, raw=False): + return self.request("GET", url, headers=headers, query_params=query_params, raw=raw) def HEAD(self, url, headers=None, query_params=None): return self.request("HEAD", url, headers=headers, query_params=query_params) diff --git a/samples/client/petstore/python/swagger_client/api_client.py b/samples/client/petstore/python/swagger_client/api_client.py index e493074ba6d..87bed511c95 100644 --- a/samples/client/petstore/python/swagger_client/api_client.py +++ b/samples/client/petstore/python/swagger_client/api_client.py @@ -17,6 +17,7 @@ import json import datetime import mimetypes import random +import tempfile # python 2 and python 3 compatibility library from six import iteritems @@ -96,9 +97,13 @@ class ApiClient(object): # request url url = self.host + resource_path - # perform request and return response - response_data = self.request(method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body) + if response == "file": + # perform request and return response + response_data = self.request(method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body, raw=True) + else: + response_data = self.request(method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body) # deserialize response data if response: @@ -173,6 +178,10 @@ class ApiClient(object): sub_class = match.group(2) return {k: self.deserialize(v, sub_class) for k, v in iteritems(obj)} + # handle file downloading - save response body into a tmp file and return the instance + if "file" == obj_class: + return self.download_file(obj) + if obj_class in ['int', 'float', 'dict', 'list', 'str', 'bool', 'datetime', "object"]: obj_class = eval(obj_class) else: # not a native type, must be model class @@ -228,12 +237,12 @@ class ApiClient(object): except ImportError: return string - def request(self, method, url, query_params=None, headers=None, post_params=None, body=None): + def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, raw=False): """ Perform http request using RESTClient. """ if method == "GET": - return RESTClient.GET(url, query_params=query_params, headers=headers) + return RESTClient.GET(url, query_params=query_params, headers=headers, raw=raw) elif method == "HEAD": return RESTClient.HEAD(url, query_params=query_params, headers=headers) elif method == "POST": @@ -308,3 +317,27 @@ class ApiClient(object): querys[auth_setting['key']] = auth_setting['value'] else: raise ValueError('Authentication token must be in `query` or `header`') + + def download_file(self, response): + """ + Save response body into a file in (the defined) temporary folder, using the filename + from the `Content-Disposition` header if provided, otherwise a random filename. + + :param response: RESTResponse + :return: file path + """ + fd, path = tempfile.mkstemp(dir=configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + content_disposition = response.getheader("Content-Disposition") + if content_disposition: + filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition).group(1) + path = os.path.join(os.path.dirname(path), filename) + + with open(path, "w") as f: + f.write(response.data) + + return path + + diff --git a/samples/client/petstore/python/swagger_client/configuration.py b/samples/client/petstore/python/swagger_client/configuration.py index b5bd0a64e0a..7b6f4023914 100644 --- a/samples/client/petstore/python/swagger_client/configuration.py +++ b/samples/client/petstore/python/swagger_client/configuration.py @@ -41,4 +41,5 @@ api_key_prefix = {} username = '' password = '' - +# Temp foloder for file download +temp_folder_path = None diff --git a/samples/client/petstore/python/swagger_client/rest.py b/samples/client/petstore/python/swagger_client/rest.py index 508f3d6693a..6c8f60316b3 100644 --- a/samples/client/petstore/python/swagger_client/rest.py +++ b/samples/client/petstore/python/swagger_client/rest.py @@ -75,7 +75,7 @@ class RESTClientObject(object): return self.pool_manager def request(self, method, url, query_params=None, headers=None, - body=None, post_params=None): + body=None, post_params=None, raw=False): """ :param method: http request method :param url: http request url @@ -128,9 +128,12 @@ class RESTClientObject(object): if r.status not in range(200, 206): raise ApiException(r) - return self.process_response(r) + return self.process_response(r, raw) - def process_response(self, response): + def process_response(self, response, raw): + if raw: + return response + # In the python 3, the response.data is bytes. # we need to decode it to string. if sys.version_info > (3,): @@ -144,8 +147,8 @@ class RESTClientObject(object): return resp - def GET(self, url, headers=None, query_params=None): - return self.request("GET", url, headers=headers, query_params=query_params) + def GET(self, url, headers=None, query_params=None, raw=False): + return self.request("GET", url, headers=headers, query_params=query_params, raw=raw) def HEAD(self, url, headers=None, query_params=None): return self.request("HEAD", url, headers=headers, query_params=query_params) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_store_api.py b/samples/client/petstore/python/tests/test_store_api.py similarity index 79% rename from samples/client/petstore/python/SwaggerPetstore-python/tests/test_store_api.py rename to samples/client/petstore/python/tests/test_store_api.py index 933a44f237d..42b92d0879c 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_store_api.py +++ b/samples/client/petstore/python/tests/test_store_api.py @@ -11,14 +11,14 @@ import os import time import unittest -import SwaggerPetstore -from SwaggerPetstore.rest import ApiException +import swagger_client +from swagger_client.rest import ApiException class StoreApiTests(unittest.TestCase): def setUp(self): - self.store_api = SwaggerPetstore.StoreApi() + self.store_api = swagger_client.StoreApi() def tearDown(self): # sleep 1 sec between two every 2 tests From 2912ee8ae19a64ddf0f7b3c1e0317c057c7aeed3 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Mon, 29 Jun 2015 21:50:19 +0800 Subject: [PATCH 02/12] Update deserialize response of Python client. --- .../src/main/resources/python/api.mustache | 2 +- .../main/resources/python/api_client.mustache | 219 +++++++++++------- .../src/main/resources/python/rest.mustache | 28 +-- samples/client/petstore/python/setup.cfg | 2 +- .../python/swagger_client/api_client.py | 219 +++++++++++------- .../python/swagger_client/apis/pet_api.py | 16 +- .../python/swagger_client/apis/store_api.py | 8 +- .../python/swagger_client/apis/user_api.py | 16 +- .../petstore/python/swagger_client/rest.py | 28 +-- .../petstore/python/tests/test_api_client.py | 10 +- 10 files changed, 309 insertions(+), 239 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/api.mustache b/modules/swagger-codegen/src/main/resources/python/api.mustache index 3fb62cb75ea..8c9e719e005 100644 --- a/modules/swagger-codegen/src/main/resources/python/api.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api.mustache @@ -107,7 +107,7 @@ class {{classname}}(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, auth_settings=auth_settings) + response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, auth_settings=auth_settings) {{#returnType}} return response {{/returnType}}{{/operation}} diff --git a/modules/swagger-codegen/src/main/resources/python/api_client.mustache b/modules/swagger-codegen/src/main/resources/python/api_client.mustache index 87bed511c95..e0c1a8ca556 100644 --- a/modules/swagger-codegen/src/main/resources/python/api_client.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api_client.mustache @@ -60,7 +60,7 @@ class ApiClient(object): self.default_headers[header_name] = header_value def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, - body=None, post_params=None, files=None, response=None, auth_settings=None): + body=None, post_params=None, files=None, response_type=None, auth_settings=None): # headers parameters header_params = header_params or {} @@ -97,17 +97,15 @@ class ApiClient(object): # request url url = self.host + resource_path - if response == "file": - # perform request and return response - response_data = self.request(method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body, raw=True) - else: - response_data = self.request(method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body) + # perform request and return response + response_data = self.request(method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body) + self.last_response = response_data + # deserialize response data - if response: - return self.deserialize(response_data, response) + if response_type: + return self.deserialize(response_data, response_type) else: return None @@ -156,93 +154,66 @@ class ApiClient(object): return {key: self.sanitize_for_serialization(val) for key, val in iteritems(obj_dict)} - def deserialize(self, obj, obj_class): + def deserialize(self, response, response_type): """ - Derialize a JSON string into an object. + Derialize response into an object. - :param obj: string or object to be deserialized - :param obj_class: class literal for deserialzied object, or string of class name + :param response: RESTResponse object to be deserialized + :param response_type: class literal for deserialzied object, or string of class name - :return object: deserialized object + :return: deserialized object """ - # Have to accept obj_class as string or actual type. Type could be a - # native Python type, or one of the model classes. - if type(obj_class) == str: - if 'list[' in obj_class: - match = re.match('list\[(.*)\]', obj_class) - sub_class = match.group(1) - return [self.deserialize(sub_obj, sub_class) for sub_obj in obj] + # handle file downloading - save response body into a tmp file and return the instance + if "file" == response_type: + return self.__deserialize_file(response) - if 'dict(' in obj_class: - match = re.match('dict\((.*), (.*)\)', obj_class) - sub_class = match.group(2) - return {k: self.deserialize(v, sub_class) for k, v in iteritems(obj)} - - # handle file downloading - save response body into a tmp file and return the instance - if "file" == obj_class: - return self.download_file(obj) - - if obj_class in ['int', 'float', 'dict', 'list', 'str', 'bool', 'datetime', "object"]: - obj_class = eval(obj_class) - else: # not a native type, must be model class - obj_class = eval('models.' + obj_class) - - if obj_class in [int, float, dict, list, str, bool]: - return obj_class(obj) - elif obj_class == object: - return object() - elif obj_class == datetime: - return self.__parse_string_to_datetime(obj) - - instance = obj_class() - - for attr, attr_type in iteritems(instance.swagger_types): - if obj is not None and instance.attribute_map[attr] in obj and type(obj) in [list, dict]: - value = obj[instance.attribute_map[attr]] - if attr_type in ['str', 'int', 'float', 'bool']: - attr_type = eval(attr_type) - try: - value = attr_type(value) - except UnicodeEncodeError: - value = unicode(value) - except TypeError: - value = value - setattr(instance, attr, value) - elif attr_type == 'datetime': - setattr(instance, attr, self.__parse_string_to_datetime(value)) - elif 'list[' in attr_type: - match = re.match('list\[(.*)\]', attr_type) - sub_class = match.group(1) - sub_values = [] - if not value: - setattr(instance, attr, None) - else: - for sub_value in value: - sub_values.append(self.deserialize(sub_value, sub_class)) - setattr(instance, attr, sub_values) - else: - setattr(instance, attr, self.deserialize(value, attr_type)) - - return instance - - def __parse_string_to_datetime(self, string): - """ - Parse datetime in string to datetime. - - The string should be in iso8601 datetime format. - """ + # fetch data from response object try: - from dateutil.parser import parse - return parse(string) - except ImportError: - return string + data = json.loads(response.data) + except ValueError: + data = response.data - def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, raw=False): + return self.__deserialize(data, response_type) + + def __deserialize(self, data, klass): + """ + :param data: dict, list or str + :param klass: class literal, or string of class name + + :return: object + """ + if type(klass) == str: + if 'list[' in klass: + sub_kls = re.match('list\[(.*)\]', klass).group(1) + return [self.__deserialize(sub_data, sub_kls) for sub_data in data] + + if 'dict(' in klass: + sub_kls = re.match('dict\((.*), (.*)\)', klass).group(2) + return {k: self.__deserialize(v, sub_kls) for k, v in iteritems(data)} + + # convert str to class + # for native types + if klass in ['int', 'float', 'str', 'bool', 'datetime', "object"]: + klass = eval(klass) + # for model types + else: + klass = eval('models.' + klass) + + if klass in [int, float, str, bool]: + return self.__deserialize_primitive(data, klass) + elif klass == object: + return self.__deserialize_object() + elif klass == datetime: + return self.__deserialize_datatime(data) + else: + return self.__deserialize_model(data, klass) + + def request(self, method, url, query_params=None, headers=None, post_params=None, body=None): """ Perform http request using RESTClient. """ if method == "GET": - return RESTClient.GET(url, query_params=query_params, headers=headers, raw=raw) + return RESTClient.GET(url, query_params=query_params, headers=headers) elif method == "HEAD": return RESTClient.HEAD(url, query_params=query_params, headers=headers) elif method == "POST": @@ -318,7 +289,7 @@ class ApiClient(object): else: raise ValueError('Authentication token must be in `query` or `header`') - def download_file(self, response): + def __deserialize_file(self, response): """ Save response body into a file in (the defined) temporary folder, using the filename from the `Content-Disposition` header if provided, otherwise a random filename. @@ -340,4 +311,78 @@ class ApiClient(object): return path + def __deserialize_primitive(self, data, klass): + """ + Deserialize string to primitive type + + :param data: str + :param klass: class literal + + :return: int, float, str, bool + """ + try: + value = klass(data) + except UnicodeEncodeError: + value = unicode(data) + except TypeError: + value = data + return value + + def __deserialize_object(self): + """ + Deserialize empty object + """ + return object() + + def __deserialize_datatime(self, string): + """ + Deserialize string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str + :return: datetime + """ + try: + from dateutil.parser import parse + return parse(string) + except ImportError: + return string + + def __deserialize_model(self, data, klass): + """ + Deserialize list or dict to model + + :param data: dict, list + :param klass: class literal + """ + instance = klass() + + for attr, attr_type in iteritems(instance.swagger_types): + if data is not None \ + and instance.attribute_map[attr] in data\ + and isinstance(data, (list, dict)): + value = data[instance.attribute_map[attr]] + if attr_type in ['str', 'int', 'float', 'bool']: + attr_type = eval(attr_type) + setattr(instance, attr, self.__deserialize_primitive(value, attr_type)) + elif attr_type == 'datetime': + setattr(instance, attr, self.__deserialize_datatime(value)) + elif 'list[' in attr_type: + if not value: + setattr(instance, attr, None) + else: + sub_kls = re.match('list\[(.*)\]', attr_type).group(1) + setattr(instance, attr, [self.__deserialize(v, sub_kls) for v in value]) + else: + setattr(instance, attr, self.__deserialize(value, attr_type)) + + return instance + + + + + + + diff --git a/modules/swagger-codegen/src/main/resources/python/rest.mustache b/modules/swagger-codegen/src/main/resources/python/rest.mustache index 6c8f60316b3..1d21402606e 100644 --- a/modules/swagger-codegen/src/main/resources/python/rest.mustache +++ b/modules/swagger-codegen/src/main/resources/python/rest.mustache @@ -75,7 +75,7 @@ class RESTClientObject(object): return self.pool_manager def request(self, method, url, query_params=None, headers=None, - body=None, post_params=None, raw=False): + body=None, post_params=None): """ :param method: http request method :param url: http request url @@ -125,30 +125,18 @@ class RESTClientObject(object): headers=headers) r = RESTResponse(r) - if r.status not in range(200, 206): - raise ApiException(r) - - return self.process_response(r, raw) - - def process_response(self, response, raw): - if raw: - return response - # In the python 3, the response.data is bytes. # we need to decode it to string. if sys.version_info > (3,): - data = response.data.decode('utf8') - else: - data = response.data - try: - resp = json.loads(data) - except ValueError: - resp = data + r.data = r.data.decode('utf8') - return resp + if r.status not in range(200, 206): + raise ApiException(r) - def GET(self, url, headers=None, query_params=None, raw=False): - return self.request("GET", url, headers=headers, query_params=query_params, raw=raw) + return r + + def GET(self, url, headers=None, query_params=None): + return self.request("GET", url, headers=headers, query_params=query_params) def HEAD(self, url, headers=None, query_params=None): return self.request("HEAD", url, headers=headers, query_params=query_params) diff --git a/samples/client/petstore/python/setup.cfg b/samples/client/petstore/python/setup.cfg index e62af080034..8d2afd06087 100644 --- a/samples/client/petstore/python/setup.cfg +++ b/samples/client/petstore/python/setup.cfg @@ -4,7 +4,7 @@ verbosity=2 randomize=true exe=true with-coverage=true -cover-package=SwaggerPetstore +cover-package=swagger_petstore cover-erase=true [flake8] diff --git a/samples/client/petstore/python/swagger_client/api_client.py b/samples/client/petstore/python/swagger_client/api_client.py index 87bed511c95..e0c1a8ca556 100644 --- a/samples/client/petstore/python/swagger_client/api_client.py +++ b/samples/client/petstore/python/swagger_client/api_client.py @@ -60,7 +60,7 @@ class ApiClient(object): self.default_headers[header_name] = header_value def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, - body=None, post_params=None, files=None, response=None, auth_settings=None): + body=None, post_params=None, files=None, response_type=None, auth_settings=None): # headers parameters header_params = header_params or {} @@ -97,17 +97,15 @@ class ApiClient(object): # request url url = self.host + resource_path - if response == "file": - # perform request and return response - response_data = self.request(method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body, raw=True) - else: - response_data = self.request(method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body) + # perform request and return response + response_data = self.request(method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body) + self.last_response = response_data + # deserialize response data - if response: - return self.deserialize(response_data, response) + if response_type: + return self.deserialize(response_data, response_type) else: return None @@ -156,93 +154,66 @@ class ApiClient(object): return {key: self.sanitize_for_serialization(val) for key, val in iteritems(obj_dict)} - def deserialize(self, obj, obj_class): + def deserialize(self, response, response_type): """ - Derialize a JSON string into an object. + Derialize response into an object. - :param obj: string or object to be deserialized - :param obj_class: class literal for deserialzied object, or string of class name + :param response: RESTResponse object to be deserialized + :param response_type: class literal for deserialzied object, or string of class name - :return object: deserialized object + :return: deserialized object """ - # Have to accept obj_class as string or actual type. Type could be a - # native Python type, or one of the model classes. - if type(obj_class) == str: - if 'list[' in obj_class: - match = re.match('list\[(.*)\]', obj_class) - sub_class = match.group(1) - return [self.deserialize(sub_obj, sub_class) for sub_obj in obj] + # handle file downloading - save response body into a tmp file and return the instance + if "file" == response_type: + return self.__deserialize_file(response) - if 'dict(' in obj_class: - match = re.match('dict\((.*), (.*)\)', obj_class) - sub_class = match.group(2) - return {k: self.deserialize(v, sub_class) for k, v in iteritems(obj)} - - # handle file downloading - save response body into a tmp file and return the instance - if "file" == obj_class: - return self.download_file(obj) - - if obj_class in ['int', 'float', 'dict', 'list', 'str', 'bool', 'datetime', "object"]: - obj_class = eval(obj_class) - else: # not a native type, must be model class - obj_class = eval('models.' + obj_class) - - if obj_class in [int, float, dict, list, str, bool]: - return obj_class(obj) - elif obj_class == object: - return object() - elif obj_class == datetime: - return self.__parse_string_to_datetime(obj) - - instance = obj_class() - - for attr, attr_type in iteritems(instance.swagger_types): - if obj is not None and instance.attribute_map[attr] in obj and type(obj) in [list, dict]: - value = obj[instance.attribute_map[attr]] - if attr_type in ['str', 'int', 'float', 'bool']: - attr_type = eval(attr_type) - try: - value = attr_type(value) - except UnicodeEncodeError: - value = unicode(value) - except TypeError: - value = value - setattr(instance, attr, value) - elif attr_type == 'datetime': - setattr(instance, attr, self.__parse_string_to_datetime(value)) - elif 'list[' in attr_type: - match = re.match('list\[(.*)\]', attr_type) - sub_class = match.group(1) - sub_values = [] - if not value: - setattr(instance, attr, None) - else: - for sub_value in value: - sub_values.append(self.deserialize(sub_value, sub_class)) - setattr(instance, attr, sub_values) - else: - setattr(instance, attr, self.deserialize(value, attr_type)) - - return instance - - def __parse_string_to_datetime(self, string): - """ - Parse datetime in string to datetime. - - The string should be in iso8601 datetime format. - """ + # fetch data from response object try: - from dateutil.parser import parse - return parse(string) - except ImportError: - return string + data = json.loads(response.data) + except ValueError: + data = response.data - def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, raw=False): + return self.__deserialize(data, response_type) + + def __deserialize(self, data, klass): + """ + :param data: dict, list or str + :param klass: class literal, or string of class name + + :return: object + """ + if type(klass) == str: + if 'list[' in klass: + sub_kls = re.match('list\[(.*)\]', klass).group(1) + return [self.__deserialize(sub_data, sub_kls) for sub_data in data] + + if 'dict(' in klass: + sub_kls = re.match('dict\((.*), (.*)\)', klass).group(2) + return {k: self.__deserialize(v, sub_kls) for k, v in iteritems(data)} + + # convert str to class + # for native types + if klass in ['int', 'float', 'str', 'bool', 'datetime', "object"]: + klass = eval(klass) + # for model types + else: + klass = eval('models.' + klass) + + if klass in [int, float, str, bool]: + return self.__deserialize_primitive(data, klass) + elif klass == object: + return self.__deserialize_object() + elif klass == datetime: + return self.__deserialize_datatime(data) + else: + return self.__deserialize_model(data, klass) + + def request(self, method, url, query_params=None, headers=None, post_params=None, body=None): """ Perform http request using RESTClient. """ if method == "GET": - return RESTClient.GET(url, query_params=query_params, headers=headers, raw=raw) + return RESTClient.GET(url, query_params=query_params, headers=headers) elif method == "HEAD": return RESTClient.HEAD(url, query_params=query_params, headers=headers) elif method == "POST": @@ -318,7 +289,7 @@ class ApiClient(object): else: raise ValueError('Authentication token must be in `query` or `header`') - def download_file(self, response): + def __deserialize_file(self, response): """ Save response body into a file in (the defined) temporary folder, using the filename from the `Content-Disposition` header if provided, otherwise a random filename. @@ -340,4 +311,78 @@ class ApiClient(object): return path + def __deserialize_primitive(self, data, klass): + """ + Deserialize string to primitive type + + :param data: str + :param klass: class literal + + :return: int, float, str, bool + """ + try: + value = klass(data) + except UnicodeEncodeError: + value = unicode(data) + except TypeError: + value = data + return value + + def __deserialize_object(self): + """ + Deserialize empty object + """ + return object() + + def __deserialize_datatime(self, string): + """ + Deserialize string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str + :return: datetime + """ + try: + from dateutil.parser import parse + return parse(string) + except ImportError: + return string + + def __deserialize_model(self, data, klass): + """ + Deserialize list or dict to model + + :param data: dict, list + :param klass: class literal + """ + instance = klass() + + for attr, attr_type in iteritems(instance.swagger_types): + if data is not None \ + and instance.attribute_map[attr] in data\ + and isinstance(data, (list, dict)): + value = data[instance.attribute_map[attr]] + if attr_type in ['str', 'int', 'float', 'bool']: + attr_type = eval(attr_type) + setattr(instance, attr, self.__deserialize_primitive(value, attr_type)) + elif attr_type == 'datetime': + setattr(instance, attr, self.__deserialize_datatime(value)) + elif 'list[' in attr_type: + if not value: + setattr(instance, attr, None) + else: + sub_kls = re.match('list\[(.*)\]', attr_type).group(1) + setattr(instance, attr, [self.__deserialize(v, sub_kls) for v in value]) + else: + setattr(instance, attr, self.__deserialize(value, attr_type)) + + return instance + + + + + + + diff --git a/samples/client/petstore/python/swagger_client/apis/pet_api.py b/samples/client/petstore/python/swagger_client/apis/pet_api.py index 7f022930869..9e040c50051 100644 --- a/samples/client/petstore/python/swagger_client/apis/pet_api.py +++ b/samples/client/petstore/python/swagger_client/apis/pet_api.py @@ -90,7 +90,7 @@ class PetApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def add_pet(self, **kwargs): """ @@ -141,7 +141,7 @@ class PetApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def find_pets_by_status(self, **kwargs): """ @@ -192,7 +192,7 @@ class PetApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='list[Pet]', auth_settings=auth_settings) + response_type='list[Pet]', auth_settings=auth_settings) return response @@ -245,7 +245,7 @@ class PetApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='list[Pet]', auth_settings=auth_settings) + response_type='list[Pet]', auth_settings=auth_settings) return response @@ -302,7 +302,7 @@ class PetApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Pet', auth_settings=auth_settings) + response_type='Pet', auth_settings=auth_settings) return response @@ -367,7 +367,7 @@ class PetApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def delete_pet(self, pet_id, **kwargs): """ @@ -426,7 +426,7 @@ class PetApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def upload_file(self, pet_id, **kwargs): """ @@ -489,7 +489,7 @@ class PetApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/swagger_client/apis/store_api.py b/samples/client/petstore/python/swagger_client/apis/store_api.py index f017df791d9..06775fdc860 100644 --- a/samples/client/petstore/python/swagger_client/apis/store_api.py +++ b/samples/client/petstore/python/swagger_client/apis/store_api.py @@ -86,7 +86,7 @@ class StoreApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='dict(str, int)', auth_settings=auth_settings) + response_type='dict(str, int)', auth_settings=auth_settings) return response @@ -139,7 +139,7 @@ class StoreApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Order', auth_settings=auth_settings) + response_type='Order', auth_settings=auth_settings) return response @@ -196,7 +196,7 @@ class StoreApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Order', auth_settings=auth_settings) + response_type='Order', auth_settings=auth_settings) return response @@ -253,7 +253,7 @@ class StoreApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/swagger_client/apis/user_api.py b/samples/client/petstore/python/swagger_client/apis/user_api.py index 177c5e3a565..8299a95c2a0 100644 --- a/samples/client/petstore/python/swagger_client/apis/user_api.py +++ b/samples/client/petstore/python/swagger_client/apis/user_api.py @@ -90,7 +90,7 @@ class UserApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def create_users_with_array_input(self, **kwargs): """ @@ -141,7 +141,7 @@ class UserApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def create_users_with_list_input(self, **kwargs): """ @@ -192,7 +192,7 @@ class UserApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def login_user(self, **kwargs): """ @@ -247,7 +247,7 @@ class UserApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='str', auth_settings=auth_settings) + response_type='str', auth_settings=auth_settings) return response @@ -296,7 +296,7 @@ class UserApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def get_user_by_name(self, username, **kwargs): """ @@ -351,7 +351,7 @@ class UserApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='User', auth_settings=auth_settings) + response_type='User', auth_settings=auth_settings) return response @@ -412,7 +412,7 @@ class UserApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) def delete_user(self, username, **kwargs): """ @@ -467,7 +467,7 @@ class UserApi(object): response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None, auth_settings=auth_settings) + response_type=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/swagger_client/rest.py b/samples/client/petstore/python/swagger_client/rest.py index 6c8f60316b3..1d21402606e 100644 --- a/samples/client/petstore/python/swagger_client/rest.py +++ b/samples/client/petstore/python/swagger_client/rest.py @@ -75,7 +75,7 @@ class RESTClientObject(object): return self.pool_manager def request(self, method, url, query_params=None, headers=None, - body=None, post_params=None, raw=False): + body=None, post_params=None): """ :param method: http request method :param url: http request url @@ -125,30 +125,18 @@ class RESTClientObject(object): headers=headers) r = RESTResponse(r) - if r.status not in range(200, 206): - raise ApiException(r) - - return self.process_response(r, raw) - - def process_response(self, response, raw): - if raw: - return response - # In the python 3, the response.data is bytes. # we need to decode it to string. if sys.version_info > (3,): - data = response.data.decode('utf8') - else: - data = response.data - try: - resp = json.loads(data) - except ValueError: - resp = data + r.data = r.data.decode('utf8') - return resp + if r.status not in range(200, 206): + raise ApiException(r) - def GET(self, url, headers=None, query_params=None, raw=False): - return self.request("GET", url, headers=headers, query_params=query_params, raw=raw) + return r + + def GET(self, url, headers=None, query_params=None): + return self.request("GET", url, headers=headers, query_params=query_params) def HEAD(self, url, headers=None, query_params=None): return self.request("HEAD", url, headers=headers, query_params=query_params) diff --git a/samples/client/petstore/python/tests/test_api_client.py b/samples/client/petstore/python/tests/test_api_client.py index d932006c052..1a2a67612fd 100644 --- a/samples/client/petstore/python/tests/test_api_client.py +++ b/samples/client/petstore/python/tests/test_api_client.py @@ -112,7 +112,7 @@ class ApiClientTests(unittest.TestCase): } } - data = self.api_client.deserialize(json, 'dict(str, Pet)') + data = self.api_client._ApiClient__deserialize(json, 'dict(str, Pet)') self.assertTrue(isinstance(data, dict)) self.assertTrue(isinstance(data['pet'], swagger_client.Pet)) @@ -121,10 +121,14 @@ class ApiClientTests(unittest.TestCase): 'integer': 1 } - data = self.api_client.deserialize(json, 'dict(str, int)') + data = self.api_client._ApiClient__deserialize(json, 'dict(str, int)') self.assertTrue(isinstance(data, dict)) self.assertTrue(isinstance(data['integer'], int)) def test_deserialize_to_object(self): - data = self.api_client.deserialize("", "object") + data = self.api_client._ApiClient__deserialize("", "object") self.assertTrue(type(data) == object) + + + + From 80d1deb2dde01c542e93af5310cac92e15ecda0a Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 30 Jun 2015 17:20:53 +0800 Subject: [PATCH 03/12] Update unit tests of Python client. Add more test cases for deserialization. --- .../src/main/resources/python/setup.mustache | 2 +- samples/client/petstore/python/setup.cfg | 2 +- samples/client/petstore/python/setup.py | 2 +- .../petstore/python/tests/test_api_client.py | 44 ------ .../python/tests/test_deserialization.py | 145 ++++++++++++++++++ 5 files changed, 148 insertions(+), 47 deletions(-) create mode 100644 samples/client/petstore/python/tests/test_deserialization.py diff --git a/modules/swagger-codegen/src/main/resources/python/setup.mustache b/modules/swagger-codegen/src/main/resources/python/setup.mustache index af4fa69baf3..9adc4e00f62 100644 --- a/modules/swagger-codegen/src/main/resources/python/setup.mustache +++ b/modules/swagger-codegen/src/main/resources/python/setup.mustache @@ -15,7 +15,7 @@ VERSION = "{{packageVersion}}" # Try reading the setuptools documentation: # http://pypi.python.org/pypi/setuptools -REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi"] +REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi", "python-dateutil"] setup( name=NAME, diff --git a/samples/client/petstore/python/setup.cfg b/samples/client/petstore/python/setup.cfg index 8d2afd06087..c9eef8726d6 100644 --- a/samples/client/petstore/python/setup.cfg +++ b/samples/client/petstore/python/setup.cfg @@ -4,7 +4,7 @@ verbosity=2 randomize=true exe=true with-coverage=true -cover-package=swagger_petstore +cover-package=swagger_client cover-erase=true [flake8] diff --git a/samples/client/petstore/python/setup.py b/samples/client/petstore/python/setup.py index 4232c3992b9..ffc6f6a3ad2 100644 --- a/samples/client/petstore/python/setup.py +++ b/samples/client/petstore/python/setup.py @@ -15,7 +15,7 @@ VERSION = "1.0.0" # Try reading the setuptools documentation: # http://pypi.python.org/pypi/setuptools -REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi"] +REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi", "python-dateutil"] setup( name=NAME, diff --git a/samples/client/petstore/python/tests/test_api_client.py b/samples/client/petstore/python/tests/test_api_client.py index 1a2a67612fd..903fde45815 100644 --- a/samples/client/petstore/python/tests/test_api_client.py +++ b/samples/client/petstore/python/tests/test_api_client.py @@ -88,47 +88,3 @@ class ApiClientTests(unittest.TestCase): content_types = [] content_type = self.api_client.select_header_content_type(content_types) self.assertEqual(content_type, 'application/json') - - def test_deserialize_to_dict(self): - # dict(str, Pet) - json = { - 'pet': { - "id": 0, - "category": { - "id": 0, - "name": "string" - }, - "name": "doggie", - "photoUrls": [ - "string" - ], - "tags": [ - { - "id": 0, - "name": "string" - } - ], - "status": "available" - } - } - - data = self.api_client._ApiClient__deserialize(json, 'dict(str, Pet)') - self.assertTrue(isinstance(data, dict)) - self.assertTrue(isinstance(data['pet'], swagger_client.Pet)) - - # dict(str, int) - json = { - 'integer': 1 - } - - data = self.api_client._ApiClient__deserialize(json, 'dict(str, int)') - self.assertTrue(isinstance(data, dict)) - self.assertTrue(isinstance(data['integer'], int)) - - def test_deserialize_to_object(self): - data = self.api_client._ApiClient__deserialize("", "object") - self.assertTrue(type(data) == object) - - - - diff --git a/samples/client/petstore/python/tests/test_deserialization.py b/samples/client/petstore/python/tests/test_deserialization.py new file mode 100644 index 00000000000..8d9be6d57a4 --- /dev/null +++ b/samples/client/petstore/python/tests/test_deserialization.py @@ -0,0 +1,145 @@ +# coding: utf-8 + +""" +Run the tests. +$ pip install nose (optional) +$ cd SwaggerPetstore-python +$ nosetests -v +""" +import os +import time +import unittest +import datetime + +import swagger_client + + +class DeserializationTests(unittest.TestCase): + + def setUp(self): + self.api_client = swagger_client.ApiClient() + self.deserialize = self.api_client._ApiClient__deserialize + + def test_deserialize_dict_str_pet(self): + """ deserialize dict(str, Pet) """ + data = { + 'pet': { + "id": 0, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + } + } + + deserialized = self.deserialize(data, 'dict(str, Pet)') + self.assertTrue(isinstance(deserialized, dict)) + self.assertTrue(isinstance(deserialized['pet'], swagger_client.Pet)) + + def test_deserialize_dict_str_int(self): + """ deserialize dict(str, int) """ + data = { + 'integer': 1 + } + + deserialized = self.deserialize(data, 'dict(str, int)') + self.assertTrue(isinstance(deserialized, dict)) + self.assertTrue(isinstance(deserialized['integer'], int)) + + def test_deserialize_str(self): + """ deserialize str """ + data = "test str" + deserialized = self.deserialize(data, "str") + self.assertTrue(isinstance(deserialized, str)) + + def test_deserialize_datetime(self): + """ deserialize dateimte """ + data = "1997-07-16T19:20:30.45+01:00" + deserialized = self.deserialize(data, "datetime") + self.assertTrue(isinstance(deserialized, datetime.datetime)) + + def test_deserialize_pet(self): + """ deserialize pet """ + data = { + "id": 0, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + } + deserialized = self.deserialize(data, "Pet") + self.assertTrue(isinstance(deserialized, swagger_client.Pet)) + self.assertEqual(deserialized.id, 0) + self.assertEqual(deserialized.name, "doggie") + self.assertTrue(isinstance(deserialized.category, swagger_client.Category)) + self.assertEqual(deserialized.category.name, "string") + self.assertTrue(isinstance(deserialized.tags, list)) + self.assertEqual(deserialized.tags[0].name, "string") + + def test_deserialize_list_of_pet(self): + """ deserialize list[Pet] """ + data = [{ + "id": 0, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie0", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + }, + { + "id": 1, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie1", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + }] + deserialized = self.deserialize(data, "list[Pet]") + self.assertTrue(isinstance(deserialized, list)) + self.assertTrue(isinstance(deserialized[0], swagger_client.Pet)) + self.assertEqual(deserialized[0].id, 0) + self.assertEqual(deserialized[1].id, 1) + self.assertEqual(deserialized[0].name, "doggie0") + self.assertEqual(deserialized[1].name, "doggie1") From b99f0068613f4a46974437cfbc537d5e4d712d23 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 30 Jun 2015 18:38:11 +0800 Subject: [PATCH 04/12] Update Python client. Throw ApiException if fail to parse string to datetime. --- .../main/resources/python/api_client.mustache | 23 ++++----- .../src/main/resources/python/rest.mustache | 47 +++++++++---------- .../python/swagger_client/api_client.py | 23 ++++----- .../petstore/python/swagger_client/rest.py | 47 +++++++++---------- .../python/tests/test_api_exception.py | 2 +- 5 files changed, 61 insertions(+), 81 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/api_client.mustache b/modules/swagger-codegen/src/main/resources/python/api_client.mustache index e0c1a8ca556..761a034e189 100644 --- a/modules/swagger-codegen/src/main/resources/python/api_client.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api_client.mustache @@ -9,6 +9,7 @@ templates.""" from __future__ import absolute_import from . import models from .rest import RESTClient +from .rest import ApiException import os import re @@ -102,7 +103,7 @@ class ApiClient(object): post_params=post_params, body=body) self.last_response = response_data - + # deserialize response data if response_type: return self.deserialize(response_data, response_type) @@ -278,7 +279,7 @@ class ApiClient(object): """ if not auth_settings: return - + for auth in auth_settings: auth_setting = configuration.auth_settings().get(auth) if auth_setting: @@ -294,13 +295,13 @@ class ApiClient(object): Save response body into a file in (the defined) temporary folder, using the filename from the `Content-Disposition` header if provided, otherwise a random filename. - :param response: RESTResponse - :return: file path + :param response: RESTResponse + :return: file path """ fd, path = tempfile.mkstemp(dir=configuration.temp_folder_path) os.close(fd) os.remove(path) - + content_disposition = response.getheader("Content-Disposition") if content_disposition: filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition).group(1) @@ -314,7 +315,7 @@ class ApiClient(object): def __deserialize_primitive(self, data, klass): """ Deserialize string to primitive type - + :param data: str :param klass: class literal @@ -348,6 +349,8 @@ class ApiClient(object): return parse(string) except ImportError: return string + except ValueError: + raise ApiException(status=0, reason="Failed to parse `{0}` into a datetime object".format(string)) def __deserialize_model(self, data, klass): """ @@ -378,11 +381,3 @@ class ApiClient(object): setattr(instance, attr, self.__deserialize(value, attr_type)) return instance - - - - - - - - diff --git a/modules/swagger-codegen/src/main/resources/python/rest.mustache b/modules/swagger-codegen/src/main/resources/python/rest.mustache index 1d21402606e..25cf702766e 100644 --- a/modules/swagger-codegen/src/main/resources/python/rest.mustache +++ b/modules/swagger-codegen/src/main/resources/python/rest.mustache @@ -131,7 +131,7 @@ class RESTClientObject(object): r.data = r.data.decode('utf8') if r.status not in range(200, 206): - raise ApiException(r) + raise ApiException(http_resp=r) return r @@ -155,37 +155,32 @@ class RESTClientObject(object): class ApiException(Exception): - """ - Non-2xx HTTP response - """ - def __init__(self, http_resp): - self.status = http_resp.status - self.reason = http_resp.reason - self.body = http_resp.data - self.headers = http_resp.getheaders() - - # In the python 3, the self.body is bytes. - # we need to decode it to string. - if sys.version_info > (3,): - data = self.body.decode('utf8') + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() else: - data = self.body - - try: - self.body = json.loads(data) - except ValueError: - self.body = data + self.status = status + self.reason = reason + self.body = None + self.headers = None def __str__(self): """ - Custom error response messages + Custom error messages for exception """ - return "({0})\n"\ - "Reason: {1}\n"\ - "HTTP response headers: {2}\n"\ - "HTTP response body: {3}\n".\ - format(self.status, self.reason, self.headers, self.body) + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}".format(self.headers) + + if self.body: + error_message += "HTTP response body: {0}".format(self.body) + + return error_message class RESTClient(object): """ diff --git a/samples/client/petstore/python/swagger_client/api_client.py b/samples/client/petstore/python/swagger_client/api_client.py index e0c1a8ca556..761a034e189 100644 --- a/samples/client/petstore/python/swagger_client/api_client.py +++ b/samples/client/petstore/python/swagger_client/api_client.py @@ -9,6 +9,7 @@ templates.""" from __future__ import absolute_import from . import models from .rest import RESTClient +from .rest import ApiException import os import re @@ -102,7 +103,7 @@ class ApiClient(object): post_params=post_params, body=body) self.last_response = response_data - + # deserialize response data if response_type: return self.deserialize(response_data, response_type) @@ -278,7 +279,7 @@ class ApiClient(object): """ if not auth_settings: return - + for auth in auth_settings: auth_setting = configuration.auth_settings().get(auth) if auth_setting: @@ -294,13 +295,13 @@ class ApiClient(object): Save response body into a file in (the defined) temporary folder, using the filename from the `Content-Disposition` header if provided, otherwise a random filename. - :param response: RESTResponse - :return: file path + :param response: RESTResponse + :return: file path """ fd, path = tempfile.mkstemp(dir=configuration.temp_folder_path) os.close(fd) os.remove(path) - + content_disposition = response.getheader("Content-Disposition") if content_disposition: filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition).group(1) @@ -314,7 +315,7 @@ class ApiClient(object): def __deserialize_primitive(self, data, klass): """ Deserialize string to primitive type - + :param data: str :param klass: class literal @@ -348,6 +349,8 @@ class ApiClient(object): return parse(string) except ImportError: return string + except ValueError: + raise ApiException(status=0, reason="Failed to parse `{0}` into a datetime object".format(string)) def __deserialize_model(self, data, klass): """ @@ -378,11 +381,3 @@ class ApiClient(object): setattr(instance, attr, self.__deserialize(value, attr_type)) return instance - - - - - - - - diff --git a/samples/client/petstore/python/swagger_client/rest.py b/samples/client/petstore/python/swagger_client/rest.py index 1d21402606e..25cf702766e 100644 --- a/samples/client/petstore/python/swagger_client/rest.py +++ b/samples/client/petstore/python/swagger_client/rest.py @@ -131,7 +131,7 @@ class RESTClientObject(object): r.data = r.data.decode('utf8') if r.status not in range(200, 206): - raise ApiException(r) + raise ApiException(http_resp=r) return r @@ -155,37 +155,32 @@ class RESTClientObject(object): class ApiException(Exception): - """ - Non-2xx HTTP response - """ - def __init__(self, http_resp): - self.status = http_resp.status - self.reason = http_resp.reason - self.body = http_resp.data - self.headers = http_resp.getheaders() - - # In the python 3, the self.body is bytes. - # we need to decode it to string. - if sys.version_info > (3,): - data = self.body.decode('utf8') + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() else: - data = self.body - - try: - self.body = json.loads(data) - except ValueError: - self.body = data + self.status = status + self.reason = reason + self.body = None + self.headers = None def __str__(self): """ - Custom error response messages + Custom error messages for exception """ - return "({0})\n"\ - "Reason: {1}\n"\ - "HTTP response headers: {2}\n"\ - "HTTP response body: {3}\n".\ - format(self.status, self.reason, self.headers, self.body) + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}".format(self.headers) + + if self.body: + error_message += "HTTP response body: {0}".format(self.body) + + return error_message class RESTClient(object): """ diff --git a/samples/client/petstore/python/tests/test_api_exception.py b/samples/client/petstore/python/tests/test_api_exception.py index f3d00cb10dc..a60594b3edd 100644 --- a/samples/client/petstore/python/tests/test_api_exception.py +++ b/samples/client/petstore/python/tests/test_api_exception.py @@ -52,7 +52,7 @@ class ApiExceptionTests(unittest.TestCase): except ApiException as e: self.assertEqual(e.status, 404) self.assertEqual(e.reason, "Not Found") - self.assertDictEqual(e.body, {'message': 'Pet not found', 'code': 1, 'type': 'error'}) + self.assertRegexpMatches(e.body, "Pet not found") def test_500_error(self): self.pet_api.add_pet(body=self.pet) From 23dfac01940096ca0a53f4d3bbfc6732f4bd2f81 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Thu, 2 Jul 2015 10:58:16 +0800 Subject: [PATCH 05/12] Update deserialization of python client. Return None if deserialize data is None. --- .../main/resources/python/api_client.mustache | 17 ++++------------- .../python/swagger_client/api_client.py | 17 ++++------------- .../python/tests/test_deserialization.py | 5 +++++ 3 files changed, 13 insertions(+), 26 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/api_client.mustache b/modules/swagger-codegen/src/main/resources/python/api_client.mustache index 761a034e189..9188c851327 100644 --- a/modules/swagger-codegen/src/main/resources/python/api_client.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api_client.mustache @@ -183,6 +183,9 @@ class ApiClient(object): :return: object """ + if data is None: + return None + if type(klass) == str: if 'list[' in klass: sub_kls = re.match('list\[(.*)\]', klass).group(1) @@ -366,18 +369,6 @@ class ApiClient(object): and instance.attribute_map[attr] in data\ and isinstance(data, (list, dict)): value = data[instance.attribute_map[attr]] - if attr_type in ['str', 'int', 'float', 'bool']: - attr_type = eval(attr_type) - setattr(instance, attr, self.__deserialize_primitive(value, attr_type)) - elif attr_type == 'datetime': - setattr(instance, attr, self.__deserialize_datatime(value)) - elif 'list[' in attr_type: - if not value: - setattr(instance, attr, None) - else: - sub_kls = re.match('list\[(.*)\]', attr_type).group(1) - setattr(instance, attr, [self.__deserialize(v, sub_kls) for v in value]) - else: - setattr(instance, attr, self.__deserialize(value, attr_type)) + setattr(instance, attr, self.__deserialize(value, attr_type)) return instance diff --git a/samples/client/petstore/python/swagger_client/api_client.py b/samples/client/petstore/python/swagger_client/api_client.py index 761a034e189..9188c851327 100644 --- a/samples/client/petstore/python/swagger_client/api_client.py +++ b/samples/client/petstore/python/swagger_client/api_client.py @@ -183,6 +183,9 @@ class ApiClient(object): :return: object """ + if data is None: + return None + if type(klass) == str: if 'list[' in klass: sub_kls = re.match('list\[(.*)\]', klass).group(1) @@ -366,18 +369,6 @@ class ApiClient(object): and instance.attribute_map[attr] in data\ and isinstance(data, (list, dict)): value = data[instance.attribute_map[attr]] - if attr_type in ['str', 'int', 'float', 'bool']: - attr_type = eval(attr_type) - setattr(instance, attr, self.__deserialize_primitive(value, attr_type)) - elif attr_type == 'datetime': - setattr(instance, attr, self.__deserialize_datatime(value)) - elif 'list[' in attr_type: - if not value: - setattr(instance, attr, None) - else: - sub_kls = re.match('list\[(.*)\]', attr_type).group(1) - setattr(instance, attr, [self.__deserialize(v, sub_kls) for v in value]) - else: - setattr(instance, attr, self.__deserialize(value, attr_type)) + setattr(instance, attr, self.__deserialize(value, attr_type)) return instance diff --git a/samples/client/petstore/python/tests/test_deserialization.py b/samples/client/petstore/python/tests/test_deserialization.py index 8d9be6d57a4..7451f2fbc2c 100644 --- a/samples/client/petstore/python/tests/test_deserialization.py +++ b/samples/client/petstore/python/tests/test_deserialization.py @@ -143,3 +143,8 @@ class DeserializationTests(unittest.TestCase): self.assertEqual(deserialized[1].id, 1) self.assertEqual(deserialized[0].name, "doggie0") self.assertEqual(deserialized[1].name, "doggie1") + + def test_deserialize_none(self): + """ deserialize None """ + deserialized = self.deserialize(None, "datetime") + self.assertIsNone(deserialized) From c88c85a3178be87305f61a297e8e66dd9caf5ca5 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Mon, 6 Jul 2015 18:39:43 +0800 Subject: [PATCH 06/12] Enhancements intergration-test of python client --- .gitignore | 3 +++ samples/client/petstore/python/.travis.yml | 12 +++++++++ samples/client/petstore/python/Makefile | 31 +++++----------------- samples/client/petstore/python/pom.xml | 25 +++++++++-------- samples/client/petstore/python/test-all.sh | 19 +++++++++++++ samples/client/petstore/python/test.sh | 19 +++++++++++++ 6 files changed, 74 insertions(+), 35 deletions(-) create mode 100644 samples/client/petstore/python/.travis.yml create mode 100755 samples/client/petstore/python/test-all.sh create mode 100755 samples/client/petstore/python/test.sh diff --git a/.gitignore b/.gitignore index a0e39ffd165..ab6b7da7269 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,6 @@ samples/client/petstore/php/SwaggerClient-php/vendor/ samples/client/petstore/silex/SwaggerServer/composer.lock samples/client/petstore/silex/SwaggerServer/venodr/ + +samples/client/petstore/python/.projectile +samples/client/petstore/python/.venv/ diff --git a/samples/client/petstore/python/.travis.yml b/samples/client/petstore/python/.travis.yml new file mode 100644 index 00000000000..bde258c4161 --- /dev/null +++ b/samples/client/petstore/python/.travis.yml @@ -0,0 +1,12 @@ +language: python +python: + - "2.6" + - "2.7" + - "3.2" + - "3.3" + - "3.4" +install: + - pip install . --use-mirrors + - pip install -r dev-requirements.txt --use-mirrors +script: + - nosetests diff --git a/samples/client/petstore/python/Makefile b/samples/client/petstore/python/Makefile index 2811b735b54..b1c318aadb7 100644 --- a/samples/client/petstore/python/Makefile +++ b/samples/client/petstore/python/Makefile @@ -1,22 +1,9 @@ + #!/bin/sh + REQUIREMENTS_FILE=dev-requirements.txt REQUIREMENTS_OUT=dev-requirements.txt.log SETUP_OUT=*.egg-info - -virtualenv: -ifndef VIRTUAL_ENV - $(error Must be run inside of a virtualenv\ - http://docs.python-guide.org/en/latest/dev/virtualenvs/) -endif - -setup: virtualenv $(SETUP_OUT) - -$(SETUP_OUT): setup.py setup.cfg - python setup.py develop - touch $(SETUP_OUT) - -$(REQUIREMENTS_OUT): $(REQUIREMENTS_FILE) - pip install -r $(REQUIREMENTS_FILE) | tee -a $(REQUIREMENTS_OUT) - python setup.py develop +VENV=.venv clean: rm -rf $(REQUIREMENTS_OUT) @@ -26,12 +13,8 @@ clean: find . -name "*.py[oc]" -delete find . -name "__pycache__" -delete -requirements: setup $(REQUIREMENTS_OUT) - -test: clean requirements - nosetests - -test-all: clean requirements - tox - +test: clean + sh ./test.sh +test-all: clean + sh ./test-all.sh diff --git a/samples/client/petstore/python/pom.xml b/samples/client/petstore/python/pom.xml index 9efbfb0a35d..b3feaf688a9 100644 --- a/samples/client/petstore/python/pom.xml +++ b/samples/client/petstore/python/pom.xml @@ -26,6 +26,20 @@ exec-maven-plugin 1.2.1 + + pip-install + pre-integration-test + + exec + + + pip + + install + virtualenv + + + nose-test integration-test @@ -44,14 +58,3 @@ - - - - - - - - - - - diff --git a/samples/client/petstore/python/test-all.sh b/samples/client/petstore/python/test-all.sh new file mode 100755 index 00000000000..e62a66c3aae --- /dev/null +++ b/samples/client/petstore/python/test-all.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +REQUIREMENTS_FILE=dev-requirements.txt +REQUIREMENTS_OUT=dev-requirements.txt.log +SETUP_OUT=*.egg-info +VENV=.venv + +### set virtualenv +if [ -z "$VIRTUAL_ENV" ]; then + virtualenv $VENV --no-site-packages + source $VENV/bin/activate +fi + +### install dependencies +pip install -r $REQUIREMENTS_FILE | tee -a $REQUIREMENTS_OUT +python setup.py develop + +### run tests +tox diff --git a/samples/client/petstore/python/test.sh b/samples/client/petstore/python/test.sh new file mode 100755 index 00000000000..309275e6ead --- /dev/null +++ b/samples/client/petstore/python/test.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +REQUIREMENTS_FILE=dev-requirements.txt +REQUIREMENTS_OUT=dev-requirements.txt.log +SETUP_OUT=*.egg-info +VENV=.venv + +### set virtualenv +if [ -z "$VIRTUAL_ENV" ]; then + virtualenv $VENV --no-site-packages + source $VENV/bin/activate +fi + +### install dependencies +pip install -r $REQUIREMENTS_FILE | tee -a $REQUIREMENTS_OUT +python setup.py develop + +### run tests +nosetests From bb570d7efa48400cf5f0722c74566354601895da Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 7 Jul 2015 10:39:58 +0800 Subject: [PATCH 07/12] Update integration-test of python client --- .../client/petstore/python/swagger_client/apis/pet_api.py | 6 +++--- .../client/petstore/python/swagger_client/models/order.py | 4 ++-- samples/client/petstore/python/test-all.sh | 7 +++++++ samples/client/petstore/python/test.sh | 8 ++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/samples/client/petstore/python/swagger_client/apis/pet_api.py b/samples/client/petstore/python/swagger_client/apis/pet_api.py index 9e040c50051..683e807adb9 100644 --- a/samples/client/petstore/python/swagger_client/apis/pet_api.py +++ b/samples/client/petstore/python/swagger_client/apis/pet_api.py @@ -374,8 +374,8 @@ class PetApi(object): Deletes a pet - :param str api_key: (optional) :param int pet_id: Pet id to delete (required) + :param str api_key: (optional) :return: None """ @@ -384,7 +384,7 @@ class PetApi(object): if pet_id is None: raise ValueError("Missing the required parameter `pet_id` when calling `delete_pet`") - all_params = ['api_key', 'pet_id'] + all_params = ['pet_id', 'api_key'] params = locals() for key, val in iteritems(params['kwargs']): @@ -435,7 +435,7 @@ class PetApi(object): :param int pet_id: ID of pet to update (required) :param str additional_metadata: Additional data to pass to server (optional) - :param File file: file to upload (optional) + :param file file: file to upload (optional) :return: None """ diff --git a/samples/client/petstore/python/swagger_client/models/order.py b/samples/client/petstore/python/swagger_client/models/order.py index e364ba5b155..2e448f5f425 100644 --- a/samples/client/petstore/python/swagger_client/models/order.py +++ b/samples/client/petstore/python/swagger_client/models/order.py @@ -34,7 +34,7 @@ class Order(object): 'id': 'int', 'pet_id': 'int', 'quantity': 'int', - 'ship_date': 'DateTime', + 'ship_date': 'datetime', 'status': 'str', 'complete': 'bool' } @@ -58,7 +58,7 @@ class Order(object): self.quantity = None # int - self.ship_date = None # DateTime + self.ship_date = None # datetime # Order Status self.status = None # str diff --git a/samples/client/petstore/python/test-all.sh b/samples/client/petstore/python/test-all.sh index e62a66c3aae..e6c2a9ff19c 100755 --- a/samples/client/petstore/python/test-all.sh +++ b/samples/client/petstore/python/test-all.sh @@ -4,11 +4,13 @@ REQUIREMENTS_FILE=dev-requirements.txt REQUIREMENTS_OUT=dev-requirements.txt.log SETUP_OUT=*.egg-info VENV=.venv +DEACTIVE=false ### set virtualenv if [ -z "$VIRTUAL_ENV" ]; then virtualenv $VENV --no-site-packages source $VENV/bin/activate + DEACTIVE=true fi ### install dependencies @@ -17,3 +19,8 @@ python setup.py develop ### run tests tox + +### deactivate virtualenv +if [ $DEACTIVE == true ]; then + deactivate +fi diff --git a/samples/client/petstore/python/test.sh b/samples/client/petstore/python/test.sh index 309275e6ead..580cd7d67e9 100755 --- a/samples/client/petstore/python/test.sh +++ b/samples/client/petstore/python/test.sh @@ -4,11 +4,13 @@ REQUIREMENTS_FILE=dev-requirements.txt REQUIREMENTS_OUT=dev-requirements.txt.log SETUP_OUT=*.egg-info VENV=.venv +DEACTIVE=false ### set virtualenv if [ -z "$VIRTUAL_ENV" ]; then virtualenv $VENV --no-site-packages source $VENV/bin/activate + DEACTIVE=true fi ### install dependencies @@ -17,3 +19,9 @@ python setup.py develop ### run tests nosetests + +### deactivate virtualenv +if [ $DEACTIVE == true ]; then + deactivate +fi + From 30925b78004504ebc8d6068ba10f600dde4a01ad Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 14 Jul 2015 10:28:36 +0800 Subject: [PATCH 08/12] Update pom.xml of python client --- samples/client/petstore/python/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/client/petstore/python/pom.xml b/samples/client/petstore/python/pom.xml index b3feaf688a9..1eca98baf76 100644 --- a/samples/client/petstore/python/pom.xml +++ b/samples/client/petstore/python/pom.xml @@ -36,6 +36,7 @@ pip install + --user virtualenv From af673530221d3db8fbc0785b88eff7a62af8d5aa Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 14 Jul 2015 15:38:23 +0800 Subject: [PATCH 09/12] Update integration test of python client --- samples/client/petstore/python/Makefile | 7 ++++--- samples/client/petstore/python/pom.xml | 15 --------------- samples/client/petstore/python/test-all.sh | 4 ++-- samples/client/petstore/python/test.sh | 4 ++-- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/samples/client/petstore/python/Makefile b/samples/client/petstore/python/Makefile index b1c318aadb7..0f65e0c6ac3 100644 --- a/samples/client/petstore/python/Makefile +++ b/samples/client/petstore/python/Makefile @@ -1,4 +1,4 @@ - #!/bin/sh + #!/bin/bash REQUIREMENTS_FILE=dev-requirements.txt REQUIREMENTS_OUT=dev-requirements.txt.log @@ -8,13 +8,14 @@ VENV=.venv clean: rm -rf $(REQUIREMENTS_OUT) rm -rf $(SETUP_OUT) + rm -rf $(VENV) rm -rf .tox rm -rf .coverage find . -name "*.py[oc]" -delete find . -name "__pycache__" -delete test: clean - sh ./test.sh + bash ./test.sh test-all: clean - sh ./test-all.sh + bash ./test-all.sh diff --git a/samples/client/petstore/python/pom.xml b/samples/client/petstore/python/pom.xml index 1eca98baf76..147938617d2 100644 --- a/samples/client/petstore/python/pom.xml +++ b/samples/client/petstore/python/pom.xml @@ -26,21 +26,6 @@ exec-maven-plugin 1.2.1 - - pip-install - pre-integration-test - - exec - - - pip - - install - --user - virtualenv - - - nose-test integration-test diff --git a/samples/client/petstore/python/test-all.sh b/samples/client/petstore/python/test-all.sh index e6c2a9ff19c..03c16abd4ae 100755 --- a/samples/client/petstore/python/test-all.sh +++ b/samples/client/petstore/python/test-all.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash REQUIREMENTS_FILE=dev-requirements.txt REQUIREMENTS_OUT=dev-requirements.txt.log @@ -8,7 +8,7 @@ DEACTIVE=false ### set virtualenv if [ -z "$VIRTUAL_ENV" ]; then - virtualenv $VENV --no-site-packages + virtualenv $VENV --no-site-packages --always-copy source $VENV/bin/activate DEACTIVE=true fi diff --git a/samples/client/petstore/python/test.sh b/samples/client/petstore/python/test.sh index 580cd7d67e9..c6889895950 100755 --- a/samples/client/petstore/python/test.sh +++ b/samples/client/petstore/python/test.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash REQUIREMENTS_FILE=dev-requirements.txt REQUIREMENTS_OUT=dev-requirements.txt.log @@ -8,7 +8,7 @@ DEACTIVE=false ### set virtualenv if [ -z "$VIRTUAL_ENV" ]; then - virtualenv $VENV --no-site-packages + virtualenv $VENV --no-site-packages --always-copy source $VENV/bin/activate DEACTIVE=true fi From 9f76acbbd7f33335028280e22d619cd8e7e6bf67 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 14 Jul 2015 15:42:01 +0800 Subject: [PATCH 10/12] Update README file of python client --- .../swagger-codegen/src/main/resources/python/README.mustache | 2 +- samples/client/petstore/python/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/README.mustache b/modules/swagger-codegen/src/main/resources/python/README.mustache index 9c590a9a508..b47d009d451 100644 --- a/modules/swagger-codegen/src/main/resources/python/README.mustache +++ b/modules/swagger-codegen/src/main/resources/python/README.mustache @@ -38,7 +38,7 @@ TODO ## Tests -(Make sure you are running it inside of a [virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/)) +(Make sure you have installed `virtualenv` using `sudo pip install virtualenv`) You can run the tests in the current python platform: diff --git a/samples/client/petstore/python/README.md b/samples/client/petstore/python/README.md index 9c590a9a508..b47d009d451 100644 --- a/samples/client/petstore/python/README.md +++ b/samples/client/petstore/python/README.md @@ -38,7 +38,7 @@ TODO ## Tests -(Make sure you are running it inside of a [virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/)) +(Make sure you have installed `virtualenv` using `sudo pip install virtualenv`) You can run the tests in the current python platform: From 746a55be73c72aaaa36b2bfc03bce11f18fb3d47 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 14 Jul 2015 17:15:24 +0800 Subject: [PATCH 11/12] Update README file of python client --- .../swagger-codegen/src/main/resources/python/README.mustache | 2 +- samples/client/petstore/python/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/README.mustache b/modules/swagger-codegen/src/main/resources/python/README.mustache index b47d009d451..d2e47801ff1 100644 --- a/modules/swagger-codegen/src/main/resources/python/README.mustache +++ b/modules/swagger-codegen/src/main/resources/python/README.mustache @@ -40,7 +40,7 @@ TODO (Make sure you have installed `virtualenv` using `sudo pip install virtualenv`) -You can run the tests in the current python platform: + Execute the following command to run the tests in the current Python (v2 or v3) environment: ```sh $ make test diff --git a/samples/client/petstore/python/README.md b/samples/client/petstore/python/README.md index b47d009d451..d2e47801ff1 100644 --- a/samples/client/petstore/python/README.md +++ b/samples/client/petstore/python/README.md @@ -40,7 +40,7 @@ TODO (Make sure you have installed `virtualenv` using `sudo pip install virtualenv`) -You can run the tests in the current python platform: + Execute the following command to run the tests in the current Python (v2 or v3) environment: ```sh $ make test From 18ea21087ff02e9fc055fad14a3d94b072b0258a Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 14 Jul 2015 17:30:15 +0800 Subject: [PATCH 12/12] Update README file of python client --- .../src/main/resources/python/README.mustache | 9 ++++----- samples/client/petstore/python/README.md | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/README.mustache b/modules/swagger-codegen/src/main/resources/python/README.mustache index d2e47801ff1..463bbb37a18 100644 --- a/modules/swagger-codegen/src/main/resources/python/README.mustache +++ b/modules/swagger-codegen/src/main/resources/python/README.mustache @@ -11,13 +11,13 @@ python setup.py install Or you can install from Github via pip: ```sh -pip install git+https://github.com/geekerzp/SwaggerPetstore-python.git +pip install git+https://github.com/geekerzp/swagger_client.git ``` To use the bindings, import the pacakge: ```python -import SwaggerPetstore +import swagger_client ``` ## Manual Installation @@ -25,7 +25,7 @@ If you do not wish to use setuptools, you can download the latest release. Then, to use the bindings, import the package: ```python -import path.to.SwaggerPetstore-python.SwaggerPetstore +import path.to.swagger_client ``` ## Getting Started @@ -38,7 +38,7 @@ TODO ## Tests -(Make sure you have installed `virtualenv` using `sudo pip install virtualenv`) +(Please make sure you have [virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/) installed) Execute the following command to run the tests in the current Python (v2 or v3) environment: @@ -71,4 +71,3 @@ $ make test-all py34: commands succeeded congratulations :) ``` - diff --git a/samples/client/petstore/python/README.md b/samples/client/petstore/python/README.md index d2e47801ff1..463bbb37a18 100644 --- a/samples/client/petstore/python/README.md +++ b/samples/client/petstore/python/README.md @@ -11,13 +11,13 @@ python setup.py install Or you can install from Github via pip: ```sh -pip install git+https://github.com/geekerzp/SwaggerPetstore-python.git +pip install git+https://github.com/geekerzp/swagger_client.git ``` To use the bindings, import the pacakge: ```python -import SwaggerPetstore +import swagger_client ``` ## Manual Installation @@ -25,7 +25,7 @@ If you do not wish to use setuptools, you can download the latest release. Then, to use the bindings, import the package: ```python -import path.to.SwaggerPetstore-python.SwaggerPetstore +import path.to.swagger_client ``` ## Getting Started @@ -38,7 +38,7 @@ TODO ## Tests -(Make sure you have installed `virtualenv` using `sudo pip install virtualenv`) +(Please make sure you have [virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/) installed) Execute the following command to run the tests in the current Python (v2 or v3) environment: @@ -71,4 +71,3 @@ $ make test-all py34: commands succeeded congratulations :) ``` -