summaryrefslogtreecommitdiff
path: root/exts
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-08-29 11:44:18 +0200
committerFlorian Dold <florian.dold@gmail.com>2019-08-29 11:44:18 +0200
commitc3a6698c48f315e124bfd89bbb98564966f89434 (patch)
tree4687fbdec2523a6070108c83a0a463d76aff50f0 /exts
parent34d79e45dcce1ba2d4dfbe0099187b2518be9ad1 (diff)
downloaddocs-c3a6698c48f315e124bfd89bbb98564966f89434.tar.gz
docs-c3a6698c48f315e124bfd89bbb98564966f89434.tar.bz2
docs-c3a6698c48f315e124bfd89bbb98564966f89434.zip
structure
Diffstat (limited to 'exts')
-rw-r--r--exts/__pycache__/tsref.cpython-35.pycbin7453 -> 0 bytes
-rw-r--r--exts/httpdomain/__init__.py14
-rw-r--r--exts/httpdomain/autohttp/__init__.py11
-rw-r--r--exts/httpdomain/autohttp/bottle.py114
-rw-r--r--exts/httpdomain/autohttp/common.py36
-rw-r--r--exts/httpdomain/autohttp/flask.py48
-rw-r--r--exts/httpdomain/autohttp/flask_base.py215
-rw-r--r--exts/httpdomain/autohttp/flaskqref.py80
-rw-r--r--exts/httpdomain/autohttp/tornado.py128
-rw-r--r--exts/httpdomain/httpdomain.py771
-rw-r--r--exts/tslex.py88
-rw-r--r--exts/tsref.py233
12 files changed, 0 insertions, 1738 deletions
diff --git a/exts/__pycache__/tsref.cpython-35.pyc b/exts/__pycache__/tsref.cpython-35.pyc
deleted file mode 100644
index c2884964..00000000
--- a/exts/__pycache__/tsref.cpython-35.pyc
+++ /dev/null
Binary files differ
diff --git a/exts/httpdomain/__init__.py b/exts/httpdomain/__init__.py
deleted file mode 100644
index b5a7dc29..00000000
--- a/exts/httpdomain/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- sphinxcontrib
- ~~~~~~~~~~~~~
-
- This package is a namespace package that contains all extensions
- distributed in the ``sphinx-contrib`` distribution.
-
- :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-"""
-
-__import__('pkg_resources').declare_namespace(__name__)
-
diff --git a/exts/httpdomain/autohttp/__init__.py b/exts/httpdomain/autohttp/__init__.py
deleted file mode 100644
index 95372d4c..00000000
--- a/exts/httpdomain/autohttp/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""
- sphinxcontrib.autohttp
- ~~~~~~~~~~~~~~~~~~~~~~
-
- The sphinx.ext.autodoc-style HTTP API reference builder
- for sphinxcontrib.httpdomain.
-
- :copyright: Copyright 2011 by Hong Minhee
- :license: BSD, see LICENSE for details.
-
-"""
diff --git a/exts/httpdomain/autohttp/bottle.py b/exts/httpdomain/autohttp/bottle.py
deleted file mode 100644
index d8c18597..00000000
--- a/exts/httpdomain/autohttp/bottle.py
+++ /dev/null
@@ -1,114 +0,0 @@
-"""
- sphinxcontrib.autohttp.bottle
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The sphinx.ext.autodoc-style HTTP API reference builder (from Bottle)
- for sphinxcontrib.httpdomain.
-
- :copyright: Copyright 2012 by Jameel Al-Aziz
- :license: BSD, see LICENSE for details.
-
-"""
-
-import re
-import six
-
-from docutils import nodes
-from docutils.parsers.rst import directives
-from docutils.statemachine import ViewList
-
-from sphinx.util import force_decode
-from sphinx.util.compat import Directive
-from sphinx.util.nodes import nested_parse_with_titles
-from sphinx.util.docstrings import prepare_docstring
-from sphinx.pycode import ModuleAnalyzer
-
-from sphinxcontrib import httpdomain
-from sphinxcontrib.autohttp.common import http_directive, import_object
-
-
-def translate_bottle_rule(app, rule):
- buf = six.StringIO()
- if hasattr(app.router, "parse_rule"):
- iterator = app.router.parse_rule(rule) # bottle 0.11
- else:
- iterator = app.router._itertokens(rule) # bottle 0.12
- for name, filter, conf in iterator:
- if filter:
- buf.write('(')
- buf.write(name)
- if (filter != app.router.default_filter and filter != 'default')\
- or conf:
- buf.write(':')
- buf.write(filter)
- if conf:
- buf.write(':')
- buf.write(conf)
- buf.write(')')
- else:
- buf.write(name)
- return buf.getvalue()
-
-
-def get_routes(app):
- for route in app.routes:
- path = translate_bottle_rule(app, route.rule)
- yield route.method, path, route
-
-
-class AutobottleDirective(Directive):
-
- has_content = True
- required_arguments = 1
- option_spec = {'endpoints': directives.unchanged,
- 'undoc-endpoints': directives.unchanged,
- 'include-empty-docstring': directives.unchanged}
-
- @property
- def endpoints(self):
- endpoints = self.options.get('endpoints', None)
- if not endpoints:
- return None
- return frozenset(re.split(r'\s*,\s*', endpoints))
-
- @property
- def undoc_endpoints(self):
- undoc_endpoints = self.options.get('undoc-endpoints', None)
- if not undoc_endpoints:
- return frozenset()
- return frozenset(re.split(r'\s*,\s*', undoc_endpoints))
-
- def make_rst(self):
- app = import_object(self.arguments[0])
- for method, path, target in get_routes(app):
- endpoint = target.name or target.callback.__name__
- if self.endpoints and endpoint not in self.endpoints:
- continue
- if endpoint in self.undoc_endpoints:
- continue
- view = target.callback
- docstring = view.__doc__ or ''
- if not isinstance(docstring, six.text_type):
- analyzer = ModuleAnalyzer.for_module(view.__module__)
- docstring = force_decode(docstring, analyzer.encoding)
- if not docstring and 'include-empty-docstring' not in self.options:
- continue
- docstring = prepare_docstring(docstring)
- for line in http_directive(method, path, docstring):
- yield line
-
- def run(self):
- node = nodes.section()
- node.document = self.state.document
- result = ViewList()
- for line in self.make_rst():
- result.append(line, '<autobottle>')
- nested_parse_with_titles(self.state, result, node)
- return node.children
-
-
-def setup(app):
- if 'http' not in app.domains:
- httpdomain.setup(app)
- app.add_directive('autobottle', AutobottleDirective)
-
diff --git a/exts/httpdomain/autohttp/common.py b/exts/httpdomain/autohttp/common.py
deleted file mode 100644
index 199e2972..00000000
--- a/exts/httpdomain/autohttp/common.py
+++ /dev/null
@@ -1,36 +0,0 @@
-"""
- sphinxcontrib.autohttp.common
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The common functions for web framework reflection.
-
- :copyright: Copyright 2011 by Hong Minhee
- :license: BSD, see LICENSE for details.
-
-"""
-import six
-from six.moves import builtins
-from six.moves import reduce
-
-def import_object(import_name):
- module_name, expr = import_name.split(':', 1)
- mod = __import__(module_name)
- mod = reduce(getattr, module_name.split('.')[1:], mod)
- globals = builtins
- if not isinstance(globals, dict):
- globals = globals.__dict__
- return eval(expr, globals, mod.__dict__)
-
-
-def http_directive(method, path, content):
- method = method.lower().strip()
- if isinstance(content, six.string_types):
- content = content.splitlines()
- yield ''
- paths = [path] if isinstance(path, six.string_types) else path
- for path in paths:
- yield '.. http:{method}:: {path}'.format(**locals())
- yield ''
- for line in content:
- yield ' ' + line
- yield ''
diff --git a/exts/httpdomain/autohttp/flask.py b/exts/httpdomain/autohttp/flask.py
deleted file mode 100644
index 4bd5232e..00000000
--- a/exts/httpdomain/autohttp/flask.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
- sphinxcontrib.autohttp.flask
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The sphinx.ext.autodoc-style HTTP API reference builder (from Flask)
- for sphinxcontrib.httpdomain.
-
- :copyright: Copyright 2011 by Hong Minhee
- :license: BSD, see LICENSE for details.
-
-"""
-from __future__ import absolute_import
-
-import re
-import itertools
-import six
-
-from docutils import nodes
-from docutils.parsers.rst import directives
-from docutils.statemachine import ViewList
-
-from sphinx.util import force_decode
-from sphinx.util.compat import Directive
-from sphinx.util.nodes import nested_parse_with_titles
-from sphinx.util.docstrings import prepare_docstring
-from sphinx.pycode import ModuleAnalyzer
-
-from sphinxcontrib import httpdomain
-from sphinxcontrib.autohttp.common import http_directive, import_object
-
-from .flask_base import AutoflaskBase
-
-class AutoflaskDirective(AutoflaskBase):
-
- def run(self):
- node = nodes.section()
- node.document = self.state.document
- result = ViewList()
- for line in self.make_rst():
- result.append(line, '<autoflask>')
- nested_parse_with_titles(self.state, result, node)
- return node.children
-
-
-def setup(app):
- if 'http' not in app.domains:
- httpdomain.setup(app)
- app.add_directive('autoflask', AutoflaskDirective)
diff --git a/exts/httpdomain/autohttp/flask_base.py b/exts/httpdomain/autohttp/flask_base.py
deleted file mode 100644
index 50454fe2..00000000
--- a/exts/httpdomain/autohttp/flask_base.py
+++ /dev/null
@@ -1,215 +0,0 @@
-"""
- sphinxcontrib.autohttp.flask
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The sphinx.ext.autodoc-style HTTP API reference builder (from Flask)
- for sphinxcontrib.httpdomain.
-
- :copyright: Copyright 2011 by Hong Minhee
- :license: BSD, see LICENSE for details.
-
-"""
-
-import re
-import itertools
-import six
-
-from docutils import nodes
-from docutils.parsers.rst import directives
-from docutils.statemachine import ViewList
-
-from sphinx.util import force_decode
-from sphinx.util.compat import Directive
-from sphinx.util.nodes import nested_parse_with_titles
-from sphinx.util.docstrings import prepare_docstring
-from sphinx.pycode import ModuleAnalyzer
-
-from sphinxcontrib import httpdomain
-from sphinxcontrib.autohttp.common import http_directive, import_object
-
-
-def translate_werkzeug_rule(rule):
- from werkzeug.routing import parse_rule
- buf = six.StringIO()
- for conv, arg, var in parse_rule(rule):
- if conv:
- buf.write('(')
- if conv != 'default':
- buf.write(conv)
- buf.write(':')
- buf.write(var)
- buf.write(')')
- else:
- buf.write(var)
- return buf.getvalue()
-
-
-def get_routes(app, endpoint=None, order=None):
- endpoints = []
- for rule in app.url_map.iter_rules(endpoint):
- url_with_endpoint = (
- six.text_type(next(app.url_map.iter_rules(rule.endpoint))),
- rule.endpoint
- )
- if url_with_endpoint not in endpoints:
- endpoints.append(url_with_endpoint)
- if order == 'path':
- endpoints.sort()
- endpoints = [e for _, e in endpoints]
- for endpoint in endpoints:
- methodrules = {}
- for rule in app.url_map.iter_rules(endpoint):
- methods = rule.methods.difference(['OPTIONS', 'HEAD'])
- path = translate_werkzeug_rule(rule.rule)
- for method in methods:
- if method in methodrules:
- methodrules[method].append(path)
- else:
- methodrules[method] = [path]
- for method, paths in methodrules.items():
- yield method, paths, endpoint
-
-
-def quickref_directive(method, path, content):
- rcomp = re.compile("^\s*.. :quickref:\s*(?P<quick>.*)$")
- method = method.lower().strip()
- if isinstance(content, six.string_types):
- content = content.splitlines()
- description=""
- name=""
- ref = path.replace("<","(").replace(">",")").replace("/","-").replace(":","-")
- for line in content:
- qref = rcomp.match(line)
- if qref:
- quickref = qref.group("quick")
- parts = quickref.split(";",1)
- if len(parts)>1:
- name = parts[0]
- description= parts[1]
- else:
- description= quickref
- break
-
- row ={}
- row['name'] = name
- row['operation'] = ' - `%s %s <#%s-%s>`_' % (method.upper(), path, method.lower(), ref)
- row['description'] = description
-
- return row
-
-class AutoflaskBase(Directive):
-
- has_content = True
- required_arguments = 1
- option_spec = {'endpoints': directives.unchanged,
- 'blueprints': directives.unchanged,
- 'modules': directives.unchanged,
- 'order': directives.unchanged,
- 'undoc-endpoints': directives.unchanged,
- 'undoc-blueprints': directives.unchanged,
- 'undoc-modules': directives.unchanged,
- 'undoc-static': directives.unchanged,
- 'include-empty-docstring': directives.unchanged}
-
- @property
- def endpoints(self):
- endpoints = self.options.get('endpoints', None)
- if not endpoints:
- return None
- return re.split(r'\s*,\s*', endpoints)
-
- @property
- def undoc_endpoints(self):
- undoc_endpoints = self.options.get('undoc-endpoints', None)
- if not undoc_endpoints:
- return frozenset()
- return frozenset(re.split(r'\s*,\s*', undoc_endpoints))
-
- @property
- def blueprints(self):
- blueprints = self.options.get('blueprints', None)
- if not blueprints:
- return None
- return frozenset(re.split(r'\s*,\s*', blueprints))
-
- @property
- def undoc_blueprints(self):
- undoc_blueprints = self.options.get('undoc-blueprints', None)
- if not undoc_blueprints:
- return frozenset()
- return frozenset(re.split(r'\s*,\s*', undoc_blueprints))
-
- @property
- def modules(self):
- modules = self.options.get('modules', None)
- if not modules:
- return frozenset()
- return frozenset(re.split(r'\s*,\s*', modules))
-
- @property
- def undoc_modules(self):
- undoc_modules = self.options.get('undoc-modules', None)
- if not undoc_modules:
- return frozenset()
- return frozenset(re.split(r'\s*,\s*', undoc_modules))
-
- @property
- def order(self):
- order = self.options.get('order', None)
- if order not in (None, 'path'):
- raise ValueError('Invalid value for :order:')
- return order
-
- def make_rst(self, qref=False):
- app = import_object(self.arguments[0])
- if self.endpoints:
- routes = itertools.chain(*[get_routes(app, endpoint, self.order)
- for endpoint in self.endpoints])
- else:
- routes = get_routes(app, order=self.order)
- for method, paths, endpoint in routes:
- try:
- blueprint, _, endpoint_internal = endpoint.rpartition('.')
- if self.blueprints and blueprint not in self.blueprints:
- continue
- if blueprint in self.undoc_blueprints:
- continue
- except ValueError:
- pass # endpoint is not within a blueprint
-
- if endpoint in self.undoc_endpoints:
- continue
- try:
- static_url_path = app.static_url_path # Flask 0.7 or higher
- except AttributeError:
- static_url_path = app.static_path # Flask 0.6 or under
- if ('undoc-static' in self.options and endpoint == 'static' and
- static_url_path + '/(path:filename)' in paths):
- continue
- view = app.view_functions[endpoint]
-
- if self.modules and view.__module__ not in self.modules:
- continue
-
- if self.undoc_modules and view.__module__ in self.modules:
- continue
-
- docstring = view.__doc__ or ''
- if hasattr(view, 'view_class'):
- meth_func = getattr(view.view_class, method.lower(), None)
- if meth_func and meth_func.__doc__:
- docstring = meth_func.__doc__
- if not isinstance(docstring, six.text_type):
- analyzer = ModuleAnalyzer.for_module(view.__module__)
- docstring = force_decode(docstring, analyzer.encoding)
-
- if not docstring and 'include-empty-docstring' not in self.options:
- continue
- docstring = prepare_docstring(docstring)
- if qref == True:
- for path in paths:
- row = quickref_directive(method, path, docstring)
- yield row
- else:
- for line in http_directive(method, paths, docstring):
- yield line
diff --git a/exts/httpdomain/autohttp/flaskqref.py b/exts/httpdomain/autohttp/flaskqref.py
deleted file mode 100644
index c28bb153..00000000
--- a/exts/httpdomain/autohttp/flaskqref.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""
- sphinxcontrib.autohttp.flaskqref
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The sphinx.ext.autodoc-style HTTP API quick reference
- builder (from Flask)
- for sphinxcontrib.httpdomain.
-
- :copyright: Copyright 2011 by Hong Minhee
- :license: BSD, see LICENSE for details.
-
-"""
-
-from docutils import nodes
-from docutils.statemachine import ViewList
-
-from sphinxcontrib import httpdomain
-from sphinx.util.nodes import nested_parse_with_titles
-
-from .flask import AutoflaskBase
-
-
-class QuickReferenceFlaskDirective(AutoflaskBase):
-
-
- header = [ '',
- '.. list-table::',
- ' :widths: 20 45 35',
- ' :header-rows: 1',
- '',
- ' * - Resource',
- ' - Operation',
- ' - Description'
- ]
-
- def run(self):
- node = nodes.section()
- node.document = self.state.document
- result = ViewList()
- for line in QuickReferenceFlaskDirective.header:
- result.append(line, '<qrefflask>')
- table={}
- table_sorted_names=[]
-
- for table_row in self.make_rst(qref=True):
- name = table_row['name']
- if table.get(name) is None:
- table[name]=[]
- table[name].append(table_row)
- if name not in table_sorted_names:
- table_sorted_names.append(name)
-
- table_sorted_names.sort()
-
- for name in table_sorted_names:
- # Keep table display clean by not repeating duplicate
- # resource names and descriptions
- display_name = name
- previous_description=None
- for row in table[name]:
- result.append(' * - %s' % display_name, '<qrefflask>')
- display_name =""
- result.append(row['operation'], '<qrefflask>')
- description = row['description']
- if previous_description is not None and previous_description == description:
- description =""
- else:
- previous_description = description
-
- result.append(' - %s' % description, '<qrefflask>')
-
- result.append('', '<qrefflask>')
- nested_parse_with_titles(self.state, result, node)
- return node.children
-
-def setup(app):
- if 'http' not in app.domains:
- httpdomain.setup(app)
- app.add_directive('qrefflask', QuickReferenceFlaskDirective)
-
diff --git a/exts/httpdomain/autohttp/tornado.py b/exts/httpdomain/autohttp/tornado.py
deleted file mode 100644
index 9a514fee..00000000
--- a/exts/httpdomain/autohttp/tornado.py
+++ /dev/null
@@ -1,128 +0,0 @@
-"""
- sphinxcontrib.autohttp.tornado
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The sphinx.ext.autodoc-style HTTP API reference builder (from Tornado)
- for sphinxcontrib.httpdomain.
-
- :copyright: Copyright 2013 by Rodrigo Machado
- :license: BSD, see LICENSE for details.
-
-"""
-
-import inspect
-import re
-import six
-
-from docutils import nodes
-from docutils.parsers.rst import directives
-from docutils.statemachine import ViewList
-
-from sphinx.util import force_decode
-from sphinx.util.compat import Directive
-from sphinx.util.nodes import nested_parse_with_titles
-from sphinx.util.docstrings import prepare_docstring
-from sphinx.pycode import ModuleAnalyzer
-
-from sphinxcontrib import httpdomain
-from sphinxcontrib.autohttp.common import http_directive, import_object
-
-
-def translate_tornado_rule(app, rule):
- buf = six.StringIO()
- for name, filter, conf in app.router.parse_rule(rule):
- if filter:
- buf.write('(')
- buf.write(name)
- if filter != app.router.default_filter or conf:
- buf.write(':')
- buf.write(filter)
- if conf:
- buf.write(':')
- buf.write(conf)
- buf.write(')')
- else:
- buf.write(name)
- return buf.getvalue()
-
-
-def get_routes(app):
- for spec in app.handlers[0][1]:
- handler = spec.handler_class
- doc_methods = list(handler.SUPPORTED_METHODS)
- if 'HEAD' in doc_methods:
- doc_methods.remove('HEAD')
- if 'OPTIONS' in doc_methods:
- doc_methods.remove('OPTIONS')
-
- for method in doc_methods:
- maybe_method = getattr(handler, method.lower(), None)
- if (inspect.isfunction(maybe_method) or
- inspect.ismethod(maybe_method)):
- yield method.lower(), spec.regex.pattern, handler
-
-
-def normalize_path(path):
- if path.endswith('$'):
- path = path[:-1]
- return path
-
-
-class AutoTornadoDirective(Directive):
-
- has_content = True
- required_arguments = 1
- option_spec = {'endpoints': directives.unchanged,
- 'undoc-endpoints': directives.unchanged,
- 'include-empty-docstring': directives.unchanged}
-
- @property
- def endpoints(self):
- endpoints = self.options.get('endpoints', None)
- if not endpoints:
- return None
- return frozenset(re.split(r'\s*,\s*', endpoints))
-
- @property
- def undoc_endpoints(self):
- undoc_endpoints = self.options.get('undoc-endpoints', None)
- if not undoc_endpoints:
- return frozenset()
- return frozenset(re.split(r'\s*,\s*', undoc_endpoints))
-
- def make_rst(self):
- app = import_object(self.arguments[0])
- for method, path, handler in get_routes(app):
- class_name = handler.__name__
- method_name = getattr(handler, method).__name__
- endpoint = '.'.join((class_name, method_name))
-
- if self.endpoints and endpoint not in self.endpoints:
- continue
- if endpoint in self.undoc_endpoints:
- continue
-
- docstring = getattr(handler, method).__doc__ or ''
- #if not isinstance(docstring, unicode):
- # analyzer = ModuleAnalyzer.for_module(view.__module__)
- # docstring = force_decode(docstring, analyzer.encoding)
- if not docstring and 'include-empty-docstring' not in self.options:
- continue
- docstring = prepare_docstring(docstring)
- for line in http_directive(method, normalize_path(path), docstring):
- yield line
-
- def run(self):
- node = nodes.section()
- node.document = self.state.document
- result = ViewList()
- for line in self.make_rst():
- result.append(line, '<autotornado>')
- nested_parse_with_titles(self.state, result, node)
- return node.children
-
-
-def setup(app):
- if 'http' not in app.domains:
- httpdomain.setup(app)
- app.add_directive('autotornado', AutoTornadoDirective)
diff --git a/exts/httpdomain/httpdomain.py b/exts/httpdomain/httpdomain.py
deleted file mode 100644
index a5e34716..00000000
--- a/exts/httpdomain/httpdomain.py
+++ /dev/null
@@ -1,771 +0,0 @@
-"""
- sphinxcontrib.httpdomain
- ~~~~~~~~~~~~~~~~~~~~~~~~
-
- The HTTP domain for documenting RESTful HTTP APIs.
-
- :copyright: Copyright 2011 by Hong Minhee
- :license: BSD, see LICENSE for details.
-
-"""
-
-import re
-
-from docutils import nodes
-
-from pygments.lexer import RegexLexer, bygroups
-from pygments.lexers import get_lexer_by_name
-from pygments.token import Literal, Text, Operator, Keyword, Name, Number
-from pygments.util import ClassNotFound
-
-from sphinx import addnodes
-from sphinx.roles import XRefRole
-from sphinx.domains import Domain, ObjType, Index
-from sphinx.directives import ObjectDescription, directives
-from sphinx.util.nodes import make_refnode
-from sphinx.util.docfields import GroupedField, TypedField
-
-# The env.get_doctree() lookup results in a pickle.load() call which is
-# expensive enough to dominate the runtime entirely when the number of endpoints
-# and references is large enough. The doctrees are generated during the read-
-# phase and we can cache their lookup during the write-phase significantly
-# improving performance.
-# Currently sphinxcontrib-httpdomain does not declare to support parallel read
-# support (parallel_read_safe is the default False) so we can simply use a
-# module global to hold the cache.
-_doctree_cache = {}
-
-
-class DocRef(object):
- """Represents a reference to an abstract specification."""
-
- def __init__(self, base_url, anchor, section):
- self.base_url = base_url
- self.anchor = anchor
- self.section = section
-
- def __repr__(self):
- """Returns the URL onto related specification section for the related
- object."""
- return '{0}#{1}{2}'.format(self.base_url, self.anchor, self.section)
-
-
-class RFC2616Ref(DocRef):
- """Represents a reference to RFC2616.
- In 2014, RFC2616 was replaced by multiple RFCs (7230-7237)."""
-
- def __init__(self, section):
- url = 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec{0:d}.html'
- url = url.format(int(section))
- super(RFC2616Ref, self).__init__(url, 'sec', section)
-
-
-class IETFRef(DocRef):
- """Represents a reference to the specific IETF RFC."""
-
- def __init__(self, rfc, section):
- url = 'https://tools.ietf.org/html/rfc{0:d}'.format(rfc)
- super(IETFRef, self).__init__(url, 'section-', section)
-
-
-class EventSourceRef(DocRef):
-
- def __init__(self, section):
- url = 'http://www.w3.org/TR/eventsource/'
- super(EventSourceRef, self).__init__(url, section, '')
-
-
-class CORSRef(DocRef):
- """Represents a reference to W3 Cross-Origin Resource Sharing recommendation."""
-
- def __init__(self, name, type):
- url = 'http://www.w3.org/TR/cors/'
- super(CORSRef, self).__init__(url, name, '-' + type)
-
-
-#: Mapping from lowercase HTTP method name to :class:`DocRef` object which
-#: maintains the URL which points to the section of the RFC which defines that
-#: HTTP method.
-METHOD_REFS = {
- 'patch': IETFRef(5789, 2),
- 'options': IETFRef(7231, '4.3.7'),
- 'get': IETFRef(7231, '4.3.1'),
- 'head': IETFRef(7231, '4.3.2'),
- 'post': IETFRef(7231, '4.3.3'),
- 'put': IETFRef(7231, '4.3.4'),
- 'delete': IETFRef(7231, '4.3.5'),
- 'trace': IETFRef(7231, '4.3.8'),
- 'connect': IETFRef(7231, '4.3.6'),
- 'copy': IETFRef(2518, 8.8),
- 'any': ''
-}
-
-
-#: Mapping from HTTP header name to :class:`DocRef` object which
-#: maintains the URL which points to the related section of the RFC.
-HEADER_REFS = {
- 'Accept': IETFRef(7231, '5.3.2'),
- 'Accept-Charset': IETFRef(7231, '5.3.3'),
- 'Accept-Encoding': IETFRef(7231, '5.3.4'),
- 'Accept-Language': IETFRef(7231, '5.3.5'),
- 'Accept-Ranges': IETFRef(7233, 2.3),
- 'Age': IETFRef(7234, 5.1),
- 'Allow': IETFRef(7231, '7.4.1'),
- 'Authorization': IETFRef(7235, 4.2),
- 'Cache-Control': IETFRef(7234, 5.2),
- 'Connection': IETFRef(7230, 6.1),
- 'Content-Encoding': IETFRef(7231, '3.1.2.2'),
- 'Content-Language': IETFRef(7231, '3.1.3.2'),
- 'Content-Length': IETFRef(7230, '3.3.2'),
- 'Content-Location': IETFRef(7231, '3.1.4.2'),
- 'Content-MD5': RFC2616Ref(14.15), # removed
- 'Content-Range': IETFRef(7233, 4.2),
- 'Content-Type': IETFRef(7231, '3.1.1.5'),
- 'Cookie': IETFRef(2109, '4.3.4'), # also RFC6265 section 5.4
- 'Date': IETFRef(7231, '7.1.1.2'),
- 'Destination': IETFRef(2518, 9.3),
- 'ETag': IETFRef(7232, 2.3),
- 'Expect': IETFRef(7231, '5.1.1'),
- 'Expires': IETFRef(7234, 5.3),
- 'From': IETFRef(7231, '5.5.2'),
- 'Host': IETFRef(7230, 5.4),
- 'If-Match': IETFRef(7232, 3.1),
- 'If-Modified-Since': IETFRef(7232, 3.3),
- 'If-None-Match': IETFRef(7232, 3.2),
- 'If-Range': IETFRef(7233, 3.2),
- 'If-Unmodified-Since': IETFRef(7232, 3.4),
- 'Last-Event-ID': EventSourceRef('last-event-id'),
- 'Last-Modified': IETFRef(7232, 2.2),
- 'Link': IETFRef(5988, '5'),
- 'Location': IETFRef(7231, '7.1.2'),
- 'Max-Forwards': IETFRef(7231, '5.1.2'),
- 'Pragma': IETFRef(7234, 5.4),
- 'Proxy-Authenticate': IETFRef(7235, 4.3),
- 'Proxy-Authorization': IETFRef(7235, 4.4),
- 'Range': IETFRef(7233, 3.1),
- 'Referer': IETFRef(7231, '5.5.2'),
- 'Retry-After': IETFRef(7231, '7.1.3'),
- 'Server': IETFRef(7231, '7.4.2'),
- 'Set-Cookie': IETFRef(2109, '4.2.2'),
- 'TE': IETFRef(7230, 4.3),
- 'Trailer': IETFRef(7230, 4.4),
- 'Transfer-Encoding': IETFRef(7230, '3.3.1'),
- 'Upgrade': IETFRef(7230, 6.7),
- 'User-Agent': IETFRef(7231, '5.5.3'),
- 'Vary': IETFRef(7231, '7.1.4'),
- 'Via': IETFRef(7230, '5.7.1'),
- 'Warning': IETFRef(7234, 5.5),
- 'WWW-Authenticate': IETFRef(7235, 4.1),
- 'Access-Control-Allow-Origin': CORSRef('access-control-allow-origin',
- 'response-header'),
- 'Access-Control-Allow-Credentials': CORSRef('access-control-allow-credentials',
- 'response-header'),
- 'Access-Control-Expose-Headers': CORSRef('access-control-expose-headers',
- 'response-header'),
- 'Access-Control-Max-Age': CORSRef('access-control-max-age',
- 'response-header'),
- 'Access-Control-Allow-Methods': CORSRef('access-control-allow-methods',
- 'response-header'),
- 'Access-Control-Allow-Headers': CORSRef('access-control-allow-headers',
- 'response-header'),
- 'Origin': CORSRef('origin', 'request-header'),
- 'Access-Control-Request-Method': CORSRef('access-control-request-method',
- 'response-header'),
- 'Access-Control-Request-Headers': CORSRef('access-control-request-headers',
- 'response-header'),
-}
-
-
-HTTP_STATUS_CODES = {
- 100: 'Continue',
- 101: 'Switching Protocols',
- 102: 'Processing',
- 200: 'OK',
- 201: 'Created',
- 202: 'Accepted',
- 203: 'Non Authoritative Information',
- 204: 'No Content',
- 205: 'Reset Content',
- 206: 'Partial Content',
- 207: 'Multi Status',
- 226: 'IM Used', # see RFC 3229
- 300: 'Multiple Choices',
- 301: 'Moved Permanently',
- 302: 'Found',
- 303: 'See Other',
- 304: 'Not Modified',
- 305: 'Use Proxy',
- 307: 'Temporary Redirect',
- 400: 'Bad Request',
- 401: 'Unauthorized',
- 402: 'Payment Required', # unused
- 403: 'Forbidden',
- 404: 'Not Found',
- 405: 'Method Not Allowed',
- 406: 'Not Acceptable',
- 407: 'Proxy Authentication Required',
- 408: 'Request Timeout',
- 409: 'Conflict',
- 410: 'Gone',
- 411: 'Length Required',
- 412: 'Precondition Failed',
- 413: 'Request Entity Too Large',
- 414: 'Request URI Too Long',
- 415: 'Unsupported Media Type',
- 416: 'Requested Range Not Satisfiable',
- 417: 'Expectation Failed',
- 418: "I'm a teapot", # see RFC 2324
- 422: 'Unprocessable Entity',
- 423: 'Locked',
- 424: 'Failed Dependency',
- 426: 'Upgrade Required',
- 429: 'Too Many Requests',
- 449: 'Retry With', # proprietary MS extension
- 451: 'Unavailable For Legal Reasons',
- 500: 'Internal Server Error',
- 501: 'Not Implemented',
- 502: 'Bad Gateway',
- 503: 'Service Unavailable',
- 504: 'Gateway Timeout',
- 505: 'HTTP Version Not Supported',
- 507: 'Insufficient Storage',
- 510: 'Not Extended'
-}
-
-WEBDAV_STATUS_CODES = [207, 422, 423, 424, 507]
-
-http_sig_param_re = re.compile(r'\((?:(?P<type>[^:)]+):)?(?P<name>[\w_]+)\)',
- re.VERBOSE)
-
-
-def sort_by_method(entries):
- def cmp(item):
- order = ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH',
- 'OPTIONS', 'TRACE', 'CONNECT', 'COPY', 'ANY']
- method = item[0].split(' ', 1)[0]
- if method in order:
- return order.index(method)
- return 100
- return sorted(entries, key=cmp)
-
-
-def http_resource_anchor(method, path):
- path = re.sub(r'[{}]', '', re.sub(r'[<>:/]', '-', path))
- return method.lower() + '-' + path
-
-
-class HTTPResource(ObjectDescription):
-
- doc_field_types = [
- TypedField('parameter', label='Parameters',
- names=('param', 'parameter', 'arg', 'argument'),
- typerolename='obj', typenames=('paramtype', 'type')),
- TypedField('jsonparameter', label='JSON Parameters',
- names=('jsonparameter', 'jsonparam', 'json'),
- typerolename='obj', typenames=('jsonparamtype', 'jsontype')),
- TypedField('requestjsonobject', label='Request JSON Object',
- names=('reqjsonobj', 'reqjson', '<jsonobj', '<json'),
- typerolename='obj', typenames=('reqjsonobj', '<jsonobj')),
- TypedField('requestjsonarray', label='Request JSON Array of Objects',
- names=('reqjsonarr', '<jsonarr'),
- typerolename='obj',
- typenames=('reqjsonarrtype', '<jsonarrtype')),
- TypedField('responsejsonobject', label='Response JSON Object',
- names=('resjsonobj', 'resjson', '>jsonobj', '>json'),
- typerolename='obj', typenames=('resjsonobj', '>jsonobj')),
- TypedField('responsejsonarray', label='Response JSON Array of Objects',
- names=('resjsonarr', '>jsonarr'),
- typerolename='obj',
- typenames=('resjsonarrtype', '>jsonarrtype')),
- TypedField('queryparameter', label='Query Parameters',
- names=('queryparameter', 'queryparam', 'qparam', 'query'),
- typerolename='obj',
- typenames=('queryparamtype', 'querytype', 'qtype')),
- GroupedField('formparameter', label='Form Parameters',
- names=('formparameter', 'formparam', 'fparam', 'form')),
- GroupedField('requestheader', label='Request Headers',
- rolename='header',
- names=('<header', 'reqheader', 'requestheader')),
- GroupedField('responseheader', label='Response Headers',
- rolename='header',
- names=('>header', 'resheader', 'responseheader')),
- GroupedField('statuscode', label='Status Codes',
- rolename='statuscode',
- names=('statuscode', 'status', 'code'))
- ]
-
- option_spec = {
- 'deprecated': directives.flag,
- 'noindex': directives.flag,
- 'synopsis': lambda x: x,
- }
-
- method = NotImplemented
-
- def handle_signature(self, sig, signode):
- method = self.method.upper() + ' '
- signode += addnodes.desc_name(method, method)
- offset = 0
- path = None
- for match in http_sig_param_re.finditer(sig):
- path = sig[offset:match.start()]
- signode += addnodes.desc_name(path, path)
- params = addnodes.desc_parameterlist()
- typ = match.group('type')
- if typ:
- typ += ': '
- params += addnodes.desc_annotation(typ, typ)
- name = match.group('name')
- params += addnodes.desc_parameter(name, name)
- signode += params
- offset = match.end()
- if offset < len(sig):
- path = sig[offset:len(sig)]
- signode += addnodes.desc_name(path, path)
- assert path is not None, 'no matches for sig: %s' % sig
- fullname = self.method.upper() + ' ' + path
- signode['method'] = self.method
- signode['path'] = sig
- signode['fullname'] = fullname
- return (fullname, self.method, sig)
-
- def needs_arglist(self):
- return False
-
- def add_target_and_index(self, name_cls, sig, signode):
- signode['ids'].append(http_resource_anchor(*name_cls[1:]))
- if 'noindex' not in self.options:
- self.env.domaindata['http'][self.method][sig] = (
- self.env.docname,
- self.options.get('synopsis', ''),
- 'deprecated' in self.options)
-
- def get_index_text(self, modname, name):
- return ''
-
-
-class HTTPOptions(HTTPResource):
-
- method = 'options'
-
-
-class HTTPHead(HTTPResource):
-
- method = 'head'
-
-
-class HTTPPatch(HTTPResource):
-
- method = 'patch'
-
-
-class HTTPPost(HTTPResource):
-
- method = 'post'
-
-
-class HTTPGet(HTTPResource):
-
- method = 'get'
-
-
-class HTTPPut(HTTPResource):
-
- method = 'put'
-
-
-class HTTPDelete(HTTPResource):
-
- method = 'delete'
-
-
-class HTTPTrace(HTTPResource):
-
- method = 'trace'
-
-
-class HTTPConnect(HTTPResource):
-
- method = 'connect'
-
-
-class HTTPCopy(HTTPResource):
-
- method = 'copy'
-
-
-class HTTPAny(HTTPResource):
-
- method = 'any'
-
-
-class HTTPXRefRole(XRefRole):
-
- def __init__(self, method, **kwargs):
- XRefRole.__init__(self, **kwargs)
- self.method = method
-
- def process_link(self, env, refnode, has_explicit_title, title, target):
- if not has_explicit_title:
- title = self.method.upper() + ' ' + title
- return title, target
-
-
-class HTTPXRefMethodRole(XRefRole):
-
- def result_nodes(self, document, env, node, is_ref):
- method = node[0][0].lower()
- rawsource = node[0].rawsource
- config = env.domains['http'].env.config
- if method not in METHOD_REFS:
- if not config['http_strict_mode']:
- return [nodes.emphasis(method, method)], []
- reporter = document.reporter
- msg = reporter.error('%s is not valid HTTP method' % method,
- line=node.line)
- prb = nodes.problematic(method, method)
- return [prb], [msg]
- url = str(METHOD_REFS[method])
- if not url:
- return [nodes.emphasis(method, method)], []
- node = nodes.reference(rawsource, method.upper(), refuri=url)
- return [node], []
-
-
-class HTTPXRefStatusRole(XRefRole):
-
- def result_nodes(self, document, env, node, is_ref):
- def get_code_status(text):
- if text.isdigit():
- code = int(text)
- return code, HTTP_STATUS_CODES.get(code)
- else:
- try:
- code, status = re.split(r'\s', text.strip(), 1)
- code = int(code)
- except ValueError:
- return None, None
- known_status = HTTP_STATUS_CODES.get(code)
- if known_status is None:
- return code, None
- elif known_status.lower() != status.lower():
- return code, None
- else:
- return code, status
-
- def report_unknown_code():
- if not config['http_strict_mode']:
- return [nodes.emphasis(text, text)], []
- reporter = document.reporter
- msg = reporter.error('%d is unknown HTTP status code' % code,
- line=node.line)
- prb = nodes.problematic(text, text)
- return [prb], [msg]
-
- def report_invalid_code():
- if not config['http_strict_mode']:
- return [nodes.emphasis(text, text)], []
- reporter = document.reporter
- msg = reporter.error(
- 'HTTP status code must be an integer (e.g. `200`) or '
- 'start with an integer (e.g. `200 OK`); %r is invalid' %
- text,
- line=node.line
- )
- prb = nodes.problematic(text, text)
- return [prb], [msg]
-
- text = node[0][0]
- rawsource = node[0].rawsource
- config = env.domains['http'].env.config
-
- code, status = get_code_status(text)
- if code is None:
- return report_invalid_code()
- elif status is None:
- return report_unknown_code()
- elif code == 226:
- url = 'http://www.ietf.org/rfc/rfc3229.txt'
- elif code == 418:
- url = 'http://www.ietf.org/rfc/rfc2324.txt'
- elif code == 429:
- url = 'http://tools.ietf.org/html/rfc6585#section-4'
- elif code == 449:
- url = 'http://msdn.microsoft.com/en-us/library/dd891478(v=prot.10).aspx'
- elif code == 451:
- url = 'http://www.ietf.org/rfc/rfc7725.txt'
- elif code in WEBDAV_STATUS_CODES:
- url = 'http://tools.ietf.org/html/rfc4918#section-11.%d' % (WEBDAV_STATUS_CODES.index(code) + 1)
- elif code in HTTP_STATUS_CODES:
- url = 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html' \
- '#sec10.' + ('%d.%d' % (code // 100, 1 + code % 100))
- else:
- url = ''
- node = nodes.reference(rawsource, '%d %s' % (code, status), refuri=url)
- return [node], []
-
-
-class HTTPXRefHeaderRole(XRefRole):
-
- def result_nodes(self, document, env, node, is_ref):
- header = node[0][0]
- rawsource = node[0].rawsource
- if header not in HEADER_REFS:
- _header = '-'.join(map(lambda i: i.title(), header.split('-')))
- if _header not in HEADER_REFS:
- return [nodes.emphasis(header, header)], []
- url = str(HEADER_REFS[header])
- node = nodes.reference(rawsource, header, refuri=url)
- return [node], []
-
-
-class HTTPIndex(Index):
-
- name = 'routingtable'
- localname = 'HTTP Routing Table'
- shortname = 'routing table'
-
- def __init__(self, *args, **kwargs):
- super(HTTPIndex, self).__init__(*args, **kwargs)
-
- self.ignore = [
- [l for l in x.split('/') if l]
- for x in self.domain.env.config['http_index_ignore_prefixes']]
- self.ignore.sort(reverse=True)
-
- # During HTML generation these values pick from class,
- # not from instance so we have a little hack the system
- cls = self.__class__
- cls.shortname = self.domain.env.config['http_index_shortname']
- cls.localname = self.domain.env.config['http_index_localname']
-
- def grouping_prefix(self, path):
- letters = [x for x in path.split('/') if x]
- for prefix in self.ignore:
- if letters[:len(prefix)] == prefix:
- return '/' + '/'.join(letters[:len(prefix) + 1])
- return '/%s' % (letters[0] if letters else '',)
-
- def generate(self, docnames=None):
- content = {}
- items = ((method, path, info)
- for method, routes in self.domain.routes.items()
- for path, info in routes.items())
- items = sorted(items, key=lambda item: item[1])
- for method, path, info in items:
- entries = content.setdefault(self.grouping_prefix(path), [])
- entries.append([
- method.upper() + ' ' + path, 0, info[0],
- http_resource_anchor(method, path),
- '', 'Deprecated' if info[2] else '', info[1]
- ])
- items = sorted(
- (path, sort_by_method(entries))
- for path, entries in content.items()
- )
- return (items, True)
-
-
-class HTTPDomain(Domain):
- """HTTP domain."""
-
- name = 'http'
- label = 'HTTP'
-
- object_types = {
- 'options': ObjType('options', 'options', 'obj'),
- 'head': ObjType('head', 'head', 'obj'),
- 'post': ObjType('post', 'post', 'obj'),
- 'get': ObjType('get', 'get', 'obj'),
- 'put': ObjType('put', 'put', 'obj'),
- 'patch': ObjType('patch', 'patch', 'obj'),
- 'delete': ObjType('delete', 'delete', 'obj'),
- 'trace': ObjType('trace', 'trace', 'obj'),
- 'connect': ObjType('connect', 'connect', 'obj'),
- 'copy': ObjType('copy', 'copy', 'obj'),
- 'any': ObjType('any', 'any', 'obj')
- }
-
- directives = {
- 'options': HTTPOptions,
- 'head': HTTPHead,
- 'post': HTTPPost,
- 'get': HTTPGet,
- 'put': HTTPPut,
- 'patch': HTTPPatch,
- 'delete': HTTPDelete,
- 'trace': HTTPTrace,
- 'connect': HTTPConnect,
- 'copy': HTTPCopy,
- 'any': HTTPAny
- }
-
- roles = {
- 'options': HTTPXRefRole('options'),
- 'head': HTTPXRefRole('head'),
- 'post': HTTPXRefRole('post'),
- 'get': HTTPXRefRole('get'),
- 'put': HTTPXRefRole('put'),
- 'patch': HTTPXRefRole('patch'),
- 'delete': HTTPXRefRole('delete'),
- 'trace': HTTPXRefRole('trace'),
- 'connect': HTTPXRefRole('connect'),
- 'copy': HTTPXRefRole('copy'),
- 'any': HTTPXRefRole('any'),
- 'statuscode': HTTPXRefStatusRole(),
- 'method': HTTPXRefMethodRole(),
- 'header': HTTPXRefHeaderRole()
- }
-
- initial_data = {
- 'options': {}, # path: (docname, synopsis)
- 'head': {},
- 'post': {},
- 'get': {},
- 'put': {},
- 'patch': {},
- 'delete': {},
- 'trace': {},
- 'connect': {},
- 'copy': {},
- 'any': {}
- }
-
- indices = [HTTPIndex]
-
- @property
- def routes(self):
- return dict((key, self.data[key]) for key in self.object_types)
-
- def clear_doc(self, docname):
- for typ, routes in self.routes.items():
- for path, info in list(routes.items()):
- if info[0] == docname:
- del routes[path]
-
- def resolve_xref(self, env, fromdocname, builder, typ, target,
- node, contnode):
- try:
- info = self.data[str(typ)][target]
- except KeyError:
- text = contnode.rawsource
- role = self.roles.get(typ)
- if role is None:
- return None
-
- if fromdocname not in _doctree_cache:
- _doctree_cache[fromdocname] = env.get_doctree(fromdocname)
- doctree = _doctree_cache[fromdocname]
-
- resnode = role.result_nodes(doctree, env, node, None)[0][0]
- if isinstance(resnode, addnodes.pending_xref):
- text = node[0][0]
- reporter = doctree.reporter
- reporter.warning('Cannot resolve reference to %r' % text,
- line=node.line)
- return None
- return resnode
- else:
- anchor = http_resource_anchor(typ, target)
- title = typ.upper() + ' ' + target
- return make_refnode(builder, fromdocname, info[0], anchor,
- contnode, title)
-
- def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
- """Resolve the pending_xref *node* with the given *target*.
-
- The reference comes from an "any" or similar role, which means that Sphinx
- don't know the type.
-
- For now sphinxcontrib-httpdomain doesn't resolve any xref nodes.
-
- :return:
- list of tuples ``('domain:role', newnode)``, where ``'domain:role'``
- is the name of a role that could have created the same reference,
- """
- return []
-
- def get_objects(self):
- for method, routes in self.routes.items():
- for path, info in routes.items():
- anchor = http_resource_anchor(method, path)
- yield (path, path, method, info[0], anchor, 1)
-
-
-class HTTPLexer(RegexLexer):
- """Lexer for HTTP sessions."""
-
- name = 'HTTP'
- aliases = ['http']
-
- flags = re.DOTALL
-
- def header_callback(self, match):
- if match.group(1).lower() == 'content-type':
- content_type = match.group(5).strip()
- if ';' in content_type:
- content_type = content_type[:content_type.find(';')].strip()
- self.content_type = content_type
- yield match.start(1), Name.Attribute, match.group(1)
- yield match.start(2), Text, match.group(2)
- yield match.start(3), Operator, match.group(3)
- yield match.start(4), Text, match.group(4)
- yield match.start(5), Literal, match.group(5)
- yield match.start(6), Text, match.group(6)
-
- def continuous_header_callback(self, match):
- yield match.start(1), Text, match.group(1)
- yield match.start(2), Literal, match.group(2)
- yield match.start(3), Text, match.group(3)
-
- def content_callback(self, match):
- content_type = getattr(self, 'content_type', None)
- content = match.group()
- offset = match.start()
- if content_type:
- from pygments.lexers import get_lexer_for_mimetype
- try:
- lexer = get_lexer_for_mimetype(content_type)
- except ClassNotFound:
- pass
- else:
- for idx, token, value in lexer.get_tokens_unprocessed(content):
- yield offset + idx, token, value
- return
- yield offset, Text, content
-
- tokens = {
- 'root': [
- (r'(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS|TRACE|COPY)( +)([^ ]+)( +)'
- r'(HTTPS?)(/)(1\.[01])(\r?\n|$)',
- bygroups(Name.Function, Text, Name.Namespace, Text,
- Keyword.Reserved, Operator, Number, Text),
- 'headers'),
- (r'(HTTPS?)(/)(1\.[01])( +)(\d{3})( +)([^\r\n]+)(\r?\n|$)',
- bygroups(Keyword.Reserved, Operator, Number, Text, Number,
- Text, Name.Exception, Text),
- 'headers'),
- ],
- 'headers': [
- (r'([^\s:]+)( *)(:)( *)([^\r\n]+)(\r?\n|$)', header_callback),
- (r'([\t ]+)([^\r\n]+)(\r?\n|$)', continuous_header_callback),
- (r'\r?\n', Text, 'content')
- ],
- 'content': [
- (r'.+', content_callback)
- ]
- }
-
-
-def setup(app):
- app.add_domain(HTTPDomain)
-
- try:
- get_lexer_by_name('http')
- except ClassNotFound:
- app.add_lexer('http', HTTPLexer())
- app.add_config_value('http_index_ignore_prefixes', [], None)
- app.add_config_value('http_index_shortname', 'routing table', True)
- app.add_config_value('http_index_localname', 'HTTP Routing Table', True)
- app.add_config_value('http_strict_mode', True, None)
- app.add_config_value('http_headers_ignore_prefixes', ['X-'], None)
diff --git a/exts/tslex.py b/exts/tslex.py
deleted file mode 100644
index 2be6f29f..00000000
--- a/exts/tslex.py
+++ /dev/null
@@ -1,88 +0,0 @@
-from pygments.token import *
-from pygments.lexer import RegexLexer, ExtendedRegexLexer, bygroups, using, \
- include, this
-import re
-
-class BetterTypeScriptLexer(RegexLexer):
- """
- For `TypeScript <https://www.typescriptlang.org/>`_ source code.
- """
-
- name = 'TypeScript'
- aliases = ['ts']
- filenames = ['*.ts']
- mimetypes = ['text/x-typescript']
-
- flags = re.DOTALL
- tokens = {
- 'commentsandwhitespace': [
- (r'\s+', Text),
- (r'<!--', Comment),
- (r'//.*?\n', Comment.Single),
- (r'/\*.*?\*/', Comment.Multiline)
- ],
- 'slashstartsregex': [
- include('commentsandwhitespace'),
- (r'/(\\.|[^[/\\\n]|\[(\\.|[^\]\\\n])*])+/'
- r'([gim]+\b|\B)', String.Regex, '#pop'),
- (r'(?=/)', Text, ('#pop', 'badregex')),
- (r'', Text, '#pop')
- ],
- 'badregex': [
- (r'\n', Text, '#pop')
- ],
- 'typeexp': [
- (r'[a-zA-Z]+', Keyword.Type),
- (r'\s+', Text),
- (r'[|]', Text),
- (r'\n', Text, "#pop"),
- (r';', Text, "#pop"),
- (r'', Text, "#pop"),
- ],
- 'root': [
- (r'^(?=\s|/|<!--)', Text, 'slashstartsregex'),
- include('commentsandwhitespace'),
- (r'\+\+|--|~|&&|\?|:|\|\||\\(?=\n)|'
- r'(<<|>>>?|==?|!=?|[-<>+*%&\|\^/])=?', Operator, 'slashstartsregex'),
- (r'[{(\[;,]', Punctuation, 'slashstartsregex'),
- (r'[})\].]', Punctuation),
- (r'(for|in|while|do|break|return|continue|switch|case|default|if|else|'
- r'throw|try|catch|finally|new|delete|typeof|instanceof|void|'
- r'this)\b', Keyword, 'slashstartsregex'),
- (r'(var|let|const|with|function)\b', Keyword.Declaration, 'slashstartsregex'),
- (r'(abstract|boolean|byte|char|class|const|debugger|double|enum|export|'
- r'extends|final|float|goto|implements|import|int|interface|long|native|'
- r'package|private|protected|public|short|static|super|synchronized|throws|'
- r'transient|volatile)\b', Keyword.Reserved),
- (r'(true|false|null|NaN|Infinity|undefined)\b', Keyword.Constant),
- (r'(Array|Boolean|Date|Error|Function|Math|netscape|'
- r'Number|Object|Packages|RegExp|String|sun|decodeURI|'
- r'decodeURIComponent|encodeURI|encodeURIComponent|'
- r'Error|eval|isFinite|isNaN|parseFloat|parseInt|document|this|'
- r'window)\b', Name.Builtin),
- # Match stuff like: module name {...}
- (r'\b(module)(\s*)(\s*[a-zA-Z0-9_?.$][\w?.$]*)(\s*)',
- bygroups(Keyword.Reserved, Text, Name.Other, Text), 'slashstartsregex'),
- # Match variable type keywords
- (r'\b(string|bool|number)\b', Keyword.Type),
- # Match stuff like: constructor
- (r'\b(constructor|declare|interface|as|AS)\b', Keyword.Reserved),
- # Match stuff like: super(argument, list)
- (r'(super)(\s*)\(([a-zA-Z0-9,_?.$\s]+\s*)\)',
- bygroups(Keyword.Reserved, Text), 'slashstartsregex'),
- # Match stuff like: function() {...}
- (r'([a-zA-Z_?.$][\w?.$]*)\(\) \{', Name.Other, 'slashstartsregex'),
- # Match stuff like: (function: return type)
- (r'([a-zA-Z0-9_?.$][\w?.$]*)(\s*:\s*)([a-zA-Z0-9_?.$][\w?.$]*)',
- bygroups(Name.Other, Text, Keyword.Type)),
- # Match stuff like: type Foo = Bar | Baz
- (r'\b(type)(\s*)([a-zA-Z0-9_?.$]+)(\s*)(=)(\s*)',
- bygroups(Keyword.Reserved, Text, Name.Other, Text, Operator, Text), 'typeexp'),
- (r'[$a-zA-Z_][a-zA-Z0-9_]*', Name.Other),
- (r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', Number.Float),
- (r'0x[0-9a-fA-F]+', Number.Hex),
- (r'[0-9]+', Number.Integer),
- (r'"(\\\\|\\"|[^"])*"', String.Double),
- (r"'(\\\\|\\'|[^'])*'", String.Single),
- ]
- }
diff --git a/exts/tsref.py b/exts/tsref.py
deleted file mode 100644
index ae108324..00000000
--- a/exts/tsref.py
+++ /dev/null
@@ -1,233 +0,0 @@
-"""
- This file is part of GNU TALER.
- Copyright (C) 2014, 2015 GNUnet e.V. and INRIA
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser General Public License as published by the Free Software
- Foundation; either version 2.1, or (at your option) any later version.
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-
- @author Florian Dold
-"""
-
-"""
-This extension adds a new lexer "tsref" for TypeScript, which
-allows reST-style links inside comments (`LinkName`_),
-and semi-automatically adds links to the definition of types.
-
-For type TYPE, a reference to tsref-type-TYPE is added.
-
-Known bugs and limitations:
- - The way the extension works right now interferes wiht
- Sphinx's caching, the build directory should be cleared
- before every build.
-"""
-
-
-from pygments.util import get_bool_opt
-from pygments.token import Name, Comment, Token, _TokenType
-from pygments.filter import Filter
-from sphinx.highlighting import PygmentsBridge
-from sphinx.builders.html import StandaloneHTMLBuilder
-from sphinx.pygments_styles import SphinxStyle
-from pygments.formatters import HtmlFormatter
-from docutils import nodes
-from docutils.nodes import make_id
-import re
-
-
-_escape_html_table = {
- ord('&'): u'&amp;',
- ord('<'): u'&lt;',
- ord('>'): u'&gt;',
- ord('"'): u'&quot;',
- ord("'"): u'&#39;',
-}
-
-
-class LinkingHtmlFormatter(HtmlFormatter):
- def __init__(self, **kwargs):
- super(LinkingHtmlFormatter, self).__init__(**kwargs)
- self._builder = kwargs['_builder']
-
- def _fmt(self, value, tok):
- cls = self._get_css_class(tok)
- href = tok_getprop(tok, "href")
- caption = tok_getprop(tok, "caption")
- content = caption if caption is not None else value
- if href:
- value = '<a style="color:inherit;text-decoration:underline" href="%s">%s</a>' % (href, content)
- if cls is None or cls == "":
- return value
- return '<span class="%s">%s</span>' % (cls, value)
-
- def _format_lines(self, tokensource):
- """
- Just format the tokens, without any wrapping tags.
- Yield individual lines.
- """
- lsep = self.lineseparator
- escape_table = _escape_html_table
-
- line = ''
- for ttype, value in tokensource:
- link = get_annotation(ttype, "link")
-
- parts = value.translate(escape_table).split('\n')
-
- if len(parts) == 0:
- # empty token, usually should not happen
- pass
- elif len(parts) == 1:
- # no newline before or after token
- line += self._fmt(parts[0], ttype)
- else:
- line += self._fmt(parts[0], ttype)
- yield 1, line + lsep
- for part in parts[1:-1]:
- yield 1, self._fmt(part, ttype) + lsep
- line = self._fmt(parts[-1], ttype)
-
- if line:
- yield 1, line + lsep
-
-
-class MyPygmentsBridge(PygmentsBridge):
- def __init__(self, builder, trim_doctest_flags):
- self.dest = "html"
- self.trim_doctest_flags = trim_doctest_flags
- self.formatter_args = {'style': SphinxStyle, '_builder': builder}
- self.formatter = LinkingHtmlFormatter
-
-
-class MyHtmlBuilder(StandaloneHTMLBuilder):
- name = "html-linked"
- def init_highlighter(self):
- if self.config.pygments_style is not None:
- style = self.config.pygments_style
- elif self.theme:
- style = self.theme.get_confstr('theme', 'pygments_style', 'none')
- else:
- style = 'sphinx'
- self.highlighter = MyPygmentsBridge(self, self.config.trim_doctest_flags)
-
- def write_doc(self, docname, doctree):
- self._current_docname = docname
- super(MyHtmlBuilder, self).write_doc(docname, doctree)
-
-
-def get_annotation(tok, key):
- if not hasattr(tok, "kv"):
- return None
- return tok.kv.get(key)
-
-
-def copy_token(tok):
- new_tok = _TokenType(tok)
- # This part is very fragile against API changes ...
- new_tok.subtypes = set(tok.subtypes)
- new_tok.parent = tok.parent
- return new_tok
-
-
-def tok_setprop(tok, key, value):
- tokid = id(tok)
- e = token_props.get(tokid)
- if e is None:
- e = token_props[tokid] = (tok, {})
- _, kv = e
- kv[key] = value
-
-
-def tok_getprop(tok, key):
- tokid = id(tok)
- e = token_props.get(tokid)
- if e is None:
- return None
- _, kv = e
- return kv.get(key)
-
-
-link_reg = re.compile(r"`([^`<]+)\s*(?:<([^>]+)>)?\s*`_")
-
-# Map from token id to props.
-# Properties can't be added to tokens
-# since they derive from Python's tuple.
-token_props = {}
-
-
-class LinkFilter(Filter):
- def __init__(self, app, **options):
- self.app = app
- Filter.__init__(self, **options)
-
- def filter(self, lexer, stream):
- id_to_doc = self.app.env.domaindata.get("_tsref", {})
- for ttype, value in stream:
- if ttype in Token.Keyword.Type:
- defname = make_id('tsref-type-' + value);
- t = copy_token(ttype)
- if defname in id_to_doc:
- docname = id_to_doc[defname]
- href = self.app.builder.get_target_uri(docname) + "#" + defname
- tok_setprop(t, "href", href)
-
- yield t, value
- elif ttype in Token.Comment:
- last = 0
- for m in re.finditer(link_reg, value):
- pre = value[last:m.start()]
- if pre:
- yield ttype, pre
- t = copy_token(ttype)
- x1, x2 = m.groups()
- if x2 is None:
- caption = x1.strip()
- id = make_id(x1)
- else:
- caption = x1.strip()
- id = make_id(x2)
- if id in id_to_doc:
- docname = id_to_doc[id]
- href = self.app.builder.get_target_uri(docname) + "#" + id
- tok_setprop(t, "href", href)
- tok_setprop(t, "caption", caption)
- else:
- self.app.builder.warn("unresolved link target in comment: " + id)
- yield t, m.group(1)
- last = m.end()
- post = value[last:]
- if post:
- yield ttype, post
- else:
- yield ttype, value
-
-
-
-def remember_targets(app, doctree):
- docname = app.env.docname
- id_to_doc = app.env.domaindata.get("_tsref", None)
- if id_to_doc is None:
- id_to_doc = app.env.domaindata["_tsref"] = {}
- for node in doctree.traverse():
- if not isinstance(node, nodes.Element):
- continue
- ids = node.get("ids")
- if ids:
- for id in ids:
- id_to_doc[id] = docname
-
-
-def setup(app):
- from sphinx.highlighting import lexers
- from pygments.token import Name
- from pygments.filters import NameHighlightFilter
- from tslex import BetterTypeScriptLexer
- lexer = BetterTypeScriptLexer()
- lexer.add_filter(LinkFilter(app))
- app.add_lexer('tsref', lexer)
- app.add_builder(MyHtmlBuilder)
- app.connect("doctree-read", remember_targets)