Make domains instances, which have factory methods for their roles and directives.

This commit is contained in:
Georg Brandl 2009-07-13 16:59:45 +02:00
parent 92e29ad323
commit ab7cfb4a99
4 changed files with 56 additions and 17 deletions

View File

@ -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):

View File

@ -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

View File

@ -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,
}

View File

@ -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: