From a9256bfa707f5f0816ff554dcc44f1808b707d22 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Thu, 6 Apr 2017 09:41:49 +0900
Subject: [PATCH 01/32] Remove Sphinx.egg-info on `make clean`
---
Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/Makefile b/Makefile
index 101cfca2c..6df3ef0ad 100644
--- a/Makefile
+++ b/Makefile
@@ -56,6 +56,7 @@ clean-backupfiles:
clean-generated:
find . -name '.DS_Store' -exec rm -f {} +
+ rm -rf Sphinx.egg-info/
rm -rf doc/_build/
rm -f sphinx/pycode/*.pickle
rm -f utils/*3.py*
From b6e4cceb8f34483d46a6cbf4410cad91f50531bf Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Sat, 8 Apr 2017 13:41:06 +0900
Subject: [PATCH 02/32] Fix #3614: Sphinx crashes with requests-2.5.0
---
CHANGES | 2 ++
sphinx/util/requests.py | 14 ++++++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/CHANGES b/CHANGES
index 6ef2c3b2b..e192bf5b7 100644
--- a/CHANGES
+++ b/CHANGES
@@ -13,6 +13,8 @@ Features added
Bugs fixed
----------
+* #3614: Sphinx crashes with requests-2.5.0
+
Testing
--------
diff --git a/sphinx/util/requests.py b/sphinx/util/requests.py
index 48d9ae93a..9fe4cfdcd 100644
--- a/sphinx/util/requests.py
+++ b/sphinx/util/requests.py
@@ -36,6 +36,16 @@ except ImportError:
# for requests < 2.4.0
InsecureRequestWarning = None
+try:
+ from requests.packages.urllib3.exceptions import InsecurePlatformWarning
+except ImportError:
+ try:
+ # for Debian-jessie
+ from urllib3.exceptions import InsecurePlatformWarning
+ except ImportError:
+ # for requests < 2.4.0
+ InsecurePlatformWarning = None
+
# try to load requests[security] (but only if SSL is available)
try:
import ssl
@@ -48,8 +58,8 @@ else:
pkg_resources.VersionConflict):
if not getattr(ssl, 'HAS_SNI', False):
# don't complain on each url processed about the SSL issue
- requests.packages.urllib3.disable_warnings(
- requests.packages.urllib3.exceptions.InsecurePlatformWarning)
+ if InsecurePlatformWarning:
+ requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
warnings.warn(
'Some links may return broken results due to being unable to '
'check the Server Name Indication (SNI) in the returned SSL cert '
From b8fe49b0a43f8415e957a85bc005767c036eedf1 Mon Sep 17 00:00:00 2001
From: shimizukawa
Date: Mon, 10 Apr 2017 10:33:53 +0900
Subject: [PATCH 03/32] add appveyor for testing on Windows
---
.appveyor.yml | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 .appveyor.yml
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 000000000..0e40891d7
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,11 @@
+environment:
+ matrix:
+ - PYTHON: 36-x64
+
+install:
+ - pip install -U pip setuptools
+ - pip install -r test-reqs.txt
+
+test_script:
+ - tox -e py36 -- -vvv
+
From 317c86e9b926135f2cc1dfdee56a57ce06850d74 Mon Sep 17 00:00:00 2001
From: shimizukawa
Date: Mon, 10 Apr 2017 10:34:53 +0900
Subject: [PATCH 04/32] Revert "add appveyor for testing on Windows"
This reverts commit b8fe49b0a43f8415e957a85bc005767c036eedf1.
---
.appveyor.yml | 11 -----------
1 file changed, 11 deletions(-)
delete mode 100644 .appveyor.yml
diff --git a/.appveyor.yml b/.appveyor.yml
deleted file mode 100644
index 0e40891d7..000000000
--- a/.appveyor.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-environment:
- matrix:
- - PYTHON: 36-x64
-
-install:
- - pip install -U pip setuptools
- - pip install -r test-reqs.txt
-
-test_script:
- - tox -e py36 -- -vvv
-
From 7897678777982e942aa6c22b823aced7ffd07095 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Tue, 11 Apr 2017 23:44:17 +0900
Subject: [PATCH 05/32] Fix #3618: autodoc crashes with tupled arguments
---
CHANGES | 1 +
sphinx/ext/autodoc.py | 17 +++++++++++++----
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/CHANGES b/CHANGES
index e192bf5b7..4035a50ce 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,7 @@ Bugs fixed
----------
* #3614: Sphinx crashes with requests-2.5.0
+* #3618: autodoc crashes with tupled arguments
Testing
--------
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index 9e513276f..9203e673b 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -380,10 +380,19 @@ def formatargspec(function, args, varargs=None, varkw=None, defaults=None,
for i, arg in enumerate(args):
arg_fd = StringIO()
- arg_fd.write(format_arg_with_annotation(arg))
- if defaults and i >= defaults_start:
- arg_fd.write(' = ' if arg in annotations else '=')
- arg_fd.write(object_description(defaults[i - defaults_start]))
+ if isinstance(arg, list):
+ # support tupled arguments list (only for py2): def foo((x, y))
+ arg_fd.write('(')
+ arg_fd.write(format_arg_with_annotation(arg[0]))
+ for param in arg[1:]:
+ arg_fd.write(', ')
+ arg_fd.write(format_arg_with_annotation(param))
+ arg_fd.write(')')
+ else:
+ arg_fd.write(format_arg_with_annotation(arg))
+ if defaults and i >= defaults_start:
+ arg_fd.write(' = ' if arg in annotations else '=')
+ arg_fd.write(object_description(defaults[i - defaults_start]))
formatted.append(arg_fd.getvalue())
if varargs:
From ac1020b540c7f5d04ebcc428b48fea5053fe734a Mon Sep 17 00:00:00 2001
From: jfbu
Date: Mon, 24 Apr 2017 10:19:49 +0200
Subject: [PATCH 06/32] Remove empty 1.5.6 section in CHANGES file
---
CHANGES | 18 ------------------
1 file changed, 18 deletions(-)
diff --git a/CHANGES b/CHANGES
index 979c39ff3..bb682a792 100644
--- a/CHANGES
+++ b/CHANGES
@@ -193,24 +193,6 @@ Deprecated
* #3628: ``sphinx_themes`` entry_point is deprecated. Please use
``sphinx.html_themes`` instead.
-Release 1.5.6 (in development)
-==============================
-
-Incompatible changes
---------------------
-
-Deprecated
-----------
-
-Features added
---------------
-
-Bugs fixed
-----------
-
-Testing
---------
-
Release 1.5.5 (released Apr 03, 2017)
=====================================
From 2807175f10158da274d7a3714d0dc612bbcff403 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Tue, 25 Apr 2017 00:36:42 +0900
Subject: [PATCH 07/32] Fix #3661: sphinx-build crashes on parallel build
---
CHANGES | 2 ++
sphinx/environment/__init__.py | 6 +++---
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/CHANGES b/CHANGES
index bb682a792..aecd3ce5b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -13,6 +13,8 @@ Features added
Bugs fixed
----------
+* #3661: sphinx-build crashes on parallel build
+
Testing
--------
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index 066f57209..fd89a07e4 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -20,7 +20,7 @@ import warnings
from os import path
from collections import defaultdict
-from six import StringIO, itervalues, class_types, next
+from six import BytesIO, itervalues, class_types, next
from six.moves import cPickle as pickle
from docutils.io import NullOutput
@@ -121,7 +121,7 @@ class BuildEnvironment(object):
@classmethod
def loads(cls, string, app=None):
# type: (unicode, Sphinx) -> BuildEnvironment
- io = StringIO(string)
+ io = BytesIO(string)
return cls.load(io, app)
@classmethod
@@ -156,7 +156,7 @@ class BuildEnvironment(object):
@classmethod
def dumps(cls, env):
# type: (BuildEnvironment) -> unicode
- io = StringIO()
+ io = BytesIO()
cls.dump(env, io)
return io.getvalue()
From 10afb48b8e6e6db61dec9665ae3bd7035b571853 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Tue, 25 Apr 2017 00:39:00 +0900
Subject: [PATCH 08/32] Revert "Remove empty 1.5.6 section in CHANGES file"
This reverts commit ac1020b540c7f5d04ebcc428b48fea5053fe734a.
---
CHANGES | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/CHANGES b/CHANGES
index aecd3ce5b..77f75a6c5 100644
--- a/CHANGES
+++ b/CHANGES
@@ -195,6 +195,24 @@ Deprecated
* #3628: ``sphinx_themes`` entry_point is deprecated. Please use
``sphinx.html_themes`` instead.
+Release 1.5.6 (in development)
+==============================
+
+Incompatible changes
+--------------------
+
+Deprecated
+----------
+
+Features added
+--------------
+
+Bugs fixed
+----------
+
+Testing
+--------
+
Release 1.5.5 (released Apr 03, 2017)
=====================================
From 7c2f5f16eb1898e8b154d1a9bcfa13782b3c2d24 Mon Sep 17 00:00:00 2001
From: jfbu
Date: Tue, 25 Apr 2017 10:14:53 +0200
Subject: [PATCH 09/32] Fix #3664 relative to ``\labelsep`` setting in LaTeX
fulllineitems
This also removes re-definition of description environment which is not
needed anymore as ``\labelsep`` is not modified.
---
CHANGES | 1 +
sphinx/texinputs/sphinx.sty | 21 +++++++--------------
2 files changed, 8 insertions(+), 14 deletions(-)
diff --git a/CHANGES b/CHANGES
index 4035a50ce..b38d91c4d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -15,6 +15,7 @@ Bugs fixed
* #3614: Sphinx crashes with requests-2.5.0
* #3618: autodoc crashes with tupled arguments
+* #3664: No space after the bullet in items of a latex list produced by Sphinx
Testing
--------
diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty
index 571f26c72..9c2a0d72f 100644
--- a/sphinx/texinputs/sphinx.sty
+++ b/sphinx/texinputs/sphinx.sty
@@ -6,7 +6,7 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
-\ProvidesPackage{sphinx}[2017/03/26 v1.5.4 LaTeX package (Sphinx markup)]
+\ProvidesPackage{sphinx}[2017/04/25 v1.5.6 LaTeX package (Sphinx markup)]
% this is the \ltx@ifundefined of ltxcmds.sty, which is loaded by
% kvoptions (and later by hyperref), but the first release of
@@ -1164,26 +1164,19 @@
% {fulllineitems} is the main environment for object descriptions.
%
\newcommand{\py@itemnewline}[1]{%
+ \kern\labelsep
\@tempdima\linewidth
- \advance\@tempdima \leftmargin\makebox[\@tempdima][l]{#1}%
+ \advance\@tempdima \labelwidth\makebox[\@tempdima][l]{#1}%
+ \kern-\labelsep
}
-\newenvironment{fulllineitems}{
- \begin{list}{}{\labelwidth \leftmargin \labelsep \z@
+\newenvironment{fulllineitems}{%
+ \begin{list}{}{\labelwidth \leftmargin
\rightmargin \z@ \topsep -\parskip \partopsep \parskip
\itemsep -\parsep
- \let\makelabel=\py@itemnewline}
+ \let\makelabel=\py@itemnewline}%
}{\end{list}}
-% Redefine description environment so that it is usable inside fulllineitems.
-%
-% FIXME: use sphinxdescription, do not redefine description environment!
-\renewcommand{\description}{%
- \list{}{\labelwidth\z@
- \itemindent-\leftmargin
- \labelsep5pt\relax
- \let\makelabel=\descriptionlabel}}
-
% Signatures, possibly multi-line
%
\newlength{\py@argswidth}
From 710ddb388045184f921666b2ad7aef16d131de3f Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Tue, 25 Apr 2017 20:05:18 +0900
Subject: [PATCH 10/32] Fix mypy violations
---
sphinx/util/requests.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sphinx/util/requests.py b/sphinx/util/requests.py
index 09b7a43b1..6834e6368 100644
--- a/sphinx/util/requests.py
+++ b/sphinx/util/requests.py
@@ -41,7 +41,7 @@ try:
except ImportError:
try:
# for Debian-jessie
- from urllib3.exceptions import InsecurePlatformWarning
+ from urllib3.exceptions import InsecurePlatformWarning # type: ignore
except ImportError:
# for requests < 2.4.0
InsecurePlatformWarning = None
From b3f596a1330137cf34bc9163cbeebba52ab511e5 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Tue, 25 Apr 2017 01:16:19 +0900
Subject: [PATCH 11/32] Fix #3662: ``builder.css_files`` is deprecated
---
CHANGES | 3 +++
sphinx/builders/html.py | 33 ++++++++++++++++++++++++++++++++-
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/CHANGES b/CHANGES
index 0d72fa989..2e4e6f676 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,9 @@ Incompatible changes
Deprecated
----------
+* #3662: ``builder.css_files`` is deprecated. Please use ``add_stylesheet()``
+ API instead.
+
Features added
--------------
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 7369ea23d..cea14965a 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -13,6 +13,7 @@ import os
import re
import sys
import codecs
+import warnings
import posixpath
from os import path
from hashlib import md5
@@ -38,6 +39,7 @@ from sphinx.util.docutils import is_html5_writer_available, __version_info__
from sphinx.util.fileutil import copy_asset
from sphinx.util.matching import patmatch, Matcher, DOTFILES
from sphinx.config import string_classes
+from sphinx.deprecation import RemovedInSphinx20Warning
from sphinx.locale import _, l_
from sphinx.search import js_index
from sphinx.theming import HTMLThemeFactory
@@ -87,6 +89,35 @@ def get_stable_hash(obj):
return md5(text_type(obj).encode('utf8')).hexdigest()
+class CSSContainer(list):
+ """The container of stylesheets.
+
+ To support the extensions which access the container directly, this wraps
+ the entry with Stylesheet class.
+ """
+ def append(self, obj):
+ warnings.warn('builder.css_files is deprecated. '
+ 'Please use app.add_stylesheet() instead.',
+ RemovedInSphinx20Warning)
+ if isinstance(obj, Stylesheet):
+ super(CSSContainer, self).append(obj)
+ else:
+ super(CSSContainer, self).append(Stylesheet(obj, None, 'stylesheet'))
+
+ def extend(self, other):
+ for item in other:
+ self.append(item)
+
+ def __iadd__(self, other):
+ for item in other:
+ self.append(item)
+
+ def __add__(self, other):
+ ret = CSSContainer(self)
+ ret += other
+ return ret
+
+
class Stylesheet(text_type):
"""The metadata of stylesheet.
@@ -136,7 +167,7 @@ class StandaloneHTMLBuilder(Builder):
script_files = ['_static/jquery.js', '_static/underscore.js',
'_static/doctools.js'] # type: List[unicode]
# Ditto for this one (Sphinx.add_stylesheet).
- css_files = [] # type: List[Dict[unicode, unicode]]
+ css_files = CSSContainer() # type: List[Dict[unicode, unicode]]
imgpath = None # type: unicode
domain_indices = [] # type: List[Tuple[unicode, Type[Index], List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool]] # NOQA
From edc7f30b9cc92f4d721eeef62ffa826f23a09a9f Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev
Date: Tue, 14 Mar 2017 23:43:04 +0300
Subject: [PATCH 12/32] Remove the custom smartypants code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Instead rely on docutils’ ‘smart_quotes’ option which is available
since docutils 0.10.
This adds support for internationalization: our code supported only
English quotes, while docutils code supports 27 different languages.
Closes #498, #580, #3345, #3472.
---
sphinx/builders/_epub_base.py | 14 +-
sphinx/builders/html.py | 15 +-
sphinx/environment/__init__.py | 5 +
sphinx/util/smartypants.py | 312 ------------------------------
sphinx/writers/html.py | 94 ---------
sphinx/writers/html5.py | 94 ---------
sphinx/writers/latex.py | 5 -
tests/test_api_translator.py | 9 -
tests/test_build_epub.py | 8 +-
tests/test_environment_toctree.py | 6 +-
tests/test_markup.py | 11 +-
tests/test_metadata.py | 4 +-
12 files changed, 38 insertions(+), 539 deletions(-)
delete mode 100644 sphinx/util/smartypants.py
diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py
index f7ebaa0e8..a63ecbc39 100644
--- a/sphinx/builders/_epub_base.py
+++ b/sphinx/builders/_epub_base.py
@@ -25,6 +25,7 @@ except ImportError:
Image = None
from docutils import nodes
+from docutils.utils import smartquotes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
@@ -32,7 +33,6 @@ from sphinx.util import logging
from sphinx.util import status_iterator
from sphinx.util.osutil import ensuredir, copyfile
from sphinx.util.fileutil import copy_asset_file
-from sphinx.util.smartypants import sphinx_smarty_pants as ssp
if False:
# For type annotation
@@ -94,6 +94,18 @@ Guide = namedtuple('Guide', ['type', 'title', 'uri'])
NavPoint = namedtuple('NavPoint', ['navpoint', 'playorder', 'text', 'refuri', 'children'])
+def sphinx_smarty_pants(t, language='en'):
+ # type: (unicode, str) -> unicode
+ t = t.replace('"', '"')
+ t = smartquotes.educateDashesOldSchool(t)
+ t = smartquotes.educateQuotes(t, language)
+ t = t.replace('"', '"')
+ return t
+
+
+ssp = sphinx_smarty_pants
+
+
# The epub publisher
class EpubBuilder(StandaloneHTMLBuilder):
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 7369ea23d..a0b3d8e87 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -45,8 +45,7 @@ from sphinx.builders import Builder
from sphinx.application import ENV_PICKLE_FILENAME
from sphinx.highlighting import PygmentsBridge
from sphinx.util.console import bold, darkgreen # type: ignore
-from sphinx.writers.html import HTMLWriter, HTMLTranslator, \
- SmartyPantsHTMLTranslator
+from sphinx.writers.html import HTMLWriter, HTMLTranslator
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.environment.adapters.toctree import TocTree
from sphinx.environment.adapters.indexentries import IndexEntries
@@ -59,7 +58,7 @@ if False:
# Experimental HTML5 Writer
if is_html5_writer_available():
- from sphinx.writers.html5 import HTML5Translator, SmartyPantsHTML5Translator
+ from sphinx.writers.html5 import HTML5Translator
html5_ready = True
else:
html5_ready = False
@@ -220,15 +219,9 @@ class StandaloneHTMLBuilder(Builder):
@property
def default_translator_class(self):
if self.config.html_experimental_html5_writer and html5_ready:
- if self.config.html_use_smartypants:
- return SmartyPantsHTML5Translator
- else:
- return HTML5Translator
+ return HTML5Translator
else:
- if self.config.html_use_smartypants:
- return SmartyPantsHTMLTranslator
- else:
- return HTMLTranslator
+ return HTMLTranslator
def get_outdated_docs(self):
# type: () -> Iterator[unicode]
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index fd89a07e4..b0a1a2ce5 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -26,6 +26,7 @@ from six.moves import cPickle as pickle
from docutils.io import NullOutput
from docutils.core import Publisher
from docutils.utils import Reporter, get_source_line
+from docutils.utils.smartquotes import smartchars
from docutils.parsers.rst import roles
from docutils.parsers.rst.languages import en as english
from docutils.frontend import OptionParser
@@ -671,6 +672,10 @@ class BuildEnvironment(object):
self.settings['trim_footnote_reference_space'] = \
self.config.trim_footnote_reference_space
self.settings['gettext_compact'] = self.config.gettext_compact
+ language = (self.config.language or 'en').replace('_', '-')
+ self.settings['language_code'] = language
+ if language in smartchars.quotes:
+ self.settings['smart_quotes'] = self.config.html_use_smartypants
docutilsconf = path.join(self.srcdir, 'docutils.conf')
# read docutils.conf from source dir, not from current dir
diff --git a/sphinx/util/smartypants.py b/sphinx/util/smartypants.py
deleted file mode 100644
index 0146ba6e9..000000000
--- a/sphinx/util/smartypants.py
+++ /dev/null
@@ -1,312 +0,0 @@
-r"""
-This is based on SmartyPants.py by `Chad Miller`_ ,
-version 1.5_1.6.
-
-Copyright and License
-=====================
-
-SmartyPants_ license::
-
- Copyright (c) 2003 John Gruber
- (http://daringfireball.net/)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- * Neither the name "SmartyPants" nor the names of its contributors
- may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
- This software is provided by the copyright holders and contributors "as
- is" and any express or implied warranties, including, but not limited
- to, the implied warranties of merchantability and fitness for a
- particular purpose are disclaimed. In no event shall the copyright
- owner or contributors be liable for any direct, indirect, incidental,
- special, exemplary, or consequential damages (including, but not
- limited to, procurement of substitute goods or services; loss of use,
- data, or profits; or business interruption) however caused and on any
- theory of liability, whether in contract, strict liability, or tort
- (including negligence or otherwise) arising in any way out of the use
- of this software, even if advised of the possibility of such damage.
-
-
-smartypants.py license::
-
- smartypants.py is a derivative work of SmartyPants.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- This software is provided by the copyright holders and contributors "as
- is" and any express or implied warranties, including, but not limited
- to, the implied warranties of merchantability and fitness for a
- particular purpose are disclaimed. In no event shall the copyright
- owner or contributors be liable for any direct, indirect, incidental,
- special, exemplary, or consequential damages (including, but not
- limited to, procurement of substitute goods or services; loss of use,
- data, or profits; or business interruption) however caused and on any
- theory of liability, whether in contract, strict liability, or tort
- (including negligence or otherwise) arising in any way out of the use
- of this software, even if advised of the possibility of such damage.
-
-.. _Chad Miller: http://web.chad.org/
-"""
-
-import re
-
-if False:
- # For type annotation
- from typing import Tuple # NOQA
-
-
-def sphinx_smarty_pants(t):
- # type: (unicode) -> unicode
- t = t.replace('"', '"')
- t = educate_dashes_oldschool(t)
- t = educate_quotes(t) # type: ignore
- t = t.replace('"', '"')
- return t
-
-
-# Constants for quote education.
-punct_class = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]"""
-end_of_word_class = r"""[\s.,;:!?)]"""
-close_class = r"""[^\ \t\r\n\[\{\(\-]"""
-dec_dashes = r"""–|—"""
-
-# Special case if the very first character is a quote
-# followed by punctuation at a non-word-break. Close the quotes by brute force:
-single_quote_start_re = re.compile(r"""^'(?=%s\\B)""" % (punct_class,))
-double_quote_start_re = re.compile(r"""^"(?=%s\\B)""" % (punct_class,))
-
-# Special case for double sets of quotes, e.g.:
-# He said, "'Quoted' words in a larger quote."
-double_quote_sets_re = re.compile(r""""'(?=\w)""")
-single_quote_sets_re = re.compile(r"""'"(?=\w)""")
-
-# Special case for decade abbreviations (the '80s):
-decade_abbr_re = re.compile(r"""\b'(?=\d{2}s)""")
-
-# Get most opening double quotes:
-opening_double_quotes_regex = re.compile(r"""
- (
- \s | # a whitespace char, or
- | # a non-breaking space entity, or
- -- | # dashes, or
- &[mn]dash; | # named dash entities
- %s | # or decimal entities
- &\#x201[34]; # or hex
- )
- " # the quote
- (?=\w) # followed by a word character
- """ % (dec_dashes,), re.VERBOSE)
-
-# Double closing quotes:
-closing_double_quotes_regex = re.compile(r"""
- #(%s)? # character that indicates the quote should be closing
- "
- (?=%s)
- """ % (close_class, end_of_word_class), re.VERBOSE)
-
-closing_double_quotes_regex_2 = re.compile(r"""
- (%s) # character that indicates the quote should be closing
- "
- """ % (close_class,), re.VERBOSE)
-
-# Get most opening single quotes:
-opening_single_quotes_regex = re.compile(r"""
- (
- \s | # a whitespace char, or
- | # a non-breaking space entity, or
- -- | # dashes, or
- &[mn]dash; | # named dash entities
- %s | # or decimal entities
- &\#x201[34]; # or hex
- )
- ' # the quote
- (?=\w) # followed by a word character
- """ % (dec_dashes,), re.VERBOSE)
-
-closing_single_quotes_regex = re.compile(r"""
- (%s)
- '
- (?!\s | s\b | \d)
- """ % (close_class,), re.VERBOSE)
-
-closing_single_quotes_regex_2 = re.compile(r"""
- (%s)
- '
- (\s | s\b)
- """ % (close_class,), re.VERBOSE)
-
-
-def educate_quotes(s):
- # type: (str) -> str
- """
- Parameter: String.
-
- Returns: The string, with "educated" curly quote HTML entities.
-
- Example input: "Isn't this fun?"
- Example output: “Isn’t this fun?”
- """
-
- # Special case if the very first character is a quote
- # followed by punctuation at a non-word-break. Close the quotes
- # by brute force:
- s = single_quote_start_re.sub("’", s)
- s = double_quote_start_re.sub("”", s)
-
- # Special case for double sets of quotes, e.g.:
- # He said, "'Quoted' words in a larger quote."
- s = double_quote_sets_re.sub("“‘", s)
- s = single_quote_sets_re.sub("‘“", s)
-
- # Special case for decade abbreviations (the '80s):
- s = decade_abbr_re.sub("’", s)
-
- s = opening_single_quotes_regex.sub(r"\1‘", s)
- s = closing_single_quotes_regex.sub(r"\1’", s)
- s = closing_single_quotes_regex_2.sub(r"\1’\2", s)
-
- # Any remaining single quotes should be opening ones:
- s = s.replace("'", "‘")
-
- s = opening_double_quotes_regex.sub(r"\1“", s)
- s = closing_double_quotes_regex.sub(r"”", s)
- s = closing_double_quotes_regex_2.sub(r"\1”", s)
-
- # Any remaining quotes should be opening ones.
- return s.replace('"', "“")
-
-
-def educate_quotes_latex(s, dquotes=("``", "''")):
- # type: (str, Tuple[str, str]) -> unicode
- """
- Parameter: String.
-
- Returns: The string, with double quotes corrected to LaTeX quotes.
-
- Example input: "Isn't this fun?"
- Example output: ``Isn't this fun?'';
- """
-
- # Special case if the very first character is a quote
- # followed by punctuation at a non-word-break. Close the quotes
- # by brute force:
- s = single_quote_start_re.sub("\x04", s)
- s = double_quote_start_re.sub("\x02", s)
-
- # Special case for double sets of quotes, e.g.:
- # He said, "'Quoted' words in a larger quote."
- s = double_quote_sets_re.sub("\x01\x03", s)
- s = single_quote_sets_re.sub("\x03\x01", s)
-
- # Special case for decade abbreviations (the '80s):
- s = decade_abbr_re.sub("\x04", s)
-
- s = opening_single_quotes_regex.sub("\\1\x03", s)
- s = closing_single_quotes_regex.sub("\\1\x04", s)
- s = closing_single_quotes_regex_2.sub("\\1\x04\\2", s)
-
- # Any remaining single quotes should be opening ones:
- s = s.replace("'", "\x03")
-
- s = opening_double_quotes_regex.sub("\\1\x01", s)
- s = closing_double_quotes_regex.sub("\x02", s)
- s = closing_double_quotes_regex_2.sub("\\1\x02", s)
-
- # Any remaining quotes should be opening ones.
- s = s.replace('"', "\x01")
-
- # Finally, replace all helpers with quotes.
- return s.replace("\x01", dquotes[0]).replace("\x02", dquotes[1]).\
- replace("\x03", "`").replace("\x04", "'")
-
-
-def educate_backticks(s):
- # type: (unicode) -> unicode
- """
- Parameter: String.
- Returns: The string, with ``backticks'' -style double quotes
- translated into HTML curly quote entities.
- Example input: ``Isn't this fun?''
- Example output: “Isn't this fun?”
- """
- return s.replace("``", "“").replace("''", "”")
-
-
-def educate_single_backticks(s):
- # type: (unicode) -> unicode
- """
- Parameter: String.
- Returns: The string, with `backticks' -style single quotes
- translated into HTML curly quote entities.
-
- Example input: `Isn't this fun?'
- Example output: ‘Isn’t this fun?’
- """
- return s.replace('`', "‘").replace("'", "’")
-
-
-def educate_dashes_oldschool(s):
- # type: (unicode) -> unicode
- """
- Parameter: String.
-
- Returns: The string, with each instance of "--" translated to
- an en-dash HTML entity, and each "---" translated to
- an em-dash HTML entity.
- """
- return s.replace('---', "—").replace('--', "–")
-
-
-def educate_dashes_oldschool_inverted(s):
- # type: (unicode) -> unicode
- """
- Parameter: String.
-
- Returns: The string, with each instance of "--" translated to
- an em-dash HTML entity, and each "---" translated to
- an en-dash HTML entity. Two reasons why: First, unlike the
- en- and em-dash syntax supported by
- educate_dashes_oldschool(), it's compatible with existing
- entries written before SmartyPants 1.1, back when "--" was
- only used for em-dashes. Second, em-dashes are more
- common than en-dashes, and so it sort of makes sense that
- the shortcut should be shorter to type. (Thanks to Aaron
- Swartz for the idea.)
- """
- return s.replace('---', "–").replace('--', "—")
-
-
-def educate_ellipses(s):
- # type: (unicode) -> unicode
- """
- Parameter: String.
- Returns: The string, with each instance of "..." translated to
- an ellipsis HTML entity.
-
- Example input: Huh...?
- Example output: Huh…?
- """
- return s.replace('...', "…").replace('. . .', "…")
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
index 63aba3cd6..572b2825e 100644
--- a/sphinx/writers/html.py
+++ b/sphinx/writers/html.py
@@ -22,7 +22,6 @@ from sphinx import addnodes
from sphinx.locale import admonitionlabels, _
from sphinx.util import logging
from sphinx.util.images import get_image_size
-from sphinx.util.smartypants import sphinx_smarty_pants
if False:
# For type annotation
@@ -74,7 +73,6 @@ class HTMLTranslator(BaseTranslator):
# type: (StandaloneHTMLBuilder, Any, Any) -> None
BaseTranslator.__init__(self, *args, **kwds)
self.highlighter = builder.highlighter
- self.no_smarty = 0
self.builder = builder
self.highlightlang = self.highlightlang_base = \
builder.config.highlight_language
@@ -786,7 +784,6 @@ class HTMLTranslator(BaseTranslator):
# type: (nodes.Node) -> None
self.depart_admonition(node)
- # these are only handled specially in the SmartyPantsHTMLTranslator
def visit_literal_emphasis(self, node):
# type: (nodes.Node) -> None
return self.visit_emphasis(node)
@@ -875,94 +872,3 @@ class HTMLTranslator(BaseTranslator):
def unknown_visit(self, node):
# type: (nodes.Node) -> None
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
-
-
-class SmartyPantsHTMLTranslator(HTMLTranslator):
- """
- Handle ordinary text via smartypants, converting quotes and dashes
- to the correct entities.
- """
-
- def __init__(self, *args, **kwds):
- # type: (Any, Any) -> None
- self.no_smarty = 0
- HTMLTranslator.__init__(self, *args, **kwds)
-
- def visit_literal(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- try:
- # this raises SkipNode
- HTMLTranslator.visit_literal(self, node)
- finally:
- self.no_smarty -= 1
-
- def visit_literal_block(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- try:
- HTMLTranslator.visit_literal_block(self, node)
- except nodes.SkipNode:
- # HTMLTranslator raises SkipNode for simple literal blocks,
- # but not for parsed literal blocks
- self.no_smarty -= 1
- raise
-
- def depart_literal_block(self, node):
- # type: (nodes.Node) -> None
- HTMLTranslator.depart_literal_block(self, node)
- self.no_smarty -= 1
-
- def visit_literal_emphasis(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- self.visit_emphasis(node)
-
- def depart_literal_emphasis(self, node):
- # type: (nodes.Node) -> None
- self.depart_emphasis(node)
- self.no_smarty -= 1
-
- def visit_literal_strong(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- self.visit_strong(node)
-
- def depart_literal_strong(self, node):
- # type: (nodes.Node) -> None
- self.depart_strong(node)
- self.no_smarty -= 1
-
- def visit_desc_signature(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- HTMLTranslator.visit_desc_signature(self, node)
-
- def depart_desc_signature(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty -= 1
- HTMLTranslator.depart_desc_signature(self, node)
-
- def visit_productionlist(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- try:
- HTMLTranslator.visit_productionlist(self, node)
- finally:
- self.no_smarty -= 1
-
- def visit_option(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- HTMLTranslator.visit_option(self, node)
-
- def depart_option(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty -= 1
- HTMLTranslator.depart_option(self, node)
-
- def bulk_text_processor(self, text):
- # type: (unicode) -> unicode
- if self.no_smarty <= 0:
- return sphinx_smarty_pants(text)
- return text
diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py
index 9deb35a88..8e3843c09 100644
--- a/sphinx/writers/html5.py
+++ b/sphinx/writers/html5.py
@@ -21,7 +21,6 @@ from sphinx import addnodes
from sphinx.locale import admonitionlabels, _
from sphinx.util import logging
from sphinx.util.images import get_image_size
-from sphinx.util.smartypants import sphinx_smarty_pants
if False:
# For type annotation
@@ -44,7 +43,6 @@ class HTML5Translator(BaseTranslator):
# type: (StandaloneHTMLBuilder, Any, Any) -> None
BaseTranslator.__init__(self, *args, **kwds)
self.highlighter = builder.highlighter
- self.no_smarty = 0
self.builder = builder
self.highlightlang = self.highlightlang_base = \
builder.config.highlight_language
@@ -729,7 +727,6 @@ class HTML5Translator(BaseTranslator):
# type: (nodes.Node) -> None
self.depart_admonition(node)
- # these are only handled specially in the SmartyPantsHTML5Translator
def visit_literal_emphasis(self, node):
# type: (nodes.Node) -> None
return self.visit_emphasis(node)
@@ -830,94 +827,3 @@ class HTML5Translator(BaseTranslator):
def unknown_visit(self, node):
# type: (nodes.Node) -> None
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
-
-
-class SmartyPantsHTML5Translator(HTML5Translator):
- """
- Handle ordinary text via smartypants, converting quotes and dashes
- to the correct entities.
- """
-
- def __init__(self, *args, **kwds):
- # type: (Any, Any) -> None
- self.no_smarty = 0
- HTML5Translator.__init__(self, *args, **kwds)
-
- def visit_literal(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- try:
- # this raises SkipNode
- HTML5Translator.visit_literal(self, node)
- finally:
- self.no_smarty -= 1
-
- def visit_literal_block(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- try:
- HTML5Translator.visit_literal_block(self, node)
- except nodes.SkipNode:
- # HTML5Translator raises SkipNode for simple literal blocks,
- # but not for parsed literal blocks
- self.no_smarty -= 1
- raise
-
- def depart_literal_block(self, node):
- # type: (nodes.Node) -> None
- HTML5Translator.depart_literal_block(self, node)
- self.no_smarty -= 1
-
- def visit_literal_emphasis(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- self.visit_emphasis(node)
-
- def depart_literal_emphasis(self, node):
- # type: (nodes.Node) -> None
- self.depart_emphasis(node)
- self.no_smarty -= 1
-
- def visit_literal_strong(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- self.visit_strong(node)
-
- def depart_literal_strong(self, node):
- # type: (nodes.Node) -> None
- self.depart_strong(node)
- self.no_smarty -= 1
-
- def visit_desc_signature(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- HTML5Translator.visit_desc_signature(self, node)
-
- def depart_desc_signature(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty -= 1
- HTML5Translator.depart_desc_signature(self, node)
-
- def visit_productionlist(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- try:
- HTML5Translator.visit_productionlist(self, node)
- finally:
- self.no_smarty -= 1
-
- def visit_option(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty += 1
- HTML5Translator.visit_option(self, node)
-
- def depart_option(self, node):
- # type: (nodes.Node) -> None
- self.no_smarty -= 1
- HTML5Translator.depart_option(self, node)
-
- def bulk_text_processor(self, text):
- # type: (unicode) -> unicode
- if self.no_smarty <= 0:
- return sphinx_smarty_pants(text)
- return text
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index fc2cbb272..c1e33374d 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -30,7 +30,6 @@ from sphinx.util.i18n import format_date
from sphinx.util.nodes import clean_astext, traverse_parent
from sphinx.util.template import LaTeXRenderer
from sphinx.util.texescape import tex_escape_map, tex_replace_map
-from sphinx.util.smartypants import educate_quotes_latex
if False:
# For type annotation
@@ -2533,10 +2532,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_Text(self, node):
# type: (nodes.Node) -> None
text = self.encode(node.astext())
- if not self.no_contractions and not self.in_parsed_literal:
- text = educate_quotes_latex(text, # type: ignore
- dquotes=("\\sphinxquotedblleft{}",
- "\\sphinxquotedblright{}"))
self.body.append(text)
def depart_Text(self, node):
diff --git a/tests/test_api_translator.py b/tests/test_api_translator.py
index 511fe1416..dadea50e5 100644
--- a/tests/test_api_translator.py
+++ b/tests/test_api_translator.py
@@ -28,15 +28,6 @@ def test_html_translator(app, status, warning):
# no set_translator()
translator_class = app.builder.get_translator_class()
assert translator_class
- assert translator_class.__name__ == 'SmartyPantsHTMLTranslator'
-
-
-@pytest.mark.sphinx('html', confoverrides={
- 'html_use_smartypants': False})
-def test_html_with_smartypants(app, status, warning):
- # no set_translator(), html_use_smartypants=False
- translator_class = app.builder.get_translator_class()
- assert translator_class
assert translator_class.__name__ == 'HTMLTranslator'
diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py
index cf0e2857a..e5d86b0ed 100644
--- a/tests/test_build_epub.py
+++ b/tests/test_build_epub.py
@@ -162,7 +162,7 @@ def test_nested_toc(app):
app.build()
# toc.ncx
- toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').text())
+ toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').bytes())
assert toc.find("./ncx:docTitle/ncx:text").text == 'Python documentation'
# toc.ncx / navPoint
@@ -175,7 +175,7 @@ def test_nested_toc(app):
navpoints = toc.findall("./ncx:navMap/ncx:navPoint")
assert len(navpoints) == 4
assert navinfo(navpoints[0]) == ('navPoint1', '1', 'index.xhtml',
- "Welcome to Sphinx Tests's documentation!")
+ u"Welcome to Sphinx Tests’s documentation!")
assert navpoints[0].findall("./ncx:navPoint") == []
# toc.ncx / nested navPoints
@@ -192,11 +192,11 @@ def test_nested_toc(app):
anchor = elem.find("./xhtml:a")
return (anchor.get('href'), anchor.text)
- nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').text())
+ nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').bytes())
toc = nav.findall("./xhtml:body/xhtml:nav/xhtml:ol/xhtml:li")
assert len(toc) == 4
assert navinfo(toc[0]) == ('index.xhtml',
- "Welcome to Sphinx Tests's documentation!")
+ u"Welcome to Sphinx Tests’s documentation!")
assert toc[0].findall("./xhtml:ol") == []
# nav.xhtml / nested toc
diff --git a/tests/test_environment_toctree.py b/tests/test_environment_toctree.py
index 0f1dffa43..a2d54fb79 100644
--- a/tests/test_environment_toctree.py
+++ b/tests/test_environment_toctree.py
@@ -36,7 +36,7 @@ def test_process_doc(app):
list_item)])
assert_node(toctree[0][0],
- [compact_paragraph, reference, "Welcome to Sphinx Tests's documentation!"])
+ [compact_paragraph, reference, u"Welcome to Sphinx Tests’s documentation!"])
assert_node(toctree[0][0][0], reference, anchorname='')
assert_node(toctree[0][1][0], addnodes.toctree,
caption="Table of Contents", glob=False, hidden=False,
@@ -150,7 +150,7 @@ def test_get_toc_for(app):
addnodes.toctree)])],
[list_item, compact_paragraph])]) # [2][0]
assert_node(toctree[0][0],
- [compact_paragraph, reference, "Welcome to Sphinx Tests's documentation!"])
+ [compact_paragraph, reference, u"Welcome to Sphinx Tests’s documentation!"])
assert_node(toctree[0][1][2],
([compact_paragraph, reference, "subsection"],
[bullet_list, list_item, compact_paragraph, reference, "subsubsection"]))
@@ -177,7 +177,7 @@ def test_get_toc_for_only(app):
addnodes.toctree)])],
[list_item, compact_paragraph])]) # [2][0]
assert_node(toctree[0][0],
- [compact_paragraph, reference, "Welcome to Sphinx Tests's documentation!"])
+ [compact_paragraph, reference, u"Welcome to Sphinx Tests’s documentation!"])
assert_node(toctree[0][1][1],
([compact_paragraph, reference, "Section for HTML"],
[bullet_list, addnodes.toctree]))
diff --git a/tests/test_markup.py b/tests/test_markup.py
index ecc4b6a11..18c9d0bbd 100644
--- a/tests/test_markup.py
+++ b/tests/test_markup.py
@@ -14,11 +14,12 @@ import pickle
from docutils import frontend, utils, nodes
from docutils.parsers.rst import Parser as RstParser
+from docutils.transforms.universal import SmartQuotes
from sphinx import addnodes
from sphinx.util import texescape
from sphinx.util.docutils import sphinx_domains
-from sphinx.writers.html import HTMLWriter, SmartyPantsHTMLTranslator
+from sphinx.writers.html import HTMLWriter, HTMLTranslator
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
import pytest
@@ -31,6 +32,7 @@ def settings(app):
optparser = frontend.OptionParser(
components=(RstParser, HTMLWriter, LaTeXWriter))
settings = optparser.get_default_values()
+ settings.smart_quotes = True
settings.env = app.builder.env
settings.env.temp_data['docname'] = 'dummy'
domain_context = sphinx_domains(settings.env)
@@ -46,6 +48,7 @@ def parse(settings):
document['file'] = 'dummy'
parser = RstParser()
parser.parse(rst, document)
+ SmartQuotes(document, startnode=None).apply()
for msg in document.traverse(nodes.system_message):
if msg['level'] == 1:
msg.replace_self([])
@@ -62,7 +65,7 @@ class ForgivingTranslator:
pass
-class ForgivingHTMLTranslator(SmartyPantsHTMLTranslator, ForgivingTranslator):
+class ForgivingHTMLTranslator(HTMLTranslator, ForgivingTranslator):
pass
@@ -178,8 +181,8 @@ def get_verifier(verify, verify_re):
# verify smarty-pants quotes
'verify',
'"John"',
- '“John”
',
- r'\sphinxquotedblleft{}John\sphinxquotedblright{}',
+ u'“John”
',
+ u"“John”",
),
(
# ... but not in literal text
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
index 77efff5ed..58f573b0a 100644
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -34,14 +34,14 @@ def test_docinfo(app, status, warning):
'field name': u'This is a generic bibliographic field.',
'field name 2': (u'Generic bibliographic fields may contain multiple '
u'body elements.\n\nLike this.'),
- 'status': u'This is a "work in progress"',
+ 'status': u'This is a “work in progress”',
'version': u'1',
'copyright': (u'This document has been placed in the public domain. '
u'You\nmay do with it as you wish. You may copy, modify,'
u'\nredistribute, reattribute, sell, buy, rent, lease,\n'
u'destroy, or improve it, quote it at length, excerpt,\n'
u'incorporate, collate, fold, staple, or mutilate it, or '
- u'do\nanything else to it that your or anyone else\'s '
+ u'do\nanything else to it that your or anyone else’s '
u'heart\ndesires.'),
'contact': u'goodger@python.org',
'date': u'2006-05-21',
From c857f52f4b933ce50c8280f32b400092a9af2ac3 Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev
Date: Fri, 24 Mar 2017 21:29:51 +0300
Subject: [PATCH 13/32] =?UTF-8?q?Monkey=20patch=20docutils=E2=80=99=20educ?=
=?UTF-8?q?ateQuotes=20function=20to=20fix=20apostrophes=20handling?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sphinx/util/__init__.py | 1 +
sphinx/util/smartypants.py | 143 +++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+)
create mode 100644 sphinx/util/smartypants.py
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index d86882259..295848e40 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -34,6 +34,7 @@ from sphinx.util import logging
from sphinx.util.console import strip_colors, colorize, bold, term_width_line # type: ignore
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.osutil import fs_encoding
+from sphinx.util import smartypants # noqa
# import other utilities; partly for backwards compatibility, so don't
# prune unused ones indiscriminately
diff --git a/sphinx/util/smartypants.py b/sphinx/util/smartypants.py
new file mode 100644
index 000000000..3932e9386
--- /dev/null
+++ b/sphinx/util/smartypants.py
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.smartypants
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ This code is copied from docutils’ docutils/utils/smartquotes.py
+ version 1.7.1 (from 2017-03-19). It should be removed in the future.
+
+ :copyright: © 2010 Günter Milde,
+ original `SmartyPants`_: © 2003 John Gruber
+ smartypants.py: © 2004, 2007 Chad Miller
+ :license: Released under the terms of the `2-Clause BSD license`_, in short:
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notices and this notice are preserved.
+ This file is offered as-is, without any warranty.
+
+ .. _SmartyPants: http://daringfireball.net/projects/smartypants/
+ .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
+
+ See the LICENSE file and the original docutils code for details.
+"""
+from __future__ import absolute_import, unicode_literals
+
+import re
+from docutils.utils import smartquotes
+from sphinx.util.docutils import __version_info__ as docutils_version
+
+
+def educateQuotes(text, language='en'):
+ # type: (unicode, unicode) -> unicode
+ """
+ Parameter: - text string (unicode or bytes).
+ - language (`BCP 47` language tag.)
+ Returns: The `text`, with "educated" curly quote characters.
+
+ Example input: "Isn't this fun?"
+ Example output: “Isn’t this fun?“;
+ """
+
+ smart = smartquotes.smartchars(language)
+ smart.apostrophe = u'’'
+
+ # oldtext = text
+ punct_class = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]"""
+
+ # Special case if the very first character is a quote
+ # followed by punctuation at a non-word-break.
+ # Close the quotes by brute force:
+ text = re.sub(r"""^'(?=%s\\B)""" % (punct_class,), smart.csquote, text)
+ text = re.sub(r"""^"(?=%s\\B)""" % (punct_class,), smart.cpquote, text)
+
+ # Special case for double sets of quotes, e.g.:
+ # He said, "'Quoted' words in a larger quote."
+ text = re.sub(r""""'(?=\w)""", smart.opquote + smart.osquote, text)
+ text = re.sub(r"""'"(?=\w)""", smart.osquote + smart.opquote, text)
+
+ # Special case for decade abbreviations (the '80s):
+ text = re.sub(r"""\b'(?=\d{2}s)""", smart.csquote, text)
+
+ close_class = r"""[^\ \t\r\n\[\{\(\-]"""
+ dec_dashes = r"""–|—"""
+
+ # Get most opening single quotes:
+ opening_single_quotes_regex = re.compile(r"""
+ (
+ \s | # a whitespace char, or
+ | # a non-breaking space entity, or
+ -- | # dashes, or
+ &[mn]dash; | # named dash entities
+ %s | # or decimal entities
+ &\#x201[34]; # or hex
+ )
+ ' # the quote
+ (?=\w) # followed by a word character
+ """ % (dec_dashes,), re.VERBOSE | re.UNICODE)
+ text = opening_single_quotes_regex.sub(r'\1' + smart.osquote, text)
+
+ # In many locales, single closing quotes are different from apostrophe:
+ if smart.csquote != smart.apostrophe:
+ apostrophe_regex = re.compile(r"(?<=(\w|\d))'(?=\w)", re.UNICODE)
+ text = apostrophe_regex.sub(smart.apostrophe, text)
+
+ closing_single_quotes_regex = re.compile(r"""
+ (%s)
+ '
+ (?!\s | # whitespace
+ s\b |
+ \d # digits ('80s)
+ )
+ """ % (close_class,), re.VERBOSE | re.UNICODE)
+ text = closing_single_quotes_regex.sub(r'\1' + smart.csquote, text)
+
+ closing_single_quotes_regex = re.compile(r"""
+ (%s)
+ '
+ (\s | s\b)
+ """ % (close_class,), re.VERBOSE | re.UNICODE)
+ text = closing_single_quotes_regex.sub(r'\1%s\2' % smart.csquote, text)
+
+ # Any remaining single quotes should be opening ones:
+ text = re.sub(r"""'""", smart.osquote, text)
+
+ # Get most opening double quotes:
+ opening_double_quotes_regex = re.compile(r"""
+ (
+ \s | # a whitespace char, or
+ | # a non-breaking space entity, or
+ -- | # dashes, or
+ &[mn]dash; | # named dash entities
+ %s | # or decimal entities
+ &\#x201[34]; # or hex
+ )
+ " # the quote
+ (?=\w) # followed by a word character
+ """ % (dec_dashes,), re.VERBOSE)
+ text = opening_double_quotes_regex.sub(r'\1' + smart.opquote, text)
+
+ # Double closing quotes:
+ closing_double_quotes_regex = re.compile(r"""
+ #(%s)? # character that indicates the quote should be closing
+ "
+ (?=\s)
+ """ % (close_class,), re.VERBOSE)
+ text = closing_double_quotes_regex.sub(smart.cpquote, text)
+
+ closing_double_quotes_regex = re.compile(r"""
+ (%s) # character that indicates the quote should be closing
+ "
+ """ % (close_class,), re.VERBOSE)
+ text = closing_double_quotes_regex.sub(r'\1' + smart.cpquote, text)
+
+ # Any remaining quotes should be opening ones.
+ text = re.sub(r'"', smart.opquote, text)
+
+ return text
+
+
+if docutils_version < (0, 13, 2):
+ # Monkey patch the old docutils versions to fix the issue mentioned
+ # at https://sourceforge.net/p/docutils/bugs/313/
+ smartquotes.educateQuotes = educateQuotes
From 1f9e25194339835ab3c68f02ba42dca842bf2803 Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev
Date: Fri, 24 Mar 2017 21:51:21 +0300
Subject: [PATCH 14/32] Add tests for English, Russian and French smart quotes
---
tests/root/markup.txt | 20 ++++++++++++++++++++
tests/test_build_html.py | 7 +++++++
2 files changed, 27 insertions(+)
diff --git a/tests/root/markup.txt b/tests/root/markup.txt
index 714dabe8d..b514b3587 100644
--- a/tests/root/markup.txt
+++ b/tests/root/markup.txt
@@ -426,6 +426,26 @@ More domains:
.. default-role::
+Smart quotes
+------------
+
+* Smart "quotes" in English 'text'.
+* Smart --- long and -- short dashes.
+* Ellipsis...
+* No smartypants in literal blocks: ``foo--"bar"...``.
+
+.. only:: html
+
+ .. LaTeX does not like Cyrillic letters in this test, so it is HTML only.
+
+ .. rst-class:: language-ru
+
+ Этот "абзац" должен использовать 'русские' кавычки.
+
+ .. rst-class:: language-fr
+
+ Il dit : "C'est 'super' !"
+
.. rubric:: Footnotes
.. [#] Like footnotes.
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 9265caed4..e8dc2b831 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -297,6 +297,13 @@ def test_static_output(app):
# tests for ``any`` role
(".//a[@href='#with']/span", 'headings'),
(".//a[@href='objects.html#func_without_body']/code/span", 'objects'),
+ # tests for smartypants
+ (".//li", u'Smart “quotes” in English ‘text’.'),
+ (".//li", u'Smart — long and – short dashes.'),
+ (".//li", u'Ellipsis…'),
+ (".//li//code//span[@class='pre']", 'foo--"bar"...'),
+ (".//p", u'Этот «абзац» должен использовать „русские“ кавычки.'),
+ (".//p", u'Il dit : « C’est ‹ super › ! »'),
],
'objects.html': [
(".//dt[@id='mod.Cls.meth1']", ''),
From 4f4014c7c0d5543cb9a3fdebc6b4cd569a026541 Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev
Date: Thu, 16 Mar 2017 19:41:23 +0300
Subject: [PATCH 15/32] Remove sphinxquotedblleft and sphinxquotedblright, no
longer needed
---
sphinx/texinputs/sphinx.sty | 4 ----
1 file changed, 4 deletions(-)
diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty
index a4ceb4940..cb443536c 100644
--- a/sphinx/texinputs/sphinx.sty
+++ b/sphinx/texinputs/sphinx.sty
@@ -1388,10 +1388,6 @@
\protected\def\sphinxstyleabbreviation {\textsc}
\protected\def\sphinxstyleliteralintitle {\sphinxcode}
-% LaTeX writer uses macros to hide double quotes from \sphinxcode's \@noligs
-\protected\def\sphinxquotedblleft{``}
-\protected\def\sphinxquotedblright{''}
-
% Tell TeX about pathological hyphenation cases:
\hyphenation{Base-HTTP-Re-quest-Hand-ler}
\endinput
From 9236beb9ee41899897d8dbfa373ee21d7d4b252f Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev
Date: Mon, 17 Apr 2017 14:15:28 +0300
Subject: [PATCH 16/32] Deprecate the html_use_smartypants option
---
doc/config.rst | 6 ++++++
sphinx/builders/html.py | 2 +-
sphinx/environment/__init__.py | 10 ++++++++--
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/doc/config.rst b/doc/config.rst
index 5e641cbfb..39feaae78 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -768,6 +768,12 @@ that use Sphinx's HTMLWriter class.
will be used to convert quotes and dashes to typographically correct
entities. Default: ``True``.
+ .. deprecated:: 1.6
+ Use the `smart_quotes option`_ in the Docutils configuration file
+ (``docutils.conf``) instead.
+
+ .. _`smart_quotes option`: http://docutils.sourceforge.net/docs/user/config.html#smart-quotes
+
.. confval:: html_add_permalinks
Sphinx will add "permalinks" for each heading and description environment as
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index a0b3d8e87..16145beb3 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -1312,7 +1312,7 @@ def setup(app):
app.add_config_value('html_static_path', [], 'html')
app.add_config_value('html_extra_path', [], 'html')
app.add_config_value('html_last_updated_fmt', None, 'html', string_classes)
- app.add_config_value('html_use_smartypants', True, 'html')
+ app.add_config_value('html_use_smartypants', None, 'html')
app.add_config_value('html_sidebars', {}, 'html')
app.add_config_value('html_additional_pages', {}, 'html')
app.add_config_value('html_domain_indices', True, 'html', [list])
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index b0a1a2ce5..4c078a9a3 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -674,8 +674,14 @@ class BuildEnvironment(object):
self.settings['gettext_compact'] = self.config.gettext_compact
language = (self.config.language or 'en').replace('_', '-')
self.settings['language_code'] = language
- if language in smartchars.quotes:
- self.settings['smart_quotes'] = self.config.html_use_smartypants
+ if self.config.html_use_smartypants is not None:
+ warnings.warn("html_use_smartypants option is deprecated. Use the "
+ "smart_quotes option in docutils.conf instead.",
+ RemovedInSphinx17Warning)
+ if language in smartchars.quotes:
+ self.settings['smart_quotes'] = self.config.html_use_smartypants
+ elif language in smartchars.quotes: # We enable smartypants by default
+ self.settings['smart_quotes'] = True
docutilsconf = path.join(self.srcdir, 'docutils.conf')
# read docutils.conf from source dir, not from current dir
From f99f5b23ee630a33cf2c149a3928a533296e3129 Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev
Date: Mon, 17 Apr 2017 14:25:28 +0300
Subject: [PATCH 17/32] Backport fixes for French quotes from docutils
---
sphinx/util/smartypants.py | 6 ++++++
tests/test_build_html.py | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/sphinx/util/smartypants.py b/sphinx/util/smartypants.py
index 3932e9386..e42bfa82f 100644
--- a/sphinx/util/smartypants.py
+++ b/sphinx/util/smartypants.py
@@ -141,3 +141,9 @@ if docutils_version < (0, 13, 2):
# Monkey patch the old docutils versions to fix the issue mentioned
# at https://sourceforge.net/p/docutils/bugs/313/
smartquotes.educateQuotes = educateQuotes
+
+ # Fix the issue with French quotes mentioned at
+ # https://sourceforge.net/p/docutils/mailman/message/35760696/
+ quotes = smartquotes.smartchars.quotes
+ quotes['fr'] = (u'«\u00a0', u'\u00a0»', u'“', u'”')
+ quotes['fr-ch'] = u'«»‹›'
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index e8dc2b831..0758874a7 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -303,7 +303,7 @@ def test_static_output(app):
(".//li", u'Ellipsis…'),
(".//li//code//span[@class='pre']", 'foo--"bar"...'),
(".//p", u'Этот «абзац» должен использовать „русские“ кавычки.'),
- (".//p", u'Il dit : « C’est ‹ super › ! »'),
+ (".//p", u'Il dit : « C’est “super” ! »'),
],
'objects.html': [
(".//dt[@id='mod.Cls.meth1']", ''),
From a9cbb42e7fd42dfbfd88df5d262fae343418528e Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev
Date: Mon, 17 Apr 2017 14:44:52 +0300
Subject: [PATCH 18/32] Remove bulk_text_processors methods, they are no longer
needed
---
sphinx/writers/html.py | 6 ------
sphinx/writers/html5.py | 6 ------
2 files changed, 12 deletions(-)
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
index 572b2825e..6dd8bafe5 100644
--- a/sphinx/writers/html.py
+++ b/sphinx/writers/html.py
@@ -683,10 +683,6 @@ class HTMLTranslator(BaseTranslator):
BaseTranslator.visit_option_group(self, node)
self.context[-2] = self.context[-2].replace(' ', ' ')
- def bulk_text_processor(self, text):
- # type: (unicode) -> unicode
- return text
-
# overwritten
def visit_Text(self, node):
# type: (nodes.Node) -> None
@@ -708,8 +704,6 @@ class HTMLTranslator(BaseTranslator):
else:
if self.in_mailto and self.settings.cloak_email_addresses:
encoded = self.cloak_email(encoded)
- else:
- encoded = self.bulk_text_processor(encoded)
self.body.append(encoded)
def visit_note(self, node):
diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py
index 8e3843c09..51c4e8ecb 100644
--- a/sphinx/writers/html5.py
+++ b/sphinx/writers/html5.py
@@ -626,10 +626,6 @@ class HTML5Translator(BaseTranslator):
# type: (nodes.Node) -> None
self.body.append('')
- def bulk_text_processor(self, text):
- # type: (unicode) -> unicode
- return text
-
# overwritten
def visit_Text(self, node):
# type: (nodes.Node) -> None
@@ -651,8 +647,6 @@ class HTML5Translator(BaseTranslator):
else:
if self.in_mailto and self.settings.cloak_email_addresses:
encoded = self.cloak_email(encoded)
- else:
- encoded = self.bulk_text_processor(encoded)
self.body.append(encoded)
def visit_note(self, node):
From 4721767d08a3e4700e72e5df39f7064f0d6ceba0 Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev
Date: Mon, 24 Apr 2017 15:12:35 +0300
Subject: [PATCH 19/32] Also monkey-patch the educate_tokens from Docutils
To fix https://sourceforge.net/p/docutils/bugs/317/.
---
sphinx/util/smartypants.py | 131 +++++++++++++++++++++++++++++++++++++
1 file changed, 131 insertions(+)
diff --git a/sphinx/util/smartypants.py b/sphinx/util/smartypants.py
index e42bfa82f..2c4fe7d92 100644
--- a/sphinx/util/smartypants.py
+++ b/sphinx/util/smartypants.py
@@ -27,6 +27,9 @@ import re
from docutils.utils import smartquotes
from sphinx.util.docutils import __version_info__ as docutils_version
+if False: # For type annotation
+ from typing import Iterable, Iterator, Tuple # NOQA
+
def educateQuotes(text, language='en'):
# type: (unicode, unicode) -> unicode
@@ -137,11 +140,139 @@ def educateQuotes(text, language='en'):
return text
+def educate_tokens(text_tokens, attr='1', language='en'):
+ # type: (Iterable[Tuple[str, unicode]], unicode, unicode) -> Iterator
+ """Return iterator that "educates" the items of `text_tokens`.
+ """
+
+ # Parse attributes:
+ # 0 : do nothing
+ # 1 : set all
+ # 2 : set all, using old school en- and em- dash shortcuts
+ # 3 : set all, using inverted old school en and em- dash shortcuts
+ #
+ # q : quotes
+ # b : backtick quotes (``double'' only)
+ # B : backtick quotes (``double'' and `single')
+ # d : dashes
+ # D : old school dashes
+ # i : inverted old school dashes
+ # e : ellipses
+ # w : convert " entities to " for Dreamweaver users
+
+ convert_quot = False # translate " entities into normal quotes?
+ do_dashes = 0
+ do_backticks = 0
+ do_quotes = False
+ do_ellipses = False
+ do_stupefy = False
+
+ if attr == "0": # Do nothing.
+ pass
+ elif attr == "1": # Do everything, turn all options on.
+ do_quotes = True
+ do_backticks = 1
+ do_dashes = 1
+ do_ellipses = True
+ elif attr == "2":
+ # Do everything, turn all options on, use old school dash shorthand.
+ do_quotes = True
+ do_backticks = 1
+ do_dashes = 2
+ do_ellipses = True
+ elif attr == "3":
+ # Do everything, use inverted old school dash shorthand.
+ do_quotes = True
+ do_backticks = 1
+ do_dashes = 3
+ do_ellipses = True
+ elif attr == "-1": # Special "stupefy" mode.
+ do_stupefy = True
+ else:
+ if "q" in attr:
+ do_quotes = True
+ if "b" in attr:
+ do_backticks = 1
+ if "B" in attr:
+ do_backticks = 2
+ if "d" in attr:
+ do_dashes = 1
+ if "D" in attr:
+ do_dashes = 2
+ if "i" in attr:
+ do_dashes = 3
+ if "e" in attr:
+ do_ellipses = True
+ if "w" in attr:
+ convert_quot = True
+
+ prev_token_last_char = " "
+ # Last character of the previous text token. Used as
+ # context to curl leading quote characters correctly.
+
+ for (ttype, text) in text_tokens:
+
+ # skip HTML and/or XML tags as well as emtpy text tokens
+ # without updating the last character
+ if ttype == 'tag' or not text:
+ yield text
+ continue
+
+ # skip literal text (math, literal, raw, ...)
+ if ttype == 'literal':
+ prev_token_last_char = text[-1:]
+ yield text
+ continue
+
+ last_char = text[-1:] # Remember last char before processing.
+
+ text = smartquotes.processEscapes(text)
+
+ if convert_quot:
+ text = re.sub('"', '"', text)
+
+ if do_dashes == 1:
+ text = smartquotes.educateDashes(text)
+ elif do_dashes == 2:
+ text = smartquotes.educateDashesOldSchool(text)
+ elif do_dashes == 3:
+ text = smartquotes.educateDashesOldSchoolInverted(text)
+
+ if do_ellipses:
+ text = smartquotes.educateEllipses(text)
+
+ # Note: backticks need to be processed before quotes.
+ if do_backticks:
+ text = smartquotes.educateBackticks(text, language)
+
+ if do_backticks == 2:
+ text = smartquotes.educateSingleBackticks(text, language)
+
+ if do_quotes:
+ # Replace plain quotes to prevent converstion to
+ # 2-character sequence in French.
+ context = prev_token_last_char.replace('"', ';').replace("'", ';')
+ text = educateQuotes(context + text, language)[1:]
+
+ if do_stupefy:
+ text = smartquotes.stupefyEntities(text, language)
+
+ # Remember last char as context for the next token
+ prev_token_last_char = last_char
+
+ text = smartquotes.processEscapes(text, restore=True)
+
+ yield text
+
+
if docutils_version < (0, 13, 2):
# Monkey patch the old docutils versions to fix the issue mentioned
# at https://sourceforge.net/p/docutils/bugs/313/
smartquotes.educateQuotes = educateQuotes
+ # And the one mentioned at https://sourceforge.net/p/docutils/bugs/317/
+ smartquotes.educate_tokens = educate_tokens
+
# Fix the issue with French quotes mentioned at
# https://sourceforge.net/p/docutils/mailman/message/35760696/
quotes = smartquotes.smartchars.quotes
From 50609f200006a24eefa44a80a5ce703831c2beb8 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Tue, 25 Apr 2017 23:28:13 +0900
Subject: [PATCH 20/32] Update CHANGES for PR #3666
---
CHANGES | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGES b/CHANGES
index 0d72fa989..12d67a00a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,8 @@ Release 1.6 beta2 (in development)
Incompatible changes
--------------------
+* #3345: Replace the custom smartypants code with docutils' smart_quotes
+
Deprecated
----------
From f8b58e41cd1bb44d576f6b9da9f07b89f3d0a823 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Thu, 27 Apr 2017 00:17:07 +0900
Subject: [PATCH 21/32] Fix #3669: gettext builder fails with "ValueError:
substring not found"
---
CHANGES | 1 +
sphinx/builders/gettext.py | 20 ++++++++++++--------
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/CHANGES b/CHANGES
index 12d67a00a..d6de0d3ad 100644
--- a/CHANGES
+++ b/CHANGES
@@ -16,6 +16,7 @@ Bugs fixed
----------
* #3661: sphinx-build crashes on parallel build
+* #3669: gettext builder fails with "ValueError: substring not found"
Testing
--------
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index 280f2be99..4da19bd2c 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -194,14 +194,18 @@ ltz = LocalTimeZone()
def should_write(filepath, new_content):
if not path.exists(filepath):
return True
- with open(filepath, 'r', encoding='utf-8') as oldpot: # type: ignore
- old_content = oldpot.read()
- old_header_index = old_content.index('"POT-Creation-Date:')
- new_header_index = new_content.index('"POT-Creation-Date:')
- old_body_index = old_content.index('"PO-Revision-Date:')
- new_body_index = new_content.index('"PO-Revision-Date:')
- return ((old_content[:old_header_index] != new_content[:new_header_index]) or
- (new_content[new_body_index:] != old_content[old_body_index:]))
+ try:
+ with open(filepath, 'r', encoding='utf-8') as oldpot: # type: ignore
+ old_content = oldpot.read()
+ old_header_index = old_content.index('"POT-Creation-Date:')
+ new_header_index = new_content.index('"POT-Creation-Date:')
+ old_body_index = old_content.index('"PO-Revision-Date:')
+ new_body_index = new_content.index('"PO-Revision-Date:')
+ return ((old_content[:old_header_index] != new_content[:new_header_index]) or
+ (new_content[new_body_index:] != old_content[old_body_index:]))
+ except ValueError:
+ pass
+
return True
From 02ff0863c671c2468b9c841b5a362eb7435bb4b2 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Thu, 27 Apr 2017 00:33:40 +0900
Subject: [PATCH 22/32] Move deprecation warning
---
sphinx/builders/html.py | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index cea14965a..a356c5f23 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -96,19 +96,22 @@ class CSSContainer(list):
the entry with Stylesheet class.
"""
def append(self, obj):
- warnings.warn('builder.css_files is deprecated. '
- 'Please use app.add_stylesheet() instead.',
- RemovedInSphinx20Warning)
if isinstance(obj, Stylesheet):
super(CSSContainer, self).append(obj)
else:
super(CSSContainer, self).append(Stylesheet(obj, None, 'stylesheet'))
def extend(self, other):
+ warnings.warn('builder.css_files is deprecated. '
+ 'Please use app.add_stylesheet() instead.',
+ RemovedInSphinx20Warning)
for item in other:
self.append(item)
def __iadd__(self, other):
+ warnings.warn('builder.css_files is deprecated. '
+ 'Please use app.add_stylesheet() instead.',
+ RemovedInSphinx20Warning)
for item in other:
self.append(item)
From 45a61843ece6049012ca117aecf9aebf81e8152b Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Thu, 27 Apr 2017 21:24:12 +0900
Subject: [PATCH 23/32] Make ImportWarning silent
---
tests/run.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/run.py b/tests/run.py
index 71a41c7c1..673ad1339 100755
--- a/tests/run.py
+++ b/tests/run.py
@@ -24,6 +24,7 @@ sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
# filter warnings of test dependencies
warnings.filterwarnings('ignore', category=DeprecationWarning, module='site') # virtualenv
warnings.filterwarnings('ignore', category=ImportWarning, module='backports')
+warnings.filterwarnings('ignore', category=ImportWarning, module='pkgutil')
warnings.filterwarnings('ignore', category=ImportWarning, module='pytest_cov')
warnings.filterwarnings('ignore', category=PendingDeprecationWarning, module=r'_pytest\..*')
From 8462d4bcdab78f1bd3f064e14c31f67519e023e7 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Thu, 27 Apr 2017 21:24:12 +0900
Subject: [PATCH 24/32] doc: Update
---
doc/theming.rst | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/doc/theming.rst b/doc/theming.rst
index 2a7063925..711d0ae72 100644
--- a/doc/theming.rst
+++ b/doc/theming.rst
@@ -47,7 +47,9 @@ file :file:`blue.zip`, you can put it right in the directory containing
html_theme_path = ["."]
The third form is a python package. If a theme you want to use is distributed
-as a python package, you can use it after installing::
+as a python package, you can use it after installing
+
+.. code-block:: bash
# installing theme package
$ pip install sphinxjp.themes.dotted
From 5c5272c4aba57b56290039d5b765e5ff07dea6b3 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Thu, 27 Apr 2017 21:44:46 +0900
Subject: [PATCH 25/32] Fix #3657: EPUB builder crashes if document startswith
genindex exists
---
CHANGES | 1 +
sphinx/builders/epub.py | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/CHANGES b/CHANGES
index b38d91c4d..344e65fff 100644
--- a/CHANGES
+++ b/CHANGES
@@ -16,6 +16,7 @@ Bugs fixed
* #3614: Sphinx crashes with requests-2.5.0
* #3618: autodoc crashes with tupled arguments
* #3664: No space after the bullet in items of a latex list produced by Sphinx
+* #3657: EPUB builder crashes if document startswith genindex exists
Testing
--------
diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py
index 152401447..ea90642bc 100644
--- a/sphinx/builders/epub.py
+++ b/sphinx/builders/epub.py
@@ -500,7 +500,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
This method is overwritten for genindex pages in order to fix href link
attributes.
"""
- if pagename.startswith('genindex'):
+ if pagename.startswith('genindex') and 'genindexentries' in addctx:
if not self.use_index:
return
self.fix_genindex(addctx['genindexentries'])
From bd66ffc1fafd0e83f07e7143f99bc4023bc72508 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Fri, 28 Apr 2017 01:19:01 +0900
Subject: [PATCH 26/32] Fix the unreleased version number is shown (refs:
#3678, #3027)
---
doc/_templates/indexsidebar.html | 2 +-
doc/conf.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/_templates/indexsidebar.html b/doc/_templates/indexsidebar.html
index bfa0139cb..6359921a5 100644
--- a/doc/_templates/indexsidebar.html
+++ b/doc/_templates/indexsidebar.html
@@ -3,7 +3,7 @@
{%trans%}project{%endtrans%}
Download
-{% if version.endswith('a0') %}
+{% if version.endswith('+') %}
{%trans%}This documentation is for version {{ version }}, which is
not released yet.{%endtrans%}
{%trans%}You can use it from the
diff --git a/doc/conf.py b/doc/conf.py
index 95d14ec46..6817af12a 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -16,7 +16,7 @@ exclude_patterns = ['_build']
project = 'Sphinx'
copyright = '2007-2017, Georg Brandl and the Sphinx team'
-version = sphinx.__released__
+version = sphinx.__display_version__
release = version
show_authors = True
From ac5e76f5989eeb74b05d9332b6a3922952a161c7 Mon Sep 17 00:00:00 2001
From: shimizukawa
Date: Sat, 29 Apr 2017 00:54:58 +0900
Subject: [PATCH 27/32] extract messages
---
sphinx/locale/sphinx.pot | 920 ++++++++++++++++++++++++++++-----------
utils/release-checklist | 7 +-
2 files changed, 666 insertions(+), 261 deletions(-)
diff --git a/sphinx/locale/sphinx.pot b/sphinx/locale/sphinx.pot
index f63434cc2..13e387dcd 100644
--- a/sphinx/locale/sphinx.pot
+++ b/sphinx/locale/sphinx.pot
@@ -1,14 +1,14 @@
# Translations template for Sphinx.
-# Copyright (C) 2016 ORGANIZATION
+# Copyright (C) 2017 ORGANIZATION
# This file is distributed under the same license as the Sphinx project.
-# FIRST AUTHOR , 2016.
+# FIRST AUTHOR , 2017.
#
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: Sphinx 1.5b1\n"
+"Project-Id-Version: Sphinx 1.6\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2016-11-06 22:40+0900\n"
+"POT-Creation-Date: 2017-04-28 15:54+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -17,600 +17,987 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"
-#: sphinx/config.py:109
+#: sphinx/application.py:181
+#, python-format
+msgid ""
+"This project needs at least Sphinx v%s and therefore cannot be built with"
+" this version."
+msgstr ""
+
+#: sphinx/application.py:208
+msgid ""
+"'setup' that is specified in the conf.py has not been callable. Please "
+"provide a callable `setup` function in order to behave as a sphinx "
+"extension conf.py itself."
+msgstr ""
+
+#: sphinx/application.py:222
+#, python-format
+msgid "primary_domain %r not found, ignored."
+msgstr ""
+
+#: sphinx/application.py:259 sphinx/application.py:287
+msgid "done"
+msgstr ""
+
+#: sphinx/application.py:280
+msgid "loading pickled environment... "
+msgstr ""
+
+#: sphinx/application.py:290
+msgid "not yet created"
+msgstr ""
+
+#: sphinx/application.py:292
+#, python-format
+msgid "failed: %s"
+msgstr ""
+
+#: sphinx/application.py:302
+msgid "No builder selected, using default: html"
+msgstr ""
+
+#: sphinx/application.py:341
+msgid "succeeded"
+msgstr ""
+
+#: sphinx/application.py:341
+msgid "finished with problems"
+msgstr ""
+
+#: sphinx/application.py:343
+#, python-format
+msgid "build %s, %s warning%s."
+msgstr ""
+
+#: sphinx/application.py:347
+#, python-format
+msgid "build %s."
+msgstr ""
+
+#: sphinx/application.py:506
+#, python-format
+msgid "Config value %r already present"
+msgstr ""
+
+#: sphinx/application.py:518
+#, python-format
+msgid "A Translator for the %s builder is changed."
+msgstr ""
+
+#: sphinx/application.py:526
+#, python-format
+msgid ""
+"while setting up extension %s: node class %r is already registered, its "
+"visitors will be overridden"
+msgstr ""
+
+#: sphinx/application.py:535
+#, python-format
+msgid "Value for key %r must be a (visit, depart) function tuple"
+msgstr ""
+
+#: sphinx/application.py:582
+#, python-format
+msgid ""
+"while setting up extension %s: directive %r is already registered, it "
+"will be overridden"
+msgstr ""
+
+#: sphinx/application.py:593 sphinx/application.py:605
+#, python-format
+msgid ""
+"while setting up extension %s: role %r is already registered, it will be "
+"overridden"
+msgstr ""
+
+#: sphinx/config.py:127
#, python-format
msgid "Section %s"
msgstr ""
-#: sphinx/config.py:110
+#: sphinx/config.py:128
#, python-format
msgid "Fig. %s"
msgstr ""
-#: sphinx/config.py:111
+#: sphinx/config.py:129
#, python-format
msgid "Table %s"
msgstr ""
-#: sphinx/config.py:112
+#: sphinx/config.py:130
#, python-format
msgid "Listing %s"
msgstr ""
-#: sphinx/roles.py:187
+#: sphinx/config.py:236
+#, python-format
+msgid ""
+"cannot override dictionary config setting %r, ignoring (use %r to set "
+"individual elements)"
+msgstr ""
+
+#: sphinx/config.py:245
+#, python-format
+msgid "invalid number %r for config value %r, ignoring"
+msgstr ""
+
+#: sphinx/config.py:250
+#, python-format
+msgid "cannot override config setting %r with unsupported type, ignoring"
+msgstr ""
+
+#: sphinx/config.py:280
+#, python-format
+msgid "unknown config value %r in override, ignoring"
+msgstr ""
+
+#: sphinx/config.py:299
+#, python-format
+msgid "No such config value: %s"
+msgstr ""
+
+#: sphinx/events.py:56
+#, python-format
+msgid "Event %r already present"
+msgstr ""
+
+#: sphinx/events.py:62
+#, python-format
+msgid "Unknown event name: %s"
+msgstr ""
+
+#: sphinx/extension.py:53
+#, python-format
+msgid ""
+"needs_extensions config value specifies a version requirement for "
+"extension %s, but it is not loaded"
+msgstr ""
+
+#: sphinx/extension.py:59
+#, python-format
+msgid ""
+"This project needs the extension %s at least in version %s and therefore "
+"cannot be built with the loaded version (%s)."
+msgstr ""
+
+#: sphinx/registry.py:56
+#, python-format
+msgid "Builder class %s has no \"name\" attribute"
+msgstr ""
+
+#: sphinx/registry.py:58
+#, python-format
+msgid "Builder %r already exists (in module %s)"
+msgstr ""
+
+#: sphinx/registry.py:72
+#, python-format
+msgid "Builder name %s not registered or available through entry point"
+msgstr ""
+
+#: sphinx/registry.py:80
+#, python-format
+msgid "Builder name %s not registered"
+msgstr ""
+
+#: sphinx/registry.py:87
+#, python-format
+msgid "domain %s already registered"
+msgstr ""
+
+#: sphinx/registry.py:102 sphinx/registry.py:112 sphinx/registry.py:119
+#: sphinx/registry.py:125
+#, python-format
+msgid "domain %s not yet registered"
+msgstr ""
+
+#: sphinx/registry.py:104
+#, python-format
+msgid "new domain not a subclass of registered %s domain"
+msgstr ""
+
+#: sphinx/registry.py:160
+#, python-format
+msgid "source_parser for %r is already registered"
+msgstr ""
+
+#: sphinx/registry.py:187
+#, python-format
+msgid ""
+"the extension %r was already merged with Sphinx since version %s; this "
+"extension is ignored."
+msgstr ""
+
+#: sphinx/registry.py:198
+msgid "Original exception:\n"
+msgstr ""
+
+#: sphinx/registry.py:199
+#, python-format
+msgid "Could not import extension %s"
+msgstr ""
+
+#: sphinx/registry.py:202
+#, python-format
+msgid ""
+"extension %r has no setup() function; is it really a Sphinx extension "
+"module?"
+msgstr ""
+
+#: sphinx/registry.py:211
+#, python-format
+msgid ""
+"The %s extension used by this project needs at least Sphinx v%s; it "
+"therefore cannot be built with this version."
+msgstr ""
+
+#: sphinx/registry.py:221
+#, python-format
+msgid ""
+"extension %r returned an unsupported object from its setup() function; it"
+" should return None or a metadata dictionary"
+msgstr ""
+
+#: sphinx/roles.py:200
#, python-format
msgid "Python Enhancement Proposals; PEP %s"
msgstr ""
-#: sphinx/builders/changes.py:75
+#: sphinx/theming.py:83
+#, python-format
+msgid "theme %r doesn't have \"theme\" setting"
+msgstr ""
+
+#: sphinx/theming.py:85
+#, python-format
+msgid "theme %r doesn't have \"inherit\" setting"
+msgstr ""
+
+#: sphinx/theming.py:91
+#, python-format
+msgid "no theme named %r found, inherited by %r"
+msgstr ""
+
+#: sphinx/theming.py:116
+#, python-format
+msgid "setting %s.%s occurs in none of the searched theme configs"
+msgstr ""
+
+#: sphinx/theming.py:237
+#, python-format
+msgid "Theme extension %r does not response correctly."
+msgstr ""
+
+#: sphinx/theming.py:264
+#, python-format
+msgid "file %r on theme path is not a valid zipfile or contains no theme"
+msgstr ""
+
+#: sphinx/theming.py:280
+msgid ""
+"sphinx_rtd_theme is no longer a hard dependency since version 1.4.0. "
+"Please install it manually.(pip install sphinx_rtd_theme)"
+msgstr ""
+
+#: sphinx/theming.py:284
+#, python-format
+msgid "no theme named %r found (missing theme.conf?)"
+msgstr ""
+
+#: sphinx/builders/changes.py:86
msgid "Builtins"
msgstr ""
-#: sphinx/builders/changes.py:77
+#: sphinx/builders/changes.py:88
msgid "Module level"
msgstr ""
-#: sphinx/builders/html.py:294 sphinx/transforms/__init__.py:46
-#: sphinx/writers/latex.py:393 sphinx/writers/manpage.py:100
-#: sphinx/writers/texinfo.py:221
+#: sphinx/builders/html.py:357 sphinx/transforms/__init__.py:119
+#: sphinx/writers/latex.py:561 sphinx/writers/manpage.py:110
+#: sphinx/writers/texinfo.py:241
#, python-format
msgid "%b %d, %Y"
msgstr ""
-#: sphinx/builders/html.py:315 sphinx/themes/basic/defindex.html:30
+#: sphinx/builders/html.py:377 sphinx/themes/basic/defindex.html:30
msgid "General Index"
msgstr ""
-#: sphinx/builders/html.py:315
+#: sphinx/builders/html.py:377
msgid "index"
msgstr ""
-#: sphinx/builders/html.py:377
+#: sphinx/builders/html.py:441
msgid "next"
msgstr ""
-#: sphinx/builders/html.py:386
+#: sphinx/builders/html.py:450
msgid "previous"
msgstr ""
-#: sphinx/builders/html.py:1222
+#: sphinx/builders/html.py:1313
#, python-format
msgid "%s %s documentation"
msgstr ""
-#: sphinx/builders/latex.py:177 sphinx/builders/texinfo.py:199
+#: sphinx/builders/latex.py:199 sphinx/builders/texinfo.py:217
msgid " (in "
msgstr ""
-#: sphinx/directives/code.py:140 sphinx/directives/code.py:370
+#: sphinx/directives/code.py:66
+msgid "Over dedent has detected"
+msgstr ""
+
+#: sphinx/directives/code.py:86
#, python-format
msgid "Invalid caption: %s"
msgstr ""
-#: sphinx/directives/other.py:149
+#: sphinx/directives/code.py:201
+#, python-format
+msgid "Cannot use both \"%s\" and \"%s\" options"
+msgstr ""
+
+#: sphinx/directives/code.py:218
+#, python-format
+msgid "Include file %r not found or reading it failed"
+msgstr ""
+
+#: sphinx/directives/code.py:220
+#, python-format
+msgid ""
+"Encoding %r used for reading included file %r seems to be wrong, try "
+"giving an :encoding: option"
+msgstr ""
+
+#: sphinx/directives/code.py:257
+#, python-format
+msgid "Object named %r not found in include file %r"
+msgstr ""
+
+#: sphinx/directives/code.py:283
+msgid "Cannot use \"lineno-match\" with a disjoint set of \"lines\""
+msgstr ""
+
+#: sphinx/directives/code.py:288
+#, python-format
+msgid "Line spec %r: no lines pulled from include file %r"
+msgstr ""
+
+#: sphinx/directives/other.py:158
msgid "Section author: "
msgstr ""
-#: sphinx/directives/other.py:151
+#: sphinx/directives/other.py:160
msgid "Module author: "
msgstr ""
-#: sphinx/directives/other.py:153
+#: sphinx/directives/other.py:162
msgid "Code author: "
msgstr ""
-#: sphinx/directives/other.py:155
+#: sphinx/directives/other.py:164
msgid "Author: "
msgstr ""
-#: sphinx/domains/__init__.py:277
+#: sphinx/domains/__init__.py:310
#, python-format
msgid "%s %s"
msgstr ""
-#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:4051
-#: sphinx/domains/python.py:149
+#: sphinx/domains/c.py:65 sphinx/domains/cpp.py:4436
+#: sphinx/domains/python.py:177
msgid "Parameters"
msgstr ""
-#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:4060
-#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:161
+#: sphinx/domains/c.py:68 sphinx/domains/cpp.py:4445
+#: sphinx/domains/javascript.py:210 sphinx/domains/python.py:189
msgid "Returns"
msgstr ""
-#: sphinx/domains/c.py:63 sphinx/domains/javascript.py:130
-#: sphinx/domains/python.py:163
+#: sphinx/domains/c.py:70 sphinx/domains/javascript.py:212
+#: sphinx/domains/python.py:191
msgid "Return type"
msgstr ""
-#: sphinx/domains/c.py:177
+#: sphinx/domains/c.py:188
#, python-format
msgid "%s (C function)"
msgstr ""
-#: sphinx/domains/c.py:179
+#: sphinx/domains/c.py:190
#, python-format
msgid "%s (C member)"
msgstr ""
-#: sphinx/domains/c.py:181
+#: sphinx/domains/c.py:192
#, python-format
msgid "%s (C macro)"
msgstr ""
-#: sphinx/domains/c.py:183
+#: sphinx/domains/c.py:194
#, python-format
msgid "%s (C type)"
msgstr ""
-#: sphinx/domains/c.py:185
+#: sphinx/domains/c.py:196
#, python-format
msgid "%s (C variable)"
msgstr ""
-#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:4418
-#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:614
+#: sphinx/domains/c.py:257 sphinx/domains/cpp.py:4820
+#: sphinx/domains/javascript.py:299 sphinx/domains/python.py:696
msgid "function"
msgstr ""
-#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:4419
+#: sphinx/domains/c.py:258 sphinx/domains/cpp.py:4821
msgid "member"
msgstr ""
-#: sphinx/domains/c.py:244
+#: sphinx/domains/c.py:259
msgid "macro"
msgstr ""
-#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:4420
+#: sphinx/domains/c.py:260 sphinx/domains/cpp.py:4822
msgid "type"
msgstr ""
-#: sphinx/domains/c.py:246
+#: sphinx/domains/c.py:261
msgid "variable"
msgstr ""
-#: sphinx/domains/cpp.py:4054
+#: sphinx/domains/cpp.py:4439
msgid "Template Parameters"
msgstr ""
-#: sphinx/domains/cpp.py:4057 sphinx/domains/javascript.py:125
+#: sphinx/domains/cpp.py:4442 sphinx/domains/javascript.py:207
msgid "Throws"
msgstr ""
-#: sphinx/domains/cpp.py:4205
+#: sphinx/domains/cpp.py:4607
#, python-format
msgid "%s (C++ type)"
msgstr ""
-#: sphinx/domains/cpp.py:4216
+#: sphinx/domains/cpp.py:4617
#, python-format
msgid "%s (C++ concept)"
msgstr ""
-#: sphinx/domains/cpp.py:4227
+#: sphinx/domains/cpp.py:4627
#, python-format
msgid "%s (C++ member)"
msgstr ""
-#: sphinx/domains/cpp.py:4238
+#: sphinx/domains/cpp.py:4637
#, python-format
msgid "%s (C++ function)"
msgstr ""
-#: sphinx/domains/cpp.py:4249
+#: sphinx/domains/cpp.py:4647
#, python-format
msgid "%s (C++ class)"
msgstr ""
-#: sphinx/domains/cpp.py:4260
+#: sphinx/domains/cpp.py:4657
#, python-format
msgid "%s (C++ enum)"
msgstr ""
-#: sphinx/domains/cpp.py:4281
+#: sphinx/domains/cpp.py:4677
#, python-format
msgid "%s (C++ enumerator)"
msgstr ""
-#: sphinx/domains/cpp.py:4417 sphinx/domains/javascript.py:165
-#: sphinx/domains/python.py:616
+#: sphinx/domains/cpp.py:4819 sphinx/domains/javascript.py:301
+#: sphinx/domains/python.py:698
msgid "class"
msgstr ""
-#: sphinx/domains/cpp.py:4421
+#: sphinx/domains/cpp.py:4823
msgid "concept"
msgstr ""
-#: sphinx/domains/cpp.py:4422
+#: sphinx/domains/cpp.py:4824
msgid "enum"
msgstr ""
-#: sphinx/domains/cpp.py:4423
+#: sphinx/domains/cpp.py:4825
msgid "enumerator"
msgstr ""
-#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:307
+#: sphinx/domains/javascript.py:131 sphinx/domains/python.py:386
#, python-format
msgid "%s() (built-in function)"
msgstr ""
-#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:371
+#: sphinx/domains/javascript.py:132 sphinx/domains/python.py:451
#, python-format
msgid "%s() (%s method)"
msgstr ""
-#: sphinx/domains/javascript.py:109
+#: sphinx/domains/javascript.py:134
#, python-format
msgid "%s() (class)"
msgstr ""
-#: sphinx/domains/javascript.py:111
+#: sphinx/domains/javascript.py:136
#, python-format
msgid "%s (global variable or constant)"
msgstr ""
-#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:409
+#: sphinx/domains/javascript.py:138 sphinx/domains/python.py:489
#, python-format
msgid "%s (%s attribute)"
msgstr ""
-#: sphinx/domains/javascript.py:122
+#: sphinx/domains/javascript.py:204
msgid "Arguments"
msgstr ""
-#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:615
-msgid "data"
-msgstr ""
-
-#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:621
-msgid "attribute"
-msgstr ""
-
-#: sphinx/domains/python.py:154
-msgid "Variables"
-msgstr ""
-
-#: sphinx/domains/python.py:158
-msgid "Raises"
-msgstr ""
-
-#: sphinx/domains/python.py:308 sphinx/domains/python.py:365
-#: sphinx/domains/python.py:377 sphinx/domains/python.py:390
-#, python-format
-msgid "%s() (in module %s)"
-msgstr ""
-
-#: sphinx/domains/python.py:311
-#, python-format
-msgid "%s (built-in variable)"
-msgstr ""
-
-#: sphinx/domains/python.py:312 sphinx/domains/python.py:403
-#, python-format
-msgid "%s (in module %s)"
-msgstr ""
-
-#: sphinx/domains/python.py:328
-#, python-format
-msgid "%s (built-in class)"
-msgstr ""
-
-#: sphinx/domains/python.py:329
-#, python-format
-msgid "%s (class in %s)"
-msgstr ""
-
-#: sphinx/domains/python.py:369
-#, python-format
-msgid "%s() (%s.%s method)"
-msgstr ""
-
-#: sphinx/domains/python.py:381
-#, python-format
-msgid "%s() (%s.%s static method)"
-msgstr ""
-
-#: sphinx/domains/python.py:384
-#, python-format
-msgid "%s() (%s static method)"
-msgstr ""
-
-#: sphinx/domains/python.py:394
-#, python-format
-msgid "%s() (%s.%s class method)"
-msgstr ""
-
-#: sphinx/domains/python.py:397
-#, python-format
-msgid "%s() (%s class method)"
-msgstr ""
-
-#: sphinx/domains/python.py:407
-#, python-format
-msgid "%s (%s.%s attribute)"
-msgstr ""
-
-#: sphinx/domains/python.py:488
+#: sphinx/domains/javascript.py:266 sphinx/domains/python.py:566
#, python-format
msgid "%s (module)"
msgstr ""
-#: sphinx/domains/python.py:545
-msgid "Python Module Index"
-msgstr ""
-
-#: sphinx/domains/python.py:546
-msgid "modules"
-msgstr ""
-
-#: sphinx/domains/python.py:592
-msgid "Deprecated"
-msgstr ""
-
-#: sphinx/domains/python.py:617 sphinx/locale/__init__.py:183
-msgid "exception"
-msgstr ""
-
-#: sphinx/domains/python.py:618
+#: sphinx/domains/javascript.py:300 sphinx/domains/python.py:700
msgid "method"
msgstr ""
-#: sphinx/domains/python.py:619
-msgid "class method"
+#: sphinx/domains/javascript.py:302 sphinx/domains/python.py:697
+msgid "data"
msgstr ""
-#: sphinx/domains/python.py:620
-msgid "static method"
+#: sphinx/domains/javascript.py:303 sphinx/domains/python.py:703
+msgid "attribute"
msgstr ""
-#: sphinx/domains/python.py:622 sphinx/locale/__init__.py:179
+#: sphinx/domains/javascript.py:304 sphinx/domains/python.py:704
+#: sphinx/locale/__init__.py:218
msgid "module"
msgstr ""
-#: sphinx/domains/python.py:787
+#: sphinx/domains/python.py:182
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:186
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:387 sphinx/domains/python.py:445
+#: sphinx/domains/python.py:457 sphinx/domains/python.py:470
+#, python-format
+msgid "%s() (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:390
+#, python-format
+msgid "%s (built-in variable)"
+msgstr ""
+
+#: sphinx/domains/python.py:391 sphinx/domains/python.py:483
+#, python-format
+msgid "%s (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:411
+#, python-format
+msgid "%s (built-in class)"
+msgstr ""
+
+#: sphinx/domains/python.py:412
+#, python-format
+msgid "%s (class in %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:449
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr ""
+
+#: sphinx/domains/python.py:461
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:464
+#, python-format
+msgid "%s() (%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:474
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:477
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:487
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr ""
+
+#: sphinx/domains/python.py:625
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:626
+msgid "modules"
+msgstr ""
+
+#: sphinx/domains/python.py:674
+msgid "Deprecated"
+msgstr ""
+
+#: sphinx/domains/python.py:699 sphinx/locale/__init__.py:222
+msgid "exception"
+msgstr ""
+
+#: sphinx/domains/python.py:701
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:702
+msgid "static method"
+msgstr ""
+
+#: sphinx/domains/python.py:874
msgid " (deprecated)"
msgstr ""
-#: sphinx/domains/rst.py:55
+#: sphinx/domains/rst.py:65
#, python-format
msgid "%s (directive)"
msgstr ""
-#: sphinx/domains/rst.py:57
+#: sphinx/domains/rst.py:67
#, python-format
msgid "%s (role)"
msgstr ""
-#: sphinx/domains/rst.py:106
+#: sphinx/domains/rst.py:119
msgid "directive"
msgstr ""
-#: sphinx/domains/rst.py:107
+#: sphinx/domains/rst.py:120
msgid "role"
msgstr ""
-#: sphinx/domains/std.py:72 sphinx/domains/std.py:88
+#: sphinx/domains/std.py:84 sphinx/domains/std.py:101
#, python-format
msgid "environment variable; %s"
msgstr ""
-#: sphinx/domains/std.py:186
+#: sphinx/domains/std.py:200
#, python-format
msgid "%scommand line option; %s"
msgstr ""
-#: sphinx/domains/std.py:434
+#: sphinx/domains/std.py:455
msgid "glossary term"
msgstr ""
-#: sphinx/domains/std.py:435
+#: sphinx/domains/std.py:456
msgid "grammar token"
msgstr ""
-#: sphinx/domains/std.py:436
+#: sphinx/domains/std.py:457
msgid "reference label"
msgstr ""
-#: sphinx/domains/std.py:438
+#: sphinx/domains/std.py:459
msgid "environment variable"
msgstr ""
-#: sphinx/domains/std.py:439
+#: sphinx/domains/std.py:460
msgid "program option"
msgstr ""
-#: sphinx/domains/std.py:473 sphinx/themes/basic/genindex-single.html:30
+#: sphinx/domains/std.py:461
+msgid "document"
+msgstr ""
+
+#: sphinx/domains/std.py:497 sphinx/themes/basic/genindex-single.html:30
#: sphinx/themes/basic/genindex-single.html:55
#: sphinx/themes/basic/genindex-split.html:11
#: sphinx/themes/basic/genindex-split.html:14
#: sphinx/themes/basic/genindex.html:30 sphinx/themes/basic/genindex.html:33
-#: sphinx/themes/basic/genindex.html:66 sphinx/themes/basic/layout.html:135
-#: sphinx/writers/latex.py:381 sphinx/writers/texinfo.py:480
+#: sphinx/themes/basic/genindex.html:66 sphinx/themes/basic/layout.html:149
+#: sphinx/writers/latex.py:545 sphinx/writers/texinfo.py:517
msgid "Index"
msgstr ""
-#: sphinx/domains/std.py:474
+#: sphinx/domains/std.py:498
msgid "Module Index"
msgstr ""
-#: sphinx/domains/std.py:475 sphinx/themes/basic/defindex.html:25
+#: sphinx/domains/std.py:499 sphinx/themes/basic/defindex.html:25
msgid "Search Page"
msgstr ""
-#: sphinx/environment/managers/indexentries.py:104
+#: sphinx/environment/__init__.py:568
+#, python-format
+msgid ""
+"the %s extension does not declare if it is safe for parallel reading, "
+"assuming it isn't - please ask the extension author to check and make it "
+"explicit"
+msgstr ""
+
+#: sphinx/environment/adapters/indexentries.py:85
#, python-format
msgid "see %s"
msgstr ""
-#: sphinx/environment/managers/indexentries.py:108
+#: sphinx/environment/adapters/indexentries.py:89
#, python-format
msgid "see also %s"
msgstr ""
-#: sphinx/environment/managers/indexentries.py:168
+#: sphinx/environment/adapters/indexentries.py:159
msgid "Symbols"
msgstr ""
-#: sphinx/ext/autodoc.py:1297
+#: sphinx/ext/autodoc.py:1451
#, python-format
msgid "Bases: %s"
msgstr ""
-#: sphinx/ext/autodoc.py:1350
+#: sphinx/ext/autodoc.py:1506
#, python-format
msgid "alias of :class:`%s`"
msgstr ""
-#: sphinx/ext/graphviz.py:331 sphinx/ext/graphviz.py:340
+#: sphinx/ext/doctest.py:134
+#, python-format
+msgid "missing '+' or '-' in '%s' option."
+msgstr ""
+
+#: sphinx/ext/doctest.py:139
+#, python-format
+msgid "'%s' is not a valid option."
+msgstr ""
+
+#: sphinx/ext/doctest.py:155
+#, python-format
+msgid "'%s' is not a valid pyversion option"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:96
+msgid "Graphviz directive cannot have both content and a filename argument"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:107
+#, python-format
+msgid "External Graphviz file %r not found or reading it failed"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:113
+msgid "Ignoring \"graphviz\" directive without content."
+msgstr ""
+
+#: sphinx/ext/graphviz.py:204
+#, python-format
+msgid ""
+"dot command %r cannot be run (needed for graphviz output), check the "
+"graphviz_dot setting"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:222
+#, python-format
+msgid ""
+"dot exited with error:\n"
+"[stderr]\n"
+"%s\n"
+"[stdout]\n"
+"%s"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:225
+#, python-format
+msgid ""
+"dot did not produce an output file:\n"
+"[stderr]\n"
+"%s\n"
+"[stdout]\n"
+"%s"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:236
+#, python-format
+msgid "graphviz_output_format must be one of 'png', 'svg', but is %r"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:336 sphinx/ext/graphviz.py:345
#, python-format
msgid "[graph: %s]"
msgstr ""
-#: sphinx/ext/graphviz.py:333 sphinx/ext/graphviz.py:342
+#: sphinx/ext/graphviz.py:338 sphinx/ext/graphviz.py:347
msgid "[graph]"
msgstr ""
-#: sphinx/ext/imgmath.py:258 sphinx/ext/jsmath.py:39 sphinx/ext/mathjax.py:40
+#: sphinx/ext/imgconverter.py:46 sphinx/ext/imgconverter.py:63
+#, python-format
+msgid "convert command %r cannot be run.check the image_converter setting"
+msgstr ""
+
+#: sphinx/ext/imgconverter.py:76
+#, python-format
+msgid ""
+"convert exited with error:\n"
+"[stderr]\n"
+"%s\n"
+"[stdout]\n"
+"%s"
+msgstr ""
+
+#: sphinx/ext/imgmath.py:274 sphinx/ext/jsmath.py:39 sphinx/ext/mathjax.py:40
msgid "Permalink to this equation"
msgstr ""
-#: sphinx/ext/intersphinx.py:337
+#: sphinx/ext/intersphinx.py:319
#, python-format
msgid "(in %s v%s)"
msgstr ""
-#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:103
+#: sphinx/ext/linkcode.py:75 sphinx/ext/viewcode.py:112
msgid "[source]"
msgstr ""
-#: sphinx/ext/mathbase.py:92
+#: sphinx/ext/mathbase.py:106
#, python-format
msgid "duplicate label of equation %s, other instance in %s"
msgstr ""
-#: sphinx/ext/todo.py:56
+#: sphinx/ext/todo.py:66
msgid "Todo"
msgstr ""
-#: sphinx/ext/todo.py:134
+#: sphinx/ext/todo.py:148
msgid "<>"
msgstr ""
-#: sphinx/ext/todo.py:137
+#: sphinx/ext/todo.py:151
#, python-format
msgid "(The <> is located in %s, line %d.)"
msgstr ""
-#: sphinx/ext/todo.py:146
+#: sphinx/ext/todo.py:160
msgid "original entry"
msgstr ""
-#: sphinx/ext/viewcode.py:166
+#: sphinx/ext/viewcode.py:179
msgid "[docs]"
msgstr ""
-#: sphinx/ext/viewcode.py:180
+#: sphinx/ext/viewcode.py:193
msgid "Module code"
msgstr ""
-#: sphinx/ext/viewcode.py:186
+#: sphinx/ext/viewcode.py:199
#, python-format
msgid "Source code for %s
"
msgstr ""
-#: sphinx/ext/viewcode.py:212
+#: sphinx/ext/viewcode.py:225
msgid "Overview: module code"
msgstr ""
-#: sphinx/ext/viewcode.py:213
+#: sphinx/ext/viewcode.py:226
msgid "All modules for which code is available
"
msgstr ""
-#: sphinx/ext/napoleon/__init__.py:313
+#: sphinx/ext/napoleon/__init__.py:320
msgid "Keyword Arguments"
msgstr ""
-#: sphinx/locale/__init__.py:159
+#: sphinx/locale/__init__.py:198
msgid "Attention"
msgstr ""
-#: sphinx/locale/__init__.py:160
+#: sphinx/locale/__init__.py:199
msgid "Caution"
msgstr ""
-#: sphinx/locale/__init__.py:161
+#: sphinx/locale/__init__.py:200
msgid "Danger"
msgstr ""
-#: sphinx/locale/__init__.py:162
+#: sphinx/locale/__init__.py:201
msgid "Error"
msgstr ""
-#: sphinx/locale/__init__.py:163
+#: sphinx/locale/__init__.py:202
msgid "Hint"
msgstr ""
-#: sphinx/locale/__init__.py:164
+#: sphinx/locale/__init__.py:203
msgid "Important"
msgstr ""
-#: sphinx/locale/__init__.py:165
+#: sphinx/locale/__init__.py:204
msgid "Note"
msgstr ""
-#: sphinx/locale/__init__.py:166
+#: sphinx/locale/__init__.py:205
msgid "See also"
msgstr ""
-#: sphinx/locale/__init__.py:167
+#: sphinx/locale/__init__.py:206
msgid "Tip"
msgstr ""
-#: sphinx/locale/__init__.py:168
+#: sphinx/locale/__init__.py:207
msgid "Warning"
msgstr ""
-#: sphinx/locale/__init__.py:172
+#: sphinx/locale/__init__.py:211
#, python-format
msgid "New in version %s"
msgstr ""
-#: sphinx/locale/__init__.py:173
+#: sphinx/locale/__init__.py:212
#, python-format
msgid "Changed in version %s"
msgstr ""
-#: sphinx/locale/__init__.py:174
+#: sphinx/locale/__init__.py:213
#, python-format
msgid "Deprecated since version %s"
msgstr ""
-#: sphinx/locale/__init__.py:180
+#: sphinx/locale/__init__.py:219
msgid "keyword"
msgstr ""
-#: sphinx/locale/__init__.py:181
+#: sphinx/locale/__init__.py:220
msgid "operator"
msgstr ""
-#: sphinx/locale/__init__.py:182
+#: sphinx/locale/__init__.py:221
msgid "object"
msgstr ""
-#: sphinx/locale/__init__.py:184
+#: sphinx/locale/__init__.py:223
msgid "statement"
msgstr ""
-#: sphinx/locale/__init__.py:185
+#: sphinx/locale/__init__.py:224
msgid "built-in function"
msgstr ""
#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
-#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:38
msgid "Table Of Contents"
msgstr ""
-#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:138
+#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:152
#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
#: sphinx/themes/basic/searchresults.html:10
msgid "Search"
@@ -688,39 +1075,39 @@ msgstr ""
msgid "can be huge"
msgstr ""
-#: sphinx/themes/basic/layout.html:29
+#: sphinx/themes/basic/layout.html:31
msgid "Navigation"
msgstr ""
-#: sphinx/themes/basic/layout.html:123
+#: sphinx/themes/basic/layout.html:137
#, python-format
msgid "Search within %(docstitle)s"
msgstr ""
-#: sphinx/themes/basic/layout.html:132
+#: sphinx/themes/basic/layout.html:146
msgid "About these documents"
msgstr ""
-#: sphinx/themes/basic/layout.html:141
+#: sphinx/themes/basic/layout.html:155
msgid "Copyright"
msgstr ""
-#: sphinx/themes/basic/layout.html:186
+#: sphinx/themes/basic/layout.html:200
#, python-format
msgid "© Copyright %(copyright)s."
msgstr ""
-#: sphinx/themes/basic/layout.html:188
+#: sphinx/themes/basic/layout.html:202
#, python-format
msgid "© Copyright %(copyright)s."
msgstr ""
-#: sphinx/themes/basic/layout.html:192
+#: sphinx/themes/basic/layout.html:206
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr ""
-#: sphinx/themes/basic/layout.html:195
+#: sphinx/themes/basic/layout.html:209
#, python-format
msgid ""
"Created using Sphinx "
@@ -767,12 +1154,12 @@ msgid "search"
msgstr ""
#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
-#: sphinx/themes/basic/static/searchtools.js_t:287
+#: sphinx/themes/basic/static/searchtools.js_t:336
msgid "Search Results"
msgstr ""
#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
-#: sphinx/themes/basic/static/searchtools.js_t:289
+#: sphinx/themes/basic/static/searchtools.js_t:338
msgid ""
"Your search did not match any documents. Please make sure that all words "
"are spelled correctly and that you've selected enough categories."
@@ -814,43 +1201,45 @@ msgstr ""
msgid "Other changes"
msgstr ""
-#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:708
-#: sphinx/writers/html.py:713
+#: sphinx/themes/basic/static/doctools.js_t:171 sphinx/writers/html.py:405
+#: sphinx/writers/html.py:410 sphinx/writers/html5.py:352
+#: sphinx/writers/html5.py:357
msgid "Permalink to this headline"
msgstr ""
-#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:108
-#: sphinx/writers/html.py:117
+#: sphinx/themes/basic/static/doctools.js_t:177 sphinx/writers/html.py:126
+#: sphinx/writers/html.py:137 sphinx/writers/html5.py:96
+#: sphinx/writers/html5.py:107
msgid "Permalink to this definition"
msgstr ""
-#: sphinx/themes/basic/static/doctools.js_t:208
+#: sphinx/themes/basic/static/doctools.js_t:210
msgid "Hide Search Matches"
msgstr ""
-#: sphinx/themes/basic/static/searchtools.js_t:121
+#: sphinx/themes/basic/static/searchtools.js_t:142
msgid "Searching"
msgstr ""
-#: sphinx/themes/basic/static/searchtools.js_t:126
+#: sphinx/themes/basic/static/searchtools.js_t:147
msgid "Preparing search..."
msgstr ""
-#: sphinx/themes/basic/static/searchtools.js_t:291
+#: sphinx/themes/basic/static/searchtools.js_t:340
#, python-format
msgid "Search finished, found %s page(s) matching the search query."
msgstr ""
-#: sphinx/themes/basic/static/searchtools.js_t:344
+#: sphinx/themes/basic/static/searchtools.js_t:398
msgid ", in "
msgstr ""
-#: sphinx/themes/classic/static/sidebar.js_t:83
+#: sphinx/themes/classic/static/sidebar.js_t:92
msgid "Expand sidebar"
msgstr ""
-#: sphinx/themes/classic/static/sidebar.js_t:96
-#: sphinx/themes/classic/static/sidebar.js_t:124
+#: sphinx/themes/classic/static/sidebar.js_t:105
+#: sphinx/themes/classic/static/sidebar.js_t:135
msgid "Collapse sidebar"
msgstr ""
@@ -858,54 +1247,65 @@ msgstr ""
msgid "Contents"
msgstr ""
-#: sphinx/writers/html.py:389
-msgid "Permalink to this code"
+#: sphinx/transforms/post_transforms/__init__.py:105
+#, python-format
+msgid "more than one target found for 'any' cross-reference %r: could be %s"
msgstr ""
-#: sphinx/writers/html.py:393
-msgid "Permalink to this image"
+#: sphinx/transforms/post_transforms/__init__.py:135
+#, python-format
+msgid "%s:%s reference target not found: %%(target)s"
msgstr ""
-#: sphinx/writers/html.py:395
-msgid "Permalink to this toctree"
+#: sphinx/transforms/post_transforms/__init__.py:138
+#, python-format
+msgid "%r reference target not found: %%(target)s"
msgstr ""
-#: sphinx/writers/html.py:717
+#: sphinx/util/docutils.py:171
+msgid "when adding directive classes, no additional arguments may be given"
+msgstr ""
+
+#: sphinx/writers/html.py:414 sphinx/writers/html5.py:361
msgid "Permalink to this table"
msgstr ""
-#: sphinx/writers/latex.py:380
+#: sphinx/writers/html.py:466 sphinx/writers/html5.py:413
+msgid "Permalink to this code"
+msgstr ""
+
+#: sphinx/writers/html.py:470 sphinx/writers/html5.py:417
+msgid "Permalink to this image"
+msgstr ""
+
+#: sphinx/writers/html.py:472 sphinx/writers/html5.py:419
+msgid "Permalink to this toctree"
+msgstr ""
+
+#: sphinx/writers/latex.py:549
msgid "Release"
msgstr ""
-#: sphinx/writers/latex.py:483
+#: sphinx/writers/latex.py:654
msgid "page"
msgstr ""
-#: sphinx/writers/latex.py:528
+#: sphinx/writers/latex.py:704
#, python-format
msgid "Unknown configure key: latex_elements[%r] is ignored."
msgstr ""
-#: sphinx/writers/latex.py:1003 sphinx/writers/manpage.py:238
-#: sphinx/writers/texinfo.py:619
+#: sphinx/writers/latex.py:1252 sphinx/writers/manpage.py:275
+#: sphinx/writers/texinfo.py:670
msgid "Footnotes"
msgstr ""
-#: sphinx/writers/latex.py:1112
-msgid "continued from previous page"
-msgstr ""
-
-#: sphinx/writers/latex.py:1118
-msgid "Continued on next page"
-msgstr ""
-
-#: sphinx/writers/manpage.py:287 sphinx/writers/text.py:591
+#: sphinx/writers/manpage.py:331 sphinx/writers/text.py:699
#, python-format
msgid "[image: %s]"
msgstr ""
-#: sphinx/writers/manpage.py:288 sphinx/writers/text.py:592
+#: sphinx/writers/manpage.py:332 sphinx/writers/text.py:700
msgid "[image]"
msgstr ""
diff --git a/utils/release-checklist b/utils/release-checklist
index e8f716acd..a79147724 100644
--- a/utils/release-checklist
+++ b/utils/release-checklist
@@ -4,7 +4,12 @@ Release checklist
* open https://travis-ci.org/sphinx-doc/sphinx/branches and check stable branch is green
* Check `git status`
* Run `make style-check`
-* if final major release ...
+* Update sphinx/locale/sphinx.pot if first major release (beta1)
+
+ * Run `pytho nsetup.py extract_messages`
+ * Run `(cd sphinx/locale; tx push -s)`
+
+* Update sphinx/locale// files if final major release ...
* Run `(cd sphinx/locale; tx pull -a -f)`
* Run `python setup.py compile_catalog`
From 370bdddc7c9cc20383d6211a27ef6868773bd82e Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Sat, 29 Apr 2017 15:22:34 +0900
Subject: [PATCH 28/32] make websupport-dependency optional
---
CHANGES | 1 +
setup.py | 4 +++-
sphinx/websupport/__init__.py | 19 ++++++++++++-------
3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/CHANGES b/CHANGES
index 0ed869b50..c333a95f3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -20,6 +20,7 @@ Bugs fixed
* #3661: sphinx-build crashes on parallel build
* #3669: gettext builder fails with "ValueError: substring not found"
+* #3660: Sphinx always depends on sphinxcontrib-websupport and its dependencies
Testing
--------
diff --git a/setup.py b/setup.py
index 1fd2d34d0..4354b0baa 100644
--- a/setup.py
+++ b/setup.py
@@ -51,7 +51,6 @@ requires = [
'alabaster>=0.7,<0.8',
'imagesize',
'requests>=2.0.0',
- 'sphinxcontrib-websupport',
'typing',
'setuptools',
]
@@ -60,6 +59,9 @@ extras_require = {
':sys_platform=="win32"': [
'colorama>=0.3.5',
],
+ 'websupport': [
+ 'sphinxcontrib-websupport',
+ ],
'test': [
'pytest',
'mock', # it would be better for 'test:python_version in 2.7'
diff --git a/sphinx/websupport/__init__.py b/sphinx/websupport/__init__.py
index f06d98433..f71034708 100644
--- a/sphinx/websupport/__init__.py
+++ b/sphinx/websupport/__init__.py
@@ -12,11 +12,16 @@
import warnings
from sphinx.deprecation import RemovedInSphinx20Warning
-from sphinxcontrib.websupport import WebSupport # NOQA
-from sphinxcontrib.websupport import errors # NOQA
-from sphinxcontrib.websupport.search import BaseSearch, SEARCH_ADAPTERS # NOQA
-from sphinxcontrib.websupport.storage import StorageBackend # NOQA
-warnings.warn('sphinx.websupport module is now provided as sphinxcontrib.webuspport. '
- 'sphinx.websupport will be removed in Sphinx-2.0. Please use it instaed',
- RemovedInSphinx20Warning)
+try:
+ from sphinxcontrib.websupport import WebSupport # NOQA
+ from sphinxcontrib.websupport import errors # NOQA
+ from sphinxcontrib.websupport.search import BaseSearch, SEARCH_ADAPTERS # NOQA
+ from sphinxcontrib.websupport.storage import StorageBackend # NOQA
+
+ warnings.warn('sphinx.websupport module is now provided as sphinxcontrib-webuspport. '
+ 'sphinx.websupport will be removed in Sphinx-2.0. Please use it instaed',
+ RemovedInSphinx20Warning)
+except ImportError:
+ warnings.warn('Since Sphinx-1.6, sphinx.websupport module is now separated to '
+ 'sphinxcontrib-webuspport package. Please add it into your dependency list.')
From d8f57ea86525107e9f9a7e050fd12a5e95a63ec8 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Sat, 29 Apr 2017 23:26:28 +0900
Subject: [PATCH 29/32] Update CHANGES
---
CHANGES | 6 ------
1 file changed, 6 deletions(-)
diff --git a/CHANGES b/CHANGES
index c333a95f3..5350385bb 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,9 +12,6 @@ Deprecated
* #3662: ``builder.css_files`` is deprecated. Please use ``add_stylesheet()``
API instead.
-Features added
---------------
-
Bugs fixed
----------
@@ -22,9 +19,6 @@ Bugs fixed
* #3669: gettext builder fails with "ValueError: substring not found"
* #3660: Sphinx always depends on sphinxcontrib-websupport and its dependencies
-Testing
---------
-
Release 1.6 beta1 (released Apr 24, 2017)
=========================================
From 0960c7d8571e090827064f2229e404c5320dcb96 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Sat, 29 Apr 2017 23:29:43 +0900
Subject: [PATCH 30/32] Bump to 1.6b2
---
CHANGES | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CHANGES b/CHANGES
index 5350385bb..d9ac606ad 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,5 @@
-Release 1.6 beta2 (in development)
-==================================
+Release 1.6 beta2 (released Apr 29, 2017)
+=========================================
Incompatible changes
--------------------
From 0f25c18ce90dd1019db63fe29a6f4878aff702c9 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Sat, 29 Apr 2017 23:46:19 +0900
Subject: [PATCH 31/32] Bump to 1.6b2
---
sphinx/__init__.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index a071097da..62562c067 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -34,8 +34,8 @@ if 'PYTHONWARNINGS' not in os.environ:
warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io')
-__version__ = '1.6+'
-__released__ = '1.6' # used when Sphinx builds its own docs
+__version__ = '1.6b2'
+__released__ = '1.6b2' # used when Sphinx builds its own docs
# version info for better programmatic use
# possible values for 3rd element: 'alpha', 'beta', 'rc', 'final'
From 004dfae2db177eda4570bfdf4a04ae014ef6ada5 Mon Sep 17 00:00:00 2001
From: Takeshi KOMIYA
Date: Sat, 29 Apr 2017 23:50:17 +0900
Subject: [PATCH 32/32] Bump version
---
CHANGES | 18 ++++++++++++++++++
sphinx/__init__.py | 6 +++---
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/CHANGES b/CHANGES
index d9ac606ad..dea12e681 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,21 @@
+Release 1.6 beta3 (in development)
+==================================
+
+Incompatible changes
+--------------------
+
+Deprecated
+----------
+
+Features added
+--------------
+
+Bugs fixed
+----------
+
+Testing
+--------
+
Release 1.6 beta2 (released Apr 29, 2017)
=========================================
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index 62562c067..cd8ad2c0d 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -34,13 +34,13 @@ if 'PYTHONWARNINGS' not in os.environ:
warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io')
-__version__ = '1.6b2'
-__released__ = '1.6b2' # used when Sphinx builds its own docs
+__version__ = '1.6+'
+__released__ = '1.6' # 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, 6, 0, 'beta', 2)
+version_info = (1, 6, 0, 'beta', 3)
package_dir = path.abspath(path.dirname(__file__))