From ed1f47e1908b322de1ac0348ad42c61366cd131d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 13:09:15 +0900 Subject: [PATCH 01/10] Move logs to registry --- sphinx/application.py | 15 --------------- sphinx/registry.py | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index 05d302c81..c184e43c4 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -444,7 +444,6 @@ class Sphinx(object): def add_builder(self, builder): # type: (Type[Builder]) -> None - logger.debug('[app] adding builder: %r', builder) self.registry.add_builder(builder) def add_config_value(self, name, default, rebuild, types=()): @@ -464,7 +463,6 @@ class Sphinx(object): def set_translator(self, name, translator_class): # type: (unicode, Type[nodes.NodeVisitor]) -> None - logger.info(bold(__('Change of translator for the %s builder.') % name)) self.registry.add_translator(name, translator_class) def add_node(self, node, **kwds): @@ -553,39 +551,30 @@ class Sphinx(object): def add_domain(self, domain): # type: (Type[Domain]) -> None - logger.debug('[app] adding domain: %r', domain) self.registry.add_domain(domain) def override_domain(self, domain): # type: (Type[Domain]) -> None - logger.debug('[app] overriding domain: %r', domain) self.registry.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)) self.registry.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)) self.registry.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)) self.registry.add_index_to_domain(domain, 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 - logger.debug('[app] adding object type: %r', - (directivename, rolename, indextemplate, parse_node, - ref_nodeclass, objname, doc_field_types)) self.registry.add_object_type(directivename, rolename, indextemplate, parse_node, ref_nodeclass, objname, doc_field_types) @@ -602,9 +591,6 @@ class Sphinx(object): def add_crossref_type(self, directivename, rolename, indextemplate='', ref_nodeclass=None, objname=''): # type: (unicode, unicode, unicode, nodes.Node, unicode) -> None - logger.debug('[app] adding crossref type: %r', - (directivename, rolename, indextemplate, ref_nodeclass, - objname)) self.registry.add_crossref_type(directivename, rolename, indextemplate, ref_nodeclass, objname) @@ -677,7 +663,6 @@ class Sphinx(object): def add_source_parser(self, suffix, parser): # type: (unicode, Parser) -> None - logger.debug('[app] adding search source_parser: %r, %r', suffix, parser) self.registry.add_source_parser(suffix, parser) def add_env_collector(self, collector): diff --git a/sphinx/registry.py b/sphinx/registry.py index b627f23af..6da6dbeaf 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -24,6 +24,7 @@ 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.console import bold # type: ignore from sphinx.util.docutils import directive_helper if False: @@ -56,6 +57,7 @@ class SphinxComponentRegistry(object): def add_builder(self, builder): # type: (Type[Builder]) -> None + logger.debug('[app] adding builder: %r', builder) if not hasattr(builder, 'name'): raise ExtensionError(__('Builder class %s has no "name" attribute') % builder) if builder.name in self.builders: @@ -87,6 +89,7 @@ class SphinxComponentRegistry(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 @@ -102,6 +105,7 @@ class SphinxComponentRegistry(object): 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]): @@ -112,6 +116,8 @@ class SphinxComponentRegistry(object): 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) directive = directive_helper(obj, has_content, argument_spec, **option_spec) @@ -119,12 +125,14 @@ class SphinxComponentRegistry(object): 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 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) @@ -133,6 +141,10 @@ class SphinxComponentRegistry(object): parse_node=None, ref_nodeclass=None, objname='', doc_field_types=[]): # type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None + logger.debug('[app] adding object type: %r', + (directivename, rolename, indextemplate, parse_node, + ref_nodeclass, objname, doc_field_types)) + # create a subclass of GenericObject as the new directive directive = type(directivename, # type: ignore (GenericObject, object), @@ -148,6 +160,9 @@ class SphinxComponentRegistry(object): def add_crossref_type(self, directivename, rolename, indextemplate='', ref_nodeclass=None, objname=''): # type: (unicode, unicode, unicode, nodes.Node, unicode) -> None + logger.debug('[app] adding crossref type: %r', + (directivename, rolename, indextemplate, ref_nodeclass, objname)) + # create a subclass of Target as the new directive directive = type(directivename, # type: ignore (Target, object), @@ -160,6 +175,7 @@ class SphinxComponentRegistry(object): def add_source_parser(self, suffix, parser): # type: (unicode, Type[Parser]) -> None + logger.debug('[app] adding search source_parser: %r, %r', suffix, parser) if suffix in self.source_parsers: raise ExtensionError(__('source_parser for %r is already registered') % suffix) self.source_parsers[suffix] = parser @@ -216,6 +232,7 @@ class SphinxComponentRegistry(object): def add_translator(self, name, translator): # type: (unicode, Type[nodes.NodeVisitor]) -> None + logger.info(bold(__('Change of translator for the %s builder.') % name)) self.translators[name] = translator def get_translator_class(self, builder): From 27ea988f6e5a6637441f418a8f0c5dff5d5397bf Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 14:09:32 +0900 Subject: [PATCH 02/10] Move Transform manager to registry --- sphinx/application.py | 3 +-- sphinx/io.py | 10 ++++++++-- sphinx/registry.py | 11 +++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index c184e43c4..fc669d798 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -596,8 +596,7 @@ class Sphinx(object): def add_transform(self, transform): # type: (Type[Transform]) -> None - logger.debug('[app] adding transform: %r', transform) - SphinxStandaloneReader.transforms.append(transform) + self.registry.add_transform(transform) def add_post_transform(self, transform): # type: (Type[Transform]) -> None diff --git a/sphinx/io.py b/sphinx/io.py index 8a41069db..4bb554742 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -80,7 +80,13 @@ class SphinxStandaloneReader(SphinxBaseReader): Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds, RemoveTranslatableInline, PreserveTranslatableMessages, FilterSystemMessages, - RefOnlyBulletListTransform, UnreferencedFootnotesDetector] + RefOnlyBulletListTransform, UnreferencedFootnotesDetector + ] # type: List[Transform] + + def __init__(self, app, *args, **kwargs): + # type: (Sphinx, Any, Any) -> None + self.transforms = self.transforms + app.registry.get_transforms() + SphinxBaseReader.__init__(self, *args, **kwargs) class SphinxI18nReader(SphinxBaseReader): @@ -259,7 +265,7 @@ 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() + reader = SphinxStandaloneReader(app) source = input_class(app, env, source=None, source_path=filename, encoding=env.config.source_encoding) parser = app.registry.create_source_parser(app, filename) diff --git a/sphinx/registry.py b/sphinx/registry.py index 6da6dbeaf..95320db36 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -33,6 +33,7 @@ if False: from docutils import nodes # NOQA from docutils.io import Input # NOQA from docutils.parsers import Parser # NOQA + from docutils.transform import Transform # NOQA from sphinx.application import Sphinx # NOQA from sphinx.builders import Builder # NOQA from sphinx.domains import Domain, Index # NOQA @@ -54,6 +55,7 @@ class SphinxComponentRegistry(object): self.source_parsers = {} # type: Dict[unicode, Parser] self.source_inputs = {} # type: Dict[unicode, Input] self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] + self.transforms = [] # type: List[Type[Transform]] def add_builder(self, builder): # type: (Type[Builder]) -> None @@ -245,6 +247,15 @@ class SphinxComponentRegistry(object): translator_class = self.get_translator_class(builder) return translator_class(builder, document) + def add_transform(self, transform): + # type: (Type[Transform]) -> None + logger.debug('[app] adding transform: %r', transform) + self.transforms.append(transform) + + def get_transforms(self): + # type: () -> List[Type[Transform]] + return self.transforms + def load_extension(self, app, extname): # type: (Sphinx, unicode) -> None """Load a Sphinx extension.""" From 2a26656ce6e508e080aaa18922f2a75541f1c96c Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 14:40:02 +0900 Subject: [PATCH 03/10] Move post-transform manager to registry --- sphinx/application.py | 4 +--- sphinx/environment/__init__.py | 2 +- sphinx/registry.py | 10 ++++++++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index fc669d798..ef20e56d8 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -120,7 +120,6 @@ class Sphinx(object): self.env = None # type: BuildEnvironment self.registry = SphinxComponentRegistry() self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, Callable]] # NOQA - self.post_transforms = [] # type: List[Transform] self.html_themes = {} # type: Dict[unicode, unicode] self.srcdir = srcdir @@ -600,8 +599,7 @@ class Sphinx(object): def add_post_transform(self, transform): # type: (Type[Transform]) -> None - logger.debug('[app] adding post transform: %r', transform) - self.post_transforms.append(transform) + self.registry.add_post_transform(transform) def add_javascript(self, filename): # type: (unicode) -> None diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 5ebf9d4d5..b4c40b608 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -878,7 +878,7 @@ class BuildEnvironment(object): transformer = SphinxTransformer(doctree) transformer.set_environment(self) - transformer.add_transforms(self.app.post_transforms) + transformer.add_transforms(self.app.registry.get_post_transforms()) transformer.apply_transforms() finally: self.temp_data = backup diff --git a/sphinx/registry.py b/sphinx/registry.py index 95320db36..6f9bbe4d9 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -52,6 +52,7 @@ class SphinxComponentRegistry(object): def __init__(self): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] + self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] self.source_inputs = {} # type: Dict[unicode, Input] self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] @@ -256,6 +257,15 @@ class SphinxComponentRegistry(object): # type: () -> List[Type[Transform]] return self.transforms + def add_post_transform(self, transform): + # type: (Type[Transform]) -> None + logger.debug('[app] adding post transform: %r', transform) + self.post_transforms.append(transform) + + def get_post_transforms(self): + # type: () -> List[Type[Transform]] + return self.post_transforms + def load_extension(self, app, extname): # type: (Sphinx, unicode) -> None """Load a Sphinx extension.""" From c09f3e77677625374b7c81131c883ca6a5b7b645 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 19:41:27 +0900 Subject: [PATCH 04/10] Transplant directives on instantiate domain --- sphinx/domains/__init__.py | 12 ++++++++---- sphinx/registry.py | 26 ++++++++++++++++---------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 6edc3cdb0..6af0870de 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -161,6 +161,14 @@ class Domain(object): def __init__(self, env): # type: (BuildEnvironment) -> None self.env = env # type: BuildEnvironment + self._role_cache = {} # type: Dict[unicode, Callable] + self._directive_cache = {} # type: Dict[unicode, Callable] + self._role2type = {} # type: Dict[unicode, List[unicode]] + self._type2role = {} # type: Dict[unicode, unicode] + + # convert class variables to instance one (to enhance through API) + self.directives = dict(self.directives) + if self.name not in env.domaindata: assert isinstance(self.initial_data, dict) new_data = copy.deepcopy(self.initial_data) @@ -170,10 +178,6 @@ class Domain(object): self.data = env.domaindata[self.name] if self.data['version'] != self.data_version: raise IOError('data of %r domain out of date' % self.label) - self._role_cache = {} # type: Dict[unicode, Callable] - self._directive_cache = {} # type: Dict[unicode, Callable] - self._role2type = {} # type: Dict[unicode, List[unicode]] - self._type2role = {} # type: Dict[unicode, unicode] for name, obj in iteritems(self.object_types): for rolename in obj.roles: self._role2type.setdefault(rolename, []).append(name) diff --git a/sphinx/registry.py b/sphinx/registry.py index 6f9bbe4d9..0bbd59756 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -50,13 +50,14 @@ EXTENSION_BLACKLIST = { class SphinxComponentRegistry(object): def __init__(self): - self.builders = {} # type: Dict[unicode, Type[Builder]] - self.domains = {} # type: Dict[unicode, Type[Domain]] - self.post_transforms = [] # type: List[Type[Transform]] - self.source_parsers = {} # type: Dict[unicode, Parser] - self.source_inputs = {} # type: Dict[unicode, Input] - self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] - self.transforms = [] # type: List[Type[Transform]] + self.builders = {} # type: Dict[unicode, Type[Builder]] + self.domains = {} # type: Dict[unicode, Type[Domain]] + self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] + self.post_transforms = [] # type: List[Type[Transform]] + self.source_parsers = {} # type: Dict[unicode, Parser] + self.source_inputs = {} # type: Dict[unicode, Input] + self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] + self.transforms = [] # type: List[Type[Transform]] def add_builder(self, builder): # type: (Type[Builder]) -> None @@ -104,7 +105,12 @@ class SphinxComponentRegistry(object): def create_domains(self, env): # type: (BuildEnvironment) -> Iterator[Domain] for DomainClass in itervalues(self.domains): - yield DomainClass(env) + domain = DomainClass(env) + + # transplant components added by extensions + domain.directives.update(self.domain_directives.get(domain.name, {})) + + yield domain def override_domain(self, domain): # type: (Type[Domain]) -> None @@ -123,8 +129,8 @@ class SphinxComponentRegistry(object): (domain, name, obj, has_content, argument_spec, option_spec)) 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 + directives = self.domain_directives.setdefault(domain, {}) + directives[name] = directive_helper(obj, has_content, argument_spec, **option_spec) def add_role_to_domain(self, domain, name, role): # type: (unicode, unicode, Any) -> None From a2880dffe66aa25d7212002ac395cf9687f65138 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 2 May 2017 12:31:36 +0900 Subject: [PATCH 05/10] Transplant roles on instantiate domain --- sphinx/domains/__init__.py | 1 + sphinx/registry.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 6af0870de..dbd8c6c33 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -168,6 +168,7 @@ class Domain(object): # convert class variables to instance one (to enhance through API) self.directives = dict(self.directives) + self.roles = dict(self.roles) if self.name not in env.domaindata: assert isinstance(self.initial_data, dict) diff --git a/sphinx/registry.py b/sphinx/registry.py index 0bbd59756..fba90934a 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -53,6 +53,7 @@ class SphinxComponentRegistry(object): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] + self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Any]] self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] self.source_inputs = {} # type: Dict[unicode, Input] @@ -109,6 +110,7 @@ class SphinxComponentRegistry(object): # transplant components added by extensions domain.directives.update(self.domain_directives.get(domain.name, {})) + domain.roles.update(self.domain_roles.get(domain.name, {})) yield domain @@ -137,7 +139,8 @@ class SphinxComponentRegistry(object): 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 + roles = self.domain_roles.setdefault(domain, {}) + roles[name] = role def add_index_to_domain(self, domain, index): # type: (unicode, Type[Index]) -> None From a7d4fd1a503cd7b1bbe3d3c7bf6d41ab86cc936d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 2 May 2017 12:38:55 +0900 Subject: [PATCH 06/10] Transplant indices on instantiate domain --- sphinx/domains/__init__.py | 1 + sphinx/registry.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index dbd8c6c33..510d997ae 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -169,6 +169,7 @@ class Domain(object): # convert class variables to instance one (to enhance through API) self.directives = dict(self.directives) self.roles = dict(self.roles) + self.indices = list(self.indices) if self.name not in env.domaindata: assert isinstance(self.initial_data, dict) diff --git a/sphinx/registry.py b/sphinx/registry.py index fba90934a..cba2aaeca 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -53,6 +53,7 @@ class SphinxComponentRegistry(object): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] + self.domain_indices = {} # type: Dict[unicode, List[Index]] self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Any]] self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] @@ -111,6 +112,7 @@ class SphinxComponentRegistry(object): # transplant components added by extensions domain.directives.update(self.domain_directives.get(domain.name, {})) domain.roles.update(self.domain_roles.get(domain.name, {})) + domain.indices.extend(self.domain_indices.get(domain.name, [])) yield domain @@ -147,7 +149,8 @@ class SphinxComponentRegistry(object): 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) + indices = self.domain_indices.setdefault(domain, []) + indices.append(index) def add_object_type(self, directivename, rolename, indextemplate='', parse_node=None, ref_nodeclass=None, objname='', From b2837eee0ccd6020c3c1d6470381f6a07185ca0e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 2 May 2017 12:45:16 +0900 Subject: [PATCH 07/10] Transplant object_types on instantiate domain --- sphinx/domains/__init__.py | 1 + sphinx/registry.py | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 510d997ae..ddb6c7c66 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -167,6 +167,7 @@ class Domain(object): self._type2role = {} # type: Dict[unicode, unicode] # convert class variables to instance one (to enhance through API) + self.object_types = dict(self.object_types) self.directives = dict(self.directives) self.roles = dict(self.roles) self.indices = list(self.indices) diff --git a/sphinx/registry.py b/sphinx/registry.py index cba2aaeca..265524b28 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -54,6 +54,7 @@ class SphinxComponentRegistry(object): self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] self.domain_indices = {} # type: Dict[unicode, List[Index]] + self.domain_object_types = {} # type: Dict[unicode, Dict[unicode, ObjType]] self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Any]] self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] @@ -110,6 +111,7 @@ class SphinxComponentRegistry(object): domain = DomainClass(env) # transplant components added by extensions + domain.object_types.update(self.domain_object_types.get(domain.name, {})) domain.directives.update(self.domain_directives.get(domain.name, {})) domain.roles.update(self.domain_roles.get(domain.name, {})) domain.indices.extend(self.domain_indices.get(domain.name, [])) @@ -167,10 +169,11 @@ class SphinxComponentRegistry(object): 'parse_node': staticmethod(parse_node), '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) + self.add_directive_to_domain('std', directivename, directive) + self.add_role_to_domain('std', rolename, XRefRole(innernodeclass=ref_nodeclass)) + + object_types = self.domain_object_types.setdefault('std', {}) + object_types[directivename] = ObjType(objname or directivename, rolename) def add_crossref_type(self, directivename, rolename, indextemplate='', ref_nodeclass=None, objname=''): @@ -183,10 +186,11 @@ class SphinxComponentRegistry(object): (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) + self.add_directive_to_domain('std', directive) + self.add_role_to_domain('std', XRefRole(innernodeclass=ref_nodeclass)) + + object_types = self.domain_object_types.setdefault('std', {}) + object_types[directivename] = ObjType(objname or directivename, rolename) def add_source_parser(self, suffix, parser): # type: (unicode, Type[Parser]) -> None From fe07365a8cea7186261930f19b7f15735e545c57 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 15 Dec 2017 22:17:03 +0900 Subject: [PATCH 08/10] Fix mypy violations --- sphinx/application.py | 5 +++-- sphinx/domains/__init__.py | 2 +- sphinx/io.py | 2 +- sphinx/registry.py | 13 +++++++------ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index ef20e56d8..3edd3fb98 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -33,7 +33,6 @@ from sphinx.deprecation import RemovedInSphinx20Warning from sphinx.environment import BuildEnvironment from sphinx.events import EventManager from sphinx.extension import verify_required_extensions -from sphinx.io import SphinxStandaloneReader from sphinx.locale import __ from sphinx.registry import SphinxComponentRegistry from sphinx.util import pycompat # noqa: F401 @@ -54,7 +53,9 @@ if False: from sphinx.domains import Domain, Index # NOQA from sphinx.environment.collectors import EnvironmentCollector # NOQA from sphinx.extension import Extension # NOQA + from sphinx.roles import XRefRole # NOQA from sphinx.theming import Theme # NOQA + from sphinx.util.typing import RoleFunction # NOQA builtin_extensions = ( 'sphinx.builders.applehelp', @@ -563,7 +564,7 @@ class Sphinx(object): has_content, argument_spec, **option_spec) def add_role_to_domain(self, domain, name, role): - # type: (unicode, unicode, Any) -> None + # type: (unicode, unicode, Union[RoleFunction, XRefRole]) -> None self.registry.add_role_to_domain(domain, name, role) def add_index_to_domain(self, domain, index): diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index ddb6c7c66..1b9a7345a 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -141,7 +141,7 @@ class Domain(object): #: domain label: longer, more descriptive (used in messages) label = '' #: type (usually directive) name -> ObjType instance - object_types = {} # type: Dict[unicode, Any] + object_types = {} # type: Dict[unicode, ObjType] #: directive name -> directive class directives = {} # type: Dict[unicode, Any] #: role name -> role callable diff --git a/sphinx/io.py b/sphinx/io.py index 4bb554742..804932863 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -86,7 +86,7 @@ class SphinxStandaloneReader(SphinxBaseReader): def __init__(self, app, *args, **kwargs): # type: (Sphinx, Any, Any) -> None self.transforms = self.transforms + app.registry.get_transforms() - SphinxBaseReader.__init__(self, *args, **kwargs) + SphinxBaseReader.__init__(self, *args, **kwargs) # type: ignore class SphinxI18nReader(SphinxBaseReader): diff --git a/sphinx/registry.py b/sphinx/registry.py index 265524b28..885c7a256 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -29,7 +29,7 @@ from sphinx.util.docutils import directive_helper if False: # For type annotation - from typing import Any, Callable, Dict, Iterator, List, Type # NOQA + from typing import Any, Callable, Dict, Iterator, List, Type, Union # NOQA from docutils import nodes # NOQA from docutils.io import Input # NOQA from docutils.parsers import Parser # NOQA @@ -38,6 +38,7 @@ if False: from sphinx.builders import Builder # NOQA from sphinx.domains import Domain, Index # NOQA from sphinx.environment import BuildEnvironment # NOQA + from sphinx.util.typing import RoleFunction # NOQA logger = logging.getLogger(__name__) @@ -53,9 +54,9 @@ class SphinxComponentRegistry(object): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] - self.domain_indices = {} # type: Dict[unicode, List[Index]] + self.domain_indices = {} # type: Dict[unicode, List[Type[Index]]] self.domain_object_types = {} # type: Dict[unicode, Dict[unicode, ObjType]] - self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Any]] + self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Union[RoleFunction, XRefRole]]] # NOQA self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] self.source_inputs = {} # type: Dict[unicode, Input] @@ -139,7 +140,7 @@ class SphinxComponentRegistry(object): directives[name] = directive_helper(obj, has_content, argument_spec, **option_spec) def add_role_to_domain(self, domain, name, role): - # type: (unicode, unicode, Any) -> None + # type: (unicode, unicode, Union[RoleFunction, XRefRole]) -> 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) @@ -186,8 +187,8 @@ class SphinxComponentRegistry(object): (Target, object), {'indextemplate': indextemplate}) - self.add_directive_to_domain('std', directive) - self.add_role_to_domain('std', XRefRole(innernodeclass=ref_nodeclass)) + self.add_directive_to_domain('std', directivename, directive) + self.add_role_to_domain('std', rolename, XRefRole(innernodeclass=ref_nodeclass)) object_types = self.domain_object_types.setdefault('std', {}) object_types[directivename] = ObjType(objname or directivename, rolename) From 838f7fc29a0af74d778cb99d235d645716ba02ab Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 20 Dec 2017 00:31:32 +0900 Subject: [PATCH 09/10] Add Domain.add_object_type() to update internal caches correctly --- sphinx/domains/__init__.py | 12 ++++++++++++ sphinx/registry.py | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 1b9a7345a..868f56c91 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -188,6 +188,18 @@ class Domain(object): self.objtypes_for_role = self._role2type.get # type: Callable[[unicode], List[unicode]] # NOQA self.role_for_objtype = self._type2role.get # type: Callable[[unicode], unicode] + def add_object_type(self, name, objtype): + # type: (Objtype) -> None + """Add an object type.""" + self.object_types[name] = objtype + if objtype.roles: + self._type2role[name] = objtype.roles[0] + else: + self._type2role[name] = '' + + for role in objtype.roles: + self._role2type.setdefault(role, []).append(name) + def role(self, name): # type: (unicode) -> Callable """Return a role adapter function that always gives the registered diff --git a/sphinx/registry.py b/sphinx/registry.py index 885c7a256..6ec966a6a 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -112,10 +112,11 @@ class SphinxComponentRegistry(object): domain = DomainClass(env) # transplant components added by extensions - domain.object_types.update(self.domain_object_types.get(domain.name, {})) domain.directives.update(self.domain_directives.get(domain.name, {})) domain.roles.update(self.domain_roles.get(domain.name, {})) domain.indices.extend(self.domain_indices.get(domain.name, [])) + for name, objtype in iteritems(self.domain_object_types.get(domain.name, {})): + domain.add_object_type(name, objtype) yield domain From b07de530619d7e26a62540cf75954839f0f712d9 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 21 Dec 2017 00:19:02 +0900 Subject: [PATCH 10/10] Fix mypy violation --- sphinx/domains/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 868f56c91..1c80d3a42 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -189,7 +189,7 @@ class Domain(object): self.role_for_objtype = self._type2role.get # type: Callable[[unicode], unicode] def add_object_type(self, name, objtype): - # type: (Objtype) -> None + # type: (unicode, ObjType) -> None """Add an object type.""" self.object_types[name] = objtype if objtype.roles: