summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/coverage.py16
-rw-r--r--tests/root/Makefile2
-rw-r--r--tests/root/autodoc_missing_imports.py9
-rw-r--r--tests/root/img.foo.pngbin67765 -> 66247 bytes
-rw-r--r--tests/root/img.pngbin67765 -> 66247 bytes
-rw-r--r--tests/root/objects.txt8
-rw-r--r--tests/root/pep_0420/a/b/c/__init__.py1
-rw-r--r--tests/root/pep_0420/a/b/c/d.py1
-rw-r--r--tests/root/pep_0420/a/b/x/y.py1
-rw-r--r--tests/root/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/root/subdir/img.pngbin67765 -> 66247 bytes
-rw-r--r--tests/root/subdir/simg.pngbin67765 -> 66247 bytes
-rw-r--r--tests/root/testtheme/static/staticimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-add_enumerable_node/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-config/conf.py3
-rw-r--r--tests/roots/test-directive-code/lineno_match.rst6
-rw-r--r--tests/roots/test-ext-autodoc/autodoc_dummy_module.py6
-rw-r--r--tests/roots/test-ext-autodoc/conf.py12
-rw-r--r--tests/roots/test-ext-autodoc/contents.rst3
-rw-r--r--tests/roots/test-ext-graphviz/index.rst6
-rw-r--r--tests/roots/test-ext-inheritance_diagram/index.rst3
-rw-r--r--tests/roots/test-ext-math/index.rst4
-rw-r--r--tests/roots/test-ext-todo/bar.rst4
-rw-r--r--tests/roots/test-ext-todo/conf.py4
-rw-r--r--tests/roots/test-ext-todo/foo.rst4
-rw-r--r--tests/roots/test-ext-todo/index.rst9
-rw-r--r--tests/roots/test-footnotes/index.rst28
-rw-r--r--tests/roots/test-footnotes/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-html_assets/conf.py (renamed from tests/roots/test-html_extra_path/conf.py)3
-rw-r--r--tests/roots/test-html_assets/extra/.htaccess (renamed from tests/roots/test-html_extra_path/extra/.htaccess)0
-rw-r--r--tests/roots/test-html_assets/extra/.htpasswd (renamed from tests/roots/test-html_extra_path/extra/.htpasswd)0
-rw-r--r--tests/roots/test-html_assets/extra/API.html_t1
-rw-r--r--tests/roots/test-html_assets/extra/css/style.css (renamed from tests/roots/test-html_extra_path/extra/css/style.css)0
-rw-r--r--tests/roots/test-html_assets/extra/rimg.pngbin0 -> 120 bytes
-rw-r--r--tests/roots/test-html_assets/extra/subdir/.htaccess (renamed from tests/roots/test-html_extra_path/extra/API.html_t)0
-rw-r--r--tests/roots/test-html_assets/extra/subdir/.htpasswd (renamed from tests/roots/test-html_extra_path/subdir/_build/index.html)0
-rw-r--r--tests/roots/test-html_assets/index.rst (renamed from tests/roots/test-html_extra_path/index.rst)0
-rw-r--r--tests/roots/test-html_assets/static/.htaccess0
-rw-r--r--tests/roots/test-html_assets/static/.htpasswd0
-rw-r--r--tests/roots/test-html_assets/static/API.html_t1
-rw-r--r--tests/roots/test-html_assets/static/css/style.css0
-rw-r--r--tests/roots/test-html_assets/static/rimg.pngbin0 -> 120 bytes
-rw-r--r--tests/roots/test-html_assets/static/subdir/.htaccess0
-rw-r--r--tests/roots/test-html_assets/static/subdir/.htpasswd0
-rw-r--r--tests/roots/test-html_assets/subdir/_build/index.html0
-rw-r--r--tests/roots/test-html_assets/subdir/background.pngbin0 -> 120 bytes
-rw-r--r--tests/roots/test-html_extra_path/extra/rimg.pngbin218 -> 0 bytes
-rw-r--r--tests/roots/test-html_extra_path/subdir/background.pngbin218 -> 0 bytes
-rw-r--r--tests/roots/test-image-glob/img.ja.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-image-glob/img.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-image-glob/img.zh.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-image-glob/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-image-glob/rimg.xx.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-image-glob/subdir/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-image-glob/subdir/rimg.xx.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-image-glob/testimäge.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-image-in-section/pic.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-intl/contents.po26
-rw-r--r--tests/roots/test-intl/contents.txt5
-rw-r--r--tests/roots/test-intl/i18n.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-intl/img.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-intl/only.po29
-rw-r--r--tests/roots/test-intl/only.txt14
-rw-r--r--tests/roots/test-keep_warnings/conf.py4
-rw-r--r--tests/roots/test-keep_warnings/index.rst2
-rw-r--r--tests/roots/test-linkcheck/conf.py4
-rw-r--r--tests/roots/test-linkcheck/links.txt11
-rw-r--r--tests/roots/test-maxlistdepth/conf.py14
-rw-r--r--tests/roots/test-maxlistdepth/index.rst57
-rw-r--r--tests/roots/test-numfig/bar.rst8
-rw-r--r--tests/roots/test-numfig/baz.rst2
-rw-r--r--tests/roots/test-numfig/foo.rst10
-rw-r--r--tests/roots/test-numfig/index.rst7
-rw-r--r--tests/roots/test-numfig/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-refonly_bullet_list/conf.py8
-rw-r--r--tests/roots/test-refonly_bullet_list/index.rst14
-rw-r--r--tests/roots/test-search/conf.py3
-rw-r--r--tests/roots/test-search/index.rst30
-rw-r--r--tests/roots/test-search/tocitem.rst10
-rw-r--r--tests/roots/test-toctree-glob/index.rst16
-rw-r--r--tests/roots/test-toctree-maxdepth/qux.rst9
-rw-r--r--tests/roots/test-toctree/bar.rst2
-rw-r--r--tests/roots/test-toctree/baz.rst2
-rw-r--r--tests/roots/test-toctree/conf.py7
-rw-r--r--tests/roots/test-toctree/foo.rst15
-rw-r--r--tests/roots/test-toctree/index.rst54
-rw-r--r--tests/roots/test-toctree/quux.rst2
-rw-r--r--tests/roots/test-toctree/qux.rst1
-rw-r--r--tests/roots/test-toctree/tocdepth.rst15
-rwxr-xr-xtests/run.py4
-rw-r--r--tests/test_api_translator.py2
-rw-r--r--tests/test_apidoc.py88
-rw-r--r--tests/test_application.py9
-rw-r--r--tests/test_autodoc.py61
-rw-r--r--tests/test_build.py29
-rw-r--r--tests/test_build_html.py186
-rw-r--r--tests/test_build_latex.py392
-rw-r--r--tests/test_build_linkcheck.py38
-rw-r--r--tests/test_build_texinfo.py5
-rw-r--r--tests/test_build_text.py2
-rw-r--r--tests/test_config.py16
-rw-r--r--tests/test_directive_code.py16
-rw-r--r--tests/test_directive_only.py3
-rw-r--r--tests/test_domain_cpp.py85
-rw-r--r--tests/test_domain_std.py4
-rw-r--r--tests/test_environment_indexentries.py136
-rw-r--r--tests/test_environment_toctree.py332
-rw-r--r--tests/test_ext_autodoc.py25
-rw-r--r--tests/test_ext_graphviz.py9
-rw-r--r--tests/test_ext_inheritance_diagram.py25
-rw-r--r--tests/test_ext_intersphinx.py97
-rw-r--r--tests/test_ext_math.py18
-rw-r--r--tests/test_ext_napoleon.py2
-rw-r--r--tests/test_ext_napoleon_docstring.py51
-rw-r--r--tests/test_ext_todo.py85
-rw-r--r--tests/test_intl.py60
-rw-r--r--tests/test_markup.py54
-rw-r--r--tests/test_quickstart.py13
-rw-r--r--tests/test_search.py73
-rw-r--r--tests/test_searchadapters.py2
-rw-r--r--tests/test_setup_command.py22
-rw-r--r--tests/test_theming.py8
-rw-r--r--tests/test_util_fileutil.py114
-rw-r--r--tests/test_util_i18n.py12
-rw-r--r--tests/test_util_matching.py91
-rw-r--r--tests/test_writer_latex.py36
-rw-r--r--tests/typing_test_data.py14
-rw-r--r--tests/util.py40
128 files changed, 2338 insertions, 437 deletions
diff --git a/tests/coverage.py b/tests/coverage.py
index f9341d8ba..cd36e218a 100755
--- a/tests/coverage.py
+++ b/tests/coverage.py
@@ -472,10 +472,9 @@ class coverage:
def save(self):
if self.usecache and self.cache:
self.canonicalize_filenames()
- cache = open(self.cache, 'wb')
import marshal
- marshal.dump(self.cexecuted, cache)
- cache.close()
+ with open(self.cache, 'wb') as cache:
+ marshal.dump(self.cexecuted, cache)
# restore(). Restore coverage data from the coverage cache (if it exists).
@@ -488,10 +487,9 @@ class coverage:
def restore_file(self, file_name):
try:
- cache = open(file_name, 'rb')
import marshal
- cexecuted = marshal.load(cache)
- cache.close()
+ with open(file_name, 'rb') as cache:
+ cexecuted = marshal.load(cache)
if isinstance(cexecuted, dict):
return cexecuted
else:
@@ -614,8 +612,8 @@ class coverage:
)
filename = filename[:-1]
if not source:
- sourcef = open(filename, 'rU')
- source = sourcef.read()
+ with open(filename, 'rU') as sourcef:
+ source = sourcef.read()
try:
lines, excluded_lines, line_map = self.find_executable_statements(
source, exclude=self.exclude_re
@@ -625,8 +623,6 @@ class coverage:
"Couldn't parse '%s' as Python source: '%s' at line %d" %
(filename, synerr.msg, synerr.lineno)
)
- if sourcef:
- sourcef.close()
result = filename, lines, excluded_lines, line_map
self.analysis_cache[morf] = result
return result
diff --git a/tests/root/Makefile b/tests/root/Makefile
index 7954bc7cb..7d5162fe7 100644
--- a/tests/root/Makefile
+++ b/tests/root/Makefile
@@ -17,7 +17,7 @@ help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " pickle to make pickle files (usable by e.g. sphinx-web)"
- @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " htmlhelp to make HTML files and an HTML help project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview over all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
diff --git a/tests/root/autodoc_missing_imports.py b/tests/root/autodoc_missing_imports.py
index 7a7173452..0901ce8e2 100644
--- a/tests/root/autodoc_missing_imports.py
+++ b/tests/root/autodoc_missing_imports.py
@@ -5,5 +5,14 @@ import missing_package1.missing_module1
from missing_package2 import missing_module2
from missing_package3.missing_module3 import missing_name
+@missing_name
+def decoratedFunction():
+ """decoratedFunction docstring"""
+ return None
+
class TestAutodoc(object):
"""TestAutodoc docstring."""
+ @missing_name
+ def decoratedMethod(self):
+ """TestAutodoc::decoratedMethod docstring"""
+ return None
diff --git a/tests/root/img.foo.png b/tests/root/img.foo.png
index 4c8f89929..a97e86d66 100644
--- a/tests/root/img.foo.png
+++ b/tests/root/img.foo.png
Binary files differ
diff --git a/tests/root/img.png b/tests/root/img.png
index 4c8f89929..a97e86d66 100644
--- a/tests/root/img.png
+++ b/tests/root/img.png
Binary files differ
diff --git a/tests/root/objects.txt b/tests/root/objects.txt
index cd711070f..1fc23567a 100644
--- a/tests/root/objects.txt
+++ b/tests/root/objects.txt
@@ -93,7 +93,7 @@ Referring to :func:`nothing <>`.
* expression
:returns: a new :class:`Time` instance
:rtype: Time
- :raises ValueError: if the values are out of range
+ :raises Error: if the values are out of range
:ivar int hour: like *hour*
:ivar minute: like *minute*
:vartype minute: int
@@ -172,9 +172,13 @@ Others
.. option:: +p
+.. option:: --plugin.option
+
+.. option:: create-auth-token
+
.. option:: arg
-Link to :option:`perl +p` and :option:`arg`
+Link to :option:`perl +p`, :option:`--plugin.option`, :option:`create-auth-token` and :option:`arg`
.. program:: hg
diff --git a/tests/root/pep_0420/a/b/c/__init__.py b/tests/root/pep_0420/a/b/c/__init__.py
new file mode 100644
index 000000000..619273942
--- /dev/null
+++ b/tests/root/pep_0420/a/b/c/__init__.py
@@ -0,0 +1 @@
+"Package C" \ No newline at end of file
diff --git a/tests/root/pep_0420/a/b/c/d.py b/tests/root/pep_0420/a/b/c/d.py
new file mode 100644
index 000000000..6b0b45d90
--- /dev/null
+++ b/tests/root/pep_0420/a/b/c/d.py
@@ -0,0 +1 @@
+"Module d" \ No newline at end of file
diff --git a/tests/root/pep_0420/a/b/x/y.py b/tests/root/pep_0420/a/b/x/y.py
new file mode 100644
index 000000000..8b49b2079
--- /dev/null
+++ b/tests/root/pep_0420/a/b/x/y.py
@@ -0,0 +1 @@
+"Module y" \ No newline at end of file
diff --git a/tests/root/rimg.png b/tests/root/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/root/rimg.png
+++ b/tests/root/rimg.png
Binary files differ
diff --git a/tests/root/subdir/img.png b/tests/root/subdir/img.png
index 4c8f89929..a97e86d66 100644
--- a/tests/root/subdir/img.png
+++ b/tests/root/subdir/img.png
Binary files differ
diff --git a/tests/root/subdir/simg.png b/tests/root/subdir/simg.png
index 4c8f89929..a97e86d66 100644
--- a/tests/root/subdir/simg.png
+++ b/tests/root/subdir/simg.png
Binary files differ
diff --git a/tests/root/testtheme/static/staticimg.png b/tests/root/testtheme/static/staticimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/root/testtheme/static/staticimg.png
+++ b/tests/root/testtheme/static/staticimg.png
Binary files differ
diff --git a/tests/roots/test-add_enumerable_node/rimg.png b/tests/roots/test-add_enumerable_node/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-add_enumerable_node/rimg.png
+++ b/tests/roots/test-add_enumerable_node/rimg.png
Binary files differ
diff --git a/tests/roots/test-config/conf.py b/tests/roots/test-config/conf.py
index b6075e5cb..1e583d1e0 100644
--- a/tests/roots/test-config/conf.py
+++ b/tests/roots/test-config/conf.py
@@ -1,4 +1,4 @@
-from sphinx.config import string_classes
+from sphinx.config import string_classes, ENUM
value1 = 123 # wrong type
value2 = 123 # lambda with wrong type
@@ -45,3 +45,4 @@ def setup(app):
app.add_config_value('value14', None, False, string_classes)
app.add_config_value('value15', u'unicode', False)
app.add_config_value('value16', u'unicode', False)
+ app.add_config_value('value17', 'default', False, ENUM('default', 'one', 'two'))
diff --git a/tests/roots/test-directive-code/lineno_match.rst b/tests/roots/test-directive-code/lineno_match.rst
index 1015c8df7..42987609a 100644
--- a/tests/roots/test-directive-code/lineno_match.rst
+++ b/tests/roots/test-directive-code/lineno_match.rst
@@ -16,5 +16,11 @@ Literal Includes with Line Numbers Matching
:start-after: pass
:lineno-match:
+.. literalinclude:: literal.inc
+ :language: python
+ :start-at: class Bar:
+ :end-at: pass
+ :lineno-match:
+
.. literalinclude:: empty.inc
:lineno-match:
diff --git a/tests/roots/test-ext-autodoc/autodoc_dummy_module.py b/tests/roots/test-ext-autodoc/autodoc_dummy_module.py
new file mode 100644
index 000000000..c05d96e0d
--- /dev/null
+++ b/tests/roots/test-ext-autodoc/autodoc_dummy_module.py
@@ -0,0 +1,6 @@
+from dummy import *
+
+
+def test():
+ """Dummy function using dummy.*"""
+ dummy_function()
diff --git a/tests/roots/test-ext-autodoc/conf.py b/tests/roots/test-ext-autodoc/conf.py
new file mode 100644
index 000000000..01e6dcc75
--- /dev/null
+++ b/tests/roots/test-ext-autodoc/conf.py
@@ -0,0 +1,12 @@
+import sys, os
+
+sys.path.insert(0, os.path.abspath('.'))
+
+extensions = ['sphinx.ext.autodoc']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+autodoc_mock_imports = [
+ 'dummy'
+]
diff --git a/tests/roots/test-ext-autodoc/contents.rst b/tests/roots/test-ext-autodoc/contents.rst
new file mode 100644
index 000000000..b808eafda
--- /dev/null
+++ b/tests/roots/test-ext-autodoc/contents.rst
@@ -0,0 +1,3 @@
+
+.. automodule:: autodoc_dummy_module
+ :members:
diff --git a/tests/roots/test-ext-graphviz/index.rst b/tests/roots/test-ext-graphviz/index.rst
index b778307e3..ab86e2a5a 100644
--- a/tests/roots/test-ext-graphviz/index.rst
+++ b/tests/roots/test-ext-graphviz/index.rst
@@ -19,3 +19,9 @@ Hello |graph| graphviz world
.. graphviz:: graph.dot
+
+.. digraph:: bar
+ :align: right
+ :caption: on right
+
+ foo -> bar
diff --git a/tests/roots/test-ext-inheritance_diagram/index.rst b/tests/roots/test-ext-inheritance_diagram/index.rst
index 876996ca8..777192bd7 100644
--- a/tests/roots/test-ext-inheritance_diagram/index.rst
+++ b/tests/roots/test-ext-inheritance_diagram/index.rst
@@ -3,3 +3,6 @@ test-ext-inheritance_diagram
============================
.. inheritance-diagram:: test.Foo
+
+.. inheritance-diagram:: test.Foo
+ :caption: Test Foo!
diff --git a/tests/roots/test-ext-math/index.rst b/tests/roots/test-ext-math/index.rst
index 02f50c20a..9d16824f6 100644
--- a/tests/roots/test-ext-math/index.rst
+++ b/tests/roots/test-ext-math/index.rst
@@ -1,6 +1,10 @@
Test Math
=========
+.. toctree::
+
+ math
+
.. math:: a^2+b^2=c^2
Inline :math:`E=mc^2`
diff --git a/tests/roots/test-ext-todo/bar.rst b/tests/roots/test-ext-todo/bar.rst
new file mode 100644
index 000000000..6804a68c1
--- /dev/null
+++ b/tests/roots/test-ext-todo/bar.rst
@@ -0,0 +1,4 @@
+bar
+===
+
+.. todo:: todo in bar
diff --git a/tests/roots/test-ext-todo/conf.py b/tests/roots/test-ext-todo/conf.py
new file mode 100644
index 000000000..c67a86c5a
--- /dev/null
+++ b/tests/roots/test-ext-todo/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+extensions = ['sphinx.ext.todo']
+master_doc = 'index'
diff --git a/tests/roots/test-ext-todo/foo.rst b/tests/roots/test-ext-todo/foo.rst
new file mode 100644
index 000000000..269199977
--- /dev/null
+++ b/tests/roots/test-ext-todo/foo.rst
@@ -0,0 +1,4 @@
+foo
+===
+
+.. todo:: todo in foo
diff --git a/tests/roots/test-ext-todo/index.rst b/tests/roots/test-ext-todo/index.rst
new file mode 100644
index 000000000..6b95f73fd
--- /dev/null
+++ b/tests/roots/test-ext-todo/index.rst
@@ -0,0 +1,9 @@
+test for sphinx.ext.todo
+========================
+
+.. toctree::
+
+ foo
+ bar
+
+.. todolist::
diff --git a/tests/roots/test-footnotes/index.rst b/tests/roots/test-footnotes/index.rst
index 3a8bc25c5..a714f9e22 100644
--- a/tests/roots/test-footnotes/index.rst
+++ b/tests/roots/test-footnotes/index.rst
@@ -76,15 +76,17 @@ Footnote in term [#]_
.. [#] Foot note in table
-.. list-table:: footnote [#]_ in caption of longtable
+.. list-table:: footnote [#]_ in caption [#]_ of longtable
:widths: 1 1
:header-rows: 1
* - name
- desc
- * - a
- - b
- * - a
+ * - This is a reference to the code-block in the footnote:
+ :ref:`codeblockinfootnote`
+ - This is one more footnote with some code in it [#]_.
+ * - This is a reference to the other code block:
+ :ref:`codeblockinanotherfootnote`
- b
* - a
- b
@@ -148,3 +150,21 @@ Footnote in term [#]_
- b
.. [#] Foot note in longtable
+
+.. [#] Second footnote in caption of longtable
+
+ .. code-block:: python
+ :caption: I am in a footnote
+ :name: codeblockinfootnote
+
+ def foo(x,y):
+ return x+y
+
+.. [#] Third footnote in longtable
+
+ .. code-block:: python
+ :caption: I am also in a footnote
+ :name: codeblockinanotherfootnote
+
+ def bar(x,y):
+ return x+y
diff --git a/tests/roots/test-footnotes/rimg.png b/tests/roots/test-footnotes/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-footnotes/rimg.png
+++ b/tests/roots/test-footnotes/rimg.png
Binary files differ
diff --git a/tests/roots/test-html_extra_path/conf.py b/tests/roots/test-html_assets/conf.py
index 53ee62197..a17e417a3 100644
--- a/tests/roots/test-html_extra_path/conf.py
+++ b/tests/roots/test-html_assets/conf.py
@@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
+project = 'Sphinx'
+version = '1.4.4'
+html_static_path = ['static', 'subdir']
html_extra_path = ['extra', 'subdir']
exclude_patterns = ['**/_build', '**/.htpasswd']
diff --git a/tests/roots/test-html_extra_path/extra/.htaccess b/tests/roots/test-html_assets/extra/.htaccess
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/extra/.htaccess
+++ b/tests/roots/test-html_assets/extra/.htaccess
diff --git a/tests/roots/test-html_extra_path/extra/.htpasswd b/tests/roots/test-html_assets/extra/.htpasswd
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/extra/.htpasswd
+++ b/tests/roots/test-html_assets/extra/.htpasswd
diff --git a/tests/roots/test-html_assets/extra/API.html_t b/tests/roots/test-html_assets/extra/API.html_t
new file mode 100644
index 000000000..34ecd9df1
--- /dev/null
+++ b/tests/roots/test-html_assets/extra/API.html_t
@@ -0,0 +1 @@
+{{ project }}-{{ version }}
diff --git a/tests/roots/test-html_extra_path/extra/css/style.css b/tests/roots/test-html_assets/extra/css/style.css
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/extra/css/style.css
+++ b/tests/roots/test-html_assets/extra/css/style.css
diff --git a/tests/roots/test-html_assets/extra/rimg.png b/tests/roots/test-html_assets/extra/rimg.png
new file mode 100644
index 000000000..fda6cd29e
--- /dev/null
+++ b/tests/roots/test-html_assets/extra/rimg.png
Binary files differ
diff --git a/tests/roots/test-html_extra_path/extra/API.html_t b/tests/roots/test-html_assets/extra/subdir/.htaccess
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/extra/API.html_t
+++ b/tests/roots/test-html_assets/extra/subdir/.htaccess
diff --git a/tests/roots/test-html_extra_path/subdir/_build/index.html b/tests/roots/test-html_assets/extra/subdir/.htpasswd
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/subdir/_build/index.html
+++ b/tests/roots/test-html_assets/extra/subdir/.htpasswd
diff --git a/tests/roots/test-html_extra_path/index.rst b/tests/roots/test-html_assets/index.rst
index 6d5619455..6d5619455 100644
--- a/tests/roots/test-html_extra_path/index.rst
+++ b/tests/roots/test-html_assets/index.rst
diff --git a/tests/roots/test-html_assets/static/.htaccess b/tests/roots/test-html_assets/static/.htaccess
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/.htaccess
diff --git a/tests/roots/test-html_assets/static/.htpasswd b/tests/roots/test-html_assets/static/.htpasswd
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/.htpasswd
diff --git a/tests/roots/test-html_assets/static/API.html_t b/tests/roots/test-html_assets/static/API.html_t
new file mode 100644
index 000000000..34ecd9df1
--- /dev/null
+++ b/tests/roots/test-html_assets/static/API.html_t
@@ -0,0 +1 @@
+{{ project }}-{{ version }}
diff --git a/tests/roots/test-html_assets/static/css/style.css b/tests/roots/test-html_assets/static/css/style.css
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/css/style.css
diff --git a/tests/roots/test-html_assets/static/rimg.png b/tests/roots/test-html_assets/static/rimg.png
new file mode 100644
index 000000000..fda6cd29e
--- /dev/null
+++ b/tests/roots/test-html_assets/static/rimg.png
Binary files differ
diff --git a/tests/roots/test-html_assets/static/subdir/.htaccess b/tests/roots/test-html_assets/static/subdir/.htaccess
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/subdir/.htaccess
diff --git a/tests/roots/test-html_assets/static/subdir/.htpasswd b/tests/roots/test-html_assets/static/subdir/.htpasswd
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/subdir/.htpasswd
diff --git a/tests/roots/test-html_assets/subdir/_build/index.html b/tests/roots/test-html_assets/subdir/_build/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/subdir/_build/index.html
diff --git a/tests/roots/test-html_assets/subdir/background.png b/tests/roots/test-html_assets/subdir/background.png
new file mode 100644
index 000000000..fda6cd29e
--- /dev/null
+++ b/tests/roots/test-html_assets/subdir/background.png
Binary files differ
diff --git a/tests/roots/test-html_extra_path/extra/rimg.png b/tests/roots/test-html_extra_path/extra/rimg.png
deleted file mode 100644
index 1081dc143..000000000
--- a/tests/roots/test-html_extra_path/extra/rimg.png
+++ /dev/null
Binary files differ
diff --git a/tests/roots/test-html_extra_path/subdir/background.png b/tests/roots/test-html_extra_path/subdir/background.png
deleted file mode 100644
index 1081dc143..000000000
--- a/tests/roots/test-html_extra_path/subdir/background.png
+++ /dev/null
Binary files differ
diff --git a/tests/roots/test-image-glob/img.ja.png b/tests/roots/test-image-glob/img.ja.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-image-glob/img.ja.png
+++ b/tests/roots/test-image-glob/img.ja.png
Binary files differ
diff --git a/tests/roots/test-image-glob/img.png b/tests/roots/test-image-glob/img.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-image-glob/img.png
+++ b/tests/roots/test-image-glob/img.png
Binary files differ
diff --git a/tests/roots/test-image-glob/img.zh.png b/tests/roots/test-image-glob/img.zh.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-image-glob/img.zh.png
+++ b/tests/roots/test-image-glob/img.zh.png
Binary files differ
diff --git a/tests/roots/test-image-glob/rimg.png b/tests/roots/test-image-glob/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-glob/rimg.png
+++ b/tests/roots/test-image-glob/rimg.png
Binary files differ
diff --git a/tests/roots/test-image-glob/rimg.xx.png b/tests/roots/test-image-glob/rimg.xx.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-glob/rimg.xx.png
+++ b/tests/roots/test-image-glob/rimg.xx.png
Binary files differ
diff --git a/tests/roots/test-image-glob/subdir/rimg.png b/tests/roots/test-image-glob/subdir/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-glob/subdir/rimg.png
+++ b/tests/roots/test-image-glob/subdir/rimg.png
Binary files differ
diff --git a/tests/roots/test-image-glob/subdir/rimg.xx.png b/tests/roots/test-image-glob/subdir/rimg.xx.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-glob/subdir/rimg.xx.png
+++ b/tests/roots/test-image-glob/subdir/rimg.xx.png
Binary files differ
diff --git a/tests/roots/test-image-glob/testimäge.png b/tests/roots/test-image-glob/testimäge.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-image-glob/testimäge.png
+++ b/tests/roots/test-image-glob/testimäge.png
Binary files differ
diff --git a/tests/roots/test-image-in-section/pic.png b/tests/roots/test-image-in-section/pic.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-in-section/pic.png
+++ b/tests/roots/test-image-in-section/pic.png
Binary files differ
diff --git a/tests/roots/test-intl/contents.po b/tests/roots/test-intl/contents.po
new file mode 100644
index 000000000..76ef049f0
--- /dev/null
+++ b/tests/roots/test-intl/contents.po
@@ -0,0 +1,26 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010, Georg Brandl & Team
+# This file is distributed under the same license as the Sphinx <Tests> package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx <Tests> 0.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-12-16 14:11+0000\n"
+"PO-Revision-Date: 2012-12-18 06:14+0900\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Table of Contents"
+msgstr "TABLE OF CONTENTS"
+
+msgid "testdata for i18n"
+msgstr "TESTDATA FOR I18N"
+
+msgid "i18n, sphinx, markup"
+msgstr "I18N, SPHINX, MARKUP"
diff --git a/tests/roots/test-intl/contents.txt b/tests/roots/test-intl/contents.txt
index 8882137f3..e2336856c 100644
--- a/tests/roots/test-intl/contents.txt
+++ b/tests/roots/test-intl/contents.txt
@@ -1,9 +1,14 @@
CONTENTS
========
+.. meta::
+ :description: testdata for i18n
+ :keywords: i18n, sphinx, markup
+
.. toctree::
:maxdepth: 2
:numbered:
+ :caption: Table of Contents
subdir/contents
bom
diff --git a/tests/roots/test-intl/i18n.png b/tests/roots/test-intl/i18n.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-intl/i18n.png
+++ b/tests/roots/test-intl/i18n.png
Binary files differ
diff --git a/tests/roots/test-intl/img.png b/tests/roots/test-intl/img.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-intl/img.png
+++ b/tests/roots/test-intl/img.png
Binary files differ
diff --git a/tests/roots/test-intl/only.po b/tests/roots/test-intl/only.po
new file mode 100644
index 000000000..43eb7d60f
--- /dev/null
+++ b/tests/roots/test-intl/only.po
@@ -0,0 +1,29 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010, Georg Brandl & Team
+# This file is distributed under the same license as the Sphinx <Tests> package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx <Tests> 0.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-04 13:06+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Only directive"
+msgstr "ONLY DIRECTIVE"
+
+msgid "In HTML."
+msgstr "IN HTML."
+
+msgid "In LaTeX."
+msgstr "IN LATEX."
+
+msgid "In both."
+msgstr "IN BOTH."
diff --git a/tests/roots/test-intl/only.txt b/tests/roots/test-intl/only.txt
new file mode 100644
index 000000000..2c8990e5f
--- /dev/null
+++ b/tests/roots/test-intl/only.txt
@@ -0,0 +1,14 @@
+Only directive
+--------------
+
+.. only:: html
+
+ In HTML.
+
+.. only:: latex
+
+ In LaTeX.
+
+.. only:: html or latex
+
+ In both.
diff --git a/tests/roots/test-keep_warnings/conf.py b/tests/roots/test-keep_warnings/conf.py
new file mode 100644
index 000000000..d0db3db83
--- /dev/null
+++ b/tests/roots/test-keep_warnings/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
+keep_warnings = True
diff --git a/tests/roots/test-keep_warnings/index.rst b/tests/roots/test-keep_warnings/index.rst
new file mode 100644
index 000000000..1e2d5977f
--- /dev/null
+++ b/tests/roots/test-keep_warnings/index.rst
@@ -0,0 +1,2 @@
+keep_warnings
+=====
diff --git a/tests/roots/test-linkcheck/conf.py b/tests/roots/test-linkcheck/conf.py
new file mode 100644
index 000000000..ae8ef24b7
--- /dev/null
+++ b/tests/roots/test-linkcheck/conf.py
@@ -0,0 +1,4 @@
+master_doc = 'links'
+source_suffix = '.txt'
+exclude_patterns = ['_build']
+linkcheck_anchors = True
diff --git a/tests/roots/test-linkcheck/links.txt b/tests/roots/test-linkcheck/links.txt
new file mode 100644
index 000000000..36376bef4
--- /dev/null
+++ b/tests/roots/test-linkcheck/links.txt
@@ -0,0 +1,11 @@
+This is from CPython documentation.
+
+* Also, if there is a `default namespace <https://www.w3.org/TR/2006/REC-xml-names-20060816/#defaulting>`__, that full URI gets prepended to all of the non-prefixed tags.
+
+* The URL having anchor: `http://www.sphinx-doc.org/en/1.4.8/tutorial.html#install-sphinx`_
+
+Some additional anchors to exercise ignore code
+
+* `Example Bar invalid <http://example.com/#!bar>`_
+* `Example Bar invalid <http://example.com#!bar>`_ tests that default ignore anchor of #! does not need to be prefixed with /
+* `Example Bar invalid <http://example.com/#top>`_
diff --git a/tests/roots/test-maxlistdepth/conf.py b/tests/roots/test-maxlistdepth/conf.py
new file mode 100644
index 000000000..5a43b67bf
--- /dev/null
+++ b/tests/roots/test-maxlistdepth/conf.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
+html_theme = 'classic'
+exclude_patterns = ['_build']
+
+latex_documents = [
+ ('index', 'SphinxTests.tex', 'Testing maxlistdepth=10',
+ 'Georg Brandl', 'howto'),
+ ]
+
+latex_elements = {
+ 'maxlistdepth': '10',
+}
diff --git a/tests/roots/test-maxlistdepth/index.rst b/tests/roots/test-maxlistdepth/index.rst
new file mode 100644
index 000000000..5d9bc2193
--- /dev/null
+++ b/tests/roots/test-maxlistdepth/index.rst
@@ -0,0 +1,57 @@
+test-maxlistdepth
+=================
+
+
+1. 1
+
+ 1. 2
+
+ 1. 3
+
+ 1. 4
+
+ 1. 5
+
+ 1. 6
+
+ 1. 7
+
+ 1. 8
+
+ 1. 9
+
+ 10a
+
+ - 10b
+
+ .. code-block:: python
+
+ def foo():
+
+
+- 1
+
+ - 2
+
+ - 3
+
+ - 4
+
+ - 5
+
+ - 6
+
+ - 7
+
+ - 8
+
+ 1. 9
+
+ 10a
+
+ 1. 10b
+
+ .. code-block:: python
+
+ def foo():
+
diff --git a/tests/roots/test-numfig/bar.rst b/tests/roots/test-numfig/bar.rst
index f86e7475a..c4367c5b8 100644
--- a/tests/roots/test-numfig/bar.rst
+++ b/tests/roots/test-numfig/bar.rst
@@ -1,7 +1,11 @@
+.. _bar:
+
===
Bar
===
+.. _bar_a:
+
Bar A
=====
@@ -37,9 +41,13 @@ Bar A
print('hello world')
+.. _bar_b:
+
Bar B
=====
+.. _bar_b1:
+
Bar B1
------
diff --git a/tests/roots/test-numfig/baz.rst b/tests/roots/test-numfig/baz.rst
index 42fcb06d1..3ac684b43 100644
--- a/tests/roots/test-numfig/baz.rst
+++ b/tests/roots/test-numfig/baz.rst
@@ -1,3 +1,5 @@
+.. _baz_a:
+
Baz A
-----
diff --git a/tests/roots/test-numfig/foo.rst b/tests/roots/test-numfig/foo.rst
index ef713574a..6b6a8651c 100644
--- a/tests/roots/test-numfig/foo.rst
+++ b/tests/roots/test-numfig/foo.rst
@@ -1,3 +1,5 @@
+.. _foo:
+
===
Foo
===
@@ -16,6 +18,8 @@ Foo
print('hello world')
+.. _foo_a:
+
Foo A
=====
@@ -47,12 +51,18 @@ Foo A
print('hello world')
+.. _foo_a1:
+
Foo A1
------
+.. _foo_b:
+
Foo B
=====
+.. _foo_b1:
+
Foo B1
------
diff --git a/tests/roots/test-numfig/index.rst b/tests/roots/test-numfig/index.rst
index 6dd39a93a..939903839 100644
--- a/tests/roots/test-numfig/index.rst
+++ b/tests/roots/test-numfig/index.rst
@@ -1,3 +1,5 @@
+.. _index:
+
test-tocdepth
=============
@@ -48,5 +50,10 @@ test-tocdepth
* Table.2.2 is :numref:`Table:%s <table22>`
* List.1 is :numref:`CODE_1`
* List.2.2 is :numref:`Code-%s <CODE22>`
+* Section.1 is :numref:`foo`
+* Section.2.1 is :numref:`bar_a`
+* Unnumbered section is :numref:`index`
* Invalid numfig_format 01: :numref:`invalid <fig1>`
* Invalid numfig_format 02: :numref:`Fig %s %s <fig1>`
+* Fig.1 is :numref:`Fig.{number} {name} <fig1>`
+* Section.1 is :numref:`Sect.{number} {name} <foo>`
diff --git a/tests/roots/test-numfig/rimg.png b/tests/roots/test-numfig/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-numfig/rimg.png
+++ b/tests/roots/test-numfig/rimg.png
Binary files differ
diff --git a/tests/roots/test-refonly_bullet_list/conf.py b/tests/roots/test-refonly_bullet_list/conf.py
new file mode 100644
index 000000000..68357c9a4
--- /dev/null
+++ b/tests/roots/test-refonly_bullet_list/conf.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
+html_compact_lists = False
+
+latex_documents = [
+ (master_doc, 'test.tex', 'The basic Sphinx documentation for testing', 'Sphinx', 'report')
+]
diff --git a/tests/roots/test-refonly_bullet_list/index.rst b/tests/roots/test-refonly_bullet_list/index.rst
new file mode 100644
index 000000000..9d8539dba
--- /dev/null
+++ b/tests/roots/test-refonly_bullet_list/index.rst
@@ -0,0 +1,14 @@
+test-refonly_bullet_list
+========================
+
+List A:
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+List B:
+
+* Hello
+* Sphinx
+* World
diff --git a/tests/roots/test-search/conf.py b/tests/roots/test-search/conf.py
new file mode 100644
index 000000000..38b8b28c5
--- /dev/null
+++ b/tests/roots/test-search/conf.py
@@ -0,0 +1,3 @@
+master_doc = 'index'
+exclude_patterns = ['_build']
+html_search_language = 'en'
diff --git a/tests/roots/test-search/index.rst b/tests/roots/test-search/index.rst
new file mode 100644
index 000000000..1e0dd93de
--- /dev/null
+++ b/tests/roots/test-search/index.rst
@@ -0,0 +1,30 @@
+meta keywords
+=============
+
+.. meta::
+ :keywords lang=en: findthiskey, thistoo, notgerman
+ :keywords: thisonetoo
+ :keywords lang=de: onlygerman, onlytoogerman
+ :description: thisnoteither
+
+Stemmer
+=======
+
+zfs
+findthisstemmedkey
+
+textinheading
+
+International
+
+.. toctree::
+
+ tocitem
+
+.. raw:: html
+
+ <span class="raw">rawword"</span>
+
+.. raw:: latex
+
+ latex_keyword
diff --git a/tests/roots/test-search/tocitem.rst b/tests/roots/test-search/tocitem.rst
new file mode 100644
index 000000000..61c42a242
--- /dev/null
+++ b/tests/roots/test-search/tocitem.rst
@@ -0,0 +1,10 @@
+heading 1
+=========
+
+lorem ipsum
+
+
+textinheading
+=============
+
+lorem ipsum \ No newline at end of file
diff --git a/tests/roots/test-toctree-glob/index.rst b/tests/roots/test-toctree-glob/index.rst
index 079cd6027..a3c198ce3 100644
--- a/tests/roots/test-toctree-glob/index.rst
+++ b/tests/roots/test-toctree-glob/index.rst
@@ -1,8 +1,24 @@
test-toctree-glob
=================
+normal order
+------------
+
+.. toctree::
+ :glob:
+
+ foo
+ bar/index
+ bar/*
+ baz
+ qux/index
+
+reversed order
+-------------
+
.. toctree::
:glob:
+ :reversed:
foo
bar/index
diff --git a/tests/roots/test-toctree-maxdepth/qux.rst b/tests/roots/test-toctree-maxdepth/qux.rst
new file mode 100644
index 000000000..35e9ac127
--- /dev/null
+++ b/tests/roots/test-toctree-maxdepth/qux.rst
@@ -0,0 +1,9 @@
+test-toctree-max-depth
+======================
+
+.. toctree::
+ :numbered:
+ :maxdepth: 4
+
+ foo
+ bar
diff --git a/tests/roots/test-toctree/bar.rst b/tests/roots/test-toctree/bar.rst
new file mode 100644
index 000000000..1cccd3cb7
--- /dev/null
+++ b/tests/roots/test-toctree/bar.rst
@@ -0,0 +1,2 @@
+bar
+===
diff --git a/tests/roots/test-toctree/baz.rst b/tests/roots/test-toctree/baz.rst
new file mode 100644
index 000000000..52e2e72ac
--- /dev/null
+++ b/tests/roots/test-toctree/baz.rst
@@ -0,0 +1,2 @@
+baz
+===
diff --git a/tests/roots/test-toctree/conf.py b/tests/roots/test-toctree/conf.py
new file mode 100644
index 000000000..31e7a6ed4
--- /dev/null
+++ b/tests/roots/test-toctree/conf.py
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
+
+latex_documents = [
+ (master_doc, 'test.tex', 'The basic Sphinx documentation for testing', 'Sphinx', 'report')
+]
diff --git a/tests/roots/test-toctree/foo.rst b/tests/roots/test-toctree/foo.rst
new file mode 100644
index 000000000..49f4d4b97
--- /dev/null
+++ b/tests/roots/test-toctree/foo.rst
@@ -0,0 +1,15 @@
+foo
+===
+
+.. toctree::
+
+ quux
+
+foo.1
+-----
+
+foo.1-1
+^^^^^^^
+
+foo.2
+-----
diff --git a/tests/roots/test-toctree/index.rst b/tests/roots/test-toctree/index.rst
new file mode 100644
index 000000000..dc7fd2e4a
--- /dev/null
+++ b/tests/roots/test-toctree/index.rst
@@ -0,0 +1,54 @@
+.. Sphinx Tests documentation master file, created by sphinx-quickstart on Wed Jun 4 23:49:58 2008.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to Sphinx Tests's documentation!
+========================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+ :caption: Table of Contents
+ :name: mastertoc
+
+ foo
+ bar
+ http://sphinx-doc.org/
+
+.. only:: html
+
+ Section for HTML
+ ----------------
+
+ .. toctree::
+
+ baz
+
+----------
+subsection
+----------
+
+subsubsection
+-------------
+
+Test for issue #1157
+====================
+
+This used to crash:
+
+.. toctree::
+
+.. toctree::
+ :hidden:
+
+ Latest reference <http://sphinx-doc.org/latest/>
+ Python <http://python.org/>
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/tests/roots/test-toctree/quux.rst b/tests/roots/test-toctree/quux.rst
new file mode 100644
index 000000000..07dd0a0a3
--- /dev/null
+++ b/tests/roots/test-toctree/quux.rst
@@ -0,0 +1,2 @@
+quux
+====
diff --git a/tests/roots/test-toctree/qux.rst b/tests/roots/test-toctree/qux.rst
new file mode 100644
index 000000000..26176b947
--- /dev/null
+++ b/tests/roots/test-toctree/qux.rst
@@ -0,0 +1 @@
+qux.rst has no section title
diff --git a/tests/roots/test-toctree/tocdepth.rst b/tests/roots/test-toctree/tocdepth.rst
new file mode 100644
index 000000000..1069b4cb4
--- /dev/null
+++ b/tests/roots/test-toctree/tocdepth.rst
@@ -0,0 +1,15 @@
+:tocdepth: 2
+
+=======
+level 1
+=======
+
+level 2
+=======
+
+-------
+level 3
+-------
+
+level 4
+-------
diff --git a/tests/run.py b/tests/run.py
index 0ca6ad1ae..d2d3b9fc8 100755
--- a/tests/run.py
+++ b/tests/run.py
@@ -24,7 +24,7 @@ sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
# check dependencies before testing
print('Checking dependencies...')
for modname in ('nose', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
- 'snowballstemmer', 'babel'):
+ 'snowballstemmer', 'babel', 'html5lib'):
try:
__import__(modname)
except ImportError as err:
@@ -48,4 +48,4 @@ tempdir.makedirs()
print('Running Sphinx test suite (with Python %s)...' % sys.version.split()[0])
sys.stdout.flush()
-nose.main()
+nose.main(argv=sys.argv)
diff --git a/tests/test_api_translator.py b/tests/test_api_translator.py
index e8cfcb458..7a70fd4c8 100644
--- a/tests/test_api_translator.py
+++ b/tests/test_api_translator.py
@@ -57,7 +57,7 @@ def test_html_with_set_translator_for_html_(app, status, warning):
@with_app('html', testroot='api-set-translator',
- confoverrides={'html_translator_class': 'ext.ExtHTMLTranslator'})
+ confoverrides={'html_translator_class': 'translator.ExtHTMLTranslator'})
def test_html_with_set_translator_for_html_and_html_translator_class(
app, status, warning):
# use set_translator() and html_translator_class.
diff --git a/tests/test_apidoc.py b/tests/test_apidoc.py
index 596890041..ff6a147ca 100644
--- a/tests/test_apidoc.py
+++ b/tests/test_apidoc.py
@@ -44,6 +44,94 @@ def test_simple(tempdir):
@with_tempdir
+def test_pep_0420_enabled(tempdir):
+ codedir = rootdir / 'root' / 'pep_0420'
+ outdir = tempdir / 'out'
+ args = ['sphinx-apidoc', '-o', outdir, '-F', codedir, "--implicit-namespaces"]
+ apidoc.main(args)
+
+ assert (outdir / 'conf.py').isfile()
+ assert (outdir / 'a.b.c.rst').isfile()
+ assert (outdir / 'a.b.x.rst').isfile()
+
+ with open(outdir / 'a.b.c.rst') as f:
+ rst = f.read()
+ assert "a.b.c package\n" in rst
+ assert "automodule:: a.b.c.d\n" in rst
+ assert "automodule:: a.b.c\n" in rst
+
+ with open(outdir / 'a.b.x.rst') as f:
+ rst = f.read()
+ assert "a.b.x namespace\n" in rst
+ assert "automodule:: a.b.x.y\n" in rst
+ assert "automodule:: a.b.x\n" not in rst
+
+ @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)
+
+
+@with_tempdir
+def test_pep_0420_disabled(tempdir):
+ codedir = rootdir / 'root' / 'pep_0420'
+ outdir = tempdir / 'out'
+ args = ['sphinx-apidoc', '-o', outdir, '-F', codedir]
+ apidoc.main(args)
+
+ assert (outdir / 'conf.py').isfile()
+ assert not (outdir / 'a.b.c.rst').exists()
+ assert not (outdir / 'a.b.x.rst').exists()
+
+ @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)
+
+@with_tempdir
+def test_pep_0420_disabled_top_level_verify(tempdir):
+ codedir = rootdir / 'root' / 'pep_0420' / 'a' / 'b'
+ outdir = tempdir / 'out'
+ args = ['sphinx-apidoc', '-o', outdir, '-F', codedir]
+ apidoc.main(args)
+
+ assert (outdir / 'conf.py').isfile()
+ assert (outdir / 'c.rst').isfile()
+ assert not (outdir / 'x.rst').exists()
+
+ with open(outdir / 'c.rst') as f:
+ rst = f.read()
+ assert "c package\n" in rst
+ assert "automodule:: c.d\n" in rst
+ assert "automodule:: c\n" in rst
+
+ @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)
+
+@with_tempdir
def test_multibyte_parameters(tempdir):
codedir = rootdir / 'root'
outdir = tempdir / 'out'
diff --git a/tests/test_application.py b/tests/test_application.py
index 420680451..ad4f84870 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -14,7 +14,7 @@ from docutils import nodes
from sphinx.application import ExtensionError
from sphinx.domains import Domain
-from util import with_app, raises_msg
+from util import with_app, raises_msg, strip_escseq
@with_app()
@@ -60,20 +60,21 @@ def test_output(app, status, warning):
old_count = app._warncount
app.warn("Bad news!")
- assert warning.getvalue() == "WARNING: Bad news!\n"
+ assert strip_escseq(warning.getvalue()) == "WARNING: Bad news!\n"
assert app._warncount == old_count + 1
@with_app()
def test_extensions(app, status, warning):
app.setup_extension('shutil')
- assert warning.getvalue().startswith("WARNING: extension 'shutil'")
+ assert strip_escseq(warning.getvalue()).startswith("WARNING: extension 'shutil'")
@with_app()
def test_extension_in_blacklist(app, status, warning):
app.setup_extension('sphinxjp.themecore')
- assert warning.getvalue().startswith("WARNING: the extension 'sphinxjp.themecore' was")
+ msg = strip_escseq(warning.getvalue())
+ assert msg.startswith("WARNING: the extension 'sphinxjp.themecore' was")
@with_app()
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 711e5e807..d2ba95608 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -14,6 +14,7 @@
from util import TestApp, Struct, raises, SkipTest # NOQA
from nose.tools import with_setup, eq_
+import enum
from six import StringIO
from docutils.statemachine import ViewList
@@ -825,6 +826,26 @@ def test_generate():
del directive.env.temp_data['autodoc:module']
del directive.env.ref_context['py:module']
+ # test members with enum attributes
+ directive.env.ref_context['py:module'] = 'test_autodoc'
+ options.inherited_members = False
+ options.undoc_members = False
+ options.members = ALL
+ assert_processes([
+ ('class', 'test_autodoc.EnumCls'),
+ ('attribute', 'test_autodoc.EnumCls.val1'),
+ ('attribute', 'test_autodoc.EnumCls.val2'),
+ ('attribute', 'test_autodoc.EnumCls.val3'),
+ ], 'class', 'EnumCls')
+ assert_result_contains(
+ ' :annotation: = 12', 'attribute', 'EnumCls.val1')
+ assert_result_contains(
+ ' :annotation: = 23', 'attribute', 'EnumCls.val2')
+ assert_result_contains(
+ ' :annotation: = 34', 'attribute', 'EnumCls.val3')
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+
# test descriptor class documentation
options.members = ['CustomDataDescriptor']
assert_result_contains('.. py:class:: CustomDataDescriptor(doc)',
@@ -832,6 +853,17 @@ def test_generate():
assert_result_contains(' .. py:method:: CustomDataDescriptor.meth()',
'module', 'test_autodoc')
+ # test mocked module imports
+ options.members = ['TestAutodoc']
+ options.undoc_members = False
+ assert_result_contains('.. py:class:: TestAutodoc',
+ 'module', 'autodoc_missing_imports')
+ assert_result_contains(' .. py:method:: TestAutodoc.decoratedMethod()',
+ 'module', 'autodoc_missing_imports')
+ options.members = ['decoratedFunction']
+ assert_result_contains('.. py:function:: decoratedFunction()',
+ 'module', 'autodoc_missing_imports')
+
# --- generate fodder ------------
__all__ = ['Class']
@@ -1020,12 +1052,24 @@ class InstAttCls(object):
"""Docstring for instance attribute InstAttCls.ia2."""
+class EnumCls(enum.Enum):
+ """
+ this is enum class
+ """
+
+ #: doc for val1
+ val1 = 12
+ val2 = 23 #: doc for val2
+ val3 = 34
+ """doc for val3"""
+
+
def test_type_hints():
from sphinx.ext.autodoc import formatargspec
from sphinx.util.inspect import getargspec
try:
- from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10
+ from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11
except (ImportError, SyntaxError):
raise SkipTest('Cannot import Python code with function annotations')
@@ -1052,16 +1096,19 @@ def test_type_hints():
# Keyword-only arguments
verify_arg_spec(f5, '(x: int, *, y: str, z: str) -> None')
+ # Keyword-only arguments with varargs
+ verify_arg_spec(f6, '(x: int, *args, y: str, z: str) -> None')
+
# Space around '=' for defaults
- verify_arg_spec(f6, '(x: int = None, y: dict = {}) -> None')
+ verify_arg_spec(f7, '(x: int = None, y: dict = {}) -> None')
# Callable types
- verify_arg_spec(f7, '(x: typing.Callable[[int, str], int]) -> None')
- verify_arg_spec(f8, '(x: typing.Callable) -> None')
+ verify_arg_spec(f8, '(x: typing.Callable[[int, str], int]) -> None')
+ verify_arg_spec(f9, '(x: typing.Callable) -> None')
# Tuple types
- verify_arg_spec(f9, '(x: typing.Tuple[int, str],'
- ' y: typing.Tuple[int, ...]) -> None')
+ verify_arg_spec(f10, '(x: typing.Tuple[int, str],'
+ ' y: typing.Tuple[int, ...]) -> None')
# Instance annotations
- verify_arg_spec(f10, '(x: CustomAnnotation, y: 123) -> None')
+ verify_arg_spec(f11, '(x: CustomAnnotation, y: 123) -> None')
diff --git a/tests/test_build.py b/tests/test_build.py
index 507a1cab3..cc34de2c1 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -13,6 +13,7 @@ from six import BytesIO
import pickle
from docutils import nodes
+import mock
from textwrap import dedent
from sphinx.errors import SphinxError
import sphinx.builders.linkcheck
@@ -25,14 +26,11 @@ except ImportError:
ManWriter = None
-class MockOpener(object):
- def open(self, req, **kwargs):
- class result(BytesIO):
- headers = None
- url = req.url
- return result()
-
-sphinx.builders.linkcheck.opener = MockOpener()
+def request_session_head(url, **kwargs):
+ response = mock.Mock()
+ response.status_code = 200
+ response.url = url
+ return response
def verify_build(buildername, srcdir):
@@ -68,12 +66,15 @@ def test_build_all():
""" % {'test_name': test_name})
)
- # note: no 'html' - if it's ok with dirhtml it's ok with html
- for buildername in ['dirhtml', 'singlehtml', 'latex', 'texinfo', 'pickle',
- 'json', 'text', 'htmlhelp', 'qthelp', 'epub', 'epub3',
- 'applehelp', 'changes', 'xml', 'pseudoxml', 'man',
- 'linkcheck']:
- yield verify_build, buildername, srcdir
+ with mock.patch('sphinx.builders.linkcheck.requests') as requests:
+ requests.head = request_session_head
+
+ # note: no 'html' - if it's ok with dirhtml it's ok with html
+ for buildername in ['dirhtml', 'singlehtml', 'latex', 'texinfo', 'pickle',
+ 'json', 'text', 'htmlhelp', 'qthelp', 'epub2', 'epub',
+ 'applehelp', 'changes', 'xml', 'pseudoxml', 'man',
+ 'linkcheck']:
+ yield verify_build, buildername, srcdir
@with_tempdir
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index d77867c0e..d8aff88ab 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -13,13 +13,16 @@ import os
import re
from six import PY3, iteritems
-from six.moves import html_entities
from sphinx import __display_version__
-from util import remove_unicode_literals, gen_with_app, with_app
-from etree13 import ElementTree as ET
+from util import remove_unicode_literals, gen_with_app, with_app, strip_escseq
+from etree13 import ElementTree
+from html5lib import getTreeBuilder, HTMLParser
+TREE_BUILDER = getTreeBuilder('etree', implementation=ElementTree)
+HTML_PARSER = HTMLParser(TREE_BUILDER, namespaceHTMLElements=False)
+
ENV_WARNINGS = """\
(%(root)s/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
WARNING: duplicate object description of autodoc_fodder.MarkupError, other \
@@ -65,6 +68,7 @@ HTML_XPATH = {
(".//img[@src='_images/img1.png']", ''),
(".//img[@src='_images/simg.png']", ''),
(".//img[@src='_images/svgimg.svg']", ''),
+ (".//a[@href='_sources/images.txt']", ''),
],
'subdir/images.html': [
(".//img[@src='../_images/img1.png']", ''),
@@ -174,7 +178,7 @@ HTML_XPATH = {
# ``seealso`` directive
(".//div/p[@class='first admonition-title']", 'See also'),
# a ``hlist`` directive
- (".//table[@class='hlist']/tr/td/ul/li", '^This$'),
+ (".//table[@class='hlist']/tbody/tr/td/ul/li", '^This$'),
# a ``centered`` directive
(".//p[@class='centered']/strong", 'LICENSE'),
# a glossary
@@ -203,6 +207,7 @@ HTML_XPATH = {
# docfields
(".//a[@class='reference internal'][@href='#TimeInt']/em", 'TimeInt'),
(".//a[@class='reference internal'][@href='#Time']", 'Time'),
+ (".//a[@class='reference internal'][@href='#errmod.Error']/strong", 'Error'),
# C references
(".//span[@class='pre']", 'CFunction()'),
(".//a[@href='#c.Sphinx_DoSomething']", ''),
@@ -235,10 +240,15 @@ HTML_XPATH = {
(".//td[@class='field-body']/ul/li/em", '^DuplicateType$'),
(".//td[@class='field-body']/ul/li/em", tail_check(r'.* Some parameter')),
# others
- (".//a[@class='reference internal'][@href='#cmdoption-perl-arg-+p']/code/span",
+ (".//a[@class='reference internal'][@href='#cmdoption-perl-arg-p']/code/span",
'perl'),
- (".//a[@class='reference internal'][@href='#cmdoption-perl-arg-+p']/code/span",
+ (".//a[@class='reference internal'][@href='#cmdoption-perl-arg-p']/code/span",
'\+p'),
+ (".//a[@class='reference internal'][@href='#cmdoption-perl-plugin-option']/code/span",
+ '--plugin.option'),
+ (".//a[@class='reference internal'][@href='#cmdoption-perl-arg-create-auth-token']"
+ "/code/span",
+ 'create-auth-token'),
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-arg']/code/span",
'arg'),
(".//a[@class='reference internal'][@href='#cmdoption-hg-arg-commit']/code/span",
@@ -297,7 +307,7 @@ HTML_XPATH = {
(".//a/strong", "[1]"),
(".//a/strong", "Other"),
(".//a", "entry"),
- (".//dt/a", "double"),
+ (".//li/a", "double"),
],
'footnote.html': [
(".//a[@class='footnote-reference'][@href='#id7'][@id='id1']", r"\[1\]"),
@@ -315,25 +325,11 @@ HTML_XPATH = {
],
'otherext.html': [
(".//h1", "Generated section"),
+ (".//a[@href='_sources/otherext.foo.txt']", ''),
]
}
-class NslessParser(ET.XMLParser):
- """XMLParser that throws away namespaces in tag names."""
-
- def _fixname(self, key):
- try:
- return self._names[key]
- except KeyError:
- name = key
- br = name.find('}')
- if br > 0:
- name = name[br+1:]
- self._names[key] = name = self._fixtext(name)
- return name
-
-
def check_xpath(etree, fname, path, check, be_found=True):
nodes = list(etree.findall(path))
if check is None:
@@ -394,8 +390,7 @@ def check_extra_entries(outdir):
@with_app(buildername='html', testroot='warnings', freshenv=True)
def test_html_warnings(app, status, warning):
app.builder.build_all()
-
- html_warnings = warning.getvalue().replace(os.sep, '/')
+ html_warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
html_warnings_exp = HTML_WARNINGS % {
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(html_warnings_exp + '$', html_warnings), \
@@ -409,10 +404,8 @@ def test_html_warnings(app, status, warning):
def test_html_output(app, status, warning):
app.builder.build_all()
for fname, paths in iteritems(HTML_XPATH):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for path, check in paths:
yield check_xpath, etree, fname, path, check
@@ -459,10 +452,8 @@ def test_tocdepth(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -501,10 +492,8 @@ def test_tocdepth_singlehtml(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -514,10 +503,11 @@ def test_tocdepth_singlehtml(app, status, warning):
def test_numfig_disabled(app, status, warning):
app.builder.build_all()
- assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.'
- in warning.getvalue())
- assert 'index.rst:51: WARNING: invalid numfig_format: invalid' not in warning.getvalue()
- assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' not in warning.getvalue()
+ warnings = warning.getvalue()
+ assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' in warnings
+ assert 'index.rst:55: WARNING: no number is assigned for section: index' not in warnings
+ assert 'index.rst:56: WARNING: invalid numfig_format: invalid' not in warnings
+ assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' not in warnings
expects = {
'index.html': [
@@ -532,6 +522,10 @@ def test_numfig_disabled(app, status, warning):
(".//li/code/span", '^Table:%s$', True),
(".//li/code/span", '^CODE_1$', True),
(".//li/code/span", '^Code-%s$', True),
+ (".//li/code/span", '^foo$', True),
+ (".//li/code/span", '^bar_a$', True),
+ (".//li/code/span", '^Fig.{number}$', True),
+ (".//li/code/span", '^Sect.{number}$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
@@ -557,10 +551,8 @@ def test_numfig_disabled(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -575,10 +567,11 @@ def test_numfig_without_numbered_toctree(app, status, warning):
(app.srcdir / 'index.rst').write_text(index, encoding='utf-8')
app.builder.build_all()
- assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.'
- not in warning.getvalue())
- assert 'index.rst:51: WARNING: invalid numfig_format: invalid' in warning.getvalue()
- assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' in warning.getvalue()
+ warnings = warning.getvalue()
+ assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' not in warnings
+ assert 'index.rst:55: WARNING: no number is assigned for section: index' in warnings
+ assert 'index.rst:56: WARNING: invalid numfig_format: invalid' in warnings
+ assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' in warnings
expects = {
'index.html': [
@@ -600,6 +593,10 @@ def test_numfig_without_numbered_toctree(app, status, warning):
(".//li/a/span", '^Table:6$', True),
(".//li/a/span", '^Listing 9$', True),
(".//li/a/span", '^Code-6$', True),
+ (".//li/code/span", '^foo$', True),
+ (".//li/code/span", '^bar_a$', True),
+ (".//li/a/span", '^Fig.9 should be Fig.1$', True),
+ (".//li/code/span", '^Sect.{number}$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
@@ -658,10 +655,8 @@ def test_numfig_without_numbered_toctree(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -672,10 +667,11 @@ def test_numfig_without_numbered_toctree(app, status, warning):
def test_numfig_with_numbered_toctree(app, status, warning):
app.builder.build_all()
- assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.'
- not in warning.getvalue())
- assert 'index.rst:51: WARNING: invalid numfig_format: invalid' in warning.getvalue()
- assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' in warning.getvalue()
+ warnings = warning.getvalue()
+ assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' not in warnings
+ assert 'index.rst:55: WARNING: no number is assigned for section: index' in warnings
+ assert 'index.rst:56: WARNING: invalid numfig_format: invalid' in warnings
+ assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' in warnings
expects = {
'index.html': [
@@ -697,6 +693,10 @@ def test_numfig_with_numbered_toctree(app, status, warning):
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.2$', True),
+ (".//li/a/span", '^Section.1$', True),
+ (".//li/a/span", '^Section.2.1$', True),
+ (".//li/a/span", '^Fig.1 should be Fig.1$', True),
+ (".//li/a/span", '^Sect.1 Foo$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
@@ -755,10 +755,8 @@ def test_numfig_with_numbered_toctree(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -768,14 +766,16 @@ def test_numfig_with_numbered_toctree(app, status, warning):
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s',
'table': 'Tab_%s',
- 'code-block': 'Code-%s'}})
+ 'code-block': 'Code-%s',
+ 'section': 'SECTION-%s'}})
def test_numfig_with_prefix(app, status, warning):
app.builder.build_all()
- assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.'
- not in warning.getvalue())
- assert 'index.rst:51: WARNING: invalid numfig_format: invalid' in warning.getvalue()
- assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' in warning.getvalue()
+ warnings = warning.getvalue()
+ assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' not in warnings
+ assert 'index.rst:55: WARNING: no number is assigned for section: index' in warnings
+ assert 'index.rst:56: WARNING: invalid numfig_format: invalid' in warnings
+ assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' in warnings
expects = {
'index.html': [
@@ -797,6 +797,10 @@ def test_numfig_with_prefix(app, status, warning):
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Code-1$', True),
(".//li/a/span", '^Code-2.2$', True),
+ (".//li/a/span", '^SECTION-1$', True),
+ (".//li/a/span", '^SECTION-2.1$', True),
+ (".//li/a/span", '^Fig.1 should be Fig.1$', True),
+ (".//li/a/span", '^Sect.1 Foo$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
@@ -855,10 +859,8 @@ def test_numfig_with_prefix(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -869,10 +871,11 @@ def test_numfig_with_prefix(app, status, warning):
def test_numfig_with_secnum_depth(app, status, warning):
app.builder.build_all()
- assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.'
- not in warning.getvalue())
- assert 'index.rst:51: WARNING: invalid numfig_format: invalid' in warning.getvalue()
- assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' in warning.getvalue()
+ warnings = warning.getvalue()
+ assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' not in warnings
+ assert 'index.rst:55: WARNING: no number is assigned for section: index' in warnings
+ assert 'index.rst:56: WARNING: invalid numfig_format: invalid' in warnings
+ assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' in warnings
expects = {
'index.html': [
@@ -894,6 +897,10 @@ def test_numfig_with_secnum_depth(app, status, warning):
(".//li/a/span", '^Table:2.1.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.1.2$', True),
+ (".//li/a/span", '^Section.1$', True),
+ (".//li/a/span", '^Section.2.1$', True),
+ (".//li/a/span", '^Fig.1 should be Fig.1$', True),
+ (".//li/a/span", '^Sect.1 Foo$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
@@ -952,10 +959,8 @@ def test_numfig_with_secnum_depth(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -986,6 +991,10 @@ def test_numfig_with_singlehtml(app, status, warning):
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.2$', True),
+ (".//li/a/span", '^Section.1$', True),
+ (".//li/a/span", '^Section.2.1$', True),
+ (".//li/a/span", '^Fig.1 should be Fig.1$', True),
+ (".//li/a/span", '^Sect.1 Foo$', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
@@ -1038,10 +1047,8 @@ def test_numfig_with_singlehtml(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -1070,19 +1077,30 @@ def test_enumerable_node(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
-@with_app(buildername='html', testroot='html_extra_path')
-def test_html_extra_path(app, status, warning):
+@with_app(buildername='html', testroot='html_assets')
+def test_html_assets(app, status, warning):
app.builder.build_all()
+ # html_static_path
+ assert not (app.outdir / '_static' / '.htaccess').exists()
+ assert not (app.outdir / '_static' / '.htpasswd').exists()
+ assert (app.outdir / '_static' / 'API.html').exists()
+ assert (app.outdir / '_static' / 'API.html').text() == 'Sphinx-1.4.4'
+ assert (app.outdir / '_static' / 'css/style.css').exists()
+ assert (app.outdir / '_static' / 'rimg.png').exists()
+ assert not (app.outdir / '_static' / '_build/index.html').exists()
+ assert (app.outdir / '_static' / 'background.png').exists()
+ assert not (app.outdir / '_static' / 'subdir' / '.htaccess').exists()
+ assert not (app.outdir / '_static' / 'subdir' / '.htpasswd').exists()
+
+ # html_extra_path
assert (app.outdir / '.htaccess').exists()
assert not (app.outdir / '.htpasswd').exists()
assert (app.outdir / 'API.html_t').exists()
@@ -1090,3 +1108,17 @@ def test_html_extra_path(app, status, warning):
assert (app.outdir / 'rimg.png').exists()
assert not (app.outdir / '_build/index.html').exists()
assert (app.outdir / 'background.png').exists()
+ assert (app.outdir / 'subdir' / '.htaccess').exists()
+ assert not (app.outdir / 'subdir' / '.htpasswd').exists()
+
+
+@with_app(buildername='html', confoverrides={'html_sourcelink_suffix': ''})
+def test_html_sourcelink_suffix(app, status, warning):
+ app.builder.build_all()
+ content_otherext = (app.outdir / 'otherext.html').text()
+ content_images = (app.outdir / 'images.html').text()
+
+ assert '<a href="_sources/otherext.foo"' in content_otherext
+ assert '<a href="_sources/images.txt"' in content_images
+ assert (app.outdir / '_sources' / 'otherext.foo').exists()
+ assert (app.outdir / '_sources' / 'images.txt').exists()
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
index 77ba4ca85..fcef77be6 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -12,17 +12,26 @@ from __future__ import print_function
import os
import re
+from functools import wraps
+from itertools import product
from subprocess import Popen, PIPE
from six import PY3
from sphinx.errors import SphinxError
+from sphinx.util.osutil import cd, ensuredir
from sphinx.writers.latex import LaTeXTranslator
-from util import SkipTest, remove_unicode_literals, with_app
+from util import SkipTest, remove_unicode_literals, with_app, strip_escseq, skip_if
from test_build_html import ENV_WARNINGS
+LATEX_ENGINES = ['pdflatex', 'lualatex', 'xelatex']
+DOCCLASSES = ['howto', 'manual']
+STYLEFILES = ['article.cls', 'fancyhdr.sty', 'titlesec.sty', 'amsmath.sty',
+ 'framed.sty', 'color.sty', 'fancyvrb.sty', 'threeparttable.sty',
+ 'fncychap.sty', 'geometry.sty', 'kvoptions.sty', 'hyperref.sty']
+
LATEX_WARNINGS = ENV_WARNINGS + """\
%(root)s/index.rst:\\d+: WARNING: unknown option: &option
%(root)s/index.rst:\\d+: WARNING: citation not found: missing
@@ -34,70 +43,71 @@ if PY3:
LATEX_WARNINGS = remove_unicode_literals(LATEX_WARNINGS)
-def run_latex(outdir):
- """Run pdflatex, xelatex, and lualatex in the outdir"""
- cwd = os.getcwd()
- os.chdir(outdir)
+# only run latex if all needed packages are there
+def kpsetest(*filenames):
try:
- latexes = ('pdflatex', 'xelatex', 'lualatex')
- available_latexes = len(latexes)
- for latex in latexes:
- try:
- os.mkdir(latex)
- p = Popen([latex, '--interaction=nonstopmode',
- '-output-directory=%s' % latex, 'SphinxTests.tex'],
- stdout=PIPE, stderr=PIPE)
- except OSError: # most likely the latex executable was not found
- available_latexes -= 1
- else:
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- print(stdout)
- print(stderr)
- assert False, '%s exited with return code %s' % (
- latex, p.returncode)
- finally:
- os.chdir(cwd)
-
- if available_latexes == 0: # no latex is available, skip the test
- raise SkipTest
+ p = Popen(['kpsewhich'] + list(filenames), stdout=PIPE)
+ except OSError:
+ # no kpsewhich... either no tex distribution is installed or it is
+ # a "strange" one -- don't bother running latex
+ return None
+ else:
+ p.communicate()
+ if p.returncode != 0:
+ # not found
+ return False
+ # found
+ return True
+
+
+# compile latex document with app.config.latex_engine
+def compile_latex_document(app):
+ # now, try to run latex over it
+ with cd(app.outdir):
+ try:
+ ensuredir(app.config.latex_engine)
+ p = Popen([app.config.latex_engine,
+ '--interaction=nonstopmode',
+ '-output-directory=%s' % app.config.latex_engine,
+ 'SphinxTests.tex'],
+ stdout=PIPE, stderr=PIPE)
+ except OSError: # most likely the latex executable was not found
+ raise SkipTest
+ else:
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ print(stdout)
+ print(stderr)
+ assert False, '%s exited with return code %s' % (
+ app.config.latex_engine, p.returncode)
+
+def skip_if_stylefiles_notfound(testfunc):
+ if kpsetest(*STYLEFILES) is False:
+ return skip_if(testfunc,
+ 'not running latex, the required styles do not seem to be installed')
+ else:
+ return testfunc
+
+def test_latex():
+ for engine, docclass in product(LATEX_ENGINES, DOCCLASSES):
+ yield build_latex_doc, engine, docclass
+
+
+@skip_if_stylefiles_notfound
@with_app(buildername='latex')
-def test_latex(app, status, warning):
+def build_latex_doc(app, status, warning, engine, docclass):
+ app.config.latex_engine = engine
+ app.config.latex_documents[0] = app.config.latex_documents[0][:4] + (docclass,)
+
LaTeXTranslator.ignore_missing_images = True
app.builder.build_all()
# file from latex_additional_files
assert (app.outdir / 'svgimg.svg').isfile()
- # only run latex if all needed packages are there
- def kpsetest(filename):
- try:
- p = Popen(['kpsewhich', filename], stdout=PIPE)
- except OSError:
- # no kpsewhich... either no tex distribution is installed or it is
- # a "strange" one -- don't bother running latex
- return None
- else:
- p.communicate()
- if p.returncode != 0:
- # not found
- return False
- # found
- return True
-
- if kpsetest('article.sty') is None:
- raise SkipTest('not running latex, it doesn\'t seem to be installed')
- for filename in ['fancyhdr.sty', 'fancybox.sty', 'titlesec.sty',
- 'amsmath.sty', 'framed.sty', 'color.sty', 'fancyvrb.sty',
- 'threeparttable.sty']:
- if not kpsetest(filename):
- raise SkipTest('not running latex, the %s package doesn\'t '
- 'seem to be installed' % filename)
-
- # now, try to run latex over it
- run_latex(app.outdir)
+ compile_latex_document(app)
@with_app(buildername='latex')
@@ -126,53 +136,11 @@ def test_writer(app, status, warning):
'\\end{wrapfigure}' in result)
-@with_app(buildername='latex',
- confoverrides={'latex_documents': [
- ('contents', 'SphinxTests.tex', 'Sphinx Tests Documentation',
- 'Georg Brandl \\and someone else', 'howto'),
- ]},
- srcdir='latex_howto')
-def test_latex_howto(app, status, warning):
- LaTeXTranslator.ignore_missing_images = True
- app.builder.build_all()
-
- # file from latex_additional_files
- assert (app.outdir / 'svgimg.svg').isfile()
-
- # only run latex if all needed packages are there
- def kpsetest(filename):
- try:
- p = Popen(['kpsewhich', filename], stdout=PIPE)
- except OSError:
- # no kpsewhich... either no tex distribution is installed or it is
- # a "strange" one -- don't bother running latex
- return None
- else:
- p.communicate()
- if p.returncode != 0:
- # not found
- return False
- # found
- return True
-
- if kpsetest('article.sty') is None:
- raise SkipTest('not running latex, it doesn\'t seem to be installed')
- for filename in ['fancyhdr.sty', 'fancybox.sty', 'titlesec.sty',
- 'amsmath.sty', 'framed.sty', 'color.sty', 'fancyvrb.sty',
- 'threeparttable.sty']:
- if not kpsetest(filename):
- raise SkipTest('not running latex, the %s package doesn\'t '
- 'seem to be installed' % filename)
-
- # now, try to run latex over it
- run_latex(app.outdir)
-
-
@with_app(buildername='latex', testroot='warnings', freshenv=True)
def test_latex_warnings(app, status, warning):
app.builder.build_all()
- warnings = warning.getvalue().replace(os.sep, '/')
+ warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
warnings_exp = LATEX_WARNINGS % {
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(warnings_exp + '$', warnings), \
@@ -191,20 +159,25 @@ def test_numref(app, status, warning):
print(warning.getvalue())
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Fig.\\@ }}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Table }}' in result
- assert '\\SetupFloatingEnvironment{literal-block}{name=Listing }' in result
+ assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Listing }}' in result
assert '\\hyperref[index:fig1]{Fig.\\@ \\ref{index:fig1}}' in result
assert '\\hyperref[baz:fig22]{Figure\\ref{baz:fig22}}' in result
assert '\\hyperref[index:table-1]{Table \\ref{index:table-1}}' in result
assert '\\hyperref[baz:table22]{Table:\\ref{baz:table22}}' in result
assert '\\hyperref[index:code-1]{Listing \\ref{index:code-1}}' in result
assert '\\hyperref[baz:code22]{Code-\\ref{baz:code22}}' in result
+ assert '\\hyperref[foo:foo]{Section \\ref{foo:foo}}' in result
+ assert '\\hyperref[bar:bar-a]{Section \\ref{bar:bar-a}}' in result
+ assert '\\hyperref[index:fig1]{Fig.\\ref{index:fig1} \\nameref{index:fig1}}' in result
+ assert '\\hyperref[foo:foo]{Sect.\\ref{foo:foo} \\nameref{foo:foo}}' in result
@with_app(buildername='latex', testroot='numfig',
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s',
'table': 'Tab_%s',
- 'code-block': 'Code-%s'}})
+ 'code-block': 'Code-%s',
+ 'section': 'SECTION-%s'}})
def test_numref_with_prefix1(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -213,7 +186,7 @@ def test_numref_with_prefix1(app, status, warning):
print(warning.getvalue())
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Figure:}}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Tab\\_}}' in result
- assert '\\SetupFloatingEnvironment{literal-block}{name=Code-}' in result
+ assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Code-}}' in result
assert '\\ref{index:fig1}' in result
assert '\\ref{baz:fig22}' in result
assert '\\ref{index:table-1}' in result
@@ -226,13 +199,18 @@ def test_numref_with_prefix1(app, status, warning):
assert '\\hyperref[baz:table22]{Table:\\ref{baz:table22}}' in result
assert '\\hyperref[index:code-1]{Code-\\ref{index:code-1}}' in result
assert '\\hyperref[baz:code22]{Code-\\ref{baz:code22}}' in result
+ assert '\\hyperref[foo:foo]{SECTION-\\ref{foo:foo}}' in result
+ assert '\\hyperref[bar:bar-a]{SECTION-\\ref{bar:bar-a}}' in result
+ assert '\\hyperref[index:fig1]{Fig.\\ref{index:fig1} \\nameref{index:fig1}}' in result
+ assert '\\hyperref[foo:foo]{Sect.\\ref{foo:foo} \\nameref{foo:foo}}' in result
@with_app(buildername='latex', testroot='numfig',
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s.',
'table': 'Tab_%s:',
- 'code-block': 'Code-%s | '}})
+ 'code-block': 'Code-%s | ',
+ 'section': 'SECTION_%s_'}})
def test_numref_with_prefix2(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -243,13 +221,17 @@ def test_numref_with_prefix2(app, status, warning):
assert '\\def\\fnum@figure{\\figurename\\thefigure.\\@}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Tab\\_}}' in result
assert '\\def\\fnum@table{\\tablename\\thetable:}' in result
- assert '\\SetupFloatingEnvironment{literal-block}{name=Code-}' in result
+ assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Code-}}' in result
assert '\\hyperref[index:fig1]{Figure:\\ref{index:fig1}.\\@}' in result
assert '\\hyperref[baz:fig22]{Figure\\ref{baz:fig22}}' in result
assert '\\hyperref[index:table-1]{Tab\\_\\ref{index:table-1}:}' in result
assert '\\hyperref[baz:table22]{Table:\\ref{baz:table22}}' in result
assert '\\hyperref[index:code-1]{Code-\\ref{index:code-1} \\textbar{} }' in result
assert '\\hyperref[baz:code22]{Code-\\ref{baz:code22}}' in result
+ assert '\\hyperref[foo:foo]{SECTION\\_\\ref{foo:foo}\\_}' in result
+ assert '\\hyperref[bar:bar-a]{SECTION\\_\\ref{bar:bar-a}\\_}' in result
+ assert '\\hyperref[index:fig1]{Fig.\\ref{index:fig1} \\nameref{index:fig1}}' in result
+ assert '\\hyperref[foo:foo]{Sect.\\ref{foo:foo} \\nameref{foo:foo}}' in result
@with_app(buildername='latex', testroot='numfig',
@@ -262,13 +244,17 @@ def test_numref_with_language_ja(app, status, warning):
print(warning.getvalue())
assert u'\\renewcommand{\\figurename}{\u56f3 }' in result
assert '\\renewcommand{\\tablename}{TABLE }' in result
- assert '\\SetupFloatingEnvironment{literal-block}{name=LIST }' in result
+ assert '\\renewcommand{\\literalblockname}{LIST }' in result
assert u'\\hyperref[index:fig1]{\u56f3 \\ref{index:fig1}}' in result
assert '\\hyperref[baz:fig22]{Figure\\ref{baz:fig22}}' in result
assert '\\hyperref[index:table-1]{TABLE \\ref{index:table-1}}' in result
assert '\\hyperref[baz:table22]{Table:\\ref{baz:table22}}' in result
assert '\\hyperref[index:code-1]{LIST \\ref{index:code-1}}' in result
assert '\\hyperref[baz:code22]{Code-\\ref{baz:code22}}' in result
+ assert '\\hyperref[foo:foo]{Section \\ref{foo:foo}}' in result
+ assert '\\hyperref[bar:bar-a]{Section \\ref{bar:bar-a}}' in result
+ assert '\\hyperref[index:fig1]{Fig.\\ref{index:fig1} \\nameref{index:fig1}}' in result
+ assert '\\hyperref[foo:foo]{Sect.\\ref{foo:foo} \\nameref{foo:foo}}' in result
@with_app(buildername='latex')
@@ -408,22 +394,26 @@ def test_footnote(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert '\\footnote[1]{\sphinxAtStartFootnote%\nnumbered\n}' in result
- assert '\\footnote[2]{\sphinxAtStartFootnote%\nauto numbered\n}' in result
- assert '\\footnote[3]{\sphinxAtStartFootnote%\nnamed\n}' in result
+ assert ('\\begin{footnote}[1]\\sphinxAtStartFootnote\nnumbered\n%\n'
+ '\\end{footnote}') in result
+ assert ('\\begin{footnote}[2]\\sphinxAtStartFootnote\nauto numbered\n%\n'
+ '\\end{footnote}') in result
+ assert '\\begin{footnote}[3]\\sphinxAtStartFootnote\nnamed\n%\n\\end{footnote}' in result
assert '{\\hyperref[footnote:bar]{\\sphinxcrossref{{[}bar{]}}}}' in result
assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} ' in result
assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} \ncite' in result
assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} \ncite\n}' in result
- assert '\\capstart\\caption{Table caption \\protect\\footnotemark[4]}' in result
- assert 'name \\protect\\footnotemark[5]' in result
- assert ('\\end{threeparttable}\n\n'
- '\\footnotetext[4]{\sphinxAtStartFootnote%\nfootnotes in table caption\n}'
- '\\footnotetext[5]{\sphinxAtStartFootnote%\nfootnotes in table\n}' in result)
+ assert '\\caption{Table caption \\sphinxfootnotemark[4]' in result
+ assert 'name \\sphinxfootnotemark[5]' in result
+ assert ('\\end{threeparttable}\n\n%\n'
+ '\\begin{footnotetext}[4]\sphinxAtStartFootnote\n'
+ 'footnotes in table caption\n%\n\\end{footnotetext}%\n'
+ '\\begin{footnotetext}[5]\sphinxAtStartFootnote\n'
+ 'footnotes in table\n%\n\\end{footnotetext}') in result
@with_app(buildername='latex', testroot='footnotes')
-def test_reference_in_caption(app, status, warning):
+def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
print(result)
@@ -434,20 +424,27 @@ 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[4]}\n'
+ assert ('\\chapter{The section with a reference to \\sphinxfootnotemark[4]}\n'
'\\label{index:the-section-with-a-reference-to}'
- '\\footnotetext[4]{\sphinxAtStartFootnote%\nFootnote in section\n}' in result)
+ '%\n\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n'
+ 'Footnote in section\n%\n\\end{footnotetext}') in result
assert ('\\caption{This is the figure caption with a footnote to '
- '\\protect\\footnotemark[6].}\label{index:id23}\end{figure}\n'
- '\\footnotetext[6]{\sphinxAtStartFootnote%\nFootnote in caption\n}')in result
- assert ('\\caption{footnote \\protect\\footnotemark[7] '
- 'in caption of normal table}') in result
- assert ('\\end{threeparttable}\n\n\\footnotetext[7]{\sphinxAtStartFootnote%\n'
- 'Foot note in table\n}' in result)
- assert ('\\caption{footnote \\protect\\footnotemark[8] in caption of longtable}'
- in result)
- assert ('\end{longtable}\n\n\\footnotetext[8]{\sphinxAtStartFootnote%\n'
- 'Foot note in longtable\n}' in result)
+ '\\sphinxfootnotemark[6].}\label{index:id27}\end{figure}\n'
+ '%\n\\begin{footnotetext}[6]\\sphinxAtStartFootnote\n'
+ 'Footnote in caption\n%\n\\end{footnotetext}')in result
+ assert ('\\caption{footnote \\sphinxfootnotemark[7] '
+ 'in caption of normal table}\\label{index:id28}') in result
+ assert ('\\caption{footnote \\sphinxfootnotemark[8] '
+ 'in caption \sphinxfootnotemark[9] of longtable}') in result
+ assert ('\end{longtable}\n\n%\n\\begin{footnotetext}[8]'
+ '\sphinxAtStartFootnote\n'
+ 'Foot note in longtable\n%\n\\end{footnotetext}' in result)
+ assert ('This is a reference to the code-block in the footnote:\n'
+ '{\hyperref[index:codeblockinfootnote]{\\sphinxcrossref{\\DUrole'
+ '{std,std-ref}{I am in a footnote}}}}') in result
+ assert ('&\nThis is one more footnote with some code in it '
+ '\\sphinxfootnotemark[10].\n\\\\') in result
+ assert '\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]' in result
@with_app(buildername='latex', testroot='footnotes',
@@ -458,29 +455,32 @@ def test_latex_show_urls_is_inline(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
- 'footnote in bar\n} in bar.rst' in result)
- assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
- 'footnote in baz\n} in baz.rst' in result)
- assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
+ assert ('Same footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
+ 'footnote in bar\n%\n\\end{footnote} in bar.rst' in result)
+ assert ('Auto footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
+ 'footnote in baz\n%\n\\end{footnote} in baz.rst' in result)
+ assert ('\\phantomsection\\label{index:id30}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
'{\\sphinxcrossref{The section with a reference to '
'\\phantomsection\\label{index:id1}'
'{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result)
- assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
+ assert ('\\phantomsection\\label{index:id31}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]'
'{\\sphinxcrossref{The section with a reference to }}}' in result)
- assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote%\nFirst\n}' in result
- assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result
+ assert ('First footnote: %\n\\begin{footnote}[2]\\sphinxAtStartFootnote\n'
+ 'First\n%\n\\end{footnote}') in result
+ assert ('Second footnote: %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
+ 'Second\n%\n\\end{footnote}') in result
assert '\\href{http://sphinx-doc.org/}{Sphinx} (http://sphinx-doc.org/)' in result
- assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote%\nThird\n}' in result
+ assert ('Third footnote: %\n\\begin{footnote}[3]\\sphinxAtStartFootnote\n'
+ 'Third\n%\n\\end{footnote}') in result
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde} '
'(http://sphinx-doc.org/\\textasciitilde{}test/)' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term} (http://sphinx-doc.org/)}] '
'\\leavevmode\nDescription' in result)
- assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] '
- '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote%\n'
- 'Footnote in term\n}\nDescription' in result)
+ assert ('\\item[{Footnote in term \\sphinxfootnotemark[5]}] '
+ '\\leavevmode%\n\\begin{footnotetext}[5]\\sphinxAtStartFootnote\n'
+ 'Footnote in term\n%\n\\end{footnotetext}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist} '
'(http://sphinx-doc.org/)}] \\leavevmode\nDescription' in result)
assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result)
@@ -496,40 +496,45 @@ def test_latex_show_urls_is_footnote(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
- 'footnote in bar\n} in bar.rst' in result)
- assert ('Auto footnote number \\footnote[2]{\sphinxAtStartFootnote%\n'
- 'footnote in baz\n} in baz.rst' in result)
- assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
+ assert ('Same footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
+ 'footnote in bar\n%\n\\end{footnote} in bar.rst' in result)
+ assert ('Auto footnote number %\n\\begin{footnote}[2]\\sphinxAtStartFootnote\n'
+ 'footnote in baz\n%\n\\end{footnote} in baz.rst' in result)
+ assert ('\\phantomsection\\label{index:id30}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
'{\\sphinxcrossref{The section with a reference '
'to \\phantomsection\\label{index:id1}'
'{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result)
- assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
+ assert ('\\phantomsection\\label{index:id31}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]'
'{\\sphinxcrossref{The section with a reference to }}}' in result)
- assert 'First footnote: \\footnote[3]{\sphinxAtStartFootnote%\nFirst\n}' in result
- assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result
+ assert ('First footnote: %\n\\begin{footnote}[3]\\sphinxAtStartFootnote\n'
+ 'First\n%\n\\end{footnote}') in result
+ assert ('Second footnote: %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
+ 'Second\n%\n\\end{footnote}') in result
assert ('\\href{http://sphinx-doc.org/}{Sphinx}'
- '\\footnote[4]{\sphinxAtStartFootnote%\n'
- '\\nolinkurl{http://sphinx-doc.org/}\n}' in result)
- assert 'Third footnote: \\footnote[6]{\sphinxAtStartFootnote%\nThird\n}' in result
+ '%\n\\begin{footnote}[4]\\sphinxAtStartFootnote\n'
+ '\\nolinkurl{http://sphinx-doc.org/}\n%\n\\end{footnote}') in result
+ assert ('Third footnote: %\n\\begin{footnote}[6]\\sphinxAtStartFootnote\n'
+ 'Third\n%\n\\end{footnote}') in result
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
- '\\footnote[5]{\sphinxAtStartFootnote%\n'
- '\\nolinkurl{http://sphinx-doc.org/~test/}\n}' in result)
- assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[8]}] '
- '\\leavevmode\\footnotetext[8]{\sphinxAtStartFootnote%\n'
- '\\nolinkurl{http://sphinx-doc.org/}\n}\nDescription' in result)
- assert ('\\item[{Footnote in term \\protect\\footnotemark[10]}] '
- '\\leavevmode\\footnotetext[10]{\sphinxAtStartFootnote%\n'
- 'Footnote in term\n}\nDescription' in result)
- assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\protect'
- '\\footnotemark[9]}] '
- '\\leavevmode\\footnotetext[9]{\sphinxAtStartFootnote%\n'
- '\\nolinkurl{http://sphinx-doc.org/}\n}\nDescription' in result)
+ '%\n\\begin{footnote}[5]\\sphinxAtStartFootnote\n'
+ '\\nolinkurl{http://sphinx-doc.org/~test/}\n%\n\\end{footnote}') in result
+ assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\sphinxfootnotemark[8]}] '
+ '\\leavevmode%\n\\begin{footnotetext}[8]\\sphinxAtStartFootnote\n'
+ '\\nolinkurl{http://sphinx-doc.org/}\n%\n'
+ '\\end{footnotetext}\nDescription') in result
+ assert ('\\item[{Footnote in term \\sphinxfootnotemark[10]}] '
+ '\\leavevmode%\n\\begin{footnotetext}[10]\\sphinxAtStartFootnote\n'
+ 'Footnote in term\n%\n\\end{footnotetext}\nDescription') in result
+ assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}'
+ '\\sphinxfootnotemark[9]}] '
+ '\\leavevmode%\n\\begin{footnotetext}[9]\\sphinxAtStartFootnote\n'
+ '\\nolinkurl{http://sphinx-doc.org/}\n%\n'
+ '\\end{footnotetext}\nDescription') in result
assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result)
assert ('\\href{mailto:sphinx-dev@googlegroups.com}'
- '{sphinx-dev@googlegroups.com}\n' in result)
+ '{sphinx-dev@googlegroups.com}\n') in result
@with_app(buildername='latex', testroot='footnotes',
@@ -540,33 +545,36 @@ def test_latex_show_urls_is_no(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
- 'footnote in bar\n} in bar.rst' in result)
- assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
- 'footnote in baz\n} in baz.rst' in result)
- assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
+ assert ('Same footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
+ 'footnote in bar\n%\n\\end{footnote} in bar.rst') in result
+ assert ('Auto footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
+ 'footnote in baz\n%\n\\end{footnote} in baz.rst') in result
+ assert ('\\phantomsection\\label{index:id30}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
'{\\sphinxcrossref{The section with a reference '
'to \\phantomsection\\label{index:id1}'
- '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result)
- assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
+ '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}') in result
+ assert ('\\phantomsection\\label{index:id31}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]'
'{\\sphinxcrossref{The section with a reference to }}}' in result)
- assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote%\nFirst\n}' in result
- assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result
+ assert ('First footnote: %\n\\begin{footnote}[2]\\sphinxAtStartFootnote\n'
+ 'First\n%\n\\end{footnote}') in result
+ assert ('Second footnote: %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
+ 'Second\n%\n\\end{footnote}') in result
assert '\\href{http://sphinx-doc.org/}{Sphinx}' in result
- assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote%\nThird\n}' in result
+ assert ('Third footnote: %\n\\begin{footnote}[3]\\sphinxAtStartFootnote\n'
+ 'Third\n%\n\\end{footnote}') in result
assert '\\href{http://sphinx-doc.org/~test/}{URL including tilde}' in result
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}}] '
- '\\leavevmode\nDescription' in result)
- assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] '
- '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote%\n'
- 'Footnote in term\n}\nDescription' in result)
+ '\\leavevmode\nDescription') in result
+ assert ('\\item[{Footnote in term \\sphinxfootnotemark[5]}] '
+ '\\leavevmode%\n\\begin{footnotetext}[5]\\sphinxAtStartFootnote\n'
+ 'Footnote in term\n%\n\\end{footnotetext}\nDescription') in result
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}}] '
- '\\leavevmode\nDescription' in result)
+ '\\leavevmode\nDescription') in result
assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result)
assert ('\\href{mailto:sphinx-dev@googlegroups.com}'
- '{sphinx-dev@googlegroups.com}\n' in result)
+ '{sphinx-dev@googlegroups.com}\n') in result
@with_app(buildername='latex', testroot='image-in-section')
@@ -577,10 +585,10 @@ def test_image_in_section(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert ('\\chapter[Test section]{\\lowercase{\\sphinxincludegraphics'
- '[width=15pt,height=15pt]}{{pic}.png} Test section}'
+ '[width=15bp,height=15bp]}{{pic}.png} Test section}'
in result)
assert ('\\chapter[Other {[}blah{]} section]{Other {[}blah{]} '
- '\\lowercase{\\sphinxincludegraphics[width=15pt,height=15pt]}'
+ '\\lowercase{\\sphinxincludegraphics[width=15bp,height=15bp]}'
'{{pic}.png} section}' in result)
assert ('\\chapter{Another section}' in result)
@@ -606,6 +614,7 @@ def test_toctree_maxdepth_manual(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert '\\setcounter{tocdepth}{1}' in result
+ assert '\\setcounter{secnumdepth}' not in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
@@ -620,6 +629,7 @@ def test_toctree_maxdepth_howto(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert '\\setcounter{tocdepth}{2}' in result
+ assert '\\setcounter{secnumdepth}' not in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
@@ -631,6 +641,7 @@ def test_toctree_not_found(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert '\\setcounter{tocdepth}' not in result
+ assert '\\setcounter{secnumdepth}' not in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
@@ -642,6 +653,19 @@ def test_toctree_without_maxdepth(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert '\\setcounter{tocdepth}' not in result
+ assert '\\setcounter{secnumdepth}' not in result
+
+
+@with_app(buildername='latex', testroot='toctree-maxdepth',
+ confoverrides={'master_doc': 'qux'})
+def test_toctree_with_deeper_maxdepth(app, status, warning):
+ app.builder.build_all()
+ result = (app.outdir / 'Python.tex').text(encoding='utf8')
+ print(result)
+ print(status.getvalue())
+ print(warning.getvalue())
+ assert '\\setcounter{tocdepth}{3}' in result
+ assert '\\setcounter{secnumdepth}{3}' in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
@@ -686,3 +710,13 @@ def test_latex_toplevel_sectioning_is_section(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert '\\section{Foo}' in result
+
+@skip_if_stylefiles_notfound
+@with_app(buildername='latex', testroot='maxlistdepth')
+def test_maxlistdepth_at_ten(app, status, warning):
+ app.builder.build_all()
+ result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
+ print(result)
+ print(status.getvalue())
+ print(warning.getvalue())
+ compile_latex_document(app)
diff --git a/tests/test_build_linkcheck.py b/tests/test_build_linkcheck.py
new file mode 100644
index 000000000..1d75135af
--- /dev/null
+++ b/tests/test_build_linkcheck.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+"""
+ test_build_linkcheck
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Test the build process with manpage builder with the test root.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from __future__ import print_function
+
+from util import with_app
+
+
+@with_app('linkcheck', testroot='linkcheck', freshenv=True)
+def test_defaults(app, status, warning):
+ app.builder.build_all()
+
+ assert (app.outdir / 'output.txt').exists()
+ content = (app.outdir / 'output.txt').text()
+
+ print(content)
+ # looking for #top should fail
+ assert "Anchor 'top' not found" in content
+ assert len(content.splitlines()) == 1
+
+
+@with_app('linkcheck', testroot='linkcheck', freshenv=True,
+ confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"]})
+def test_anchors_ignored(app, status, warning):
+ app.builder.build_all()
+
+ assert (app.outdir / 'output.txt').exists()
+ content = (app.outdir / 'output.txt').text()
+
+ # expect all ok when excluding #top
+ assert not content
diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py
index 47bec2e23..06da311df 100644
--- a/tests/test_build_texinfo.py
+++ b/tests/test_build_texinfo.py
@@ -18,7 +18,7 @@ from six import PY3
from sphinx.writers.texinfo import TexinfoTranslator
-from util import SkipTest, remove_unicode_literals, with_app
+from util import SkipTest, remove_unicode_literals, with_app, strip_escseq
from test_build_html import ENV_WARNINGS
@@ -36,8 +36,7 @@ if PY3:
@with_app(buildername='texinfo', testroot='warnings', freshenv=True)
def test_texinfo_warnings(app, status, warning):
app.builder.build_all()
-
- warnings = warning.getvalue().replace(os.sep, '/')
+ warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
warnings_exp = TEXINFO_WARNINGS % {
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(warnings_exp + '$', warnings), \
diff --git a/tests/test_build_text.py b/tests/test_build_text.py
index 613d95d1f..f95e4d2ab 100644
--- a/tests/test_build_text.py
+++ b/tests/test_build_text.py
@@ -65,7 +65,7 @@ def test_nonascii_title_line(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'nonascii_title.txt').text(encoding='utf-8')
expect_underline = '******'
- result_underline = result.splitlines()[2].strip()
+ result_underline = result.splitlines()[1].strip()
assert expect_underline == result_underline
diff --git a/tests/test_config.py b/tests/test_config.py
index 5b18e3101..1b3c94957 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -10,7 +10,7 @@
:license: BSD, see LICENSE for details.
"""
from six import PY3, iteritems
-from util import mock
+import mock
from util import TestApp, with_app, gen_with_app, with_tempdir, \
raises, raises_msg, assert_in, assert_not_in
@@ -38,7 +38,7 @@ def test_core_config(app, status, warning):
# simple default values
assert 'locale_dirs' not in cfg.__dict__
- assert cfg.locale_dirs == []
+ assert cfg.locale_dirs == ['locales']
assert cfg.trim_footnote_reference_space is False
# complex default values
@@ -206,3 +206,15 @@ def test_gen_check_types(app, status, warning):
'override on "%s" should%s raise a type warning' %
(key, '' if should else ' NOT')
)
+
+
+@with_app(testroot='config')
+def test_check_enum(app, status, warning):
+ assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
+ not in warning.getvalue()
+
+
+@with_app(testroot='config', confoverrides={'value17': 'invalid'})
+def test_check_enum_failed(app, status, warning):
+ assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
+ "but `invalid` is given." in warning.getvalue()
diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py
index 8209e8f61..a29db6b90 100644
--- a/tests/test_directive_code.py
+++ b/tests/test_directive_code.py
@@ -65,7 +65,7 @@ def test_code_block_caption_html(app, status, warning):
def test_code_block_caption_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
- caption = '\\sphinxSetupCaptionForVerbatim{literal-block}{caption \\emph{test} rb}'
+ caption = '\\sphinxSetupCaptionForVerbatim{caption \\sphinxstyleemphasis{test} rb}'
label = '\\def\\sphinxLiteralBlockLabel{\\label{caption:id1}}'
link = '\hyperref[caption:name-test-rb]' \
'{Listing \\ref{caption:name-test-rb}}'
@@ -222,17 +222,25 @@ def test_literal_include_lineno_match(app, status, warning):
'14</pre></div></td>')
assert start_after in html
+ start_at_end_at = (
+ '<td class="linenos"><div class="linenodiv"><pre>'
+ ' 9\n'
+ '10\n'
+ '11</pre></div></td>')
+ assert start_at_end_at in html
+
@with_app('latex', testroot='directive-code')
def test_literalinclude_file_whole_of_emptyline(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8').replace('\r\n', '\n')
includes = (
- '\\begin{Verbatim}[commandchars=\\\\\\{\\},numbers=left,firstnumber=1,stepnumber=1]\n'
+ '\\begin{sphinxVerbatim}'
+ '[commandchars=\\\\\\{\\},numbers=left,firstnumber=1,stepnumber=1]\n'
'\n'
'\n'
'\n'
- '\\end{Verbatim}\n')
+ '\\end{sphinxVerbatim}\n')
assert includes in latex
@@ -252,7 +260,7 @@ def test_literalinclude_caption_html(app, status, warning):
def test_literalinclude_caption_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
- caption = '\\sphinxSetupCaptionForVerbatim{literal-block}{caption \\textbf{test} py}'
+ caption = '\\sphinxSetupCaptionForVerbatim{caption \\sphinxstylestrong{test} py}'
label = '\\def\\sphinxLiteralBlockLabel{\\label{caption:id2}}'
link = '\hyperref[caption:name-test-py]' \
'{Listing \\ref{caption:name-test-py}}'
diff --git a/tests/test_directive_only.py b/tests/test_directive_only.py
index 7e499a3a1..def064c5a 100644
--- a/tests/test_directive_only.py
+++ b/tests/test_directive_only.py
@@ -12,6 +12,7 @@
import re
from docutils import nodes
+from sphinx.util.nodes import process_only_nodes
from util import with_app
@@ -46,7 +47,7 @@ def test_sectioning(app, status, warning):
app.builder.build(['only'])
doctree = app.env.get_doctree('only')
- app.env.process_only_nodes(doctree, app.builder)
+ process_only_nodes(doctree, app.builder.tags)
parts = [getsects(n)
for n in [_n for _n in doctree.children if isinstance(_n, nodes.section)]]
diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py
index 778ac1c55..4a505119d 100644
--- a/tests/test_domain_cpp.py
+++ b/tests/test_domain_cpp.py
@@ -24,7 +24,10 @@ ids = []
def parse(name, string):
- parser = DefinitionParser(string, None)
+ class Config(object):
+ cpp_id_attributes = ["id_attr"]
+ cpp_paren_attributes = ["paren_attr"]
+ parser = DefinitionParser(string, None, Config())
ast = parser.parse_declaration(name)
if not parser.eof:
print("Parsing stopped at", parser.pos)
@@ -50,7 +53,7 @@ def check(name, input, idv1output=None, idv2output=None, output=None):
print("Expected: ", output)
raise DefinitionError("")
rootSymbol = Symbol(None, None, None, None, None, None)
- symbol = rootSymbol.add_declaration(ast, docname="Test")
+ symbol = rootSymbol.add_declaration(ast, docname="TestDoc")
parentNode = addnodes.desc()
signode = addnodes.desc_signature(input, '')
parentNode += signode
@@ -138,6 +141,20 @@ def test_type_definitions():
check('type', 'void (*f)(std::function<void(int i)> g)', 'f', '1f')
+def test_concept_definitions():
+ check('concept', 'template<typename Param> A::B::Concept',
+ None, 'I0EN1A1B7ConceptE')
+ check('concept', 'template<typename A, typename B, typename ...C> Foo',
+ None, 'I00DpE3Foo')
+ check('concept', 'template<typename Param> A::B::Concept()',
+ None, 'I0EN1A1B7ConceptE')
+ check('concept', 'template<typename A, typename B, typename ...C> Foo()',
+ None, 'I00DpE3Foo')
+ raises(DefinitionError, parse, 'concept', 'Foo')
+ raises(DefinitionError, parse, 'concept',
+ 'template<typename T> template<typename U> Foo')
+
+
def test_member_definitions():
check('member', ' const std::string & name = 42',
"name__ssCR", "4name", output='const std::string &name = 42')
@@ -401,6 +418,70 @@ def test_templates():
None, "I00ElsRNSt13basic_ostreamI4Char6TraitsEE"
"RK18c_string_view_baseIK4Char6TraitsE")
+ # template introductions
+ raises(DefinitionError, parse, 'enum', 'abc::ns::foo{id_0, id_1, id_2} A')
+ raises(DefinitionError, parse, 'enumerator', 'abc::ns::foo{id_0, id_1, id_2} A')
+ check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar',
+ None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE')
+ check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar',
+ None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE')
+ check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar<id_0, id_1, id_2>',
+ None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barI4id_04id_14id_2EE')
+ check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar<id_0, id_1, id_2...>',
+ None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barI4id_04id_1Dp4id_2EE')
+
+ check('class', 'template<> Concept{U} A<int>::B',
+ None, 'IEI0EX7ConceptI1UEEN1AIiE1BE')
+
+ check('type', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar = ghi::qux',
+ None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE')
+ check('type', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar = ghi::qux',
+ None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE')
+ check('function', 'abc::ns::foo{id_0, id_1, id_2} void xyz::bar()',
+ None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv')
+ check('function', 'abc::ns::foo{id_0, id_1, ...id_2} void xyz::bar()',
+ None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barEv')
+ check('member', 'abc::ns::foo{id_0, id_1, id_2} ghi::qux xyz::bar',
+ None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE')
+ check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar',
+ None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE')
+ check('concept', 'Iterator{T, U} Another',
+ None, 'I00EX8IteratorI1T1UEE7Another')
+ check('concept', 'template<typename ...Pack> Numerics = (... && Numeric<Pack>)',
+ None, 'IDpE8Numerics')
+
+
+def test_attributes():
+ # style: C++
+ check('member', '[[]] int f', 'f__i', '1f')
+ check('member', '[ [ ] ] int f', 'f__i', '1f',
+ # this will fail when the proper grammar is implemented
+ output='[[ ]] int f')
+ check('member', '[[a]] int f', 'f__i', '1f')
+ # style: GNU
+ check('member', '__attribute__(()) int f', 'f__i', '1f')
+ check('member', '__attribute__((a)) int f', 'f__i', '1f')
+ check('member', '__attribute__((a, b)) int f', 'f__i', '1f')
+ # style: user-defined id
+ check('member', 'id_attr int f', 'f__i', '1f')
+ # style: user-defined paren
+ check('member', 'paren_attr() int f', 'f__i', '1f')
+ check('member', 'paren_attr(a) int f', 'f__i', '1f')
+ check('member', 'paren_attr("") int f', 'f__i', '1f')
+ check('member', 'paren_attr(()[{}][]{}) int f', 'f__i', '1f')
+ raises(DefinitionError, parse, 'member', 'paren_attr(() int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr([) int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr({) int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr([)]) int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr((])) int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr({]}) int f')
+
+ # position: decl specs
+ check('function', 'static inline __attribute__(()) void f()',
+ 'f', '1fv',
+ output='__attribute__(()) static inline void f()')
+
+
# def test_print():
# # used for getting all the ids out for checking
diff --git a/tests/test_domain_std.py b/tests/test_domain_std.py
index 2d31ada2e..4f892cb01 100644
--- a/tests/test_domain_std.py
+++ b/tests/test_domain_std.py
@@ -10,9 +10,9 @@
"""
from docutils import nodes
+import mock
from sphinx.domains.std import StandardDomain
-from util import mock
def test_process_doc_handle_figure_caption():
@@ -26,6 +26,7 @@ def test_process_doc_handle_figure_caption():
nameids={'testname': 'testid'},
ids={'testid': figure_node},
)
+ document.traverse.return_value = []
domain = StandardDomain(env)
if 'testname' in domain.data['labels']:
@@ -47,6 +48,7 @@ def test_process_doc_handle_table_title():
nameids={'testname': 'testid'},
ids={'testid': table_node},
)
+ document.traverse.return_value = []
domain = StandardDomain(env)
if 'testname' in domain.data['labels']:
diff --git a/tests/test_environment_indexentries.py b/tests/test_environment_indexentries.py
new file mode 100644
index 000000000..57a3cf52f
--- /dev/null
+++ b/tests/test_environment_indexentries.py
@@ -0,0 +1,136 @@
+# -*- coding: utf-8 -*-
+"""
+ test_environment_indexentries
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Test the sphinx.environment.managers.indexentries.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from collections import namedtuple
+from sphinx import locale
+from sphinx.environment.managers.indexentries import IndexEntries
+
+import mock
+
+Environment = namedtuple('Environment', 'indexentries')
+
+dummy_builder = mock.Mock()
+dummy_builder.get_relative_uri.return_value = ''
+
+
+def test_create_single_index():
+ # type, value, tid, main, index_key
+ env = Environment({
+ 'index': [
+ ('single', 'docutils', 'id1', '', None),
+ ('single', 'Python', 'id2', '', None),
+ ('single', 'pip; install', 'id3', '', None),
+ ('single', 'pip; upgrade', 'id4', '', None),
+ ('single', 'Sphinx', 'id5', '', None),
+ ],
+ })
+ index = IndexEntries(env).create_index(dummy_builder)
+ assert len(index) == 3
+ assert index[0] == (u'D', [(u'docutils', [[('', '#id1')], [], None])])
+ assert index[1] == (u'P', [(u'pip', [[], [(u'install', [('', '#id3')]),
+ (u'upgrade', [('', '#id4')])], None]),
+ (u'Python', [[('', '#id2')], [], None])])
+ assert index[2] == (u'S', [(u'Sphinx', [[('', '#id5')], [], None])])
+
+
+def test_create_pair_index():
+ # type, value, tid, main, index_key
+ env = Environment({
+ 'index': [
+ ('pair', 'docutils; reStructuredText', 'id1', '', None),
+ ('pair', 'Python; interpreter', 'id2', '', None),
+ ('pair', 'Sphinx; documentation tool', 'id3', '', None),
+ ],
+ })
+ index = IndexEntries(env).create_index(dummy_builder)
+ assert len(index) == 5
+ assert index[0] == (u'D',
+ [(u'documentation tool', [[], [(u'Sphinx', [('', '#id3')])], None]),
+ (u'docutils', [[], [(u'reStructuredText', [('', '#id1')])], None])])
+ assert index[1] == (u'I', [(u'interpreter', [[], [(u'Python', [('', '#id2')])], None])])
+ assert index[2] == (u'P', [(u'Python', [[], [(u'interpreter', [('', '#id2')])], None])])
+ assert index[3] == (u'R',
+ [(u'reStructuredText', [[], [(u'docutils', [('', '#id1')])], None])])
+ assert index[4] == (u'S',
+ [(u'Sphinx', [[], [(u'documentation tool', [('', '#id3')])], None])])
+
+
+def test_create_triple_index():
+ # type, value, tid, main, index_key
+ env = Environment({
+ 'index': [
+ ('triple', 'foo; bar; baz', 'id1', '', None),
+ ('triple', 'Python; Sphinx; reST', 'id2', '', None),
+ ],
+ })
+ index = IndexEntries(env).create_index(dummy_builder)
+ assert len(index) == 5
+ assert index[0] == (u'B', [(u'bar', [[], [(u'baz, foo', [('', '#id1')])], None]),
+ (u'baz', [[], [(u'foo bar', [('', '#id1')])], None])])
+ assert index[1] == (u'F', [(u'foo', [[], [(u'bar baz', [('', '#id1')])], None])])
+ assert index[2] == (u'P', [(u'Python', [[], [(u'Sphinx reST', [('', '#id2')])], None])])
+ assert index[3] == (u'R', [(u'reST', [[], [(u'Python Sphinx', [('', '#id2')])], None])])
+ assert index[4] == (u'S', [(u'Sphinx', [[], [(u'reST, Python', [('', '#id2')])], None])])
+
+
+def test_create_see_index():
+ locale.init([], None)
+
+ # type, value, tid, main, index_key
+ env = Environment({
+ 'index': [
+ ('see', 'docutils; reStructuredText', 'id1', '', None),
+ ('see', 'Python; interpreter', 'id2', '', None),
+ ('see', 'Sphinx; documentation tool', 'id3', '', None),
+ ],
+ })
+ index = IndexEntries(env).create_index(dummy_builder)
+ assert len(index) == 3
+ assert index[0] == (u'D', [(u'docutils', [[], [(u'see reStructuredText', [])], None])])
+ assert index[1] == (u'P', [(u'Python', [[], [(u'see interpreter', [])], None])])
+ assert index[2] == (u'S', [(u'Sphinx', [[], [(u'see documentation tool', [])], None])])
+
+
+def test_create_seealso_index():
+ locale.init([], None)
+
+ # type, value, tid, main, index_key
+ env = Environment({
+ 'index': [
+ ('seealso', 'docutils; reStructuredText', 'id1', '', None),
+ ('seealso', 'Python; interpreter', 'id2', '', None),
+ ('seealso', 'Sphinx; documentation tool', 'id3', '', None),
+ ],
+ })
+ index = IndexEntries(env).create_index(dummy_builder)
+ assert len(index) == 3
+ assert index[0] == (u'D',
+ [(u'docutils', [[], [(u'see also reStructuredText', [])], None])])
+ assert index[1] == (u'P',
+ [(u'Python', [[], [(u'see also interpreter', [])], None])])
+ assert index[2] == (u'S',
+ [(u'Sphinx', [[], [(u'see also documentation tool', [])], None])])
+
+
+def test_create_index_by_key():
+ # type, value, tid, main, index_key
+ env = Environment({
+ 'index': [
+ ('single', 'docutils', 'id1', '', None),
+ ('single', 'Python', 'id2', '', None),
+ ('single', u'スフィンクス', 'id3', '', u'ス'),
+ ],
+ })
+ index = IndexEntries(env).create_index(dummy_builder)
+ assert len(index) == 3
+ assert index[0] == (u'D', [(u'docutils', [[('', '#id1')], [], None])])
+ assert index[1] == (u'P', [(u'Python', [[('', '#id2')], [], None])])
+ assert index[2] == (u'ス', [(u'スフィンクス', [[('', '#id3')], [], u'ス'])])
diff --git a/tests/test_environment_toctree.py b/tests/test_environment_toctree.py
new file mode 100644
index 000000000..20188c16a
--- /dev/null
+++ b/tests/test_environment_toctree.py
@@ -0,0 +1,332 @@
+# -*- coding: utf-8 -*-
+"""
+ test_environment_toctree
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Test the sphinx.environment.managers.toctree.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+from docutils.nodes import bullet_list, list_item, caption, comment, reference
+from sphinx import addnodes
+from sphinx.addnodes import compact_paragraph, only
+from sphinx.builders.html import StandaloneHTMLBuilder
+
+from util import with_app, gen_with_app, assert_node
+
+
+@gen_with_app('xml', testroot='toctree')
+def test_basic(app, status, warning):
+ app.build()
+ yield _test_process_doc, app
+ yield _test_get_toc_for, app
+ yield _test_get_toc_for_only, app
+ yield _test_get_toc_for_tocdepth, app
+ yield _test_get_toctree_for, app
+ yield _test_get_toctree_for_collapse, app
+ yield _test_get_toctree_for_maxdepth, app
+ yield _test_get_toctree_for_includehidden, app
+
+
+def _test_process_doc(app):
+ # tocs
+ toctree = app.env.tocs['index']
+ assert_node(toctree,
+ [bullet_list, ([list_item, (compact_paragraph, # [0][0]
+ [bullet_list, (addnodes.toctree, # [0][1][0]
+ only, # [0][1][1]
+ list_item)])], # [0][1][2]
+ [list_item, (compact_paragraph, # [1][0]
+ [bullet_list, (addnodes.toctree, # [1][1][0]
+ addnodes.toctree)])], # [1][1][1]
+ list_item)])
+
+ assert_node(toctree[0][0],
+ [compact_paragraph, reference, "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,
+ titlesonly=False, maxdepth=2, numbered=999,
+ entries=[(None, 'foo'), (None, 'bar'), (None, 'http://sphinx-doc.org/')],
+ includefiles=['foo', 'bar'])
+
+ # only branch
+ assert_node(toctree[0][1][1], addnodes.only, expr="html")
+ assert_node(toctree[0][1][1],
+ [only, list_item, ([compact_paragraph, reference, "Section for HTML"],
+ [bullet_list, addnodes.toctree])])
+ assert_node(toctree[0][1][1][0][0][0], reference, anchorname='#section-for-html')
+ assert_node(toctree[0][1][1][0][1][0], addnodes.toctree,
+ caption=None, glob=False, hidden=False, entries=[(None, 'baz')],
+ includefiles=['baz'], titlesonly=False, maxdepth=-1, numbered=0)
+ assert_node(toctree[0][1][2],
+ ([compact_paragraph, reference, "subsection"],
+ [bullet_list, list_item, compact_paragraph, reference, "subsubsection"]))
+
+ assert_node(toctree[1][0],
+ [compact_paragraph, reference, "Test for issue #1157"])
+ assert_node(toctree[1][0][0], reference, anchorname='#test-for-issue-1157')
+ assert_node(toctree[1][1][0], addnodes.toctree,
+ caption=None, entries=[], glob=False, hidden=False,
+ titlesonly=False, maxdepth=-1, numbered=0)
+ assert_node(toctree[1][1][1], addnodes.toctree,
+ caption=None, glob=False, hidden=True,
+ titlesonly=False, maxdepth=-1, numbered=0,
+ entries=[('Latest reference', 'http://sphinx-doc.org/latest/'),
+ ('Python', 'http://python.org/')])
+
+ assert_node(toctree[2][0],
+ [compact_paragraph, reference, "Indices and tables"])
+
+ # other collections
+ assert app.env.toc_num_entries['index'] == 6
+ assert app.env.toctree_includes['index'] == ['foo', 'bar', 'baz']
+ assert app.env.files_to_rebuild['foo'] == set(['index'])
+ assert app.env.files_to_rebuild['bar'] == set(['index'])
+ assert app.env.files_to_rebuild['baz'] == set(['index'])
+ assert app.env.glob_toctrees == set()
+ assert app.env.numbered_toctrees == set(['index'])
+
+ # qux has no section title
+ assert len(app.env.tocs['qux']) == 0
+ assert_node(app.env.tocs['qux'], nodes.bullet_list)
+ assert app.env.toc_num_entries['qux'] == 0
+ assert 'qux' not in app.env.toctree_includes
+
+
+@with_app('dummy', testroot='toctree-glob')
+def test_glob(app, status, warning):
+ includefiles = ['foo', 'bar/index', 'bar/bar_1', 'bar/bar_2',
+ 'bar/bar_3', 'baz', 'qux/index']
+
+ app.build()
+
+ # tocs
+ toctree = app.env.tocs['index']
+ assert_node(toctree,
+ [bullet_list, list_item, (compact_paragraph, # [0][0]
+ [bullet_list, (list_item, # [0][1][0]
+ list_item)])]) # [0][1][1]
+
+ assert_node(toctree[0][0],
+ [compact_paragraph, reference, "test-toctree-glob"])
+ assert_node(toctree[0][1][0],
+ [list_item, ([compact_paragraph, reference, "normal order"],
+ [bullet_list, addnodes.toctree])]) # [0][1][0][1][0]
+ assert_node(toctree[0][1][0][1][0], addnodes.toctree, caption=None,
+ glob=True, hidden=False, titlesonly=False,
+ maxdepth=-1, numbered=0, includefiles=includefiles,
+ entries=[(None, 'foo'), (None, 'bar/index'), (None, 'bar/bar_1'),
+ (None, 'bar/bar_2'), (None, 'bar/bar_3'), (None, 'baz'),
+ (None, 'qux/index')])
+ assert_node(toctree[0][1][1],
+ [list_item, ([compact_paragraph, reference, "reversed order"],
+ [bullet_list, addnodes.toctree])]) # [0][1][1][1][0]
+ assert_node(toctree[0][1][1][1][0], addnodes.toctree, caption=None,
+ glob=True, hidden=False, titlesonly=False,
+ maxdepth=-1, numbered=0, includefiles=includefiles,
+ entries=[(None, 'qux/index'), (None, 'baz'), (None, 'bar/bar_3'),
+ (None, 'bar/bar_2'), (None, 'bar/bar_1'), (None, 'bar/index'),
+ (None, 'foo')])
+ includefiles = ['foo', 'bar/index', 'bar/bar_1', 'bar/bar_2',
+ 'bar/bar_3', 'baz', 'qux/index']
+
+ # other collections
+ assert app.env.toc_num_entries['index'] == 3
+ assert app.env.toctree_includes['index'] == includefiles + includefiles
+ for file in includefiles:
+ assert 'index' in app.env.files_to_rebuild[file]
+ assert 'index' in app.env.glob_toctrees
+ assert app.env.numbered_toctrees == set()
+
+
+def _test_get_toc_for(app):
+ toctree = app.env.get_toc_for('index', app.builder)
+
+ assert_node(toctree,
+ [bullet_list, ([list_item, (compact_paragraph, # [0][0]
+ [bullet_list, (addnodes.toctree, # [0][1][0]
+ comment, # [0][1][1]
+ list_item)])], # [0][1][2]
+ [list_item, (compact_paragraph, # [1][0]
+ [bullet_list, (addnodes.toctree,
+ addnodes.toctree)])],
+ [list_item, compact_paragraph])]) # [2][0]
+ assert_node(toctree[0][0],
+ [compact_paragraph, reference, "Welcome to Sphinx Tests's documentation!"])
+ assert_node(toctree[0][1][2],
+ ([compact_paragraph, reference, "subsection"],
+ [bullet_list, list_item, compact_paragraph, reference, "subsubsection"]))
+ assert_node(toctree[1][0],
+ [compact_paragraph, reference, "Test for issue #1157"])
+ assert_node(toctree[2][0],
+ [compact_paragraph, reference, "Indices and tables"])
+
+
+def _test_get_toc_for_only(app):
+ builder = StandaloneHTMLBuilder(app)
+ toctree = app.env.get_toc_for('index', builder)
+
+ assert_node(toctree,
+ [bullet_list, ([list_item, (compact_paragraph, # [0][0]
+ [bullet_list, (addnodes.toctree, # [0][1][0]
+ list_item, # [0][1][1]
+ list_item)])], # [0][1][2]
+ [list_item, (compact_paragraph, # [1][0]
+ [bullet_list, (addnodes.toctree,
+ addnodes.toctree)])],
+ [list_item, compact_paragraph])]) # [2][0]
+ assert_node(toctree[0][0],
+ [compact_paragraph, reference, "Welcome to Sphinx Tests's documentation!"])
+ assert_node(toctree[0][1][1],
+ ([compact_paragraph, reference, "Section for HTML"],
+ [bullet_list, addnodes.toctree]))
+ assert_node(toctree[0][1][2],
+ ([compact_paragraph, reference, "subsection"],
+ [bullet_list, list_item, compact_paragraph, reference, "subsubsection"]))
+ assert_node(toctree[1][0],
+ [compact_paragraph, reference, "Test for issue #1157"])
+ assert_node(toctree[2][0],
+ [compact_paragraph, reference, "Indices and tables"])
+
+
+def _test_get_toc_for_tocdepth(app):
+ toctree = app.env.get_toc_for('tocdepth', app.builder)
+
+ assert_node(toctree,
+ [bullet_list, list_item, (compact_paragraph, # [0][0]
+ bullet_list)]) # [0][1]
+ assert_node(toctree[0][0],
+ [compact_paragraph, reference, "level 1"])
+ assert_node(toctree[0][1],
+ [bullet_list, list_item, compact_paragraph, reference, "level 2"])
+
+
+def _test_get_toctree_for(app):
+ toctree = app.env.get_toctree_for('index', app.builder, collapse=False)
+ assert_node(toctree,
+ [compact_paragraph, ([caption, "Table of Contents"],
+ bullet_list,
+ bullet_list,
+ bullet_list)])
+
+ assert_node(toctree[1],
+ ([list_item, ([compact_paragraph, reference, "foo"],
+ bullet_list)],
+ [list_item, compact_paragraph, reference, "bar"],
+ [list_item, compact_paragraph, reference, "http://sphinx-doc.org/"]))
+ assert_node(toctree[1][0][1],
+ ([list_item, compact_paragraph, reference, "quux"],
+ [list_item, compact_paragraph, reference, "foo.1"],
+ [list_item, compact_paragraph, reference, "foo.2"]))
+
+ assert_node(toctree[1][0][0][0], reference, refuri="foo", secnumber=(1,))
+ assert_node(toctree[1][0][1][0][0][0], reference, refuri="quux", secnumber=(1, 1))
+ assert_node(toctree[1][0][1][1][0][0], reference, refuri="foo#foo-1", secnumber=(1, 2))
+ assert_node(toctree[1][0][1][2][0][0], reference, refuri="foo#foo-2", secnumber=(1, 3))
+ assert_node(toctree[1][1][0][0], reference, refuri="bar", secnumber=(2,))
+ assert_node(toctree[1][2][0][0], reference, refuri="http://sphinx-doc.org/")
+
+ assert_node(toctree[2],
+ [bullet_list, list_item, compact_paragraph, reference, "baz"])
+ assert_node(toctree[3],
+ ([list_item, compact_paragraph, reference, "Latest reference"],
+ [list_item, compact_paragraph, reference, "Python"]))
+ assert_node(toctree[3][0][0][0], reference, refuri="http://sphinx-doc.org/latest/")
+ assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
+
+
+def _test_get_toctree_for_collapse(app):
+ toctree = app.env.get_toctree_for('index', app.builder, collapse=True)
+ assert_node(toctree,
+ [compact_paragraph, ([caption, "Table of Contents"],
+ bullet_list,
+ bullet_list,
+ bullet_list)])
+
+ assert_node(toctree[1],
+ ([list_item, compact_paragraph, reference, "foo"],
+ [list_item, compact_paragraph, reference, "bar"],
+ [list_item, compact_paragraph, reference, "http://sphinx-doc.org/"]))
+ assert_node(toctree[1][0][0][0], reference, refuri="foo", secnumber=(1,))
+ assert_node(toctree[1][1][0][0], reference, refuri="bar", secnumber=(2,))
+ assert_node(toctree[1][2][0][0], reference, refuri="http://sphinx-doc.org/")
+
+ assert_node(toctree[2],
+ [bullet_list, list_item, compact_paragraph, reference, "baz"])
+ assert_node(toctree[3],
+ ([list_item, compact_paragraph, reference, "Latest reference"],
+ [list_item, compact_paragraph, reference, "Python"]))
+ assert_node(toctree[3][0][0][0], reference, refuri="http://sphinx-doc.org/latest/")
+ assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
+
+
+def _test_get_toctree_for_maxdepth(app):
+ toctree = app.env.get_toctree_for('index', app.builder, collapse=False, maxdepth=3)
+ assert_node(toctree,
+ [compact_paragraph, ([caption, "Table of Contents"],
+ bullet_list,
+ bullet_list,
+ bullet_list)])
+
+ assert_node(toctree[1],
+ ([list_item, ([compact_paragraph, reference, "foo"],
+ bullet_list)],
+ [list_item, compact_paragraph, reference, "bar"],
+ [list_item, compact_paragraph, reference, "http://sphinx-doc.org/"]))
+ assert_node(toctree[1][0][1],
+ ([list_item, compact_paragraph, reference, "quux"],
+ [list_item, ([compact_paragraph, reference, "foo.1"],
+ bullet_list)],
+ [list_item, compact_paragraph, reference, "foo.2"]))
+ assert_node(toctree[1][0][1][1][1],
+ [bullet_list, list_item, compact_paragraph, reference, "foo.1-1"])
+
+ assert_node(toctree[1][0][0][0], reference, refuri="foo", secnumber=(1,))
+ assert_node(toctree[1][0][1][0][0][0], reference, refuri="quux", secnumber=(1, 1))
+ assert_node(toctree[1][0][1][1][0][0], reference, refuri="foo#foo-1", secnumber=(1, 2))
+ assert_node(toctree[1][0][1][1][1][0][0][0],
+ reference, refuri="foo#foo-1-1", secnumber=(1, 2, 1))
+ assert_node(toctree[1][0][1][2][0][0], reference, refuri="foo#foo-2", secnumber=(1, 3))
+ assert_node(toctree[1][1][0][0], reference, refuri="bar", secnumber=(2,))
+ assert_node(toctree[1][2][0][0], reference, refuri="http://sphinx-doc.org/")
+
+ assert_node(toctree[2],
+ [bullet_list, list_item, compact_paragraph, reference, "baz"])
+ assert_node(toctree[3],
+ ([list_item, compact_paragraph, reference, "Latest reference"],
+ [list_item, compact_paragraph, reference, "Python"]))
+ assert_node(toctree[3][0][0][0], reference, refuri="http://sphinx-doc.org/latest/")
+ assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
+
+
+def _test_get_toctree_for_includehidden(app):
+ toctree = app.env.get_toctree_for('index', app.builder, collapse=False,
+ includehidden=False)
+ assert_node(toctree,
+ [compact_paragraph, ([caption, "Table of Contents"],
+ bullet_list,
+ bullet_list)])
+
+ assert_node(toctree[1],
+ ([list_item, ([compact_paragraph, reference, "foo"],
+ bullet_list)],
+ [list_item, compact_paragraph, reference, "bar"],
+ [list_item, compact_paragraph, reference, "http://sphinx-doc.org/"]))
+ assert_node(toctree[1][0][1],
+ ([list_item, compact_paragraph, reference, "quux"],
+ [list_item, compact_paragraph, reference, "foo.1"],
+ [list_item, compact_paragraph, reference, "foo.2"]))
+
+ assert_node(toctree[1][0][0][0], reference, refuri="foo", secnumber=(1,))
+ assert_node(toctree[1][0][1][0][0][0], reference, refuri="quux", secnumber=(1, 1))
+ assert_node(toctree[1][0][1][1][0][0], reference, refuri="foo#foo-1", secnumber=(1, 2))
+ assert_node(toctree[1][0][1][2][0][0], reference, refuri="foo#foo-2", secnumber=(1, 3))
+ assert_node(toctree[1][1][0][0], reference, refuri="bar", secnumber=(2,))
+ assert_node(toctree[1][2][0][0], reference, refuri="http://sphinx-doc.org/")
+
+ assert_node(toctree[2],
+ [bullet_list, list_item, compact_paragraph, reference, "baz"])
diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py
new file mode 100644
index 000000000..dad7521af
--- /dev/null
+++ b/tests/test_ext_autodoc.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+"""
+ test_autodoc
+ ~~~~~~~~~~~~
+
+ Test the autodoc extension.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import pickle
+from docutils import nodes
+from sphinx import addnodes
+from util import with_app
+
+
+@with_app(buildername='dummy', testroot='ext-autodoc')
+def test_autodoc(app, status, warning):
+ app.builder.build_all()
+
+ content = pickle.loads((app.doctreedir / 'contents.doctree').bytes())
+ assert isinstance(content[3], addnodes.desc)
+ assert content[3][0].astext() == 'autodoc_dummy_module.test'
+ assert content[3][1].astext() == 'Dummy function using dummy.*'
diff --git a/tests/test_ext_graphviz.py b/tests/test_ext_graphviz.py
index dbab33761..aa97f4135 100644
--- a/tests/test_ext_graphviz.py
+++ b/tests/test_ext_graphviz.py
@@ -55,6 +55,10 @@ def test_graphviz_html(app, status, warning):
html = '<img src=".*?" alt="digraph {\n bar -&gt; baz\n}" />'
assert re.search(html, content, re.M)
+ html = ('<div class="figure align-right" .*?>\s*<img .*?/>\s*<p class="caption">'
+ '<span class="caption-text">on right</span>.*</p>\s*</div>')
+ assert re.search(html, content, re.S)
+
@with_app('latex', testroot='ext-graphviz')
@skip_if_graphviz_not_found
@@ -70,6 +74,11 @@ def test_graphviz_latex(app, status, warning):
macro = 'Hello \\\\includegraphics{graphviz-\w+.pdf} graphviz world'
assert re.search(macro, content, re.S)
+ macro = ('\\\\begin{wrapfigure}{r}{0pt}\n\\\\centering\n'
+ '\\\\includegraphics{graphviz-\w+.pdf}\n'
+ '\\\\caption{on right}\\\\label{.*}\\\\end{wrapfigure}')
+ assert re.search(macro, content, re.S)
+
@with_app('html', testroot='ext-graphviz', confoverrides={'language': 'xx'})
@skip_if_graphviz_not_found
diff --git a/tests/test_ext_inheritance_diagram.py b/tests/test_ext_inheritance_diagram.py
index 64446eed8..bf1bbbac0 100644
--- a/tests/test_ext_inheritance_diagram.py
+++ b/tests/test_ext_inheritance_diagram.py
@@ -9,9 +9,34 @@
:license: BSD, see LICENSE for details.
"""
+import re
from util import with_app
+from test_ext_graphviz import skip_if_graphviz_not_found
@with_app('html', testroot='ext-inheritance_diagram')
+@skip_if_graphviz_not_found
def test_inheritance_diagram_html(app, status, warning):
app.builder.build_all()
+
+ content = (app.outdir / 'index.html').text()
+
+ pattern = ('<div class="figure" id="id1">\n'
+ '<img src="_images/inheritance-\w+.png" alt="Inheritance diagram of test.Foo" '
+ 'class="inheritance"/>\n<p class="caption"><span class="caption-text">'
+ 'Test Foo!</span><a class="headerlink" href="#id1" '
+ 'title="Permalink to this image">\xb6</a></p>')
+ assert re.search(pattern, content, re.M)
+
+
+@with_app('latex', testroot='ext-inheritance_diagram')
+@skip_if_graphviz_not_found
+def test_inheritance_diagram_latex(app, status, warning):
+ app.builder.build_all()
+
+ content = (app.outdir / 'Python.tex').text()
+
+ pattern = ('\\\\begin{figure}\\[htbp]\n\\\\centering\n\\\\capstart\n\n'
+ '\\\\includegraphics{inheritance-\\w+.pdf}\n'
+ '\\\\caption{Test Foo!}\\\\label{index:id1}\\\\end{figure}')
+ assert re.search(pattern, content, re.M)
diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py
index deec5a379..e1995e3d3 100644
--- a/tests/test_ext_intersphinx.py
+++ b/tests/test_ext_intersphinx.py
@@ -15,13 +15,15 @@ import zlib
from six import BytesIO
from docutils import nodes
+import mock
from sphinx import addnodes
-from sphinx.ext.intersphinx import read_inventory_v1, read_inventory_v2, \
+from sphinx.ext.intersphinx import setup as intersphinx_setup
+from sphinx.ext.intersphinx import read_inventory, \
load_mappings, missing_reference, _strip_basic_auth, _read_from_url, \
_get_safe_url, fetch_inventory, INVENTORY_FILENAME
-from util import with_app, with_tempdir, mock
+from util import with_app, with_tempdir
inventory_v1 = '''\
@@ -49,8 +51,7 @@ a term including:colon std:term -1 glossary.html#term-a-term-including-colon -
def test_read_inventory_v1():
f = BytesIO(inventory_v1)
- f.readline()
- invdata = read_inventory_v1(f, '/util', posixpath.join)
+ invdata = read_inventory(f, '/util', posixpath.join)
assert invdata['py:module']['module'] == \
('foo', '1.0', '/util/foo.html#module-module', '-')
assert invdata['py:class']['module.cls'] == \
@@ -59,13 +60,11 @@ def test_read_inventory_v1():
def test_read_inventory_v2():
f = BytesIO(inventory_v2)
- f.readline()
- invdata1 = read_inventory_v2(f, '/util', posixpath.join)
+ invdata1 = read_inventory(f, '/util', posixpath.join)
# try again with a small buffer size to test the chunking algorithm
f = BytesIO(inventory_v2)
- f.readline()
- invdata2 = read_inventory_v2(f, '/util', posixpath.join, bufsize=5)
+ invdata2 = read_inventory(f, '/util', posixpath.join, bufsize=5)
assert invdata1 == invdata2
@@ -84,47 +83,48 @@ def test_read_inventory_v2():
@with_app()
-@mock.patch('sphinx.ext.intersphinx.read_inventory_v2')
+@mock.patch('sphinx.ext.intersphinx.read_inventory')
@mock.patch('sphinx.ext.intersphinx._read_from_url')
-def test_fetch_inventory_redirection(app, status, warning, _read_from_url, read_inventory_v2):
+def test_fetch_inventory_redirection(app, status, warning, _read_from_url, read_inventory):
+ intersphinx_setup(app)
_read_from_url().readline.return_value = '# Sphinx inventory version 2'.encode('utf-8')
# same uri and inv, not redirected
- _read_from_url().geturl.return_value = 'http://hostname/' + INVENTORY_FILENAME
+ _read_from_url().url = 'http://hostname/' + INVENTORY_FILENAME
fetch_inventory(app, 'http://hostname/', 'http://hostname/' + INVENTORY_FILENAME)
assert 'intersphinx inventory has moved' not in status.getvalue()
- assert read_inventory_v2.call_args[0][1] == 'http://hostname/'
+ assert read_inventory.call_args[0][1] == 'http://hostname/'
# same uri and inv, redirected
status.seek(0)
status.truncate(0)
- _read_from_url().geturl.return_value = 'http://hostname/new/' + INVENTORY_FILENAME
+ _read_from_url().url = 'http://hostname/new/' + INVENTORY_FILENAME
fetch_inventory(app, 'http://hostname/', 'http://hostname/' + INVENTORY_FILENAME)
assert status.getvalue() == ('intersphinx inventory has moved: '
'http://hostname/%s -> http://hostname/new/%s\n' %
(INVENTORY_FILENAME, INVENTORY_FILENAME))
- assert read_inventory_v2.call_args[0][1] == 'http://hostname/new'
+ assert read_inventory.call_args[0][1] == 'http://hostname/new'
# different uri and inv, not redirected
status.seek(0)
status.truncate(0)
- _read_from_url().geturl.return_value = 'http://hostname/new/' + INVENTORY_FILENAME
+ _read_from_url().url = 'http://hostname/new/' + INVENTORY_FILENAME
fetch_inventory(app, 'http://hostname/', 'http://hostname/new/' + INVENTORY_FILENAME)
assert 'intersphinx inventory has moved' not in status.getvalue()
- assert read_inventory_v2.call_args[0][1] == 'http://hostname/'
+ assert read_inventory.call_args[0][1] == 'http://hostname/'
# different uri and inv, redirected
status.seek(0)
status.truncate(0)
- _read_from_url().geturl.return_value = 'http://hostname/other/' + INVENTORY_FILENAME
+ _read_from_url().url = 'http://hostname/other/' + INVENTORY_FILENAME
fetch_inventory(app, 'http://hostname/', 'http://hostname/new/' + INVENTORY_FILENAME)
assert status.getvalue() == ('intersphinx inventory has moved: '
'http://hostname/new/%s -> http://hostname/other/%s\n' %
(INVENTORY_FILENAME, INVENTORY_FILENAME))
- assert read_inventory_v2.call_args[0][1] == 'http://hostname/'
+ assert read_inventory.call_args[0][1] == 'http://hostname/'
@with_app()
@@ -248,64 +248,23 @@ class TestStripBasicAuth(unittest.TestCase):
"""basic auth creds stripped from URL containing creds"""
url = 'https://user:12345@domain.com/project/objects.inv'
expected = 'https://domain.com/project/objects.inv'
- actual_url, actual_username, actual_password = _strip_basic_auth(url)
- self.assertEqual(expected, actual_url)
- self.assertEqual('user', actual_username)
- self.assertEqual('12345', actual_password)
+ actual = _strip_basic_auth(url)
+ self.assertEqual(expected, actual)
def test_no_auth(self):
"""url unchanged if param doesn't contain basic auth creds"""
url = 'https://domain.com/project/objects.inv'
expected = 'https://domain.com/project/objects.inv'
- actual_url, actual_username, actual_password = _strip_basic_auth(url)
- self.assertEqual(expected, actual_url)
- self.assertEqual(None, actual_username)
- self.assertEqual(None, actual_password)
+ actual = _strip_basic_auth(url)
+ self.assertEqual(expected, actual)
def test_having_port(self):
"""basic auth creds correctly stripped from URL containing creds even if URL
contains port"""
url = 'https://user:12345@domain.com:8080/project/objects.inv'
expected = 'https://domain.com:8080/project/objects.inv'
- actual_url, actual_username, actual_password = _strip_basic_auth(url)
- self.assertEqual(expected, actual_url)
- self.assertEqual('user', actual_username)
- self.assertEqual('12345', actual_password)
-
-
-@mock.patch('six.moves.urllib.request.HTTPBasicAuthHandler')
-@mock.patch('six.moves.urllib.request.HTTPPasswordMgrWithDefaultRealm')
-@mock.patch('six.moves.urllib.request.build_opener')
-def test_readfromurl_authed(m_build_opener, m_HTTPPasswordMgrWithDefaultRealm,
- m_HTTPBasicAuthHandler):
- # read from URL containing basic auth creds
- password_mgr = mock.Mock()
- m_HTTPPasswordMgrWithDefaultRealm.return_value = password_mgr
-
- url = 'https://user:12345@domain.com/project/objects.inv'
- _read_from_url(url)
-
- m_HTTPPasswordMgrWithDefaultRealm.assert_called_once_with()
- password_mgr.add_password.assert_called_with(
- None, 'https://domain.com/project/objects.inv', 'user', '12345')
-
-
-@mock.patch('six.moves.urllib.request.HTTPBasicAuthHandler')
-@mock.patch('six.moves.urllib.request.HTTPPasswordMgrWithDefaultRealm')
-@mock.patch('sphinx.ext.intersphinx.default_opener')
-def test_readfromurl_unauthed(m_default_opener, m_HTTPPasswordMgrWithDefaultRealm,
- m_HTTPBasicAuthHandler):
- # read from URL without auth creds
- password_mgr = mock.Mock()
- m_HTTPPasswordMgrWithDefaultRealm.return_value = password_mgr
-
- url = 'https://domain.com/project/objects.inv'
- _read_from_url(url)
-
- # assert password manager not created
- assert m_HTTPPasswordMgrWithDefaultRealm.call_args is None
- # assert no password added to the password manager
- assert password_mgr.add_password.call_args is None
+ actual = _strip_basic_auth(url)
+ self.assertEqual(expected, actual)
def test_getsafeurl_authed():
@@ -316,6 +275,14 @@ def test_getsafeurl_authed():
assert expected == actual
+def test_getsafeurl_authed_having_port():
+ """_get_safe_url() with a url with basic auth having port"""
+ url = 'https://user:12345@domain.com:8080/project/objects.inv'
+ expected = 'https://user@domain.com:8080/project/objects.inv'
+ actual = _get_safe_url(url)
+ assert expected == actual
+
+
def test_getsafeurl_unauthed():
"""_get_safe_url() with a url without basic auth"""
url = 'https://domain.com/project/objects.inv'
diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py
index c858afcd2..0c7d44e8e 100644
--- a/tests/test_ext_math.py
+++ b/tests/test_ext_math.py
@@ -22,10 +22,13 @@ def test_jsmath(app, status, warning):
assert '<div class="math">\na^2 + b^2 = c^2</div>' in content
assert '<div class="math">\n\\begin{split}a + 1 &lt; b\\end{split}</div>' in content
- assert ('<span class="eqno">(1)</span><div class="math" id="equation-foo">\n'
- 'e^{i\\pi} = 1</div>' in content)
- assert ('<span class="eqno">(2)</span><div class="math">\n'
- 'e^{ix} = \\cos x + i\\sin x</div>' in content)
+ assert (u'<span class="eqno">(1)<a class="headerlink" href="#equation-foo" '
+ u'title="Permalink to this equation">\xb6</a></span>'
+ u'<div class="math" id="equation-foo">\ne^{i\\pi} = 1</div>' in content)
+ assert (u'<span class="eqno">(2)<a class="headerlink" href="#equation-math:0" '
+ u'title="Permalink to this equation">\xb6</a></span>'
+ u'<div class="math" id="equation-math:0">\n'
+ u'e^{ix} = \\cos x + i\\sin x</div>' in content)
assert '<div class="math">\nn \\in \\mathbb N</div>' in content
assert '<div class="math">\na + 1 &lt; b</div>' in content
@@ -80,8 +83,8 @@ def test_math_number_all_mathjax(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
- html = (r'<div class="math">\s*'
- r'<span class="eqno">\(1\)</span>\\\[a\^2\+b\^2=c\^2\\\]</div>')
+ html = (r'<div class="math" id="equation-index:0">\s*'
+ r'<span class="eqno">\(1\)<a .*>\xb6</a></span>\\\[a\^2\+b\^2=c\^2\\\]</div>')
assert re.search(html, content, re.S)
@@ -109,3 +112,6 @@ def test_math_number_all_latex(app, status, warning):
r'V &= \\frac\{4}\{3} \\pi r\^3\\\\\s*'
r'\\end{aligned}\\end{align\*}')
assert re.search(macro, content, re.S)
+
+ macro = r'Referencing equation \\eqref{equation:math:foo}.'
+ assert re.search(macro, content, re.S)
diff --git a/tests/test_ext_napoleon.py b/tests/test_ext_napoleon.py
index d4ce96001..7ecd08292 100644
--- a/tests/test_ext_napoleon.py
+++ b/tests/test_ext_napoleon.py
@@ -16,7 +16,7 @@ from unittest import TestCase
from sphinx.application import Sphinx
from sphinx.ext.napoleon import (_process_docstring, _skip_member, Config,
setup)
-from util import mock
+import mock
def _private_doc():
diff --git a/tests/test_ext_napoleon_docstring.py b/tests/test_ext_napoleon_docstring.py
index 17c1a7a56..37dcca90c 100644
--- a/tests/test_ext_napoleon_docstring.py
+++ b/tests/test_ext_napoleon_docstring.py
@@ -19,7 +19,7 @@ from unittest import TestCase
from sphinx.ext.napoleon import Config
from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
-from util import mock
+import mock
class NamedtupleSubclass(namedtuple('NamedtupleSubclass', ('attr1', 'attr2'))):
@@ -222,6 +222,24 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
+ Args:
+ arg1 (list(int)): Description
+ arg2 (list[int]): Description
+ arg3 (dict(str, int)): Description
+ arg4 (dict[str, int]): Description
+ """,
+ """
+ Single line summary
+
+ :Parameters: * **arg1** (*list(int)*) -- Description
+ * **arg2** (*list[int]*) -- Description
+ * **arg3** (*dict(str, int)*) -- Description
+ * **arg4** (*dict[str, int]*) -- Description
+ """
+ ), (
+ """
+ Single line summary
+
Yield:
str:Extended
description of yielded value
@@ -249,7 +267,11 @@ class GoogleDocstringTest(BaseDocstringTest):
)]
def test_docstrings(self):
- config = Config(napoleon_use_param=False, napoleon_use_rtype=False)
+ config = Config(
+ napoleon_use_param=False,
+ napoleon_use_rtype=False,
+ napoleon_use_keyword=False
+ )
for docstring, expected in self.docstrings:
actual = str(GoogleDocstring(dedent(docstring), config))
expected = dedent(expected)
@@ -325,7 +347,9 @@ Returns:
codecode
"""
expected = """
-:returns: foo::
+:returns:
+
+ foo::
codecode
codecode
@@ -1046,7 +1070,10 @@ class NumpyDocstringTest(BaseDocstringTest):
)]
def test_docstrings(self):
- config = Config(napoleon_use_param=False, napoleon_use_rtype=False)
+ config = Config(
+ napoleon_use_param=False,
+ napoleon_use_rtype=False,
+ napoleon_use_keyword=False)
for docstring, expected in self.docstrings:
actual = str(NumpyDocstring(dedent(docstring), config))
expected = dedent(expected)
@@ -1736,3 +1763,19 @@ definition_after_normal_text : int
config = Config(napoleon_use_param=False)
actual = str(NumpyDocstring(docstring, config))
self.assertEqual(expected, actual)
+
+ def test_keywords_with_types(self):
+ docstring = """\
+Do as you please
+
+Keyword Args:
+ gotham_is_yours (None): shall interfere.
+"""
+ actual = str(GoogleDocstring(docstring))
+ expected = """\
+Do as you please
+
+:keyword gotham_is_yours: shall interfere.
+:kwtype gotham_is_yours: None
+"""
+ self.assertEqual(expected, actual)
diff --git a/tests/test_ext_todo.py b/tests/test_ext_todo.py
new file mode 100644
index 000000000..269a8a2be
--- /dev/null
+++ b/tests/test_ext_todo.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+"""
+ test_ext_todo
+ ~~~~~~~~~~~~~
+
+ Test sphinx.ext.todo extension.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+from util import with_app
+
+
+@with_app('html', testroot='ext-todo', freshenv=True,
+ confoverrides={'todo_include_todos': True, 'todo_emit_warnings': True})
+def test_todo(app, status, warning):
+ todos = []
+
+ def on_todo_defined(app, node):
+ todos.append(node)
+
+ app.connect('todo-defined', on_todo_defined)
+ app.builder.build_all()
+
+ # check todolist
+ content = (app.outdir / 'index.html').text()
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in foo</p>')
+ assert re.search(html, content, re.S)
+
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in bar</p>')
+ assert re.search(html, content, re.S)
+
+ # check todo
+ content = (app.outdir / 'foo.html').text()
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in foo</p>')
+ assert re.search(html, content, re.S)
+
+ # check emitted warnings
+ assert 'WARNING: TODO entry found: todo in foo' in warning.getvalue()
+ assert 'WARNING: TODO entry found: todo in bar' in warning.getvalue()
+
+ # check handled event
+ assert len(todos) == 2
+ assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar'])
+
+
+@with_app('html', testroot='ext-todo', freshenv=True,
+ confoverrides={'todo_include_todos': False, 'todo_emit_warnings': True})
+def test_todo_not_included(app, status, warning):
+ todos = []
+
+ def on_todo_defined(app, node):
+ todos.append(node)
+
+ app.connect('todo-defined', on_todo_defined)
+ app.builder.build_all()
+
+ # check todolist
+ content = (app.outdir / 'index.html').text()
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in foo</p>')
+ assert not re.search(html, content, re.S)
+
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in bar</p>')
+ assert not re.search(html, content, re.S)
+
+ # check todo
+ content = (app.outdir / 'foo.html').text()
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in foo</p>')
+ assert not re.search(html, content, re.S)
+
+ # check emitted warnings
+ assert 'WARNING: TODO entry found: todo in foo' in warning.getvalue()
+ assert 'WARNING: TODO entry found: todo in bar' in warning.getvalue()
+
+ # check handled event
+ assert len(todos) == 2
+ assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar'])
diff --git a/tests/test_intl.py b/tests/test_intl.py
index b31f1678b..43cd17c8e 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -118,6 +118,11 @@ def assert_count(expected_expr, result, count):
def test_text_builder(app, status, warning):
app.builder.build_all()
+ # --- toctree
+
+ result = (app.outdir / 'contents.txt').text(encoding='utf-8')
+ yield assert_startswith, result, u"CONTENTS\n********\n\nTABLE OF CONTENTS\n"
+
# --- warnings in translation
warnings = getwarning(warning)
@@ -126,7 +131,7 @@ def test_text_builder(app, status, warning):
yield assert_re_search, warning_expr, warnings
result = (app.outdir / 'warnings.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH REST WARNINGS"
+ expect = (u"I18N WITH REST WARNINGS"
u"\n***********************\n"
u"\nLINE OF >>``<<BROKEN LITERAL MARKUP.\n")
yield assert_equal, result, expect
@@ -134,7 +139,7 @@ def test_text_builder(app, status, warning):
# --- simple translation; check title underlines
result = (app.outdir / 'bom.txt').text(encoding='utf-8')
- expect = (u"\nDatei mit UTF-8"
+ expect = (u"Datei mit UTF-8"
u"\n***************\n" # underline matches new translation
u"\nThis file has umlauts: äöü.\n")
yield assert_equal, result, expect
@@ -142,12 +147,12 @@ def test_text_builder(app, status, warning):
# --- check translation in subdirs
result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8')
- yield assert_startswith, result, u"\nsubdir contents\n***************\n"
+ yield assert_startswith, result, u"subdir contents\n***************\n"
# --- check warnings for inconsistency in number of references
result = (app.outdir / 'refs_inconsistency.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH REFS INCONSISTENCY"
+ expect = (u"I18N WITH REFS INCONSISTENCY"
u"\n****************************\n"
u"\n* FOR FOOTNOTE [ref2].\n"
u"\n* reference FOR reference.\n"
@@ -169,7 +174,7 @@ def test_text_builder(app, status, warning):
# --- check warning for literal block
result = (app.outdir / 'literalblock.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH LITERAL BLOCK"
+ expect = (u"I18N WITH LITERAL BLOCK"
u"\n***********************\n"
u"\nCORRECT LITERAL BLOCK:\n"
u"\n this is"
@@ -186,7 +191,7 @@ def test_text_builder(app, status, warning):
# --- definition terms: regression test for #975, #2198, #2205
result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH DEFINITION TERMS"
+ expect = (u"I18N WITH DEFINITION TERMS"
u"\n**************************\n"
u"\nSOME TERM"
u"\n THE CORRESPONDING DEFINITION\n"
@@ -202,7 +207,7 @@ def test_text_builder(app, status, warning):
# --- glossary terms: regression test for #1090
result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH GLOSSARY TERMS"
+ expect = (u"I18N WITH GLOSSARY TERMS"
u"\n************************\n"
u"\nSOME NEW TERM"
u"\n THE CORRESPONDING GLOSSARY\n"
@@ -216,7 +221,7 @@ def test_text_builder(app, status, warning):
# --- glossary term inconsistencies: regression test for #1090
result = (app.outdir / 'glossary_terms_inconsistency.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH GLOSSARY TERMS INCONSISTENCY"
+ expect = (u"I18N WITH GLOSSARY TERMS INCONSISTENCY"
u"\n**************************************\n"
u"\n1. LINK TO *SOME NEW TERM*.\n")
yield assert_equal, result, expect
@@ -230,7 +235,7 @@ def test_text_builder(app, status, warning):
# --- seealso
result = (app.outdir / 'seealso.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH SEEALSO"
+ expect = (u"I18N WITH SEEALSO"
u"\n*****************\n"
u"\nSee also: SHORT TEXT 1\n"
u"\nSee also: LONG TEXT 1\n"
@@ -241,7 +246,7 @@ def test_text_builder(app, status, warning):
# --- figure captions: regression test for #940
result = (app.outdir / 'figure.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH FIGURE CAPTION"
+ expect = (u"I18N WITH FIGURE CAPTION"
u"\n************************\n"
u"\n [image]MY CAPTION OF THE FIGURE\n"
u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
@@ -267,7 +272,7 @@ def test_text_builder(app, status, warning):
# --- rubric: regression test for pull request #190
result = (app.outdir / 'rubric.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH RUBRIC"
+ expect = (u"I18N WITH RUBRIC"
u"\n****************\n"
u"\n-[ RUBRIC TITLE ]-\n"
u"\n"
@@ -280,7 +285,7 @@ def test_text_builder(app, status, warning):
# --- docfields
result = (app.outdir / 'docfields.txt').text(encoding='utf-8')
- expect = (u"\nI18N WITH DOCFIELDS"
+ expect = (u"I18N WITH DOCFIELDS"
u"\n*******************\n"
u"\nclass Cls1\n"
u"\n Parameters:"
@@ -318,6 +323,12 @@ def test_text_builder(app, status, warning):
def test_gettext_builder(app, status, warning):
app.builder.build_all()
+ # --- toctree
+ expect = read_po(app.srcdir / 'contents.po')
+ actual = read_po(app.outdir / 'contents.pot')
+ for expect_msg in [m for m in expect if m.id]:
+ yield assert_in, expect_msg.id, [m.id for m in actual if m.id]
+
# --- definition terms: regression test for #2198, #2205
expect = read_po(app.srcdir / 'definition_terms.po')
actual = read_po(app.outdir / 'definition_terms.pot')
@@ -338,11 +349,25 @@ def test_gettext_builder(app, status, warning):
for expect_msg in [m for m in expect if m.id]:
yield assert_in, expect_msg.id, [m.id for m in actual if m.id]
+ # --- gettext builder always ignores ``only`` directive
+ expect = read_po(app.srcdir / 'only.po')
+ actual = read_po(app.outdir / 'only.pot')
+ for expect_msg in [m for m in expect if m.id]:
+ yield assert_in, expect_msg.id, [m.id for m in actual if m.id]
+
@gen_with_intl_app('html', freshenv=True)
def test_html_builder(app, status, warning):
app.builder.build_all()
+ # --- test for meta
+
+ result = (app.outdir / 'contents.html').text(encoding='utf-8')
+ expected_expr = '<meta content="TESTDATA FOR I18N" name="description" />'
+ yield assert_in, expected_expr, result
+ expected_expr = '<meta content="I18N, SPHINX, MARKUP" name="keywords" />'
+ yield assert_in, expected_expr, result
+
# --- test for #955 cant-build-html-with-footnotes-when-using
# expect no error by build
@@ -373,7 +398,10 @@ def test_html_builder(app, status, warning):
start_tag = "<%s[^>]*>" % tag
end_tag = "</%s>" % tag
return r"%s\s*%s\s*%s" % (start_tag, keyword, end_tag)
-
+ def wrap_nest(parenttag, childtag, keyword):
+ start_tag1 = "<%s[^>]*>" % parenttag
+ start_tag2 = "<%s[^>]*>" % childtag
+ return r"%s\s*%s\s*%s" % (start_tag1, keyword, start_tag2)
expected_exprs = [
wrap('a', 'NEWSLETTER'),
wrap('a', 'MAILING LIST'),
@@ -381,8 +409,8 @@ def test_html_builder(app, status, warning):
wrap('a', 'FIRST SECOND'),
wrap('a', 'SECOND THIRD'),
wrap('a', 'THIRD, FIRST'),
- wrap('dt', 'ENTRY'),
- wrap('dt', 'SEE'),
+ wrap_nest('li', 'ul', 'ENTRY'),
+ wrap_nest('li', 'ul', 'SEE'),
wrap('a', 'MODULE'),
wrap('a', 'KEYWORD'),
wrap('a', 'OPERATOR'),
@@ -603,7 +631,7 @@ def test_xml_builder(app, status, warning):
yield (assert_elem,
para2[3],
['LINK TO', '--module', 'AND', '-m', '.'],
- ['cmdoption--module', 'cmdoption-m'])
+ ['cmdoption-module', 'cmdoption-m'])
yield (assert_elem,
para2[4],
['LINK TO', 'env2', 'AND', 'env1', '.'],
diff --git a/tests/test_markup.py b/tests/test_markup.py
index 2fde2306c..ec203447f 100644
--- a/tests/test_markup.py
+++ b/tests/test_markup.py
@@ -15,31 +15,35 @@ import pickle
from docutils import frontend, utils, nodes
from docutils.parsers import rst
+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.latex import LaTeXWriter, LaTeXTranslator
from util import TestApp, with_app, assert_node
-app = settings = parser = None
+app = settings = parser = domain_context = None
def setup_module():
- global app, settings, parser
+ global app, settings, parser, domain_context
texescape.init() # otherwise done by the latex builder
app = TestApp()
optparser = frontend.OptionParser(
components=(rst.Parser, HTMLWriter, LaTeXWriter))
settings = optparser.get_default_values()
settings.env = app.builder.env
- settings.env.patch_lookup_functions()
settings.env.temp_data['docname'] = 'dummy'
parser = rst.Parser()
+ domain_context = sphinx_domains(settings.env)
+ domain_context.enable()
def teardown_module():
app.cleanup()
+ domain_context.disable()
# since we're not resolving the markup afterwards, these nodes may remain
@@ -101,7 +105,7 @@ def test_inline():
'<p><code class="samp docutils literal"><span class="pre">a</span>'
'<em><span class="pre">b</span></em>'
'<span class="pre">c</span></code></p>',
- '\\sphinxcode{a\\emph{b}c}')
+ '\\sphinxcode{a\\sphinxstyleemphasis{b}c}')
# interpolation of arrows in menuselection
yield (verify, ':menuselection:`a --> b`',
@@ -131,7 +135,7 @@ def test_inline():
# verify classes for inline roles
yield (verify, ':manpage:`mp(1)`',
'<p><em class="manpage">mp(1)</em></p>',
- '\\emph{\\texttt{mp(1)}}')
+ '\\sphinxstyleliteralemphasis{mp(1)}')
def test_latex_escaping():
@@ -140,9 +144,9 @@ def test_latex_escaping():
r'\(\Gamma\)\textbackslash{}\(\infty\)\$')
# in verbatim code fragments
yield (verify, u'::\n\n @Γ\\∞${}', None,
- u'\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n'
+ u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
- u'\\end{Verbatim}')
+ u'\\end{sphinxVerbatim}')
# in URIs
yield (verify_re, u'`test <http://example.com/~me/>`_', None,
r'\\href{http://example.com/~me/}{test}.*')
@@ -170,3 +174,39 @@ def test_rst_prolog(app, status, warning):
# rst_prolog & rst_epilog on exlucding reST parser
assert not md.rawsource.startswith('*Hello world*.')
assert not md.rawsource.endswith('*Good-bye world*.\n')
+
+
+@with_app(buildername='dummy', testroot='keep_warnings')
+def test_keep_warnings_is_True(app, status, warning):
+ app.builder.build_all()
+ doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
+ assert_node(doctree[0], nodes.section)
+ assert len(doctree[0]) == 2
+ assert_node(doctree[0][1], nodes.system_message)
+
+
+@with_app(buildername='dummy', testroot='keep_warnings',
+ confoverrides={'keep_warnings': False})
+def test_keep_warnings_is_False(app, status, warning):
+ app.builder.build_all()
+ doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
+ assert_node(doctree[0], nodes.section)
+ assert len(doctree[0]) == 1
+
+
+@with_app(buildername='dummy', testroot='refonly_bullet_list')
+def test_compact_refonly_bullet_list(app, status, warning):
+ app.builder.build_all()
+ doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
+ assert_node(doctree[0], nodes.section)
+ assert len(doctree[0]) == 5
+
+ assert doctree[0][1].astext() == 'List A:'
+ assert_node(doctree[0][2], nodes.bullet_list)
+ assert_node(doctree[0][2][0][0], addnodes.compact_paragraph)
+ assert doctree[0][2][0][0].astext() == 'genindex'
+
+ assert doctree[0][3].astext() == 'List B:'
+ assert_node(doctree[0][4], nodes.bullet_list)
+ assert_node(doctree[0][4][0][0], nodes.paragraph)
+ assert doctree[0][4][0][0].astext() == 'Hello'
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index ac6507ce5..7a77ce225 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -298,3 +298,16 @@ def test_default_filename(tempdir):
assert ns['latex_documents'][0][1] == 'sphinx.tex'
assert ns['man_pages'][0][1] == 'sphinx'
assert ns['texinfo_documents'][0][1] == 'sphinx'
+
+
+@with_tempdir
+def test_extensions(tempdir):
+ qs.main(['sphinx-quickstart', '-q',
+ '-p', 'project_name', '-a', 'author',
+ '--extensions', 'foo,bar,baz', tempdir])
+
+ conffile = tempdir / 'conf.py'
+ assert conffile.isfile()
+ ns = {}
+ execfile_(conffile, ns)
+ assert ns['extensions'] == ['foo', 'bar', 'baz']
diff --git a/tests/test_search.py b/tests/test_search.py
index b7c38674f..fb7d47d6f 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -8,6 +8,7 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+import os
from docutils import frontend, utils
from docutils.parsers import rst
@@ -28,6 +29,17 @@ def setup_module():
parser = rst.Parser()
+def jsload(path):
+ searchindex = path.text()
+ assert searchindex.startswith('Search.setIndex(')
+
+ return jsdump.loads(searchindex[16:-2])
+
+
+def is_registered_term(index, keyword):
+ return index['terms'].get(keyword, []) != []
+
+
FILE_CONTENTS = '''\
.. test that comments are not indexed: boson
@@ -41,7 +53,7 @@ def test_wordcollector():
parser.parse(FILE_CONTENTS, doc)
ix = IndexBuilder(None, 'en', {}, None)
- ix.feed('filename', 'title', doc)
+ ix.feed('docname', 'filename', 'title', doc)
assert 'boson' not in ix._mapping
assert 'fermion' in ix._mapping
@@ -54,3 +66,62 @@ def test_objects_are_escaped(app, status, warning):
index = jsdump.loads(searchindex[16:-2])
assert 'n::Array&lt;T, d&gt;' in index.get('objects').get('') # n::Array<T,d> is escaped
+
+
+@with_app(testroot='search')
+def test_meta_keys_are_handled_for_language_en(app, status, warning):
+ app.builder.build_all()
+ searchindex = jsload(app.outdir / 'searchindex.js')
+ assert not is_registered_term(searchindex, 'thisnoteith')
+ assert is_registered_term(searchindex, 'thisonetoo')
+ assert is_registered_term(searchindex, 'findthiskei')
+ assert is_registered_term(searchindex, 'thistoo')
+ assert not is_registered_term(searchindex, 'onlygerman')
+ assert is_registered_term(searchindex, 'notgerman')
+ assert not is_registered_term(searchindex, 'onlytoogerman')
+
+
+@with_app(testroot='search', confoverrides={'html_search_language': 'de'})
+def test_meta_keys_are_handled_for_language_de(app, status, warning):
+ app.builder.build_all()
+ searchindex = jsload(app.outdir / 'searchindex.js')
+ assert not is_registered_term(searchindex, 'thisnoteith')
+ assert is_registered_term(searchindex, 'thisonetoo')
+ assert not is_registered_term(searchindex, 'findthiskei')
+ assert not is_registered_term(searchindex, 'thistoo')
+ assert is_registered_term(searchindex, 'onlygerman')
+ assert not is_registered_term(searchindex, 'notgerman')
+ assert is_registered_term(searchindex, 'onlytoogerman')
+
+
+@with_app(testroot='search')
+def test_stemmer_does_not_remove_short_words(app, status, warning):
+ app.builder.build_all()
+ searchindex = (app.outdir / 'searchindex.js').text()
+ assert 'zfs' in searchindex
+
+
+@with_app(testroot='search')
+def test_stemmer(app, status, warning):
+ searchindex = jsload(app.outdir / 'searchindex.js')
+ print(searchindex)
+ assert is_registered_term(searchindex, 'findthisstemmedkei')
+ assert is_registered_term(searchindex, 'intern')
+
+
+@with_app(testroot='search')
+def test_term_in_heading_and_section(app, status, warning):
+ searchindex = (app.outdir / 'searchindex.js').text()
+ # if search term is in the title of one doc and in the text of another
+ # both documents should be a hit in the search index as a title,
+ # respectively text hit
+ assert 'textinhead:1' in searchindex
+ assert 'textinhead:0' in searchindex
+
+
+@with_app(testroot='search')
+def test_term_in_raw_directive(app, status, warning):
+ searchindex = jsload(app.outdir / 'searchindex.js')
+ assert not is_registered_term(searchindex, 'raw')
+ assert is_registered_term(searchindex, 'rawword')
+ assert not is_registered_term(searchindex, 'latex_keyword')
diff --git a/tests/test_searchadapters.py b/tests/test_searchadapters.py
index 78f9b64ab..ee350182f 100644
--- a/tests/test_searchadapters.py
+++ b/tests/test_searchadapters.py
@@ -41,7 +41,7 @@ def search_adapter_helper(adapter):
# Make sure documents are properly updated by the search adapter.
s.init_indexing(changed=['markup'])
- s.add_document(u'markup', u'title', u'SomeLongRandomWord')
+ s.add_document(u'markup', u'filename', u'title', u'SomeLongRandomWord')
s.finish_indexing()
# Now a search for "Epigraph" should return zero results.
results = s.query(u'Epigraph')
diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py
index 77c9ade46..c92f6220f 100644
--- a/tests/test_setup_command.py
+++ b/tests/test_setup_command.py
@@ -108,3 +108,25 @@ def test_build_sphinx_return_nonzero_status(pkgroot, proc):
print(out)
print(err)
assert proc.returncode != 0, 'expect non-zero status for setup.py'
+
+
+@with_setup_command(root)
+def test_build_sphinx_warning_return_zero_status(pkgroot, proc):
+ srcdir = (pkgroot / 'doc')
+ (srcdir / 'contents.txt').write_text(
+ 'See :ref:`unexisting-reference-label`')
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode == 0
+
+
+@with_setup_command(root, '--warning-is-error')
+def test_build_sphinx_warning_is_error_return_nonzero_status(pkgroot, proc):
+ srcdir = (pkgroot / 'doc')
+ (srcdir / 'contents.txt').write_text(
+ 'See :ref:`unexisting-reference-label`')
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode != 0, 'expect non-zero status for setup.py'
diff --git a/tests/test_theming.py b/tests/test_theming.py
index 07787ecca..b62cbcd72 100644
--- a/tests/test_theming.py
+++ b/tests/test_theming.py
@@ -12,9 +12,11 @@
import os
import zipfile
+import mock
+
from sphinx.theming import Theme, ThemeError
-from util import with_app, raises, mock, path
+from util import with_app, raises, path
@with_app(confoverrides={'html_theme': 'ziptheme',
@@ -26,7 +28,7 @@ def test_theme_api(app, status, warning):
assert set(Theme.themes.keys()) == \
set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku',
'traditional', 'testtheme', 'ziptheme', 'epub', 'nature',
- 'pyramid', 'bizstyle', 'classic'])
+ 'pyramid', 'bizstyle', 'classic', 'nonav'])
assert Theme.themes['testtheme'][1] is None
assert isinstance(Theme.themes['ziptheme'][1], zipfile.ZipFile)
@@ -66,7 +68,7 @@ def test_js_source(app, status, warning):
app.builder.build(['contents'])
- v = '1.11.1'
+ v = '3.1.0'
msg = 'jquery.js version does not match to {v}'.format(v=v)
jquery_min = (app.outdir / '_static' / 'jquery.js').text()
assert 'jQuery v{v}'.format(v=v) in jquery_min, msg
diff --git a/tests/test_util_fileutil.py b/tests/test_util_fileutil.py
new file mode 100644
index 000000000..5810dd2a8
--- /dev/null
+++ b/tests/test_util_fileutil.py
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_fileutil
+ ~~~~~~~~~~~~~~~~~~
+
+ Tests sphinx.util.fileutil functions.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from sphinx.util.fileutil import copy_asset, copy_asset_file
+from sphinx.jinja2glue import BuiltinTemplateLoader
+
+import mock
+from util import with_tempdir
+
+
+class DummyTemplateLoader(BuiltinTemplateLoader):
+ def __init__(self):
+ BuiltinTemplateLoader.__init__(self)
+ builder = mock.Mock()
+ builder.config.templates_path = []
+ builder.app.translater = None
+ self.init(builder)
+
+
+@with_tempdir
+def test_copy_asset_file(tmpdir):
+ renderer = DummyTemplateLoader()
+
+ # copy normal file
+ src = (tmpdir / 'asset.txt')
+ src.write_text('# test data')
+ dest = (tmpdir / 'output.txt')
+
+ copy_asset_file(src, dest)
+ assert dest.exists()
+ assert src.text() == dest.text()
+
+ # copy template file
+ src = (tmpdir / 'asset.txt_t')
+ src.write_text('# {{var1}} data')
+ dest = (tmpdir / 'output.txt_t')
+
+ copy_asset_file(src, dest, {'var1': 'template'}, renderer)
+ assert not dest.exists()
+ assert (tmpdir / 'output.txt').exists()
+ assert (tmpdir / 'output.txt').text() == '# template data'
+
+ # copy template file to subdir
+ src = (tmpdir / 'asset.txt_t')
+ src.write_text('# {{var1}} data')
+ subdir1 = (tmpdir / 'subdir')
+ subdir1.makedirs()
+
+ copy_asset_file(src, subdir1, {'var1': 'template'}, renderer)
+ assert (subdir1 / 'asset.txt').exists()
+ assert (subdir1 / 'asset.txt').text() == '# template data'
+
+ # copy template file without context
+ src = (tmpdir / 'asset.txt_t')
+ subdir2 = (tmpdir / 'subdir2')
+ subdir2.makedirs()
+
+ copy_asset_file(src, subdir2)
+ assert not (subdir2 / 'asset.txt').exists()
+ assert (subdir2 / 'asset.txt_t').exists()
+ assert (subdir2 / 'asset.txt_t').text() == '# {{var1}} data'
+
+
+@with_tempdir
+def test_copy_asset(tmpdir):
+ renderer = DummyTemplateLoader()
+
+ # prepare source files
+ source = (tmpdir / 'source')
+ source.makedirs()
+ (source / 'index.rst').write_text('index.rst')
+ (source / 'foo.rst_t').write_text('{{var1}}.rst')
+ (source / '_static').makedirs()
+ (source / '_static' / 'basic.css').write_text('basic.css')
+ (source / '_templates').makedirs()
+ (source / '_templates' / 'layout.html').write_text('layout.html')
+ (source / '_templates' / 'sidebar.html_t').write_text('sidebar: {{var2}}')
+
+ # copy a single file
+ assert not (tmpdir / 'test1').exists()
+ copy_asset(source / 'index.rst', tmpdir / 'test1')
+ assert (tmpdir / 'test1').exists()
+ assert (tmpdir / 'test1/index.rst').exists()
+
+ # copy directories
+ destdir = tmpdir / 'test2'
+ copy_asset(source, destdir, context=dict(var1='bar', var2='baz'), renderer=renderer)
+ assert (destdir / 'index.rst').exists()
+ assert (destdir / 'foo.rst').exists()
+ assert (destdir / 'foo.rst').text() == 'bar.rst'
+ assert (destdir / '_static' / 'basic.css').exists()
+ assert (destdir / '_templates' / 'layout.html').exists()
+ assert (destdir / '_templates' / 'sidebar.html').exists()
+ assert (destdir / '_templates' / 'sidebar.html').text() == 'sidebar: baz'
+
+ # copy with exclusion
+ def excluded(path):
+ return ('sidebar.html' in path or 'basic.css' in path)
+
+ destdir = tmpdir / 'test3'
+ copy_asset(source, destdir, excluded,
+ context=dict(var1='bar', var2='baz'), renderer=renderer)
+ assert (destdir / 'index.rst').exists()
+ assert (destdir / 'foo.rst').exists()
+ assert not (destdir / '_static' / 'basic.css').exists()
+ assert (destdir / '_templates' / 'layout.html').exists()
+ assert not (destdir / '_templates' / 'sidebar.html').exists()
diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py
index 3e0cfd5f3..849796a8f 100644
--- a/tests/test_util_i18n.py
+++ b/tests/test_util_i18n.py
@@ -255,6 +255,18 @@ def test_get_filename_for_language():
'../foo.png', app.env) == 'images/en/../foo.png'
assert i18n.get_image_filename_for_language('foo', app.env) == 'images/en/foo'
+ # new path and basename tokens
+ app.env.config.language = 'en'
+ app.env.config.figure_language_filename = '{path}{language}/{basename}{ext}'
+ assert i18n.get_image_filename_for_language('foo.png', app.env) == 'en/foo.png'
+ assert i18n.get_image_filename_for_language(
+ 'foo.bar.png', app.env) == 'en/foo.bar.png'
+ assert i18n.get_image_filename_for_language(
+ 'subdir/foo.png', app.env) == 'subdir/en/foo.png'
+ assert i18n.get_image_filename_for_language(
+ '../foo.png', app.env) == '../en/foo.png'
+ assert i18n.get_image_filename_for_language('foo', app.env) == 'en/foo'
+
# invalid figure_language_filename
app.env.config.figure_language_filename = '{root}.{invalid}{ext}'
raises(SphinxError, i18n.get_image_filename_for_language, 'foo.png', app.env)
diff --git a/tests/test_util_matching.py b/tests/test_util_matching.py
new file mode 100644
index 000000000..9e99a5322
--- /dev/null
+++ b/tests/test_util_matching.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_matching
+ ~~~~~~~~~~~~~~~~~~
+
+ Tests sphinx.util.matching functions.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from sphinx.util.matching import compile_matchers, Matcher
+
+
+def test_compile_matchers():
+ # exact matching
+ pat = compile_matchers(['hello.py']).pop()
+ assert pat('hello.py')
+ assert not pat('hello-py')
+ assert not pat('subdir/hello.py')
+
+ # wild card (*)
+ pat = compile_matchers(['hello.*']).pop()
+ assert pat('hello.py')
+ assert pat('hello.rst')
+
+ pat = compile_matchers(['*.py']).pop()
+ assert pat('hello.py')
+ assert pat('world.py')
+ assert not pat('subdir/hello.py')
+
+ # wild card (**)
+ pat = compile_matchers(['hello.**']).pop()
+ assert pat('hello.py')
+ assert pat('hello.rst')
+ assert pat('hello.py/world.py')
+
+ pat = compile_matchers(['**.py']).pop()
+ assert pat('hello.py')
+ assert pat('world.py')
+ assert pat('subdir/hello.py')
+
+ pat = compile_matchers(['**/hello.py']).pop()
+ assert not pat('hello.py')
+ assert pat('subdir/hello.py')
+ assert pat('subdir/subdir/hello.py')
+
+ # wild card (?)
+ pat = compile_matchers(['hello.?']).pop()
+ assert pat('hello.c')
+ assert not pat('hello.py')
+
+ # pattern ([...])
+ pat = compile_matchers(['hello[12\\].py']).pop()
+ assert pat('hello1.py')
+ assert pat('hello2.py')
+ assert pat('hello\\.py')
+ assert not pat('hello3.py')
+
+ pat = compile_matchers(['hello[^12].py']).pop() # "^" is not negative identifier
+ assert pat('hello1.py')
+ assert pat('hello2.py')
+ assert pat('hello^.py')
+ assert not pat('hello3.py')
+
+ # negative pattern ([!...])
+ pat = compile_matchers(['hello[!12].py']).pop()
+ assert not pat('hello1.py')
+ assert not pat('hello2.py')
+ assert not pat('hello/.py') # negative pattern does not match to "/"
+ assert pat('hello3.py')
+
+ # non patterns
+ pat = compile_matchers(['hello[.py']).pop()
+ assert pat('hello[.py')
+ assert not pat('hello.py')
+
+ pat = compile_matchers(['hello[].py']).pop()
+ assert pat('hello[].py')
+ assert not pat('hello.py')
+
+ pat = compile_matchers(['hello[!].py']).pop()
+ assert pat('hello[!].py')
+ assert not pat('hello.py')
+
+
+def test_Matcher():
+ matcher = Matcher(['hello.py', '**/world.py'])
+ assert matcher('hello.py')
+ assert not matcher('subdir/hello.py')
+ assert matcher('world.py')
+ assert matcher('subdir/world.py')
diff --git a/tests/test_writer_latex.py b/tests/test_writer_latex.py
new file mode 100644
index 000000000..72eb7ed2a
--- /dev/null
+++ b/tests/test_writer_latex.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+"""
+ test_writer_latex
+ ~~~~~~~~~~~~~~~~
+
+ Test the LaTeX writer
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from __future__ import print_function
+from sphinx.writers.latex import rstdim_to_latexdim
+
+from util import raises
+
+
+def test_rstdim_to_latexdim():
+ # Length units docutils supported
+ # http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#length-units
+ assert rstdim_to_latexdim('160em') == '160em'
+ assert rstdim_to_latexdim('160px') == '160\\sphinxpxdimen'
+ assert rstdim_to_latexdim('160in') == '160in'
+ assert rstdim_to_latexdim('160cm') == '160cm'
+ assert rstdim_to_latexdim('160mm') == '160mm'
+ assert rstdim_to_latexdim('160pt') == '160bp'
+ assert rstdim_to_latexdim('160pc') == '160pc'
+ assert rstdim_to_latexdim('30%') == '0.300\\linewidth'
+ assert rstdim_to_latexdim('160') == '160\\sphinxpxdimen'
+
+ # flaot values
+ assert rstdim_to_latexdim('160.0em') == '160.0em'
+ assert rstdim_to_latexdim('.5em') == '.5em'
+
+ # unknown values (it might be generated by 3rd party extension)
+ raises(ValueError, rstdim_to_latexdim, 'unknown')
+ assert rstdim_to_latexdim('160.0unknown') == '160.0unknown'
diff --git a/tests/typing_test_data.py b/tests/typing_test_data.py
index 3c3126b07..84bb3377b 100644
--- a/tests/typing_test_data.py
+++ b/tests/typing_test_data.py
@@ -35,20 +35,24 @@ def f5(x: int, *, y: str, z: str) -> None:
pass
-def f6(x: int = None, y: dict = {}) -> None:
+def f6(x: int, *args, y: str, z: str) -> None:
pass
-def f7(x: Callable[[int, str], int]) -> None:
+def f7(x: int = None, y: dict = {}) -> None:
+ pass
+
+
+def f8(x: Callable[[int, str], int]) -> None:
# See https://github.com/ambv/typehinting/issues/149 for Callable[..., int]
pass
-def f8(x: Callable) -> None:
+def f9(x: Callable) -> None:
pass
-def f9(x: Tuple[int, str], y: Tuple[int, ...]) -> None:
+def f10(x: Tuple[int, str], y: Tuple[int, ...]) -> None:
pass
@@ -57,5 +61,5 @@ class CustomAnnotation:
return 'CustomAnnotation'
-def f10(x: CustomAnnotation(), y: 123) -> None:
+def f11(x: CustomAnnotation(), y: 123) -> None:
pass
diff --git a/tests/util.py b/tests/util.py
index cb0d3f7a0..120492d47 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -13,7 +13,7 @@ import sys
import tempfile
from functools import wraps
-from six import StringIO
+from six import StringIO, string_types
from nose import tools, SkipTest
@@ -28,12 +28,6 @@ from sphinx.pycode import ModuleAnalyzer
from path import path, repr_as # NOQA
-try:
- # Python >=3.3
- from unittest import mock
-except ImportError:
- import mock
-
__all__ = [
'rootdir', 'tempdir', 'raises', 'raises_msg',
@@ -41,7 +35,6 @@ __all__ = [
'ListOutput', 'TestApp', 'with_app', 'gen_with_app',
'path', 'with_tempdir',
'sprint', 'remove_unicode_literals',
- 'mock',
]
@@ -94,14 +87,33 @@ def assert_startswith(thing, prefix):
assert False, '%r does not start with %r' % (thing, prefix)
-def assert_node(node, cls=None, **kwargs):
+def assert_node(node, cls=None, xpath="", **kwargs):
if cls:
- assert isinstance(node, cls), '%r is not subclass of %r' % (node, cls)
+ if isinstance(cls, list):
+ assert_node(node, cls[0], xpath=xpath, **kwargs)
+ if cls[1:]:
+ if isinstance(cls[1], tuple):
+ assert_node(node, cls[1], xpath=xpath, **kwargs)
+ else:
+ assert len(node) == 1, \
+ 'The node%s has %d child nodes, not one' % (xpath, len(node))
+ assert_node(node[0], cls[1:], xpath=xpath + "[0]", **kwargs)
+ elif isinstance(cls, tuple):
+ assert len(node) == len(cls), \
+ 'The node%s has %d child nodes, not %r' % (xpath, len(node), len(cls))
+ for i, nodecls in enumerate(cls):
+ path = xpath + "[%d]" % i
+ assert_node(node[i], nodecls, xpath=path, **kwargs)
+ elif isinstance(cls, string_types):
+ assert node == cls, 'The node %r is not %r: %r' % (xpath, cls, node)
+ else:
+ assert isinstance(node, cls), \
+ 'The node%s is not subclass of %r: %r' % (xpath, cls, node)
for key, value in kwargs.items():
- assert key in node, '%r does not have %r attribute' % (node, key)
+ assert key in node, 'The node%s does not have %r attribute: %r' % (xpath, key, node)
assert node[key] == value, \
- '%r[%s]: %r does not equals %r' % (node, key, node[key], value)
+ 'The node%s[%s] is not %r: %r' % (xpath, key, value, node[key])
try:
@@ -309,3 +321,7 @@ def find_files(root, suffix=None):
for f in [f for f in files if not suffix or f.endswith(suffix)]:
fpath = dirpath / f
yield os.path.relpath(fpath, root)
+
+
+def strip_escseq(text):
+ return re.sub('\x1b.*?m', '', text)