Commits

Georg Brandl  committed e2283da

First step of domain handling in environment.

  • Participants
  • Parent commits 646e503

Comments (0)

Files changed (6)

File sphinx/application.py

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

File sphinx/domains.py

 """
 
 import re
+import string
+
+from docutils import nodes
 
 from sphinx import addnodes
 from sphinx.roles import XRefRole
     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 = {}
 
         state['_directive_cache'] = {}
         return state
 
+    #def clear_doc
+
     def role(self, name):
         """
         Return a role adapter function that always gives the registered
             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

File sphinx/environment.py

             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):
         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')
             picklefile.close()
         movefile(filename + '.tmp', filename)
         # reset attributes
+        self.domains = domains
         self.config.values = values
         self.set_warnfunc(warnfunc)
 
         # 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
         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,
                     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, []
         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, []
                 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,
                 # 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)

File sphinx/util/__init__.py

         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('', '')
     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

File tests/root/desc.txt

 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

File tests/test_env.py

 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():
 
     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]
         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]