diff --git a/.travis.yml b/.travis.yml index 5f035b73b..8cef03f44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ env: global: - TEST='-v --with-timer --timer-top-n 25' - PYTHONFAULTHANDLER=x + - PYTHONWARNINGS=all matrix: - DOCUTILS=0.11 - DOCUTILS=0.12 diff --git a/CHANGES b/CHANGES index 356f96484..a75612240 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,24 @@ Incompatible changes -------------------- * #2986: ``themes/basic/defindex.html`` is now deprecated +* Emit warnings that will be deprecated in Sphinx 1.6 by default. + Users can change the behavior by setting the environment variable + PYTHONWARNINGS. Please refer :ref:`when-deprecation-warnings-are-displayed`. + +Deprecated +---------- + +These features are removed in Sphinx-1.6: + +* LDML format support in i18n feature +* ``sphinx.addnodes.termsep`` +* Some functions and classes in ``sphinx.util.pycompat``: + ``zip_longest``, ``product``, ``all``, ``any``, ``next``, ``open``, + ``class_types``, ``base_exception``, ``relpath``, ``StringIO``, ``BytesIO``. + Please use the standard library version instead; + +If any deprecation warning like ``RemovedInSphinxXXXWarning`` are displayed, +please refer :ref:`when-deprecation-warnings-are-displayed`. Features added -------------- diff --git a/doc/devguide.rst b/doc/devguide.rst index b621f622a..f29646550 100644 --- a/doc/devguide.rst +++ b/doc/devguide.rst @@ -114,6 +114,11 @@ These are the basic steps needed to start developing on Sphinx. pip install -r test-reqs.txt make test + * Again, it's useful to turn on deprecation warnings on so they're shown in + the test output:: + + PYTHONWARNINGS=all make test + * Build the documentation and check the output for different builders:: cd doc @@ -272,3 +277,55 @@ Debugging Tips $ npm install $ node_modules/.bin/grunt build # -> dest/*.global.js + +Deprecating a feature +--------------------- + +There are a couple reasons that code in Sphinx might be deprecated: + +* If a feature has been improved or modified in a backwards-incompatible way, + the old feature or behavior will be deprecated. + +* Sometimes Sphinx will include a backport of a Python library that's not + included in a version of Python that Sphinx currently supports. When Sphinx + no longer needs to support the older version of Python that doesn't include + the library, the library will be deprecated in Sphinx. + +As the :ref:`deprecation-policy` describes, +the first release of Sphinx that deprecates a feature (``A.B``) should raise a +``RemovedInSphinxXXWarning`` (where XX is the Sphinx version where the feature +will be removed) when the deprecated feature is invoked. Assuming we have good +test coverage, these warnings are converted to errors when running the test +suite with warnings enabled: ``python -Wall tests/run.py``. Thus, when adding +a ``RemovedInSphinxXXWarning`` you need to eliminate or silence any warnings +generated when running the tests. + +.. _deprecation-policy: + +Deprecation policy +------------------ + +A feature release may deprecate certain features from previous releases. If a +feature is deprecated in feature release 1.A, it will continue to work in all +1.A.x versions (for all versions of x) but raise warnings. Deprecated features +will be removed in the first 1.B release, or 1.B.1 for features deprecated in +the last 1.A.x feature release to ensure deprecations are done over at least 2 +feature releases. + +So, for example, if we decided to start the deprecation of a function in +Sphinx 1.4: + +* Sphinx 1.4.x will contain a backwards-compatible replica of the function + which will raise a ``RemovedInSphinx16Warning``. + +* Sphinx 1.5 (the version that follows 1.4) will still contain the + backwards-compatible replica. + +* Sphinx 1.6 will remove the feature outright. + +The warnings are displayed by default. You can turn off display of these +warnings with: + +* ``PYTHONWARNINGS= make html`` (Linux/Mac) +* ``export PYTHONWARNINGS=`` and do ``make html`` (Linux/Mac) +* ``set PYTHONWARNINGS=`` and do ``make html`` (Windows) diff --git a/doc/glossary.rst b/doc/glossary.rst index 3ef1623db..a92e52b98 100644 --- a/doc/glossary.rst +++ b/doc/glossary.rst @@ -73,6 +73,11 @@ Glossary directive" (e.g. :rst:dir:`function` or :rst:dir:`object`) creates such a block; and most objects can be cross-referenced to. + RemoveInSphinxXXXWarning + The feature which is warned will be removed in Sphinx-XXX version. + It usually caused from Sphinx extensions which is using deprecated. + See also :ref:`when-deprecation-warnings-are-displayed`. + role A reStructuredText markup element that allows marking a piece of text. Like directives, roles are extensible. The basic syntax looks like this: diff --git a/doc/invocation.rst b/doc/invocation.rst index 4b4593014..a16ab2128 100644 --- a/doc/invocation.rst +++ b/doc/invocation.rst @@ -410,6 +410,23 @@ variables to customize behavior: Additional options for :program:`sphinx-build`. +.. _when-deprecation-warnings-are-displayed: + +Deprecation Warnings +-------------------- + +If any deprecation warning like ``RemovedInSphinxXXXWarning`` are displayed +when building a user's document, some Sphinx extension is using deprecated +features. In that case, please report it to author of the extension. + +To disable the deprecation warnings, please set ``PYTHONWARNINGS=`` environment +variable to your environment. For example: + +* ``PYTHONWARNINGS= make html`` (Linux/Mac) +* ``export PYTHONWARNINGS=`` and do ``make html`` (Linux/Mac) +* ``set PYTHONWARNINGS=`` and do ``make html`` (Windows) +* modify your Makefile/make.bat and set the environment variable + .. _invocation-apidoc: diff --git a/sphinx/__init__.py b/sphinx/__init__.py index 415a85421..84265e51e 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -12,9 +12,24 @@ # Keep this file executable as-is in Python 3! # (Otherwise getting the version out of it from setup.py is impossible.) +from __future__ import absolute_import + +import os import sys +import warnings from os import path +from .deprecation import RemovedInNextVersionWarning + +# by default, all DeprecationWarning under sphinx package will be emit. +# Users can avoid this by using environment variable: PYTHONWARNINGS= +if 'PYTHONWARNINGS' not in os.environ: + warnings.filterwarnings('default', + category=RemovedInNextVersionWarning, module='sphinx') +# docutils.io using mode='rU' for open +warnings.filterwarnings('ignore', "'U' mode is deprecated", + DeprecationWarning, module='docutils.io') + __version__ = '1.5b2' __released__ = '1.5b2' # used when Sphinx builds its own docs diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py index 4035faa2d..95f58052d 100644 --- a/sphinx/addnodes.py +++ b/sphinx/addnodes.py @@ -12,6 +12,7 @@ import warnings from docutils import nodes +from sphinx.deprecation import RemovedInSphinx16Warning class translatable(object): @@ -276,12 +277,12 @@ class termsep(nodes.Structural, nodes.Element): """Separates two terms within a node. .. versionchanged:: 1.4 - sphinx.addnodes.termsep is deprecated. It will be removed at Sphinx-1.5. + sphinx.addnodes.termsep is deprecated. It will be removed at Sphinx-1.6. """ def __init__(self, *args, **kw): - warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.5', - DeprecationWarning, stacklevel=2) + warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.6', + RemovedInSphinx16Warning, stacklevel=2) super(termsep, self).__init__(*args, **kw) diff --git a/sphinx/deprecation.py b/sphinx/deprecation.py new file mode 100644 index 000000000..a5d14762f --- /dev/null +++ b/sphinx/deprecation.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +""" + sphinx.deprecation + ~~~~~~~~~~~~~~~~~~ + + Sphinx deprecation classes and utilities. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + + +class RemovedInSphinx16Warning(DeprecationWarning): + pass + + +class RemovedInSphinx17Warning(PendingDeprecationWarning): + pass + + +RemovedInNextVersionWarning = RemovedInSphinx16Warning diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py index 112353d47..41a9c5e20 100644 --- a/sphinx/util/i18n.py +++ b/sphinx/util/i18n.py @@ -22,6 +22,7 @@ from babel.messages.pofile import read_po from babel.messages.mofile import write_mo from sphinx.errors import SphinxError +from sphinx.deprecation import RemovedInSphinx16Warning from sphinx.util.osutil import walk from sphinx.util import SEP @@ -194,8 +195,8 @@ def format_date(format, date=None, language=None, warn=None): if re.match('EEE|MMM|dd|DDD|MM|WW|medium|YY', format): # consider the format as babel's - warnings.warn('LDML format support will be dropped at Sphinx-1.5', - DeprecationWarning) + warnings.warn('LDML format support will be dropped at Sphinx-1.6', + RemovedInSphinx16Warning) return babel_format_date(date, format, locale=language, warn=warn, formatter=babel.dates.format_datetime) diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py index e3b17ef62..69a5e07cf 100644 --- a/sphinx/util/pycompat.py +++ b/sphinx/util/pycompat.py @@ -15,10 +15,11 @@ import codecs import warnings from six import class_types +from six import PY3, text_type, exec_ from six.moves import zip_longest from itertools import product -from six import PY3, text_type, exec_ +from sphinx.deprecation import RemovedInSphinx16Warning NoneType = type(None) @@ -105,7 +106,8 @@ def execfile_(filepath, _globals, open=open): from sphinx.util.osutil import fs_encoding # get config source -- 'b' is a no-op under 2.x, while 'U' is # ignored under 3.x (but 3.x compile() accepts \r\n newlines) - with open(filepath, 'rbU') as f: + mode = 'rb' if PY3 else 'rbU' + with open(filepath, mode) as f: source = f.read() # py26 accept only LF eol instead of CRLF @@ -138,9 +140,9 @@ class _DeprecationWrapper(object): def __getattr__(self, attr): if attr in self._deprecated: warnings.warn("sphinx.util.pycompat.%s is deprecated and will be " - "removed in Sphinx 1.4, please use the standard " + "removed in Sphinx 1.6, please use the standard " "library version instead." % attr, - DeprecationWarning, stacklevel=2) + RemovedInSphinx16Warning, stacklevel=2) return self._deprecated[attr] return getattr(self._mod, attr) diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 5c0fa0fee..af8b6d98d 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -20,6 +20,7 @@ from docutils import nodes from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator from sphinx import addnodes +from sphinx.deprecation import RemovedInSphinx16Warning from sphinx.locale import admonitionlabels, _ from sphinx.util.images import get_image_size from sphinx.util.smartypants import sphinx_smarty_pants @@ -688,8 +689,10 @@ class HTMLTranslator(BaseTranslator): self.body.append('\n') def visit_termsep(self, node): - warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.5', - DeprecationWarning) + warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.6. ' + 'This warning is displayed because some Sphinx extension ' + 'uses sphinx.addnodes.termsep. Please report it to ' + 'author of the extension.', RemovedInSphinx16Warning) self.body.append('
') raise nodes.SkipNode diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 104401152..52d8e268c 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -24,6 +24,7 @@ from docutils.writers.latex2e import Babel from sphinx import addnodes from sphinx import highlighting from sphinx.errors import SphinxError +from sphinx.deprecation import RemovedInSphinx16Warning from sphinx.locale import admonitionlabels, _ from sphinx.util import split_into from sphinx.util.i18n import format_date @@ -1339,8 +1340,10 @@ class LaTeXTranslator(nodes.NodeVisitor): self.in_term -= 1 def visit_termsep(self, node): - warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.5', - DeprecationWarning) + warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.6. ' + 'This warning is displayed because some Sphinx extension ' + 'uses sphinx.addnodes.termsep. Please report it to ' + 'author of the extension.', RemovedInSphinx16Warning) self.body.append(', ') raise nodes.SkipNode diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py index b9c9bd646..53cf29767 100644 --- a/sphinx/writers/manpage.py +++ b/sphinx/writers/manpage.py @@ -19,6 +19,7 @@ from docutils.writers.manpage import ( ) from sphinx import addnodes +from sphinx.deprecation import RemovedInSphinx16Warning from sphinx.locale import admonitionlabels, _ from sphinx.util.compat import docutils_version from sphinx.util.i18n import format_date @@ -216,8 +217,10 @@ class ManualPageTranslator(BaseTranslator): BaseTranslator.visit_term(self, node) def visit_termsep(self, node): - warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.5', - DeprecationWarning) + warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.6. ' + 'This warning is displayed because some Sphinx extension ' + 'uses sphinx.addnodes.termsep. Please report it to ' + 'author of the extension.', RemovedInSphinx16Warning) self.body.append(', ') raise nodes.SkipNode diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index 6ec077fd7..18dcd9177 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -19,6 +19,7 @@ from six.moves import range from docutils import nodes, writers from sphinx import addnodes, __display_version__ +from sphinx.deprecation import RemovedInSphinx16Warning from sphinx.locale import admonitionlabels, _ from sphinx.util.i18n import format_date from sphinx.writers.latex import collected_footnote @@ -954,8 +955,10 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def visit_termsep(self, node): - warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.5', - DeprecationWarning) + warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.6. ' + 'This warning is displayed because some Sphinx extension ' + 'uses sphinx.addnodes.termsep. Please report it to ' + 'author of the extension.', RemovedInSphinx16Warning) self.body.append('\n%s ' % self.at_item_x) def depart_termsep(self, node): diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py index 7032208ea..fc9e3378c 100644 --- a/sphinx/writers/text.py +++ b/sphinx/writers/text.py @@ -20,6 +20,7 @@ from docutils import nodes, writers from docutils.utils import column_width from sphinx import addnodes +from sphinx.deprecation import RemovedInSphinx16Warning from sphinx.locale import admonitionlabels, _ @@ -651,8 +652,10 @@ class TextTranslator(nodes.NodeVisitor): self.end_state(end=None) def visit_termsep(self, node): - warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.5', - DeprecationWarning) + warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.6. ' + 'This warning is displayed because some Sphinx extension ' + 'uses sphinx.addnodes.termsep. Please report it to ' + 'author of the extension.', RemovedInSphinx16Warning) self.add_text(', ') raise nodes.SkipNode diff --git a/tox.ini b/tox.ini index ca3cac99b..1ccaa583f 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ deps= setenv = SPHINX_TEST_TEMPDIR = {envdir}/testbuild commands= - {envpython} tests/run.py -I py35 -m '^[tT]est' {posargs} + {envpython} -Wall tests/run.py -I py35 -m '^[tT]est' {posargs} sphinx-build -q -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html [testenv:pypy] @@ -48,5 +48,5 @@ deps= [testenv:py35] commands= - {envpython} tests/run.py -m '^[tT]est' {posargs} + {envpython} -Wall tests/run.py -m '^[tT]est' {posargs} sphinx-build -q -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html