mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Move domain class manager to SphinxFactory
This commit is contained in:
parent
3cc9d8c250
commit
8ca9bdfbd4
@ -29,8 +29,6 @@ import sphinx
|
||||
from sphinx import package_dir, locale
|
||||
from sphinx.config import Config
|
||||
from sphinx.errors import ConfigError, ExtensionError, VersionRequirementError
|
||||
from sphinx.domains import ObjType
|
||||
from sphinx.domains.std import GenericObject, Target, StandardDomain
|
||||
from sphinx.deprecation import RemovedInSphinx17Warning, RemovedInSphinx20Warning
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.events import EventManager
|
||||
@ -38,7 +36,6 @@ from sphinx.extension import load_extension, verify_required_extensions
|
||||
from sphinx.factory import SphinxFactory
|
||||
from sphinx.io import SphinxStandaloneReader
|
||||
from sphinx.locale import _
|
||||
from sphinx.roles import XRefRole
|
||||
from sphinx.util import pycompat # noqa: F401
|
||||
from sphinx.util import import_object
|
||||
from sphinx.util import logging
|
||||
@ -120,7 +117,6 @@ class Sphinx(object):
|
||||
self.extensions = {} # type: Dict[unicode, Extension]
|
||||
self._additional_source_parsers = {} # type: Dict[unicode, Parser]
|
||||
self._setting_up_extension = ['?'] # type: List[unicode]
|
||||
self.domains = {} # type: Dict[unicode, Type[Domain]]
|
||||
self.builder = None # type: Builder
|
||||
self.env = None # type: BuildEnvironment
|
||||
self.factory = SphinxFactory()
|
||||
@ -223,9 +219,9 @@ class Sphinx(object):
|
||||
verify_required_extensions(self, self.config.needs_extensions)
|
||||
|
||||
# check primary_domain if requested
|
||||
if self.config.primary_domain and self.config.primary_domain not in self.domains:
|
||||
logger.warning(_('primary_domain %r not found, ignored.'),
|
||||
self.config.primary_domain)
|
||||
primary_domain = self.config.primary_domain
|
||||
if primary_domain and not self.factory.has_domain(primary_domain):
|
||||
logger.warning(_('primary_domain %r not found, ignored.'), primary_domain)
|
||||
|
||||
# create the builder
|
||||
self.builder = self.create_builder(buildername)
|
||||
@ -279,17 +275,17 @@ class Sphinx(object):
|
||||
if freshenv:
|
||||
self.env = BuildEnvironment(self)
|
||||
self.env.find_files(self.config, self.builder)
|
||||
for domain in self.domains.keys():
|
||||
self.env.domains[domain] = self.domains[domain](self.env)
|
||||
for domain in self.factory.create_domains(self.env):
|
||||
self.env.domains[domain.name] = domain
|
||||
else:
|
||||
try:
|
||||
logger.info(bold(_('loading pickled environment... ')), nonl=True)
|
||||
filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
||||
self.env = BuildEnvironment.frompickle(filename, self)
|
||||
self.env.domains = {}
|
||||
for domain in self.domains.keys():
|
||||
for domain in self.factory.create_domains(self.env):
|
||||
# this can raise if the data version doesn't fit
|
||||
self.env.domains[domain] = self.domains[domain](self.env)
|
||||
self.env.domains[domain.name] = domain
|
||||
logger.info(_('done'))
|
||||
except Exception as err:
|
||||
if isinstance(err, IOError) and err.errno == ENOENT:
|
||||
@ -618,43 +614,30 @@ class Sphinx(object):
|
||||
def add_domain(self, domain):
|
||||
# type: (Type[Domain]) -> None
|
||||
logger.debug('[app] adding domain: %r', domain)
|
||||
if domain.name in self.domains:
|
||||
raise ExtensionError(_('domain %s already registered') % domain.name)
|
||||
self.domains[domain.name] = domain
|
||||
self.factory.add_domain(domain)
|
||||
|
||||
def override_domain(self, domain):
|
||||
# type: (Type[Domain]) -> None
|
||||
logger.debug('[app] overriding domain: %r', domain)
|
||||
if domain.name not in self.domains:
|
||||
raise ExtensionError(_('domain %s not yet registered') % domain.name)
|
||||
if not issubclass(domain, self.domains[domain.name]):
|
||||
raise ExtensionError(_('new domain not a subclass of registered %s '
|
||||
'domain') % domain.name)
|
||||
self.domains[domain.name] = domain
|
||||
self.factory.override_domain(domain)
|
||||
|
||||
def add_directive_to_domain(self, domain, name, obj,
|
||||
has_content=None, argument_spec=None, **option_spec):
|
||||
# type: (unicode, unicode, Any, bool, Any, Any) -> None
|
||||
logger.debug('[app] adding directive to domain: %r',
|
||||
(domain, name, obj, has_content, argument_spec, option_spec))
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||
self.domains[domain].directives[name] = \
|
||||
directive_helper(obj, has_content, argument_spec, **option_spec)
|
||||
self.factory.add_directive_to_domain(domain, name, obj,
|
||||
has_content, argument_spec, **option_spec)
|
||||
|
||||
def add_role_to_domain(self, domain, name, role):
|
||||
# type: (unicode, unicode, Any) -> None
|
||||
logger.debug('[app] adding role to domain: %r', (domain, name, role))
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||
self.domains[domain].roles[name] = role
|
||||
self.factory.add_role_to_domain(domain, name, role)
|
||||
|
||||
def add_index_to_domain(self, domain, index):
|
||||
# type: (unicode, Type[Index]) -> None
|
||||
logger.debug('[app] adding index to domain: %r', (domain, index))
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||
self.domains[domain].indices.append(index)
|
||||
self.factory.add_index_to_domain(domain, index)
|
||||
|
||||
def add_object_type(self, directivename, rolename, indextemplate='',
|
||||
parse_node=None, ref_nodeclass=None, objname='',
|
||||
@ -663,19 +646,18 @@ class Sphinx(object):
|
||||
logger.debug('[app] adding object type: %r',
|
||||
(directivename, rolename, indextemplate, parse_node,
|
||||
ref_nodeclass, objname, doc_field_types))
|
||||
StandardDomain.object_types[directivename] = \
|
||||
ObjType(objname or directivename, rolename)
|
||||
# create a subclass of GenericObject as the new directive
|
||||
new_directive = type(directivename, (GenericObject, object), # type: ignore
|
||||
{'indextemplate': indextemplate,
|
||||
'parse_node': staticmethod(parse_node), # type: ignore
|
||||
'doc_field_types': doc_field_types})
|
||||
StandardDomain.directives[directivename] = new_directive
|
||||
# XXX support more options?
|
||||
StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
||||
self.factory.add_object_type(directivename, rolename, indextemplate, parse_node,
|
||||
ref_nodeclass, objname, doc_field_types)
|
||||
|
||||
# backwards compatible alias
|
||||
add_description_unit = add_object_type
|
||||
def add_description_unit(self, directivename, rolename, indextemplate='',
|
||||
parse_node=None, ref_nodeclass=None, objname='',
|
||||
doc_field_types=[]):
|
||||
# type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None
|
||||
warnings.warn('app.add_description_unit() is now deprecated. '
|
||||
'Use app.add_object_type() instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
self.add_object_type(directivename, rolename, indextemplate, parse_node,
|
||||
ref_nodeclass, objname, doc_field_types)
|
||||
|
||||
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
||||
ref_nodeclass=None, objname=''):
|
||||
@ -683,14 +665,8 @@ class Sphinx(object):
|
||||
logger.debug('[app] adding crossref type: %r',
|
||||
(directivename, rolename, indextemplate, ref_nodeclass,
|
||||
objname))
|
||||
StandardDomain.object_types[directivename] = \
|
||||
ObjType(objname or directivename, rolename)
|
||||
# create a subclass of Target as the new directive
|
||||
new_directive = type(directivename, (Target, object), # type: ignore
|
||||
{'indextemplate': indextemplate})
|
||||
StandardDomain.directives[directivename] = new_directive
|
||||
# XXX support more options?
|
||||
StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
||||
self.factory.add_crossref_type(directivename, rolename,
|
||||
indextemplate, ref_nodeclass, objname)
|
||||
|
||||
def add_transform(self, transform):
|
||||
# type: (Type[Transform]) -> None
|
||||
|
@ -11,22 +11,32 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
from pkg_resources import iter_entry_points
|
||||
from six import itervalues
|
||||
|
||||
from sphinx.errors import ExtensionError, SphinxError
|
||||
from sphinx.domains import ObjType
|
||||
from sphinx.domains.std import GenericObject, Target
|
||||
from sphinx.extension import load_extension
|
||||
from sphinx.locale import _
|
||||
from sphinx.roles import XRefRole
|
||||
from sphinx.util.docutils import directive_helper
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Dict, Type # NOQA
|
||||
from typing import Any, Callable, Dict, Iterator, List, Type # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.builders import Builder # NOQA
|
||||
from sphinx.domains import Domain, Index # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
|
||||
|
||||
class SphinxFactory(object):
|
||||
def __init__(self):
|
||||
self.builders = {} # type: Dict[unicode, Type[Builder]]
|
||||
self.domains = {} # type: Dict[unicode, Type[Domain]]
|
||||
|
||||
def add_builder(self, builder):
|
||||
# type: (Type[Builder]) -> None
|
||||
@ -57,3 +67,76 @@ class SphinxFactory(object):
|
||||
raise SphinxError(_('Builder name %s not registered') % name)
|
||||
|
||||
return self.builders[name](app)
|
||||
|
||||
def add_domain(self, domain):
|
||||
# type: (Type[Domain]) -> None
|
||||
if domain.name in self.domains:
|
||||
raise ExtensionError(_('domain %s already registered') % domain.name)
|
||||
self.domains[domain.name] = domain
|
||||
|
||||
def has_domain(self, domain):
|
||||
# type: (unicode) -> bool
|
||||
return domain in self.domains
|
||||
|
||||
def create_domains(self, env):
|
||||
# type: (BuildEnvironment) -> Iterator[Domain]
|
||||
for DomainClass in itervalues(self.domains):
|
||||
yield DomainClass(env)
|
||||
|
||||
def override_domain(self, domain):
|
||||
# type: (Type[Domain]) -> None
|
||||
if domain.name not in self.domains:
|
||||
raise ExtensionError(_('domain %s not yet registered') % domain.name)
|
||||
if not issubclass(domain, self.domains[domain.name]):
|
||||
raise ExtensionError(_('new domain not a subclass of registered %s '
|
||||
'domain') % domain.name)
|
||||
self.domains[domain.name] = domain
|
||||
|
||||
def add_directive_to_domain(self, domain, name, obj,
|
||||
has_content=None, argument_spec=None, **option_spec):
|
||||
# type: (unicode, unicode, Any, bool, Any, Any) -> None
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||
directive = directive_helper(obj, has_content, argument_spec, **option_spec)
|
||||
self.domains[domain].directives[name] = directive
|
||||
|
||||
def add_role_to_domain(self, domain, name, role):
|
||||
# type: (unicode, unicode, Any) -> None
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||
self.domains[domain].roles[name] = role
|
||||
|
||||
def add_index_to_domain(self, domain, index):
|
||||
# type: (unicode, Type[Index]) -> None
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||
self.domains[domain].indices.append(index)
|
||||
|
||||
def add_object_type(self, directivename, rolename, indextemplate='',
|
||||
parse_node=None, ref_nodeclass=None, objname='',
|
||||
doc_field_types=[]):
|
||||
# type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None
|
||||
# create a subclass of GenericObject as the new directive
|
||||
directive = type(directivename, # type: ignore
|
||||
(GenericObject, object),
|
||||
{'indextemplate': indextemplate,
|
||||
'parse_node': staticmethod(parse_node), # type: ignore
|
||||
'doc_field_types': doc_field_types})
|
||||
|
||||
stddomain = self.domains['std']
|
||||
stddomain.directives[directivename] = directive
|
||||
stddomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
||||
stddomain.object_types[directivename] = ObjType(objname or directivename, rolename)
|
||||
|
||||
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
||||
ref_nodeclass=None, objname=''):
|
||||
# type: (unicode, unicode, unicode, nodes.Node, unicode) -> None
|
||||
# create a subclass of Target as the new directive
|
||||
directive = type(directivename, # type: ignore
|
||||
(Target, object),
|
||||
{'indextemplate': indextemplate})
|
||||
|
||||
stddomain = self.domains['std']
|
||||
stddomain.directives[directivename] = directive
|
||||
stddomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
||||
stddomain.object_types[directivename] = ObjType(objname or directivename, rolename)
|
||||
|
Loading…
Reference in New Issue
Block a user