From 18efa1a63ac9820e990a79303890ef2634b14396 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 10 Feb 2018 16:59:43 +0900 Subject: [PATCH] refactor: Store enumerable_nodes to registry --- sphinx/application.py | 22 +++++++++++----------- sphinx/domains/std.py | 10 ++++++++++ sphinx/registry.py | 11 ++++++++++- sphinx/util/typing.py | 3 +++ tests/test_domain_std.py | 3 +++ 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index 43af6a2c2..54cf6cb1b 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -56,7 +56,7 @@ if TYPE_CHECKING: 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 + from sphinx.util.typing import RoleFunction, TitleGetter # NOQA builtin_extensions = ( 'sphinx.builders.applehelp', @@ -132,7 +132,6 @@ class Sphinx(object): self.builder = None # type: Builder self.env = None # type: BuildEnvironment self.registry = SphinxComponentRegistry() - self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, Callable]] # NOQA self.html_themes = {} # type: Dict[unicode, unicode] # validate provided directories @@ -252,8 +251,6 @@ class Sphinx(object): self._init_env(freshenv) # set up the builder self._init_builder() - # set up the enumerable nodes - self._init_enumerable_nodes() def _init_i18n(self): # type: () -> None @@ -323,11 +320,6 @@ class Sphinx(object): self.builder.init() self.emit('builder-inited') - def _init_enumerable_nodes(self): - # type: () -> None - for node, settings in iteritems(self.enumerable_nodes): - self.env.get_domain('std').enumerable_nodes[node] = settings # type: ignore - # ---- main "build" method ------------------------------------------------- def build(self, force_all=False, filenames=None): @@ -661,7 +653,7 @@ class Sphinx(object): setattr(translator, 'depart_' + node.__name__, depart) def add_enumerable_node(self, node, figtype, title_getter=None, **kwds): - # type: (nodes.Node, unicode, Callable, Any) -> None + # type: (nodes.Node, unicode, TitleGetter, Any) -> None """Register a Docutils node class as a numfig target. Sphinx numbers the node automatically. And then the users can refer it @@ -685,9 +677,17 @@ class Sphinx(object): .. versionadded:: 1.4 """ - self.enumerable_nodes[node] = (figtype, title_getter) + self.registry.add_enumerable_node(node, figtype, title_getter) self.add_node(node, **kwds) + @property + def enumerable_nodes(self): + # type: () -> Dict[nodes.Node, Tuple[unicode, TitleGetter]] + warnings.warn('app.enumerable_nodes() is deprecated. ' + 'Use app.get_domain("std").enumerable_nodes instead.', + RemovedInSphinx30Warning) + return self.registry.enumerable_nodes + def add_directive(self, name, obj, content=None, arguments=None, **options): # type: (unicode, Any, bool, Tuple[int, int, bool], Any) -> None """Register a Docutils directive. diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index 0a4c5d5ed..801f54b14 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -11,6 +11,7 @@ import re import unicodedata +from copy import copy from typing import TYPE_CHECKING from docutils import nodes @@ -522,6 +523,15 @@ class StandardDomain(Domain): nodes.container: ('code-block', None), } # type: Dict[nodes.Node, Tuple[unicode, Callable]] + def __init__(self, env): + # type: (BuildEnvironment) -> None + super(StandardDomain, self).__init__(env) + + # set up enumerable nodes + self.enumerable_nodes = copy(self.enumerable_nodes) # create a copy for this instance + for node, settings in iteritems(env.app.registry.enumerable_nodes): + self.enumerable_nodes[node] = settings + def clear_doc(self, docname): # type: (unicode) -> None for key, (fn, _l) in list(self.data['progoptions'].items()): diff --git a/sphinx/registry.py b/sphinx/registry.py index 20799afca..547641306 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -40,7 +40,7 @@ if TYPE_CHECKING: from sphinx.domains import Domain, Index # NOQA from sphinx.environment import BuildEnvironment # NOQA from sphinx.ext.autodoc import Documenter # NOQA - from sphinx.util.typing import RoleFunction # NOQA + from sphinx.util.typing import RoleFunction, TitleGetter # NOQA logger = logging.getLogger(__name__) @@ -82,6 +82,10 @@ class SphinxComponentRegistry(object): #: a dict of domain name -> dict of role name -> role impl. self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Union[RoleFunction, XRefRole]]] # NOQA + #: additional enumerable nodes + #: a dict of node class -> tuple of figtype and title_getter function + self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, TitleGetter]] + #: LaTeX packages; list of package names and its options self.latex_packages = [] # type: List[Tuple[unicode, unicode]] @@ -349,6 +353,11 @@ class SphinxComponentRegistry(object): logger.debug('[app] adding latex package: %r', name) self.latex_packages.append((name, options)) + def add_enumerable_node(self, node, figtype, title_getter=None): + # type: (nodes.Node, unicode, TitleGetter) -> None + logger.debug('[app] adding enumerable node: (%r, %r, %r)', node, figtype, title_getter) + self.enumerable_nodes[node] = (figtype, title_getter) + def load_extension(self, app, extname): # type: (Sphinx, unicode) -> None """Load a Sphinx extension.""" diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 3cc4a46b5..a26dac473 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -22,3 +22,6 @@ if PY3: # common role functions RoleFunction = Callable[[unicode, unicode, unicode, int, Inliner, Dict, List[unicode]], Tuple[List[nodes.Node], List[nodes.Node]]] + +# title getter functions for enumerable nodes (see sphinx.domains.std) +TitleGetter = Callable[[nodes.Node], unicode] diff --git a/tests/test_domain_std.py b/tests/test_domain_std.py index dce7a5ddf..57d0bf185 100644 --- a/tests/test_domain_std.py +++ b/tests/test_domain_std.py @@ -17,6 +17,7 @@ from sphinx.domains.std import StandardDomain def test_process_doc_handle_figure_caption(): env = mock.Mock(domaindata={}) + env.app.registry.enumerable_nodes = {} figure_node = nodes.figure( '', nodes.caption('caption text', 'caption text'), @@ -40,6 +41,7 @@ def test_process_doc_handle_figure_caption(): def test_process_doc_handle_table_title(): env = mock.Mock(domaindata={}) + env.app.registry.enumerable_nodes = {} table_node = nodes.table( '', nodes.title('title text', 'title text'), @@ -63,6 +65,7 @@ def test_process_doc_handle_table_title(): def test_get_full_qualified_name(): env = mock.Mock(domaindata={}) + env.app.registry.enumerable_nodes = {} domain = StandardDomain(env) # normal references