added readme, rebuilt client

This commit is contained in:
Tony Tam 2015-02-15 19:50:23 -08:00
parent 719820c089
commit e943f5c864
8 changed files with 259 additions and 210 deletions

View File

@ -26,6 +26,8 @@ cd $APP_DIR
./bin/java-petstore-filemap.sh ./bin/java-petstore-filemap.sh
./bin/java-petstore.sh ./bin/java-petstore.sh
./bin/java-wordnik-api.sh ./bin/java-wordnik-api.sh
./bin/php-petstore.sh
./bin/python-petstore.sh
./bin/objc-petstore.sh ./bin/objc-petstore.sh
./bin/objc-wordnik-api.sh ./bin/objc-wordnik-api.sh
./bin/tizen-petstore.sh ./bin/tizen-petstore.sh

View File

@ -31,6 +31,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ -i http://petstore.swagger.io/v2/swagger.json -l python -o samples/client/petstore/python -t modules/swagger-codegen/src/main/resources/python" ags="$@ -i http://petstore.swagger.io/v2/swagger.json -l python -o samples/client/petstore/python"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

View File

@ -62,6 +62,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("date", "datetime"); typeMapping.put("date", "datetime");
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("swagger.mustache", module, "swagger.py")); supportingFiles.add(new SupportingFile("swagger.mustache", module, "swagger.py"));
supportingFiles.add(new SupportingFile("__init__.mustache", module, "__init__.py")); supportingFiles.add(new SupportingFile("__init__.mustache", module, "__init__.py"));
supportingFiles.add(new SupportingFile("__init__.mustache", modelPackage.replaceAll("\\.", File.separator), "__init__.py")); supportingFiles.add(new SupportingFile("__init__.mustache", modelPackage.replaceAll("\\.", File.separator), "__init__.py"));

View File

@ -0,0 +1,25 @@
# Swagger Generated Python client
Usage example, based on the swagger petstore:
```python
# include the client module
from client import *
# build a client connection. In this example, we are passing the hostname as arg0, and
# sending a header with name `api_key` and value `special-key` on each call to the api.
client = swagger.ApiClient('http://petstore.swagger.io/v2', 'api_key', 'special-key')
# create the PetApi class with the client we just created
petApi = PetApi.PetApi(client)
# call the API and fetch a pet, with petId=3
pet = petApi.getPetById(petId=3)
# write it into pretty JSON
json = client.sanitizeForSerialization(pet)
print json
{'category': {'category': None, 'status': None, 'name': 'string', 'tags': None, 'photoUrls': None, 'id': 0L}, 'status': {'category': None, 'status': None, 'name': None, 'tags': None, 'photoUrls': None, 'id': None}, 'name': 'foogly', 'tags': [{'id': 0L, 'name': 'string'}], 'photoUrls': ['string'], 'id': 3L}
```

View File

@ -0,0 +1,25 @@
# Swagger Generated Python client
Usage example, based on the swagger petstore:
```python
# include the client module
from client import *
# build a client connection. In this example, we are passing the hostname as arg0, and
# sending a header with name `api_key` and value `special-key` on each call to the api.
client = swagger.ApiClient('http://petstore.swagger.io/v2', 'api_key', 'special-key')
# create the PetApi class with the client we just created
petApi = PetApi.PetApi(client)
# call the API and fetch a pet, with petId=3
pet = petApi.getPetById(petId=3)
# write it into pretty JSON
json = client.sanitizeForSerialization(pet)
print json
{'category': {'category': None, 'status': None, 'name': 'string', 'tags': None, 'photoUrls': None, 'id': 0L}, 'status': {'category': None, 'status': None, 'name': None, 'tags': None, 'photoUrls': None, 'id': None}, 'name': 'foogly', 'tags': [{'id': 0L, 'name': 'string'}], 'photoUrls': ['string'], 'id': 3L}
```

View File

@ -5,5 +5,5 @@ import os
__all__ = [] __all__ = []
for module in os.listdir(os.path.dirname(__file__)): for module in os.listdir(os.path.dirname(__file__)):
if module != '__init__.py' and module[-3:] == '.py': if module != '__init__.py' and module[-3:] == '.py':
__all__.append(module[:-3]) __all__.append(module[:-3])

View File

@ -5,5 +5,5 @@ import os
__all__ = [] __all__ = []
for module in os.listdir(os.path.dirname(__file__)): for module in os.listdir(os.path.dirname(__file__)):
if module != '__init__.py' and module[-3:] == '.py': if module != '__init__.py' and module[-3:] == '.py':
__all__.append(module[:-3]) __all__.append(module[:-3])

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
"""Wordnik.com's Swagger generic API client. This client handles the client- """Swagger generic API client. This client handles the client-
server communication, and is invariant across implementations. Specifics of server communication, and is invariant across implementations. Specifics of
the methods and models for each application are generated from the Swagger the methods and models for each application are generated from the Swagger
templates.""" templates."""
@ -20,231 +20,227 @@ from models import *
class ApiClient: class ApiClient:
"""Generic API client for Swagger client library builds""" """Generic API client for Swagger client library builds
def __init__(self, apiKey=None, apiServer=None): Attributes:
if apiKey == None: host: The base path for the server to call
raise Exception('You must pass an apiKey when instantiating the ' headerName: a header to pass when making calls to the API
'APIClient') headerValue: a header value to pass when making calls to the API
self.apiKey = apiKey """
self.apiServer = apiServer def __init__(self, host=None, headerName=None, headerValue=None):
self.cookie = None self.headerName = headerName
self.boundary = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(30)) self.headerValue = headerValue
self.host = host
self.cookie = None
self.boundary = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(30))
def callAPI(self, resourcePath, method, queryParams, postData, def callAPI(self, resourcePath, method, queryParams, postData,
headerParams=None, files=None): headerParams=None, files=None):
url = self.apiServer + resourcePath url = self.host + resourcePath
headers = {} headers = {}
if headerParams: if headerParams:
for param, value in headerParams.iteritems(): for param, value in headerParams.iteritems():
headers[param] = value headers[param] = value
headers['api_key'] = self.apiKey if self.headerName:
headers[self.headerName] = self.headerValue
if self.cookie: if self.cookie:
headers['Cookie'] = self.cookie headers['Cookie'] = self.cookie
data = None data = None
if queryParams: if queryParams:
# Need to remove None values, these should not be sent # Need to remove None values, these should not be sent
sentQueryParams = {} sentQueryParams = {}
for param, value in queryParams.items(): for param, value in queryParams.items():
if value != None: if value != None:
sentQueryParams[param] = value sentQueryParams[param] = value
url = url + '?' + urllib.urlencode(sentQueryParams) url = url + '?' + urllib.urlencode(sentQueryParams)
if method in ['GET']: if method in ['GET']:
#Options to add statements later on and for compatibility
#Options to add statements later on and for compatibility pass
pass
elif method in ['POST', 'PUT', 'DELETE']:
if postData:
postData = self.sanitizeForSerialization(postData)
if 'Content-type' not in headers:
headers['Content-type'] = 'application/json'
data = json.dumps(postData)
elif headers['Content-type'] == 'multipart/form-data':
data = self.buildMultipartFormData(postData, files)
headers['Content-type'] = 'multipart/form-data; boundary={0}'.format(self.boundary)
headers['Content-length'] = str(len(data))
else:
data = urllib.urlencode(postData)
elif method in ['POST', 'PUT', 'DELETE']:
if postData:
postData = self.sanitizeForSerialization(postData)
if 'Content-type' not in headers:
headers['Content-type'] = 'application/json'
data = json.dumps(postData)
elif headers['Content-type'] == 'multipart/form-data':
data = self.buildMultipartFormData(postData, files)
headers['Content-type'] = 'multipart/form-data; boundary={0}'.format(self.boundary)
headers['Content-length'] = str(len(data))
else: else:
raise Exception('Method ' + method + ' is not recognized.') data = urllib.urlencode(postData)
request = MethodRequest(method=method, url=url, headers=headers, else:
data=data) raise Exception('Method ' + method + ' is not recognized.')
# Make the request request = MethodRequest(method=method, url=url, headers=headers,
response = urllib2.urlopen(request) data=data)
if 'Set-Cookie' in response.headers:
self.cookie = response.headers['Set-Cookie']
string = response.read()
try: # Make the request
data = json.loads(string) response = urllib2.urlopen(request)
except ValueError: # PUT requests don't return anything if 'Set-Cookie' in response.headers:
data = None self.cookie = response.headers['Set-Cookie']
string = response.read()
return data try:
data = json.loads(string)
except ValueError: # PUT requests don't return anything
data = None
def toPathValue(self, obj): return data
"""Convert a string or object to a path-friendly value
Args:
obj -- object or string value
Returns:
string -- quoted value
"""
if type(obj) == list:
return urllib.quote(','.join(obj))
else:
return urllib.quote(str(obj))
def sanitizeForSerialization(self, obj): def toPathValue(self, obj):
"""Dump an object into JSON for POSTing.""" """Convert a string or object to a path-friendly value
Args:
obj -- object or string value
Returns:
string -- quoted value
"""
if type(obj) == list:
return urllib.quote(','.join(obj))
else:
return urllib.quote(str(obj))
if type(obj) == type(None): def sanitizeForSerialization(self, obj):
return None """Dump an object into JSON for POSTing."""
elif type(obj) in [str, int, long, float, bool]:
return obj if type(obj) == type(None):
elif type(obj) == list: return None
return [self.sanitizeForSerialization(subObj) for subObj in obj] elif type(obj) in [str, int, long, float, bool]:
elif type(obj) == datetime.datetime: return obj
return obj.isoformat() elif type(obj) == list:
else: return [self.sanitizeForSerialization(subObj) for subObj in obj]
if type(obj) == dict: elif type(obj) == datetime.datetime:
objDict = obj return obj.isoformat()
else:
if type(obj) == dict:
objDict = obj
else:
objDict = obj.__dict__
return {key: self.sanitizeForSerialization(val)
for (key, val) in objDict.iteritems()
if key != 'swaggerTypes'}
if type(postData) == list:
# Could be a list of objects
if type(postData[0]) in safeToDump:
data = json.dumps(postData)
else:
data = json.dumps([datum.__dict__ for datum in postData])
elif type(postData) not in safeToDump:
data = json.dumps(postData.__dict__)
def buildMultipartFormData(self, postData, files):
def escape_quotes(s):
return s.replace('"', '\\"')
lines = []
for name, value in postData.items():
lines.extend((
'--{0}'.format(self.boundary),
'Content-Disposition: form-data; name="{0}"'.format(escape_quotes(name)),
'',
str(value),
))
for name, filepath in files.items():
f = open(filepath, 'r')
filename = filepath.split('/')[-1]
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
lines.extend((
'--{0}'.format(self.boundary),
'Content-Disposition: form-data; name="{0}"; filename="{1}"'.format(escape_quotes(name), escape_quotes(filename)),
'Content-Type: {0}'.format(mimetype),
'',
f.read()
))
lines.extend((
'--{0}--'.format(self.boundary),
''
))
return '\r\n'.join(lines)
def deserialize(self, obj, objClass):
"""Derialize a JSON string into an object.
Args:
obj -- string or object to be deserialized
objClass -- class literal for deserialzied object, or string
of class name
Returns:
object -- deserialized object"""
# Have to accept objClass as string or actual type. Type could be a
# native Python type, or one of the model classes.
if type(objClass) == str:
if 'list[' in objClass:
match = re.match('list\[(.*)\]', objClass)
subClass = match.group(1)
return [self.deserialize(subObj, subClass) for subObj in obj]
if (objClass in ['int', 'float', 'long', 'dict', 'list', 'str', 'bool', 'datetime']):
objClass = eval(objClass)
else: # not a native type, must be model class
objClass = eval(objClass + '.' + objClass)
if objClass in [int, long, float, dict, list, str, bool]:
return objClass(obj)
elif objClass == datetime:
# Server will always return a time stamp in UTC, but with
# trailing +0000 indicating no offset from UTC. So don't process
# last 5 characters.
return datetime.datetime.strptime(obj[:-5], "%Y-%m-%dT%H:%M:%S.%f")
instance = objClass()
for attr, attrType in instance.swaggerTypes.iteritems():
if obj is not None and attr in obj and type(obj) in [list, dict]:
value = obj[attr]
if attrType in ['str', 'int', 'long', 'float', 'bool']:
attrType = eval(attrType)
try:
value = attrType(value)
except UnicodeEncodeError:
value = unicode(value)
except TypeError:
value = value
setattr(instance, attr, value)
elif (attrType == 'datetime'):
setattr(instance, attr, datetime.datetime.strptime(value[:-5], "%Y-%m-%dT%H:%M:%S.%f"))
elif 'list[' in attrType:
match = re.match('list\[(.*)\]', attrType)
subClass = match.group(1)
subValues = []
if not value:
setattr(instance, attr, None)
else: else:
objDict = obj.__dict__ for subValue in value:
return {key: self.sanitizeForSerialization(val) subValues.append(self.deserialize(subValue, subClass))
for (key, val) in objDict.iteritems() setattr(instance, attr, subValues)
if key != 'swaggerTypes'} else:
setattr(instance, attr, self.deserialize(value, objClass))
if type(postData) == list: return instance
# Could be a list of objects
if type(postData[0]) in safeToDump:
data = json.dumps(postData)
else:
data = json.dumps([datum.__dict__ for datum in postData])
elif type(postData) not in safeToDump:
data = json.dumps(postData.__dict__)
def buildMultipartFormData(self, postData, files):
def escape_quotes(s):
return s.replace('"', '\\"')
lines = []
for name, value in postData.items():
lines.extend((
'--{0}'.format(self.boundary),
'Content-Disposition: form-data; name="{0}"'.format(escape_quotes(name)),
'',
str(value),
))
for name, filepath in files.items():
f = open(filepath, 'r')
filename = filepath.split('/')[-1]
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
lines.extend((
'--{0}'.format(self.boundary),
'Content-Disposition: form-data; name="{0}"; filename="{1}"'.format(escape_quotes(name), escape_quotes(filename)),
'Content-Type: {0}'.format(mimetype),
'',
f.read()
))
lines.extend((
'--{0}--'.format(self.boundary),
''
))
return '\r\n'.join(lines)
def deserialize(self, obj, objClass):
"""Derialize a JSON string into an object.
Args:
obj -- string or object to be deserialized
objClass -- class literal for deserialzied object, or string
of class name
Returns:
object -- deserialized object"""
# Have to accept objClass as string or actual type. Type could be a
# native Python type, or one of the model classes.
if type(objClass) == str:
if 'list[' in objClass:
match = re.match('list\[(.*)\]', objClass)
subClass = match.group(1)
return [self.deserialize(subObj, subClass) for subObj in obj]
if (objClass in ['int', 'float', 'long', 'dict', 'list', 'str', 'bool', 'datetime']):
objClass = eval(objClass)
else: # not a native type, must be model class
objClass = eval(objClass + '.' + objClass)
if objClass in [int, long, float, dict, list, str, bool]:
return objClass(obj)
elif objClass == datetime:
# Server will always return a time stamp in UTC, but with
# trailing +0000 indicating no offset from UTC. So don't process
# last 5 characters.
return datetime.datetime.strptime(obj[:-5],
"%Y-%m-%dT%H:%M:%S.%f")
instance = objClass()
for attr, attrType in instance.swaggerTypes.iteritems():
if obj is not None and attr in obj and type(obj) in [list, dict]:
value = obj[attr]
if attrType in ['str', 'int', 'long', 'float', 'bool']:
attrType = eval(attrType)
try:
value = attrType(value)
except UnicodeEncodeError:
value = unicode(value)
except TypeError:
value = value
setattr(instance, attr, value)
elif (attrType == 'datetime'):
setattr(instance, attr, datetime.datetime.strptime(value[:-5],
"%Y-%m-%dT%H:%M:%S.%f"))
elif 'list[' in attrType:
match = re.match('list\[(.*)\]', attrType)
subClass = match.group(1)
subValues = []
if not value:
setattr(instance, attr, None)
else:
for subValue in value:
subValues.append(self.deserialize(subValue,
subClass))
setattr(instance, attr, subValues)
else:
setattr(instance, attr, self.deserialize(value,
objClass))
return instance
class MethodRequest(urllib2.Request): class MethodRequest(urllib2.Request):
def __init__(self, *args, **kwargs):
"""Construct a MethodRequest. Usage is the same as for
`urllib2.Request` except it also takes an optional `method`
keyword argument. If supplied, `method` will be used instead of
the default."""
def __init__(self, *args, **kwargs): if 'method' in kwargs:
"""Construct a MethodRequest. Usage is the same as for self.method = kwargs.pop('method')
`urllib2.Request` except it also takes an optional `method` return urllib2.Request.__init__(self, *args, **kwargs)
keyword argument. If supplied, `method` will be used instead of
the default."""
if 'method' in kwargs:
self.method = kwargs.pop('method')
return urllib2.Request.__init__(self, *args, **kwargs)
def get_method(self):
return getattr(self, 'method', urllib2.Request.get_method(self))
def get_method(self):
return getattr(self, 'method', urllib2.Request.get_method(self))