Commits

Georg Brandl committed 0ac6246

#481, #482: fix ``.name`` reference matching.

#482: When doing a non-exact search, match only the given type of object.
#481: Apply non-exact search for Python reference targets with ``.name`` for modules too.

  • Participants
  • Parent commits 7a4d839

Comments (0)

Files changed (15)

 Release 1.0.2 (in development)
 ==============================
 
+* #482: When doing a non-exact search, match only the given type
+  of object.
+
+* #481: Apply non-exact search for Python reference targets with
+  ``.name`` for modules too.
+
 * #484: Fix crash when duplicating a parameter in an info field list.
 
 * #487: Fix setting the default role to one provided by the
 files.  They also copy the reST source files in the directory ``_sources``
 under the output directory.
 
-The :class:`PickleHTMLBuilder` is a builtin subclass that implements the pickle
+The :class:`.PickleHTMLBuilder` is a builtin subclass that implements the pickle
 serialization interface.
 
 The files per source file have the extensions of
-:attr:`~SerializingHTMLBuilder.out_suffix`, and are arranged in directories
+:attr:`~.SerializingHTMLBuilder.out_suffix`, and are arranged in directories
 just as the source files are.  They unserialize to a dictionary (or dictionary
 like structure) with these keys:
 
 
 The special files are located in the root output directory.  They are:
 
-:attr:`SerializingHTMLBuilder.globalcontext_filename`
+:attr:`.SerializingHTMLBuilder.globalcontext_filename`
    A pickled dict with these keys:
 
    ``project``, ``copyright``, ``release``, ``version``
    ``titles``
       A dictionary of all documents' titles, as HTML strings.
 
-:attr:`SerializingHTMLBuilder.searchindex_filename`
+:attr:`.SerializingHTMLBuilder.searchindex_filename`
    An index that can be used for searching the documentation.  It is a pickled
    list with these entries:
 
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
               'sphinx.ext.autosummary', 'sphinx.ext.extlinks']
 
-#intersphinx_mapping = {'python': ('http://docs.python.org/dev', None)}
-
 master_doc = 'contents'
 templates_path = ['_templates']
 exclude_patterns = ['_build']
      'template generator', '', 1),
 ]
 
+# We're not using intersphinx right now, but if we did, this would be part of
+# the mapping:
+intersphinx_mapping = {'python': ('http://docs.python.org/dev', None)}
+
 
 # -- Extension interface -------------------------------------------------------
 
 
    A boolean that decides whether module names are prepended to all
    :term:`object` names (for object types where a "module" of some kind is
-   defined), e.g. for :rst:dir:`function` directives.  Default is ``True``.
+   defined), e.g. for :rst:dir:`py:function` directives.  Default is ``True``.
 
 .. confval:: show_authors
 
-   A boolean that decides whether :rst:dir:`moduleauthor` and :rst:dir:`sectionauthor`
-   directives produce any output in the built files.
+   A boolean that decides whether :rst:dir:`codeauthor` and
+   :rst:dir:`sectionauthor` directives produce any output in the built files.
 
 .. confval:: modindex_common_prefix
 
 These options influence HTML as well as HTML Help output, and other builders
 that use Sphinx' HTMLWriter class.
 
+.. XXX document html_context
+
 .. confval:: html_theme
 
    The "theme" that the HTML output should use.  See the :doc:`section about
    This will render the template ``customdownload.html`` as the page
    ``download.html``.
 
-   .. note::
-
-      Earlier versions of Sphinx had a value called :confval:`html_index` which
-      was a clumsy way of controlling the content of the "index" document.  If
-      you used this feature, migrate it by adding an ``'index'`` key to this
-      setting, with your custom template as the value, and in your custom
-      template, use ::
-
-         {% extend "defindex.html" %}
-         {% block tables %}
-         ... old template content ...
-         {% endblock %}
-
 .. confval:: html_domain_indices
 
    If true, generate domain-specific indices in addition to the general index.
 .. rst:directive:: .. py:currentmodule:: name
 
    This directive tells Sphinx that the classes, functions etc. documented from
-   here are in the given module (like :rst:dir:`py:module`), but it will not create
-   index entries, an entry in the Global Module Index, or a link target for
-   :rst:role:`mod`.  This is helpful in situations where documentation for things in
-   a module is spread over multiple files or sections -- one location has the
-   :rst:dir:`py:module` directive, the others only :rst:dir:`py:currentmodule`.
+   here are in the given module (like :rst:dir:`py:module`), but it will not
+   create index entries, an entry in the Global Module Index, or a link target
+   for :rst:role:`py:mod`.  This is helpful in situations where documentation
+   for things in a module is spread over multiple files or sections -- one
+   location has the :rst:dir:`py:module` directive, the others only
+   :rst:dir:`py:currentmodule`.
 
 
 The following directives are provided for module and class contents:
 :mod:`codecs` module, ``:py:func:`open``` always refers to the built-in
 function, while ``:py:func:`.open``` refers to :func:`codecs.open`.
 
+A similar heuristic is used to determine whether the name is an attribute of the
+currently documented class.
+
 Also, if the name is prefixed with a dot, and no exact match is found, the
 target is taken as a suffix and all object names with that suffix are
 searched.  For example, ``:py:meth:`.TarFile.close``` references the
 ``tarfile``.  Since this can get ambiguous, if there is more than one possible
 match, you will get a warning from Sphinx.
 
-A similar heuristic is used to determine whether the name is an attribute of the
-currently documented class.
+Note that you can combine the ``~`` and ``.`` prefixes:
+``:py:meth:`~.TarFile.close``` will reference the ``tarfile.TarFile.close()``
+method, but the visible link caption will only be ``close()``.
 
 
 .. _c-domain:

doc/ext/appapi.rst

    standard Sphinx roles (see :ref:`xref-syntax`).
 
    This method is also available under the deprecated alias
-   :meth:`add_description_unit`.
+   ``add_description_unit``.
 
 .. method:: Sphinx.add_crossref_type(directivename, rolename, indextemplate='', ref_nodeclass=None, objname='')
 
    This allows to auto-document new types of objects.  See the source of the
    autodoc module for examples on how to subclass :class:`Documenter`.
 
+   .. XXX add real docs for Documenter and subclassing
+
    .. versionadded:: 0.6
 
 .. method:: Sphinx.add_autodoc_attrgetter(type, getter)

doc/ext/autodoc.rst

 auto-generated-looking pure API documentation.
 
 :mod:`autodoc` provides several directives that are versions of the usual
-:rst:dir:`module`, :rst:dir:`class` and so forth.  On parsing time, they import the
-corresponding module and extract the docstring of the given objects, inserting
-them into the page source under a suitable :rst:dir:`module`, :rst:dir:`class` etc.
-directive.
+:rst:dir:`py:module`, :rst:dir:`py:class` and so forth.  On parsing time, they
+import the corresponding module and extract the docstring of the given objects,
+inserting them into the page source under a suitable :rst:dir:`py:module`,
+:rst:dir:`py:class` etc.  directive.
 
 .. note::
 
-   Just as :rst:dir:`class` respects the current :rst:dir:`module`, :rst:dir:`autoclass`
-   will also do so, and likewise with :rst:dir:`method` and :rst:dir:`class`.
+   Just as :rst:dir:`py:class` respects the current :rst:dir:`py:module`,
+   :rst:dir:`autoclass` will also do so.  Likewise, :rst:dir:`automethod` will
+   respect the current :rst:dir:`py:class`.
 
 
 .. rst:directive:: automodule
-               autoclass
-               autoexception
+                   autoclass
+                   autoexception
 
    Document a module, class or exception.  All three directives will by default
    only insert the docstring of the object itself::
 
      .. versionadded:: 0.4
 
-   * The :rst:dir:`automodule`, :rst:dir:`autoclass` and :rst:dir:`autoexception` directives
-     also support a flag option called ``show-inheritance``.  When given, a list
-     of base classes will be inserted just below the class signature (when used
-     with :rst:dir:`automodule`, this will be inserted for every class that is
-     documented in the module).
+   * The :rst:dir:`automodule`, :rst:dir:`autoclass` and
+     :rst:dir:`autoexception` directives also support a flag option called
+     ``show-inheritance``.  When given, a list of base classes will be inserted
+     just below the class signature (when used with :rst:dir:`automodule`, this
+     will be inserted for every class that is documented in the module).
 
      .. versionadded:: 0.4
 
    * All autodoc directives support the ``noindex`` flag option that has the
-     same effect as for standard :rst:dir:`function` etc. directives: no index
-     entries are generated for the documented object (and all autodocumented
-     members).
+     same effect as for standard :rst:dir:`py:function` etc. directives: no
+     index entries are generated for the documented object (and all
+     autodocumented members).
 
      .. versionadded:: 0.4
 
    * :rst:dir:`automodule` also recognizes the ``synopsis``, ``platform`` and
-     ``deprecated`` options that the standard :rst:dir:`module` directive supports.
+     ``deprecated`` options that the standard :rst:dir:`py:module` directive
+     supports.
 
      .. versionadded:: 0.5
 
 
    ``"class"``
       Only the class' docstring is inserted.  This is the default.  You can
-      still document ``__init__`` as a separate method using :rst:dir:`automethod`
-      or the ``members`` option to :rst:dir:`autoclass`.
+      still document ``__init__`` as a separate method using
+      :rst:dir:`automethod` or the ``members`` option to :rst:dir:`autoclass`.
    ``"both"``
       Both the class' and the ``__init__`` method's docstring are concatenated
       and inserted.

doc/ext/inheritance.rst

 
    This directive has one or more arguments, each giving a module or class
    name.  Class names can be unqualified; in that case they are taken to exist
-   in the currently described module (see :rst:dir:`module`).
+   in the currently described module (see :rst:dir:`py:module`).
 
    For each given class, and each class in each given module, the base classes
    are determined.  Then, from all classes and their base classes, a graph is
 
 .. note::
 
-   :mod:`sphinx.ext.mathbase` is not meant to be added to the
-   :confval:`extensions` config value, instead, use either
-   :mod:`sphinx.ext.pngmath` or :mod:`sphinx.ext.jsmath` as described below.
+   :mod:`.mathbase` is not meant to be added to the :confval:`extensions` config
+   value, instead, use either :mod:`sphinx.ext.pngmath` or
+   :mod:`sphinx.ext.jsmath` as described below.
 
 The input language for mathematics is LaTeX markup.  This is the de-facto
 standard for plain-text math notation and has the added advantage that no
 further translation is necessary when building LaTeX output.
 
-:mod:`mathbase` defines these new markup elements:
+:mod:`.mathbase` defines these new markup elements:
 
 .. rst:role:: math
 

doc/markup/inline.rst

 .. rst:role:: samp
 
    A piece of literal text, such as code.  Within the contents, you can use
-   curly braces to indicate a "variable" part, as in :rst:dir:`file`.  For
+   curly braces to indicate a "variable" part, as in :rst:role:`file`.  For
    example, in ``:samp:`print 1+{variable}```, the part ``variable`` would be
    emphasized.
 

doc/markup/toctree.rst

   :ref:`object descriptions <basic-domain-markup>`, and from :rst:dir:`index`
   directives.
 
-  The module index contains one entry per :rst:dir:`module` directive.
+  The Python module index contains one entry per :rst:dir:`py:module` directive.
 
   The search page contains a form that uses the generated JSON search index and
   JavaScript to full-text search the generated documents for search words; it

doc/templating.rst

   configuration value accordingly.
 
 * You can :ref:`write a custom builder <writing-builders>` that derives from
-  :class:`~sphinx.builders.StandaloneHTMLBuilder` and calls your template engine
-  of choice.
+  :class:`~sphinx.builders.html.StandaloneHTMLBuilder` and calls your template
+  engine of choice.
 
-* You can use the :class:`~sphinx.builders.PickleHTMLBuilder` that produces
+* You can use the :class:`~sphinx.builders.html.PickleHTMLBuilder` that produces
   pickle files with the page contents, and postprocess them using a custom tool,
   or use them in your Web application.
 
 
 .. data:: file_suffix
 
-   The value of the builder's :attr:`out_suffix` attribute, i.e. the file name
-   extension that the output files will get.  For a standard HTML builder, this
-   is usually ``.html``.
+   The value of the builder's :attr:`~.SerializingHTMLBuilder.out_suffix`
+   attribute, i.e. the file name extension that the output files will get.  For
+   a standard HTML builder, this is usually ``.html``.
 
 .. data:: has_source
 

sphinx/domains/python.py

         env.domaindata['py']['modules'][modname] = \
             (env.docname, self.options.get('synopsis', ''),
              self.options.get('platform', ''), 'deprecated' in self.options)
+        # make a duplicate entry in 'objects' to facilitate searching for the
+        # module in PythonDomain.find_obj()
+        env.domaindata['py']['objects'][modname] = (env.docname, 'module')
         targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
         self.state.document.note_explicit_target(targetnode)
         ret = [targetnode]
             if fn == docname:
                 del self.data['modules'][modname]
 
-    def find_obj(self, env, modname, classname, name, type, searchorder=0):
+    def find_obj(self, env, modname, classname, name, type, searchmode=0):
         """
         Find a Python object for "name", perhaps using the given module and/or
         classname.  Returns a list of (name, object entry) tuples.
         matches = []
 
         newname = None
-        if searchorder == 1:
-            if modname and classname and \
-                   modname + '.' + classname + '.' + name in objects:
-                newname = modname + '.' + classname + '.' + name
-            elif modname and modname + '.' + name in objects:
-                newname = modname + '.' + name
-            elif name in objects:
-                newname = name
-            else:
-                # "fuzzy" searching mode
-                searchname = '.' + name
-                matches = [(name, objects[name]) for name in objects
-                           if name.endswith(searchname)]
+        if searchmode == 1:
+            objtypes = self.objtypes_for_role(type)
+            if modname and classname:
+                fullname = modname + '.' + classname + '.' + name
+                if fullname in objects and objects[fullname][1] in objtypes:
+                    newname = fullname
+            if not newname:
+                if modname and modname + '.' + name in objects and \
+                   objects[modname + '.' + name][1] in objtypes:
+                    newname = modname + '.' + name
+                elif name in objects and objects[name][1] in objtypes:
+                    newname = name
+                else:
+                    # "fuzzy" searching mode
+                    searchname = '.' + name
+                    matches = [(name, objects[name]) for name in objects
+                               if name.endswith(searchname)
+                               and objects[name][1] in objtypes]
         else:
+            # NOTE: searching for exact match, object type is not considered
             if name in objects:
                 newname = name
+            elif type == 'mod':
+                # only exact matches allowed for modules
+                return []
             elif classname and classname + '.' + name in objects:
                 newname = classname + '.' + name
             elif modname and modname + '.' + name in objects:
 
     def resolve_xref(self, env, fromdocname, builder,
                      type, target, node, contnode):
-        if (type == 'mod' or
-            type == 'obj' and target in self.data['modules']):
-            docname, synopsis, platform, deprecated = \
-                self.data['modules'].get(target, ('','','', ''))
-            if not docname:
-                return None
-            else:
-                title = '%s%s%s' % ((platform and '(%s) ' % platform),
-                                    synopsis,
-                                    (deprecated and ' (deprecated)' or ''))
-                return make_refnode(builder, fromdocname, docname,
-                                    'module-' + target, contnode, title)
+        modname = node.get('py:module')
+        clsname = node.get('py:class')
+        searchmode = node.hasattr('refspecific') and 1 or 0
+        matches = self.find_obj(env, modname, clsname, target,
+                                type, searchmode)
+        if not matches:
+            return None
+        elif len(matches) > 1:
+            env.warn(fromdocname,
+                     'more than one target found for cross-reference '
+                     '%r: %s' % (target,
+                                 ', '.join(match[0] for match in matches)),
+                     node.line)
+        name, obj = matches[0]
+
+        if obj[1] == 'module':
+            # get additional info for modules
+            docname, synopsis, platform, deprecated = self.data['modules'][name]
+            assert docname == obj[0]
+            title = name
+            if synopsis:
+                title += ': ' + synopsis
+            if deprecated:
+                title += _(' (deprecated)')
+            if platform:
+                title += ' (' + platform + ')'
+            return make_refnode(builder, fromdocname, docname,
+                                'module-' + name, contnode, title)
         else:
-            modname = node.get('py:module')
-            clsname = node.get('py:class')
-            searchorder = node.hasattr('refspecific') and 1 or 0
-            matches = self.find_obj(env, modname, clsname, target,
-                                    type, searchorder)
-            if not matches:
-                return None
-            elif len(matches) > 1:
-                env.warn(fromdocname,
-                         'more than one target found for cross-reference '
-                         '%r: %s' % (target,
-                                     ', '.join(match[0] for match in matches)),
-                         node.line)
-            name, obj = matches[0]
             return make_refnode(builder, fromdocname, obj[0], name,
                                 contnode, name)
 

sphinx/domains/rst.py

     """
 
     def add_target_and_index(self, name, sig, signode):
-        targetname = name + '-' + self.objtype
+        targetname = self.objtype + '-' + name
         if targetname not in self.state.document.ids:
             signode['names'].append(targetname)
             signode['ids'].append(targetname)

sphinx/environment.py

 
 # This is increased every time an environment attribute is added
 # or changed to properly invalidate pickle files.
-ENV_VERSION = 37
+ENV_VERSION = 38
 
 
 default_substitutions = set([