Refactor sphinx.io; independ parser generation from reader class

This commit is contained in:
Takeshi KOMIYA 2017-12-07 23:49:32 +09:00
parent 8f28837616
commit a12399dbe4
3 changed files with 29 additions and 44 deletions

View File

@ -50,37 +50,6 @@ class SphinxBaseReader(standalone.Reader):
""" """
Add our source parsers Add our source parsers
""" """
def __init__(self, app, parsers={}, *args, **kwargs):
# type: (Sphinx, Dict[unicode, Parser], Any, Any) -> None
standalone.Reader.__init__(self, *args, **kwargs)
self.parser_map = {} # type: Dict[unicode, Parser]
for suffix, parser_class in parsers.items():
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser') # type: ignore
parser = parser_class()
if hasattr(parser, 'set_application'):
parser.set_application(app)
self.parser_map[suffix] = parser
def read(self, source, parser, settings):
# type: (Input, Parser, Dict) -> nodes.document
self.source = source
for suffix in self.parser_map:
if source.source_path.endswith(suffix):
self.parser = self.parser_map[suffix]
break
else:
# use special parser for unknown file-extension '*' (if exists)
self.parser = self.parser_map.get('*')
if not self.parser:
self.parser = parser
self.settings = settings
self.input = self.source.read()
self.parse()
return self.document
def get_transforms(self): def get_transforms(self):
# type: () -> List[Transform] # type: () -> List[Transform]
return standalone.Reader.get_transforms(self) + self.transforms return standalone.Reader.get_transforms(self) + self.transforms
@ -114,17 +83,13 @@ class SphinxI18nReader(SphinxBaseReader):
This class provides the correct line numbers when reporting. This class provides the correct line numbers when reporting.
""" """
lineno = None # type: int
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences, transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
AutoNumbering, SortIds, RemoveTranslatableInline, AutoNumbering, SortIds, RemoveTranslatableInline,
FilterSystemMessages, RefOnlyBulletListTransform, FilterSystemMessages, RefOnlyBulletListTransform,
UnreferencedFootnotesDetector] UnreferencedFootnotesDetector]
def __init__(self, *args, **kwargs):
# type: (Any, Any) -> None
SphinxBaseReader.__init__(self, *args, **kwargs)
self.lineno = None # type: int
def set_lineno_for_reporter(self, lineno): def set_lineno_for_reporter(self, lineno):
# type: (int) -> None # type: (int) -> None
self.lineno = lineno self.lineno = lineno
@ -216,11 +181,13 @@ class SphinxFileInput(FileInput):
def read_doc(app, env, filename): def read_doc(app, env, filename):
# type: (Sphinx, BuildEnvironment, unicode) -> nodes.document # type: (Sphinx, BuildEnvironment, unicode) -> nodes.document
"""Parse a document and convert to doctree.""" """Parse a document and convert to doctree."""
reader = SphinxStandaloneReader(app, parsers=app.registry.get_source_parsers()) reader = SphinxStandaloneReader()
source = SphinxFileInput(app, env, source=None, source_path=filename, source = SphinxFileInput(app, env, source=None, source_path=filename,
encoding=env.config.source_encoding) encoding=env.config.source_encoding)
parser = app.registry.create_source_parser(app, filename)
pub = Publisher(reader=reader, pub = Publisher(reader=reader,
parser=parser,
writer=SphinxDummyWriter(), writer=SphinxDummyWriter(),
source_class=SphinxDummySourceClass, source_class=SphinxDummySourceClass,
destination=NullOutput()) destination=NullOutput())

View File

@ -13,15 +13,17 @@ from __future__ import print_function
import traceback import traceback
from pkg_resources import iter_entry_points from pkg_resources import iter_entry_points
from six import itervalues from six import iteritems, itervalues, string_types
from sphinx.errors import ExtensionError, SphinxError, VersionRequirementError from sphinx.errors import ExtensionError, SphinxError, VersionRequirementError
from sphinx.extension import Extension from sphinx.extension import Extension
from sphinx.domains import ObjType from sphinx.domains import ObjType
from sphinx.domains.std import GenericObject, Target from sphinx.domains.std import GenericObject, Target
from sphinx.locale import __ from sphinx.locale import __
from sphinx.parsers import Parser as SphinxParser
from sphinx.roles import XRefRole from sphinx.roles import XRefRole
from sphinx.util import logging from sphinx.util import logging
from sphinx.util import import_object
from sphinx.util.docutils import directive_helper from sphinx.util.docutils import directive_helper
if False: if False:
@ -160,6 +162,25 @@ class SphinxComponentRegistry(object):
raise ExtensionError(__('source_parser for %r is already registered') % suffix) raise ExtensionError(__('source_parser for %r is already registered') % suffix)
self.source_parsers[suffix] = parser self.source_parsers[suffix] = parser
def create_source_parser(self, app, filename):
# type: (Sphinx, unicode) -> Parser
for suffix, parser_class in iteritems(self.source_parsers):
if filename.endswith(suffix):
break
else:
# use special parser for unknown file-extension '*' (if exists)
parser_class = self.source_parsers.get('*')
if parser_class is None:
raise SphinxError(__('Source parser for %s not registered') % filename)
else:
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser') # type: ignore
parser = parser_class()
if isinstance(parser, SphinxParser):
parser.set_application(app)
return parser
def get_source_parsers(self): def get_source_parsers(self):
# type: () -> Dict[unicode, Parser] # type: () -> Dict[unicode, Parser]
return self.source_parsers return self.source_parsers

View File

@ -50,15 +50,12 @@ def publish_msgstr(app, source, source_path, source_line, config, settings):
:rtype: docutils.nodes.document :rtype: docutils.nodes.document
""" """
from sphinx.io import SphinxI18nReader from sphinx.io import SphinxI18nReader
reader = SphinxI18nReader( reader = SphinxI18nReader()
app=app,
parsers=app.registry.get_source_parsers(),
parser_name='restructuredtext', # default parser
)
reader.set_lineno_for_reporter(source_line) reader.set_lineno_for_reporter(source_line)
parser = app.registry.create_source_parser(app, '')
doc = reader.read( doc = reader.read(
source=StringInput(source=source, source_path=source_path), source=StringInput(source=source, source_path=source_path),
parser=reader.parser, parser=parser,
settings=settings, settings=settings,
) )
try: try: