Skip to content

Commit 49e9c74

Browse files
committed
Merge pull request #572 from swagger-api/issue-567
Issue 570
2 parents f2ce5ef + 492ab20 commit 49e9c74

File tree

7 files changed

+152
-44
lines changed

7 files changed

+152
-44
lines changed

modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.wordnik.swagger.models.properties.*;
55

66
import java.io.File;
7+
import java.util.*;
78

89
public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig {
910
String module = "client";
@@ -50,7 +51,14 @@ public PythonClientCodegen() {
5051
typeMapping.put("string", "str");
5152
typeMapping.put("date", "datetime");
5253

53-
54+
// from https://docs.python.org/release/2.5.4/ref/keywords.html
55+
reservedWords = new HashSet<String> (
56+
Arrays.asList(
57+
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
58+
"assert", "else", "if", "pass", "yield", "break", "except", "import",
59+
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
60+
"return", "def", "for", "lambda", "try"));
61+
5462
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
5563
supportingFiles.add(new SupportingFile("swagger.mustache", module, "swagger.py"));
5664
supportingFiles.add(new SupportingFile("__init__.mustache", module, "__init__.py"));

samples/client/petstore/python/client/models/Category.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@
1515
limitations under the License.
1616
"""
1717

18-
class Category:
18+
class Category(object):
1919
"""NOTE: This class is auto generated by the swagger code generator program.
2020
Do not edit the class manually."""
2121

2222

2323
def __init__(self):
24+
"""
25+
Attributes:
26+
swaggerTypes (dict): The key is attribute name and the value is attribute type.
27+
attributeMap (dict): The key is attribute name and the value is json key in definition.
28+
"""
2429
self.swaggerTypes = {
2530

2631
'id': 'long',
@@ -30,6 +35,13 @@ def __init__(self):
3035

3136
}
3237

38+
self.attributeMap = {
39+
40+
'id': 'id',
41+
42+
'name': 'name'
43+
44+
}
3345

3446

3547

samples/client/petstore/python/client/models/Order.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@
1515
limitations under the License.
1616
"""
1717

18-
class Order:
18+
class Order(object):
1919
"""NOTE: This class is auto generated by the swagger code generator program.
2020
Do not edit the class manually."""
2121

2222

2323
def __init__(self):
24+
"""
25+
Attributes:
26+
swaggerTypes (dict): The key is attribute name and the value is attribute type.
27+
attributeMap (dict): The key is attribute name and the value is json key in definition.
28+
"""
2429
self.swaggerTypes = {
2530

2631
'id': 'long',
@@ -42,6 +47,21 @@ def __init__(self):
4247

4348
}
4449

50+
self.attributeMap = {
51+
52+
'id': 'id',
53+
54+
'petId': 'petId',
55+
56+
'quantity': 'quantity',
57+
58+
'shipDate': 'shipDate',
59+
60+
'status': 'status',
61+
62+
'complete': 'complete'
63+
64+
}
4565

4666

4767

samples/client/petstore/python/client/models/Pet.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@
1515
limitations under the License.
1616
"""
1717

18-
class Pet:
18+
class Pet(object):
1919
"""NOTE: This class is auto generated by the swagger code generator program.
2020
Do not edit the class manually."""
2121

2222

2323
def __init__(self):
24+
"""
25+
Attributes:
26+
swaggerTypes (dict): The key is attribute name and the value is attribute type.
27+
attributeMap (dict): The key is attribute name and the value is json key in definition.
28+
"""
2429
self.swaggerTypes = {
2530

2631
'id': 'long',
@@ -42,6 +47,21 @@ def __init__(self):
4247

4348
}
4449

50+
self.attributeMap = {
51+
52+
'id': 'id',
53+
54+
'category': 'category',
55+
56+
'name': 'name',
57+
58+
'photoUrls': 'photoUrls',
59+
60+
'tags': 'tags',
61+
62+
'status': 'status'
63+
64+
}
4565

4666

4767

samples/client/petstore/python/client/models/Tag.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@
1515
limitations under the License.
1616
"""
1717

18-
class Tag:
18+
class Tag(object):
1919
"""NOTE: This class is auto generated by the swagger code generator program.
2020
Do not edit the class manually."""
2121

2222

2323
def __init__(self):
24+
"""
25+
Attributes:
26+
swaggerTypes (dict): The key is attribute name and the value is attribute type.
27+
attributeMap (dict): The key is attribute name and the value is json key in definition.
28+
"""
2429
self.swaggerTypes = {
2530

2631
'id': 'long',
@@ -30,6 +35,13 @@ def __init__(self):
3035

3136
}
3237

38+
self.attributeMap = {
39+
40+
'id': 'id',
41+
42+
'name': 'name'
43+
44+
}
3345

3446

3547

samples/client/petstore/python/client/models/User.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@
1515
limitations under the License.
1616
"""
1717

18-
class User:
18+
class User(object):
1919
"""NOTE: This class is auto generated by the swagger code generator program.
2020
Do not edit the class manually."""
2121

2222

2323
def __init__(self):
24+
"""
25+
Attributes:
26+
swaggerTypes (dict): The key is attribute name and the value is attribute type.
27+
attributeMap (dict): The key is attribute name and the value is json key in definition.
28+
"""
2429
self.swaggerTypes = {
2530

2631
'id': 'long',
@@ -48,6 +53,25 @@ def __init__(self):
4853

4954
}
5055

56+
self.attributeMap = {
57+
58+
'id': 'id',
59+
60+
'username': 'username',
61+
62+
'firstName': 'firstName',
63+
64+
'lastName': 'lastName',
65+
66+
'email': 'email',
67+
68+
'password': 'password',
69+
70+
'phone': 'phone',
71+
72+
'userStatus': 'userStatus'
73+
74+
}
5175

5276

5377

samples/client/petstore/python/client/swagger.py

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from models import *
2020

2121

22-
class ApiClient:
22+
class ApiClient(object):
2323
"""Generic API client for Swagger client library builds
2424
2525
Attributes:
@@ -41,22 +41,22 @@ def callAPI(self, resourcePath, method, queryParams, postData,
4141
headers = {}
4242
if headerParams:
4343
for param, value in headerParams.iteritems():
44-
headers[param] = value
44+
headers[param] = ApiClient.sanitizeForSerialization(value)
4545

4646
if self.headerName:
47-
headers[self.headerName] = self.headerValue
47+
headers[self.headerName] = ApiClient.sanitizeForSerialization(self.headerValue)
4848

4949
if self.cookie:
50-
headers['Cookie'] = self.cookie
50+
headers['Cookie'] = ApiClient.sanitizeForSerialization(self.cookie)
5151

5252
data = None
5353

5454
if queryParams:
5555
# Need to remove None values, these should not be sent
5656
sentQueryParams = {}
5757
for param, value in queryParams.items():
58-
if value != None:
59-
sentQueryParams[param] = value
58+
if value is not None:
59+
sentQueryParams[param] = ApiClient.sanitizeForSerialization(value)
6060
url = url + '?' + urllib.urlencode(sentQueryParams)
6161

6262
if method in ['GET']:
@@ -65,7 +65,7 @@ def callAPI(self, resourcePath, method, queryParams, postData,
6565

6666
elif method in ['POST', 'PUT', 'DELETE']:
6767
if postData:
68-
postData = self.sanitizeForSerialization(postData)
68+
postData = ApiClient.sanitizeForSerialization(postData)
6969
if 'Content-type' not in headers:
7070
headers['Content-type'] = 'application/json'
7171
data = json.dumps(postData)
@@ -107,34 +107,38 @@ def toPathValue(self, obj):
107107
else:
108108
return urllib.quote(str(obj))
109109

110-
def sanitizeForSerialization(self, obj):
111-
"""Dump an object into JSON for POSTing."""
112-
113-
if type(obj) == type(None):
110+
@staticmethod
111+
def sanitizeForSerialization(obj):
112+
"""
113+
Sanitize an object for Request.
114+
115+
If obj is None, return None.
116+
If obj is str, int, long, float, bool, return directly.
117+
If obj is datetime.datetime, datetime.date convert to string in iso8601 format.
118+
If obj is list, santize each element in the list.
119+
If obj is dict, return the dict.
120+
If obj is swagger model, return the properties dict.
121+
"""
122+
if isinstance(obj, type(None)):
114123
return None
115-
elif type(obj) in [str, int, long, float, bool]:
124+
elif isinstance(obj, (str, int, long, float, bool, file)):
116125
return obj
117-
elif type(obj) == list:
118-
return [self.sanitizeForSerialization(subObj) for subObj in obj]
119-
elif type(obj) == datetime.datetime:
126+
elif isinstance(obj, list):
127+
return [ApiClient.sanitizeForSerialization(subObj) for subObj in obj]
128+
elif isinstance(obj, (datetime.datetime, datetime.date)):
120129
return obj.isoformat()
121130
else:
122-
if type(obj) == dict:
131+
if isinstance(obj, dict):
123132
objDict = obj
124133
else:
125-
objDict = obj.__dict__
126-
return {key: self.sanitizeForSerialization(val)
127-
for (key, val) in objDict.iteritems()
128-
if key != 'swaggerTypes'}
129-
130-
if type(postData) == list:
131-
# Could be a list of objects
132-
if type(postData[0]) in safeToDump:
133-
data = json.dumps(postData)
134-
else:
135-
data = json.dumps([datum.__dict__ for datum in postData])
136-
elif type(postData) not in safeToDump:
137-
data = json.dumps(postData.__dict__)
134+
# Convert model obj to dict except attributes `swaggerTypes`, `attributeMap`
135+
# and attributes which value is not None.
136+
# Convert attribute name to json key in model definition for request.
137+
objDict = {obj.attributeMap[key]: val
138+
for key, val in obj.__dict__.iteritems()
139+
if key != 'swaggerTypes' and key != 'attributeMap' and val is not None}
140+
return {key: ApiClient.sanitizeForSerialization(val)
141+
for (key, val) in objDict.iteritems()}
138142

139143
def buildMultipartFormData(self, postData, files):
140144
def escape_quotes(s):
@@ -194,16 +198,13 @@ def deserialize(self, obj, objClass):
194198
if objClass in [int, long, float, dict, list, str, bool]:
195199
return objClass(obj)
196200
elif objClass == datetime:
197-
# Server will always return a time stamp in UTC, but with
198-
# trailing +0000 indicating no offset from UTC. So don't process
199-
# last 5 characters.
200-
return datetime.datetime.strptime(obj[:-5], "%Y-%m-%dT%H:%M:%S.%f")
201+
return self.__parse_string_to_datetime(obj)
201202

202203
instance = objClass()
203204

204205
for attr, attrType in instance.swaggerTypes.iteritems():
205-
if obj is not None and attr in obj and type(obj) in [list, dict]:
206-
value = obj[attr]
206+
if obj is not None and instance.attributeMap[attr] in obj and type(obj) in [list, dict]:
207+
value = obj[instance.attributeMap[attr]]
207208
if attrType in ['str', 'int', 'long', 'float', 'bool']:
208209
attrType = eval(attrType)
209210
try:
@@ -214,7 +215,7 @@ def deserialize(self, obj, objClass):
214215
value = value
215216
setattr(instance, attr, value)
216217
elif (attrType == 'datetime'):
217-
setattr(instance, attr, datetime.datetime.strptime(value[:-5], "%Y-%m-%dT%H:%M:%S.%f"))
218+
setattr(instance, attr, self.__parse_string_to_datetime(value))
218219
elif 'list[' in attrType:
219220
match = re.match('list\[(.*)\]', attrType)
220221
subClass = match.group(1)
@@ -226,10 +227,21 @@ def deserialize(self, obj, objClass):
226227
subValues.append(self.deserialize(subValue, subClass))
227228
setattr(instance, attr, subValues)
228229
else:
229-
setattr(instance, attr, self.deserialize(value, objClass))
230+
setattr(instance, attr, self.deserialize(value, attrType))
230231

231232
return instance
232233

234+
def __parse_string_to_datetime(self, string):
235+
"""
236+
Parse datetime in string to datetime.
237+
238+
The string should be in iso8601 datetime format.
239+
"""
240+
try:
241+
from dateutil.parser import parse
242+
return parse(string)
243+
except ImportError:
244+
return string
233245

234246
class MethodRequest(urllib2.Request):
235247
def __init__(self, *args, **kwargs):
@@ -243,4 +255,4 @@ def __init__(self, *args, **kwargs):
243255
return urllib2.Request.__init__(self, *args, **kwargs)
244256

245257
def get_method(self):
246-
return getattr(self, 'method', urllib2.Request.get_method(self))
258+
return getattr(self, 'method', urllib2.Request.get_method(self))

0 commit comments

Comments
 (0)