From 61d18a533fbe37c10259dd2ceb5ebd0674753d56 Mon Sep 17 00:00:00 2001 From: Hong Xu Date: Sat, 19 Dec 2015 12:51:52 -0800 Subject: [PATCH 01/20] Update changes for #2182 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index ef7083505..2ffb8c1a8 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,7 @@ Bugs fixed * #1237: Fix footnotes not working in definition list in LaTeX * #2168: Fix raw directive does not work for text writer * #2171: Fix cannot linkcheck url with unicode +* #2182: LaTeX: support image file names with more than 1 dots Release 1.3.3 (released Dec 2, 2015) From eac142f8b894d3af34e73752ecc9cba3e31a3d76 Mon Sep 17 00:00:00 2001 From: Hong Xu Date: Sat, 19 Dec 2015 19:24:16 -0800 Subject: [PATCH 02/20] LaTeX: Support math in section titles Fix #1480 --- sphinx/ext/mathbase.py | 18 +++++++++++++++++- tests/root/math.txt | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index 1c5de3cd7..5cd157275 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -56,6 +56,17 @@ def eq_role(role, rawtext, text, lineno, inliner, options={}, content=[]): return [node], [] +def is_in_section_title(node): + """Determine whether the node is in a section title""" + from sphinx.util.nodes import traverse_parent + + for ancestor in traverse_parent(node): + if isinstance(ancestor, nodes.title) and \ + isinstance(ancestor.parent, nodes.section): + return True + return False + + class MathDirective(Directive): has_content = True @@ -91,7 +102,12 @@ class MathDirective(Directive): def latex_visit_math(self, node): - self.body.append('\\(' + node['latex'] + '\\)') + if is_in_section_title(node): + protect = r'\protect' + else: + protect = '' + equation = protect + r'\(' + node['latex'] + protect + r'\)' + self.body.append(equation) raise nodes.SkipNode diff --git a/tests/root/math.txt b/tests/root/math.txt index 36b244943..b252353c7 100644 --- a/tests/root/math.txt +++ b/tests/root/math.txt @@ -1,5 +1,5 @@ -Test math extensions -==================== +Test math extensions :math:`E = m c^2` +====================================== This is inline math: :math:`a^2 + b^2 = c^2`. From f85d1a0b999796ee3bb653b8cdf219de14e87542 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 21 Dec 2015 11:40:53 +0900 Subject: [PATCH 03/20] Fix #2189: previous sibling link has broken if the file was appeared twice or more --- CHANGES | 1 + sphinx/environment.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 2ffb8c1a8..0b9878189 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,7 @@ Bugs fixed * #2168: Fix raw directive does not work for text writer * #2171: Fix cannot linkcheck url with unicode * #2182: LaTeX: support image file names with more than 1 dots +* #2189: Fix previous sibling link for first file in subdirectory uses last file, not intended previous from root toctree Release 1.3.3 (released Dec 2, 2015) diff --git a/sphinx/environment.py b/sphinx/environment.py index da92f2e81..ac95a4eb6 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -1958,6 +1958,8 @@ class BuildEnvironment: if docname in parents_set: # we will warn about this in resolve_toctree() return + if docname in relations: + return includes = getinc(docname) # previous if not previous: From 4d3fdc0e47b88c8afe31acfe0cebe076481afe2c Mon Sep 17 00:00:00 2001 From: Hong Xu Date: Sat, 19 Dec 2015 19:34:39 -0800 Subject: [PATCH 04/20] Fix LaTeX output of \mathbb in math If \mathbb is used in math, which is commonly used to represent sets, the output LaTeX won't compile. This commit fixes this issue by adding amsfonts package in the setup of sphinx.ext.mathbase . --- sphinx/ext/mathbase.py | 1 + tests/root/math.txt | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index 1c5de3cd7..97c9eac5b 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -214,3 +214,4 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): app.add_role('eq', eq_role) app.add_directive('math', MathDirective) app.connect('doctree-resolved', number_equations) + app.add_latex_package('amsfonts') diff --git a/tests/root/math.txt b/tests/root/math.txt index 36b244943..4c3c363dc 100644 --- a/tests/root/math.txt +++ b/tests/root/math.txt @@ -19,4 +19,8 @@ This is inline math: :math:`a^2 + b^2 = c^2`. e^{ix} = \cos x + i\sin x +.. math:: + + n \in \mathbb N + Referencing equation :eq:`foo`. From 8b57bc72277ed3b230a1aa96ab31b1cb48bb080b Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 21 Dec 2015 22:34:04 +0900 Subject: [PATCH 05/20] Fix #2003: decode error under python2 (only) when ``make linkcheck`` is run --- CHANGES | 2 ++ sphinx/builders/linkcheck.py | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/CHANGES b/CHANGES index 0b9878189..6952a7f4b 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,8 @@ Bugs fixed * #2171: Fix cannot linkcheck url with unicode * #2182: LaTeX: support image file names with more than 1 dots * #2189: Fix previous sibling link for first file in subdirectory uses last file, not intended previous from root toctree +* #2003: Fix decode error under python2 (only) when ``make linkcheck`` is run + Release 1.3.3 (released Dec 2, 2015) diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index 15b22d9e1..5dac89e2f 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -95,6 +95,17 @@ def check_anchor(f, hash): return parser.found +def get_content_charset(f): + content_type = f.headers.get('content-type') + if content_type: + params = (p.strip() for p in content_type.split(';')[1:]) + for param in params: + if param.startswith('charset='): + return param[8:] + + return None + + class CheckExternalLinksBuilder(Builder): """ Checks for broken external links. @@ -165,6 +176,8 @@ class CheckExternalLinksBuilder(Builder): encoding = 'utf-8' if hasattr(f.headers, 'get_content_charset'): encoding = f.headers.get_content_charset() or encoding + else: + encoding = get_content_charset(f) or encoding found = check_anchor(TextIOWrapper(f, encoding), unquote(hash)) f.close() From 21093adfeeb8d3e60ecdda8f6712954eb3a8454d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 22 Dec 2015 10:29:27 +0900 Subject: [PATCH 06/20] Update CHANGES for #2186 --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 6952a7f4b..d4f5c5e35 100644 --- a/CHANGES +++ b/CHANGES @@ -16,7 +16,7 @@ Bugs fixed * #2182: LaTeX: support image file names with more than 1 dots * #2189: Fix previous sibling link for first file in subdirectory uses last file, not intended previous from root toctree * #2003: Fix decode error under python2 (only) when ``make linkcheck`` is run - +* #2186: Fix LaTeX output of \mathbb in math Release 1.3.3 (released Dec 2, 2015) From ae1d9d8ff7bbc2bf4166cb5fef15cdacad4ac3e0 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 22 Dec 2015 11:35:30 +0900 Subject: [PATCH 07/20] Update CHANGES for PR #2188 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index d4f5c5e35..1710efb35 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Bugs fixed * #2189: Fix previous sibling link for first file in subdirectory uses last file, not intended previous from root toctree * #2003: Fix decode error under python2 (only) when ``make linkcheck`` is run * #2186: Fix LaTeX output of \mathbb in math +* #1480, #2188: LaTeX: Support math in section titles Release 1.3.3 (released Dec 2, 2015) From 02f013aba556d5d84429afb15e417f4d1c292b9e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 24 Dec 2015 10:57:03 +0900 Subject: [PATCH 08/20] Fix TestApp.cleanup_trees was obsoleted --- tests/test_build_latex.py | 1 - tests/test_build_texinfo.py | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index d4f9f8451..521572ac3 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -87,7 +87,6 @@ def test_latex(app, status, warning): if p.returncode != 0: print(stdout) print(stderr) - del app.cleanup_trees[:] assert False, 'latex exited with return code %s' % p.returncode finally: os.chdir(cwd) diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py index 8050695d9..618d79015 100644 --- a/tests/test_build_texinfo.py +++ b/tests/test_build_texinfo.py @@ -58,7 +58,6 @@ def test_texinfo(app, status, warning): if retcode != 0: print(stdout) print(stderr) - del app.cleanup_trees[:] assert False, 'makeinfo exited with return code %s' % retcode finally: os.chdir(cwd) From ee7e3cc078365ab20be24e846fbc868b422d252d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 24 Dec 2015 12:41:07 +0900 Subject: [PATCH 09/20] Fix empty cell in table header causes LaTeX error (#1574) --- sphinx/writers/latex.py | 7 +++++-- tests/root/markup.txt | 9 +++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index af1c6af7a..192207bce 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1061,8 +1061,11 @@ class LaTeXTranslator(nodes.NodeVisitor): self.remember_multirowcol[self.table.col] = node.get('morecols') self.table.col += node.get('morecols') if isinstance(node.parent.parent, nodes.thead): - self.body.append('\\textsf{\\relax ') - context += '}' + if len(node) == 1 and isinstance(node[0], nodes.paragraph) and node.astext() == '': + pass + else: + self.body.append('\\textsf{\\relax ') + context += '}' while self.remember_multirow.get(self.table.col + 1, 0): self.table.col += 1 self.remember_multirow[self.table.col] -= 1 diff --git a/tests/root/markup.txt b/tests/root/markup.txt index 9e8c6bc86..b322b39fa 100644 --- a/tests/root/markup.txt +++ b/tests/root/markup.txt @@ -187,6 +187,15 @@ Tables | 2 | Empty cells: | | +----+----------------+----+ +.. table:: empty cell in table header + + ===== ====== + \ + ===== ====== + 1 2 + 3 4 + ===== ====== + Tables with multirow and multicol: .. only:: latex From 0719611d54b7f40233c2e69439b35dd2b08f98b0 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 25 Dec 2015 10:43:41 +0900 Subject: [PATCH 10/20] Fix #2071: Same footnote in more than two section titles => LaTeX/PDF Bug --- CHANGES | 1 + sphinx/writers/latex.py | 2 +- tests/roots/test-footnotes/index.rst | 3 +++ tests/test_build_latex.py | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 1710efb35..9d2aee6b1 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ Bugs fixed * #2003: Fix decode error under python2 (only) when ``make linkcheck`` is run * #2186: Fix LaTeX output of \mathbb in math * #1480, #2188: LaTeX: Support math in section titles +* #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug Release 1.3.3 (released Dec 2, 2015) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 192207bce..f5f3b64b2 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1662,7 +1662,7 @@ class LaTeXTranslator(nodes.NodeVisitor): # if a footnote has been inserted once, it shouldn't be repeated # by the next reference if used: - if self.table or self.in_term: + if self.table or self.in_term or self.in_title: self.body.append('\\protect\\footnotemark[%s]' % num) else: self.body.append('\\footnotemark[%s]' % num) diff --git a/tests/roots/test-footnotes/index.rst b/tests/roots/test-footnotes/index.rst index c7fe38ff9..e8137da71 100644 --- a/tests/roots/test-footnotes/index.rst +++ b/tests/roots/test-footnotes/index.rst @@ -33,6 +33,9 @@ The section with a reference to [AuthorYear]_ .. [1] Second .. [#] Third +The section with a reference to [1]_ +===================================== + `URL in term `_ Description Description Description ... diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 521572ac3..3b2fdaaaa 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -331,6 +331,7 @@ def test_reference_in_caption(app, status, warning): assert '\\chapter{The section with a reference to {[}AuthorYear{]}}' in result assert '\\caption{The table title with a reference to {[}AuthorYear{]}}' in result assert '\\paragraph{The rubric title with a reference to {[}AuthorYear{]}}' in result + assert '\\chapter{The section with a reference to \\protect\\footnotemark[1]}' in result @with_app(buildername='latex', testroot='footnotes', From f1cf5d594a8cdb3a5008d700af6b88084e634dc6 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 25 Dec 2015 15:52:51 +0900 Subject: [PATCH 11/20] Fix #2040: UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters --- CHANGES | 1 + sphinx/apidoc.py | 19 +++++++++++++++---- tests/test_apidoc.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 9d2aee6b1..8ac51f522 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Bugs fixed * #2186: Fix LaTeX output of \mathbb in math * #1480, #2188: LaTeX: Support math in section titles * #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug +* #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters Release 1.3.3 (released Dec 2, 2015) diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py index 10311e6f3..73bb963ce 100644 --- a/sphinx/apidoc.py +++ b/sphinx/apidoc.py @@ -353,10 +353,10 @@ Note: By default this script will not overwrite already created files.""") path = opts.destdir, sep = False, dot = '_', - project = opts.header, - author = opts.author or 'Author', - version = opts.version or '', - release = opts.release or opts.version or '', + project = None, + author = 'Author', + version = '', + release = '', suffix = '.' + opts.suffix, master = 'index', epub = True, @@ -369,6 +369,17 @@ Note: By default this script will not overwrite already created files.""") mastertoctree = text, language = 'en', ) + if opts.header: + d['project'] = opts.header.decode('utf-8') + if opts.author: + d['author'] = opts.author.decode('utf-8') + if opts.version: + d['version'] = opts.version.decode('utf-8') + if opts.release: + d['release'] = opts.release.decode('utf-8') + elif opts.version: + d['release'] = opts.version.decode('utf-8') + if not opts.dryrun: qs.generate(d, silent=True, overwrite=opts.force) elif not opts.notoc: diff --git a/tests/test_apidoc.py b/tests/test_apidoc.py index 215b2e571..64fcd8fc0 100644 --- a/tests/test_apidoc.py +++ b/tests/test_apidoc.py @@ -40,3 +40,37 @@ def test_simple(tempdir): assert_build() finally: sys.path.remove(codedir) + + +@with_tempdir +def test_multibyte_parameters(tempdir): + codedir = rootdir / 'root' + outdir = tempdir / 'out' + args = ['sphinx-apidoc', '-o', outdir, '-F', codedir, + '--doc-project', u'プロジェクト名'.encode('utf-8'), + '--doc-author', u'著者名'.encode('utf-8'), + '--doc-version', u'バージョン'.encode('utf-8'), + '--doc-release', u'リリース'.encode('utf-8')] + apidoc.main(args) + + assert (outdir / 'conf.py').isfile() + assert (outdir / 'autodoc_fodder.rst').isfile() + assert (outdir / 'index.rst').isfile() + + conf_py = (outdir / 'conf.py').text() + assert u"project = u'プロジェクト名'" in conf_py + assert u"author = u'著者名'" in conf_py + assert u"version = u'バージョン'" in conf_py + assert u"release = u'リリース'" in conf_py + + @with_app('text', srcdir=outdir) + def assert_build(app, status, warning): + app.build() + print(status.getvalue()) + print(warning.getvalue()) + + sys.path.append(codedir) + try: + assert_build() + finally: + sys.path.remove(codedir) From 66ef8102c47415c5249b8973661927251ca810f5 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 25 Dec 2015 16:10:37 +0900 Subject: [PATCH 12/20] Fix broken in py3 --- sphinx/apidoc.py | 27 +++++++++++++-------------- tests/test_apidoc.py | 15 +++++++++++---- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py index 73bb963ce..1238693c8 100644 --- a/sphinx/apidoc.py +++ b/sphinx/apidoc.py @@ -20,6 +20,7 @@ import os import sys import optparse from os import path +from six import binary_type from sphinx.util.osutil import walk from sphinx import __display_version__ @@ -353,10 +354,10 @@ Note: By default this script will not overwrite already created files.""") path = opts.destdir, sep = False, dot = '_', - project = None, - author = 'Author', - version = '', - release = '', + project = opts.header, + author = opts.author or 'Author', + version = opts.version or '', + release = opts.release or opts.version or '', suffix = '.' + opts.suffix, master = 'index', epub = True, @@ -369,16 +370,14 @@ Note: By default this script will not overwrite already created files.""") mastertoctree = text, language = 'en', ) - if opts.header: - d['project'] = opts.header.decode('utf-8') - if opts.author: - d['author'] = opts.author.decode('utf-8') - if opts.version: - d['version'] = opts.version.decode('utf-8') - if opts.release: - d['release'] = opts.release.decode('utf-8') - elif opts.version: - d['release'] = opts.version.decode('utf-8') + if isinstance(opts.header, binary_type): + d['project'] = d['project'].decode('utf-8') + if isinstance(opts.author, binary_type): + d['author'] = d['author'].decode('utf-8') + if isinstance(opts.version, binary_type): + d['version'] = d['version'].decode('utf-8') + if isinstance(opts.release, binary_type): + d['release'] = d['release'].decode('utf-8') if not opts.dryrun: qs.generate(d, silent=True, overwrite=opts.force) diff --git a/tests/test_apidoc.py b/tests/test_apidoc.py index 64fcd8fc0..794b1a293 100644 --- a/tests/test_apidoc.py +++ b/tests/test_apidoc.py @@ -12,6 +12,7 @@ from __future__ import print_function import sys +from six import PY2 from sphinx import apidoc @@ -58,10 +59,16 @@ def test_multibyte_parameters(tempdir): assert (outdir / 'index.rst').isfile() conf_py = (outdir / 'conf.py').text() - assert u"project = u'プロジェクト名'" in conf_py - assert u"author = u'著者名'" in conf_py - assert u"version = u'バージョン'" in conf_py - assert u"release = u'リリース'" in conf_py + if PY2: + assert u"project = u'プロジェクト名'" in conf_py + assert u"author = u'著者名'" in conf_py + assert u"version = u'バージョン'" in conf_py + assert u"release = u'リリース'" in conf_py + else: + assert u"project = 'プロジェクト名'" in conf_py + assert u"author = '著者名'" in conf_py + assert u"version = 'バージョン'" in conf_py + assert u"release = 'リリース'" in conf_py @with_app('text', srcdir=outdir) def assert_build(app, status, warning): From 9c2704b705d9989ff235625fbf735c79b8086753 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 26 Dec 2015 01:44:40 +0900 Subject: [PATCH 13/20] Fix #2193: shutil.SameFileError if source directory and destination directory are same --- CHANGES | 1 + sphinx/cmdline.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 8ac51f522..561d0f45c 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,7 @@ Bugs fixed * #1480, #2188: LaTeX: Support math in section titles * #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug * #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters +* #2193: Fix shutil.SameFileError if source directory and destination directory are same Release 1.3.3 (released Dec 2, 2015) diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py index e411836c3..e9d76bb83 100644 --- a/sphinx/cmdline.py +++ b/sphinx/cmdline.py @@ -144,6 +144,10 @@ def main(argv): file=sys.stderr) return 1 outdir = abspath(args[1]) + if srcdir == outdir: + print('Error: source directory and destination directory are same.', + file=sys.stderr) + return 1 except IndexError: parser.print_help() return 1 From f1518c5fc4446d63c0ba92150f5a226e3691aa62 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 26 Dec 2015 11:17:04 +0900 Subject: [PATCH 14/20] Fix #2183 porterstemmer causes `make json` to fail Drop PorterStemmer package support. For now, PyStemmer can accelarate stemming process of snowballstemmer. --- CHANGES | 1 + sphinx/search/en.py | 21 +++++---------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index 561d0f45c..af3293ff6 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,7 @@ Bugs fixed * #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug * #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters * #2193: Fix shutil.SameFileError if source directory and destination directory are same +* #2183: Fix porterstemmer causes `make json` to fail Release 1.3.3 (released Dec 2, 2015) diff --git a/sphinx/search/en.py b/sphinx/search/en.py index de77ae294..08b113c62 100644 --- a/sphinx/search/en.py +++ b/sphinx/search/en.py @@ -12,18 +12,11 @@ from sphinx.search import SearchLanguage try: - # http://bitbucket.org/methane/porterstemmer/ - from porterstemmer import Stemmer as CStemmer - CSTEMMER = True - PYSTEMMER = False + from Stemmer import Stemmer as PyStemmer + PYSTEMMER = True except ImportError: - CSTEMMER = False - try: - from Stemmer import Stemmer as PyStemmer - PYSTEMMER = True - except ImportError: - from sphinx.util.stemmer import PorterStemmer - PYSTEMMER = False + from sphinx.util.stemmer import PorterStemmer + PYSTEMMER = False english_stopwords = set(""" a and are as at @@ -231,11 +224,7 @@ class SearchEnglish(SearchLanguage): stopwords = english_stopwords def init(self, options): - if CSTEMMER: - class Stemmer(CStemmer): - def stem(self, word): - return self(word.lower()) - elif PYSTEMMER: + if PYSTEMMER: class Stemmer(object): def __init__(self): self.stemmer = PyStemmer('porter') From 9fc83df2de5c59ce066ee684e72fd80ebcd73dd9 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 26 Dec 2015 13:15:36 +0900 Subject: [PATCH 15/20] Revert "Fix #2183 porterstemmer causes `make json` to fail" This is a breaking change. So we move the change into master branch. This reverts commit f1518c5fc4446d63c0ba92150f5a226e3691aa62. --- CHANGES | 1 - sphinx/search/en.py | 21 ++++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index af3293ff6..561d0f45c 100644 --- a/CHANGES +++ b/CHANGES @@ -21,7 +21,6 @@ Bugs fixed * #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug * #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters * #2193: Fix shutil.SameFileError if source directory and destination directory are same -* #2183: Fix porterstemmer causes `make json` to fail Release 1.3.3 (released Dec 2, 2015) diff --git a/sphinx/search/en.py b/sphinx/search/en.py index 08b113c62..de77ae294 100644 --- a/sphinx/search/en.py +++ b/sphinx/search/en.py @@ -12,11 +12,18 @@ from sphinx.search import SearchLanguage try: - from Stemmer import Stemmer as PyStemmer - PYSTEMMER = True -except ImportError: - from sphinx.util.stemmer import PorterStemmer + # http://bitbucket.org/methane/porterstemmer/ + from porterstemmer import Stemmer as CStemmer + CSTEMMER = True PYSTEMMER = False +except ImportError: + CSTEMMER = False + try: + from Stemmer import Stemmer as PyStemmer + PYSTEMMER = True + except ImportError: + from sphinx.util.stemmer import PorterStemmer + PYSTEMMER = False english_stopwords = set(""" a and are as at @@ -224,7 +231,11 @@ class SearchEnglish(SearchLanguage): stopwords = english_stopwords def init(self, options): - if PYSTEMMER: + if CSTEMMER: + class Stemmer(CStemmer): + def stem(self, word): + return self(word.lower()) + elif PYSTEMMER: class Stemmer(object): def __init__(self): self.stemmer = PyStemmer('porter') From 222a51e0cf0080b74f3a8a233590c707ee4eec32 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 26 Dec 2015 21:43:54 +0900 Subject: [PATCH 16/20] Fix #2189: next sibling link has broken if the file was appeared twice or more --- sphinx/environment.py | 13 ++++++++--- tests/roots/test-toctree-glob/bar/bar_1.rst | 4 ++++ tests/roots/test-toctree-glob/bar/bar_2.rst | 4 ++++ tests/roots/test-toctree-glob/bar/bar_3.rst | 4 ++++ tests/roots/test-toctree-glob/bar/index.rst | 7 ++++++ tests/roots/test-toctree-glob/baz.rst | 4 ++++ tests/roots/test-toctree-glob/conf.py | 4 ++++ tests/roots/test-toctree-glob/foo.rst | 4 ++++ tests/roots/test-toctree-glob/index.rst | 10 +++++++++ tests/test_toctree.py | 24 +++++++++++++++++++++ 10 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 tests/roots/test-toctree-glob/bar/bar_1.rst create mode 100644 tests/roots/test-toctree-glob/bar/bar_2.rst create mode 100644 tests/roots/test-toctree-glob/bar/bar_3.rst create mode 100644 tests/roots/test-toctree-glob/bar/index.rst create mode 100644 tests/roots/test-toctree-glob/baz.rst create mode 100644 tests/roots/test-toctree-glob/conf.py create mode 100644 tests/roots/test-toctree-glob/foo.rst create mode 100644 tests/roots/test-toctree-glob/index.rst create mode 100644 tests/test_toctree.py diff --git a/sphinx/environment.py b/sphinx/environment.py index ac95a4eb6..6c3a2cc98 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -1987,9 +1987,16 @@ class BuildEnvironment: # else the grandparent's sibling, if present, and so forth for parname, parindex in parents: parincs = getinc(parname) - if parincs and parindex + 1 < len(parincs): - next = parincs[parindex+1] - break + if parincs: + for parinc in parincs[parindex + 1:]: + if parinc in relations or parinc == docname: + pass + else: + next = parinc + break + + if next: + break # else it will stay None # same for children if includes: diff --git a/tests/roots/test-toctree-glob/bar/bar_1.rst b/tests/roots/test-toctree-glob/bar/bar_1.rst new file mode 100644 index 000000000..6229a1561 --- /dev/null +++ b/tests/roots/test-toctree-glob/bar/bar_1.rst @@ -0,0 +1,4 @@ +Bar-1 +===== + +bar diff --git a/tests/roots/test-toctree-glob/bar/bar_2.rst b/tests/roots/test-toctree-glob/bar/bar_2.rst new file mode 100644 index 000000000..ed7862100 --- /dev/null +++ b/tests/roots/test-toctree-glob/bar/bar_2.rst @@ -0,0 +1,4 @@ +Bar-2 +===== + +bar diff --git a/tests/roots/test-toctree-glob/bar/bar_3.rst b/tests/roots/test-toctree-glob/bar/bar_3.rst new file mode 100644 index 000000000..93c58d41f --- /dev/null +++ b/tests/roots/test-toctree-glob/bar/bar_3.rst @@ -0,0 +1,4 @@ +Bar-3 +===== + +bar diff --git a/tests/roots/test-toctree-glob/bar/index.rst b/tests/roots/test-toctree-glob/bar/index.rst new file mode 100644 index 000000000..290bd2b75 --- /dev/null +++ b/tests/roots/test-toctree-glob/bar/index.rst @@ -0,0 +1,7 @@ +Bar +=== + +.. toctree:: + :glob: + + * diff --git a/tests/roots/test-toctree-glob/baz.rst b/tests/roots/test-toctree-glob/baz.rst new file mode 100644 index 000000000..2c1bbbc72 --- /dev/null +++ b/tests/roots/test-toctree-glob/baz.rst @@ -0,0 +1,4 @@ +Baz +=== + +baz diff --git a/tests/roots/test-toctree-glob/conf.py b/tests/roots/test-toctree-glob/conf.py new file mode 100644 index 000000000..cf05c9b5c --- /dev/null +++ b/tests/roots/test-toctree-glob/conf.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' +html_theme = 'classic' diff --git a/tests/roots/test-toctree-glob/foo.rst b/tests/roots/test-toctree-glob/foo.rst new file mode 100644 index 000000000..83f952239 --- /dev/null +++ b/tests/roots/test-toctree-glob/foo.rst @@ -0,0 +1,4 @@ +Foo +=== + +foo diff --git a/tests/roots/test-toctree-glob/index.rst b/tests/roots/test-toctree-glob/index.rst new file mode 100644 index 000000000..4a8acecbc --- /dev/null +++ b/tests/roots/test-toctree-glob/index.rst @@ -0,0 +1,10 @@ +test-toctree-glob +================= + +.. toctree:: + :glob: + + foo + bar/index + bar/* + baz diff --git a/tests/test_toctree.py b/tests/test_toctree.py new file mode 100644 index 000000000..17e1a780d --- /dev/null +++ b/tests/test_toctree.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" + test_toctree + ~~~~~~~~~~~~ + + Test the HTML builder and check output against XPath. + + :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from util import with_app + + +@with_app(testroot='toctree-glob') +def test_relations(app, status, warning): + app.builder.build_all() + assert app.builder.relations['index'] == [None, None, 'foo'] + assert app.builder.relations['foo'] == ['index', 'index', 'bar/index'] + assert app.builder.relations['bar/index'] == ['index', 'foo', 'bar/bar_1'] + assert app.builder.relations['bar/bar_1'] == ['bar/index', 'bar/index', 'bar/bar_2'] + assert app.builder.relations['bar/bar_2'] == ['bar/index', 'bar/bar_1', 'bar/bar_3'] + assert app.builder.relations['bar/bar_3'] == ['bar/index', 'bar/bar_2', 'baz'] + assert app.builder.relations['baz'] == ['index', 'bar/bar_3', None] From 8a763feb6b92404a4acea0894dc23d4060e9f36e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 26 Dec 2015 23:57:09 +0900 Subject: [PATCH 17/20] Fix #2189: previous sibling link has broken if previous doc is under nested toctree --- sphinx/environment.py | 76 ++++++------------- .../test-toctree-glob/bar/bar_4/index.rst | 4 + tests/roots/test-toctree-glob/bar/index.rst | 1 + tests/roots/test-toctree-glob/index.rst | 1 + tests/roots/test-toctree-glob/quux.rst | 4 + tests/roots/test-toctree-glob/qux/index.rst | 8 ++ tests/roots/test-toctree-glob/qux/qux_1.rst | 4 + tests/roots/test-toctree-glob/qux/qux_2.rst | 4 + tests/test_toctree.py | 9 ++- 9 files changed, 55 insertions(+), 56 deletions(-) create mode 100644 tests/roots/test-toctree-glob/bar/bar_4/index.rst create mode 100644 tests/roots/test-toctree-glob/quux.rst create mode 100644 tests/roots/test-toctree-glob/qux/index.rst create mode 100644 tests/roots/test-toctree-glob/qux/qux_1.rst create mode 100644 tests/roots/test-toctree-glob/qux/qux_2.rst diff --git a/sphinx/environment.py b/sphinx/environment.py index 6c3a2cc98..743021e0f 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -1950,63 +1950,31 @@ class BuildEnvironment: for (key_, group) in groupby(newlist, keyfunc2)] def collect_relations(self): + traversed = set() + + def traverse_toctree(parent, docname): + # traverse toctree by pre-order + yield parent, docname + traversed.add(docname) + + for child in (self.toctree_includes.get(docname) or []): + for subparent, subdocname in traverse_toctree(docname, child): + if subdocname not in traversed: + yield subparent, subdocname + traversed.add(subdocname) + relations = {} - getinc = self.toctree_includes.get + docnames = traverse_toctree(None, self.config.master_doc) + prevdoc = None + parent, docname = docnames.next() + for nextparent, nextdoc in docnames: + relations[docname] = [parent, prevdoc, nextdoc] + prevdoc = docname + docname = nextdoc + parent = nextparent - def collect(parents, parents_set, docname, previous, next): - # circular relationship? - if docname in parents_set: - # we will warn about this in resolve_toctree() - return - if docname in relations: - return - includes = getinc(docname) - # previous - if not previous: - # if no previous sibling, go to parent - previous = parents[0][0] - else: - # else, go to previous sibling, or if it has children, to - # the last of its children, or if that has children, to the - # last of those, and so forth - while 1: - previncs = getinc(previous) - if previncs: - previous = previncs[-1] - else: - break - # next - if includes: - # if it has children, go to first of them - next = includes[0] - elif next: - # else, if next sibling, go to it - pass - else: - # else, go to the next sibling of the parent, if present, - # else the grandparent's sibling, if present, and so forth - for parname, parindex in parents: - parincs = getinc(parname) - if parincs: - for parinc in parincs[parindex + 1:]: - if parinc in relations or parinc == docname: - pass - else: - next = parinc - break + relations[docname] = [parent, prevdoc, None] - if next: - break - # else it will stay None - # same for children - if includes: - for subindex, args in enumerate(zip(includes, - [None] + includes, - includes[1:] + [None])): - collect([(docname, subindex)] + parents, - parents_set.union([docname]), *args) - relations[docname] = [parents[0][0], previous, next] - collect([(None, 0)], set(), self.config.master_doc, None, None) return relations def check_consistency(self): diff --git a/tests/roots/test-toctree-glob/bar/bar_4/index.rst b/tests/roots/test-toctree-glob/bar/bar_4/index.rst new file mode 100644 index 000000000..4fae623ce --- /dev/null +++ b/tests/roots/test-toctree-glob/bar/bar_4/index.rst @@ -0,0 +1,4 @@ +Bar-4 +===== + +bar diff --git a/tests/roots/test-toctree-glob/bar/index.rst b/tests/roots/test-toctree-glob/bar/index.rst index 290bd2b75..74a9ba942 100644 --- a/tests/roots/test-toctree-glob/bar/index.rst +++ b/tests/roots/test-toctree-glob/bar/index.rst @@ -5,3 +5,4 @@ Bar :glob: * + bar_4/index diff --git a/tests/roots/test-toctree-glob/index.rst b/tests/roots/test-toctree-glob/index.rst index 4a8acecbc..079cd6027 100644 --- a/tests/roots/test-toctree-glob/index.rst +++ b/tests/roots/test-toctree-glob/index.rst @@ -8,3 +8,4 @@ test-toctree-glob bar/index bar/* baz + qux/index diff --git a/tests/roots/test-toctree-glob/quux.rst b/tests/roots/test-toctree-glob/quux.rst new file mode 100644 index 000000000..340389d0a --- /dev/null +++ b/tests/roots/test-toctree-glob/quux.rst @@ -0,0 +1,4 @@ +Quux +==== + +quux diff --git a/tests/roots/test-toctree-glob/qux/index.rst b/tests/roots/test-toctree-glob/qux/index.rst new file mode 100644 index 000000000..ad0bee51f --- /dev/null +++ b/tests/roots/test-toctree-glob/qux/index.rst @@ -0,0 +1,8 @@ +Qux +=== + +.. toctree:: + :glob: + :hidden: + + * diff --git a/tests/roots/test-toctree-glob/qux/qux_1.rst b/tests/roots/test-toctree-glob/qux/qux_1.rst new file mode 100644 index 000000000..bac227b42 --- /dev/null +++ b/tests/roots/test-toctree-glob/qux/qux_1.rst @@ -0,0 +1,4 @@ +Qux-1 +===== + +qux diff --git a/tests/roots/test-toctree-glob/qux/qux_2.rst b/tests/roots/test-toctree-glob/qux/qux_2.rst new file mode 100644 index 000000000..bac227b42 --- /dev/null +++ b/tests/roots/test-toctree-glob/qux/qux_2.rst @@ -0,0 +1,4 @@ +Qux-1 +===== + +qux diff --git a/tests/test_toctree.py b/tests/test_toctree.py index 17e1a780d..d91d92389 100644 --- a/tests/test_toctree.py +++ b/tests/test_toctree.py @@ -20,5 +20,10 @@ def test_relations(app, status, warning): assert app.builder.relations['bar/index'] == ['index', 'foo', 'bar/bar_1'] assert app.builder.relations['bar/bar_1'] == ['bar/index', 'bar/index', 'bar/bar_2'] assert app.builder.relations['bar/bar_2'] == ['bar/index', 'bar/bar_1', 'bar/bar_3'] - assert app.builder.relations['bar/bar_3'] == ['bar/index', 'bar/bar_2', 'baz'] - assert app.builder.relations['baz'] == ['index', 'bar/bar_3', None] + assert app.builder.relations['bar/bar_3'] == ['bar/index', 'bar/bar_2', 'bar/bar_4/index'] + assert app.builder.relations['bar/bar_4/index'] == ['bar/index', 'bar/bar_3', 'baz'] + assert app.builder.relations['baz'] == ['index', 'bar/bar_4/index', 'qux/index'] + assert app.builder.relations['qux/index'] == ['index', 'baz', 'qux/qux_1'] + assert app.builder.relations['qux/qux_1'] == ['qux/index', 'qux/index', 'qux/qux_2'] + assert app.builder.relations['qux/qux_2'] == ['qux/index', 'qux/qux_1', None] + assert 'quux' not in app.builder.relations From 2f27459e8082c73bf95205ef2f63d17519680509 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 27 Dec 2015 00:46:14 +0900 Subject: [PATCH 18/20] Fix flake8 violation --- sphinx/environment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/environment.py b/sphinx/environment.py index 743021e0f..ebf579c59 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -24,7 +24,7 @@ from glob import glob from itertools import groupby from six import iteritems, itervalues, text_type, class_types, string_types -from six.moves import cPickle as pickle, zip +from six.moves import cPickle as pickle from docutils import nodes from docutils.io import FileInput, NullOutput from docutils.core import Publisher From 98ac902650f1d0e498f974eeee0f87425613040f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 27 Dec 2015 00:52:58 +0900 Subject: [PATCH 19/20] Fix broken in py3 (for 8a763feb6b92404a4acea0894dc23d4060e9f36e) --- sphinx/environment.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx/environment.py b/sphinx/environment.py index ebf579c59..371b3a6c4 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -23,7 +23,7 @@ from os import path from glob import glob from itertools import groupby -from six import iteritems, itervalues, text_type, class_types, string_types +from six import iteritems, itervalues, text_type, class_types, string_types, next from six.moves import cPickle as pickle from docutils import nodes from docutils.io import FileInput, NullOutput @@ -1966,7 +1966,7 @@ class BuildEnvironment: relations = {} docnames = traverse_toctree(None, self.config.master_doc) prevdoc = None - parent, docname = docnames.next() + parent, docname = next(docnames) for nextparent, nextdoc in docnames: relations[docname] = [parent, prevdoc, nextdoc] prevdoc = docname From 87998df9cbef2380345d436121e6bca43345d2bd Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 27 Dec 2015 01:32:40 +0900 Subject: [PATCH 20/20] Fix a documentation for sphinx.ext.viewcode --- doc/ext/viewcode.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/doc/ext/viewcode.rst b/doc/ext/viewcode.rst index f2b6c9283..5bf8eb033 100644 --- a/doc/ext/viewcode.rst +++ b/doc/ext/viewcode.rst @@ -15,11 +15,7 @@ a highlighted version of the source code, and a link will be added to all object descriptions that leads to the source code of the described object. A link back from the source to the description will also be inserted. -There are currently no configuration values for this extension; you just need to -add ``'sphinx.ext.viewcode'`` to your :confval:`extensions` value for it to -work. - -There is also an additional config value: +There is an additional config value: .. confval:: viewcode_import