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
"""
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):
# type: () -> List[Transform]
return standalone.Reader.get_transforms(self) + self.transforms
@ -114,17 +83,13 @@ class SphinxI18nReader(SphinxBaseReader):
This class provides the correct line numbers when reporting.
"""
lineno = None # type: int
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
AutoNumbering, SortIds, RemoveTranslatableInline,
FilterSystemMessages, RefOnlyBulletListTransform,
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):
# type: (int) -> None
self.lineno = lineno
@ -216,11 +181,13 @@ class SphinxFileInput(FileInput):
def read_doc(app, env, filename):
# type: (Sphinx, BuildEnvironment, unicode) -> nodes.document
"""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,
encoding=env.config.source_encoding)
parser = app.registry.create_source_parser(app, filename)
pub = Publisher(reader=reader,
parser=parser,
writer=SphinxDummyWriter(),
source_class=SphinxDummySourceClass,
destination=NullOutput())

View File

@ -13,15 +13,17 @@ from __future__ import print_function
import traceback
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.extension import Extension
from sphinx.domains import ObjType
from sphinx.domains.std import GenericObject, Target
from sphinx.locale import __
from sphinx.parsers import Parser as SphinxParser
from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util import import_object
from sphinx.util.docutils import directive_helper
if False:
@ -160,6 +162,25 @@ class SphinxComponentRegistry(object):
raise ExtensionError(__('source_parser for %r is already registered') % suffix)
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):
# type: () -> Dict[unicode, Parser]
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
"""
from sphinx.io import SphinxI18nReader
reader = SphinxI18nReader(
app=app,
parsers=app.registry.get_source_parsers(),
parser_name='restructuredtext', # default parser
)
reader = SphinxI18nReader()
reader.set_lineno_for_reporter(source_line)
parser = app.registry.create_source_parser(app, '')
doc = reader.read(
source=StringInput(source=source, source_path=source_path),
parser=reader.parser,
parser=parser,
settings=settings,
)
try: