sphinxcontrib-httpdomain-1.3.0/0000755000076500000240000000000012366220063017117 5ustar dahliastaff00000000000000sphinxcontrib-httpdomain-1.3.0/LICENSE0000644000076500000240000000261212316036450020125 0ustar dahliastaff00000000000000If not otherwise noted, the extensions in this package are licensed under the following license. Copyright (c) 2010 by the contributors (see AUTHORS file). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. sphinxcontrib-httpdomain-1.3.0/MANIFEST.in0000644000076500000240000000006112316036450020652 0ustar dahliastaff00000000000000include README include LICENSE include CHANGES.* sphinxcontrib-httpdomain-1.3.0/PKG-INFO0000644000076500000240000000170612366220063020220 0ustar dahliastaff00000000000000Metadata-Version: 1.1 Name: sphinxcontrib-httpdomain Version: 1.3.0 Summary: Sphinx domain for HTTP APIs Home-page: http://bitbucket.org/birkenfeld/sphinx-contrib Author: Hong Minhee Author-email: minhee@dahlia.kr License: BSD Download-URL: http://pypi.python.org/pypi/sphinxcontrib-httpdomain Description: This contrib extension, sphinxcontrib.httpdomain provides a Sphinx domain for describing RESTful HTTP APIs. You can find the documentation from the following URL: http://pythonhosted.org/sphinxcontrib-httpdomain/ Platform: any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Console Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Documentation Classifier: Topic :: Utilities sphinxcontrib-httpdomain-1.3.0/README.rst0000644000076500000240000000051712316036450020611 0ustar dahliastaff00000000000000sphinxcontrib.httpdomain --- Documenting RESTful HTTP APIs ========================================================== This contrib extension, sphinxcontrib.httpdomain, provides a Sphinx domain for describing RESTful HTTP APIs. You can find the documentation from the following URL: http://pythonhosted.org/sphinxcontrib-httpdomain/ sphinxcontrib-httpdomain-1.3.0/setup.cfg0000644000076500000240000000034212366220063020737 0ustar dahliastaff00000000000000[aliases] upload_docs = build_sphinx upload_docs [bdist_wheel] universal = 1 [upload_docs] repository = https://pypi.python.org/pypi upload_dir = build/sphinx/html [egg_info] tag_svn_revision = 0 tag_build = tag_date = 0 sphinxcontrib-httpdomain-1.3.0/setup.py0000644000076500000240000000237312366217126020644 0ustar dahliastaff00000000000000# -*- coding: utf-8 -*- from setuptools import setup, find_packages long_desc = ''' This contrib extension, sphinxcontrib.httpdomain provides a Sphinx domain for describing RESTful HTTP APIs. You can find the documentation from the following URL: http://pythonhosted.org/sphinxcontrib-httpdomain/ ''' requires = [ 'Sphinx >= 1.0', 'six' ] setup( name='sphinxcontrib-httpdomain', version='1.3.0', url='http://bitbucket.org/birkenfeld/sphinx-contrib', download_url='http://pypi.python.org/pypi/sphinxcontrib-httpdomain', license='BSD', author='Hong Minhee', author_email='minhee@dahlia.kr', description='Sphinx domain for HTTP APIs', long_description=long_desc, zip_safe=False, classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Console', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Topic :: Documentation', 'Topic :: Utilities', ], platforms='any', packages=find_packages(), include_package_data=True, install_requires=requires, namespace_packages=['sphinxcontrib'], ) sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/0000755000076500000240000000000012366220063022011 5ustar dahliastaff00000000000000sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/__init__.py0000644000076500000240000000055612316036450024130 0ustar dahliastaff00000000000000# -*- 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__) sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/autohttp/0000755000076500000240000000000012366220063023661 5ustar dahliastaff00000000000000sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/autohttp/__init__.py0000644000076500000240000000037112316036450025773 0ustar dahliastaff00000000000000""" 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. """ sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/autohttp/bottle.py0000644000076500000240000000707012366217115025534 0ustar dahliastaff00000000000000""" 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, '') 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) sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/autohttp/common.py0000644000076500000240000000163612366217115025535 0ustar dahliastaff00000000000000""" 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 '' yield '.. http:{method}:: {path}'.format(**locals()) yield '' for line in content: yield ' ' + line yield '' sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/autohttp/flask.py0000644000076500000240000001157312366217115025346 0ustar dahliastaff00000000000000""" 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 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): for rule in app.url_map.iter_rules(): methods = rule.methods.difference(['OPTIONS', 'HEAD']) for method in methods: path = translate_werkzeug_rule(rule.rule) yield method, path, rule.endpoint class AutoflaskDirective(Directive): has_content = True required_arguments = 1 option_spec = {'endpoints': directives.unchanged, 'blueprints': directives.unchanged, 'undoc-endpoints': directives.unchanged, 'undoc-blueprints': 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 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)) @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)) def make_rst(self): app = import_object(self.arguments[0]) for method, path, endpoint in get_routes(app): 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 self.endpoints and endpoint not in self.endpoints: continue 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 path == static_url_path + '/(path:filename)'): continue view = app.view_functions[endpoint] 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) 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, '') 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) sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/autohttp/tornado.py0000644000076500000240000000776312366217115025722 0ustar dahliastaff00000000000000""" 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, '') 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) sphinxcontrib-httpdomain-1.3.0/sphinxcontrib/httpdomain.py0000644000076500000240000005400412366217115024541 0ustar dahliastaff00000000000000""" 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 docutils.parsers.rst.roles import set_classes 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 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.""" 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 = 'http://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, '') #: 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': RFC2616Ref(9.2), 'get': RFC2616Ref(9.3), 'head': RFC2616Ref(9.4), 'post': RFC2616Ref(9.5), 'put': RFC2616Ref(9.6), 'delete': RFC2616Ref(9.7), 'trace': RFC2616Ref(9.8), 'connect': RFC2616Ref(9.9), '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': RFC2616Ref(14.1), 'Accept-Charset': RFC2616Ref(14.2), 'Accept-Encoding': RFC2616Ref(14.3), 'Accept-Language': RFC2616Ref(14.4), 'Accept-Ranges': RFC2616Ref(14.5), 'Age': RFC2616Ref(14.6), 'Allow': RFC2616Ref(14.7), 'Authorization': RFC2616Ref(14.8), 'Cache-Control': RFC2616Ref(14.9), 'Connection': RFC2616Ref(14.10), 'Content-Encoding': RFC2616Ref(14.11), 'Content-Language': RFC2616Ref(14.12), 'Content-Length': RFC2616Ref(14.13), 'Content-Location': RFC2616Ref(14.14), 'Content-MD5': RFC2616Ref(14.15), 'Content-Range': RFC2616Ref(14.16), 'Content-Type': RFC2616Ref(14.17), 'Cookie': IETFRef(2109, '4.3.4'), 'Date': RFC2616Ref(14.18), 'Destination': IETFRef(2518, 9.3), 'ETag': RFC2616Ref(14.19), 'Expect': RFC2616Ref(14.20), 'Expires': RFC2616Ref(14.21), 'From': RFC2616Ref(14.22), 'Host': RFC2616Ref(14.23), 'If-Match': RFC2616Ref(14.24), 'If-Modified-Since': RFC2616Ref(14.25), 'If-None-Match': RFC2616Ref(14.26), 'If-Range': RFC2616Ref(14.27), 'If-Unmodified-Since': RFC2616Ref(14.28), 'Last-Event-ID': EventSourceRef('last-event-id'), 'Last-Modified': RFC2616Ref(14.29), 'Location': RFC2616Ref(14.30), 'Max-Forwards': RFC2616Ref(14.31), 'Pragma': RFC2616Ref(14.32), 'Proxy-Authenticate': RFC2616Ref(14.33), 'Proxy-Authorization': RFC2616Ref(14.34), 'Range': RFC2616Ref(14.35), 'Referer': RFC2616Ref(14.36), 'Retry-After': RFC2616Ref(14.37), 'Server': RFC2616Ref(14.38), 'Set-Cookie': IETFRef(2109, '4.2.2'), 'TE': RFC2616Ref(14.39), 'Trailer': RFC2616Ref(14.40), 'Transfer-Encoding': RFC2616Ref(14.41), 'Upgrade': RFC2616Ref(14.42), 'User-Agent': RFC2616Ref(14.43), 'Vary': RFC2616Ref(14.44), 'Via': RFC2616Ref(14.45), 'Warning': RFC2616Ref(14.46), 'WWW-Authenticate': RFC2616Ref(14.47) } 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', 449: 'Retry With', # proprietary MS extension 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' } http_sig_param_re = re.compile(r'\((?:(?P[^:)]+):)?(?P[\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=('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='mailheader', 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' def http_statuscode_role(name, rawtext, text, lineno, inliner, options=None, content=None): if options is None: options = {} if content is None: content = [] if text.isdigit(): code = int(text) try: status = HTTP_STATUS_CODES[code] except KeyError: msg = inliner.reporter.error('%d is invalid HTTP status code' % code, lineno=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] else: try: code, status = re.split(r'\s', text.strip(), 1) code = int(code) except ValueError: msg = inliner.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=lineno ) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] nodes.reference(rawtext) if code == 226: url = 'http://www.ietf.org/rfc/rfc3229.txt' elif code == 418: url = 'http://www.ietf.org/rfc/rfc2324.txt' elif code == 449: url = 'http://msdn.microsoft.com/en-us/library/dd891478(v=prot.10).aspx' 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 = '' set_classes(options) node = nodes.reference(rawtext, '%d %s' % (code, status), refuri=url, **options) return [node], [] def http_method_role(name, rawtext, text, lineno, inliner, options=None, content=None): if options is None: options = {} if content is None: content = [] method = str(text).lower() if method not in METHOD_REFS: msg = inliner.reporter.error('%s is not valid HTTP method' % method, lineno=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] url = str(METHOD_REFS[method]) if not url: return [nodes.emphasis(text, text)], [] node = nodes.reference(rawtext, method.upper(), refuri=url, **options) return [node], [] def http_header_role(name, rawtext, text, lineno, inliner, options=None, content=None): if options is None: options = {} if content is None: content = [] header = str(text) if header not in HEADER_REFS: header = header.title() if header not in HEADER_REFS: if header.startswith('X-'): # skip custom headers return [nodes.strong(header, header)], [] msg = inliner.reporter.error('%s is not unknown HTTP header' % header, lineno=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] url = str(HEADER_REFS[header]) node = nodes.reference(rawtext, header, refuri=url, **options) return [node], [] 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 target.startswith('/'): pass if not has_explicit_title: title = self.method.upper() + ' ' + title return title, target 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': http_statuscode_role, 'method': http_method_role, 'header': http_header_role } 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 if typ == 'statuscode': return http_statuscode_role(None, text, text, None, None)[0][0] elif typ == 'mailheader': return http_header_role(None, text, text, None, None)[0][0] else: return nodes.emphasis(text, text) else: anchor = http_resource_anchor(typ, target) title = typ.upper() + ' ' + target return make_refnode(builder, fromdocname, info[0], anchor, contnode, title) 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) sphinxcontrib-httpdomain-1.3.0/sphinxcontrib_httpdomain.egg-info/0000755000076500000240000000000012366220063025732 5ustar dahliastaff00000000000000sphinxcontrib-httpdomain-1.3.0/sphinxcontrib_httpdomain.egg-info/dependency_links.txt0000644000076500000240000000000112366220062031777 0ustar dahliastaff00000000000000 sphinxcontrib-httpdomain-1.3.0/sphinxcontrib_httpdomain.egg-info/namespace_packages.txt0000644000076500000240000000001612366220062032261 0ustar dahliastaff00000000000000sphinxcontrib sphinxcontrib-httpdomain-1.3.0/sphinxcontrib_httpdomain.egg-info/not-zip-safe0000644000076500000240000000000112316036536030165 0ustar dahliastaff00000000000000 sphinxcontrib-httpdomain-1.3.0/sphinxcontrib_httpdomain.egg-info/PKG-INFO0000644000076500000240000000170612366220062027032 0ustar dahliastaff00000000000000Metadata-Version: 1.1 Name: sphinxcontrib-httpdomain Version: 1.3.0 Summary: Sphinx domain for HTTP APIs Home-page: http://bitbucket.org/birkenfeld/sphinx-contrib Author: Hong Minhee Author-email: minhee@dahlia.kr License: BSD Download-URL: http://pypi.python.org/pypi/sphinxcontrib-httpdomain Description: This contrib extension, sphinxcontrib.httpdomain provides a Sphinx domain for describing RESTful HTTP APIs. You can find the documentation from the following URL: http://pythonhosted.org/sphinxcontrib-httpdomain/ Platform: any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Console Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Documentation Classifier: Topic :: Utilities sphinxcontrib-httpdomain-1.3.0/sphinxcontrib_httpdomain.egg-info/requires.txt0000644000076500000240000000002112366220062030322 0ustar dahliastaff00000000000000Sphinx >= 1.0 sixsphinxcontrib-httpdomain-1.3.0/sphinxcontrib_httpdomain.egg-info/SOURCES.txt0000644000076500000240000000114512366220063027617 0ustar dahliastaff00000000000000LICENSE MANIFEST.in README.rst setup.cfg setup.py sphinxcontrib/__init__.py sphinxcontrib/httpdomain.py sphinxcontrib/autohttp/__init__.py sphinxcontrib/autohttp/bottle.py sphinxcontrib/autohttp/common.py sphinxcontrib/autohttp/flask.py sphinxcontrib/autohttp/tornado.py sphinxcontrib_httpdomain.egg-info/PKG-INFO sphinxcontrib_httpdomain.egg-info/SOURCES.txt sphinxcontrib_httpdomain.egg-info/dependency_links.txt sphinxcontrib_httpdomain.egg-info/namespace_packages.txt sphinxcontrib_httpdomain.egg-info/not-zip-safe sphinxcontrib_httpdomain.egg-info/requires.txt sphinxcontrib_httpdomain.egg-info/top_level.txtsphinxcontrib-httpdomain-1.3.0/sphinxcontrib_httpdomain.egg-info/top_level.txt0000644000076500000240000000001612366220062030460 0ustar dahliastaff00000000000000sphinxcontrib