File: directive.py

package info (click to toggle)
sphinxcontrib-openapi 0.8.4-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 876 kB
  • sloc: python: 7,575; makefile: 15
file content (58 lines) | stat: -rw-r--r-- 2,039 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
"""
    sphinxcontrib.openapi.directive
    -------------------------------

    The main directive for the extension.

    :copyright: (c) 2016, Ihor Kalnytskyi.
    :license: BSD, see LICENSE for details.
"""

import functools

from docutils.parsers.rst import directives
from sphinx.util.docutils import SphinxDirective
import yaml


# Locally cache spec to speedup processing of same spec file in multiple
# openapi directives
@functools.lru_cache()
def _get_spec(abspath, encoding):
    with open(abspath, 'rt', encoding=encoding) as stream:
        return yaml.safe_load(stream)


def create_directive_from_renderer(renderer_cls):
    """Create rendering directive from a renderer class."""

    class _RenderingDirective(SphinxDirective):
        required_arguments = 1                  # path to openapi spec
        final_argument_whitespace = True        # path may contain whitespaces
        option_spec = dict(
            {
                'encoding': directives.encoding,    # useful for non-ascii cases :)
            },
            **renderer_cls.option_spec
        )

        def run(self):
            relpath, abspath = self.env.relfn2path(directives.path(self.arguments[0]))

            # URI parameter is crucial for resolving relative references. So we
            # need to set this option properly as it's used later down the
            # stack.
            self.options.setdefault('uri', 'file://%s' % abspath)

            # Add a given OpenAPI spec as a dependency of the referring
            # reStructuredText document, so the document is rebuilt each time
            # the spec is changed.
            self.env.note_dependency(relpath)

            # Read the spec using encoding passed to the directive or fallback to
            # the one specified in Sphinx's config.
            encoding = self.options.get('encoding', self.config.source_encoding)
            spec = _get_spec(abspath, encoding)
            return renderer_cls(self.state, self.options).render(spec)

    return _RenderingDirective