API: Added auto generated API documentation at /api/documentation
to implement this generator in every Path you want to document add the following decorator: @auto.doc()
This commit is contained in:
parent
252ecbb40e
commit
278a39710a
11 changed files with 338 additions and 0 deletions
|
@ -10,6 +10,8 @@ from flask import Flask, request, render_template, redirect, abort
|
|||
# from User import User
|
||||
from flask.ext.github import GitHub
|
||||
from flask.ext.cors import CORS, cross_origin
|
||||
from flask.ext.autodoc import Autodoc
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -22,6 +24,7 @@ app.config['GITHUB_CLIENT_SECRET'] = githubKeys.getSecret()
|
|||
|
||||
github = GitHub(app)
|
||||
cross = CORS(app)
|
||||
auto = Autodoc(app)
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
|
@ -31,6 +34,10 @@ def page_not_found(e):
|
|||
def wellcomePage():
|
||||
return app.send_static_file('index.html')
|
||||
|
||||
@app.route('/api/documentation')
|
||||
def documentation():
|
||||
return auto.html()
|
||||
|
||||
@app.route('/home')
|
||||
def returnHome():
|
||||
try:
|
||||
|
@ -41,7 +48,13 @@ def returnHome():
|
|||
|
||||
|
||||
@app.route('/api/getUserByToken/<string:token>', methods=["GET"])
|
||||
@auto.doc()
|
||||
def getUserByToken(token):
|
||||
'''
|
||||
param: String - token: users se-Token
|
||||
return: JSON object of the user
|
||||
if no valid seToken, return message: No User Found
|
||||
'''
|
||||
query = User.all()
|
||||
query.filter("seToken = ", token)
|
||||
|
||||
|
|
92
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/PKG-INFO
Normal file
92
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/PKG-INFO
Normal file
|
@ -0,0 +1,92 @@
|
|||
Metadata-Version: 1.1
|
||||
Name: Flask-Autodoc
|
||||
Version: 0.1.1
|
||||
Summary: Documentation generator for flask
|
||||
Home-page: http://github.com/acoomans/flask-autodoc
|
||||
Author: Arnaud Coomans
|
||||
Author-email: arnaud.coomans@gmail.com
|
||||
License: MIT
|
||||
Description: Flask-Autodoc
|
||||
=============
|
||||
|
||||
Flask Autodoc is a Flask extension that automatically creates documentation for your endpoints based on the routes,
|
||||
function arguments and docstring.
|
||||
|
||||
## Install
|
||||
|
||||
To install Flask-Autodoc:
|
||||
|
||||
python setup.py install
|
||||
|
||||
## Usage
|
||||
|
||||
Start using Flask-Autodoc by importing it and initializing it:
|
||||
|
||||
from flask import Flask
|
||||
from flask.ext.autodoc import Autodoc
|
||||
|
||||
app = Flask(__name__)
|
||||
auto = Autodoc(app)
|
||||
|
||||
by default, Flask-Autodoc will only document the routes you explicitly tell him to with the _doc_ decorator,
|
||||
like this:
|
||||
|
||||
@app.route('/user/<int:id>')
|
||||
@auto.doc
|
||||
def show_user(id):
|
||||
"""This returns a user with a given id."""
|
||||
return user_from_database(id)
|
||||
|
||||
to generate the documentation from an endpoint, use the _html()_ method:
|
||||
|
||||
@app.route('/documentation')
|
||||
def documentation():
|
||||
return auto.html()
|
||||
|
||||
if you to access the documentation without it being rendered in html:
|
||||
|
||||
@app.route('/documentation')
|
||||
def documentation():
|
||||
return auto.generate()
|
||||
|
||||
the documentation will then be returned as a list of rules, where each rule is a dictionary containing:
|
||||
|
||||
- methods: the set of allowed methods (ie ['GET', 'POST'])
|
||||
- rule: relative url (ie '/user/<int:id>')
|
||||
- endpoint: function name (ie 'show_user')
|
||||
- doc: docstring of the function
|
||||
- args: function arguments
|
||||
- defaults: defaults values for the arguments
|
||||
|
||||
## Groups
|
||||
|
||||
You may want to group endpoints together, to have different documentation sets. With this you can for example, only
|
||||
show some endpoints to third party developer and have full documentation for your own.
|
||||
|
||||
to assign an endpoint to a group, pass the name of the group as argument of the _doc_ decorator:
|
||||
|
||||
@app.route('/user/<int:id>')
|
||||
@auto.doc("public")
|
||||
def show_user(id):
|
||||
|
||||
to assign an endpoint to multiple groups, pass a list of group names as the _groups_ argument to _doc_:
|
||||
|
||||
@app.route('/user/<int:id>')
|
||||
@auto.doc(groups=["public","private"])
|
||||
def show_user(id):
|
||||
|
||||
to generate the documentation for a specific group, pass the name of the group to the _generate_ or _html_ methods:
|
||||
|
||||
auto.generate("public")
|
||||
|
||||
or
|
||||
|
||||
auto.html("public")
|
||||
Platform: any
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
13
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/SOURCES.txt
Normal file
13
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/SOURCES.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
MANIFEST.in
|
||||
README
|
||||
setup.cfg
|
||||
setup.py
|
||||
Flask_Autodoc.egg-info/PKG-INFO
|
||||
Flask_Autodoc.egg-info/SOURCES.txt
|
||||
Flask_Autodoc.egg-info/dependency_links.txt
|
||||
Flask_Autodoc.egg-info/not-zip-safe
|
||||
Flask_Autodoc.egg-info/requires.txt
|
||||
Flask_Autodoc.egg-info/top_level.txt
|
||||
flask_autodoc/__init__.py
|
||||
flask_autodoc/autodoc.py
|
||||
flask_autodoc/templates/autodoc_default.html
|
|
@ -0,0 +1 @@
|
|||
|
12
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/installed-files.txt
Normal file
12
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/installed-files.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
../flask_autodoc/autodoc.py
|
||||
../flask_autodoc/__init__.py
|
||||
../flask_autodoc/templates/autodoc_default.html
|
||||
../flask_autodoc/autodoc.pyc
|
||||
../flask_autodoc/__init__.pyc
|
||||
./
|
||||
top_level.txt
|
||||
SOURCES.txt
|
||||
requires.txt
|
||||
PKG-INFO
|
||||
not-zip-safe
|
||||
dependency_links.txt
|
1
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/not-zip-safe
Normal file
1
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/not-zip-safe
Normal file
|
@ -0,0 +1 @@
|
|||
|
1
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/requires.txt
Normal file
1
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/requires.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Flask
|
1
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/top_level.txt
Normal file
1
lib/Flask_Autodoc-0.1.1-py2.7.egg-info/top_level.txt
Normal file
|
@ -0,0 +1 @@
|
|||
flask_autodoc
|
2
lib/flask_autodoc/__init__.py
Normal file
2
lib/flask_autodoc/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
__author__ = 'arnaud'
|
||||
from autodoc import Autodoc
|
126
lib/flask_autodoc/autodoc.py
Normal file
126
lib/flask_autodoc/autodoc.py
Normal file
|
@ -0,0 +1,126 @@
|
|||
import os
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from flask import current_app, render_template, render_template_string
|
||||
from jinja2 import evalcontextfilter
|
||||
|
||||
|
||||
try:
|
||||
from flask import _app_ctx_stack as stack
|
||||
except ImportError:
|
||||
from flask import _request_ctx_stack as stack
|
||||
|
||||
|
||||
class Autodoc(object):
|
||||
|
||||
def __init__(self, app=None):
|
||||
self.app = app
|
||||
self.groups = defaultdict(set)
|
||||
if app is not None:
|
||||
self.init_app(app)
|
||||
|
||||
def init_app(self, app):
|
||||
if hasattr(app, 'teardown_appcontext'):
|
||||
app.teardown_appcontext(self.teardown)
|
||||
else:
|
||||
app.teardown_request(self.teardown)
|
||||
self.add_custom_template_filters(app)
|
||||
|
||||
def teardown(self, exception):
|
||||
ctx = stack.top
|
||||
|
||||
def add_custom_template_filters(self, app):
|
||||
"""Add custom filters to jinja2 templating engine"""
|
||||
self.add_custom_nl2br_filters(app)
|
||||
|
||||
def add_custom_nl2br_filters(self, app):
|
||||
"""Add a custom filter nl2br to jinja2
|
||||
Replaces all newline to <BR>
|
||||
"""
|
||||
_paragraph_re = re.compile(r'(?:\r\n|\r|\n){3,}')
|
||||
@app.template_filter()
|
||||
@evalcontextfilter
|
||||
def nl2br(eval_ctx, value):
|
||||
result = u'\n\n'.join(u'%s' % p.replace('\n', '<br>\n') for p in _paragraph_re.split(value))
|
||||
return result
|
||||
|
||||
def doc(self, group=None, aa=None, groups=None):
|
||||
"""Decorator to add flask route to autodoc for automatic documentation\
|
||||
|
||||
Any route decorated with this method will be added to the list of routes to be documented by the generate() or
|
||||
html() methods.
|
||||
|
||||
By default, the route is added to the 'all' group.
|
||||
By specifying group or groups argument, the route can be added to one or multiple other groups as well, besides
|
||||
the 'all' group.
|
||||
"""
|
||||
def decorator(f):
|
||||
if groups:
|
||||
groupset = set(groups)
|
||||
else:
|
||||
groupset = set()
|
||||
if group:
|
||||
groupset.add(group)
|
||||
groupset.add("all")
|
||||
for g in groupset:
|
||||
self.groups[g].add(f)
|
||||
return f
|
||||
return decorator
|
||||
|
||||
def generate(self, group="all", groups=[], sort=None):
|
||||
"""Returns a list of dict describing the routes specified by the doc() method
|
||||
|
||||
Each dict contains:
|
||||
- methods: the set of allowed methods (ie ['GET', 'POST'])
|
||||
- rule: relative url (ie '/user/<int:id>')
|
||||
- endpoint: function name (ie 'show_user')
|
||||
- doc: docstring of the function
|
||||
- args: function arguments
|
||||
- defaults: defaults values for the arguments
|
||||
|
||||
By specifying the group or groups arguments, only routes belonging to those groups will be returned.
|
||||
|
||||
Routes are sorted alphabetically based on the rule.
|
||||
"""
|
||||
links = []
|
||||
for rule in current_app.url_map.iter_rules():
|
||||
|
||||
if rule.endpoint == 'static':
|
||||
continue
|
||||
|
||||
func = current_app.view_functions[rule.endpoint]
|
||||
|
||||
if (groups and [True for g in groups if func in self.groups[g]]) or \
|
||||
(not groups and func in self.groups[group]):
|
||||
links.append(
|
||||
dict(
|
||||
methods = rule.methods,
|
||||
rule = "%s" % rule,
|
||||
endpoint = rule.endpoint,
|
||||
docstring = func.__doc__,
|
||||
args = list(func.func_code.co_varnames),
|
||||
defaults = rule.defaults
|
||||
)
|
||||
)
|
||||
if sort:
|
||||
return sort(links)
|
||||
else:
|
||||
return sorted(links, cmp=lambda x,y: cmp(x['rule'], y['rule']))
|
||||
|
||||
def html(self, template=None, group="all", groups=None, **context):
|
||||
"""Returns an html string of the routes specified by the doc() method
|
||||
|
||||
A template can be specified. A list of routes is available under the 'autodoc' value (refer to the documentation
|
||||
for the generate() for a description of available values). If no template is specified, a default template is
|
||||
used.
|
||||
|
||||
By specifying the group or groups arguments, only routes belonging to those groups will be returned.
|
||||
"""
|
||||
if template:
|
||||
return render_template(template, autodoc=self.generate(group), **context)
|
||||
else:
|
||||
filename = os.path.dirname(__file__)+"/templates/autodoc_default.html"
|
||||
with open(filename) as file:
|
||||
content = file.read()
|
||||
with current_app.app_context():
|
||||
return render_template_string(content, autodoc=self.generate(group=group, groups=groups), **context)
|
76
lib/flask_autodoc/templates/autodoc_default.html
Normal file
76
lib/flask_autodoc/templates/autodoc_default.html
Normal file
|
@ -0,0 +1,76 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>
|
||||
{% if title is defined -%}
|
||||
{{title}}
|
||||
{% else -%}
|
||||
Documentation
|
||||
{% endif -%}
|
||||
</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
div.mapping {
|
||||
margin: 20px 20px;
|
||||
}
|
||||
|
||||
ul.methods:before { content: "Methods: "; }
|
||||
ul.methods li {
|
||||
display: inline;
|
||||
list-style: none;
|
||||
}
|
||||
ul.methods li:after { content: ","; }
|
||||
ul.methods li:last-child:after { content: ""; }
|
||||
|
||||
ul.arguments:before { content: "Arguments: "; }
|
||||
ul.arguments li {
|
||||
display: inline;
|
||||
list-style: none;
|
||||
}
|
||||
ul.arguments .argument { font-style:italic }
|
||||
ul.arguments .default:not(:empty):before { content: "("; }
|
||||
ul.arguments .default:not(:empty):after { content: ")"; }
|
||||
ul.arguments li:after { content: ","; }
|
||||
ul.arguments li:last-child:after { content: ""; }
|
||||
|
||||
.docstring:before { content: "Description: "; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
{% if title is defined -%}
|
||||
{{title}}
|
||||
{% else -%}
|
||||
Documentation
|
||||
{% endif -%}
|
||||
</h1>
|
||||
|
||||
{% for doc in autodoc %}
|
||||
<div class="mapping">
|
||||
<a id="rule-{{doc.rule|urlencode}}" class="rule"><h2>{{doc.rule|escape}}</h2></a>
|
||||
<ul class="methods">
|
||||
{% for method in doc.methods -%}
|
||||
<li class="method">{{method}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<ul class="arguments">
|
||||
{% for arg in doc.args %}
|
||||
<li>
|
||||
<span class="argument">{{arg}}</span>
|
||||
<span class="default">{{doc.defaults[arg]}}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<p class="docstring">{{doc.docstring|urlize|nl2br}}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue