From 278a39710aeba3cd2bee756f74507a1ee492e396 Mon Sep 17 00:00:00 2001 From: Sagi Dayan Date: Tue, 12 May 2015 11:32:22 +0300 Subject: [PATCH] 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() --- SE_API/API.py | 13 ++ .../PKG-INFO | 92 +++++++++++++ .../SOURCES.txt | 13 ++ .../dependency_links.txt | 1 + .../installed-files.txt | 12 ++ .../not-zip-safe | 1 + .../requires.txt | 1 + .../top_level.txt | 1 + lib/flask_autodoc/__init__.py | 2 + lib/flask_autodoc/autodoc.py | 126 ++++++++++++++++++ .../templates/autodoc_default.html | 76 +++++++++++ 11 files changed, 338 insertions(+) create mode 100644 lib/Flask_Autodoc-0.1.1-py2.7.egg-info/PKG-INFO create mode 100644 lib/Flask_Autodoc-0.1.1-py2.7.egg-info/SOURCES.txt create mode 100644 lib/Flask_Autodoc-0.1.1-py2.7.egg-info/dependency_links.txt create mode 100644 lib/Flask_Autodoc-0.1.1-py2.7.egg-info/installed-files.txt create mode 100644 lib/Flask_Autodoc-0.1.1-py2.7.egg-info/not-zip-safe create mode 100644 lib/Flask_Autodoc-0.1.1-py2.7.egg-info/requires.txt create mode 100644 lib/Flask_Autodoc-0.1.1-py2.7.egg-info/top_level.txt create mode 100644 lib/flask_autodoc/__init__.py create mode 100644 lib/flask_autodoc/autodoc.py create mode 100644 lib/flask_autodoc/templates/autodoc_default.html diff --git a/SE_API/API.py b/SE_API/API.py index 3f7c71e..1499197 100644 --- a/SE_API/API.py +++ b/SE_API/API.py @@ -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/', 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) diff --git a/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/PKG-INFO b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/PKG-INFO new file mode 100644 index 0000000..a824e17 --- /dev/null +++ b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/PKG-INFO @@ -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/') + @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/') + - 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/') + @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/') + @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 diff --git a/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/SOURCES.txt b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/SOURCES.txt new file mode 100644 index 0000000..57e888a --- /dev/null +++ b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/SOURCES.txt @@ -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 \ No newline at end of file diff --git a/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/dependency_links.txt b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/installed-files.txt b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/installed-files.txt new file mode 100644 index 0000000..898acd7 --- /dev/null +++ b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/installed-files.txt @@ -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 diff --git a/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/not-zip-safe b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/not-zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/not-zip-safe @@ -0,0 +1 @@ + diff --git a/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/requires.txt b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/requires.txt new file mode 100644 index 0000000..e3e9a71 --- /dev/null +++ b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/requires.txt @@ -0,0 +1 @@ +Flask diff --git a/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/top_level.txt b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/top_level.txt new file mode 100644 index 0000000..74da9a6 --- /dev/null +++ b/lib/Flask_Autodoc-0.1.1-py2.7.egg-info/top_level.txt @@ -0,0 +1 @@ +flask_autodoc diff --git a/lib/flask_autodoc/__init__.py b/lib/flask_autodoc/__init__.py new file mode 100644 index 0000000..1874862 --- /dev/null +++ b/lib/flask_autodoc/__init__.py @@ -0,0 +1,2 @@ +__author__ = 'arnaud' +from autodoc import Autodoc \ No newline at end of file diff --git a/lib/flask_autodoc/autodoc.py b/lib/flask_autodoc/autodoc.py new file mode 100644 index 0000000..27e38df --- /dev/null +++ b/lib/flask_autodoc/autodoc.py @@ -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
+ """ + _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', '
\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/') + - 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) \ No newline at end of file diff --git a/lib/flask_autodoc/templates/autodoc_default.html b/lib/flask_autodoc/templates/autodoc_default.html new file mode 100644 index 0000000..d6bce0e --- /dev/null +++ b/lib/flask_autodoc/templates/autodoc_default.html @@ -0,0 +1,76 @@ + + + + {% if title is defined -%} + {{title}} + {% else -%} + Documentation + {% endif -%} + + + + +

+ {% if title is defined -%} + {{title}} + {% else -%} + Documentation + {% endif -%} +

+ + {% for doc in autodoc %} +
+

{{doc.rule|escape}}

+
    + {% for method in doc.methods -%} +
  • {{method}}
  • + {% endfor %} +
+
    + {% for arg in doc.args %} +
  • + {{arg}} + {{doc.defaults[arg]}} +
  • + {% endfor %} +
+

{{doc.docstring|urlize|nl2br}}

+
+ {% endfor %} + + \ No newline at end of file