The following is an assessment of using Swagger to generate Python servers.
Under the Hood
The Connexion Framework provides most of the brains. It automagically routes HTTP requests to the correct handler based on the OpenAPI 2.0 Specification.
Python 3 must be used as the models use Function Annotations to specify the accepted parameter types.
Layout
The code is generated into three packages:
- controllers
- models
- test
and an entry point module app.py and a utils module util.py.
Controllers
The controllers package contains per resource modules. For example, in our test spec we define a Player resource. This means a players_controller.py file is generated.
Inside this module an operation for each endpoint is generated e.g.
def players_player_id_get(playerId):
...
def players_post():
...
Models
The models package also contains per resource modules. If the resource is Player the module is player.py. Nice, logical and straightforward.
The Player model is easy to understand, using private variables (I know it’s only a naming convention), and @property decorators.
It also generates models for the responses. In this case it created inline_response_200.py.
app.py
The entry point sets up the connexion app, specifies a Swagger aware JSONEncoder (custom treatment for objects with a swagger_types attribute), and runs it on port 8080.
Code Gen Error
The controller imports inline_response200 rather than inline_response_200.
Running
Running is straightforward. Install the dependencies, and then run app.py:
pip install -r requirements
python3 app.py
During my testing I was able to access the swagger UI (http://<server>/<baseURL>/ui),
and using the UI I could see the two operations exposed by the API:
The POST worked as expected and returned the response created by the swagger
codegen:
However I was unable to make the GET work, it always returned 404:
Conclusion
I think there may be potential here, but that is tempered by my previous encounters with code generators, and the couple of issues I ran into here.
As all of the routing and handler resolution is done automatically it means there is less opportunities for custom code when required at the request response level.
Compared to our current Django APIs, there is not really too much saving to be had.
Using the Django Rest Framework we can directly serialize Django database models,
coupled with Django Method View we have logical class based handlers that are named
according to the HTTP accept header, making custom handlers for different formats
simple (and avoid if...elif...else... noise). We are also able to easily use custom API
endpoints to make the API easier to consume by developers.
There may be a middle ground we can find here. There is Django REST Swagger which can generate documentation using Django Rest Framework. This would mean there is a contract for the clients to follow, and this would evolve in conjunction with the server. Again it would be a bit of departure from what we currently use but might be worth investigating.
In the short-term I don’t think we should use swagger codegen for Marty, as having codegen for three parts of the project is probably a step too far. We will produce an Open API Specification though, and the apps can use whatever parts of it they wish.
The API Specification is the really important part of the process. As we use it in more and more projects, we will end up developing our own reusable code that, that we should also use in projects where we are not developing the server side components.


