diff options
73 files changed, 506 insertions, 620 deletions
@@ -1,9 +1,44 @@ -Release 1.2.1 (in development) -============================== +Release 1.3 (in development) +============================ + +Incompatible changes +-------------------- + +* Dropped support for Python 2.5 and 3.1. + +* Removed the ``sphinx.ext.oldcmarkup`` extension. + +* A new node, ``sphinx.addnodes.literal_strong``, has been added, for text that + should appear literally (i.e. no smart quotes) in strong font. Custom writers + will have to be adapted to handle this node. + +New features +------------ + +* PR#202: Allow "." and "~" prefixed references in ``:param:`` doc fields + for Python. + +* PR#184: Add :confval:`autodoc_mock_imports`, allowing to mock imports of + external modules that need not be present when autodocumenting. + +* #925: Allow list-typed config values to be provided on the command line, + like ``-D key=val1,val2``. + +* #668: Allow line numbering of ``code-block`` and ``literalinclude`` directives + to start at an arbitrary line number, with a new ``lineno-start`` option. + +* PR#172: The :rst:dir:`code-block` and :rst:dir:`literalinclude` directives now + can have a ``filename`` option that shows a filename before the code in the + output. + +* Prompt for the document language in sphinx-quickstart. Bugs fixed ---------- +* #1174: Fix smart quotes being applied inside roles like :rst:role:`program` or + :rst:role:`makevar`. + * #1335: Fix autosummary template overloading with exclamation prefix like ``{% extends "!autosummary/class.rst" %}`` cause infinite recursive function call. This caused by PR#181. diff --git a/doc/config.rst b/doc/config.rst index 82ecdfdf..e4d9feaf 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -45,7 +45,8 @@ Important points to note: * There is a special object named ``tags`` available in the config file. It can be used to query and change the tags (see :ref:`tags`). Use ``tags.has('tag')`` to query, ``tags.add('tag')`` and ``tags.remove('tag')`` - to change. + to change. Only tags set via the ``-t`` command-line option or via + ``tags.add('tag')`` can be queried using ``tags.has('tag')``. General configuration @@ -120,7 +121,7 @@ General configuration in that case. .. deprecated:: 1.0 - Use :confval:`exclude_patterns` instead. + Use :confval:`exclude_patterns` or :ref:`metadata` instead. .. confval:: exclude_trees diff --git a/doc/domains.rst b/doc/domains.rst index 024edc9a..6c3c4359 100644 --- a/doc/domains.rst +++ b/doc/domains.rst @@ -157,17 +157,6 @@ declarations: The following directives are provided for module and class contents: -.. rst:directive:: .. py:data:: name - - Describes global data in a module, including both variables and values used - as "defined constants." Class and object attributes are not documented - using this environment. - -.. rst:directive:: .. py:exception:: name - - Describes an exception class. The signature can, but need not include - parentheses with constructor arguments. - .. rst:directive:: .. py:function:: name(parameters) Describes a module-level function. The signature should include the @@ -178,11 +167,23 @@ The following directives are provided for module and class contents: For methods you should use :rst:dir:`py:method`. - The description should include information about the parameters required and - how they are used (especially whether mutable objects passed as parameters - are modified), side effects, and possible exceptions. This information can - optionally be given in a structured form, see :ref:`info-field-lists`. A - small example may be provided. + The description normally includes information about the parameters required + and how they are used (especially whether mutable objects passed as + parameters are modified), side effects, and possible exceptions. + + This information can (in any ``py`` directive) optionally be given in a + structured form, see :ref:`info-field-lists`. + +.. rst:directive:: .. py:data:: name + + Describes global data in a module, including both variables and values used + as "defined constants." Class and object attributes are not documented + using this environment. + +.. rst:directive:: .. py:exception:: name + + Describes an exception class. The signature can, but need not include + parentheses with constructor arguments. .. rst:directive:: .. py:class:: name .. py:class:: name(parameters) diff --git a/doc/ext/appapi.rst b/doc/ext/appapi.rst index a6393d40..156dede8 100644 --- a/doc/ext/appapi.rst +++ b/doc/ext/appapi.rst @@ -199,10 +199,13 @@ the following public API: .. index:: pair: function; directive The reference node will be of class ``literal`` (so it will be rendered in a - proportional font, as appropriate for code) unless you give the *ref_nodeclass* - argument, which must be a docutils node class (most useful are - ``docutils.nodes.emphasis`` or ``docutils.nodes.strong`` -- you can also use - ``docutils.nodes.generated`` if you want no further text decoration). + proportional font, as appropriate for code) unless you give the + *ref_nodeclass* argument, which must be a docutils node class. Most useful + are ``docutils.nodes.emphasis`` or ``docutils.nodes.strong`` -- you can also + use ``docutils.nodes.generated`` if you want no further text decoration. If + the text should be treated as literal (e.g. no smart quote replacement), but + not have typewriter styling, use ``sphinx.addnodes.literal_emphasis`` or + ``sphinx.addnodes.literal_strong``. For the role content, you have the same syntactical possibilities as for standard Sphinx roles (see :ref:`xref-syntax`). diff --git a/doc/ext/autodoc.rst b/doc/ext/autodoc.rst index c92fe0c4..94b05423 100644 --- a/doc/ext/autodoc.rst +++ b/doc/ext/autodoc.rst @@ -195,6 +195,12 @@ inserting them into the page source under a suitable :rst:dir:`py:module`, .. versionadded:: 1.2 + * Add a list of modules in the :confval:`autodoc_mock_imports` to prevent + import errors to halt the building process when some external dependencies + are not importable at build time. + + .. versionadded:: 1.3 + .. rst:directive:: autofunction autodata @@ -335,6 +341,14 @@ There are also new config values that you can set: .. versionadded:: 1.1 +.. confval:: autodoc_mock_imports + + This value contains a list of modules to be mocked up. This is useful when + some external dependencies are not met at build time and break the building + process. + + .. versionadded:: 1.3 + Docstring preprocessing ----------------------- diff --git a/doc/ext/oldcmarkup.rst b/doc/ext/oldcmarkup.rst deleted file mode 100644 index 0fdd9fec..00000000 --- a/doc/ext/oldcmarkup.rst +++ /dev/null @@ -1,35 +0,0 @@ -:mod:`sphinx.ext.oldcmarkup` -- Compatibility extension for old C markup -======================================================================== - -.. module:: sphinx.ext.oldcmarkup - :synopsis: Allow further use of the pre-domain C markup -.. moduleauthor:: Georg Brandl - -.. versionadded:: 1.0 - - -This extension is a transition helper for projects that used the old -(pre-domain) C markup, i.e. the directives like ``cfunction`` and roles like -``cfunc``. Since the introduction of domains, they must be called by their -fully-qualified name (``c:function`` and ``c:func``, respectively) or, with the -default domain set to ``c``, by their new name (``function`` and ``func``). -(See :ref:`c-domain` for the details.) - -If you activate this extension, it will register the old names, and you can -use them like before Sphinx 1.0. The directives are: - -- ``cfunction`` -- ``cmember`` -- ``cmacro`` -- ``ctype`` -- ``cvar`` - -The roles are: - -- ``cdata`` -- ``cfunc`` -- ``cmacro`` -- ``ctype`` - -However, it is advised to migrate to the new markup -- this extension is a -compatibility convenience and will disappear in a future version of Sphinx. diff --git a/doc/extensions.rst b/doc/extensions.rst index 334e5039..7597f281 100644 --- a/doc/extensions.rst +++ b/doc/extensions.rst @@ -53,7 +53,6 @@ These extensions are built in and can be activated by respective entries in the ext/extlinks ext/viewcode ext/linkcode - ext/oldcmarkup Third-party extensions diff --git a/doc/install.rst b/doc/install.rst index bf653872..71e37e9c 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -4,7 +4,7 @@ Installing Sphinx ================= Since Sphinx is written in the Python language, you need to install Python -(the required version is at least 2.5) and Sphinx. +(the required version is at least 2.6) and Sphinx. Sphinx packages are available on the `Python Package Index <https://pypi.python.org/pypi/Sphinx>`_. @@ -79,8 +79,8 @@ sidebar and under "Quick Links", click "Windows Installer" to download. .. note:: - Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.2 can run - under Python 2.5 to 2.7 and 3.1 to 3.3, with the recommended version being + Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.3 can run + under Python 2.6, 2.7, 3.2, 3.3, with the recommended version being 2.7. This chapter assumes you have installed Python 2.7. Follow the Windows installer for Python. diff --git a/doc/intro.rst b/doc/intro.rst index 66d0c58d..dd541bf1 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -54,7 +54,7 @@ See the :ref:`pertinent section in the FAQ list <usingwith>`. Prerequisites ------------- -Sphinx needs at least **Python 2.5** or **Python 3.1** to run, as well as the +Sphinx needs at least **Python 2.6** or **Python 3.2** to run, as well as the docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.7 or some (not broken) SVN trunk snapshot. If you like to have source code highlighting support, you must also install the Pygments_ library. diff --git a/doc/invocation.rst b/doc/invocation.rst index 52ee803f..f831dc0a 100644 --- a/doc/invocation.rst +++ b/doc/invocation.rst @@ -124,13 +124,22 @@ The :program:`sphinx-build` script has several options: .. option:: -D setting=value Override a configuration value set in the :file:`conf.py` file. The value - must be a string or dictionary value. For the latter, supply the setting - name and key like this: ``-D latex_elements.docclass=scrartcl``. For boolean - values, use ``0`` or ``1`` as the value. + must be a number, string, list or dictionary value. + + For lists, you can separate elements with a comma like this: ``-D + html_theme_path=path1,path2``. + + For dictionary values, supply the setting name and key like this: + ``-D latex_elements.docclass=scrartcl``. + + For boolean values, use ``0`` or ``1`` as the value. .. versionchanged:: 0.6 The value can now be a dictionary value. + .. versionchanged:: 1.3 + The value can now also be a list value. + .. option:: -A name=value Make the *name* assigned to *value* in the HTML templates. diff --git a/doc/markup/code.rst b/doc/markup/code.rst index 98fdad7d..e9f8f1da 100644 --- a/doc/markup/code.rst +++ b/doc/markup/code.rst @@ -86,6 +86,14 @@ on line numbers for the individual block:: Some more Ruby code. +The first line number can be selected with the ``lineno-start`` option. If +present, ``linenos`` is automatically activated as well. + + .. code-block:: ruby + :lineno-start: 10 + + Some more Ruby code, with line numbering starting at 10. + Additionally, an ``emphasize-lines`` option can be given to have Pygments emphasize particular lines:: @@ -101,6 +109,9 @@ emphasize particular lines:: .. versionchanged:: 1.1 ``emphasize-lines`` has been added. +.. versionchanged:: 1.3 + ``lineno-start`` has been added. + Includes ^^^^^^^^ @@ -121,10 +132,11 @@ Includes Tabs in the input are expanded if you give a ``tab-width`` option with the desired tab width. - The directive also supports the ``linenos`` flag option to switch on line - numbers, the ``emphasize-lines`` option to emphasize particular lines, and - a ``language`` option to select a language different from the current - file's standard language. Example with options:: + Like :rst:dir:`code-block`, the directive supports the ``linenos`` flag + option to switch on line numbers, the ``lineno-start`` option to select the + first line number, the ``emphasize-lines`` option to emphasize particular + lines, and a ``language`` option to select a language different from the + current file's standard language. Example with options:: .. literalinclude:: example.rb :language: ruby @@ -176,6 +188,25 @@ Includes The ``prepend`` and ``append`` options, as well as ``tab-width``. +Showing a file name +^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 1.3 + +A ``filename`` option can be given to show that name before the code block. For +example:: + + .. code-block:: python + :filename: this.py + + print 'Explicit is better than implicit.' + + +:rst:dir:`literalinclude` also supports the ``filename`` option, with the +additional feature that if you leave the value empty, the shown filename will be +exactly the one given as an argument. + + .. rubric:: Footnotes .. [1] There is a standard ``.. include`` directive, but it raises errors if the diff --git a/doc/markup/toctree.rst b/doc/markup/toctree.rst index 9316e69a..fdecc37d 100644 --- a/doc/markup/toctree.rst +++ b/doc/markup/toctree.rst @@ -141,8 +141,9 @@ tables of contents. The ``toctree`` directive is the central element. In the end, all documents in the :term:`source directory` (or subdirectories) must occur in some ``toctree`` directive; Sphinx will emit a warning if it finds a file that is not included, because that means that this file will not - be reachable through standard navigation. Use :confval:`exclude_patterns` to - explicitly exclude documents or directories from building. + be reachable through standard navigation. Use :ref:`metadata` to remove the + warning, and :confval:`exclude_patterns` to explicitly exclude documents or + directories from building. The "master document" (selected by :confval:`master_doc`) is the "root" of the TOC tree hierarchy. It can be used as the documentation's main page, or @@ -44,20 +44,20 @@ A development egg can be found `here <http://bitbucket.org/birkenfeld/sphinx/get/tip.gz#egg=Sphinx-dev>`_. ''' +if sys.version_info < (2, 6) or (3, 0) <= sys.version_info < (3, 2): + print('ERROR: Sphinx requires at least Python 2.6 or 3.2 to run.') + sys.exit(1) + requires = ['Pygments>=1.2', 'docutils>=0.7'] if sys.version_info[:3] >= (3, 3, 0): requires[1] = 'docutils>=0.10' -if sys.version_info < (2, 6) or (3, 0) <= sys.version_info < (3, 3): +if (3, 0) <= sys.version_info < (3, 3): requires.append('Jinja2>=2.3,<2.7') -else: +else: # 2.6, 2.7, 3.3 or later requires.append('Jinja2>=2.3') -if sys.version_info < (2, 5): - print('ERROR: Sphinx requires at least Python 2.5 to run.') - sys.exit(1) - # tell distribute to use 2to3 with our own fixers extra = {} if sys.version_info >= (3, 0): diff --git a/sphinx/__init__.py b/sphinx/__init__.py index 8a1b97f7..c1e9e38d 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -15,12 +15,12 @@ import sys from os import path -__version__ = '1.2+' -__released__ = '1.2' # used when Sphinx builds its own docs +__version__ = '1.3a0' +__released__ = '1.3a0' # used when Sphinx builds its own docs # version info for better programmatic use # possible values for 3rd element: 'alpha', 'beta', 'rc', 'final' # 'final' has 0 as the last element -version_info = (1, 2, 0, 'final', 0) +version_info = (1, 3, 0, 'alpha', 0) package_dir = path.abspath(path.dirname(__file__)) @@ -42,8 +42,9 @@ if '+' in __version__ or 'pre' in __version__: def main(argv=sys.argv): """Sphinx build "main" command-line entry.""" - if sys.version_info[:3] < (2, 5, 0): - sys.stderr.write('Error: Sphinx requires at least Python 2.5 to run.\n') + if (sys.version_info[:3] < (2, 6, 0) or + (3, 0, 0) <= sys.version_info[:3] < (3, 2, 0)): + sys.stderr.write('Error: Sphinx requires at least Python 2.6 to run.\n') return 1 try: from sphinx import cmdline diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py index d8dca2ce..e3f6d7d6 100644 --- a/sphinx/addnodes.py +++ b/sphinx/addnodes.py @@ -168,6 +168,11 @@ class literal_emphasis(nodes.emphasis): applied (e.g. smartypants for HTML output). """ +class literal_strong(nodes.strong): + """Node that behaves like `strong`, but further text processors are not + applied (e.g. smartypants for HTML output). + """ + class abbreviation(nodes.Inline, nodes.TextElement): """Node for abbreviations with explanations.""" diff --git a/sphinx/application.py b/sphinx/application.py index ceb7c32c..6b86b181 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -15,6 +15,7 @@ import os import sys import types import posixpath +import traceback from os import path from cStringIO import StringIO @@ -112,8 +113,6 @@ class Sphinx(object): if self.confdir is None: self.confdir = self.srcdir - # backwards compatibility: activate old C markup - self.setup_extension('sphinx.ext.oldcmarkup') # load all user-given extension modules for extension in self.config.extensions: self.setup_extension(extension) @@ -122,7 +121,7 @@ class Sphinx(object): self.config.setup(self) # now that we know all config values, collect them from conf.py - self.config.init_values() + self.config.init_values(self.warn) # check the Sphinx version if requested if self.config.needs_sphinx and \ @@ -282,6 +281,7 @@ class Sphinx(object): try: mod = __import__(extension, None, None, ['setup']) except ImportError, err: + self.verbose('Original exception:\n' + traceback.format_exc()) raise ExtensionError('Could not import extension %s' % extension, err) if not hasattr(mod, 'setup'): diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py index 1dfcc704..35061b79 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -12,7 +12,6 @@ import os import re -import sys import time import codecs import zipfile @@ -750,12 +749,5 @@ class EpubBuilder(StandaloneHTMLBuilder): zipfile.ZIP_STORED) for file in projectfiles: fp = path.join(outdir, file) - if sys.version_info < (2, 6): - # When zipile.ZipFile.write call with unicode filename, ZipFile - # encode filename to 'utf-8' (only after Python-2.6). - if isinstance(file, unicode): - # OEBPS Container Format (OCF) 2.0.1 specification require - # "File Names MUST be UTF-8 encoded". - file = file.encode('utf-8') epub.write(fp, file, zipfile.ZIP_DEFLATED) epub.close() diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index dd62e2ba..b6ebf926 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -16,11 +16,7 @@ import codecs import posixpath import cPickle as pickle from os import path -try: - from hashlib import md5 -except ImportError: - # 2.4 compatibility - from md5 import md5 +from hashlib import md5 from docutils import nodes from docutils.io import DocTreeInput, StringOutput @@ -35,7 +31,7 @@ from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \ movefile, ustrftime, copyfile from sphinx.util.nodes import inline_all_toctrees from sphinx.util.matching import patmatch, compile_matchers -from sphinx.util.pycompat import any, b +from sphinx.util.pycompat import b from sphinx.errors import SphinxError from sphinx.locale import _ from sphinx.search import js_index @@ -1098,8 +1094,4 @@ class JSONHTMLBuilder(SerializingHTMLBuilder): searchindex_filename = 'searchindex.json' def init(self): - if jsonimpl.json is None: - raise SphinxError( - 'The module simplejson (or json in Python >= 2.6) ' - 'is not available. The JSONHTMLBuilder builder will not work.') SerializingHTMLBuilder.init(self) diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index 6cbe361b..171e68d5 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -10,7 +10,6 @@ """ import re -import sys import Queue import socket import threading @@ -110,7 +109,7 @@ class CheckExternalLinksBuilder(Builder): def check_thread(self): kwargs = {} - if sys.version_info > (2, 5) and self.app.config.linkcheck_timeout: + if self.app.config.linkcheck_timeout: kwargs['timeout'] = self.app.config.linkcheck_timeout def check(): diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py index f4a09e16..fdb47dec 100644 --- a/sphinx/cmdline.py +++ b/sphinx/cmdline.py @@ -181,14 +181,11 @@ def main(argv): print >>sys.stderr, ('Error: -D option argument must be ' 'in the form name=value.') return 1 - try: - val = int(val) - except ValueError: - if likely_encoding and isinstance(val, bytes): - try: - val = val.decode(likely_encoding) - except UnicodeError: - pass + if likely_encoding and isinstance(val, bytes): + try: + val = val.decode(likely_encoding) + except UnicodeError: + pass confoverrides[key] = val elif opt == '-A': try: diff --git a/sphinx/config.py b/sphinx/config.py index 8b15bdf3..df74e914 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -214,8 +214,11 @@ class Config(object): self.overrides = overrides self.values = Config.config_values.copy() config = {} - if "extensions" in overrides: - config["extensions"] = overrides["extensions"] + if 'extensions' in overrides: + if isinstance(overrides['extensions'], (str, unicode)): + config['extensions'] = overrides.pop('extensions').split(',') + else: + config['extensions'] = overrides.pop('extensions') if dirname is not None: config_file = path.join(dirname, filename) config['__file__'] = config_file @@ -248,12 +251,36 @@ class Config(object): 'Please use Unicode strings, e.g. %r.' % (name, u'Content') ) - def init_values(self): + def init_values(self, warn): config = self._raw_config for valname, value in self.overrides.iteritems(): if '.' in valname: realvalname, key = valname.split('.', 1) config.setdefault(realvalname, {})[key] = value + continue + elif valname not in self.values: + warn('unknown config value %r in override, ignoring' % valname) + continue + defvalue = self.values[valname][0] + if isinstance(value, (str, unicode)): + if isinstance(defvalue, dict): + warn('cannot override dictionary config setting %r, ' + 'ignoring (use %r to set individual elements)' % + (valname, valname + '.key=value')) + continue + elif isinstance(defvalue, list): + config[valname] = value.split(',') + elif isinstance(defvalue, (int, long)): + try: + config[valname] = int(value) + except ValueError: + warn('invalid number %r for config value %r, ignoring' + % (value, valname)) + elif defvalue is not None and not isinstance(defvalue, (str, unicode)): + warn('cannot override config setting %r with unsupported type, ' + 'ignoring' % valname) + else: + config[valname] = value else: config[valname] = value for name in config: diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index 4d43e5ff..6900ea6b 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -56,7 +56,9 @@ class CodeBlock(Directive): final_argument_whitespace = False option_spec = { 'linenos': directives.flag, + 'lineno-start': int, 'emphasize-lines': directives.unchanged_required, + 'filename': directives.unchanged_required, } def run(self): @@ -75,9 +77,16 @@ class CodeBlock(Directive): literal = nodes.literal_block(code, code) literal['language'] = self.arguments[0] - literal['linenos'] = 'linenos' in self.options + filename = self.options.get('filename') + if filename: + literal['filename'] = filename + literal['linenos'] = 'linenos' in self.options or \ + 'lineno-start' in self.options + extra_args = literal['highlight_args'] = {} if hl_lines is not None: - literal['highlight_args'] = {'hl_lines': hl_lines} + extra_args['hl_lines'] = hl_lines + if 'lineno-start' in self.options: + extra_args['linenostart'] = self.options['lineno-start'] set_source_info(self, literal) return [literal] @@ -95,6 +104,7 @@ class LiteralInclude(Directive): final_argument_whitespace = True option_spec = { 'linenos': directives.flag, + 'lineno-start': int, 'tab-width': int, 'language': directives.unchanged_required, 'encoding': directives.encoding, @@ -105,6 +115,7 @@ class LiteralInclude(Directive): 'prepend': directives.unchanged_required, 'append': directives.unchanged_required, 'emphasize-lines': directives.unchanged_required, + 'filename': directives.unchanged, } def run(self): @@ -204,10 +215,18 @@ class LiteralInclude(Directive): set_source_info(self, retnode) if self.options.get('language', ''): retnode['language'] = self.options['language'] - if 'linenos' in self.options: - retnode['linenos'] = True + retnode['linenos'] = 'linenos' in self.options or \ + 'lineno-start' in self.options + filename = self.options.get('filename') + if filename is not None: + if not filename: + filename = self.arguments[0] + retnode['filename'] = filename + extra_args = retnode['highlight_args'] = {} if hl_lines is not None: - retnode['highlight_args'] = {'hl_lines': hl_lines} + extra_args['hl_lines'] = hl_lines + if 'lineno-start' in self.options: + extra_args['linenostart'] = self.options['lineno-start'] env.note_dependency(rel_filename) return [retnode] diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index a7ed7557..6714e838 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -81,6 +81,23 @@ def _pseudo_parse_arglist(signode, arglist): signode += paramlist +# This override allows our inline type specifiers to behave like :class: link +# when it comes to handling "." and "~" prefixes. +class PyTypedField(TypedField): + def make_xref(self, rolename, domain, target, innernode=nodes.emphasis): + result = super(PyTypedField, self).make_xref(rolename, domain, target, + innernode) + if target.startswith('.'): + result['reftarget'] = target[1:] + result['refspecific'] = True + result[0][0] = nodes.Text(target[1:]) + if target.startswith('~'): + result['reftarget'] = target[1:] + title = target.split('.')[-1] + result[0][0] = nodes.Text(title) + return result + + class PyObject(ObjectDescription): """ Description of a general Python object. @@ -92,7 +109,7 @@ class PyObject(ObjectDescription): } doc_field_types = [ - TypedField('parameter', label=l_('Parameters'), + PyTypedField('parameter', label=l_('Parameters'), names=('param', 'parameter', 'arg', 'argument', 'keyword', 'kwarg', 'kwparam'), typerolename='obj', typenames=('paramtype', 'type'), diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index c454641b..86837ff8 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -29,7 +29,7 @@ from sphinx.util.nodes import nested_parse_with_titles from sphinx.util.compat import Directive from sphinx.util.inspect import getargspec, isdescriptor, safe_getmembers, \ safe_getattr, safe_repr, is_builtin_class_method -from sphinx.util.pycompat import base_exception, class_types +from sphinx.util.pycompat import class_types from sphinx.util.docstrings import prepare_docstring @@ -70,6 +70,35 @@ class Options(dict): return None +class _MockModule(object): + """Used by autodoc_mock_imports.""" + def __init__(self, *args, **kwargs): + pass + + def __call__(self, *args, **kwargs): + return _MockModule() + + @classmethod + def __getattr__(cls, name): + if name in ('__file__', '__path__'): + return '/dev/null' + elif name[0] == name[0].upper(): + # Not very good, we assume Uppercase names are classes... + mocktype = type(name, (), {}) + mocktype.__module__ = __name__ + return mocktype + else: + return _MockModule() + +def mock_import(modname): + if '.' in modname: + pkg, _n, mods = modname.rpartition('.') + mock_import(pkg) + mod = _MockModule() + sys.modules[modname] = mod + return mod + + ALL = object() INSTANCEATTR = object() @@ -332,6 +361,9 @@ class Documenter(object): self.modname, '.'.join(self.objpath)) try: dbg('[autodoc] import %s', self.modname) + for modname in self.env.config.autodoc_mock_imports: + dbg('[autodoc] adding a mock module %s!', self.modname) + mock_import(modname) __import__(self.modname) parent = None obj = self.module = sys.modules[self.modname] @@ -1130,7 +1162,7 @@ class ExceptionDocumenter(ClassDocumenter): @classmethod def can_document_member(cls, member, membername, isattr, parent): return isinstance(member, class_types) and \ - issubclass(member, base_exception) + issubclass(member, BaseException) class DataDocumenter(ModuleLevelDocumenter): @@ -1453,6 +1485,7 @@ def setup(app): app.add_config_value('autodoc_member_order', 'alphabetic', True) app.add_config_value('autodoc_default_flags', [], True) app.add_config_value('autodoc_docstring_signature', True, True) + app.add_config_value('autodoc_mock_imports', [], True) app.add_event('autodoc-process-docstring') app.add_event('autodoc-process-signature') app.add_event('autodoc-skip-member') diff --git a/sphinx/ext/oldcmarkup.py b/sphinx/ext/oldcmarkup.py deleted file mode 100644 index aa10246b..00000000 --- a/sphinx/ext/oldcmarkup.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -""" - sphinx.ext.oldcmarkup - ~~~~~~~~~~~~~~~~~~~~~ - - Extension for compatibility with old C markup (directives and roles). - - :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" - -from docutils.parsers.rst import directives - -from sphinx.util.compat import Directive - -_warned_oldcmarkup = False -WARNING_MSG = 'using old C markup; please migrate to new-style markup ' \ - '(e.g. c:function instead of cfunction), see ' \ - 'http://sphinx-doc.org/domains.html' - - -class OldCDirective(Directive): - has_content = True - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = { - 'noindex': directives.flag, - 'module': directives.unchanged, - } - - def run(self): - env = self.state.document.settings.env - if not env.app._oldcmarkup_warned: - self.state_machine.reporter.warning(WARNING_MSG, line=self.lineno) - env.app._oldcmarkup_warned = True - newname = 'c:' + self.name[1:] - newdir = env.lookup_domain_element('directive', newname)[0] - return newdir(newname, self.arguments, self.options, - self.content, self.lineno, self.content_offset, - self.block_text, self.state, self.state_machine).run() - - -def old_crole(typ, rawtext, text, lineno, inliner, options={}, content=[]): - env = inliner.document.settings.env - if not typ: - typ = env.config.default_role - if not env.app._oldcmarkup_warned: - inliner.reporter.warning(WARNING_MSG, line=lineno) - env.app._oldcmarkup_warned = True - newtyp = 'c:' + typ[1:] - newrole = env.lookup_domain_element('role', newtyp)[0] - return newrole(newtyp, rawtext, text, lineno, inliner, options, content) - - -def setup(app): - app._oldcmarkup_warned = False - app.add_directive('cfunction', OldCDirective) - app.add_directive('cmember', OldCDirective) - app.add_directive('cmacro', OldCDirective) - app.add_directive('ctype', OldCDirective) - app.add_directive('cvar', OldCDirective) - app.add_role('cdata', old_crole) - app.add_role('cfunc', old_crole) - app.add_role('cmacro', old_crole) - app.add_role('ctype', old_crole) - app.add_role('cmember', old_crole) diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index de5d2b9f..253ae07d 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -171,4 +171,3 @@ def setup(app): app.connect('doctree-read', process_todos) app.connect('doctree-resolved', process_todo_nodes) app.connect('env-purge-doc', purge_todos) - diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index 2c95dec0..c30c9ef3 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -63,12 +63,6 @@ _LATEX_STYLES = r''' \newcommand\PYGZcb{\char`\}} ''' -parsing_exceptions = (SyntaxError, UnicodeEncodeError) -if sys.version_info < (2, 5): - # Python <= 2.4 raises MemoryError when parsing an - # invalid encoding cookie - parsing_exceptions += MemoryError, - class PygmentsBridge(object): # Set these attributes if you want to have different Pygments formatters @@ -131,10 +125,6 @@ class PygmentsBridge(object): # lines beginning with "..." are probably placeholders for suite src = re.sub(r"(?m)^(\s*)" + mark + "(.)", r"\1"+ mark + r"# \2", src) - # if we're using 2.5, use the with statement - if sys.version_info >= (2, 5): - src = 'from __future__ import with_statement\n' + src - if sys.version_info < (3, 0) and isinstance(src, unicode): # Non-ASCII chars will only occur in string literals # and comments. If we wanted to give them to the parser @@ -143,18 +133,12 @@ class PygmentsBridge(object): # just replace all non-ASCII characters. src = src.encode('ascii', 'replace') - if (3, 0) <= sys.version_info < (3, 2): - # Python 3.1 can't process '\r' as linesep. - # `parser.suite("print('hello')\r\n")` cause error. - if '\r\n' in src: - src = src.replace('\r\n', '\n') - if parser is None: return True try: parser.suite(src) - except parsing_exceptions: + except (SyntaxError, UnicodeEncodeError): return False else: return True diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py index 2c0708f9..54e79da6 100644 --- a/sphinx/pycode/__init__.py +++ b/sphinx/pycode/__init__.py @@ -17,7 +17,7 @@ from sphinx.errors import PycodeError from sphinx.pycode import nodes from sphinx.pycode.pgen2 import driver, token, tokenize, parse, literals from sphinx.util import get_module_source, detect_encoding -from sphinx.util.pycompat import next, StringIO, BytesIO, TextIOWrapper +from sphinx.util.pycompat import StringIO, BytesIO, TextIOWrapper from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc diff --git a/sphinx/pycode/pgen2/parse.c b/sphinx/pycode/pgen2/parse.c index e09f5058..96fa6c8b 100644 --- a/sphinx/pycode/pgen2/parse.c +++ b/sphinx/pycode/pgen2/parse.c @@ -353,95 +353,6 @@ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name); /*proto*/ -#if PY_VERSION_HEX < 0x02050000 -#ifndef PyAnySet_CheckExact - -#define PyAnySet_CheckExact(ob) \ - ((ob)->ob_type == &PySet_Type || \ - (ob)->ob_type == &PyFrozenSet_Type) - -#define PySet_New(iterable) \ - PyObject_CallFunctionObjArgs((PyObject *)&PySet_Type, (iterable), NULL) - -#define Pyx_PyFrozenSet_New(iterable) \ - PyObject_CallFunctionObjArgs((PyObject *)&PyFrozenSet_Type, (iterable), NULL) - -#define PySet_Size(anyset) \ - PyObject_Size((anyset)) - -#define PySet_Contains(anyset, key) \ - PySequence_Contains((anyset), (key)) - -#define PySet_Pop(set) \ - PyObject_CallMethod(set, (char *)"pop", NULL) - -static INLINE int PySet_Clear(PyObject *set) { - PyObject *ret = PyObject_CallMethod(set, (char *)"clear", NULL); - if (!ret) return -1; - Py_DECREF(ret); return 0; -} - -static INLINE int PySet_Discard(PyObject *set, PyObject *key) { - PyObject *ret = PyObject_CallMethod(set, (char *)"discard", (char *)"O", key); - if (!ret) return -1; - Py_DECREF(ret); return 0; -} - -static INLINE int PySet_Add(PyObject *set, PyObject *key) { - PyObject *ret = PyObject_CallMethod(set, (char *)"add", (char *)"O", key); - if (!ret) return -1; - Py_DECREF(ret); return 0; -} - -#endif /* PyAnySet_CheckExact (<= Py2.4) */ - -#if PY_VERSION_HEX < 0x02040000 -#ifndef Py_SETOBJECT_H -#define Py_SETOBJECT_H - -static PyTypeObject *__Pyx_PySet_Type = NULL; -static PyTypeObject *__Pyx_PyFrozenSet_Type = NULL; - -#define PySet_Type (*__Pyx_PySet_Type) -#define PyFrozenSet_Type (*__Pyx_PyFrozenSet_Type) - -#define PyAnySet_Check(ob) \ - (PyAnySet_CheckExact(ob) || \ - PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \ - PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type)) - -#define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type) - -static int __Pyx_Py23SetsImport(void) { - PyObject *sets=0, *Set=0, *ImmutableSet=0; - - sets = PyImport_ImportModule((char *)"sets"); - if (!sets) goto bad; - Set = PyObject_GetAttrString(sets, (char *)"Set"); - if (!Set) goto bad; - ImmutableSet = PyObject_GetAttrString(sets, (char *)"ImmutableSet"); - if (!ImmutableSet) goto bad; - Py_DECREF(sets); - - __Pyx_PySet_Type = (PyTypeObject*) Set; - __Pyx_PyFrozenSet_Type = (PyTypeObject*) ImmutableSet; - - return 0; - - bad: - Py_XDECREF(sets); - Py_XDECREF(Set); - Py_XDECREF(ImmutableSet); - return -1; -} - -#else -static int __Pyx_Py23SetsImport(void) { return 0; } -#endif /* !Py_SETOBJECT_H */ -#endif /* < Py2.4 */ -#endif /* < Py2.5 */ - - static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { PyObject *r; if (!j) return NULL; diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index d9449f74..fd358532 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -11,6 +11,7 @@ import sys, os, time, re from os import path +from io import open TERM_ENCODING = getattr(sys.stdin, 'encoding', None) @@ -21,7 +22,6 @@ from sphinx.util.osutil import make_filename from sphinx.util.console import purple, bold, red, turquoise, \ nocolor, color_terminal from sphinx.util import texescape -from sphinx.util.pycompat import open # function to get input from terminal -- overridden by the test suite try: @@ -99,7 +99,10 @@ release = '%(release_str)s' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = %(language)r # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: @@ -320,7 +323,7 @@ epub_copyright = u'%(copyright_str)s' #epub_theme = 'epub' # The language of the text. It defaults to the language option -# or en if the language is not set. +# or 'en' if the language is not set. #epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. @@ -1018,6 +1021,7 @@ def ask_user(d): * author: author names * version: version of project * release: release of project + * language: document language * suffix: source file suffix * master: master document name * epub: use epub (bool) @@ -1084,6 +1088,18 @@ just set both to the same value.''' if 'release' not in d: do_prompt(d, 'release', 'Project release', d['version']) + if 'language' not in d: + print ''' +If the documents are to be written in a language other than English, +you can select a language here by its language code. Sphinx will then +translate text that it generates into that language. + +For a list of supported codes, see +http://sphinx-doc.org/config.html#confval-language.''' + do_prompt(d, 'language', 'Project language', 'en') + if d['language'] == 'en': + d['language'] = None + if 'suffix' not in d: print ''' The file name suffix for source files. Commonly, this is either ".txt" diff --git a/sphinx/roles.py b/sphinx/roles.py index 6703b6b8..3b858588 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -22,15 +22,15 @@ from sphinx.util.nodes import split_explicit_title, process_index_entry, \ generic_docroles = { - 'command' : nodes.strong, + 'command' : addnodes.literal_strong, 'dfn' : nodes.emphasis, 'kbd' : nodes.literal, 'mailheader' : addnodes.literal_emphasis, - 'makevar' : nodes.strong, + 'makevar' : addnodes.literal_strong, 'manpage' : addnodes.literal_emphasis, 'mimetype' : addnodes.literal_emphasis, 'newsgroup' : addnodes.literal_emphasis, - 'program' : nodes.strong, # XXX should be an x-ref + 'program' : addnodes.literal_strong, # XXX should be an x-ref 'regexp' : nodes.literal, } diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile index 6b87ad88..5e6030c0 100644 --- a/sphinx/texinputs/Makefile +++ b/sphinx/texinputs/Makefile @@ -9,6 +9,10 @@ ARCHIVEPRREFIX = # Additional LaTeX options LATEXOPTS = +LATEX = latex +PDFLATEX = pdflatex +MAKEINDEX = makeindex + all: $(ALLPDF) all-pdf: $(ALLPDF) all-dvi: $(ALLDVI) @@ -43,20 +47,20 @@ bz2: tar # The number of LaTeX runs is quite conservative, but I don't expect it # to get run often, so the little extra time won't hurt. %.dvi: %.tex - latex $(LATEXOPTS) '$<' - latex $(LATEXOPTS) '$<' - latex $(LATEXOPTS) '$<' - -makeindex -s python.ist '$(basename $<).idx' - latex $(LATEXOPTS) '$<' - latex $(LATEXOPTS) '$<' + $(LATEX) $(LATEXOPTS) '$<' + $(LATEX) $(LATEXOPTS) '$<' + $(LATEX) $(LATEXOPTS) '$<' + -$(MAKEINDEX) -s python.ist '$(basename $<).idx' + $(LATEX) $(LATEXOPTS) '$<' + $(LATEX) $(LATEXOPTS) '$<' %.pdf: %.tex - pdflatex $(LATEXOPTS) '$<' - pdflatex $(LATEXOPTS) '$<' - pdflatex $(LATEXOPTS) '$<' - -makeindex -s python.ist '$(basename $<).idx' - pdflatex $(LATEXOPTS) '$<' - pdflatex $(LATEXOPTS) '$<' + $(PDFLATEX) $(LATEXOPTS) '$<' + $(PDFLATEX) $(LATEXOPTS) '$<' + $(PDFLATEX) $(LATEXOPTS) '$<' + -$(MAKEINDEX) -s python.ist '$(basename $<).idx' + $(PDFLATEX) $(LATEXOPTS) '$<' + $(PDFLATEX) $(LATEXOPTS) '$<' clean: rm -f *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla diff --git a/sphinx/themes/agogo/layout.html b/sphinx/themes/agogo/layout.html index fde19dbc..f2ddb217 100644 --- a/sphinx/themes/agogo/layout.html +++ b/sphinx/themes/agogo/layout.html @@ -11,7 +11,7 @@ {%- extends "basic/layout.html" %} {% block header %} - <div class="header-wrapper"> + <div class="header-wrapper" role="banner"> <div class="header"> {%- if logo %} <p class="logo"><a href="{{ pathto(master_doc) }}"> @@ -22,7 +22,7 @@ <div class="headertitle"><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a></div> {%- endblock %} - <div class="rel"> + <div class="rel" role="navigation" aria-label="related navigation"> {%- for rellink in rellinks|reverse %} <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}" {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a> @@ -47,16 +47,18 @@ {{ toctree() }} {%- endblock %} {%- block sidebarsearch %} - <h3 style="margin-top: 1.5em;">{{ _('Search') }}</h3> - <form class="search" action="{{ pathto('search') }}" method="get"> - <input type="text" name="q" /> - <input type="submit" value="{{ _('Go') }}" /> - <input type="hidden" name="check_keywords" value="yes" /> - <input type="hidden" name="area" value="default" /> - </form> - <p class="searchtip" style="font-size: 90%"> - {{ _('Enter search terms or a module, class or function name.') }} - </p> + <div role="search"> + <h3 style="margin-top: 1.5em;">{{ _('Search') }}</h3> + <form class="search" action="{{ pathto('search') }}" method="get"> + <input type="text" name="q" /> + <input type="submit" value="{{ _('Go') }}" /> + <input type="hidden" name="check_keywords" value="yes" /> + <input type="hidden" name="area" value="default" /> + </form> + <p class="searchtip" style="font-size: 90%"> + {{ _('Enter search terms or a module, class or function name.') }} + </p> + </div> {%- endblock %} </div> <div class="clearer"></div> @@ -68,16 +70,20 @@ <div class="footer-wrapper"> <div class="footer"> <div class="left"> - {%- for rellink in rellinks|reverse %} - <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}" - {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a> - {%- if not loop.last %}{{ reldelim2 }}{% endif %} - {%- endfor %} - {%- if show_source and has_source and sourcename %} - <br/> - <a href="{{ pathto('_sources/' + sourcename, true)|e }}" - rel="nofollow">{{ _('Show Source') }}</a> - {%- endif %} + <div role="navigation" aria-label="related navigaton"> + {%- for rellink in rellinks|reverse %} + <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}" + {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a> + {%- if not loop.last %}{{ reldelim2 }}{% endif %} + {%- endfor %} + </div> + <div role="note" aria-label="source link"> + {%- if show_source and has_source and sourcename %} + <br/> + <a href="{{ pathto('_sources/' + sourcename, true)|e }}" + rel="nofollow">{{ _('Show Source') }}</a> + {%- endif %} + </div> </div> <div class="right"> diff --git a/sphinx/themes/agogo/static/agogo.css_t b/sphinx/themes/agogo/static/agogo.css_t index 3fb81178..4c7eb378 100644 --- a/sphinx/themes/agogo/static/agogo.css_t +++ b/sphinx/themes/agogo/static/agogo.css_t @@ -462,3 +462,10 @@ div.viewcode-block:target { border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } + +div.code-block-filename { + background-color: #ddd; + color: #333; + padding: 2px 5px; + font-size: small; +} diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index 9e4e39a1..68a070b3 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -25,7 +25,7 @@ {%- endif %} {%- macro relbar() %} - <div class="related"> + <div class="related" role="navigation" aria-label="related navigation"> <h3>{{ _('Navigation') }}</h3> <ul> {%- for rellink in rellinks %} @@ -47,7 +47,7 @@ {%- macro sidebar() %} {%- if render_sidebar %} - <div class="sphinxsidebar"> + <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> <div class="sphinxsidebarwrapper"> {%- block sidebarlogo %} {%- if logo %} @@ -152,7 +152,7 @@ {%- endblock %} {%- block extrahead %} {% endblock %} </head> - <body> + <body role="document"> {%- block header %}{% endblock %} {%- block relbar1 %}{{ relbar() }}{% endblock %} @@ -166,7 +166,7 @@ {%- if render_sidebar %} <div class="bodywrapper"> {%- endif %} - <div class="body"> + <div class="body" role="main"> {% block body %} {% endblock %} </div> {%- if render_sidebar %} @@ -183,7 +183,7 @@ {%- block relbar2 %}{{ relbar() }}{% endblock %} {%- block footer %} - <div class="footer"> + <div class="footer" role="contentinfo"> {%- if show_copyright %} {%- if hasdoc('copyright') %} {% trans path=pathto('copyright'), copyright=copyright|e %}© <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %} diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html index 609aac83..0a573c32 100644 --- a/sphinx/themes/basic/searchbox.html +++ b/sphinx/themes/basic/searchbox.html @@ -8,7 +8,7 @@ :license: BSD, see LICENSE for details. #} {%- if pagename != "search" %} -<div id="searchbox" style="display: none"> +<div id="searchbox" style="display: none" role="search"> <h3>{{ _('Quick search') }}</h3> <form class="search" action="{{ pathto('search') }}" method="get"> <input type="text" name="q" /> diff --git a/sphinx/themes/basic/sourcelink.html b/sphinx/themes/basic/sourcelink.html index 08232efc..fbbae064 100644 --- a/sphinx/themes/basic/sourcelink.html +++ b/sphinx/themes/basic/sourcelink.html @@ -8,9 +8,11 @@ :license: BSD, see LICENSE for details. #} {%- if show_source and has_source and sourcename %} - <h3>{{ _('This Page') }}</h3> - <ul class="this-page-menu"> - <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}" - rel="nofollow">{{ _('Show Source') }}</a></li> - </ul> + <div role="note" aria-label="source link"> + <h3>{{ _('This Page') }}</h3> + <ul class="this-page-menu"> + <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}" + rel="nofollow">{{ _('Show Source') }}</a></li> + </ul> + </div> {%- endif %} diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t index d54e7f4e..a3255ebd 100644 --- a/sphinx/themes/basic/static/basic.css_t +++ b/sphinx/themes/basic/static/basic.css_t @@ -471,6 +471,20 @@ table.highlighttable td { padding: 0 0.5em 0 0.5em; } +div.code-block-filename { + padding: 2px 5px; + font-size: small; +} + +div.code-block-filename tt { + background-color: transparent; +} + +div.code-block-filename + pre, +div.code-block-filename + div.highlight > pre { + margin-top: 0; +} + tt.descname { background-color: transparent; font-weight: bold; diff --git a/sphinx/themes/default/static/default.css_t b/sphinx/themes/default/static/default.css_t index 5db77108..cdc1b782 100644 --- a/sphinx/themes/default/static/default.css_t +++ b/sphinx/themes/default/static/default.css_t @@ -308,3 +308,8 @@ div.viewcode-block:target { border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } + +div.code-block-filename { + color: #efefef; + background-color: #1c4e63; +} diff --git a/sphinx/themes/haiku/layout.html b/sphinx/themes/haiku/layout.html index 0c6b41e7..a98d89c6 100644 --- a/sphinx/themes/haiku/layout.html +++ b/sphinx/themes/haiku/layout.html @@ -32,7 +32,7 @@ {% endmacro %} {% block content %} - <div class="header"> + <div class="header" role="banner"> {%- block haikuheader %} {%- if theme_full_logo != "false" %} <a href="{{ pathto('index') }}"> @@ -48,7 +48,7 @@ {%- endif %} {%- endblock %} </div> - <div class="topnav"> + <div class="topnav" role="navigation" aria-label="top navigation"> {{ nav() }} </div> <div class="content"> @@ -60,7 +60,7 @@ {%- endif %}#} {% block body %}{% endblock %} </div> - <div class="bottomnav"> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> {{ nav() }} </div> {% endblock %} diff --git a/sphinx/themes/nature/static/nature.css_t b/sphinx/themes/nature/static/nature.css_t index 3c492034..e4f4d2ed 100644 --- a/sphinx/themes/nature/static/nature.css_t +++ b/sphinx/themes/nature/static/nature.css_t @@ -243,3 +243,9 @@ div.viewcode-block:target { border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } + +div.code-block-filename { + background-color: #ddd; + color: #222; + border: 1px solid #C6C9CB; +} diff --git a/sphinx/themes/pyramid/layout.html b/sphinx/themes/pyramid/layout.html index 8780ceae..318a3662 100644 --- a/sphinx/themes/pyramid/layout.html +++ b/sphinx/themes/pyramid/layout.html @@ -10,7 +10,7 @@ {% block header %} {%- if logo %} -<div class="header"> +<div class="header" role="banner"> <div class="logo"> <a href="{{ pathto(master_doc) }}"> <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/> diff --git a/sphinx/themes/pyramid/static/pyramid.css_t b/sphinx/themes/pyramid/static/pyramid.css_t index c4e94908..c724a493 100644 --- a/sphinx/themes/pyramid/static/pyramid.css_t +++ b/sphinx/themes/pyramid/static/pyramid.css_t @@ -340,3 +340,8 @@ tt.xref { font-weight: normal; font-style: normal; } + +div.code-block-filename { + background-color: #ddd; + color: #222; +} diff --git a/sphinx/themes/scrolls/layout.html b/sphinx/themes/scrolls/layout.html index 48e5e4e4..0961808e 100644 --- a/sphinx/themes/scrolls/layout.html +++ b/sphinx/themes/scrolls/layout.html @@ -20,7 +20,7 @@ <h1 class="heading"><a href="{{ pathto('index') }}" title="back to the documentation overview"><span>{{ title|striptags|e }}</span></a></h1> </div> - <div class="relnav"> + <div class="relnav" role="navigation" aria-label="related navigation"> {%- if prev %} <a href="{{ prev.link|e }}">« {{ prev.title }}</a> | {%- endif %} @@ -31,7 +31,7 @@ </div> <div id="contentwrapper"> {%- if display_toc %} - <div id="toc"> + <div id="toc" role="navigation" aria-label="table of contents navigation"> <h3>{{ _('Table Of Contents') }}</h3> {{ toc }} </div> diff --git a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t index af498257..1d7c5796 100644 --- a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +++ b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t @@ -337,3 +337,9 @@ div.viewcode-block:target { border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } + +div.code-block-filename { + background-color: #ddd; + color: #222; + border: 1px solid #ccc; +} diff --git a/sphinx/themes/traditional/static/traditional.css_t b/sphinx/themes/traditional/static/traditional.css_t index fff411ef..cbea798c 100644 --- a/sphinx/themes/traditional/static/traditional.css_t +++ b/sphinx/themes/traditional/static/traditional.css_t @@ -698,3 +698,7 @@ div.viewcode-block:target { margin: -1px -10px; padding: 0 10px; } + +div.code-block-filename { + background-color: #cceeff; +} diff --git a/sphinx/transforms.py b/sphinx/transforms.py index 53bbadb0..e44a3d3e 100644 --- a/sphinx/transforms.py +++ b/sphinx/transforms.py @@ -23,7 +23,6 @@ from sphinx.util import split_index_msg from sphinx.util.nodes import traverse_translatable_index, extract_messages from sphinx.util.osutil import ustrftime, find_catalog from sphinx.util.compat import docutils_version -from sphinx.util.pycompat import all from sphinx.domains.std import ( make_term_from_paragraph_node, make_termnodes_from_paragraph_node, diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py index 6fd8ba95..150bf3a1 100644 --- a/sphinx/util/docfields.py +++ b/sphinx/util/docfields.py @@ -99,7 +99,8 @@ class GroupedField(Field): return Field.make_field(self, types, domain, items[0]) for fieldarg, content in items: par = nodes.paragraph() - par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong) + par += self.make_xref(self.rolename, domain, fieldarg, + addnodes.literal_strong) par += nodes.Text(' -- ') par += content listnode += nodes.list_item('', par) @@ -137,7 +138,8 @@ class TypedField(GroupedField): def make_field(self, types, domain, items): def handle_item(fieldarg, content): par = nodes.paragraph() - par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong) + par += self.make_xref(self.rolename, domain, fieldarg, + addnodes.literal_strong) if fieldarg in types: par += nodes.Text(' (') # NOTE: using .pop() here to prevent a single type node to be diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 61061a9a..c7556d05 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -55,7 +55,7 @@ if sys.version_info >= (3, 0): raise TypeError('%r is not a Python function' % func) return inspect.getfullargspec(func) -elif sys.version_info >= (2, 5): +else: # 2.6, 2.7 from functools import partial def getargspec(func): """Like inspect.getargspec but supports functools.partial as well.""" @@ -86,12 +86,7 @@ elif sys.version_info >= (2, 5): del func_defaults[i] except IndexError: pass - if sys.version_info >= (2, 6): - return inspect.ArgSpec(args, varargs, varkw, func_defaults) - else: - return (args, varargs, varkw, func_defaults) -else: - getargspec = inspect.getargspec + return inspect.ArgSpec(args, varargs, varkw, func_defaults) def isdescriptor(x): diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py index aa0ea825..de846b24 100644 --- a/sphinx/util/jsonimpl.py +++ b/sphinx/util/jsonimpl.py @@ -10,27 +10,15 @@ """ import UserString +import json -try: - import json - # json-py's json module has no JSONEncoder; this will raise AttributeError - # if json-py is imported instead of the built-in json module - JSONEncoder = json.JSONEncoder -except (ImportError, AttributeError): - try: - import simplejson as json - JSONEncoder = json.JSONEncoder - except ImportError: - json = None - JSONEncoder = object - - -class SphinxJSONEncoder(JSONEncoder): + +class SphinxJSONEncoder(json.JSONEncoder): """JSONEncoder subclass that forces translation proxies.""" def default(self, obj): if isinstance(obj, UserString.UserString): return unicode(obj) - return JSONEncoder.default(self, obj) + return json.JSONEncoder.default(self, obj) def dump(obj, fp, *args, **kwds): diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py index 87717771..a5c461a6 100644 --- a/sphinx/util/osutil.py +++ b/sphinx/util/osutil.py @@ -69,6 +69,9 @@ def ensuredir(path): raise +# This function is same as os.walk of Python2.6, 2.7, 3.2, 3.3 except a +# customization that check UnicodeError. +# The customization obstacle to replace the function with the os.walk. def walk(top, topdown=True, followlinks=False): """Backport of os.walk from 2.6, where the *followlinks* argument was added. @@ -155,9 +158,8 @@ else: def safe_relpath(path, start=None): - from sphinx.util.pycompat import relpath try: - return relpath(path, start) + return os.path.relpath(path, start) except ValueError: return path @@ -171,14 +173,13 @@ def find_catalog(docname, compaction): def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction): - from sphinx.util.pycompat import relpath if not(lang and locale_dirs): return [] domain = find_catalog(docname, compaction) files = [gettext.find(domain, path.join(srcdir, dir_), [lang]) for dir_ in locale_dirs] - files = [relpath(f, srcdir) for f in files if f] + files = [path.relpath(f, srcdir) for f in files if f] return files diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py index 1e5ea314..9941dc0c 100644 --- a/sphinx/util/pycompat.py +++ b/sphinx/util/pycompat.py @@ -11,7 +11,6 @@ import sys import codecs -import encodings # ------------------------------------------------------------------------------ # Python 2/3 compatibility @@ -48,6 +47,7 @@ if sys.version_info >= (3, 0): # try to match ParseError details with SyntaxError details raise SyntaxError(err.msg, (filepath, lineno, offset, err.value)) return unicode(tree) + from itertools import zip_longest # Python 3 name else: # Python 2 @@ -69,6 +69,8 @@ else: # error handler import locale sys_encoding = locale.getpreferredencoding() + # use Python 3 name + from itertools import izip_longest as zip_longest def execfile_(filepath, _globals): @@ -81,8 +83,8 @@ def execfile_(filepath, _globals): finally: f.close() - # py25,py26,py31 accept only LF eol instead of CRLF - if sys.version_info[:2] in ((2, 5), (2, 6), (3, 1)): + # py26 accept only LF eol instead of CRLF + if sys.version_info[:2] == (2, 6): source = source.replace(b('\r\n'), b('\n')) # compile to a code object, handle syntax errors @@ -100,178 +102,7 @@ def execfile_(filepath, _globals): exec code in _globals -try: - from html import escape as htmlescape -except ImportError: +if sys.version_info >= (3, 2): + from html import escape as htmlescape # >= Python 3.2 +else: # 2.6, 2.7, 3.1 from cgi import escape as htmlescape - -# ------------------------------------------------------------------------------ -# Missing builtins and itertools in Python < 2.6 - -if sys.version_info >= (2, 6): - # Python >= 2.6 - next = next - - from itertools import product - try: - from itertools import zip_longest # Python 3 name - except ImportError: - from itertools import izip_longest as zip_longest - - import os - relpath = os.path.relpath - del os - - import io - open = io.open - -else: - # Python < 2.6 - from itertools import izip, repeat, chain - - # this is on Python 2, where the method is called "next" (it is refactored - # to __next__ by 2to3, but in that case never executed) - def next(iterator): - return iterator.next() - - # These replacement functions have been taken from the Python 2.6 - # itertools documentation. - def product(*args, **kwargs): - pools = map(tuple, args) * kwargs.get('repeat', 1) - result = [[]] - for pool in pools: - result = [x + [y] for x in result for y in pool] - for prod in result: - yield tuple(prod) - - def zip_longest(*args, **kwds): - # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- - fillvalue = kwds.get('fillvalue') - def sentinel(counter = ([fillvalue]*(len(args)-1)).pop): - yield counter() # yields the fillvalue, or raises IndexError - fillers = repeat(fillvalue) - iters = [chain(it, sentinel(), fillers) for it in args] - try: - for tup in izip(*iters): - yield tup - except IndexError: - pass - - from os.path import curdir - def relpath(path, start=curdir): - """Return a relative version of a path""" - from os.path import sep, abspath, commonprefix, join, pardir - - if not path: - raise ValueError("no path specified") - - start_list = abspath(start).split(sep) - path_list = abspath(path).split(sep) - - # Work out how much of the filepath is shared by start and path. - i = len(commonprefix([start_list, path_list])) - - rel_list = [pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return start - return join(*rel_list) - del curdir - - from types import MethodType - def open(filename, mode='r', *args, **kw): - newline = kw.pop('newline', None) - mode = mode.replace('t', '') - f = codecs.open(filename, mode, *args, **kw) - if newline is not None: - f._write = f.write - def write(self, text): - text = text.replace(u'\r\n', u'\n').replace(u'\n', newline) - self._write(text) - f.write = MethodType(write, f) - return f - - -# ------------------------------------------------------------------------------ -# Missing builtins and codecs in Python < 2.5 - -if sys.version_info >= (2, 5): - # Python >= 2.5 - base_exception = BaseException - any = any - all = all - -else: - # Python 2.4 - base_exception = Exception - - def all(gen): - for i in gen: - if not i: - return False - return True - - def any(gen): - for i in gen: - if i: - return True - return False - - # Python 2.4 doesn't know the utf-8-sig encoding, so deliver it here - - def my_search_function(encoding): - norm_encoding = encodings.normalize_encoding(encoding) - if norm_encoding != 'utf_8_sig': - return None - return (encode, decode, StreamReader, StreamWriter) - - codecs.register(my_search_function) - - # begin code copied from utf_8_sig.py in Python 2.6 - - def encode(input, errors='strict'): - return (codecs.BOM_UTF8 + - codecs.utf_8_encode(input, errors)[0], len(input)) - - def decode(input, errors='strict'): - prefix = 0 - if input[:3] == codecs.BOM_UTF8: - input = input[3:] - prefix = 3 - (output, consumed) = codecs.utf_8_decode(input, errors, True) - return (output, consumed+prefix) - - class StreamWriter(codecs.StreamWriter): - def reset(self): - codecs.StreamWriter.reset(self) - try: - del self.encode - except AttributeError: - pass - - def encode(self, input, errors='strict'): - self.encode = codecs.utf_8_encode - return encode(input, errors) - - class StreamReader(codecs.StreamReader): - def reset(self): - codecs.StreamReader.reset(self) - try: - del self.decode - except AttributeError: - pass - - def decode(self, input, errors='strict'): - if len(input) < 3: - if codecs.BOM_UTF8.startswith(input): - # not enough data to decide if this is a BOM - # => try again on the next call - return (u"", 0) - elif input[:3] == codecs.BOM_UTF8: - self.decode = codecs.utf_8_decode - (output, consumed) = codecs.utf_8_decode(input[3:],errors) - return (output, consumed+3) - # (else) no BOM present - self.decode = codecs.utf_8_decode - return codecs.utf_8_decode(input, errors) - - # end code copied from utf_8_sig.py diff --git a/sphinx/versioning.py b/sphinx/versioning.py index a16751bb..ccab41d4 100644 --- a/sphinx/versioning.py +++ b/sphinx/versioning.py @@ -11,8 +11,9 @@ """ from uuid import uuid4 from operator import itemgetter +from itertools import product -from sphinx.util.pycompat import product, zip_longest, all +from sphinx.util.pycompat import zip_longest # anything below that ratio is considered equal/changed diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 41663a0c..61b905f6 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -267,6 +267,9 @@ class HTMLTranslator(BaseTranslator): **highlight_args) starttag = self.starttag(node, 'div', suffix='', CLASS='highlight-%s' % lang) + if node.has_key('filename'): + starttag += '<div class="code-block-filename"><tt>%s</tt></div>' % ( + node['filename'],) self.body.append(starttag + highlighted + '</div>\n') raise nodes.SkipNode @@ -508,6 +511,11 @@ class HTMLTranslator(BaseTranslator): def depart_literal_emphasis(self, node): return self.depart_emphasis(node) + def visit_literal_strong(self, node): + return self.visit_strong(node) + def depart_literal_strong(self, node): + return self.depart_strong(node) + def visit_abbreviation(self, node): attrs = {} if node.hasattr('explanation'): @@ -618,6 +626,14 @@ class SmartyPantsHTMLTranslator(HTMLTranslator): self.depart_emphasis(node) self.no_smarty -= 1 + def visit_literal_strong(self, node): + self.no_smarty += 1 + self.visit_strong(node) + + def depart_literal_strong(self, node): + self.depart_strong(node) + self.no_smarty -= 1 + def visit_desc_signature(self, node): self.no_smarty += 1 HTMLTranslator.visit_desc_signature(self, node) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 3c1a50f8..61aa5828 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -25,7 +25,6 @@ from sphinx.errors import SphinxError from sphinx.locale import admonitionlabels, _ from sphinx.util import split_into from sphinx.util.osutil import ustrftime -from sphinx.util.pycompat import any from sphinx.util.texescape import tex_escape_map, tex_replace_map from sphinx.util.smartypants import educate_quotes_latex @@ -1247,6 +1246,13 @@ class LaTeXTranslator(nodes.NodeVisitor): def depart_strong(self, node): self.body.append('}') + def visit_literal_strong(self, node): + self.body.append(r'\textbf{\texttt{') + self.no_contractions += 1 + def depart_literal_strong(self, node): + self.body.append('}}') + self.no_contractions -= 1 + def visit_abbreviation(self, node): abbr = node.astext() self.body.append(r'\textsc{') @@ -1331,6 +1337,11 @@ class LaTeXTranslator(nodes.NodeVisitor): highlight_args['force'] = True if 'linenos' in node: linenos = node['linenos'] + filename = node.get('filename') + if filename: + self.body.append('\n{\\colorbox[rgb]{0.9,0.9,0.9}' + '{\\makebox[\\textwidth][l]' + '{\\small\\texttt{%s}}}}\n' % (filename,)) def warner(msg): self.builder.warn(msg, (self.curfilestack[-1], node.line)) hlcode = self.highlighter.highlight_block(code, lang, warn=warner, diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py index bc4da17a..0aa0058c 100644 --- a/sphinx/writers/manpage.py +++ b/sphinx/writers/manpage.py @@ -304,6 +304,11 @@ class ManualPageTranslator(BaseTranslator): def depart_literal_emphasis(self, node): return self.depart_emphasis(node) + def visit_literal_strong(self, node): + return self.visit_strong(node) + def depart_literal_strong(self, node): + return self.depart_strong(node) + def visit_abbreviation(self, node): pass def depart_abbreviation(self, node): diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index 7b70485a..a930a525 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -1207,6 +1207,11 @@ class TexinfoTranslator(nodes.NodeVisitor): def depart_literal_emphasis(self, node): self.body.append('}') + def visit_literal_strong(self, node): + self.body.append('@code{') + def depart_literal_strong(self, node): + self.body.append('}') + def visit_index(self, node): # terminate the line but don't prevent paragraph breaks if isinstance(node.parent, nodes.paragraph): diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py index 57a40b29..a174bc26 100644 --- a/sphinx/writers/text.py +++ b/sphinx/writers/text.py @@ -762,6 +762,11 @@ class TextTranslator(nodes.NodeVisitor): def depart_strong(self, node): self.add_text('**') + def visit_literal_strong(self, node): + self.add_text('**') + def depart_literal_strong(self, node): + self.add_text('**') + def visit_abbreviation(self, node): self.add_text('') def depart_abbreviation(self, node): diff --git a/tests/root/autodoc.txt b/tests/root/autodoc.txt index d4b3404c..aa0dffba 100644 --- a/tests/root/autodoc.txt +++ b/tests/root/autodoc.txt @@ -45,3 +45,5 @@ Just testing a few autodoc possibilities... :members: ca1, ia1 Specific members (2 total) + +.. automodule:: autodoc_missing_imports diff --git a/tests/root/autodoc_missing_imports.py b/tests/root/autodoc_missing_imports.py new file mode 100644 index 00000000..7a717345 --- /dev/null +++ b/tests/root/autodoc_missing_imports.py @@ -0,0 +1,9 @@ + +import missing_module +from missing_module import missing_name +import missing_package1.missing_module1 +from missing_package2 import missing_module2 +from missing_package3.missing_module3 import missing_name + +class TestAutodoc(object): + """TestAutodoc docstring.""" diff --git a/tests/root/conf.py b/tests/root/conf.py index 8025ba33..cf88c2bb 100644 --- a/tests/root/conf.py +++ b/tests/root/conf.py @@ -8,7 +8,7 @@ sys.path.append(os.path.abspath('..')) extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.autosummary', 'sphinx.ext.doctest', 'sphinx.ext.extlinks', - 'sphinx.ext.viewcode', 'sphinx.ext.oldcmarkup', 'ext'] + 'sphinx.ext.viewcode', 'ext'] jsmath_path = 'dummy.js' @@ -71,6 +71,13 @@ autosummary_generate = ['autosummary'] extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '), 'pyurl': ('http://python.org/%s', None)} +autodoc_mock_imports = [ + 'missing_module', + 'missing_package1.missing_module1', + 'missing_package2.missing_module2', + 'missing_package3.missing_module3', +] + # modify tags from conf.py tags.add('confpytag') diff --git a/tests/root/includes.txt b/tests/root/includes.txt index 904f0677..08917811 100644 --- a/tests/root/includes.txt +++ b/tests/root/includes.txt @@ -40,6 +40,7 @@ Literalinclude options .. cssclass:: inc-lines .. literalinclude:: literal.inc :lines: 6-7,9 + :lineno-start: 6 .. cssclass:: inc-startend .. literalinclude:: literal.inc diff --git a/tests/root/objects.txt b/tests/root/objects.txt index 57e82212..73661d22 100644 --- a/tests/root/objects.txt +++ b/tests/root/objects.txt @@ -101,6 +101,7 @@ Referring to :func:`nothing <>`. :type hour: DuplicateType :param hour: Duplicate param. Should not lead to crashes. :type hour: DuplicateType + :param .Cls extcls: A class from another module. C items @@ -117,14 +118,6 @@ C items .. c:var:: sphinx_global -Old C items (from oldcmarkup ext) ---------------------------------- - -.. cfunction:: Sphinx_Func() - -Refer to :cfunc:`Sphinx_Func`. - - Javascript items ================ diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 3735a7b6..82eb0f71 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -751,12 +751,8 @@ def _funky_classmethod(name, b, c, d, docstring=None): some arguments.""" def template(cls, a, b, c, d=4, e=5, f=6): return a, b, c, d, e, f - if sys.version_info >= (2, 5): - from functools import partial - function = partial(template, b=b, c=c, d=d) - else: - def function(cls, a, e=5, f=6): - return template(a, b, c, d, e, f) + from functools import partial + function = partial(template, b=b, c=c, d=d) function.__name__ = name function.__doc__ = docstring return classmethod(function) @@ -788,10 +784,9 @@ class Class(Base): #: should be documented -- süß attr = 'bar' + @property def prop(self): """Property.""" - # stay 2.4 compatible (docstring!) - prop = property(prop, doc="Property.") docattr = 'baz' """should likewise be documented -- süß""" diff --git a/tests/test_build_html.py b/tests/test_build_html.py index ef8e3888..603ad546 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -44,9 +44,6 @@ reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \ %(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png %(root)s/markup.txt:\\d+: WARNING: Malformed :option: u'Python c option', does \ not contain option marker - or -- or / -%(root)s/objects.txt:\\d*: WARNING: using old C markup; please migrate to \ -new-style markup \(e.g. c:function instead of cfunction\), see \ -http://sphinx-doc.org/domains.html """ HTML_WARNINGS = ENV_WARNINGS + """\ @@ -191,8 +188,6 @@ HTML_XPATH = { (".//a[@href='#c.SPHINX_USE_PYTHON']", ''), (".//a[@href='#c.SphinxType']", ''), (".//a[@href='#c.sphinx_global']", ''), - # reference from old C markup extension - (".//a[@href='#c.Sphinx_Func']", ''), # test global TOC created by toctree() (".//ul[@class='current']/li[@class='toctree-l1 current']/a[@href='']", 'Testing object descriptions'), diff --git a/tests/test_config.py b/tests/test_config.py index 4d3d51b0..ea6f3ba4 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -19,7 +19,8 @@ from sphinx.util.pycompat import b @with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True', - 'latex_elements.docclass': 'scrartcl'}) + 'latex_elements.docclass': 'scrartcl', + 'modindex_common_prefix': 'path1,path2'}) def test_core_config(app): cfg = app.config @@ -31,6 +32,7 @@ def test_core_config(app): # overrides assert cfg.master_doc == 'master' assert cfg.latex_elements['docclass'] == 'scrartcl' + assert cfg.modindex_common_prefix == ['path1', 'path2'] # simple default values assert 'locale_dirs' not in cfg.__dict__ @@ -92,7 +94,7 @@ def test_errors_warnings(dir): write_file(dir / 'conf.py', u'# -*- coding: utf-8\n\n' u'project = u"Jägermeister"\n', 'utf-8') cfg = Config(dir, 'conf.py', {}, None) - cfg.init_values() + cfg.init_values(lambda warning: 1/0) assert cfg.project == u'Jägermeister' # test the warning for bytestrings with non-ascii content @@ -122,5 +124,5 @@ def test_config_eol(tmpdir): for eol in ('\n', '\r\n'): configfile.write_bytes(b('project = "spam"' + eol)) cfg = Config(tmpdir, 'conf.py', {}, None) - cfg.init_values() + cfg.init_values(lambda warning: 1/0) assert cfg.project == u'spam' diff --git a/tests/test_intersphinx.py b/tests/test_intersphinx.py index a8679e7e..8ce02cc1 100644 --- a/tests/test_intersphinx.py +++ b/tests/test_intersphinx.py @@ -81,7 +81,7 @@ def test_read_inventory_v2(): '/util/glossary.html#term-a-term' -@with_app(confoverrides={'extensions': 'sphinx.ext.intersphinx'}) +@with_app() @with_tempdir def test_missing_reference(tempdir, app): inv_file = tempdir / 'inventory' @@ -157,7 +157,7 @@ def test_missing_reference(tempdir, app): assert contnode[0].astext() == 'py3k:unknown' -@with_app(confoverrides={'extensions': 'sphinx.ext.intersphinx'}) +@with_app() @with_tempdir def test_load_mappings_warnings(tempdir, app): """ diff --git a/tests/test_intl.py b/tests/test_intl.py index c9822089..0119d677 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -16,8 +16,6 @@ from StringIO import StringIO from subprocess import Popen, PIPE from xml.etree import ElementTree -from sphinx.util.pycompat import relpath - from util import test_roots, path, with_app, SkipTest @@ -49,7 +47,7 @@ def setup_module(): for f in [f for f in files if f.endswith('.po')]: po = dirpath / f mo = root / 'xx' / 'LC_MESSAGES' / ( - relpath(po[:-3], root) + '.mo') + os.path.relpath(po[:-3], root) + '.mo') if not mo.parent.exists(): mo.parent.makedirs() try: @@ -75,7 +73,7 @@ def teardown_module(): def elem_gettexts(elem): def itertext(self): # this function copied from Python-2.7 'ElementTree.itertext'. - # for compatibility to Python-2.5, 2.6, 3.1 + # for compatibility to Python-2.6 tag = self.tag if not isinstance(tag, basestring) and tag is not None: return diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index 9daa7401..7323f48e 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -170,6 +170,7 @@ def test_quickstart_all_answers(tempdir): 'Author name': u'Wolfgang Schäuble & G\'Beckstein'.encode('utf-8'), 'Project version': '2.0', 'Project release': '2.0.1', + 'Project language': 'de', 'Source file suffix': '.txt', 'Name of your master document': 'contents', 'autodoc': 'y', diff --git a/tests/test_versioning.py b/tests/test_versioning.py index 6469a33c..5cff92ff 100644 --- a/tests/test_versioning.py +++ b/tests/test_versioning.py @@ -15,7 +15,6 @@ from docutils.parsers.rst.directives.html import MetaBody from sphinx import addnodes from sphinx.versioning import add_uids, merge_doctrees, get_ratio -from sphinx.util.pycompat import all from util import test_root, TestApp diff --git a/tests/test_websupport.py b/tests/test_websupport.py index 611a131a..d950a36c 100644 --- a/tests/test_websupport.py +++ b/tests/test_websupport.py @@ -11,12 +11,7 @@ import os from StringIO import StringIO - -try: - from functools import wraps -except ImportError: - # functools is new in 2.5 - wraps = lambda f: (lambda w: w) +from functools import wraps from sphinx.websupport import WebSupport from sphinx.websupport.errors import DocumentNotFoundError, \ diff --git a/tests/util.py b/tests/util.py index 4ba89030..a2f345bf 100644 --- a/tests/util.py +++ b/tests/util.py @@ -13,12 +13,7 @@ import tempfile import shutil import re from codecs import open - -try: - from functools import wraps -except ImportError: - # functools is new in 2.4 - wraps = lambda f: (lambda w: w) +from functools import wraps from sphinx import application from sphinx.theming import Theme @@ -1,5 +1,5 @@ [tox] -envlist=py25,py26,py27,py31,py32,py33,pypy,du11,du10,du09,du08,du07 +envlist=py26,py27,py32,py33,pypy,du11,du10,du09,du08,du07 [testenv] deps= @@ -12,14 +12,6 @@ commands= {envpython} tests/run.py {posargs} sphinx-build -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html -[testenv:py25] -deps= - simplejson==2.5.0 - {[testenv]deps} -setenv= - PIP_INSECURE = 1 - {[testenv]setenv} - [testenv:py33] deps= docutils>=0.10.0 |
