Refactor sphinx.io; separate FileInput class for each file type

This commit is contained in:
Takeshi KOMIYA 2017-11-15 14:48:30 +09:00
parent aa4fd0e1b7
commit 0e86ff2f11
3 changed files with 53 additions and 13 deletions

View File

@ -83,6 +83,7 @@ builtin_extensions = (
'sphinx.directives.code',
'sphinx.directives.other',
'sphinx.directives.patches',
'sphinx.io',
'sphinx.parsers',
'sphinx.roles',
'sphinx.transforms.post_transforms',

View File

@ -120,7 +120,9 @@ def SphinxDummySourceClass(source, *args, **kwargs):
return source
class SphinxFileInput(FileInput):
class SphinxBaseFileInput(FileInput):
"""A base class of SphinxFileInput."""
def __init__(self, app, env, *args, **kwds):
# type: (Sphinx, BuildEnvironment, Any, Any) -> None
self.app = app
@ -145,16 +147,7 @@ class SphinxFileInput(FileInput):
# emit source-read event
arg = [data]
self.app.emit('source-read', self.env.docname, arg)
data = arg[0]
parser = self.app.registry.get_source_parser(self.source_path)
docinfo, data = split_docinfo(data)
if 'restructuredtext' in parser.supported:
if self.env.config.rst_epilog:
data = data + '\n' + self.env.config.rst_epilog + '\n'
if self.env.config.rst_prolog:
data = self.env.config.rst_prolog + '\n' + data
return docinfo + data
return arg[0]
def warn_and_replace(self, error):
# type: (Any) -> Tuple
@ -172,11 +165,28 @@ class SphinxFileInput(FileInput):
return (u'?', error.end)
class SphinxFileInput(SphinxBaseFileInput):
pass
class SphinxRSTFileInput(SphinxBaseFileInput):
def read(self):
# type: () -> unicode
data = SphinxBaseFileInput.read(self)
docinfo, data = split_docinfo(data)
if self.env.config.rst_epilog:
data = data + '\n' + self.env.config.rst_epilog + '\n'
if self.env.config.rst_prolog:
data = self.env.config.rst_prolog + '\n' + data
return docinfo + data
def read_doc(app, env, filename):
# type: (Sphinx, BuildEnvironment, unicode) -> nodes.document
"""Parse a document and convert to doctree."""
input_class = app.registry.get_source_input(filename)
reader = SphinxStandaloneReader()
source = SphinxFileInput(app, env, source=None, source_path=filename,
source = input_class(app, env, source=None, source_path=filename,
encoding=env.config.source_encoding)
parser = app.registry.create_source_parser(app, filename)
@ -190,3 +200,8 @@ def read_doc(app, env, filename):
pub.set_source(source, filename)
pub.publish()
return pub.document
def setup(app):
app.registry.add_source_input('*', SphinxFileInput)
app.registry.add_source_input('restructuredtext', SphinxRSTFileInput)

View File

@ -30,6 +30,7 @@ if False:
# For type annotation
from typing import Any, Callable, Dict, Iterator, List, Type # NOQA
from docutils import nodes # NOQA
from docutils.io import Input # NOQA
from docutils.parsers import Parser # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
@ -50,6 +51,7 @@ class SphinxComponentRegistry(object):
self.builders = {} # type: Dict[unicode, Type[Builder]]
self.domains = {} # type: Dict[unicode, Type[Domain]]
self.source_parsers = {} # type: Dict[unicode, Parser]
self.source_inputs = {} # type: Dict[unicode, Input]
self.translators = {} # type: Dict[unicode, nodes.NodeVisitor]
def add_builder(self, builder):
@ -190,6 +192,28 @@ class SphinxComponentRegistry(object):
parser.set_application(app)
return parser
def add_source_input(self, filetype, input_class):
# type: (unicode, Type[Input]) -> None
if filetype in self.source_inputs:
raise ExtensionError(__('source_input for %r is already registered') % filetype)
self.source_inputs[filetype] = input_class
def get_source_input(self, filename):
# type: (unicode) -> Type[Input]
parser = self.get_source_parser(filename)
for filetype in parser.supported:
if filetype in self.source_inputs:
input_class = self.source_inputs[filetype]
break
else:
# use special source_input for unknown file-type '*' (if exists)
input_class = self.source_inputs.get('*')
if input_class is None:
raise SphinxError(__('source_input for %s not registered') % filename)
else:
return input_class
def add_translator(self, name, translator):
# type: (unicode, Type[nodes.NodeVisitor]) -> None
self.translators[name] = translator