First step of domain handling in environment.

This commit is contained in:
Georg Brandl 2009-07-13 20:53:11 +02:00
parent 51a78a9b88
commit a1dd4695f3
6 changed files with 60 additions and 31 deletions

View File

@ -107,11 +107,6 @@ 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]()
# set up translation infrastructure
self._init_i18n()
# set up the build environment
@ -144,20 +139,25 @@ class Sphinx(object):
self.env = BuildEnvironment(self.srcdir, self.doctreedir,
self.config)
self.env.find_files(self.config)
for domain in all_domains.keys():
self.env.domains[domain] = all_domains[domain](self.env)
else:
try:
self.info(bold('loading pickled environment... '), nonl=True)
self.env = BuildEnvironment.frompickle(self.config,
path.join(self.doctreedir, ENV_PICKLE_FILENAME))
self.env.domains = {}
for domain in all_domains.keys():
# this can raise if the data version doesn't fit
self.env.domains[domain] = all_domains[domain](self.env)
self.info('done')
except Exception, err:
if type(err) is IOError and err.errno == 2:
self.info('not yet created')
else:
self.info('failed: %s' % err)
self.env = BuildEnvironment(self.srcdir, self.doctreedir,
self.config)
self.env.find_files(self.config)
return self._init_env(freshenv=True)
self.env.set_warnfunc(self.warn)
def _init_builder(self, buildername):

View File

@ -11,6 +11,9 @@
"""
import re
import string
from docutils import nodes
from sphinx import addnodes
from sphinx.roles import XRefRole
@ -24,7 +27,18 @@ class Domain(object):
roles = {}
label = ''
def __init__(self):
# data value for a fresh environment
initial_data = {
}
# data version
data_version = 0
def __init__(self, env):
self.env = env
self.data = env.domaindata.get(self.name, self.initial_data)
if 'version' in self.data and self.data['version'] < self.data_version:
raise IOError('data of %r domain out of date' % self.label)
self._role_cache = {}
self._directive_cache = {}
@ -35,6 +49,8 @@ class Domain(object):
state['_directive_cache'] = {}
return state
#def clear_doc
def role(self, name):
"""
Return a role adapter function that always gives the registered
@ -492,7 +508,7 @@ class CDesc(DescDirective):
if part[0] in string.ascii_letters+'_' and \
part not in self.stopwords:
pnode = addnodes.pending_xref(
'', reftype='ctype', reftarget=part,
'', refdomain='c', reftype='type', reftarget=part,
modname=None, classname=None)
pnode += tnode
node += pnode

View File

@ -213,9 +213,9 @@ class BuildEnvironment:
env = pickle.load(picklefile)
finally:
picklefile.close()
env.config.values = config.values
if env.version != ENV_VERSION:
raise IOError('env version not current')
env.config.values = config.values
return env
def topickle(self, filename):
@ -224,6 +224,8 @@ class BuildEnvironment:
self.set_warnfunc(None)
values = self.config.values
del self.config.values
domains = self.domains
del self.domains
# first write to a temporary file, so that if dumping fails,
# the existing environment won't be overwritten
picklefile = open(filename + '.tmp', 'wb')
@ -240,6 +242,7 @@ class BuildEnvironment:
picklefile.close()
movefile(filename + '.tmp', filename)
# reset attributes
self.domains = domains
self.config.values = values
self.set_warnfunc(warnfunc)
@ -253,6 +256,9 @@ class BuildEnvironment:
# the application object; only set while update() runs
self.app = None
# all the registered domains, set by the application
self.domains = {}
# the docutils settings for building
self.settings = default_settings.copy()
self.settings['env'] = self
@ -291,6 +297,9 @@ class BuildEnvironment:
self.glob_toctrees = set() # docnames that have :glob: toctrees
self.numbered_toctrees = set() # docnames that have :numbered: toctrees
# domain-specific inventories
self.domaindata = {} # domainname -> object
# X-ref target inventory
self.descrefs = {} # fullname -> docname, desctype
self.modules = {} # modname -> docname, synopsis,
@ -600,14 +609,15 @@ class BuildEnvironment:
return data
# defaults to the global default, but can be re-set in a document
self.default_domain = app.domains.get(self.config.default_domain)
self.default_domain = self.domains.get(self.config.default_domain)
# monkey-patch, so that domain directives take precedence
def directive(directive_name, language_module, document):
directive_name = directive_name.lower()
if ':' in directive_name:
domain_name, directive_name = directive_name.split(':', 1)
if domain_name in app.domains:
domain = app.domains[domain_name]
if domain_name in self.domains:
domain = self.domains[domain_name]
directive = domain.directive(directive_name)
if directive is not None:
return directive, []
@ -620,10 +630,11 @@ class BuildEnvironment:
directives.directive = directive
def role(role_name, language_module, lineno, reporter):
role_name = role_name.lower()
if ':' in role_name:
domain_name, role_name = role_name.split(':', 1)
if domain_name in app.domains:
domain = app.domains[domain_name]
if domain_name in self.domains:
domain = self.domains[domain_name]
role = domain.role(role_name)
if role is not None:
return role, []
@ -1216,7 +1227,7 @@ class BuildEnvironment:
if node.has_key('refdomain'):
# let the domain try to resolve the reference
try:
domain = builder.app.domains[node['refdomain']]
domain = self.domains[node['refdomain']]
except KeyError:
raise NoUri
newnode = domain.resolve_xref(self, fromdocname, builder,
@ -1320,7 +1331,7 @@ class BuildEnvironment:
# no new node found? try the missing-reference event
if newnode is None:
newnode = builder.app.emit_firstresult(
'missing-reference', env, node, contnode)
'missing-reference', self, node, contnode)
except NoUri:
newnode = contnode
node.replace_self(newnode or contnode)

View File

@ -438,6 +438,8 @@ def split_explicit_title(text):
return False, text, text
from docutils import nodes
def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
"""Shortcut to create a reference node."""
node = nodes.reference('', '')
@ -481,8 +483,7 @@ def _new_traverse(self, condition=None,
return self._old_traverse(condition, include_self,
descend, siblings, ascend)
import docutils.nodes
docutils.nodes.Node._old_traverse = docutils.nodes.Node.traverse
docutils.nodes.Node._all_traverse = _all_traverse
docutils.nodes.Node._fast_traverse = _fast_traverse
docutils.nodes.Node.traverse = _new_traverse
nodes.Node._old_traverse = nodes.Node.traverse
nodes.Node._all_traverse = _all_traverse
nodes.Node._fast_traverse = _fast_traverse
nodes.Node.traverse = _new_traverse

View File

@ -43,15 +43,15 @@ Testing description units
C items
=======
.. cfunction:: Sphinx_DoSomething()
.. c:function:: Sphinx_DoSomething()
.. cmember:: SphinxStruct.member
.. c:member:: SphinxStruct.member
.. cmacro:: SPHINX_USE_PYTHON
.. c:macro:: SPHINX_USE_PYTHON
.. ctype:: SphinxType
.. c:type:: SphinxType
.. cvar:: sphinx_global
.. c:var:: sphinx_global
Testing references

View File

@ -21,7 +21,8 @@ warnings = []
def setup_module():
global app, env
app = TestApp(srcdir='(temp)')
env = BuildEnvironment(app.srcdir, app.doctreedir, app.config)
env = app.env
#env = BuildEnvironment(app.srcdir, app.doctreedir, app.config)
env.set_warnfunc(lambda *args: warnings.append(args))
def teardown_module():
@ -51,7 +52,7 @@ def test_images():
tree = env.get_doctree('images')
app._warning.reset()
htmlbuilder = StandaloneHTMLBuilder(app, env)
htmlbuilder = StandaloneHTMLBuilder(app)
htmlbuilder.post_process_images(tree)
assert "no matching candidate for image URI u'foo.*'" in \
app._warning.content[-1]
@ -61,7 +62,7 @@ def test_images():
set(['img.png', 'img1.png', 'simg.png', 'svgimg.svg'])
app._warning.reset()
latexbuilder = LaTeXBuilder(app, env)
latexbuilder = LaTeXBuilder(app)
latexbuilder.post_process_images(tree)
assert "no matching candidate for image URI u'foo.*'" in \
app._warning.content[-1]