From ab7cfb4a99e1496443fba87a37723347513169f5 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 13 Jul 2009 16:59:45 +0200 Subject: [PATCH] Make domains instances, which have factory methods for their roles and directives. --- sphinx/application.py | 11 ++++++++--- sphinx/directives/desc.py | 3 ++- sphinx/domains.py | 32 +++++++++++++++++++++++++++++++- sphinx/environment.py | 27 +++++++++++++++------------ 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index 5e34232c0..d4d8b1bf4 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -23,7 +23,7 @@ import sphinx from sphinx.roles import XRefRole from sphinx.config import Config from sphinx.errors import SphinxError, SphinxWarning, ExtensionError -from sphinx.domains import domains +from sphinx.domains import all_domains from sphinx.builders import BUILTIN_BUILDERS from sphinx.directives import GenericDesc, Target, additional_xref_types from sphinx.environment import SphinxStandaloneReader @@ -104,6 +104,11 @@ class Sphinx(object): # now that we know all config values, collect them from conf.py self.config.init_values() + # intialize domains + self.domains = {} + for domain in all_domains.keys(): + self.domains[domain] = all_domains[domain](self) + if buildername is None: print >>status, 'No builder selected, using default: html' buildername = 'html' @@ -300,9 +305,9 @@ class Sphinx(object): roles.register_local_role(name, role) def add_domain(self, domain): - if domain.name in domains: + if domain.name in all_domains: raise ExtensionError('domain %s already registered' % domain.name) - domains[domain.name] = domain + all_domains[domain.name] = domain def add_description_unit(self, directivename, rolename, indextemplate='', parse_node=None, ref_nodeclass=None): diff --git a/sphinx/directives/desc.py b/sphinx/directives/desc.py index dfd713821..e30181003 100644 --- a/sphinx/directives/desc.py +++ b/sphinx/directives/desc.py @@ -366,7 +366,8 @@ class DefaultDomain(Directive): def run(self): env = self.state.document.settings.env domain_name = arguments[0] - env.default_domain = domains.get(domain_name) + # XXX won't work + env.default_domain = env.domains.get(domain_name) # Note: the target directive is not registered here, it is used by the diff --git a/sphinx/domains.py b/sphinx/domains.py index 9fa41090f..82f1a5669 100644 --- a/sphinx/domains.py +++ b/sphinx/domains.py @@ -23,6 +23,36 @@ class Domain(object): roles = {} label = '' + def __init__(self, app): + self.app = app + self._role_cache = {} + self._directive_cache = {} + + def role(self, name): + if name in self._role_cache: + return self._role_cache[name] + if name not in self.roles: + return None + def role_adapter(typ, rawtext, text, lineno, inliner, + options={}, content=[]): + return self.roles[name](name, rawtext, text, lineno, + inliner, options, content) + self._role_cache[name] = role_adapter + return role_adapter + + def directive(self, name): + if name in self._directive_cache: + return self._directive_cache[name] + if name not in self.directives: + return None + BaseDirective = self.directives[name] + class DirectiveAdapter(BaseDirective): + def run(self): + self.name = name + return BaseDirective.run(self) + self._directive_cache[name] = DirectiveAdapter + return DirectiveAdapter + # REs for Python signatures py_sig_re = re.compile( @@ -479,7 +509,7 @@ class CDomain(Domain): # this contains all registered domains -domains = { +all_domains = { 'py': PythonDomain, 'c': CDomain, } diff --git a/sphinx/environment.py b/sphinx/environment.py index 9393b6ff9..d12d51138 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -45,7 +45,6 @@ from sphinx import addnodes from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \ docname_join, FilenameUniqDict, url_re from sphinx.errors import SphinxError -from sphinx.domains import domains from sphinx.directives import additional_xref_types orig_role_function = roles.role @@ -561,6 +560,7 @@ class BuildEnvironment: # remove all inventory entries for that file if app: app.emit('env-purge-doc', self, docname) + self.clear_doc(docname) if src_path is None: @@ -600,18 +600,19 @@ class BuildEnvironment: return data # defaults to the global default, but can be re-set in a document - self.default_domain = domains.get(self.config.default_domain) + self.default_domain = app.domains.get(self.config.default_domain) # monkey-patch, so that domain directives take precedence def directive(directive_name, language_module, document): if ':' in directive_name: domain_name, directive_name = directive_name.split(':', 1) - if domain_name in domains: - domain = domains[domain_name] - if directive_name in domain.directives: - return domain.directives[directive_name], [] + if domain_name in app.domains: + domain = app.domains[domain_name] + directive = domain.directive(directive_name) + if directive is not None: + return directive, [] elif self.default_domain is not None: - directive = self.default_domain.directives.get(directive_name) + directive = self.default_domain.directive(directive_name) if directive is not None: return directive, [] return orig_directive_function(directive_name, language_module, @@ -621,12 +622,13 @@ class BuildEnvironment: def role(role_name, language_module, lineno, reporter): if ':' in role_name: domain_name, role_name = role_name.split(':', 1) - if domain_name in domains: - domain = domains[domain_name] - if role_name in domain.roles: - return domain.roles[role_name], [] + if domain_name in app.domains: + domain = app.domains[domain_name] + role = domain.role(role_name) + if role is not None: + return role, [] elif self.default_domain is not None: - role = self.default_domain.roles.get(role_name) + role = self.default_domain.role(role_name) if role is not None: return role, [] return orig_role_function(role_name, language_module, @@ -678,6 +680,7 @@ class BuildEnvironment: self.docname = None self.currmodule = None self.currclass = None + self.default_domain = None self.gloss_entries = set() if save_parsed: