GNUnet  last
flask_base.py
Go to the documentation of this file.
1 """
2  sphinxcontrib.autohttp.flask
3  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 
5  The sphinx.ext.autodoc-style HTTP API reference builder (from Flask)
6  for sphinxcontrib.httpdomain.
7 
8  :copyright: Copyright 2011 by Hong Minhee
9  :license: BSD, see LICENSE for details.
10 
11 """
12 
13 import re
14 import itertools
15 import six
16 
17 from docutils import nodes
18 from docutils.parsers.rst import directives
19 from docutils.statemachine import ViewList
20 
21 from sphinx.util import force_decode
22 from sphinx.util.compat import Directive
23 from sphinx.util.nodes import nested_parse_with_titles
24 from sphinx.util.docstrings import prepare_docstring
25 from sphinx.pycode import ModuleAnalyzer
26 
27 from sphinxcontrib import httpdomain
28 from sphinxcontrib.autohttp.common import http_directive, import_object
29 
30 
32  from werkzeug.routing import parse_rule
33  buf = six.StringIO()
34  for conv, arg, var in parse_rule(rule):
35  if conv:
36  buf.write('(')
37  if conv != 'default':
38  buf.write(conv)
39  buf.write(':')
40  buf.write(var)
41  buf.write(')')
42  else:
43  buf.write(var)
44  return buf.getvalue()
45 
46 
47 def get_routes(app, endpoint=None, order=None):
48  endpoints = []
49  for rule in app.url_map.iter_rules(endpoint):
50  url_with_endpoint = (
51  six.text_type(next(app.url_map.iter_rules(rule.endpoint))),
52  rule.endpoint
53  )
54  if url_with_endpoint not in endpoints:
55  endpoints.append(url_with_endpoint)
56  if order == 'path':
57  endpoints.sort()
58  endpoints = [e for _, e in endpoints]
59  for endpoint in endpoints:
60  methodrules = {}
61  for rule in app.url_map.iter_rules(endpoint):
62  methods = rule.methods.difference(['OPTIONS', 'HEAD'])
63  path = translate_werkzeug_rule(rule.rule)
64  for method in methods:
65  if method in methodrules:
66  methodrules[method].append(path)
67  else:
68  methodrules[method] = [path]
69  for method, paths in methodrules.items():
70  yield method, paths, endpoint
71 
72 
73 def quickref_directive(method, path, content):
74  rcomp = re.compile("^\s*.. :quickref:\s*(?P<quick>.*)$")
75  method = method.lower().strip()
76  if isinstance(content, six.string_types):
77  content = content.splitlines()
78  description=""
79  name=""
80  ref = path.replace("<","(").replace(">",")").replace("/","-").replace(":","-")
81  for line in content:
82  qref = rcomp.match(line)
83  if qref:
84  quickref = qref.group("quick")
85  parts = quickref.split(";",1)
86  if len(parts)>1:
87  name = parts[0]
88  description= parts[1]
89  else:
90  description= quickref
91  break
92 
93  row ={}
94  row['name'] = name
95  row['operation'] = ' - `%s %s <#%s-%s>`_' % (method.upper(), path, method.lower(), ref)
96  row['description'] = description
97 
98  return row
99 
100 class AutoflaskBase(Directive):
101 
102  has_content = True
103  required_arguments = 1
104  option_spec = {'endpoints': directives.unchanged,
105  'blueprints': directives.unchanged,
106  'modules': directives.unchanged,
107  'order': directives.unchanged,
108  'undoc-endpoints': directives.unchanged,
109  'undoc-blueprints': directives.unchanged,
110  'undoc-modules': directives.unchanged,
111  'undoc-static': directives.unchanged,
112  'include-empty-docstring': directives.unchanged}
113 
114  @property
115  def endpoints(self):
116  endpoints = self.options.get('endpoints', None)
117  if not endpoints:
118  return None
119  return re.split(r'\s*,\s*', endpoints)
120 
121  @property
122  def undoc_endpoints(self):
123  undoc_endpoints = self.options.get('undoc-endpoints', None)
124  if not undoc_endpoints:
125  return frozenset()
126  return frozenset(re.split(r'\s*,\s*', undoc_endpoints))
127 
128  @property
129  def blueprints(self):
130  blueprints = self.options.get('blueprints', None)
131  if not blueprints:
132  return None
133  return frozenset(re.split(r'\s*,\s*', blueprints))
134 
135  @property
136  def undoc_blueprints(self):
137  undoc_blueprints = self.options.get('undoc-blueprints', None)
138  if not undoc_blueprints:
139  return frozenset()
140  return frozenset(re.split(r'\s*,\s*', undoc_blueprints))
141 
142  @property
143  def modules(self):
144  modules = self.options.get('modules', None)
145  if not modules:
146  return frozenset()
147  return frozenset(re.split(r'\s*,\s*', modules))
148 
149  @property
150  def undoc_modules(self):
151  undoc_modules = self.options.get('undoc-modules', None)
152  if not undoc_modules:
153  return frozenset()
154  return frozenset(re.split(r'\s*,\s*', undoc_modules))
155 
156  @property
157  def order(self):
158  order = self.options.get('order', None)
159  if order not in (None, 'path'):
160  raise ValueError('Invalid value for :order:')
161  return order
162 
163  def make_rst(self, qref=False):
164  app = import_object(self.arguments[0])
165  if self.endpointsendpointsendpoints:
166  routes = itertools.chain(*[get_routes(app, endpoint, self.orderorderorder)
167  for endpoint in self.endpointsendpointsendpoints])
168  else:
169  routes = get_routes(app, order=self.orderorderorder)
170  for method, paths, endpoint in routes:
171  try:
172  blueprint, _, endpoint_internal = endpoint.rpartition('.')
173  if self.blueprintsblueprintsblueprints and blueprint not in self.blueprintsblueprintsblueprints:
174  continue
175  if blueprint in self.undoc_blueprintsundoc_blueprintsundoc_blueprints:
176  continue
177  except ValueError:
178  pass # endpoint is not within a blueprint
179 
180  if endpoint in self.undoc_endpointsundoc_endpointsundoc_endpoints:
181  continue
182  try:
183  static_url_path = app.static_url_path # Flask 0.7 or higher
184  except AttributeError:
185  static_url_path = app.static_path # Flask 0.6 or under
186  if ('undoc-static' in self.options and endpoint == 'static' and
187  static_url_path + '/(path:filename)' in paths):
188  continue
189  view = app.view_functions[endpoint]
190 
191  if self.modulesmodulesmodules and view.__module__ not in self.modulesmodulesmodules:
192  continue
193 
194  if self.undoc_modulesundoc_modulesundoc_modules and view.__module__ in self.modulesmodulesmodules:
195  continue
196 
197  docstring = view.__doc__ or ''
198  if hasattr(view, 'view_class'):
199  meth_func = getattr(view.view_class, method.lower(), None)
200  if meth_func and meth_func.__doc__:
201  docstring = meth_func.__doc__
202  if not isinstance(docstring, six.text_type):
203  analyzer = ModuleAnalyzer.for_module(view.__module__)
204  docstring = force_decode(docstring, analyzer.encoding)
205 
206  if not docstring and 'include-empty-docstring' not in self.options:
207  continue
208  docstring = prepare_docstring(docstring)
209  if qref == True:
210  for path in paths:
211  row = quickref_directive(method, path, docstring)
212  yield row
213  else:
214  for line in http_directive(method, paths, docstring):
215  yield line
static int replace
Replace DID Document Flag.
Definition: gnunet-did.c:55
static int get
Get DID Documement for DID Flag.
Definition: gnunet-did.c:65
def http_directive(method, path, content)
Definition: common.py:25
def import_object(import_name)
Definition: common.py:15
def get_routes(app, endpoint=None, order=None)
Definition: flask_base.py:47
def quickref_directive(method, path, content)
Definition: flask_base.py:73