Python Client Stub Generator¶
The RESTCoder’s Python client stub generator can be used to quickly and easily generate Python modules that can consume remote web APIs. The generated code handles data marshaling, unmarshaling, HTTP invocation and also in many cases error handling, thereby relieving the mashup and application developers from having to manually implement all that logic. If the input API description is properly documented, the Python code generated by the stub generator would have proper docstrings describing each of the auto-generated methods. By auto-generating code that masks all the complexities of communicating with a remote API, this tool greatly simplifies the process of developing mashups, desktop applications, command-line tools and webapps that rely on remote web services.
The following sections describe how to use the code generator and what to expect as its output.
Using the Python Code Generator¶
The Python client stub generator requires Python 2.7 to be installed. If Python 2.7 is already installed, simply head over to the bin
directory of the RESTCoder installation and execute the script named codegen.py
as follows.
./codegen.py -f /path/to/api/description.json -o mymodule.py
This will generate a Python module named mymodule.py
which can be used as a client stub (proxy) to consume the remote API described in description.json
.
It is also possible to load the input API description from a HTTP/S URL.
./codegen.py -u http://example.com/description.json -o mymodule.py
By default the HTTP OPTIONS
method will be used to pull the API description from the input URL. To use a different method use the -m
flag.
To see the full list of command line options supported by the Python code generator, run codegen.py
with the -h
flag.
./codegen.py -h
Generated Code¶
Python code generated by the client stub generator can be executed on any Python 2.7 runtime. The generated code is also highly backwards compatible with Python 2.6. The auto-generated code relies on following built-in Python modules.
The generated code may also rely on the api.py
module shipped with the RESTCoder distribution. This module can be found in the python-lib
directory of RESTCoder.
The Python code generator, generates a separate Python class for each resource defined in the API description. The class is usually has the same name as the resource with the suffix Client
appended to it. Operations of a resource are converted into methods of the corresponding generated class. Therefore if a particular input API description has a resource named OrderManager
which has the operations getOrder
and submitOrder
, the code generator would generate a Python class named OrderManagerClient
which has the functions getOrder()
and submitOrder()
. The input parameters of the two operations would be turned into Python method arguments and the output of the operations would be turned into return types.
The code generator would also generate separate classes for each of the data types defined in the input API description. Instances of these classes will be used as input arguments and return objects where appropriate. A separate set of static methods would be generated which handles serialization and deserialization of Python objects.
Media Types¶
As of now the Python code generator can only generate code for JSON based APIs (i.e. APIs that consume and produce JSON). If the input API description uses other media types, the code generator would create some place holder serialization/deserialization functions which simply raises the NotImplementedError exception.
def deserialize_VideoFeed_atomxml(obj):
raise NotImplementedError
It is trivial to add support for other media types in the code generator tool. Simply implement a serializer extending the AbstractSerializer
class of the serializers.py
module. In this class, specify how to recursively convert a Python object into a byte string in the target media type and how to covert a byte string into a Python object. Refer the default JSONSerializer
class in the same module for an example.
In situations where the target API supports multiple media types, you can force the code generator to stick to a single preferred media type when generating code by specifying the -d
option.
./codegen.py -f /path/to/api/description.json -o mymodule.py -d json
Using the Generated Code¶
Simply import the generated module and use the client classes in the module to communicate with the remote API resources. The docstrings of the class methods would list all the input arguments accepted by each method.
def deleteVideo(self, videoId):
"""
Args:
videoId string
Returns:
An instance of the VideoFeedEntry class
"""
query = ''
conn = self.get_connection()
...
The generated methods will take care of marshaling input arguments, HTTP connection establishment and teardown and also unmarshaling response data. An example code snippet that uses a generated module is given below.
import youtube
if __name__ == '__main__':
client = VideoSearchFeedClient()
entries = client.getVideoFeed('api', alt='json', q='Google Glass').feed.entry
print 'Found ' + str(len(entries)) + ' videos...'
for item in entries:
print item.title.t, '(Uploaded by:', item.author[0].name.t, ') - ', item.link[0].href
Error Handling¶
If the generated code encounters an error while invoking the target API, it would throw a RemoteException
, which is a custom exception type defined in the generated module.
Using a Custom URL¶
By default, the generated code would communicate with the target API by making a HTTP connection to the base URL specified in the API description. But in some cases it would be required to communicate with the API using a custom URL (some gateway or proxy URL). To specify a custom URL, specify the endpoint
argument in the constructor of the corresponding resource client.
import youtube
if __name__ == '__main__':
client = VideoSearchFeedClient(endpoint='http://my.custom.url')
...
Debug Mode¶
The auto-generated code supports a special debug mode. When executed in this mode, the client code prints all the requests and responses exchanged with the backend API. To enable the debug mode, simply pass True
to the debug
argument of the constructor of the corresponding resource client.
import youtube
if __name__ == '__main__':
client = VideoSearchFeedClient(debug=True)
...