summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorshimizukawa <shimizukawa@gmail.com>2012-12-10 10:18:32 +0900
committershimizukawa <shimizukawa@gmail.com>2012-12-10 10:18:32 +0900
commitd45dcfbd7e5add4495a7e31ee53e672ee180d534 (patch)
treee3ccbee28f06bfccb66ab2c54cb3b1648409e704 /tests
parent207e12471f451fee53a95ca6918c93abfef3a632 (diff)
parent5818df7941b73abecdb1b399fee7956ea283d698 (diff)
downloadsphinx-d45dcfbd7e5add4495a7e31ee53e672ee180d534.tar.gz
merge heads
Diffstat (limited to 'tests')
-rw-r--r--tests/root/autodoc.txt13
-rw-r--r--tests/root/conf.py23
-rw-r--r--tests/root/contents.txt2
-rw-r--r--tests/root/i18n/external_links.po32
-rw-r--r--tests/root/i18n/external_links.txt13
-rw-r--r--tests/root/i18n/footnote.po33
-rw-r--r--tests/root/i18n/footnote.txt11
-rw-r--r--tests/root/i18n/index.txt7
-rw-r--r--tests/root/i18n/refs_inconsistency.po39
-rw-r--r--tests/root/i18n/refs_inconsistency.txt13
-rw-r--r--tests/root/only.txt203
-rwxr-xr-xtests/run.py15
-rw-r--r--tests/test_application.py21
-rw-r--r--tests/test_autodoc.py58
-rw-r--r--tests/test_build.py8
-rw-r--r--tests/test_build_html.py7
-rw-r--r--tests/test_build_latex.py3
-rw-r--r--tests/test_build_texinfo.py3
-rw-r--r--tests/test_cpp_domain.py29
-rw-r--r--tests/test_env.py1
-rw-r--r--tests/test_intl.py162
-rw-r--r--tests/test_linkcode.py28
-rw-r--r--tests/test_only_directive.py61
-rw-r--r--tests/test_quickstart.py19
-rw-r--r--tests/util.py2
25 files changed, 775 insertions, 31 deletions
diff --git a/tests/root/autodoc.txt b/tests/root/autodoc.txt
index 5c03f947..d4b3404c 100644
--- a/tests/root/autodoc.txt
+++ b/tests/root/autodoc.txt
@@ -32,3 +32,16 @@ Just testing a few autodoc possibilities...
:noindex:
.. autoclass:: MarkupError
+
+
+.. currentmodule:: test_autodoc
+
+.. autoclass:: InstAttCls
+ :members:
+
+ All members (5 total)
+
+.. autoclass:: InstAttCls
+ :members: ca1, ia1
+
+ Specific members (2 total)
diff --git a/tests/root/conf.py b/tests/root/conf.py
index b97ddfcc..a3ebeec7 100644
--- a/tests/root/conf.py
+++ b/tests/root/conf.py
@@ -3,6 +3,7 @@
import sys, os
sys.path.append(os.path.abspath('.'))
+sys.path.append(os.path.abspath('..'))
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath', 'sphinx.ext.todo',
'sphinx.ext.coverage', 'sphinx.ext.autosummary',
@@ -67,6 +68,28 @@ extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '),
# modify tags from conf.py
tags.add('confpytag')
+# -- linkcode
+
+if 'test_linkcode' in tags:
+ import glob
+
+ extensions.remove('sphinx.ext.viewcode')
+ extensions.append('sphinx.ext.linkcode')
+
+ exclude_patterns.extend(glob.glob('*.txt') + glob.glob('*/*.txt'))
+ exclude_patterns.remove('contents.txt')
+ exclude_patterns.remove('objects.txt')
+
+ def linkcode_resolve(domain, info):
+ if domain == 'py':
+ fn = info['module'].replace('.', '/')
+ return "http://foobar/source/%s.py" % fn
+ elif domain == "js":
+ return "http://foobar/js/" + info['fullname']
+ elif domain in ("c", "cpp"):
+ return "http://foobar/%s/%s" % (domain, "".join(info['names']))
+ else:
+ raise AssertionError()
# -- extension API
diff --git a/tests/root/contents.txt b/tests/root/contents.txt
index 280953b4..0a8ca00e 100644
--- a/tests/root/contents.txt
+++ b/tests/root/contents.txt
@@ -27,6 +27,8 @@ Contents:
doctest
extensions
versioning/index
+ only
+ i18n/index
Python <http://python.org/>
diff --git a/tests/root/i18n/external_links.po b/tests/root/i18n/external_links.po
new file mode 100644
index 00000000..4cd19dda
--- /dev/null
+++ b/tests/root/i18n/external_links.po
@@ -0,0 +1,32 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-11-22 08:28\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 "i18n with external links"
+msgstr "EXTERNAL LINKS"
+
+msgid "External link to Python_."
+msgstr "EXTERNAL LINK TO Python_."
+
+msgid "Internal link to `i18n with external links`_."
+msgstr "`EXTERNAL LINKS`_ IS INTERNAL LINK."
+
+msgid "Inline link by `Sphinx <http://sphinx-doc.org>`_."
+msgstr "INLINE LINK BY `SPHINX <http://sphinx-doc.org>`_."
+
+msgid "Unnamed link__."
+msgstr "UNNAMED LINK__."
diff --git a/tests/root/i18n/external_links.txt b/tests/root/i18n/external_links.txt
new file mode 100644
index 00000000..7ac1db02
--- /dev/null
+++ b/tests/root/i18n/external_links.txt
@@ -0,0 +1,13 @@
+:tocdepth: 2
+
+i18n with external links
+========================
+.. #1044 external-links-dont-work-in-localized-html
+
+* External link to Python_.
+* Internal link to `i18n with external links`_.
+* Inline link by `Sphinx <http://sphinx-doc.org>`_.
+* Unnamed link__.
+
+.. _Python: http://python.org
+.. __: http://google.com
diff --git a/tests/root/i18n/footnote.po b/tests/root/i18n/footnote.po
new file mode 100644
index 00000000..47f8d3db
--- /dev/null
+++ b/tests/root/i18n/footnote.po
@@ -0,0 +1,33 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-11-22 08:28\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 "i18n with Footnote"
+msgstr "I18N WITH FOOTNOTE"
+
+msgid "[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_"
+msgstr "`I18N WITH FOOTNOTE`_ INCLUDE THIS CONTENTS [ref]_ [#]_ [100]_"
+
+msgid "This is a auto numbered footnote."
+msgstr "THIS IS A AUTO NUMBERED FOOTNOTE."
+
+msgid "This is a named footnote."
+msgstr "THIS IS A NAMED FOOTNOTE."
+
+msgid "This is a numbered footnote."
+msgstr "THIS IS A NUMBERED FOOTNOTE."
+
diff --git a/tests/root/i18n/footnote.txt b/tests/root/i18n/footnote.txt
new file mode 100644
index 00000000..3ef76bba
--- /dev/null
+++ b/tests/root/i18n/footnote.txt
@@ -0,0 +1,11 @@
+:tocdepth: 2
+
+i18n with Footnote
+==================
+.. #955 cant-build-html-with-footnotes-when-using
+
+[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_
+
+.. [#] This is a auto numbered footnote.
+.. [ref] This is a named footnote.
+.. [100] This is a numbered footnote.
diff --git a/tests/root/i18n/index.txt b/tests/root/i18n/index.txt
new file mode 100644
index 00000000..f35e2766
--- /dev/null
+++ b/tests/root/i18n/index.txt
@@ -0,0 +1,7 @@
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+
+ footnote
+ external_links
+ refs_inconsistency
diff --git a/tests/root/i18n/refs_inconsistency.po b/tests/root/i18n/refs_inconsistency.po
new file mode 100644
index 00000000..9cab687f
--- /dev/null
+++ b/tests/root/i18n/refs_inconsistency.po
@@ -0,0 +1,39 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-12-05 08:28\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 "i18n with refs inconsistency"
+msgstr "I18N WITH REFS INCONSISTENCY"
+
+msgid "[100]_ for [#]_ footnote [ref2]_."
+msgstr "FOR FOOTNOTE [ref2]_."
+
+msgid "for reference_."
+msgstr "reference_ FOR reference_."
+
+msgid "normal text."
+msgstr "ORPHAN REFERENCE: `I18N WITH REFS INCONSISTENCY`_."
+
+msgid "This is a auto numbered footnote."
+msgstr "THIS IS A AUTO NUMBERED FOOTNOTE."
+
+msgid "This is a named footnote."
+msgstr "THIS IS A NAMED FOOTNOTE."
+
+msgid "This is a numbered footnote."
+msgstr "THIS IS A NUMBERED FOOTNOTE."
+
diff --git a/tests/root/i18n/refs_inconsistency.txt b/tests/root/i18n/refs_inconsistency.txt
new file mode 100644
index 00000000..c65c5b45
--- /dev/null
+++ b/tests/root/i18n/refs_inconsistency.txt
@@ -0,0 +1,13 @@
+:tocdepth: 2
+
+i18n with refs inconsistency
+=============================
+
+* [100]_ for [#]_ footnote [ref2]_.
+* for reference_.
+* normal text.
+
+.. [#] This is a auto numbered footnote.
+.. [ref2] This is a named footnote.
+.. [100] This is a numbered footnote.
+.. _reference: http://www.example.com
diff --git a/tests/root/only.txt b/tests/root/only.txt
new file mode 100644
index 00000000..4a3eb48a
--- /dev/null
+++ b/tests/root/only.txt
@@ -0,0 +1,203 @@
+
+1. Sections in only directives
+==============================
+
+Testing sections in only directives.
+
+.. only:: nonexisting_tag
+
+ Skipped Section
+ ---------------
+ Should not be here.
+
+.. only:: not nonexisting_tag
+
+ 1.1. Section
+ ------------
+ Should be here.
+
+1.2. Section
+------------
+
+.. only:: not nonexisting_tag
+
+ 1.2.1. Subsection
+ ~~~~~~~~~~~~~~~~~
+ Should be here.
+
+.. only:: nonexisting_tag
+
+ Skipped Subsection
+ ~~~~~~~~~~~~~~~~~~
+ Should not be here.
+
+1.3. Section
+------------
+
+1.3.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.4. Section
+------------
+
+.. only:: not nonexisting_tag
+
+ 1.4.1. Subsection
+ ~~~~~~~~~~~~~~~~~
+ Should be here.
+
+1.5. Section
+------------
+
+.. only:: not nonexisting_tag
+
+ 1.5.1. Subsection
+ ~~~~~~~~~~~~~~~~~
+ Should be here.
+
+1.5.2. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.6. Section
+------------
+
+1.6.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.6.2. Subsection
+ ~~~~~~~~~~~~~~~~~
+ Should be here.
+
+1.6.3. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.7. Section
+------------
+
+1.7.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.7.1.1. Subsubsection
+ ......................
+ Should be here.
+
+1.8. Section
+------------
+
+1.8.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.8.1.1. Subsubsection
+......................
+Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.8.1.2. Subsubsection
+ ......................
+ Should be here.
+
+1.9. Section
+------------
+
+.. only:: nonexisting_tag
+
+ Skipped Subsection
+ ~~~~~~~~~~~~~~~~~~
+
+1.9.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.9.1.1. Subsubsection
+......................
+Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.10. Section
+ -------------
+ Should be here.
+
+1.11. Section
+-------------
+
+Text before subsection 11.1.
+
+.. only:: not nonexisting_tag
+
+ More text before subsection 11.1.
+
+ 1.11.1. Subsection
+ ~~~~~~~~~~~~~~~~~~
+ Should be here.
+
+Text after subsection 11.1.
+
+.. only:: not nonexisting_tag
+
+ 1.12. Section
+ -------------
+ Should be here.
+
+ 1.12.1. Subsection
+ ~~~~~~~~~~~~~~~~~~
+ Should be here.
+
+ 1.13. Section
+ -------------
+ Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.14. Section
+ -------------
+ Should be here.
+
+ .. only:: not nonexisting_tag
+
+ 1.14.1. Subsection
+ ~~~~~~~~~~~~~~~~~~
+ Should be here.
+
+ 1.15. Section
+ -------------
+ Should be here.
+
+.. only:: nonexisting_tag
+
+ Skipped document level heading
+ ==============================
+ Should not be here.
+
+.. only:: not nonexisting_tag
+
+ 2. Included document level heading
+ ==================================
+ Should be here.
+
+3. Document level heading
+=========================
+Should be here.
+
+.. only:: nonexisting_tag
+
+ Skipped document level heading
+ ==============================
+ Should not be here.
+
+.. only:: not nonexisting_tag
+
+ 4. Another included document level heading
+ ==========================================
+ Should be here.
diff --git a/tests/run.py b/tests/run.py
index ee63fa3f..4cd4a766 100755
--- a/tests/run.py
+++ b/tests/run.py
@@ -11,19 +11,24 @@
"""
import sys
-from os import path, chdir, listdir
+from os import path, chdir, listdir, environ
if sys.version_info >= (3, 0):
print('Copying and converting sources to build/lib/tests...')
from distutils.util import copydir_run_2to3
testroot = path.dirname(__file__) or '.'
- newroot = path.join(testroot, path.pardir, 'build')
- newroot = path.join(newroot, listdir(newroot)[0], 'tests')
+ if 'BUILD_TEST_PATH' in environ:
+ # for tox testing
+ newroot = environ['BUILD_TEST_PATH']
+ # tox installs the sphinx package, no need for sys.path.insert
+ else:
+ newroot = path.join(testroot, path.pardir, 'build')
+ newroot = path.join(newroot, listdir(newroot)[0], 'tests')
+ # always test the sphinx package from build/lib/
+ sys.path.insert(0, path.abspath(path.join(newroot, path.pardir)))
copydir_run_2to3(testroot, newroot)
# switch to the converted dir so nose tests the right tests
chdir(newroot)
- # always test the sphinx package from build/lib/
- sys.path.insert(0, path.pardir)
else:
# always test the sphinx package from this directory
sys.path.insert(0, path.join(path.dirname(__file__), path.pardir))
diff --git a/tests/test_application.py b/tests/test_application.py
index 4baabcec..a6e798c2 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -12,6 +12,7 @@
from StringIO import StringIO
from sphinx.application import ExtensionError
+from sphinx.domains import Domain
from util import *
@@ -69,3 +70,23 @@ def test_extensions():
assert warnings.getvalue().startswith("WARNING: extension 'shutil'")
finally:
app.cleanup()
+
+def test_domain_override():
+ class A(Domain):
+ name = 'foo'
+ class B(A):
+ name = 'foo'
+ class C(Domain):
+ name = 'foo'
+ status, warnings = StringIO(), StringIO()
+ app = TestApp(status=status, warning=warnings)
+ try:
+ # No domain know named foo.
+ raises_msg(ExtensionError, 'domain foo not yet registered',
+ app.override_domain, A)
+ assert app.add_domain(A) is None
+ assert app.override_domain(B) is None
+ raises_msg(ExtensionError, 'new domain not a subclass of registered '
+ 'foo domain', app.override_domain, C)
+ finally:
+ app.cleanup()
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 965064c3..642b9141 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -519,6 +519,12 @@ def test_generate():
assert_result_contains(
' rest of docstring', 'method', 'test_autodoc.DocstringSig.meth')
assert_result_contains(
+ '.. py:method:: DocstringSig.meth2()', 'method',
+ 'test_autodoc.DocstringSig.meth2')
+ assert_result_contains(
+ ' indented line', 'method',
+ 'test_autodoc.DocstringSig.meth2')
+ assert_result_contains(
'.. py:classmethod:: Class.moore(a, e, f) -> happiness', 'method',
'test_autodoc.Class.moore')
@@ -534,6 +540,32 @@ def test_generate():
assert_result_contains(
' :annotation: = None', 'attribute', 'AttCls.a2')
+ # test explicit members with instance attributes
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ directive.env.temp_data['py:module'] = 'test_autodoc'
+ options.inherited_members = False
+ options.undoc_members = False
+ options.members = ALL
+ assert_processes([
+ ('class', 'test_autodoc.InstAttCls'),
+ ('attribute', 'test_autodoc.InstAttCls.ca1'),
+ ('attribute', 'test_autodoc.InstAttCls.ca2'),
+ ('attribute', 'test_autodoc.InstAttCls.ca3'),
+ ('attribute', 'test_autodoc.InstAttCls.ia1'),
+ ('attribute', 'test_autodoc.InstAttCls.ia2'),
+ ], 'class', 'InstAttCls')
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ options.members = ['ca1', 'ia1']
+ assert_processes([
+ ('class', 'test_autodoc.InstAttCls'),
+ ('attribute', 'test_autodoc.InstAttCls.ca1'),
+ ('attribute', 'test_autodoc.InstAttCls.ia1'),
+ ], 'class', 'InstAttCls')
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ del directive.env.temp_data['py:module']
# --- generate fodder ------------
@@ -660,6 +692,13 @@ First line of docstring
rest of docstring
"""
+ def meth2(self):
+ """First line, no signature
+ Second line followed by indentation::
+
+ indented line
+ """
+
class StrRepr(str):
def __repr__(self):
return self
@@ -667,3 +706,22 @@ class StrRepr(str):
class AttCls(object):
a1 = StrRepr('hello\nworld')
a2 = None
+
+class InstAttCls(object):
+ """Class with documented class and instance attributes."""
+
+ #: Doc comment for class attribute InstAttCls.ca1.
+ #: It can have multiple lines.
+ ca1 = 'a'
+
+ ca2 = 'b' #: Doc comment for InstAttCls.ca2. One line only.
+
+ ca3 = 'c'
+ """Docstring for class attribute InstAttCls.ca3."""
+
+ def __init__(self):
+ #: Doc comment for instance attribute InstAttCls.ia1
+ self.ia1 = 'd'
+
+ self.ia2 = 'e'
+ """Docstring for instance attribute InstAttCls.ia2."""
diff --git a/tests/test_build.py b/tests/test_build.py
index ae3f2921..02b3c868 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -63,6 +63,14 @@ else:
def test_singlehtml(app):
app.builder.build_all()
+@with_app(buildername='xml')
+def test_xml(app):
+ app.builder.build_all()
+
+@with_app(buildername='pseudoxml')
+def test_pseudoxml(app):
+ app.builder.build_all()
+
@with_app(buildername='html', srcdir='(temp)')
def test_multibyte_path(app):
srcdir = path(app.srcdir)
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index a38806a8..a693e6c0 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -44,7 +44,7 @@ reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \
%(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png
%(root)s/objects.txt:\\d*: WARNING: using old C markup; please migrate to \
new-style markup \(e.g. c:function instead of cfunction\), see \
-http://sphinx.pocoo.org/domains.html
+http://sphinx-doc.org/domains.html
"""
HTML_WARNINGS = ENV_WARNINGS + """\
@@ -319,7 +319,8 @@ def check_static_entries(outdir):
def test_html(app):
app.builder.build_all()
html_warnings = html_warnfile.getvalue().replace(os.sep, '/')
- html_warnings_exp = HTML_WARNINGS % {'root': re.escape(app.srcdir)}
+ html_warnings_exp = HTML_WARNINGS % {
+ 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(html_warnings_exp + '$', html_warnings), \
'Warnings don\'t match:\n' + \
'--- Expected (regex):\n' + html_warnings_exp + \
@@ -328,7 +329,7 @@ def test_html(app):
for fname, paths in HTML_XPATH.iteritems():
parser = NslessParser()
parser.entity.update(htmlentitydefs.entitydefs)
- fp = open(os.path.join(app.outdir, fname))
+ fp = open(os.path.join(app.outdir, fname), 'rb')
try:
etree = ET.parse(fp, parser)
finally:
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
index 4e1e9f70..2fa0698b 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -42,7 +42,8 @@ def test_latex(app):
LaTeXTranslator.ignore_missing_images = True
app.builder.build_all()
latex_warnings = latex_warnfile.getvalue().replace(os.sep, '/')
- latex_warnings_exp = LATEX_WARNINGS % {'root': re.escape(app.srcdir)}
+ latex_warnings_exp = LATEX_WARNINGS % {
+ 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(latex_warnings_exp + '$', latex_warnings), \
'Warnings don\'t match:\n' + \
'--- Expected (regex):\n' + latex_warnings_exp + \
diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py
index c626c976..59d03e03 100644
--- a/tests/test_build_texinfo.py
+++ b/tests/test_build_texinfo.py
@@ -41,7 +41,8 @@ def test_texinfo(app):
TexinfoTranslator.ignore_missing_images = True
app.builder.build_all()
texinfo_warnings = texinfo_warnfile.getvalue().replace(os.sep, '/')
- texinfo_warnings_exp = TEXINFO_WARNINGS % {'root': re.escape(app.srcdir)}
+ texinfo_warnings_exp = TEXINFO_WARNINGS % {
+ 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(texinfo_warnings_exp + '$', texinfo_warnings), \
'Warnings don\'t match:\n' + \
'--- Expected (regex):\n' + texinfo_warnings_exp + \
diff --git a/tests/test_cpp_domain.py b/tests/test_cpp_domain.py
index 3ab8ece4..c8466e37 100644
--- a/tests/test_cpp_domain.py
+++ b/tests/test_cpp_domain.py
@@ -11,7 +11,7 @@
from util import *
-from sphinx.domains.cpp import DefinitionParser
+from sphinx.domains.cpp import DefinitionParser, DefinitionError
def parse(name, string):
@@ -43,6 +43,15 @@ def test_type_definitions():
x = 'int printf(const char* fmt, ...)'
assert unicode(parse('function', x)) == x
+ x = 'int foo(const unsigned int j)'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(const unsigned int const j)'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(const int* const ptr)'
+ assert unicode(parse('function', x)) == x
+
x = 'std::vector<std::pair<std::string, long long>> module::blah'
assert unicode(parse('type_object', x)) == x
@@ -60,6 +69,9 @@ def test_type_definitions():
x = 'constexpr int get_value()'
assert unicode(parse('function', x)) == x
+ x = 'static constexpr int get_value()'
+ assert unicode(parse('function', x)) == x
+
x = 'int get_value() const noexcept'
assert unicode(parse('function', x)) == x
@@ -73,6 +85,21 @@ def test_type_definitions():
x = 'module::myclass foo[n]'
assert unicode(parse('member_object', x)) == x
+ x = 'int foo(Foo f=Foo(double(), std::make_pair(int(2), double(3.4))))'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(A a=x(a))'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(B b=x(a)'
+ raises(DefinitionError, parse, 'function', x)
+
+ x = 'int foo)C c=x(a))'
+ raises(DefinitionError, parse, 'function', x)
+
+ x = 'int foo(D d=x(a'
+ raises(DefinitionError, parse, 'function', x)
+
def test_bases():
x = 'A'
diff --git a/tests/test_env.py b/tests/test_env.py
index e62db33b..2f75187f 100644
--- a/tests/test_env.py
+++ b/tests/test_env.py
@@ -54,6 +54,7 @@ def test_images():
tree = env.get_doctree('images')
app._warning.reset()
htmlbuilder = StandaloneHTMLBuilder(app)
+ htmlbuilder.imgpath = 'dummy'
htmlbuilder.post_process_images(tree)
image_uri_message = "no matching candidate for image URI u'foo.*'"
if sys.version_info >= (3, 0):
diff --git a/tests/test_intl.py b/tests/test_intl.py
index d1e28002..94b21e8d 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -11,34 +11,45 @@
"""
from subprocess import Popen, PIPE
+import re
+import os
+from StringIO import StringIO
from util import *
from util import SkipTest
+warnfile = StringIO()
+
+
def setup_module():
(test_root / 'xx' / 'LC_MESSAGES').makedirs()
# Compile all required catalogs into binary format (*.mo).
- for catalog in 'bom', 'subdir':
- try:
- p = Popen(['msgfmt', test_root / '%s.po' % catalog, '-o',
- test_root / 'xx' / 'LC_MESSAGES' / '%s.mo' % catalog],
- stdout=PIPE, stderr=PIPE)
- except OSError:
- # The test will fail the second time it's run if we don't
- # tear down here. Not sure if there's a more idiomatic way
- # of ensuring that teardown gets run in the event of an
- # exception from the setup function.
- teardown_module()
- raise SkipTest # most likely msgfmt was not found
- else:
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- print stdout
- print stderr
- assert False, 'msgfmt exited with return code %s' % p.returncode
- assert (test_root / 'xx' / 'LC_MESSAGES' / ('%s.mo' % catalog)
- ).isfile(), 'msgfmt failed'
+ for dirpath, dirs, files in os.walk(test_root):
+ dirpath = path(dirpath)
+ for f in [f for f in files if f.endswith('.po')]:
+ po = dirpath / f
+ mo = test_root / 'xx' / 'LC_MESSAGES' / (
+ os.path.relpath(po[:-3], test_root) + '.mo')
+ if not mo.parent.exists():
+ mo.parent.makedirs()
+ try:
+ p = Popen(['msgfmt', po, '-o', mo],
+ stdout=PIPE, stderr=PIPE)
+ except OSError:
+ # The test will fail the second time it's run if we don't
+ # tear down here. Not sure if there's a more idiomatic way
+ # of ensuring that teardown gets run in the event of an
+ # exception from the setup function.
+ teardown_module()
+ raise SkipTest # most likely msgfmt was not found
+ else:
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ print stdout
+ print stderr
+ assert False, 'msgfmt exited with return code %s' % p.returncode
+ assert mo.isfile(), 'msgfmt failed'
def teardown_module():
@@ -63,3 +74,114 @@ def test_subdir(app):
app.builder.build(['subdir/includes'])
result = (app.outdir / 'subdir' / 'includes.txt').text(encoding='utf-8')
assert result.startswith(u"\ntranslation\n***********\n\n")
+
+
+@with_app(buildername='html', cleanenv=True,
+ confoverrides={'language': 'xx', 'locale_dirs': ['.'],
+ 'gettext_compact': False})
+def test_i18n_footnote_break_refid(app):
+ """test for #955 cant-build-html-with-footnotes-when-using"""
+ app.builder.build(['i18n/footnote'])
+ result = (app.outdir / 'i18n' / 'footnote.html').text(encoding='utf-8')
+ # expect no error by build
+
+
+@with_app(buildername='text', cleanenv=True,
+ confoverrides={'language': 'xx', 'locale_dirs': ['.'],
+ 'gettext_compact': False})
+def test_i18n_footnote_regression(app):
+ """regression test for fix #955"""
+ app.builder.build(['i18n/footnote'])
+ result = (app.outdir / 'i18n' / 'footnote.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH FOOTNOTE"
+ u"\n******************\n" # underline matches new translation
+ u"\nI18N WITH FOOTNOTE INCLUDE THIS CONTENTS [ref] [1] [100]\n"
+ u"\n[1] THIS IS A AUTO NUMBERED FOOTNOTE.\n"
+ u"\n[ref] THIS IS A NAMED FOOTNOTE.\n"
+ u"\n[100] THIS IS A NUMBERED FOOTNOTE.\n")
+ assert result == expect
+
+
+@with_app(buildername='text', warning=warnfile, cleanenv=True,
+ confoverrides={'language': 'xx', 'locale_dirs': ['.'],
+ 'gettext_compact': False})
+def test_i18n_warn_for_number_of_references_inconsistency(app):
+ app.builddir.rmtree(True)
+ app.builder.build(['i18n/refs_inconsistency'])
+ result = (app.outdir / 'i18n' / 'refs_inconsistency.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH REFS INCONSISTENCY"
+ u"\n****************************\n"
+ u"\n* FOR FOOTNOTE [ref2].\n"
+ u"\n* reference FOR reference.\n"
+ u"\n* ORPHAN REFERENCE: I18N WITH REFS INCONSISTENCY.\n"
+ u"\n[1] THIS IS A AUTO NUMBERED FOOTNOTE.\n"
+ u"\n[ref2] THIS IS A NAMED FOOTNOTE.\n"
+ u"\n[100] THIS IS A NUMBERED FOOTNOTE.\n")
+ assert result == expect
+
+ warnings = warnfile.getvalue().replace(os.sep, '/')
+ warning_fmt = u'.*/i18n/refs_inconsistency.txt:\\d+: ' \
+ u'WARNING: inconsistent %s in translated message\n'
+ expected_warning_expr = (
+ warning_fmt % 'footnote references' +
+ warning_fmt % 'references' +
+ warning_fmt % 'references')
+ assert re.search(expected_warning_expr, warnings)
+
+
+@with_app(buildername='html', cleanenv=True,
+ confoverrides={'language': 'xx', 'locale_dirs': ['.'],
+ 'gettext_compact': False})
+def test_i18n_link_to_undefined_reference(app):
+ app.builder.build(['i18n/refs_inconsistency'])
+ result = (app.outdir / 'i18n' / 'refs_inconsistency.html').text(encoding='utf-8')
+
+ expected_expr = """<a class="reference external" href="http://www.example.com">reference</a>"""
+ assert len(re.findall(expected_expr, result)) == 2
+
+ expected_expr = """<a class="reference internal" href="#reference">reference</a>"""
+ assert len(re.findall(expected_expr, result)) == 0
+
+ expected_expr = """<a class="reference internal" href="#i18n-with-refs-inconsistency">I18N WITH REFS INCONSISTENCY</a>"""
+ assert len(re.findall(expected_expr, result)) == 1
+
+
+@with_app(buildername='html', cleanenv=True,
+ confoverrides={'language': 'xx', 'locale_dirs': ['.'],
+ 'gettext_compact': False})
+def test_i18n_keep_external_links(app):
+ """regression test for #1044"""
+ app.builder.build(['i18n/external_links'])
+ result = (app.outdir / 'i18n' / 'external_links.html').text(encoding='utf-8')
+
+ # external link check
+ expect_line = u"""<li>EXTERNAL LINK TO <a class="reference external" href="http://python.org">Python</a>.</li>"""
+ matched = re.search('^<li>EXTERNAL LINK TO .*$', result, re.M)
+ matched_line = ''
+ if matched:
+ matched_line = matched.group()
+ assert expect_line == matched_line
+
+ # internal link check
+ expect_line = u"""<li><a class="reference internal" href="#i18n-with-external-links">EXTERNAL LINKS</a> IS INTERNAL LINK.</li>"""
+ matched = re.search('^<li><a .* IS INTERNAL LINK.</li>$', result, re.M)
+ matched_line = ''
+ if matched:
+ matched_line = matched.group()
+ assert expect_line == matched_line
+
+ # inline link check
+ expect_line = u"""<li>INLINE LINK BY <a class="reference external" href="http://sphinx-doc.org">SPHINX</a>.</li>"""
+ matched = re.search('^<li>INLINE LINK BY .*$', result, re.M)
+ matched_line = ''
+ if matched:
+ matched_line = matched.group()
+ assert expect_line == matched_line
+
+ # unnamed link check
+ expect_line = u"""<li>UNNAMED <a class="reference external" href="http://google.com">LINK</a>.</li>"""
+ matched = re.search('^<li>UNNAMED .*$', result, re.M)
+ matched_line = ''
+ if matched:
+ matched_line = matched.group()
+ assert expect_line == matched_line
diff --git a/tests/test_linkcode.py b/tests/test_linkcode.py
new file mode 100644
index 00000000..365e826f
--- /dev/null
+++ b/tests/test_linkcode.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+"""
+ test_linkcode
+ ~~~~~~~~~~~~~
+
+ Test the sphinx.ext.linkcode extension.
+
+ :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+from util import *
+
+@with_app(srcdir='(temp)', buildername='html', tags=['test_linkcode'])
+def test_html(app):
+ app.builder.build_all()
+
+ fp = open(os.path.join(app.outdir, 'objects.html'), 'r')
+ try:
+ stuff = fp.read()
+ finally:
+ fp.close()
+
+ assert 'http://foobar/source/foolib.py' in stuff
+ assert 'http://foobar/js/' in stuff
+ assert 'http://foobar/c/' in stuff
+ assert 'http://foobar/cpp/' in stuff
diff --git a/tests/test_only_directive.py b/tests/test_only_directive.py
new file mode 100644
index 00000000..2396046e
--- /dev/null
+++ b/tests/test_only_directive.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+"""
+ test_only_directive
+ ~~~~~~~~~~~~~~~~~~~
+
+ Test the only directive with the test root.
+
+ :copyright: Copyright 2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from docutils import nodes
+
+from util import *
+
+
+def teardown_module():
+ (test_root / '_build').rmtree(True)
+
+
+@with_app(buildername='text')
+def test_sectioning(app):
+
+ def getsects(section):
+ if not isinstance(section, nodes.section):
+ return [getsects(n) for n in section.children]
+ title = section.next_node(nodes.title).astext().strip()
+ subsects = []
+ children = section.children[:]
+ while children:
+ node = children.pop(0)
+ if isinstance(node, nodes.section):
+ subsects.append(node)
+ continue
+ children = list(node.children) + children
+ return [title, [getsects(subsect) for subsect in subsects]]
+
+ def testsects(prefix, sects, indent=0):
+ title = sects[0]
+ parent_num = title.split()[0]
+ assert prefix == parent_num, \
+ 'Section out of place: %r' % title
+ for i, subsect in enumerate(sects[1]):
+ num = subsect[0].split()[0]
+ assert re.match('[0-9]+[.0-9]*[.]', num), \
+ 'Unnumbered section: %r' % subsect[0]
+ testsects(prefix + str(i+1) + '.', subsect, indent+4)
+
+ app.builder.build(['only'])
+ doctree = app.env.get_doctree('only')
+ app.env.process_only_nodes(doctree, app.builder)
+
+ parts = [getsects(n)
+ for n in filter(lambda n: isinstance(n, nodes.section),
+ doctree.children)]
+ for i, s in enumerate(parts):
+ testsects(str(i+1) + '.', s, 4)
+ assert len(parts) == 4, 'Expected 4 document level headings, got:\n%s' % \
+ '\n'.join([p[0] for p in parts])
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index dba888dd..c054f858 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -46,6 +46,25 @@ def teardown_module():
coloron()
+def test_quickstart_inputstrip():
+ d = {}
+ answers = {
+ 'Q1': 'Y\r', # input() return with '\r' on Python-3.2.0 for Windows
+ 'Q2': ' Yes \r',
+ 'Q3': 'N',
+ 'Q4': 'N ',
+ }
+ qs.term_input = mock_raw_input(answers)
+ qs.do_prompt(d, 'k1', 'Q1')
+ assert d['k1'] == 'Y'
+ qs.do_prompt(d, 'k2', 'Q2')
+ assert d['k2'] == 'Yes'
+ qs.do_prompt(d, 'k3', 'Q3')
+ assert d['k3'] == 'N'
+ qs.do_prompt(d, 'k4', 'Q4')
+ assert d['k4'] == 'N'
+
+
def test_do_prompt():
d = {}
answers = {
diff --git a/tests/util.py b/tests/util.py
index bd50bec0..32e94a7f 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -21,6 +21,7 @@ except ImportError:
wraps = lambda f: (lambda w: w)
from sphinx import application
+from sphinx.theming import Theme
from sphinx.ext.autodoc import AutoDirective
from path import path
@@ -170,6 +171,7 @@ class TestApp(application.Sphinx):
freshenv, warningiserror, tags)
def cleanup(self, doctrees=False):
+ Theme.themes.clear()
AutoDirective._registry.clear()
for tree in self.cleanup_trees:
shutil.rmtree(tree, True)