mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2026-10-13 17:02:12 -05:00
Merge with default
This commit is contained in:
commit
3ad1f1c164
162 files changed
+5035
-4519
No files matched your search
@@ -123,6 +123,9 @@ class path(text_type):
|
||||
"""
|
||||
os.unlink(self)
|
||||
|
||||
def utime(self, arg):
|
||||
os.utime(self, arg)
|
||||
|
||||
def write_text(self, text, **kwargs):
|
||||
"""
|
||||
Writes the given `text` to the file.
|
||||
@@ -195,6 +198,9 @@ class path(text_type):
|
||||
"""
|
||||
return self.__class__(os.path.join(self, *map(self.__class__, args)))
|
||||
|
||||
def listdir(self):
|
||||
return os.listdir(self)
|
||||
|
||||
__div__ = __truediv__ = joinpath
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
+13
-35
@@ -3,12 +3,9 @@
|
||||
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',
|
||||
'sphinx.ext.doctest', 'sphinx.ext.extlinks',
|
||||
'sphinx.ext.viewcode', 'ext']
|
||||
'sphinx.ext.coverage', 'sphinx.ext.extlinks', 'ext']
|
||||
|
||||
jsmath_path = 'dummy.js'
|
||||
|
||||
@@ -18,7 +15,7 @@ master_doc = 'contents'
|
||||
source_suffix = '.txt'
|
||||
|
||||
project = 'Sphinx <Tests>'
|
||||
copyright = '2010, Georg Brandl & Team'
|
||||
copyright = '2010-2014, Georg Brandl & Team'
|
||||
# If this is changed, remember to update the versionchanges!
|
||||
version = '0.6'
|
||||
release = '0.6alpha1'
|
||||
@@ -34,7 +31,8 @@ html_theme = 'testtheme'
|
||||
html_theme_path = ['.']
|
||||
html_theme_options = {'testopt': 'testoverride'}
|
||||
html_sidebars = {'**': 'customsb.html',
|
||||
'contents': ['contentssb.html', 'localtoc.html'] }
|
||||
'contents': ['contentssb.html', 'localtoc.html',
|
||||
'globaltoc.html']}
|
||||
html_style = 'default.css'
|
||||
html_static_path = ['_static', 'templated.css_t']
|
||||
html_extra_path = ['robots.txt']
|
||||
@@ -44,15 +42,15 @@ html_context = {'hckey': 'hcval', 'hckey_co': 'wrong_hcval_co'}
|
||||
htmlhelp_basename = 'SphinxTestsdoc'
|
||||
|
||||
latex_documents = [
|
||||
('contents', 'SphinxTests.tex', 'Sphinx Tests Documentation',
|
||||
'Georg Brandl \\and someone else', 'manual'),
|
||||
('contents', 'SphinxTests.tex', 'Sphinx Tests Documentation',
|
||||
'Georg Brandl \\and someone else', 'manual'),
|
||||
]
|
||||
|
||||
latex_additional_files = ['svgimg.svg']
|
||||
|
||||
texinfo_documents = [
|
||||
('contents', 'SphinxTests', 'Sphinx Tests',
|
||||
'Georg Brandl \\and someone else', 'Sphinx Testing', 'Miscellaneous'),
|
||||
('contents', 'SphinxTests', 'Sphinx Tests',
|
||||
'Georg Brandl \\and someone else', 'Sphinx Testing', 'Miscellaneous'),
|
||||
]
|
||||
|
||||
man_pages = [
|
||||
@@ -65,8 +63,6 @@ value_from_conf_py = 84
|
||||
coverage_c_path = ['special/*.h']
|
||||
coverage_c_regexes = {'function': r'^PyAPI_FUNC\(.*\)\s+([^_][\w_]+)'}
|
||||
|
||||
autosummary_generate = ['autosummary']
|
||||
|
||||
extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '),
|
||||
'pyurl': ('http://python.org/%s', None)}
|
||||
|
||||
@@ -80,35 +76,13 @@ autodoc_mock_imports = [
|
||||
# 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
|
||||
|
||||
from docutils import nodes
|
||||
from sphinx import addnodes
|
||||
from sphinx.util.compat import Directive
|
||||
|
||||
|
||||
def userdesc_parse(env, sig, signode):
|
||||
x, y = sig.split(':')
|
||||
signode += addnodes.desc_name(x, x)
|
||||
@@ -116,15 +90,19 @@ def userdesc_parse(env, sig, signode):
|
||||
signode[-1] += addnodes.desc_parameter(y, y)
|
||||
return x
|
||||
|
||||
|
||||
def functional_directive(name, arguments, options, content, lineno,
|
||||
content_offset, block_text, state, state_machine):
|
||||
return [nodes.strong(text='from function: %s' % options['opt'])]
|
||||
|
||||
|
||||
class ClassDirective(Directive):
|
||||
option_spec = {'opt': lambda x: x}
|
||||
|
||||
def run(self):
|
||||
return [nodes.strong(text='from class: %s' % self.options['opt'])]
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_config_value('value_from_conf_py', 42, False)
|
||||
app.add_directive('funcdir', functional_directive, opt=lambda x: x)
|
||||
|
||||
+12
-3
@@ -21,15 +21,14 @@ Contents:
|
||||
bom
|
||||
math
|
||||
autodoc
|
||||
autosummary
|
||||
metadata
|
||||
extensions
|
||||
doctest
|
||||
extensions
|
||||
versioning/index
|
||||
footnote
|
||||
lists
|
||||
|
||||
http://sphinx-doc.org/
|
||||
Latest reference <http://sphinx-doc.org/latest/>
|
||||
Python <http://python.org/>
|
||||
|
||||
Indices and tables
|
||||
@@ -44,3 +43,13 @@ References
|
||||
|
||||
.. [Ref1] Reference target.
|
||||
.. [Ref_1] Reference target 2.
|
||||
|
||||
Test for issue #1157
|
||||
====================
|
||||
|
||||
This used to crash:
|
||||
|
||||
.. toctree::
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
@@ -142,6 +142,7 @@ Adding \n to test unescaping.
|
||||
* :ref:`here <some-label>`
|
||||
* :ref:`my-figure`
|
||||
* :ref:`my-table`
|
||||
* :ref:`my-code-block`
|
||||
* :doc:`subdir/includes`
|
||||
* ``:download:`` is tested in includes.txt
|
||||
* :option:`Python -c option <python -c>`
|
||||
@@ -228,8 +229,11 @@ Version markup
|
||||
Code blocks
|
||||
-----------
|
||||
|
||||
.. _my-code-block:
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:caption: my ruby code
|
||||
|
||||
def ruby?
|
||||
false
|
||||
@@ -356,6 +360,25 @@ Only directive
|
||||
Always present, because set through conf.py/command line.
|
||||
|
||||
|
||||
Any role
|
||||
--------
|
||||
|
||||
.. default-role:: any
|
||||
|
||||
Test referencing to `headings <with>` and `objects <func_without_body>`.
|
||||
Also `modules <mod>` and `classes <Time>`.
|
||||
|
||||
More domains:
|
||||
|
||||
* `JS <bar.baz>`
|
||||
* `C <SphinxType>`
|
||||
* `myobj` (user markup)
|
||||
* `n::Array`
|
||||
* `perl -c`
|
||||
|
||||
.. default-role::
|
||||
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [#] Like footnotes.
|
||||
|
||||
@@ -170,6 +170,10 @@ Others
|
||||
|
||||
.. cmdoption:: -c
|
||||
|
||||
.. option:: +p
|
||||
|
||||
Link to :option:`perl +p`.
|
||||
|
||||
|
||||
User markup
|
||||
===========
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
:orphan:
|
||||
|
||||
here: »
|
||||
@@ -1,80 +1,80 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
## set this by test
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
from sphinx.writers.html import HTMLTranslator
|
||||
from sphinx.writers.latex import LaTeXTranslator
|
||||
from sphinx.writers.manpage import ManualPageTranslator
|
||||
from sphinx.writers.texinfo import TexinfoTranslator
|
||||
from sphinx.writers.text import TextTranslator
|
||||
from sphinx.writers.websupport import WebSupportTranslator
|
||||
from docutils.writers.docutils_xml import XMLTranslator
|
||||
|
||||
|
||||
project = 'test'
|
||||
master_doc = 'index'
|
||||
|
||||
|
||||
class ConfHTMLTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfDirHTMLTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfSingleHTMLTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfPickleTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfJsonTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfLaTeXTranslator(LaTeXTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfManualPageTranslator(ManualPageTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfTexinfoTranslator(TexinfoTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfTextTranslator(TextTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfWebSupportTranslator(WebSupportTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfXMLTranslator(XMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfPseudoXMLTranslator(XMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.set_translator('html', ConfHTMLTranslator)
|
||||
app.set_translator('dirhtml', ConfDirHTMLTranslator)
|
||||
app.set_translator('singlehtml', ConfSingleHTMLTranslator)
|
||||
app.set_translator('pickle', ConfPickleTranslator)
|
||||
app.set_translator('json', ConfJsonTranslator)
|
||||
app.set_translator('latex', ConfLaTeXTranslator)
|
||||
app.set_translator('man', ConfManualPageTranslator)
|
||||
app.set_translator('texinfo', ConfTexinfoTranslator)
|
||||
app.set_translator('text', ConfTextTranslator)
|
||||
app.set_translator('websupport', ConfWebSupportTranslator)
|
||||
app.set_translator('xml', ConfXMLTranslator)
|
||||
app.set_translator('pseudoxml', ConfPseudoXMLTranslator)
|
||||
# -*- coding: utf-8 -*-
|
||||
## set this by test
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
from sphinx.writers.html import HTMLTranslator
|
||||
from sphinx.writers.latex import LaTeXTranslator
|
||||
from sphinx.writers.manpage import ManualPageTranslator
|
||||
from sphinx.writers.texinfo import TexinfoTranslator
|
||||
from sphinx.writers.text import TextTranslator
|
||||
from sphinx.writers.websupport import WebSupportTranslator
|
||||
from docutils.writers.docutils_xml import XMLTranslator
|
||||
|
||||
|
||||
project = 'test'
|
||||
master_doc = 'index'
|
||||
|
||||
|
||||
class ConfHTMLTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfDirHTMLTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfSingleHTMLTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfPickleTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfJsonTranslator(HTMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfLaTeXTranslator(LaTeXTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfManualPageTranslator(ManualPageTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfTexinfoTranslator(TexinfoTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfTextTranslator(TextTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfWebSupportTranslator(WebSupportTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfXMLTranslator(XMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ConfPseudoXMLTranslator(XMLTranslator):
|
||||
pass
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.set_translator('html', ConfHTMLTranslator)
|
||||
app.set_translator('dirhtml', ConfDirHTMLTranslator)
|
||||
app.set_translator('singlehtml', ConfSingleHTMLTranslator)
|
||||
app.set_translator('pickle', ConfPickleTranslator)
|
||||
app.set_translator('json', ConfJsonTranslator)
|
||||
app.set_translator('latex', ConfLaTeXTranslator)
|
||||
app.set_translator('man', ConfManualPageTranslator)
|
||||
app.set_translator('texinfo', ConfTexinfoTranslator)
|
||||
app.set_translator('text', ConfTextTranslator)
|
||||
app.set_translator('websupport', ConfWebSupportTranslator)
|
||||
app.set_translator('xml', ConfXMLTranslator)
|
||||
app.set_translator('pseudoxml', ConfPseudoXMLTranslator)
|
||||
@@ -1,3 +1,3 @@
|
||||
=======================
|
||||
Test API set_translator
|
||||
=======================
|
||||
Test API set_translator
|
||||
=======================
|
||||
@@ -1,9 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath('.')))
|
||||
|
||||
project = 'test'
|
||||
master_doc = 'index'
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath('.')))
|
||||
|
||||
project = 'test'
|
||||
master_doc = 'index'
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from sphinx.writers.html import HTMLTranslator
|
||||
|
||||
class ExtHTMLTranslator(HTMLTranslator):
|
||||
pass
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from sphinx.writers.html import HTMLTranslator
|
||||
|
||||
class ExtHTMLTranslator(HTMLTranslator):
|
||||
pass
|
||||
@@ -1,3 +1,7 @@
|
||||
import sys, os
|
||||
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
extensions = ['sphinx.ext.autosummary']
|
||||
|
||||
# The suffix of source filenames.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
:toctree:
|
||||
|
||||
dummy_module
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
:toctree:
|
||||
|
||||
dummy_module
|
||||
sphinx
|
||||
File renamed without changes.
@@ -0,0 +1,2 @@
|
||||
master_doc = 'contents'
|
||||
source_suffix = '.txt'
|
||||
@@ -0,0 +1,8 @@
|
||||
.. toctree::
|
||||
|
||||
maxwidth
|
||||
lineblock
|
||||
nonascii_title
|
||||
nonascii_table
|
||||
nonascii_maxwidth
|
||||
table
|
||||
@@ -0,0 +1,6 @@
|
||||
* one
|
||||
|
||||
| line-block 1
|
||||
| line-block 2
|
||||
|
||||
followed paragraph.
|
||||
@@ -0,0 +1,6 @@
|
||||
.. seealso:: ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham
|
||||
|
||||
* ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham
|
||||
* ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham
|
||||
|
||||
spam egg
|
||||
@@ -0,0 +1,5 @@
|
||||
abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc
|
||||
|
||||
日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語
|
||||
|
||||
abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語
|
||||
@@ -0,0 +1,7 @@
|
||||
.. list-table::
|
||||
|
||||
- - spam
|
||||
- egg
|
||||
|
||||
- - 日本語
|
||||
- 日本語
|
||||
@@ -0,0 +1,2 @@
|
||||
日本語
|
||||
======
|
||||
@@ -0,0 +1,7 @@
|
||||
+-----+-----+
|
||||
| XXX | XXX |
|
||||
+-----+-----+
|
||||
| | XXX |
|
||||
+-----+-----+
|
||||
| XXX | |
|
||||
+-----+-----+
|
||||
Whitespace-only changes.
@@ -0,0 +1,4 @@
|
||||
.. toctree::
|
||||
|
||||
sub
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.. toctree::
|
||||
|
||||
contents
|
||||
@@ -1,22 +1,35 @@
|
||||
Dedent
|
||||
======
|
||||
|
||||
Code blocks
|
||||
-----------
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:dedent: 4
|
||||
|
||||
def ruby?
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
Literal Include
|
||||
---------------
|
||||
|
||||
.. literalinclude:: literal.inc
|
||||
:language: python
|
||||
:lines: 10-11
|
||||
:dedent: 0
|
||||
|
||||
.. literalinclude:: literal.inc
|
||||
:language: python
|
||||
:lines: 10-11
|
||||
:dedent: 1
|
||||
|
||||
.. literalinclude:: literal.inc
|
||||
:language: python
|
||||
:lines: 10-11
|
||||
:dedent: 2
|
||||
|
||||
.. literalinclude:: literal.inc
|
||||
:language: python
|
||||
:lines: 10-11
|
||||
:dedent: 3
|
||||
|
||||
.. literalinclude:: literal.inc
|
||||
:language: python
|
||||
:lines: 10-11
|
||||
:dedent: 4
|
||||
|
||||
.. literalinclude:: literal.inc
|
||||
:language: python
|
||||
:lines: 10-11
|
||||
:dedent: 1000
|
||||
@@ -0,0 +1,53 @@
|
||||
Dedent
|
||||
======
|
||||
|
||||
Code blocks
|
||||
-----------
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:dedent: 0
|
||||
|
||||
def ruby?
|
||||
false
|
||||
end
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:dedent: 1
|
||||
|
||||
def ruby?
|
||||
false
|
||||
end
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:dedent: 2
|
||||
|
||||
def ruby?
|
||||
false
|
||||
end
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:dedent: 3
|
||||
|
||||
def ruby?
|
||||
false
|
||||
end
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:dedent: 4
|
||||
|
||||
def ruby?
|
||||
false
|
||||
end
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:dedent: 1000
|
||||
|
||||
def ruby?
|
||||
false
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
extensions = ['sphinx.ext.doctest']
|
||||
|
||||
project = 'test project for doctest'
|
||||
master_doc = 'doctest.txt'
|
||||
source_suffix = '.txt'
|
||||
@@ -125,5 +125,5 @@ Special directives
|
||||
|
||||
.. testcleanup:: *
|
||||
|
||||
import test_doctest
|
||||
test_doctest.cleanup_call()
|
||||
import test_ext_doctest
|
||||
test_ext_doctest.cleanup_call()
|
||||
@@ -1,15 +1,15 @@
|
||||
docutils conf
|
||||
=============
|
||||
|
||||
field-name-limit
|
||||
----------------
|
||||
|
||||
:short: desc
|
||||
:long long long long: long title
|
||||
|
||||
option-limit
|
||||
------------
|
||||
|
||||
--short short desc
|
||||
--long-long-long-long long desc
|
||||
|
||||
docutils conf
|
||||
=============
|
||||
|
||||
field-name-limit
|
||||
----------------
|
||||
|
||||
:short: desc
|
||||
:long long long long: long title
|
||||
|
||||
option-limit
|
||||
------------
|
||||
|
||||
--short short desc
|
||||
--long-long-long-long long desc
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||
master_doc = 'index'
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||
master_doc = 'index'
|
||||
|
||||
|
||||
if 'test_linkcode' in tags:
|
||||
extensions.remove('sphinx.ext.viewcode')
|
||||
extensions.append('sphinx.ext.linkcode')
|
||||
|
||||
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()
|
||||
@@ -1,29 +1,34 @@
|
||||
viewcode
|
||||
========
|
||||
|
||||
.. py:module:: spam
|
||||
|
||||
.. autofunction:: func1
|
||||
|
||||
.. autofunction:: func2
|
||||
|
||||
.. autofunction:: spam.mod1.func1
|
||||
|
||||
.. autofunction:: spam.mod2.func2
|
||||
|
||||
.. autofunction:: Class1
|
||||
|
||||
.. autofunction:: Class2
|
||||
|
||||
.. autofunction:: spam.mod1.Class1
|
||||
|
||||
.. autofunction:: spam.mod2.Class2
|
||||
|
||||
|
||||
.. literalinclude:: spam/__init__.py
|
||||
:language: python
|
||||
:pyobject: func1
|
||||
|
||||
.. literalinclude:: spam/mod1.py
|
||||
:language: python
|
||||
:pyobject: func1
|
||||
viewcode
|
||||
========
|
||||
|
||||
.. py:module:: spam
|
||||
|
||||
.. autofunction:: func1
|
||||
|
||||
.. autofunction:: func2
|
||||
|
||||
.. autofunction:: spam.mod1.func1
|
||||
|
||||
.. autofunction:: spam.mod2.func2
|
||||
|
||||
.. autofunction:: Class1
|
||||
|
||||
.. autofunction:: Class2
|
||||
|
||||
.. autofunction:: spam.mod1.Class1
|
||||
|
||||
.. autofunction:: spam.mod2.Class2
|
||||
|
||||
|
||||
.. literalinclude:: spam/__init__.py
|
||||
:language: python
|
||||
:pyobject: func1
|
||||
|
||||
.. literalinclude:: spam/mod1.py
|
||||
:language: python
|
||||
:pyobject: func1
|
||||
|
||||
|
||||
.. toctree::
|
||||
|
||||
objects
|
||||
@@ -0,0 +1,169 @@
|
||||
Testing object descriptions
|
||||
===========================
|
||||
|
||||
.. function:: func_without_module(a, b, *c[, d])
|
||||
|
||||
Does something.
|
||||
|
||||
.. function:: func_without_body()
|
||||
|
||||
.. function:: func_noindex
|
||||
:noindex:
|
||||
|
||||
.. function:: func_with_module
|
||||
:module: foolib
|
||||
|
||||
Referring to :func:`func with no index <func_noindex>`.
|
||||
Referring to :func:`nothing <>`.
|
||||
|
||||
.. module:: mod
|
||||
:synopsis: Module synopsis.
|
||||
:platform: UNIX
|
||||
|
||||
.. function:: func_in_module
|
||||
|
||||
.. class:: Cls
|
||||
|
||||
.. method:: meth1
|
||||
|
||||
.. staticmethod:: meths
|
||||
|
||||
.. attribute:: attr
|
||||
|
||||
.. explicit class given
|
||||
.. method:: Cls.meth2
|
||||
|
||||
.. explicit module given
|
||||
.. exception:: Error(arg1, arg2)
|
||||
:module: errmod
|
||||
|
||||
.. data:: var
|
||||
|
||||
|
||||
.. currentmodule:: None
|
||||
|
||||
.. function:: func_without_module2() -> annotation
|
||||
|
||||
.. object:: long(parameter, \
|
||||
list)
|
||||
another one
|
||||
|
||||
.. class:: TimeInt
|
||||
|
||||
Has only one parameter (triggers special behavior...)
|
||||
|
||||
:param moo: |test|
|
||||
:type moo: |test|
|
||||
|
||||
.. |test| replace:: Moo
|
||||
|
||||
.. class:: Time(hour, minute, isdst)
|
||||
|
||||
:param year: The year.
|
||||
:type year: TimeInt
|
||||
:param TimeInt minute: The minute.
|
||||
:param isdst: whether it's DST
|
||||
:type isdst: * some complex
|
||||
* expression
|
||||
:returns: a new :class:`Time` instance
|
||||
:rtype: :class:`Time`
|
||||
:raises ValueError: if the values are out of range
|
||||
:ivar int hour: like *hour*
|
||||
:ivar minute: like *minute*
|
||||
:vartype minute: int
|
||||
:param hour: Some parameter
|
||||
:type hour: DuplicateType
|
||||
:param hour: Duplicate param. Should not lead to crashes.
|
||||
:type hour: DuplicateType
|
||||
:param .Cls extcls: A class from another module.
|
||||
|
||||
|
||||
C items
|
||||
=======
|
||||
|
||||
.. c:function:: Sphinx_DoSomething()
|
||||
|
||||
.. c:member:: SphinxStruct.member
|
||||
|
||||
.. c:macro:: SPHINX_USE_PYTHON
|
||||
|
||||
.. c:type:: SphinxType
|
||||
|
||||
.. c:var:: sphinx_global
|
||||
|
||||
|
||||
Javascript items
|
||||
================
|
||||
|
||||
.. js:function:: foo()
|
||||
|
||||
.. js:data:: bar
|
||||
|
||||
.. documenting the method of any object
|
||||
.. js:function:: bar.baz(href, callback[, errback])
|
||||
|
||||
:param string href: The location of the resource.
|
||||
:param callback: Get's called with the data returned by the resource.
|
||||
:throws InvalidHref: If the `href` is invalid.
|
||||
:returns: `undefined`
|
||||
|
||||
.. js:attribute:: bar.spam
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
Referencing :class:`mod.Cls` or :Class:`mod.Cls` should be the same.
|
||||
|
||||
With target: :c:func:`Sphinx_DoSomething()` (parentheses are handled),
|
||||
:c:member:`SphinxStruct.member`, :c:macro:`SPHINX_USE_PYTHON`,
|
||||
:c:type:`SphinxType *` (pointer is handled), :c:data:`sphinx_global`.
|
||||
|
||||
Without target: :c:func:`CFunction`. :c:func:`!malloc`.
|
||||
|
||||
:js:func:`foo()`
|
||||
:js:func:`foo`
|
||||
|
||||
:js:data:`bar`
|
||||
:js:func:`bar.baz()`
|
||||
:js:func:`bar.baz`
|
||||
:js:func:`~bar.baz()`
|
||||
|
||||
:js:attr:`bar.baz`
|
||||
|
||||
|
||||
Others
|
||||
======
|
||||
|
||||
.. envvar:: HOME
|
||||
|
||||
.. program:: python
|
||||
|
||||
.. cmdoption:: -c command
|
||||
|
||||
.. program:: perl
|
||||
|
||||
.. cmdoption:: -c
|
||||
|
||||
.. option:: +p
|
||||
|
||||
Link to :option:`perl +p`.
|
||||
|
||||
|
||||
User markup
|
||||
===========
|
||||
|
||||
.. userdesc:: myobj:parameter
|
||||
|
||||
Description of userdesc.
|
||||
|
||||
|
||||
Referencing :userdescrole:`myobj`.
|
||||
|
||||
|
||||
CPP domain
|
||||
==========
|
||||
|
||||
.. cpp:class:: n::Array<T,d>
|
||||
|
||||
.. cpp:function:: T& operator[]( unsigned j )
|
||||
const T& operator[]( unsigned j ) const
|
||||
@@ -1,7 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from .mod1 import func1, Class1
|
||||
from .mod2 import (
|
||||
func2,
|
||||
Class2,
|
||||
)
|
||||
from __future__ import absolute_import
|
||||
|
||||
from .mod1 import func1, Class1
|
||||
from .mod2 import (
|
||||
func2,
|
||||
Class2,
|
||||
)
|
||||
@@ -1,15 +1,15 @@
|
||||
"""
|
||||
mod1
|
||||
"""
|
||||
|
||||
def func1(a, b):
|
||||
"""
|
||||
this is func1
|
||||
"""
|
||||
return a, b
|
||||
|
||||
|
||||
class Class1(object):
|
||||
"""
|
||||
this is Class1
|
||||
"""
|
||||
"""
|
||||
mod1
|
||||
"""
|
||||
|
||||
def func1(a, b):
|
||||
"""
|
||||
this is func1
|
||||
"""
|
||||
return a, b
|
||||
|
||||
|
||||
class Class1(object):
|
||||
"""
|
||||
this is Class1
|
||||
"""
|
||||
@@ -1,15 +1,15 @@
|
||||
"""
|
||||
mod2
|
||||
"""
|
||||
|
||||
def func2(a, b):
|
||||
"""
|
||||
this is func2
|
||||
"""
|
||||
return a, b
|
||||
|
||||
|
||||
class Class2(object):
|
||||
"""
|
||||
this is Class2
|
||||
"""
|
||||
"""
|
||||
mod2
|
||||
"""
|
||||
|
||||
def func2(a, b):
|
||||
"""
|
||||
this is func2
|
||||
"""
|
||||
return a, b
|
||||
|
||||
|
||||
class Class2(object):
|
||||
"""
|
||||
this is Class2
|
||||
"""
|
||||
@@ -1,15 +1,15 @@
|
||||
:tocdepth: 2
|
||||
|
||||
i18n with python domain refs
|
||||
=============================
|
||||
|
||||
.. currentmodule:: sensitive
|
||||
|
||||
See this decorator: :func:`sensitive_variables`.
|
||||
|
||||
.. function:: sensitive_variables(*variables)
|
||||
|
||||
Some description
|
||||
|
||||
.. currentmodule:: reporting
|
||||
|
||||
:tocdepth: 2
|
||||
|
||||
i18n with python domain refs
|
||||
=============================
|
||||
|
||||
.. currentmodule:: sensitive
|
||||
|
||||
See this decorator: :func:`sensitive_variables`.
|
||||
|
||||
.. function:: sensitive_variables(*variables)
|
||||
|
||||
Some description
|
||||
|
||||
.. currentmodule:: reporting
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
subdir contents
|
||||
===============
|
||||
subdir contents
|
||||
===============
|
||||
Whitespace-only changes.
@@ -0,0 +1,5 @@
|
||||
.. toctree::
|
||||
:numbered:
|
||||
|
||||
sub
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.. toctree::
|
||||
|
||||
contents
|
||||
@@ -1,5 +1,5 @@
|
||||
contents
|
||||
=========
|
||||
|
||||
spam egg ham
|
||||
|
||||
contents
|
||||
=========
|
||||
|
||||
spam egg ham
|
||||
|
||||
@@ -4,10 +4,4 @@ Autosummary templating test
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
|
||||
sphinx.application.Sphinx
|
||||
|
||||
.. currentmodule:: sphinx.application
|
||||
|
||||
.. autoclass:: TemplateBridge
|
||||
|
||||
.. automethod:: render
|
||||
sphinx.application.TemplateBridge
|
||||
File renamed without changes.
@@ -0,0 +1,3 @@
|
||||
project = 'versioning test root'
|
||||
master_doc = 'index'
|
||||
source_suffix = '.txt'
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+30
-36
@@ -11,47 +11,41 @@
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
from os import path, chdir, listdir, environ
|
||||
import shutil
|
||||
import traceback
|
||||
|
||||
from path import path
|
||||
|
||||
testroot = path.dirname(__file__) or '.'
|
||||
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')
|
||||
testroot = os.path.dirname(__file__) or '.'
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
|
||||
|
||||
shutil.rmtree(newroot, ignore_errors=True)
|
||||
# just copying test directory to parallel testing
|
||||
print('Copying sources to build/lib/tests...')
|
||||
shutil.copytree(testroot, newroot)
|
||||
# check dependencies before testing
|
||||
print('Checking dependencies...')
|
||||
for modname in ('nose', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
|
||||
'snowballstemmer', 'babel'):
|
||||
try:
|
||||
__import__(modname)
|
||||
except ImportError as err:
|
||||
if modname == 'mock' and sys.version_info[0] == 3:
|
||||
continue
|
||||
traceback.print_exc()
|
||||
print('The %r package is needed to run the Sphinx test suite.' % modname)
|
||||
sys.exit(1)
|
||||
|
||||
# always test the sphinx package from build/lib/
|
||||
sys.path.insert(0, path.abspath(path.join(newroot, path.pardir)))
|
||||
# switch to the copy/converted dir so nose tests the right tests
|
||||
chdir(newroot)
|
||||
|
||||
try:
|
||||
import nose
|
||||
except ImportError:
|
||||
print('The nose package is needed to run the Sphinx test suite.')
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
import docutils
|
||||
except ImportError:
|
||||
print('Sphinx requires the docutils package to be installed.')
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
import jinja2
|
||||
except ImportError:
|
||||
print('Sphinx requires the jinja2 package to be installed.')
|
||||
sys.exit(1)
|
||||
# find a temp dir for testing and clean it up now
|
||||
os.environ['SPHINX_TEST_TEMPDIR'] = \
|
||||
os.path.abspath(os.path.join(testroot, 'build')) \
|
||||
if 'SPHINX_TEST_TEMPDIR' not in os.environ \
|
||||
else os.path.abspath(os.environ['SPHINX_TEST_TEMPDIR'])
|
||||
tempdir = path(os.environ['SPHINX_TEST_TEMPDIR'])
|
||||
print('Temporary files will be placed in %s.' % tempdir)
|
||||
if tempdir.exists():
|
||||
tempdir.rmtree()
|
||||
tempdir.makedirs()
|
||||
|
||||
print('Running Sphinx test suite...')
|
||||
sys.stdout.flush()
|
||||
|
||||
import nose
|
||||
nose.main()
|
||||
@@ -8,82 +8,57 @@
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from nose.tools import with_setup
|
||||
|
||||
from util import with_app, test_roots
|
||||
from util import with_app, rootdir
|
||||
|
||||
|
||||
def setup_module():
|
||||
sys.path.insert(0, test_roots / 'test-api-set-translator')
|
||||
sys.path.insert(0, rootdir / 'roots' / 'test-api-set-translator')
|
||||
|
||||
|
||||
def teardown_module():
|
||||
sys.path.remove(test_roots / 'test-api-set-translator')
|
||||
sys.path.remove(rootdir / 'roots' / 'test-api-set-translator')
|
||||
|
||||
|
||||
def teardown_websupport():
|
||||
(test_roots / 'test-api-set-translator' / 'generated').rmtree(True)
|
||||
(test_roots / 'test-api-set-translator' / 'websupport').rmtree(True)
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='html',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
confdir=(test_roots / 'test-api-set-translator' / 'nonext'),
|
||||
)
|
||||
def test_html_translator(app):
|
||||
@with_app('html')
|
||||
def test_html_translator(app, status, warning):
|
||||
# no set_translator(), no html_translator_class
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'SmartyPantsHTMLTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='html',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
confdir=(test_roots / 'test-api-set-translator' / 'nonext'),
|
||||
confoverrides={
|
||||
'html_translator_class': 'translator.ExtHTMLTranslator'},
|
||||
)
|
||||
def test_html_with_html_translator_class(app):
|
||||
@with_app('html', confoverrides={
|
||||
'html_translator_class': 'translator.ExtHTMLTranslator'})
|
||||
def test_html_with_html_translator_class(app, status, warning):
|
||||
# no set_translator(), but html_translator_class
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ExtHTMLTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='html',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
confdir=(test_roots / 'test-api-set-translator' / 'nonext'),
|
||||
confoverrides={'html_use_smartypants': False},
|
||||
)
|
||||
def test_html_with_smartypants(app):
|
||||
@with_app('html',
|
||||
confoverrides={'html_use_smartypants': False})
|
||||
def test_html_with_smartypants(app, status, warning):
|
||||
# no set_translator(), html_use_smartypants=False
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'HTMLTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='html',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_html_with_set_translator_for_html_(app):
|
||||
@with_app('html', testroot='api-set-translator')
|
||||
def test_html_with_set_translator_for_html_(app, status, warning):
|
||||
# use set_translator(), no html_translator_class
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfHTMLTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='html',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
confoverrides={'html_translator_class': 'ext.ExtHTMLTranslator'},
|
||||
)
|
||||
def test_html_with_set_translator_for_html_and_html_translator_class(app):
|
||||
@with_app('html', testroot='api-set-translator',
|
||||
confoverrides={'html_translator_class': 'ext.ExtHTMLTranslator'})
|
||||
def test_html_with_set_translator_for_html_and_html_translator_class(app, status, warning):
|
||||
# use set_translator() and html_translator_class.
|
||||
# set_translator() is given priority over html_translator_clas.
|
||||
translator_class = app.builder.translator_class
|
||||
@@ -96,108 +71,70 @@ def test_html_with_set_translator_for_html_and_html_translator_class(app):
|
||||
# buildername='dirhtml',
|
||||
# srcdir=(test_roots / 'test-api-set-translator'),
|
||||
# )
|
||||
# def test_dirhtml_set_translator_for_dirhtml(app):
|
||||
# def test_dirhtml_set_translator_for_dirhtml(app, status, warning):
|
||||
# translator_class = app.builder.translator_class
|
||||
# assert translator_class
|
||||
# assert translator_class.__name__ == 'ConfDirHTMLTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='singlehtml',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_singlehtml_set_translator_for_singlehtml(app):
|
||||
@with_app('singlehtml', testroot='api-set-translator')
|
||||
def test_singlehtml_set_translator_for_singlehtml(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfSingleHTMLTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='pickle',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_pickle_set_translator_for_pickle(app):
|
||||
@with_app('pickle', testroot='api-set-translator')
|
||||
def test_pickle_set_translator_for_pickle(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfPickleTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='json',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_json_set_translator_for_json(app):
|
||||
@with_app('json', testroot='api-set-translator')
|
||||
def test_json_set_translator_for_json(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfJsonTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='latex',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_html_with_set_translator_for_latex(app):
|
||||
@with_app('latex', testroot='api-set-translator')
|
||||
def test_html_with_set_translator_for_latex(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfLaTeXTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='man',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_html_with_set_translator_for_man(app):
|
||||
@with_app('man', testroot='api-set-translator')
|
||||
def test_html_with_set_translator_for_man(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfManualPageTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='texinfo',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_html_with_set_translator_for_texinfo(app):
|
||||
@with_app('texinfo', testroot='api-set-translator')
|
||||
def test_html_with_set_translator_for_texinfo(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfTexinfoTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='text',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_html_with_set_translator_for_text(app):
|
||||
@with_app('text', testroot='api-set-translator')
|
||||
def test_html_with_set_translator_for_text(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfTextTranslator'
|
||||
|
||||
|
||||
@with_setup(teardown=teardown_websupport)
|
||||
@with_app(
|
||||
buildername='websupport',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_html_with_set_translator_for_websupport(app):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfWebSupportTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='xml',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_html_with_set_translator_for_xml(app):
|
||||
@with_app('xml', testroot='api-set-translator')
|
||||
def test_html_with_set_translator_for_xml(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfXMLTranslator'
|
||||
|
||||
|
||||
@with_app(
|
||||
buildername='pseudoxml',
|
||||
srcdir=(test_roots / 'test-api-set-translator'),
|
||||
)
|
||||
def test_html_with_set_translator_for_pseudoxml(app):
|
||||
@with_app('pseudoxml', testroot='api-set-translator')
|
||||
def test_html_with_set_translator_for_pseudoxml(app, status, warning):
|
||||
translator_class = app.builder.translator_class
|
||||
assert translator_class
|
||||
assert translator_class.__name__ == 'ConfPseudoXMLTranslator'
|
||||
+36
-45
@@ -9,22 +9,21 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from six import StringIO
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx.application import ExtensionError
|
||||
from sphinx.domains import Domain
|
||||
|
||||
from util import with_app, raises_msg, TestApp
|
||||
from util import with_app, raises_msg
|
||||
|
||||
|
||||
@with_app()
|
||||
def test_events(app):
|
||||
def empty(): pass
|
||||
def test_events(app, status, warning):
|
||||
def empty():
|
||||
pass
|
||||
raises_msg(ExtensionError, "Unknown event name: invalid",
|
||||
app.connect, "invalid", empty)
|
||||
|
||||
|
||||
app.add_event("my_event")
|
||||
raises_msg(ExtensionError, "Event 'my_event' already present",
|
||||
app.add_event, "my_event")
|
||||
@@ -43,57 +42,49 @@ def test_events(app):
|
||||
|
||||
|
||||
@with_app()
|
||||
def test_emit_with_nonascii_name_node(app):
|
||||
def test_emit_with_nonascii_name_node(app, status, warning):
|
||||
node = nodes.section(names=[u'\u65e5\u672c\u8a9e'])
|
||||
app.emit('my_event', node)
|
||||
|
||||
|
||||
def test_output():
|
||||
status, warnings = StringIO(), StringIO()
|
||||
app = TestApp(status=status, warning=warnings)
|
||||
try:
|
||||
status.truncate(0) # __init__ writes to status
|
||||
status.seek(0)
|
||||
app.info("Nothing here...")
|
||||
assert status.getvalue() == "Nothing here...\n"
|
||||
status.truncate(0)
|
||||
status.seek(0)
|
||||
app.info("Nothing here...", True)
|
||||
assert status.getvalue() == "Nothing here..."
|
||||
@with_app()
|
||||
def test_output(app, status, warning):
|
||||
status.truncate(0) # __init__ writes to status
|
||||
status.seek(0)
|
||||
app.info("Nothing here...")
|
||||
assert status.getvalue() == "Nothing here...\n"
|
||||
status.truncate(0)
|
||||
status.seek(0)
|
||||
app.info("Nothing here...", True)
|
||||
assert status.getvalue() == "Nothing here..."
|
||||
|
||||
old_count = app._warncount
|
||||
app.warn("Bad news!")
|
||||
assert warnings.getvalue() == "WARNING: Bad news!\n"
|
||||
assert app._warncount == old_count + 1
|
||||
finally:
|
||||
app.cleanup()
|
||||
old_count = app._warncount
|
||||
app.warn("Bad news!")
|
||||
assert warning.getvalue() == "WARNING: Bad news!\n"
|
||||
assert app._warncount == old_count + 1
|
||||
|
||||
|
||||
def test_extensions():
|
||||
status, warnings = StringIO(), StringIO()
|
||||
app = TestApp(status=status, warning=warnings)
|
||||
try:
|
||||
app.setup_extension('shutil')
|
||||
assert warnings.getvalue().startswith("WARNING: extension 'shutil'")
|
||||
finally:
|
||||
app.cleanup()
|
||||
@with_app()
|
||||
def test_extensions(app, status, warning):
|
||||
app.setup_extension('shutil')
|
||||
assert warning.getvalue().startswith("WARNING: extension 'shutil'")
|
||||
|
||||
def test_domain_override():
|
||||
|
||||
@with_app()
|
||||
def test_domain_override(app, status, warning):
|
||||
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()
|
||||
|
||||
# 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)
|
||||
+14
-14
@@ -18,7 +18,7 @@ from six import StringIO
|
||||
from docutils.statemachine import ViewList
|
||||
|
||||
from sphinx.ext.autodoc import AutoDirective, add_documenter, \
|
||||
ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
|
||||
ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
|
||||
|
||||
app = None
|
||||
|
||||
@@ -123,24 +123,24 @@ def test_parse_name():
|
||||
directive.env.temp_data['autodoc:module'] = 'util'
|
||||
verify('function', 'raises', ('util', ['raises'], None, None))
|
||||
del directive.env.temp_data['autodoc:module']
|
||||
directive.env.temp_data['py:module'] = 'util'
|
||||
directive.env.ref_context['py:module'] = 'util'
|
||||
verify('function', 'raises', ('util', ['raises'], None, None))
|
||||
verify('class', 'TestApp', ('util', ['TestApp'], None, None))
|
||||
|
||||
# for members
|
||||
directive.env.temp_data['py:module'] = 'foo'
|
||||
directive.env.ref_context['py:module'] = 'foo'
|
||||
verify('method', 'util.TestApp.cleanup',
|
||||
('util', ['TestApp', 'cleanup'], None, None))
|
||||
directive.env.temp_data['py:module'] = 'util'
|
||||
directive.env.temp_data['py:class'] = 'Foo'
|
||||
directive.env.ref_context['py:module'] = 'util'
|
||||
directive.env.ref_context['py:class'] = 'Foo'
|
||||
directive.env.temp_data['autodoc:class'] = 'TestApp'
|
||||
verify('method', 'cleanup', ('util', ['TestApp', 'cleanup'], None, None))
|
||||
verify('method', 'TestApp.cleanup',
|
||||
('util', ['TestApp', 'cleanup'], None, None))
|
||||
|
||||
# and clean up
|
||||
del directive.env.temp_data['py:module']
|
||||
del directive.env.temp_data['py:class']
|
||||
del directive.env.ref_context['py:module']
|
||||
del directive.env.ref_context['py:class']
|
||||
del directive.env.temp_data['autodoc:class']
|
||||
|
||||
|
||||
@@ -584,7 +584,7 @@ def test_generate():
|
||||
'method', 'test_autodoc.Class.foobar', more_content=None)
|
||||
|
||||
# test auto and given content mixing
|
||||
directive.env.temp_data['py:module'] = 'test_autodoc'
|
||||
directive.env.ref_context['py:module'] = 'test_autodoc'
|
||||
assert_result_contains(' Function.', 'method', 'Class.meth')
|
||||
add_content = ViewList()
|
||||
add_content.append('Content.', '', 0)
|
||||
@@ -682,12 +682,12 @@ def test_generate():
|
||||
'attribute', 'test_autodoc.Class.descr')
|
||||
|
||||
# test generation for C modules (which have no source file)
|
||||
directive.env.temp_data['py:module'] = 'time'
|
||||
directive.env.ref_context['py:module'] = 'time'
|
||||
assert_processes([('function', 'time.asctime')], 'function', 'asctime')
|
||||
assert_processes([('function', 'time.asctime')], 'function', 'asctime')
|
||||
|
||||
# test autodoc_member_order == 'source'
|
||||
directive.env.temp_data['py:module'] = 'test_autodoc'
|
||||
directive.env.ref_context['py:module'] = 'test_autodoc'
|
||||
assert_order(['.. py:class:: Class(arg)',
|
||||
' .. py:attribute:: Class.descr',
|
||||
' .. py:method:: Class.meth()',
|
||||
@@ -704,7 +704,7 @@ def test_generate():
|
||||
' .. py:method:: Class.inheritedmeth()',
|
||||
],
|
||||
'class', 'Class', member_order='bysource', all_members=True)
|
||||
del directive.env.temp_data['py:module']
|
||||
del directive.env.ref_context['py:module']
|
||||
|
||||
# test attribute initialized to class instance from other module
|
||||
directive.env.temp_data['autodoc:class'] = 'test_autodoc.Class'
|
||||
@@ -729,7 +729,7 @@ def test_generate():
|
||||
'test_autodoc.Class.moore')
|
||||
|
||||
# test new attribute documenter behavior
|
||||
directive.env.temp_data['py:module'] = 'test_autodoc'
|
||||
directive.env.ref_context['py:module'] = 'test_autodoc'
|
||||
options.undoc_members = True
|
||||
assert_processes([('class', 'test_autodoc.AttCls'),
|
||||
('attribute', 'test_autodoc.AttCls.a1'),
|
||||
@@ -743,7 +743,7 @@ def test_generate():
|
||||
# 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'
|
||||
directive.env.ref_context['py:module'] = 'test_autodoc'
|
||||
options.inherited_members = False
|
||||
options.undoc_members = False
|
||||
options.members = ALL
|
||||
@@ -765,7 +765,7 @@ def test_generate():
|
||||
], 'class', 'InstAttCls')
|
||||
del directive.env.temp_data['autodoc:class']
|
||||
del directive.env.temp_data['autodoc:module']
|
||||
del directive.env.temp_data['py:module']
|
||||
del directive.env.ref_context['py:module']
|
||||
|
||||
# test descriptor class documentation
|
||||
options.members = ['CustomDataDescriptor']
|
||||
|
||||
+54
-82
@@ -3,114 +3,86 @@
|
||||
test_build
|
||||
~~~~~~~~~~
|
||||
|
||||
Test all builders that have no special checks.
|
||||
Test all builders.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from util import with_app, test_root, path, SkipTest, TestApp
|
||||
from six import BytesIO
|
||||
|
||||
from textwrap import dedent
|
||||
|
||||
from util import with_app, rootdir, tempdir, SkipTest, TestApp
|
||||
|
||||
try:
|
||||
from docutils.writers.manpage import Writer as ManWriter
|
||||
except ImportError:
|
||||
ManWriter = None
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_root / '_build').rmtree(True)
|
||||
class MockOpener(object):
|
||||
def open(self, req, **kwargs):
|
||||
class result(BytesIO):
|
||||
headers = None
|
||||
url = req.url
|
||||
return result()
|
||||
|
||||
import sphinx.builders.linkcheck
|
||||
sphinx.builders.linkcheck.opener = MockOpener()
|
||||
|
||||
|
||||
def test_build():
|
||||
for buildername in ('pickle', 'json', 'linkcheck', 'text', 'htmlhelp',
|
||||
'qthelp', 'epub', 'changes', 'singlehtml', 'xml',
|
||||
'pseudoxml'):
|
||||
app = TestApp(buildername=buildername)
|
||||
yield lambda app: app.builder.build_all(), app
|
||||
app.cleanup()
|
||||
|
||||
|
||||
@with_app(buildername='man')
|
||||
def test_man(app):
|
||||
if ManWriter is None:
|
||||
def verify_build(buildername, srcdir):
|
||||
if buildername == 'man' and ManWriter is None:
|
||||
raise SkipTest('man writer is not available')
|
||||
app.builder.build_all()
|
||||
assert (app.outdir / 'SphinxTests.1').exists()
|
||||
|
||||
|
||||
def _test_nonascii_path(app):
|
||||
srcdir = path(app.srcdir)
|
||||
mb_name = u'\u65e5\u672c\u8a9e'
|
||||
app = TestApp(buildername=buildername, srcdir=srcdir)
|
||||
try:
|
||||
(srcdir / mb_name).makedirs()
|
||||
except UnicodeEncodeError:
|
||||
from path import FILESYSTEMENCODING
|
||||
raise SkipTest(
|
||||
'nonascii filename not supported on this filesystem encoding: '
|
||||
'%s', FILESYSTEMENCODING)
|
||||
|
||||
(srcdir / mb_name / (mb_name + '.txt')).write_text(dedent("""
|
||||
multi byte file name page
|
||||
==========================
|
||||
"""))
|
||||
|
||||
master_doc = srcdir / 'contents.txt'
|
||||
master_doc.write_bytes((master_doc.text() + dedent("""
|
||||
.. toctree::
|
||||
|
||||
%(mb_name)s/%(mb_name)s
|
||||
""" % {'mb_name': mb_name})
|
||||
).encode('utf-8'))
|
||||
app.builder.build_all()
|
||||
|
||||
|
||||
def test_nonascii_path():
|
||||
(test_root / '_build').rmtree(True) #keep this to build first gettext
|
||||
|
||||
builder_names = ['gettext', 'html', 'dirhtml', 'singlehtml', 'latex',
|
||||
'texinfo', 'pickle', 'json', 'linkcheck', 'text',
|
||||
'htmlhelp', 'qthelp', 'epub', 'changes', 'xml',
|
||||
'pseudoxml']
|
||||
if ManWriter is not None:
|
||||
builder_names.append('man')
|
||||
|
||||
for buildername in builder_names:
|
||||
app = TestApp(buildername=buildername, _copy_to_temp=True)
|
||||
yield _test_nonascii_path, app
|
||||
app.builder.build_all()
|
||||
finally:
|
||||
app.cleanup()
|
||||
|
||||
|
||||
@with_app(buildername='text', srcdir='(empty)')
|
||||
def test_circular_toctree(app):
|
||||
contents = (".. toctree::\n"
|
||||
"\n"
|
||||
" sub\n")
|
||||
(app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
|
||||
def test_build_all():
|
||||
# If supported, build in a non-ASCII source dir
|
||||
test_name = u'\u65e5\u672c\u8a9e'
|
||||
try:
|
||||
srcdir = tempdir / test_name
|
||||
(rootdir / 'root').copytree(tempdir / test_name)
|
||||
except UnicodeEncodeError:
|
||||
srcdir = tempdir / 'all'
|
||||
else:
|
||||
# add a doc with a non-ASCII file name to the source dir
|
||||
(srcdir / (test_name + '.txt')).write_text(dedent("""
|
||||
nonascii file name page
|
||||
=======================
|
||||
"""))
|
||||
|
||||
contents = (".. toctree::\n"
|
||||
"\n"
|
||||
" contents\n")
|
||||
(app.srcdir / 'sub.rst').write_text(contents, encoding='utf-8')
|
||||
master_doc = srcdir / 'contents.txt'
|
||||
master_doc.write_bytes((master_doc.text() + dedent("""
|
||||
.. toctree::
|
||||
|
||||
%(test_name)s/%(test_name)s
|
||||
""" % {'test_name': test_name})
|
||||
).encode('utf-8'))
|
||||
|
||||
# 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',
|
||||
'changes', 'xml', 'pseudoxml', 'man', 'linkcheck']:
|
||||
yield verify_build, buildername, srcdir
|
||||
|
||||
|
||||
@with_app(buildername='text', testroot='circular')
|
||||
def test_circular_toctree(app, status, warning):
|
||||
app.builder.build_all()
|
||||
warnings = "".join(app._warning.content)
|
||||
warnings = warning.getvalue()
|
||||
assert 'circular toctree references detected, ignoring: sub <- contents <- sub' in warnings
|
||||
assert 'circular toctree references detected, ignoring: contents <- sub <- contents' in warnings
|
||||
|
||||
|
||||
@with_app(buildername='text', srcdir='(empty)')
|
||||
def test_numbered_circular_toctree(app):
|
||||
contents = (".. toctree::\n"
|
||||
" :numbered:\n"
|
||||
"\n"
|
||||
" sub\n")
|
||||
(app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
|
||||
|
||||
contents = (".. toctree::\n"
|
||||
"\n"
|
||||
" contents\n")
|
||||
(app.srcdir / 'sub.rst').write_text(contents, encoding='utf-8')
|
||||
@with_app(buildername='text', testroot='numbered-circular')
|
||||
def test_numbered_circular_toctree(app, status, warning):
|
||||
app.builder.build_all()
|
||||
warnings = "\n".join(app._warning.content)
|
||||
warnings = warning.getvalue()
|
||||
assert 'circular toctree references detected, ignoring: sub <- contents <- sub' in warnings
|
||||
assert 'circular toctree references detected, ignoring: contents <- sub <- contents' in warnings
|
||||
+23
-42
@@ -10,46 +10,30 @@
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import gettext
|
||||
import os
|
||||
import re
|
||||
import gettext
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from util import test_root, test_roots, with_app, SkipTest
|
||||
from nose.tools import assert_true, assert_equal
|
||||
|
||||
from util import with_app, gen_with_app, SkipTest, assert_in
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_root / '_build').rmtree(True)
|
||||
(test_roots / 'test-intl' / '_build').rmtree(True),
|
||||
|
||||
|
||||
@with_app(buildername='gettext')
|
||||
def test_all(app):
|
||||
@gen_with_app('gettext', srcdir='root-gettext')
|
||||
def test_all(app, status, warning):
|
||||
# Generic build; should fail only when the builder is horribly broken.
|
||||
app.builder.build_all()
|
||||
|
||||
|
||||
@with_app(buildername='gettext')
|
||||
def test_build(app):
|
||||
# Do messages end up in the correct location?
|
||||
app.builder.build(['extapi', 'subdir/includes'])
|
||||
# top-level documents end up in a message catalog
|
||||
assert (app.outdir / 'extapi.pot').isfile()
|
||||
yield assert_true, (app.outdir / 'extapi.pot').isfile()
|
||||
# directory items are grouped into sections
|
||||
assert (app.outdir / 'subdir.pot').isfile()
|
||||
yield assert_true, (app.outdir / 'subdir.pot').isfile()
|
||||
|
||||
|
||||
@with_app(buildername='gettext')
|
||||
def test_seealso(app):
|
||||
# regression test for issue #960
|
||||
app.builder.build(['markup'])
|
||||
catalog = (app.outdir / 'markup.pot').text(encoding='utf-8')
|
||||
assert 'msgid "something, something else, something more"' in catalog
|
||||
|
||||
|
||||
@with_app(buildername='gettext')
|
||||
def test_gettext(app):
|
||||
app.builder.build(['markup'])
|
||||
yield assert_in, 'msgid "something, something else, something more"', catalog
|
||||
|
||||
(app.outdir / 'en' / 'LC_MESSAGES').makedirs()
|
||||
cwd = os.getcwd()
|
||||
@@ -58,7 +42,7 @@ def test_gettext(app):
|
||||
try:
|
||||
p = Popen(['msginit', '--no-translator', '-i', 'markup.pot',
|
||||
'--locale', 'en_US'],
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
except OSError:
|
||||
raise SkipTest # most likely msginit was not found
|
||||
else:
|
||||
@@ -67,12 +51,12 @@ def test_gettext(app):
|
||||
print(stdout)
|
||||
print(stderr)
|
||||
assert False, 'msginit exited with return code %s' % \
|
||||
p.returncode
|
||||
assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
|
||||
p.returncode
|
||||
yield assert_true, (app.outdir / 'en_US.po').isfile(), 'msginit failed'
|
||||
try:
|
||||
p = Popen(['msgfmt', 'en_US.po', '-o',
|
||||
os.path.join('en', 'LC_MESSAGES', 'test_root.mo')],
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
os.path.join('en', 'LC_MESSAGES', 'test_root.mo')],
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
except OSError:
|
||||
raise SkipTest # most likely msgfmt was not found
|
||||
else:
|
||||
@@ -81,25 +65,24 @@ def test_gettext(app):
|
||||
print(stdout)
|
||||
print(stderr)
|
||||
assert False, 'msgfmt exited with return code %s' % \
|
||||
p.returncode
|
||||
assert (app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo').isfile(), \
|
||||
'msgfmt failed'
|
||||
p.returncode
|
||||
yield assert_true, (app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo').isfile(), \
|
||||
'msgfmt failed'
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
_ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
|
||||
assert _("Testing various markup") == u"Testing various markup"
|
||||
yield assert_equal, _("Testing various markup"), u"Testing various markup"
|
||||
|
||||
|
||||
@with_app(buildername='gettext',
|
||||
srcdir=(test_roots / 'test-intl'),
|
||||
doctreedir=(test_roots / 'test-intl' / '_build' / 'doctree'),
|
||||
@with_app('gettext', testroot='intl',
|
||||
confoverrides={'gettext_compact': False})
|
||||
def test_gettext_index_entries(app):
|
||||
def test_gettext_index_entries(app, status, warning):
|
||||
# regression test for #976
|
||||
app.builder.build(['index_entries'])
|
||||
|
||||
_msgid_getter = re.compile(r'msgid "(.*)"').search
|
||||
|
||||
def msgid_getter(msgid):
|
||||
m = _msgid_getter(msgid)
|
||||
if m:
|
||||
@@ -139,10 +122,8 @@ def test_gettext_index_entries(app):
|
||||
assert msgids == []
|
||||
|
||||
|
||||
@with_app(buildername='gettext',
|
||||
srcdir=(test_roots / 'test-intl'),
|
||||
doctreedir=(test_roots / 'test-intl' / '_build' / 'doctree'))
|
||||
def test_gettext_template(app):
|
||||
@with_app(buildername='gettext', testroot='intl')
|
||||
def test_gettext_template(app, status, warning):
|
||||
app.builder.build_all()
|
||||
assert (app.outdir / 'sphinx.pot').isfile()
|
||||
|
||||
|
||||
+68
-91
@@ -12,39 +12,30 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from six import PY3, iteritems, StringIO
|
||||
from six import PY3, iteritems
|
||||
from six.moves import html_entities
|
||||
|
||||
try:
|
||||
import pygments
|
||||
except ImportError:
|
||||
pygments = None
|
||||
|
||||
from sphinx import __version__
|
||||
from util import test_root, test_roots, remove_unicode_literals, gen_with_app, with_app
|
||||
from util import remove_unicode_literals, gen_with_app
|
||||
from etree13 import ElementTree as ET
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_root / '_build').rmtree(True)
|
||||
|
||||
|
||||
html_warnfile = StringIO()
|
||||
|
||||
ENV_WARNINGS = """\
|
||||
%(root)s/autodoc_fodder.py:docstring of autodoc_fodder\\.MarkupError:2: \
|
||||
(%(root)s/autodoc_fodder.py:docstring of autodoc_fodder\\.MarkupError:2: \
|
||||
WARNING: Explicit markup ends without a blank line; unexpected \
|
||||
unindent\\.\\n?
|
||||
%(root)s/images.txt:9: WARNING: image file not readable: foo.png
|
||||
)?%(root)s/images.txt:9: WARNING: image file not readable: foo.png
|
||||
%(root)s/images.txt:23: WARNING: nonlocal image URI found: \
|
||||
http://www.python.org/logo.png
|
||||
%(root)s/includes.txt:\\d*: WARNING: Encoding 'utf-8-sig' used for \
|
||||
reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \
|
||||
:encoding: option\\n?
|
||||
%(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png
|
||||
%(root)s/markup.txt:\\d+: WARNING: Malformed :option: u'Python c option', does \
|
||||
not contain option marker - or -- or /
|
||||
"""
|
||||
(%(root)s/markup.txt:\\d+: WARNING: Malformed :option: u'Python c option', does \
|
||||
not contain option marker - or -- or / or \\+
|
||||
%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \
|
||||
with "\\?": b?'here: >>>\\\\xbb<<<'
|
||||
)?"""
|
||||
|
||||
HTML_WARNINGS = ENV_WARNINGS + """\
|
||||
%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
|
||||
@@ -61,6 +52,7 @@ if PY3:
|
||||
|
||||
def tail_check(check):
|
||||
rex = re.compile(check)
|
||||
|
||||
def checker(nodes):
|
||||
for node in nodes:
|
||||
if node.tail and rex.search(node.tail):
|
||||
@@ -84,6 +76,8 @@ HTML_XPATH = {
|
||||
(".//a[@href='../_downloads/img.png']", ''),
|
||||
(".//img[@src='../_images/img.png']", ''),
|
||||
(".//p", 'This is an include file.'),
|
||||
(".//pre/span", 'line 1'),
|
||||
(".//pre/span", 'line 2'),
|
||||
],
|
||||
'includes.html': [
|
||||
(".//pre", u'Max Strauß'),
|
||||
@@ -91,6 +85,23 @@ HTML_XPATH = {
|
||||
(".//a[@href='_downloads/img1.png']", ''),
|
||||
(".//pre", u'"quotes"'),
|
||||
(".//pre", u"'included'"),
|
||||
(".//pre/span[@class='s']", u'üöä'),
|
||||
(".//div[@class='inc-pyobj1 highlight-text']//pre",
|
||||
r'^class Foo:\n pass\n\s*$'),
|
||||
(".//div[@class='inc-pyobj2 highlight-text']//pre",
|
||||
r'^ def baz\(\):\n pass\n\s*$'),
|
||||
(".//div[@class='inc-lines highlight-text']//pre",
|
||||
r'^class Foo:\n pass\nclass Bar:\n$'),
|
||||
(".//div[@class='inc-startend highlight-text']//pre",
|
||||
u'^foo = "Including Unicode characters: üöä"\\n$'),
|
||||
(".//div[@class='inc-preappend highlight-text']//pre",
|
||||
r'(?m)^START CODE$'),
|
||||
(".//div[@class='inc-pyobj-dedent highlight-python']//span",
|
||||
r'def'),
|
||||
(".//div[@class='inc-tab3 highlight-text']//pre",
|
||||
r'-| |-'),
|
||||
(".//div[@class='inc-tab8 highlight-python']//pre/span",
|
||||
r'-| |-'),
|
||||
],
|
||||
'autodoc.html': [
|
||||
(".//dt[@id='test_autodoc.Class']", ''),
|
||||
@@ -144,7 +155,7 @@ HTML_XPATH = {
|
||||
(".//a[@href='subdir/includes.html']"
|
||||
"[@class='reference internal']/em", 'Including in subdir'),
|
||||
(".//a[@href='objects.html#cmdoption-python-c']"
|
||||
"[@class='reference internal']/em", 'Python -c option'),
|
||||
"[@class='reference internal']/code/span[@class='pre']", '-c'),
|
||||
# abbreviations
|
||||
(".//abbr[@title='abbreviation']", '^abbr$'),
|
||||
# version stuff
|
||||
@@ -175,6 +186,9 @@ HTML_XPATH = {
|
||||
(".//p", 'In HTML.'),
|
||||
(".//p", 'In both.'),
|
||||
(".//p", 'Always present'),
|
||||
# tests for ``any`` role
|
||||
(".//a[@href='#with']/em", 'headings'),
|
||||
(".//a[@href='objects.html#func_without_body']/code/span", 'objects'),
|
||||
],
|
||||
'objects.html': [
|
||||
(".//dt[@id='mod.Cls.meth1']", ''),
|
||||
@@ -212,12 +226,10 @@ HTML_XPATH = {
|
||||
(".//h4", 'Custom sidebar'),
|
||||
# docfields
|
||||
(".//td[@class='field-body']/strong", '^moo$'),
|
||||
(".//td[@class='field-body']/strong",
|
||||
tail_check(r'\(Moo\) .* Moo')),
|
||||
(".//td[@class='field-body']/strong", tail_check(r'\(Moo\) .* Moo')),
|
||||
(".//td[@class='field-body']/ul/li/strong", '^hour$'),
|
||||
(".//td[@class='field-body']/ul/li/em", '^DuplicateType$'),
|
||||
(".//td[@class='field-body']/ul/li/em",
|
||||
tail_check(r'.* Some parameter')),
|
||||
(".//td[@class='field-body']/ul/li/em", tail_check(r'.* Some parameter')),
|
||||
],
|
||||
'contents.html': [
|
||||
(".//meta[@name='hc'][@content='hcval']", ''),
|
||||
@@ -238,6 +250,11 @@ HTML_XPATH = {
|
||||
(".//h4", 'Contents sidebar'),
|
||||
# custom JavaScript
|
||||
(".//script[@src='file://moo.js']", ''),
|
||||
# URL in contents
|
||||
(".//a[@class='reference external'][@href='http://sphinx-doc.org/']",
|
||||
'http://sphinx-doc.org/'),
|
||||
(".//a[@class='reference external'][@href='http://sphinx-doc.org/latest/']",
|
||||
'Latest reference'),
|
||||
],
|
||||
'bom.html': [
|
||||
(".//title", " File with UTF-8 BOM"),
|
||||
@@ -257,33 +274,19 @@ HTML_XPATH = {
|
||||
(".//a/strong", "Other"),
|
||||
(".//a", "entry"),
|
||||
(".//dt/a", "double"),
|
||||
]
|
||||
],
|
||||
'footnote.html': [
|
||||
(".//a[@class='footnote-reference'][@href='#id5'][@id='id1']", r"\[1\]"),
|
||||
(".//a[@class='footnote-reference'][@href='#id6'][@id='id2']", r"\[2\]"),
|
||||
(".//a[@class='footnote-reference'][@href='#foo'][@id='id3']", r"\[3\]"),
|
||||
(".//a[@class='reference internal'][@href='#bar'][@id='id4']", r"\[bar\]"),
|
||||
(".//a[@class='fn-backref'][@href='#id1']", r"\[1\]"),
|
||||
(".//a[@class='fn-backref'][@href='#id2']", r"\[2\]"),
|
||||
(".//a[@class='fn-backref'][@href='#id3']", r"\[3\]"),
|
||||
(".//a[@class='fn-backref'][@href='#id4']", r"\[bar\]"),
|
||||
],
|
||||
}
|
||||
|
||||
if pygments:
|
||||
HTML_XPATH['includes.html'].extend([
|
||||
(".//pre/span[@class='s']", u'üöä'),
|
||||
(".//div[@class='inc-pyobj1 highlight-text']//pre",
|
||||
r'^class Foo:\n pass\n\s*$'),
|
||||
(".//div[@class='inc-pyobj2 highlight-text']//pre",
|
||||
r'^ def baz\(\):\n pass\n\s*$'),
|
||||
(".//div[@class='inc-lines highlight-text']//pre",
|
||||
r'^class Foo:\n pass\nclass Bar:\n$'),
|
||||
(".//div[@class='inc-startend highlight-text']//pre",
|
||||
u'^foo = "Including Unicode characters: üöä"\\n$'),
|
||||
(".//div[@class='inc-preappend highlight-text']//pre",
|
||||
r'(?m)^START CODE$'),
|
||||
(".//div[@class='inc-pyobj-dedent highlight-python']//span",
|
||||
r'def'),
|
||||
(".//div[@class='inc-tab3 highlight-text']//pre",
|
||||
r'-| |-'),
|
||||
(".//div[@class='inc-tab8 highlight-python']//pre/span",
|
||||
r'-| |-'),
|
||||
])
|
||||
HTML_XPATH['subdir/includes.html'].extend([
|
||||
(".//pre/span", 'line 1'),
|
||||
(".//pre/span", 'line 2'),
|
||||
])
|
||||
|
||||
class NslessParser(ET.XMLParser):
|
||||
"""XMLParser that throws away namespaces in tag names."""
|
||||
@@ -317,7 +320,8 @@ def check_xpath(etree, fname, path, check, be_found=True):
|
||||
else:
|
||||
assert False, ('%r not found in any node matching '
|
||||
'path %s in %s: %r' % (check, path, fname,
|
||||
[node.text for node in nodes]))
|
||||
[node.text for node in nodes]))
|
||||
|
||||
|
||||
def check_static_entries(outdir):
|
||||
staticdir = outdir / '_static'
|
||||
@@ -332,21 +336,23 @@ def check_static_entries(outdir):
|
||||
# a file from _static, but matches exclude_patterns
|
||||
assert not (staticdir / 'excluded.css').exists()
|
||||
|
||||
|
||||
def check_extra_entries(outdir):
|
||||
assert (outdir / 'robots.txt').isfile()
|
||||
|
||||
@gen_with_app(buildername='html', warning=html_warnfile, cleanenv=True,
|
||||
|
||||
@gen_with_app(buildername='html',
|
||||
confoverrides={'html_context.hckey_co': 'hcval_co'},
|
||||
tags=['testtag'])
|
||||
def test_html(app):
|
||||
def test_html_output(app, status, warning):
|
||||
app.builder.build_all()
|
||||
html_warnings = html_warnfile.getvalue().replace(os.sep, '/')
|
||||
html_warnings = warning.getvalue().replace(os.sep, '/')
|
||||
html_warnings_exp = HTML_WARNINGS % {
|
||||
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
|
||||
'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 + \
|
||||
'--- Got:\n' + html_warnings
|
||||
'Warnings don\'t match:\n' + \
|
||||
'--- Expected (regex):\n' + html_warnings_exp + \
|
||||
'--- Got:\n' + html_warnings
|
||||
|
||||
for fname, paths in iteritems(HTML_XPATH):
|
||||
parser = NslessParser()
|
||||
@@ -362,23 +368,9 @@ def test_html(app):
|
||||
check_static_entries(app.builder.outdir)
|
||||
check_extra_entries(app.builder.outdir)
|
||||
|
||||
@with_app(buildername='html', srcdir='(empty)',
|
||||
confoverrides={'html_sidebars': {'*': ['globaltoc.html']}},
|
||||
)
|
||||
def test_html_with_globaltoc_and_hidden_toctree(app):
|
||||
# issue #1157: combination of 'globaltoc.html' and hidden toctree cause
|
||||
# exception.
|
||||
(app.srcdir / 'contents.rst').write_text(
|
||||
'\n.. toctree::'
|
||||
'\n'
|
||||
'\n.. toctree::'
|
||||
'\n :hidden:'
|
||||
'\n')
|
||||
app.builder.build_all()
|
||||
|
||||
|
||||
@gen_with_app(buildername='html', srcdir=(test_roots / 'test-tocdepth'))
|
||||
def test_tocdepth(app):
|
||||
@gen_with_app(buildername='html', testroot='tocdepth')
|
||||
def test_tocdepth(app, status, warning):
|
||||
# issue #1251
|
||||
app.builder.build_all()
|
||||
|
||||
@@ -388,14 +380,14 @@ def test_tocdepth(app):
|
||||
(".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
|
||||
(".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
|
||||
(".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
|
||||
],
|
||||
],
|
||||
'foo.html': [
|
||||
(".//h1", '1. Foo', True),
|
||||
(".//h2", '1.1. Foo A', True),
|
||||
(".//h3", '1.1.1. Foo A1', True),
|
||||
(".//h2", '1.2. Foo B', True),
|
||||
(".//h3", '1.2.1. Foo B1', True),
|
||||
],
|
||||
],
|
||||
'bar.html': [
|
||||
(".//h1", '2. Bar', True),
|
||||
(".//h2", '2.1. Bar A', True),
|
||||
@@ -420,8 +412,8 @@ def test_tocdepth(app):
|
||||
yield check_xpath, etree, fname, xpath, check, be_found
|
||||
|
||||
|
||||
@gen_with_app(buildername='singlehtml', srcdir=(test_roots / 'test-tocdepth'))
|
||||
def test_tocdepth_singlehtml(app):
|
||||
@gen_with_app(buildername='singlehtml', testroot='tocdepth')
|
||||
def test_tocdepth_singlehtml(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
expects = {
|
||||
@@ -463,18 +455,3 @@ def test_tocdepth_singlehtml(app):
|
||||
|
||||
for xpath, check, be_found in paths:
|
||||
yield check_xpath, etree, fname, xpath, check, be_found
|
||||
|
||||
|
||||
@with_app(buildername='html', srcdir='(empty)')
|
||||
def test_url_in_toctree(app):
|
||||
contents = (".. toctree::\n"
|
||||
"\n"
|
||||
" http://sphinx-doc.org/\n"
|
||||
" Latest reference <http://sphinx-doc.org/latest/>\n")
|
||||
|
||||
(app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
|
||||
app.builder.build_all()
|
||||
|
||||
result = (app.outdir / 'contents.html').text(encoding='utf-8')
|
||||
assert '<a class="reference external" href="http://sphinx-doc.org/">http://sphinx-doc.org/</a>' in result
|
||||
assert '<a class="reference external" href="http://sphinx-doc.org/latest/">Latest reference</a>' in result
|
||||
@@ -14,20 +14,14 @@ import os
|
||||
import re
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from six import PY3, StringIO
|
||||
from six import PY3
|
||||
|
||||
from sphinx.writers.latex import LaTeXTranslator
|
||||
|
||||
from util import test_root, SkipTest, remove_unicode_literals, with_app
|
||||
from util import SkipTest, remove_unicode_literals, with_app
|
||||
from test_build_html import ENV_WARNINGS
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_root / '_build').rmtree(True)
|
||||
|
||||
|
||||
latex_warnfile = StringIO()
|
||||
|
||||
LATEX_WARNINGS = ENV_WARNINGS + """\
|
||||
None:None: WARNING: citation not found: missing
|
||||
None:None: WARNING: no matching candidate for image URI u'foo.\\*'
|
||||
@@ -39,17 +33,17 @@ if PY3:
|
||||
LATEX_WARNINGS = remove_unicode_literals(LATEX_WARNINGS)
|
||||
|
||||
|
||||
@with_app(buildername='latex', warning=latex_warnfile, cleanenv=True)
|
||||
def test_latex(app):
|
||||
@with_app(buildername='latex')
|
||||
def test_latex(app, status, warning):
|
||||
LaTeXTranslator.ignore_missing_images = True
|
||||
app.builder.build_all()
|
||||
latex_warnings = latex_warnfile.getvalue().replace(os.sep, '/')
|
||||
latex_warnings = warning.getvalue().replace(os.sep, '/')
|
||||
latex_warnings_exp = LATEX_WARNINGS % {
|
||||
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
|
||||
'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 + \
|
||||
'--- Got:\n' + latex_warnings
|
||||
'Warnings don\'t match:\n' + \
|
||||
'--- Expected (regex):\n' + latex_warnings_exp + \
|
||||
'--- Got:\n' + latex_warnings
|
||||
|
||||
# file from latex_additional_files
|
||||
assert (app.outdir / 'svgimg.svg').isfile()
|
||||
|
||||
@@ -14,20 +14,14 @@ import os
|
||||
import re
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from six import PY3, StringIO
|
||||
from six import PY3
|
||||
|
||||
from sphinx.writers.texinfo import TexinfoTranslator
|
||||
|
||||
from util import test_root, SkipTest, remove_unicode_literals, with_app
|
||||
from util import SkipTest, remove_unicode_literals, with_app
|
||||
from test_build_html import ENV_WARNINGS
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_root / '_build').rmtree(True)
|
||||
|
||||
|
||||
texinfo_warnfile = StringIO()
|
||||
|
||||
TEXINFO_WARNINGS = ENV_WARNINGS + """\
|
||||
None:None: WARNING: citation not found: missing
|
||||
None:None: WARNING: no matching candidate for image URI u'foo.\\*'
|
||||
@@ -38,17 +32,17 @@ if PY3:
|
||||
TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
|
||||
|
||||
|
||||
@with_app(buildername='texinfo', warning=texinfo_warnfile, cleanenv=True)
|
||||
def test_texinfo(app):
|
||||
@with_app('texinfo')
|
||||
def test_texinfo(app, status, warning):
|
||||
TexinfoTranslator.ignore_missing_images = True
|
||||
app.builder.build_all()
|
||||
texinfo_warnings = texinfo_warnfile.getvalue().replace(os.sep, '/')
|
||||
texinfo_warnings = warning.getvalue().replace(os.sep, '/')
|
||||
texinfo_warnings_exp = TEXINFO_WARNINGS % {
|
||||
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
|
||||
'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 + \
|
||||
'--- Got:\n' + texinfo_warnings
|
||||
'Warnings don\'t match:\n' + \
|
||||
'--- Expected (regex):\n' + texinfo_warnings_exp + \
|
||||
'--- Got:\n' + texinfo_warnings
|
||||
# now, try to run makeinfo over it
|
||||
cwd = os.getcwd()
|
||||
os.chdir(app.outdir)
|
||||
|
||||
+27
-93
@@ -18,29 +18,16 @@ from util import with_app
|
||||
def with_text_app(*args, **kw):
|
||||
default_kw = {
|
||||
'buildername': 'text',
|
||||
'srcdir': '(empty)',
|
||||
'confoverrides': {
|
||||
'project': 'text',
|
||||
'master_doc': 'contents',
|
||||
},
|
||||
'testroot': 'build-text',
|
||||
}
|
||||
default_kw.update(kw)
|
||||
return with_app(*args, **default_kw)
|
||||
|
||||
|
||||
@with_text_app()
|
||||
def test_maxwitdh_with_prefix(app):
|
||||
long_string = u' '.join([u"ham"] * 30)
|
||||
contents = (
|
||||
u".. seealso:: %(long_string)s\n\n"
|
||||
u"* %(long_string)s\n"
|
||||
u"* %(long_string)s\n"
|
||||
u"\nspam egg\n"
|
||||
) % locals()
|
||||
|
||||
(app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'contents.txt').text(encoding='utf-8')
|
||||
def test_maxwitdh_with_prefix(app, status, warning):
|
||||
app.builder.build_update()
|
||||
result = (app.outdir / 'maxwidth.txt').text(encoding='utf-8')
|
||||
|
||||
lines = result.splitlines()
|
||||
line_widths = [column_width(line) for line in lines]
|
||||
@@ -58,105 +45,52 @@ def test_maxwitdh_with_prefix(app):
|
||||
|
||||
|
||||
@with_text_app()
|
||||
def test_lineblock(app):
|
||||
def test_lineblock(app, status, warning):
|
||||
# regression test for #1109: need empty line after line block
|
||||
contents = (
|
||||
u"* one\n"
|
||||
u"\n"
|
||||
u" | line-block 1\n"
|
||||
u" | line-block 2\n"
|
||||
u"\n"
|
||||
u"followed paragraph.\n"
|
||||
)
|
||||
|
||||
(app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'contents.txt').text(encoding='utf-8')
|
||||
|
||||
app.builder.build_update()
|
||||
result = (app.outdir / 'lineblock.txt').text(encoding='utf-8')
|
||||
expect = (
|
||||
u"* one\n"
|
||||
u"\n"
|
||||
u" line-block 1\n"
|
||||
u" line-block 2\n"
|
||||
u"\n"
|
||||
u"followed paragraph.\n"
|
||||
)
|
||||
|
||||
u"* one\n"
|
||||
u"\n"
|
||||
u" line-block 1\n"
|
||||
u" line-block 2\n"
|
||||
u"\n"
|
||||
u"followed paragraph.\n"
|
||||
)
|
||||
assert result == expect
|
||||
|
||||
|
||||
@with_text_app()
|
||||
def test_nonascii_title_line(app):
|
||||
title = u'\u65e5\u672c\u8a9e'
|
||||
underline = u'=' * column_width(title)
|
||||
content = u'\n'.join((title, underline, u''))
|
||||
|
||||
(app.srcdir / 'contents.rst').write_text(content, encoding='utf-8')
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'contents.txt').text(encoding='utf-8')
|
||||
|
||||
expect_underline = underline.replace('=', '*')
|
||||
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()
|
||||
assert expect_underline == result_underline
|
||||
|
||||
|
||||
@with_text_app()
|
||||
def test_nonascii_table(app):
|
||||
text = u'\u65e5\u672c\u8a9e'
|
||||
contents = (u"\n.. list-table::"
|
||||
"\n"
|
||||
"\n - - spam"
|
||||
"\n - egg"
|
||||
"\n"
|
||||
"\n - - %(text)s"
|
||||
"\n - %(text)s"
|
||||
"\n" % locals())
|
||||
|
||||
(app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'contents.txt').text(encoding='utf-8')
|
||||
|
||||
def test_nonascii_table(app, status, warning):
|
||||
app.builder.build_update()
|
||||
result = (app.outdir / 'nonascii_table.txt').text(encoding='utf-8')
|
||||
lines = [line.strip() for line in result.splitlines() if line.strip()]
|
||||
line_widths = [column_width(line) for line in lines]
|
||||
assert len(set(line_widths)) == 1 # same widths
|
||||
|
||||
|
||||
@with_text_app()
|
||||
def test_nonascii_maxwidth(app):
|
||||
sb_text = u'abc' #length=3
|
||||
mb_text = u'\u65e5\u672c\u8a9e' #length=3
|
||||
|
||||
sb_line = ' '.join([sb_text] * int(MAXWIDTH / 3))
|
||||
mb_line = ' '.join([mb_text] * int(MAXWIDTH / 3))
|
||||
mix_line = ' '.join([sb_text, mb_text] * int(MAXWIDTH / 6))
|
||||
|
||||
contents = u'\n\n'.join((sb_line, mb_line, mix_line))
|
||||
|
||||
(app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'contents.txt').text(encoding='utf-8')
|
||||
|
||||
def test_nonascii_maxwidth(app, status, warning):
|
||||
app.builder.build_update()
|
||||
result = (app.outdir / 'nonascii_maxwidth.txt').text(encoding='utf-8')
|
||||
lines = [line.strip() for line in result.splitlines() if line.strip()]
|
||||
line_widths = [column_width(line) for line in lines]
|
||||
assert max(line_widths) < MAXWIDTH
|
||||
|
||||
|
||||
@with_text_app()
|
||||
def test_table_with_empty_cell(app):
|
||||
contents = (u"""
|
||||
+-----+-----+
|
||||
| XXX | XXX |
|
||||
+-----+-----+
|
||||
| | XXX |
|
||||
+-----+-----+
|
||||
| XXX | |
|
||||
+-----+-----+
|
||||
""")
|
||||
|
||||
(app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'contents.txt').text(encoding='utf-8')
|
||||
|
||||
def test_table_with_empty_cell(app, status, warning):
|
||||
app.builder.build_update()
|
||||
result = (app.outdir / 'table.txt').text(encoding='utf-8')
|
||||
lines = [line.strip() for line in result.splitlines() if line.strip()]
|
||||
assert lines[0] == "+-------+-------+"
|
||||
assert lines[1] == "| XXX | XXX |"
|
||||
|
||||
@@ -1,77 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_build_base
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Test the base build process.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import shutil
|
||||
|
||||
from nose.tools import with_setup
|
||||
|
||||
from util import test_roots, with_app, find_files
|
||||
|
||||
root = test_roots / 'test-intl'
|
||||
build_dir = root / '_build'
|
||||
locale_dir = build_dir / 'locale'
|
||||
|
||||
|
||||
def setup_test():
|
||||
# Delete remnants left over after failed build
|
||||
locale_dir.rmtree(True)
|
||||
# copy all catalogs into locale layout directory
|
||||
for po in find_files(root, '.po'):
|
||||
copy_po = (locale_dir / 'en' / 'LC_MESSAGES' / po)
|
||||
if not copy_po.parent.exists():
|
||||
copy_po.parent.makedirs()
|
||||
shutil.copy(root / po, copy_po)
|
||||
|
||||
|
||||
def teardown_test():
|
||||
build_dir.rmtree(True),
|
||||
|
||||
|
||||
@with_setup(setup_test, teardown_test)
|
||||
@with_app(buildername='html', srcdir=root,
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_all_catalogs(app):
|
||||
app.builder.compile_all_catalogs()
|
||||
|
||||
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
|
||||
expect = set([
|
||||
x.replace('.po', '.mo')
|
||||
for x in find_files(catalog_dir, '.po')
|
||||
])
|
||||
actual = set(find_files(catalog_dir, '.mo'))
|
||||
assert actual # not empty
|
||||
assert actual == expect
|
||||
|
||||
|
||||
@with_setup(setup_test, teardown_test)
|
||||
@with_app(buildername='html', srcdir=root,
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_specific_catalogs(app):
|
||||
app.builder.compile_specific_catalogs(['admonitions'])
|
||||
|
||||
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
|
||||
actual = set(find_files(catalog_dir, '.mo'))
|
||||
assert actual == set(['admonitions.mo'])
|
||||
|
||||
|
||||
@with_setup(setup_test, teardown_test)
|
||||
@with_app(buildername='html', srcdir=root,
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_update_catalogs(app):
|
||||
app.builder.compile_update_catalogs()
|
||||
|
||||
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
|
||||
expect = set([
|
||||
x.replace('.po', '.mo')
|
||||
for x in find_files(catalog_dir, '.po')
|
||||
])
|
||||
actual = set(find_files(catalog_dir, '.mo'))
|
||||
assert actual # not empty
|
||||
assert actual == expect
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_build_base
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Test the base build process.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import shutil
|
||||
|
||||
from nose.tools import with_setup
|
||||
|
||||
from util import with_app, find_files, rootdir, tempdir
|
||||
|
||||
root = tempdir / 'test-intl'
|
||||
build_dir = root / '_build'
|
||||
locale_dir = build_dir / 'locale'
|
||||
|
||||
|
||||
def setup_test():
|
||||
# delete remnants left over after failed build
|
||||
root.rmtree(True)
|
||||
(rootdir / 'roots' / 'test-intl').copytree(root)
|
||||
# copy all catalogs into locale layout directory
|
||||
for po in find_files(root, '.po'):
|
||||
copy_po = (locale_dir / 'en' / 'LC_MESSAGES' / po)
|
||||
if not copy_po.parent.exists():
|
||||
copy_po.parent.makedirs()
|
||||
shutil.copy(root / po, copy_po)
|
||||
|
||||
|
||||
def teardown_test():
|
||||
build_dir.rmtree(True)
|
||||
|
||||
|
||||
@with_setup(setup_test, teardown_test)
|
||||
@with_app(buildername='html', testroot='intl',
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_all_catalogs(app, status, warning):
|
||||
app.builder.compile_all_catalogs()
|
||||
|
||||
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
|
||||
expect = set([
|
||||
x.replace('.po', '.mo')
|
||||
for x in find_files(catalog_dir, '.po')
|
||||
])
|
||||
actual = set(find_files(catalog_dir, '.mo'))
|
||||
assert actual # not empty
|
||||
assert actual == expect
|
||||
|
||||
|
||||
@with_setup(setup_test, teardown_test)
|
||||
@with_app(buildername='html', testroot='intl',
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_specific_catalogs(app, status, warning):
|
||||
app.builder.compile_specific_catalogs(['admonitions'])
|
||||
|
||||
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
|
||||
actual = set(find_files(catalog_dir, '.mo'))
|
||||
assert actual == set(['admonitions.mo'])
|
||||
|
||||
|
||||
@with_setup(setup_test, teardown_test)
|
||||
@with_app(buildername='html', testroot='intl',
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_update_catalogs(app, status, warning):
|
||||
app.builder.compile_update_catalogs()
|
||||
|
||||
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
|
||||
expect = set([
|
||||
x.replace('.po', '.mo')
|
||||
for x in find_files(catalog_dir, '.po')
|
||||
])
|
||||
actual = set(find_files(catalog_dir, '.mo'))
|
||||
assert actual # not empty
|
||||
assert actual == expect
|
||||
@@ -20,7 +20,7 @@ from sphinx.errors import ExtensionError, ConfigError, VersionRequirementError
|
||||
@with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True',
|
||||
'latex_elements.docclass': 'scrartcl',
|
||||
'modindex_common_prefix': 'path1,path2'})
|
||||
def test_core_config(app):
|
||||
def test_core_config(app, status, warning):
|
||||
cfg = app.config
|
||||
|
||||
# simple values
|
||||
@@ -36,7 +36,7 @@ def test_core_config(app):
|
||||
# simple default values
|
||||
assert 'locale_dirs' not in cfg.__dict__
|
||||
assert cfg.locale_dirs == []
|
||||
assert cfg.trim_footnote_reference_space == False
|
||||
assert cfg.trim_footnote_reference_space is False
|
||||
|
||||
# complex default values
|
||||
assert 'html_title' not in cfg.__dict__
|
||||
@@ -68,7 +68,7 @@ def test_core_config(app):
|
||||
|
||||
|
||||
@with_app()
|
||||
def test_extension_values(app):
|
||||
def test_extension_values(app, status, warning):
|
||||
cfg = app.config
|
||||
|
||||
# default value
|
||||
|
||||
+111
-172
@@ -1,172 +1,111 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_directive_code
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test the code-block directive.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import re
|
||||
from xml.etree import ElementTree
|
||||
|
||||
from util import with_app, test_roots
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_roots / 'test-directive-code' / '_build').rmtree(True)
|
||||
|
||||
|
||||
@with_app(buildername='xml',
|
||||
srcdir=(test_roots / 'test-directive-code'),
|
||||
_copy_to_temp=True)
|
||||
def test_code_block(app):
|
||||
app.builder.build('index')
|
||||
et = ElementTree.parse(app.outdir / 'index.xml')
|
||||
secs = et.findall('./section/section')
|
||||
code_block = secs[0].findall('literal_block')
|
||||
assert len(code_block) > 0
|
||||
actual = code_block[0].text
|
||||
expect = (
|
||||
" def ruby?\n" +
|
||||
" false\n" +
|
||||
" end"
|
||||
)
|
||||
assert actual == expect
|
||||
|
||||
|
||||
@with_app(buildername='xml',
|
||||
srcdir=(test_roots / 'test-directive-code'),
|
||||
_copy_to_temp=True)
|
||||
def test_code_block_dedent(app):
|
||||
outdir = app.outdir
|
||||
|
||||
def get_dedent_actual(dedent):
|
||||
dedent_text = (app.srcdir / 'dedent.rst').text(encoding='utf-8')
|
||||
dedent_text = re.sub(
|
||||
r':dedent: \d', ':dedent: %d' % dedent, dedent_text)
|
||||
(app.srcdir / 'dedent.rst').write_text(dedent_text, encoding='utf-8')
|
||||
|
||||
# use another output dir to force rebuild
|
||||
app.outdir = outdir / str(dedent)
|
||||
app._init_env(freshenv=True)
|
||||
app._init_builder(app.builder.name)
|
||||
app.builder.build(['dedent'], method='specific')
|
||||
|
||||
et = ElementTree.parse(app.outdir / 'dedent.xml')
|
||||
secs = et.findall('./section/section')
|
||||
code_block = secs[0].findall('literal_block')
|
||||
|
||||
assert len(code_block) > 0
|
||||
actual = code_block[0].text
|
||||
return actual
|
||||
|
||||
for i in range(5): # 0-4
|
||||
actual = get_dedent_actual(i)
|
||||
indent = " " * (4 - i)
|
||||
expect = (
|
||||
indent + "def ruby?\n" +
|
||||
indent + " false\n" +
|
||||
indent + "end"
|
||||
)
|
||||
assert (i, actual) == (i, expect)
|
||||
|
||||
actual = get_dedent_actual(1000)
|
||||
assert actual == '\n\n'
|
||||
|
||||
|
||||
@with_app(buildername='html',
|
||||
srcdir=(test_roots / 'test-directive-code'),
|
||||
_copy_to_temp=True)
|
||||
def test_code_block_caption_html(app):
|
||||
app.builder.build('index')
|
||||
html = (app.outdir / 'caption.html').text()
|
||||
caption = '<div class="code-block-caption">caption <em>test</em> rb</div>'
|
||||
print caption, html
|
||||
assert caption in html
|
||||
|
||||
|
||||
@with_app(buildername='latex',
|
||||
srcdir=(test_roots / 'test-directive-code'),
|
||||
_copy_to_temp=True)
|
||||
def test_code_block_caption_latex(app):
|
||||
app.builder.build('index')
|
||||
latex = (app.outdir / 'Python.tex').text()
|
||||
caption = '\\caption{caption \\emph{test} rb}'
|
||||
assert caption in latex
|
||||
|
||||
|
||||
@with_app(buildername='xml',
|
||||
srcdir=(test_roots / 'test-directive-code'),
|
||||
_copy_to_temp=True)
|
||||
def test_literal_include(app):
|
||||
app.builder.build('index')
|
||||
et = ElementTree.parse(app.outdir / 'index.xml')
|
||||
secs = et.findall('./section/section')
|
||||
literal_include = secs[1].findall('literal_block')
|
||||
literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
|
||||
assert len(literal_include) > 0
|
||||
actual = literal_include[0].text
|
||||
assert actual == literal_src
|
||||
|
||||
|
||||
@with_app(buildername='xml',
|
||||
srcdir=(test_roots / 'test-directive-code'),
|
||||
_copy_to_temp=True)
|
||||
def test_literal_include_dedent(app):
|
||||
outdir = app.outdir
|
||||
literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
|
||||
literal_lines = [l[4:] for l in literal_src.split('\n')[9:11]]
|
||||
|
||||
def get_dedent_actual(dedent):
|
||||
dedent_text = (app.srcdir / 'dedent.rst').text(encoding='utf-8')
|
||||
dedent_text = re.sub(
|
||||
r':dedent: \d', ':dedent: %d' % dedent, dedent_text)
|
||||
(app.srcdir / 'dedent.rst').write_text(dedent_text, encoding='utf-8')
|
||||
|
||||
# use another output dir to force rebuild
|
||||
app.outdir = outdir / str(dedent)
|
||||
app._init_env(freshenv=True)
|
||||
app._init_builder(app.builder.name)
|
||||
app.builder.build(['dedent'])
|
||||
|
||||
et = ElementTree.parse(app.outdir / 'dedent.xml')
|
||||
secs = et.findall('./section/section')
|
||||
literal_include = secs[1].findall('literal_block')
|
||||
|
||||
assert len(literal_include) > 0
|
||||
actual = literal_include[0].text
|
||||
return actual
|
||||
|
||||
|
||||
for i in range(5): # 0-4
|
||||
actual = get_dedent_actual(i)
|
||||
indent = " " * (4 - i)
|
||||
expect = '\n'.join(indent + l for l in literal_lines) + '\n'
|
||||
assert (i, actual) == (i, expect)
|
||||
|
||||
|
||||
actual = get_dedent_actual(1000)
|
||||
assert actual == '\n\n'
|
||||
|
||||
|
||||
@with_app(buildername='html',
|
||||
srcdir=(test_roots / 'test-directive-code'),
|
||||
_copy_to_temp=True)
|
||||
def test_literalinclude_caption_html(app):
|
||||
app.builder.build('index')
|
||||
html = (app.outdir / 'caption.html').text()
|
||||
caption = '<div class="code-block-caption">caption <strong>test</strong> py</div>'
|
||||
assert caption in html
|
||||
|
||||
|
||||
@with_app(buildername='latex',
|
||||
srcdir=(test_roots / 'test-directive-code'),
|
||||
_copy_to_temp=True)
|
||||
def test_literalinclude_caption_latex(app):
|
||||
app.builder.build('index')
|
||||
latex = (app.outdir / 'Python.tex').text()
|
||||
caption = '\\caption{caption \\textbf{test} py}'
|
||||
assert caption in latex
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_directive_code
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test the code-block directive.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from xml.etree import ElementTree
|
||||
|
||||
from util import with_app
|
||||
|
||||
|
||||
@with_app('xml', testroot='directive-code')
|
||||
def test_code_block(app, status, warning):
|
||||
app.builder.build('index')
|
||||
et = ElementTree.parse(app.outdir / 'index.xml')
|
||||
secs = et.findall('./section/section')
|
||||
code_block = secs[0].findall('literal_block')
|
||||
assert len(code_block) > 0
|
||||
actual = code_block[0].text
|
||||
expect = (
|
||||
" def ruby?\n" +
|
||||
" false\n" +
|
||||
" end"
|
||||
)
|
||||
assert actual == expect
|
||||
|
||||
|
||||
@with_app('xml', testroot='directive-code')
|
||||
def test_code_block_dedent(app, status, warning):
|
||||
app.builder.build(['dedent_code'])
|
||||
et = ElementTree.parse(app.outdir / 'dedent_code.xml')
|
||||
blocks = et.findall('./section/section/literal_block')
|
||||
|
||||
for i in range(5): # 0-4
|
||||
actual = blocks[i].text
|
||||
indent = " " * (4 - i)
|
||||
expect = (
|
||||
indent + "def ruby?\n" +
|
||||
indent + " false\n" +
|
||||
indent + "end"
|
||||
)
|
||||
assert (i, actual) == (i, expect)
|
||||
|
||||
assert blocks[5].text == '\n\n' # dedent: 1000
|
||||
|
||||
|
||||
@with_app('html', testroot='directive-code')
|
||||
def test_code_block_caption_html(app, status, warning):
|
||||
app.builder.build(['caption'])
|
||||
html = (app.outdir / 'caption.html').text()
|
||||
caption = '<div class="code-block-caption">caption <em>test</em> rb</div>'
|
||||
assert caption in html
|
||||
|
||||
|
||||
@with_app('latex', testroot='directive-code')
|
||||
def test_code_block_caption_latex(app, status, warning):
|
||||
app.builder.build_all()
|
||||
latex = (app.outdir / 'Python.tex').text()
|
||||
caption = '\\caption{caption \\emph{test} rb}'
|
||||
assert caption in latex
|
||||
|
||||
|
||||
@with_app('xml', testroot='directive-code')
|
||||
def test_literal_include(app, status, warning):
|
||||
app.builder.build(['index'])
|
||||
et = ElementTree.parse(app.outdir / 'index.xml')
|
||||
secs = et.findall('./section/section')
|
||||
literal_include = secs[1].findall('literal_block')
|
||||
literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
|
||||
assert len(literal_include) > 0
|
||||
actual = literal_include[0].text
|
||||
assert actual == literal_src
|
||||
|
||||
|
||||
@with_app('xml', testroot='directive-code')
|
||||
def test_literal_include_dedent(app, status, warning):
|
||||
literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
|
||||
literal_lines = [l[4:] for l in literal_src.split('\n')[9:11]]
|
||||
|
||||
app.builder.build(['dedent'])
|
||||
et = ElementTree.parse(app.outdir / 'dedent.xml')
|
||||
blocks = et.findall('./section/section/literal_block')
|
||||
|
||||
for i in range(5): # 0-4
|
||||
actual = blocks[i].text
|
||||
indent = ' ' * (4 - i)
|
||||
expect = '\n'.join(indent + l for l in literal_lines) + '\n'
|
||||
assert (i, actual) == (i, expect)
|
||||
|
||||
assert blocks[5].text == '\n\n' # dedent: 1000
|
||||
|
||||
|
||||
@with_app('html', testroot='directive-code')
|
||||
def test_literalinclude_caption_html(app, status, warning):
|
||||
app.builder.build('index')
|
||||
html = (app.outdir / 'caption.html').text()
|
||||
caption = '<div class="code-block-caption">caption <strong>test</strong> py</div>'
|
||||
assert caption in html
|
||||
|
||||
|
||||
@with_app('latex', testroot='directive-code')
|
||||
def test_literalinclude_caption_latex(app, status, warning):
|
||||
app.builder.build('index')
|
||||
latex = (app.outdir / 'Python.tex').text()
|
||||
caption = '\\caption{caption \\textbf{test} py}'
|
||||
assert caption in latex
|
||||
@@ -13,15 +13,11 @@ import re
|
||||
|
||||
from docutils import nodes
|
||||
|
||||
from util import with_app, test_roots
|
||||
from util import with_app
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_roots / 'test-directive-only' / '_build').rmtree(True)
|
||||
|
||||
|
||||
@with_app(buildername='text', srcdir=(test_roots / 'test-directive-only'))
|
||||
def test_sectioning(app):
|
||||
@with_app('text', testroot='directive-only')
|
||||
def test_sectioning(app, status, warning):
|
||||
|
||||
def getsects(section):
|
||||
if not isinstance(section, nodes.section):
|
||||
|
||||
+19
-64
@@ -9,50 +9,17 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
from functools import wraps
|
||||
|
||||
from six import StringIO
|
||||
|
||||
from util import test_roots, TestApp, path, SkipTest
|
||||
|
||||
|
||||
html_warnfile = StringIO()
|
||||
root = test_roots / 'test-docutilsconf'
|
||||
|
||||
|
||||
# need cleanenv to rebuild everytime.
|
||||
# docutils.conf change did not effect to rebuild.
|
||||
def with_conf_app(docutilsconf='', *args, **kwargs):
|
||||
default_kw = {
|
||||
'srcdir': root,
|
||||
'cleanenv': True,
|
||||
}
|
||||
default_kw.update(kwargs)
|
||||
def generator(func):
|
||||
@wraps(func)
|
||||
def deco(*args2, **kwargs2):
|
||||
app = TestApp(*args, **default_kw)
|
||||
(app.srcdir / 'docutils.conf').write_text(docutilsconf)
|
||||
try:
|
||||
cwd = os.getcwd()
|
||||
os.chdir(app.srcdir)
|
||||
func(app, *args2, **kwargs2)
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
# don't execute cleanup if test failed
|
||||
app.cleanup()
|
||||
return deco
|
||||
return generator
|
||||
from util import with_app, path, SkipTest
|
||||
|
||||
|
||||
def regex_count(expr, result):
|
||||
return len(re.findall(expr, result))
|
||||
|
||||
|
||||
@with_conf_app(buildername='html')
|
||||
def test_html_with_default_docutilsconf(app):
|
||||
@with_app('html', testroot='docutilsconf', freshenv=True, docutilsconf='')
|
||||
def test_html_with_default_docutilsconf(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
result = (app.outdir / 'contents.html').text(encoding='utf-8')
|
||||
|
||||
@@ -62,13 +29,13 @@ def test_html_with_default_docutilsconf(app):
|
||||
assert regex_count(r'<td class="option-group" colspan="2">', result) == 1
|
||||
|
||||
|
||||
@with_conf_app(buildername='html', docutilsconf=(
|
||||
@with_app('html', testroot='docutilsconf', freshenv=True, docutilsconf=(
|
||||
'\n[html4css1 writer]'
|
||||
'\noption-limit:1'
|
||||
'\nfield-name-limit:1'
|
||||
'\n')
|
||||
)
|
||||
def test_html_with_docutilsconf(app):
|
||||
def test_html_with_docutilsconf(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
result = (app.outdir / 'contents.html').text(encoding='utf-8')
|
||||
|
||||
@@ -78,41 +45,32 @@ def test_html_with_docutilsconf(app):
|
||||
assert regex_count(r'<td class="option-group" colspan="2">', result) == 2
|
||||
|
||||
|
||||
@with_conf_app(buildername='html', warning=html_warnfile)
|
||||
def test_html(app):
|
||||
@with_app('html', testroot='docutilsconf')
|
||||
def test_html(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
assert html_warnfile.getvalue() == ''
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@with_conf_app(buildername='latex', warning=html_warnfile)
|
||||
def test_latex(app):
|
||||
@with_app('latex', testroot='docutilsconf')
|
||||
def test_latex(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
assert html_warnfile.getvalue() == ''
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@with_conf_app(buildername='man', warning=html_warnfile)
|
||||
def test_man(app):
|
||||
@with_app('man', testroot='docutilsconf')
|
||||
def test_man(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
assert html_warnfile.getvalue() == ''
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@with_conf_app(buildername='texinfo', warning=html_warnfile)
|
||||
def test_texinfo(app):
|
||||
@with_app('texinfo', testroot='docutilsconf')
|
||||
def test_texinfo(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
|
||||
|
||||
@with_conf_app(buildername='html', srcdir='(empty)',
|
||||
docutilsconf='[general]\nsource_link=true\n')
|
||||
def test_docutils_source_link(app):
|
||||
srcdir = path(app.srcdir)
|
||||
(srcdir / 'conf.py').write_text('')
|
||||
(srcdir / 'contents.rst').write_text('')
|
||||
app.builder.build_all()
|
||||
|
||||
|
||||
@with_conf_app(buildername='html', srcdir='(empty)',
|
||||
docutilsconf='[general]\nsource_link=true\n')
|
||||
def test_docutils_source_link_with_nonascii_file(app):
|
||||
@with_app('html', testroot='docutilsconf',
|
||||
docutilsconf='[general]\nsource_link=true\n')
|
||||
def test_docutils_source_link_with_nonascii_file(app, status, warning):
|
||||
srcdir = path(app.srcdir)
|
||||
mb_name = u'\u65e5\u672c\u8a9e'
|
||||
try:
|
||||
@@ -123,7 +81,4 @@ def test_docutils_source_link_with_nonascii_file(app):
|
||||
'nonascii filename not supported on this filesystem encoding: '
|
||||
'%s', FILESYSTEMENCODING)
|
||||
|
||||
(srcdir / 'conf.py').write_text('')
|
||||
(srcdir / 'contents.rst').write_text('')
|
||||
|
||||
app.builder.build_all()
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_py_domain
|
||||
test_domain_py
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Tests the Python Domain
|
||||
File renamed without changes.
+80
-80
@@ -1,80 +1,80 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_domain_std
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Tests the std domain
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx.domains.std import StandardDomain
|
||||
from util import mock
|
||||
|
||||
|
||||
def test_process_doc_handle_figure_caption():
|
||||
env = mock.Mock(domaindata={})
|
||||
figure_node = nodes.figure(
|
||||
'',
|
||||
nodes.caption('caption text', 'caption text'),
|
||||
)
|
||||
document = mock.Mock(
|
||||
nametypes={'testname': True},
|
||||
nameids={'testname': 'testid'},
|
||||
ids={'testid': figure_node},
|
||||
)
|
||||
|
||||
domain = StandardDomain(env)
|
||||
if 'testname' in domain.data['labels']:
|
||||
del domain.data['labels']['testname']
|
||||
domain.process_doc(env, 'testdoc', document)
|
||||
assert 'testname' in domain.data['labels']
|
||||
assert domain.data['labels']['testname'] == (
|
||||
'testdoc', 'testid', 'caption text')
|
||||
|
||||
|
||||
def test_process_doc_handle_image_parent_figure_caption():
|
||||
env = mock.Mock(domaindata={})
|
||||
img_node = nodes.image('', alt='image alt')
|
||||
figure_node = nodes.figure(
|
||||
'',
|
||||
nodes.caption('caption text', 'caption text'),
|
||||
img_node,
|
||||
)
|
||||
document = mock.Mock(
|
||||
nametypes={'testname': True},
|
||||
nameids={'testname': 'testid'},
|
||||
ids={'testid': img_node},
|
||||
)
|
||||
|
||||
domain = StandardDomain(env)
|
||||
if 'testname' in domain.data['labels']:
|
||||
del domain.data['labels']['testname']
|
||||
domain.process_doc(env, 'testdoc', document)
|
||||
assert 'testname' in domain.data['labels']
|
||||
assert domain.data['labels']['testname'] == (
|
||||
'testdoc', 'testid', 'caption text')
|
||||
|
||||
|
||||
def test_process_doc_handle_table_title():
|
||||
env = mock.Mock(domaindata={})
|
||||
table_node = nodes.table(
|
||||
'',
|
||||
nodes.title('title text', 'title text'),
|
||||
)
|
||||
document = mock.Mock(
|
||||
nametypes={'testname': True},
|
||||
nameids={'testname': 'testid'},
|
||||
ids={'testid': table_node},
|
||||
)
|
||||
|
||||
domain = StandardDomain(env)
|
||||
if 'testname' in domain.data['labels']:
|
||||
del domain.data['labels']['testname']
|
||||
domain.process_doc(env, 'testdoc', document)
|
||||
assert 'testname' in domain.data['labels']
|
||||
assert domain.data['labels']['testname'] == (
|
||||
'testdoc', 'testid', 'title text')
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_domain_std
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Tests the std domain
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx.domains.std import StandardDomain
|
||||
from util import mock
|
||||
|
||||
|
||||
def test_process_doc_handle_figure_caption():
|
||||
env = mock.Mock(domaindata={})
|
||||
figure_node = nodes.figure(
|
||||
'',
|
||||
nodes.caption('caption text', 'caption text'),
|
||||
)
|
||||
document = mock.Mock(
|
||||
nametypes={'testname': True},
|
||||
nameids={'testname': 'testid'},
|
||||
ids={'testid': figure_node},
|
||||
)
|
||||
|
||||
domain = StandardDomain(env)
|
||||
if 'testname' in domain.data['labels']:
|
||||
del domain.data['labels']['testname']
|
||||
domain.process_doc(env, 'testdoc', document)
|
||||
assert 'testname' in domain.data['labels']
|
||||
assert domain.data['labels']['testname'] == (
|
||||
'testdoc', 'testid', 'caption text')
|
||||
|
||||
|
||||
def test_process_doc_handle_image_parent_figure_caption():
|
||||
env = mock.Mock(domaindata={})
|
||||
img_node = nodes.image('', alt='image alt')
|
||||
figure_node = nodes.figure(
|
||||
'',
|
||||
nodes.caption('caption text', 'caption text'),
|
||||
img_node,
|
||||
)
|
||||
document = mock.Mock(
|
||||
nametypes={'testname': True},
|
||||
nameids={'testname': 'testid'},
|
||||
ids={'testid': img_node},
|
||||
)
|
||||
|
||||
domain = StandardDomain(env)
|
||||
if 'testname' in domain.data['labels']:
|
||||
del domain.data['labels']['testname']
|
||||
domain.process_doc(env, 'testdoc', document)
|
||||
assert 'testname' in domain.data['labels']
|
||||
assert domain.data['labels']['testname'] == (
|
||||
'testdoc', 'testid', 'caption text')
|
||||
|
||||
|
||||
def test_process_doc_handle_table_title():
|
||||
env = mock.Mock(domaindata={})
|
||||
table_node = nodes.table(
|
||||
'',
|
||||
nodes.title('title text', 'title text'),
|
||||
)
|
||||
document = mock.Mock(
|
||||
nametypes={'testname': True},
|
||||
nameids={'testname': 'testid'},
|
||||
ids={'testid': table_node},
|
||||
)
|
||||
|
||||
domain = StandardDomain(env)
|
||||
if 'testname' in domain.data['labels']:
|
||||
del domain.data['labels']['testname']
|
||||
domain.process_doc(env, 'testdoc', document)
|
||||
assert 'testname' in domain.data['labels']
|
||||
assert domain.data['labels']['testname'] == (
|
||||
'testdoc', 'testid', 'title text')
|
||||
@@ -8,9 +8,10 @@
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from six import PY3
|
||||
|
||||
from util import TestApp, remove_unicode_literals, path, with_app
|
||||
from util import TestApp, remove_unicode_literals, path
|
||||
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
from sphinx.builders.latex import LaTeXBuilder
|
||||
@@ -18,34 +19,35 @@ from sphinx.builders.latex import LaTeXBuilder
|
||||
app = env = None
|
||||
warnings = []
|
||||
|
||||
|
||||
def setup_module():
|
||||
global app, env
|
||||
app = TestApp(freshenv=True, _copy_to_temp=True)
|
||||
app = TestApp(srcdir='root-envtest')
|
||||
env = app.env
|
||||
env.set_warnfunc(lambda *args: warnings.append(args))
|
||||
|
||||
|
||||
def teardown_module():
|
||||
app.cleanup()
|
||||
|
||||
|
||||
def warning_emitted(file, text):
|
||||
for warning in warnings:
|
||||
if len(warning) == 2 and file in warning[1] and text in warning[0]:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Tests are run in the order they appear in the file, therefore we can
|
||||
# afford to not run update() in the setup but in its own test
|
||||
|
||||
def test_first_update():
|
||||
msg, num, it = env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
assert msg.endswith('%d added, 0 changed, 0 removed' % len(env.found_docs))
|
||||
docnames = set()
|
||||
for docname in it: # the generator does all the work
|
||||
docnames.add(docname)
|
||||
assert docnames == env.found_docs == set(env.all_docs)
|
||||
updated = env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
assert set(updated) == env.found_docs == set(env.all_docs)
|
||||
# test if exclude_patterns works ok
|
||||
assert 'subdir/excluded' not in env.found_docs
|
||||
|
||||
|
||||
def test_images():
|
||||
assert warning_emitted('images', 'image file not readable: foo.png')
|
||||
assert warning_emitted('images', 'nonlocal image URI found: '
|
||||
@@ -75,6 +77,7 @@ def test_images():
|
||||
assert set(latexbuilder.images.values()) == \
|
||||
set(['img.pdf', 'img.png', 'img1.png', 'simg.png', 'svgimg.pdf'])
|
||||
|
||||
|
||||
def test_second_update():
|
||||
# delete, add and "edit" (change saved mtime) some files and update again
|
||||
env.all_docs['contents'] = 0
|
||||
@@ -83,30 +86,33 @@ def test_second_update():
|
||||
# the contents.txt toctree; otherwise section numbers would shift
|
||||
(root / 'autodoc.txt').unlink()
|
||||
(root / 'new.txt').write_text('New file\n========\n')
|
||||
msg, num, it = env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
assert '1 added, 3 changed, 1 removed' in msg
|
||||
docnames = set()
|
||||
for docname in it:
|
||||
docnames.add(docname)
|
||||
updated = env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
# "includes" and "images" are in there because they contain references
|
||||
# to nonexisting downloadable or image files, which are given another
|
||||
# chance to exist
|
||||
assert docnames == set(['contents', 'new', 'includes', 'images'])
|
||||
assert set(updated) == set(['contents', 'new', 'includes', 'images'])
|
||||
assert 'autodoc' not in env.all_docs
|
||||
assert 'autodoc' not in env.found_docs
|
||||
|
||||
|
||||
@with_app(srcdir='(empty)')
|
||||
def test_undecodable_source_reading_emit_warnings(app):
|
||||
# issue #1524
|
||||
warnings[:] = []
|
||||
app.env.set_warnfunc(lambda *args: warnings.append(args))
|
||||
(app.srcdir / 'contents.rst').write_bytes(b'1\xbb2')
|
||||
_, _, it = app.env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
list(it) # the generator does all the work
|
||||
assert warning_emitted(
|
||||
'contents', 'undecodable source characters, replacing with "?":'
|
||||
)
|
||||
def test_env_read_docs():
|
||||
"""By default, docnames are read in alphanumeric order"""
|
||||
def on_env_read_docs_1(app, env, docnames):
|
||||
pass
|
||||
|
||||
app.connect('env-before-read-docs', on_env_read_docs_1)
|
||||
|
||||
read_docnames = env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
assert len(read_docnames) > 2 and read_docnames == sorted(read_docnames)
|
||||
|
||||
def on_env_read_docs_2(app, env, docnames):
|
||||
docnames.reverse()
|
||||
|
||||
app.connect('env-before-read-docs', on_env_read_docs_2)
|
||||
|
||||
read_docnames = env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
reversed_read_docnames = sorted(read_docnames, reverse=True)
|
||||
assert len(read_docnames) > 2 and read_docnames == reversed_read_docnames
|
||||
|
||||
|
||||
def test_object_inventory():
|
||||
@@ -8,49 +8,24 @@
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import sys
|
||||
from functools import wraps
|
||||
|
||||
from six import iteritems, StringIO
|
||||
|
||||
from sphinx.ext.autosummary import mangle_signature
|
||||
|
||||
from util import test_roots, TestApp
|
||||
from util import with_app
|
||||
|
||||
html_warnfile = StringIO()
|
||||
|
||||
|
||||
def with_autosummary_app(*args, **kw):
|
||||
default_kw = {
|
||||
'srcdir': (test_roots / 'test-autosummary'),
|
||||
'confoverrides': {
|
||||
'extensions': ['sphinx.ext.autosummary'],
|
||||
'autosummary_generate': True,
|
||||
'source_suffix': '.rst'
|
||||
}
|
||||
default_kw = {
|
||||
'testroot': 'autosummary',
|
||||
'confoverrides': {
|
||||
'extensions': ['sphinx.ext.autosummary'],
|
||||
'autosummary_generate': True,
|
||||
'source_suffix': '.rst'
|
||||
}
|
||||
default_kw.update(kw)
|
||||
def generator(func):
|
||||
@wraps(func)
|
||||
def deco(*args2, **kwargs2):
|
||||
# Now, modify the python path...
|
||||
srcdir = default_kw['srcdir']
|
||||
sys.path.insert(0, srcdir)
|
||||
try:
|
||||
app = TestApp(*args, **default_kw)
|
||||
func(app, *args2, **kwargs2)
|
||||
finally:
|
||||
if srcdir in sys.path:
|
||||
sys.path.remove(srcdir)
|
||||
# remove the auto-generated dummy_module.rst
|
||||
dummy_rst = srcdir / 'dummy_module.rst'
|
||||
if dummy_rst.isfile():
|
||||
dummy_rst.unlink()
|
||||
|
||||
# don't execute cleanup if test failed
|
||||
app.cleanup()
|
||||
return deco
|
||||
return generator
|
||||
}
|
||||
|
||||
|
||||
def test_mangle_signature():
|
||||
@@ -79,10 +54,8 @@ def test_mangle_signature():
|
||||
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
|
||||
|
||||
|
||||
@with_autosummary_app(buildername='html', warning=html_warnfile)
|
||||
def test_get_items_summary(app):
|
||||
app.builddir.rmtree(True)
|
||||
|
||||
@with_app(buildername='html', **default_kw)
|
||||
def test_get_items_summary(app, status, warning):
|
||||
# monkey-patch Autosummary.get_items so we can easily get access to it's
|
||||
# results..
|
||||
import sphinx.ext.autosummary
|
||||
@@ -96,13 +69,17 @@ def test_get_items_summary(app):
|
||||
autosummary_items[name] = result
|
||||
return results
|
||||
|
||||
def handler(app, what, name, obj, options, lines):
|
||||
assert isinstance(lines, list)
|
||||
app.connect('autodoc-process-docstring', handler)
|
||||
|
||||
sphinx.ext.autosummary.Autosummary.get_items = new_get_items
|
||||
try:
|
||||
app.builder.build_all()
|
||||
finally:
|
||||
sphinx.ext.autosummary.Autosummary.get_items = orig_get_items
|
||||
|
||||
html_warnings = html_warnfile.getvalue()
|
||||
html_warnings = warning.getvalue()
|
||||
assert html_warnings == ''
|
||||
|
||||
expected_values = {
|
||||
@@ -118,13 +95,3 @@ def test_get_items_summary(app):
|
||||
for key, expected in iteritems(expected_values):
|
||||
assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
|
||||
' expected %r' % (key, autosummary_items[key], expected)
|
||||
|
||||
|
||||
@with_autosummary_app(buildername='html')
|
||||
def test_process_doc_event(app):
|
||||
app.builddir.rmtree(True)
|
||||
|
||||
def handler(app, what, name, obj, options, lines):
|
||||
assert isinstance(lines, list)
|
||||
app.connect('autodoc-process-docstring', handler)
|
||||
app.builder.build_all()
|
||||
@@ -15,7 +15,7 @@ from util import with_app
|
||||
|
||||
|
||||
@with_app(buildername='coverage')
|
||||
def test_build(app):
|
||||
def test_build(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
py_undoc = (app.outdir / 'python.txt').text()
|
||||
@@ -8,30 +8,24 @@
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
from six import StringIO
|
||||
|
||||
from util import with_app
|
||||
|
||||
|
||||
status = StringIO()
|
||||
cleanup_called = 0
|
||||
|
||||
@with_app(buildername='doctest', status=status)
|
||||
def test_build(app):
|
||||
|
||||
@with_app(buildername='doctest', testroot='doctest')
|
||||
def test_build(app, status, warning):
|
||||
global cleanup_called
|
||||
cleanup_called = 0
|
||||
app.builder.build_all()
|
||||
if app.statuscode != 0:
|
||||
print(status.getvalue(), file=sys.stderr)
|
||||
assert False, 'failures in doctests'
|
||||
assert False, 'failures in doctests:' + status.getvalue()
|
||||
# in doctest.txt, there are two named groups and the default group,
|
||||
# so the cleanup function must be called three times
|
||||
assert cleanup_called == 3, 'testcleanup did not get executed enough times'
|
||||
|
||||
|
||||
def cleanup_call():
|
||||
global cleanup_called
|
||||
cleanup_called += 1
|
||||
@@ -17,7 +17,7 @@ from docutils import nodes
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.ext.intersphinx import read_inventory_v1, read_inventory_v2, \
|
||||
load_mappings, missing_reference
|
||||
load_mappings, missing_reference
|
||||
|
||||
from util import with_app, with_tempdir
|
||||
|
||||
@@ -49,9 +49,9 @@ def test_read_inventory_v1():
|
||||
f.readline()
|
||||
invdata = read_inventory_v1(f, '/util', posixpath.join)
|
||||
assert invdata['py:module']['module'] == \
|
||||
('foo', '1.0', '/util/foo.html#module-module', '-')
|
||||
('foo', '1.0', '/util/foo.html#module-module', '-')
|
||||
assert invdata['py:class']['module.cls'] == \
|
||||
('foo', '1.0', '/util/foo.html#module.cls', '-')
|
||||
('foo', '1.0', '/util/foo.html#module.cls', '-')
|
||||
|
||||
|
||||
def test_read_inventory_v2():
|
||||
@@ -68,19 +68,19 @@ def test_read_inventory_v2():
|
||||
|
||||
assert len(invdata1['py:module']) == 2
|
||||
assert invdata1['py:module']['module1'] == \
|
||||
('foo', '2.0', '/util/foo.html#module-module1', 'Long Module desc')
|
||||
('foo', '2.0', '/util/foo.html#module-module1', 'Long Module desc')
|
||||
assert invdata1['py:module']['module2'] == \
|
||||
('foo', '2.0', '/util/foo.html#module-module2', '-')
|
||||
('foo', '2.0', '/util/foo.html#module-module2', '-')
|
||||
assert invdata1['py:function']['module1.func'][2] == \
|
||||
'/util/sub/foo.html#module1.func'
|
||||
'/util/sub/foo.html#module1.func'
|
||||
assert invdata1['c:function']['CFunc'][2] == '/util/cfunc.html#CFunc'
|
||||
assert invdata1['std:term']['a term'][2] == \
|
||||
'/util/glossary.html#term-a-term'
|
||||
'/util/glossary.html#term-a-term'
|
||||
|
||||
|
||||
@with_app()
|
||||
@with_tempdir
|
||||
def test_missing_reference(tempdir, app):
|
||||
def test_missing_reference(tempdir, app, status, warning):
|
||||
inv_file = tempdir / 'inventory'
|
||||
inv_file.write_bytes(inventory_v2)
|
||||
app.config.intersphinx_mapping = {
|
||||
@@ -94,7 +94,7 @@ def test_missing_reference(tempdir, app):
|
||||
inv = app.env.intersphinx_inventory
|
||||
|
||||
assert inv['py:module']['module2'] == \
|
||||
('foo', '2.0', 'http://docs.python.org/foo.html#module-module2', '-')
|
||||
('foo', '2.0', 'http://docs.python.org/foo.html#module-module2', '-')
|
||||
|
||||
# create fake nodes and check referencing
|
||||
|
||||
@@ -156,7 +156,7 @@ def test_missing_reference(tempdir, app):
|
||||
|
||||
@with_app()
|
||||
@with_tempdir
|
||||
def test_load_mappings_warnings(tempdir, app):
|
||||
def test_load_mappings_warnings(tempdir, app, status, warning):
|
||||
"""
|
||||
load_mappings issues a warning if new-style mapping
|
||||
identifiers are not alphanumeric
|
||||
@@ -174,4 +174,4 @@ def test_load_mappings_warnings(tempdir, app):
|
||||
app.config.intersphinx_cache_limit = 0
|
||||
# load the inventory and check if it's done correctly
|
||||
load_mappings(app)
|
||||
assert len(app._warning.content) == 2
|
||||
assert warning.getvalue().count('\n') == 2
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+44
-43
@@ -1,43 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_ext_viewcode
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test sphinx.ext.viewcode extension.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from six import StringIO
|
||||
|
||||
from util import test_roots, with_app
|
||||
|
||||
|
||||
warnfile = StringIO()
|
||||
root = test_roots / 'test-ext-viewcode'
|
||||
doctreedir = root / '_build' / 'doctree'
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(root / '_build').rmtree(True)
|
||||
|
||||
|
||||
@with_app(srcdir=root, warning=warnfile)
|
||||
def test_simple(app):
|
||||
app.builder.build_all()
|
||||
|
||||
warnings = re.sub(r'\\+', '/', warnfile.getvalue())
|
||||
assert re.findall(
|
||||
r"index.rst:\d+: WARNING: Object named 'func1' not found in include " +
|
||||
r"file .*/spam/__init__.py'",
|
||||
warnings
|
||||
)
|
||||
|
||||
result = (app.outdir / 'index.html').text(encoding='utf-8')
|
||||
assert result.count('href="_modules/spam/mod1.html#func1"') == 2
|
||||
assert result.count('href="_modules/spam/mod2.html#func2"') == 2
|
||||
assert result.count('href="_modules/spam/mod1.html#Class1"') == 2
|
||||
assert result.count('href="_modules/spam/mod2.html#Class2"') == 2
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_ext_viewcode
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test sphinx.ext.viewcode extension.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from util import with_app
|
||||
|
||||
|
||||
@with_app(testroot='ext-viewcode')
|
||||
def test_viewcode(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
warnings = re.sub(r'\\+', '/', warning.getvalue())
|
||||
assert re.findall(
|
||||
r"index.rst:\d+: WARNING: Object named 'func1' not found in include " +
|
||||
r"file .*/spam/__init__.py'",
|
||||
warnings
|
||||
)
|
||||
|
||||
result = (app.outdir / 'index.html').text(encoding='utf-8')
|
||||
assert result.count('href="_modules/spam/mod1.html#func1"') == 2
|
||||
assert result.count('href="_modules/spam/mod2.html#func2"') == 2
|
||||
assert result.count('href="_modules/spam/mod1.html#Class1"') == 2
|
||||
assert result.count('href="_modules/spam/mod2.html#Class2"') == 2
|
||||
|
||||
|
||||
@with_app(testroot='ext-viewcode', tags=['test_linkcode'])
|
||||
def test_linkcode(app, status, warning):
|
||||
app.builder.build(['objects'])
|
||||
|
||||
stuff = (app.outdir / 'objects.html').text(encoding='utf-8')
|
||||
|
||||
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
|
||||
@@ -1,37 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_footnote
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Test for footnote and citation.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from util import test_root, with_app
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_root / '_build').rmtree(True)
|
||||
|
||||
|
||||
@with_app(buildername='html')
|
||||
def test_html(app):
|
||||
app.builder.build(['footnote'])
|
||||
result = (app.outdir / 'footnote.html').text(encoding='utf-8')
|
||||
expects = [
|
||||
'<a class="footnote-reference" href="#id5" id="id1">[1]</a>',
|
||||
'<a class="footnote-reference" href="#id6" id="id2">[2]</a>',
|
||||
'<a class="footnote-reference" href="#foo" id="id3">[3]</a>',
|
||||
'<a class="reference internal" href="#bar" id="id4">[bar]</a>',
|
||||
'<a class="fn-backref" href="#id1">[1]</a>',
|
||||
'<a class="fn-backref" href="#id2">[2]</a>',
|
||||
'<a class="fn-backref" href="#id3">[3]</a>',
|
||||
'<a class="fn-backref" href="#id4">[bar]</a>',
|
||||
]
|
||||
for expect in expects:
|
||||
matches = re.findall(re.escape(expect), result)
|
||||
assert len(matches) == 1
|
||||
@@ -15,12 +15,7 @@ from pygments.formatters.html import HtmlFormatter
|
||||
|
||||
from sphinx.highlighting import PygmentsBridge
|
||||
|
||||
from util import with_app, SkipTest
|
||||
|
||||
try:
|
||||
import pygments
|
||||
except ImportError:
|
||||
raise SkipTest('pygments not available')
|
||||
from util import with_app
|
||||
|
||||
|
||||
class MyLexer(RegexLexer):
|
||||
@@ -46,13 +41,14 @@ class ComplainOnUnhighlighted(PygmentsBridge):
|
||||
|
||||
|
||||
@with_app()
|
||||
def test_add_lexer(app):
|
||||
def test_add_lexer(app, status, warning):
|
||||
app.add_lexer('test', MyLexer())
|
||||
|
||||
bridge = PygmentsBridge('html')
|
||||
ret = bridge.highlight_block('ab', 'test')
|
||||
assert '<span class="n">a</span>b' in ret
|
||||
|
||||
|
||||
def test_detect_interactive():
|
||||
bridge = ComplainOnUnhighlighted('html')
|
||||
blocks = [
|
||||
@@ -60,11 +56,12 @@ def test_detect_interactive():
|
||||
>>> testing()
|
||||
True
|
||||
""",
|
||||
]
|
||||
]
|
||||
for block in blocks:
|
||||
ret = bridge.highlight_block(block.lstrip(), 'python')
|
||||
assert ret.startswith("<div class=\"highlight\">")
|
||||
|
||||
|
||||
def test_set_formatter():
|
||||
PygmentsBridge.html_formatter = MyFormatter
|
||||
try:
|
||||
@@ -74,6 +71,7 @@ def test_set_formatter():
|
||||
finally:
|
||||
PygmentsBridge.html_formatter = HtmlFormatter
|
||||
|
||||
|
||||
def test_trim_doctest_flags():
|
||||
PygmentsBridge.html_formatter = MyFormatter
|
||||
try:
|
||||
|
||||
+1
-1
@@ -13,5 +13,5 @@ from util import with_app
|
||||
|
||||
|
||||
@with_app(confoverrides={'language': 'de'})
|
||||
def test_i18n(app):
|
||||
def test_i18n(app, status, warning):
|
||||
app.builder.build_all()
|
||||
+368
-434
@@ -16,45 +16,45 @@ import re
|
||||
from subprocess import Popen, PIPE
|
||||
from xml.etree import ElementTree
|
||||
|
||||
from six import StringIO, string_types
|
||||
from nose.tools import assert_equal
|
||||
from six import string_types
|
||||
|
||||
from util import test_roots, path, with_app, SkipTest
|
||||
from util import tempdir, rootdir, path, gen_with_app, SkipTest, \
|
||||
assert_re_search, assert_not_re_search, assert_in, assert_not_in, \
|
||||
assert_startswith
|
||||
|
||||
|
||||
warnfile = StringIO()
|
||||
root = test_roots / 'test-intl'
|
||||
doctreedir = root / '_build' / 'doctree'
|
||||
root = tempdir / 'test-intl'
|
||||
|
||||
|
||||
def with_intl_app(*args, **kw):
|
||||
def gen_with_intl_app(*args, **kw):
|
||||
default_kw = {
|
||||
'srcdir': root,
|
||||
'doctreedir': doctreedir,
|
||||
'testroot': 'intl',
|
||||
'confoverrides': {
|
||||
'language': 'xx', 'locale_dirs': ['.'],
|
||||
'gettext_compact': False,
|
||||
},
|
||||
}
|
||||
default_kw.update(kw)
|
||||
return with_app(*args, **default_kw)
|
||||
return gen_with_app(*args, **default_kw)
|
||||
|
||||
|
||||
def setup_module():
|
||||
if not root.exists():
|
||||
(rootdir / 'roots' / 'test-intl').copytree(root)
|
||||
# Delete remnants left over after failed build
|
||||
(root / 'xx').rmtree(True)
|
||||
(root / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
# Compile all required catalogs into binary format (*.mo).
|
||||
for dirpath, dirs, files in os.walk(root):
|
||||
dirpath = path(dirpath)
|
||||
for f in [f for f in files if f.endswith('.po')]:
|
||||
po = dirpath / f
|
||||
mo = root / 'xx' / 'LC_MESSAGES' / (
|
||||
os.path.relpath(po[:-3], root) + '.mo')
|
||||
os.path.relpath(po[:-3], root) + '.mo')
|
||||
if not mo.parent.exists():
|
||||
mo.parent.makedirs()
|
||||
try:
|
||||
p = Popen(['msgfmt', po, '-o', mo],
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
except OSError:
|
||||
raise SkipTest # most likely msgfmt was not found
|
||||
else:
|
||||
@@ -67,11 +67,6 @@ def setup_module():
|
||||
assert mo.isfile(), 'msgfmt failed'
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(root / '_build').rmtree(True)
|
||||
(root / 'xx').rmtree(True)
|
||||
|
||||
|
||||
def elem_gettexts(elem):
|
||||
def itertext(self):
|
||||
# this function copied from Python-2.7 'ElementTree.itertext'.
|
||||
@@ -105,125 +100,38 @@ def assert_elem(elem, texts=None, refs=None, names=None):
|
||||
assert _names == names
|
||||
|
||||
|
||||
@with_intl_app(buildername='text')
|
||||
def test_simple(app):
|
||||
app.builder.build(['bom'])
|
||||
result = (app.outdir / 'bom.txt').text(encoding='utf-8')
|
||||
expect = (u"\nDatei mit UTF-8"
|
||||
u"\n***************\n" # underline matches new translation
|
||||
u"\nThis file has umlauts: äöü.\n")
|
||||
assert result == expect
|
||||
@gen_with_intl_app('text', freshenv=True)
|
||||
def test_text_builder(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
# --- warnings in translation
|
||||
|
||||
@with_intl_app(buildername='text')
|
||||
def test_subdir(app):
|
||||
app.builder.build(['subdir/contents'])
|
||||
result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8')
|
||||
assert result.startswith(u"\nsubdir contents\n***************\n")
|
||||
warnings = warning.getvalue().replace(os.sep, '/')
|
||||
warning_expr = u'.*/warnings.txt:4: ' \
|
||||
u'WARNING: Inline literal start-string without end-string.\n'
|
||||
yield assert_re_search, warning_expr, warnings
|
||||
|
||||
|
||||
@with_intl_app(buildername='text', warning=warnfile)
|
||||
def test_i18n_warnings_in_translation(app):
|
||||
app.builddir.rmtree(True)
|
||||
app.builder.build(['warnings'])
|
||||
result = (app.outdir / 'warnings.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH REST WARNINGS"
|
||||
u"\n***********************\n"
|
||||
u"\nLINE OF >>``<<BROKEN LITERAL MARKUP.\n")
|
||||
yield assert_equal, result, expect
|
||||
|
||||
assert result == expect
|
||||
# --- simple translation; check title underlines
|
||||
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
warning_expr = u'.*/warnings.txt:4: ' \
|
||||
u'WARNING: Inline literal start-string without end-string.\n'
|
||||
assert re.search(warning_expr, warnings)
|
||||
result = (app.outdir / 'bom.txt').text(encoding='utf-8')
|
||||
expect = (u"\nDatei mit UTF-8"
|
||||
u"\n***************\n" # underline matches new translation
|
||||
u"\nThis file has umlauts: äöü.\n")
|
||||
yield assert_equal, result, expect
|
||||
|
||||
# --- check translation in subdirs
|
||||
|
||||
@with_intl_app(buildername='html', cleanenv=True)
|
||||
def test_i18n_footnote_break_refid(app):
|
||||
"""test for #955 cant-build-html-with-footnotes-when-using"""
|
||||
app.builder.build(['footnote'])
|
||||
result = (app.outdir / 'footnote.html').text(encoding='utf-8')
|
||||
# expect no error by build
|
||||
result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8')
|
||||
yield assert_startswith, result, u"\nsubdir contents\n***************\n"
|
||||
|
||||
# --- check warnings for inconsistency in number of references
|
||||
|
||||
@with_intl_app(buildername='xml', warning=warnfile)
|
||||
def test_i18n_footnote_regression(app):
|
||||
# regression test for fix #955, #1176
|
||||
app.builddir.rmtree(True)
|
||||
app.builder.build(['footnote'])
|
||||
et = ElementTree.parse(app.outdir / 'footnote.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
para0 = secs[0].findall('paragraph')
|
||||
assert_elem(
|
||||
para0[0],
|
||||
texts=['I18N WITH FOOTNOTE', 'INCLUDE THIS CONTENTS',
|
||||
'2', '[ref]', '1', '100', '.'],
|
||||
refs=['i18n-with-footnote', 'ref'])
|
||||
|
||||
footnote0 = secs[0].findall('footnote')
|
||||
assert_elem(
|
||||
footnote0[0],
|
||||
texts=['1','THIS IS A AUTO NUMBERED FOOTNOTE.'],
|
||||
names=['1'])
|
||||
assert_elem(
|
||||
footnote0[1],
|
||||
texts=['100','THIS IS A NUMBERED FOOTNOTE.'],
|
||||
names=['100'])
|
||||
assert_elem(
|
||||
footnote0[2],
|
||||
texts=['2','THIS IS A AUTO NUMBERED NAMED FOOTNOTE.'],
|
||||
names=['named'])
|
||||
|
||||
citation0 = secs[0].findall('citation')
|
||||
assert_elem(
|
||||
citation0[0],
|
||||
texts=['ref','THIS IS A NAMED FOOTNOTE.'],
|
||||
names=['ref'])
|
||||
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
warning_expr = u'.*/footnote.xml:\\d*: SEVERE: Duplicate ID: ".*".\n'
|
||||
assert not re.search(warning_expr, warnings)
|
||||
|
||||
|
||||
@with_intl_app(buildername='xml', cleanenv=True)
|
||||
def test_i18n_footnote_backlink(app):
|
||||
# i18n test for #1058
|
||||
app.builder.build(['footnote'])
|
||||
et = ElementTree.parse(app.outdir / 'footnote.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
para0 = secs[0].findall('paragraph')
|
||||
refs0 = para0[0].findall('footnote_reference')
|
||||
refid2id = dict([
|
||||
(r.attrib.get('refid'), r.attrib.get('ids')) for r in refs0])
|
||||
|
||||
footnote0 = secs[0].findall('footnote')
|
||||
for footnote in footnote0:
|
||||
ids = footnote.attrib.get('ids')
|
||||
backrefs = footnote.attrib.get('backrefs')
|
||||
assert refid2id[ids] == backrefs
|
||||
|
||||
|
||||
@with_intl_app(buildername='xml', warning=warnfile)
|
||||
def test_i18n_refs_python_domain(app):
|
||||
app.builder.build(['refs_python_domain'])
|
||||
et = ElementTree.parse(app.outdir / 'refs_python_domain.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
# regression test for fix #1363
|
||||
para0 = secs[0].findall('paragraph')
|
||||
assert_elem(
|
||||
para0[0],
|
||||
texts=['SEE THIS DECORATOR:', 'sensitive_variables()', '.'],
|
||||
refs=['sensitive.sensitive_variables'])
|
||||
|
||||
|
||||
@with_intl_app(buildername='text', warning=warnfile, cleanenv=True)
|
||||
def test_i18n_warn_for_number_of_references_inconsistency(app):
|
||||
app.builddir.rmtree(True)
|
||||
app.builder.build(['refs_inconsistency'])
|
||||
result = (app.outdir / 'refs_inconsistency.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH REFS INCONSISTENCY"
|
||||
u"\n****************************\n"
|
||||
@@ -233,98 +141,19 @@ def test_i18n_warn_for_number_of_references_inconsistency(app):
|
||||
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
|
||||
yield assert_equal, result, expect
|
||||
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
warnings = warning.getvalue().replace(os.sep, '/')
|
||||
warning_fmt = u'.*/refs_inconsistency.txt:\\d+: ' \
|
||||
u'WARNING: inconsistent %s in translated message\n'
|
||||
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)
|
||||
yield assert_re_search, expected_warning_expr, warnings
|
||||
|
||||
# --- check warning for literal block
|
||||
|
||||
@with_intl_app(buildername='html', cleanenv=True)
|
||||
def test_i18n_link_to_undefined_reference(app):
|
||||
app.builder.build(['refs_inconsistency'])
|
||||
result = (app.outdir / '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_intl_app(buildername='xml', cleanenv=True)
|
||||
def test_i18n_keep_external_links(app):
|
||||
# regression test for #1044
|
||||
app.builder.build(['external_links'])
|
||||
et = ElementTree.parse(app.outdir / 'external_links.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
para0 = secs[0].findall('paragraph')
|
||||
# external link check
|
||||
assert_elem(
|
||||
para0[0],
|
||||
texts=['EXTERNAL LINK TO', 'Python', '.'],
|
||||
refs=['http://python.org/index.html'])
|
||||
|
||||
# internal link check
|
||||
assert_elem(
|
||||
para0[1],
|
||||
texts=['EXTERNAL LINKS', 'IS INTERNAL LINK.'],
|
||||
refs=['i18n-with-external-links'])
|
||||
|
||||
# inline link check
|
||||
assert_elem(
|
||||
para0[2],
|
||||
texts=['INLINE LINK BY', 'THE SPHINX SITE', '.'],
|
||||
refs=['http://sphinx-doc.org'])
|
||||
|
||||
# unnamed link check
|
||||
assert_elem(
|
||||
para0[3],
|
||||
texts=['UNNAMED', 'LINK', '.'],
|
||||
refs=['http://google.com'])
|
||||
|
||||
# link target swapped translation
|
||||
para1 = secs[1].findall('paragraph')
|
||||
assert_elem(
|
||||
para1[0],
|
||||
texts=['LINK TO', 'external2', 'AND', 'external1', '.'],
|
||||
refs=['http://example.com/external2',
|
||||
'http://example.com/external1'])
|
||||
assert_elem(
|
||||
para1[1],
|
||||
texts=['LINK TO', 'THE PYTHON SITE', 'AND', 'THE SPHINX SITE',
|
||||
'.'],
|
||||
refs=['http://python.org', 'http://sphinx-doc.org'])
|
||||
|
||||
# multiple references in the same line
|
||||
para2 = secs[2].findall('paragraph')
|
||||
assert_elem(
|
||||
para2[0],
|
||||
texts=['LINK TO', 'EXTERNAL LINKS', ',', 'Python', ',',
|
||||
'THE SPHINX SITE', ',', 'UNNAMED', 'AND',
|
||||
'THE PYTHON SITE', '.'],
|
||||
refs=['i18n-with-external-links', 'http://python.org/index.html',
|
||||
'http://sphinx-doc.org', 'http://google.com',
|
||||
'http://python.org'])
|
||||
|
||||
|
||||
@with_intl_app(buildername='text', warning=warnfile, cleanenv=True)
|
||||
def test_i18n_literalblock_warning(app):
|
||||
app.builddir.rmtree(True) #for warnings acceleration
|
||||
app.builder.build(['literalblock'])
|
||||
result = (app.outdir / 'literalblock.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH LITERAL BLOCK"
|
||||
u"\n***********************\n"
|
||||
@@ -333,18 +162,15 @@ def test_i18n_literalblock_warning(app):
|
||||
u"\n literal block\n"
|
||||
u"\nMISSING LITERAL BLOCK:\n"
|
||||
u"\n<SYSTEM MESSAGE:")
|
||||
assert result.startswith(expect)
|
||||
yield assert_startswith, result, expect
|
||||
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
warnings = warning.getvalue().replace(os.sep, '/')
|
||||
expected_warning_expr = u'.*/literalblock.txt:\\d+: ' \
|
||||
u'WARNING: Literal block expected; none found.'
|
||||
assert re.search(expected_warning_expr, warnings)
|
||||
u'WARNING: Literal block expected; none found.'
|
||||
yield assert_re_search, expected_warning_expr, warnings
|
||||
|
||||
# --- definition terms: regression test for #975
|
||||
|
||||
@with_intl_app(buildername='text')
|
||||
def test_i18n_definition_terms(app):
|
||||
# regression test for #975
|
||||
app.builder.build(['definition_terms'])
|
||||
result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH DEFINITION TERMS"
|
||||
u"\n**************************\n"
|
||||
@@ -352,15 +178,10 @@ def test_i18n_definition_terms(app):
|
||||
u"\n THE CORRESPONDING DEFINITION\n"
|
||||
u"\nSOME OTHER TERM"
|
||||
u"\n THE CORRESPONDING DEFINITION #2\n")
|
||||
yield assert_equal, result, expect
|
||||
|
||||
assert result == expect
|
||||
# --- glossary terms: regression test for #1090
|
||||
|
||||
|
||||
@with_intl_app(buildername='text', warning=warnfile)
|
||||
def test_i18n_glossary_terms(app):
|
||||
# regression test for #1090
|
||||
app.builddir.rmtree(True) #for warnings acceleration
|
||||
app.builder.build(['glossary_terms'])
|
||||
result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH GLOSSARY TERMS"
|
||||
u"\n************************\n"
|
||||
@@ -369,146 +190,26 @@ def test_i18n_glossary_terms(app):
|
||||
u"\nSOME OTHER NEW TERM"
|
||||
u"\n THE CORRESPONDING GLOSSARY #2\n"
|
||||
u"\nLINK TO *SOME NEW TERM*.\n")
|
||||
assert result == expect
|
||||
yield assert_equal, result, expect
|
||||
warnings = warning.getvalue().replace(os.sep, '/')
|
||||
yield assert_not_in, 'term not in glossary', warnings
|
||||
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
assert 'term not in glossary' not in warnings
|
||||
# --- glossary term inconsistencies: regression test for #1090
|
||||
|
||||
|
||||
@with_intl_app(buildername='xml', warning=warnfile)
|
||||
def test_i18n_role_xref(app):
|
||||
# regression test for #1090, #1193
|
||||
app.builddir.rmtree(True) #for warnings acceleration
|
||||
app.builder.build(['role_xref'])
|
||||
et = ElementTree.parse(app.outdir / 'role_xref.xml')
|
||||
sec1, sec2 = et.findall('section')
|
||||
|
||||
para1, = sec1.findall('paragraph')
|
||||
assert_elem(
|
||||
para1,
|
||||
texts=['LINK TO', "I18N ROCK'N ROLE XREF", ',', 'CONTENTS', ',',
|
||||
'SOME NEW TERM', '.'],
|
||||
refs=['i18n-role-xref', 'contents',
|
||||
'glossary_terms#term-some-term'])
|
||||
|
||||
para2 = sec2.findall('paragraph')
|
||||
assert_elem(
|
||||
para2[0],
|
||||
texts=['LINK TO', 'SOME OTHER NEW TERM', 'AND', 'SOME NEW TERM',
|
||||
'.'],
|
||||
refs=['glossary_terms#term-some-other-term',
|
||||
'glossary_terms#term-some-term'])
|
||||
assert_elem(
|
||||
para2[1],
|
||||
texts=['LINK TO', 'SAME TYPE LINKS', 'AND',
|
||||
"I18N ROCK'N ROLE XREF", '.'],
|
||||
refs=['same-type-links', 'i18n-role-xref'])
|
||||
assert_elem(
|
||||
para2[2],
|
||||
texts=['LINK TO', 'I18N WITH GLOSSARY TERMS', 'AND', 'CONTENTS',
|
||||
'.'],
|
||||
refs=['glossary_terms', 'contents'])
|
||||
assert_elem(
|
||||
para2[3],
|
||||
texts=['LINK TO', '--module', 'AND', '-m', '.'],
|
||||
refs=['cmdoption--module', 'cmdoption-m'])
|
||||
assert_elem(
|
||||
para2[4],
|
||||
texts=['LINK TO', 'env2', 'AND', 'env1', '.'],
|
||||
refs=['envvar-env2', 'envvar-env1'])
|
||||
assert_elem(
|
||||
para2[5],
|
||||
texts=['LINK TO', 'token2', 'AND', 'token1', '.'],
|
||||
refs=[]) #TODO: how do I link token role to productionlist?
|
||||
assert_elem(
|
||||
para2[6],
|
||||
texts=['LINK TO', 'same-type-links', 'AND', "i18n-role-xref", '.'],
|
||||
refs=['same-type-links', 'i18n-role-xref'])
|
||||
|
||||
#warnings
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
assert 'term not in glossary' not in warnings
|
||||
assert 'undefined label' not in warnings
|
||||
assert 'unknown document' not in warnings
|
||||
|
||||
|
||||
@with_intl_app(buildername='xml', warning=warnfile)
|
||||
def test_i18n_label_target(app):
|
||||
# regression test for #1193, #1265
|
||||
app.builder.build(['label_target'])
|
||||
et = ElementTree.parse(app.outdir / 'label_target.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
para0 = secs[0].findall('paragraph')
|
||||
assert_elem(
|
||||
para0[0],
|
||||
texts=['X SECTION AND LABEL', 'POINT TO', 'implicit-target', 'AND',
|
||||
'X SECTION AND LABEL', 'POINT TO', 'section-and-label', '.'],
|
||||
refs=['implicit-target', 'section-and-label'])
|
||||
|
||||
para1 = secs[1].findall('paragraph')
|
||||
assert_elem(
|
||||
para1[0],
|
||||
texts=['X EXPLICIT-TARGET', 'POINT TO', 'explicit-target', 'AND',
|
||||
'X EXPLICIT-TARGET', 'POINT TO DUPLICATED ID LIKE', 'id1',
|
||||
'.'],
|
||||
refs=['explicit-target', 'id1'])
|
||||
|
||||
para2 = secs[2].findall('paragraph')
|
||||
assert_elem(
|
||||
para2[0],
|
||||
texts=['X IMPLICIT SECTION NAME', 'POINT TO',
|
||||
'implicit-section-name', '.'],
|
||||
refs=['implicit-section-name'])
|
||||
|
||||
sec2 = secs[2].findall('section')
|
||||
|
||||
para2_0 = sec2[0].findall('paragraph')
|
||||
assert_elem(
|
||||
para2_0[0],
|
||||
texts=['`X DUPLICATED SUB SECTION`_', 'IS BROKEN LINK.'],
|
||||
refs=[])
|
||||
|
||||
para3 = secs[3].findall('paragraph')
|
||||
assert_elem(
|
||||
para3[0],
|
||||
texts=['X', 'bridge label',
|
||||
'IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED ' +
|
||||
'SECTION TITLE.'],
|
||||
refs=['label-bridged-target-section'])
|
||||
assert_elem(
|
||||
para3[1],
|
||||
texts=['X', 'bridge label', 'POINT TO',
|
||||
'LABEL BRIDGED TARGET SECTION', 'AND', 'bridge label2',
|
||||
'POINT TO', 'SECTION AND LABEL', '. THE SECOND APPEARED',
|
||||
'bridge label2', 'POINT TO CORRECT TARGET.'],
|
||||
refs=['label-bridged-target-section',
|
||||
'section-and-label',
|
||||
'section-and-label'])
|
||||
|
||||
|
||||
@with_intl_app(buildername='text', warning=warnfile)
|
||||
def test_i18n_glossary_terms_inconsistency(app):
|
||||
# regression test for #1090
|
||||
app.builddir.rmtree(True) #for warnings acceleration
|
||||
app.builder.build(['glossary_terms_inconsistency'])
|
||||
result = (app.outdir / 'glossary_terms_inconsistency.txt'
|
||||
).text(encoding='utf-8')
|
||||
result = (app.outdir / 'glossary_terms_inconsistency.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH GLOSSARY TERMS INCONSISTENCY"
|
||||
u"\n**************************************\n"
|
||||
u"\n1. LINK TO *SOME NEW TERM*.\n")
|
||||
assert result == expect
|
||||
yield assert_equal, result, expect
|
||||
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
warnings = warning.getvalue().replace(os.sep, '/')
|
||||
expected_warning_expr = (
|
||||
u'.*/glossary_terms_inconsistency.txt:\\d+: '
|
||||
u'WARNING: inconsistent term references in translated message\n')
|
||||
assert re.search(expected_warning_expr, warnings)
|
||||
u'.*/glossary_terms_inconsistency.txt:\\d+: '
|
||||
u'WARNING: inconsistent term references in translated message\n')
|
||||
yield assert_re_search, expected_warning_expr, warnings
|
||||
|
||||
# --- seealso
|
||||
|
||||
@with_intl_app(buildername='text')
|
||||
def test_seealso(app):
|
||||
app.builder.build(['seealso'])
|
||||
result = (app.outdir / 'seealso.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH SEEALSO"
|
||||
u"\n*****************\n"
|
||||
@@ -516,13 +217,10 @@ def test_seealso(app):
|
||||
u"\nSee also: LONG TEXT 1\n"
|
||||
u"\nSee also: SHORT TEXT 2\n"
|
||||
u"\n LONG TEXT 2\n")
|
||||
assert result == expect
|
||||
yield assert_equal, result, expect
|
||||
|
||||
# --- figure captions: regression test for #940
|
||||
|
||||
@with_intl_app(buildername='text')
|
||||
def test_i18n_figure_caption(app):
|
||||
# regression test for #940
|
||||
app.builder.build(['figure_caption'])
|
||||
result = (app.outdir / 'figure_caption.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH FIGURE CAPTION"
|
||||
u"\n************************\n"
|
||||
@@ -536,14 +234,10 @@ def test_i18n_figure_caption(app):
|
||||
u"\n [image]MY CAPTION OF THE FIGURE\n"
|
||||
u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
|
||||
u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n")
|
||||
yield assert_equal, result, expect
|
||||
|
||||
assert result == expect
|
||||
# --- rubric: regression test for pull request #190
|
||||
|
||||
|
||||
@with_intl_app(buildername='text')
|
||||
def test_i18n_rubric(app):
|
||||
# regression test for pull request #190
|
||||
app.builder.build(['rubric'])
|
||||
result = (app.outdir / 'rubric.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH RUBRIC"
|
||||
u"\n****************\n"
|
||||
@@ -553,14 +247,73 @@ def test_i18n_rubric(app):
|
||||
u"\n===================\n"
|
||||
u"\nBLOCK\n"
|
||||
u"\n -[ RUBRIC TITLE ]-\n")
|
||||
yield assert_equal, result, expect
|
||||
|
||||
assert result == expect
|
||||
# --- docfields
|
||||
|
||||
result = (app.outdir / 'docfields.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH DOCFIELDS"
|
||||
u"\n*******************\n"
|
||||
u"\nclass class Cls1\n"
|
||||
u"\n Parameters:"
|
||||
u"\n **param** -- DESCRIPTION OF PARAMETER param\n"
|
||||
u"\nclass class Cls2\n"
|
||||
u"\n Parameters:"
|
||||
u"\n * **foo** -- DESCRIPTION OF PARAMETER foo\n"
|
||||
u"\n * **bar** -- DESCRIPTION OF PARAMETER bar\n"
|
||||
u"\nclass class Cls3(values)\n"
|
||||
u"\n Raises ValueError:"
|
||||
u"\n IF THE VALUES ARE OUT OF RANGE\n"
|
||||
u"\nclass class Cls4(values)\n"
|
||||
u"\n Raises:"
|
||||
u"\n * **TypeError** -- IF THE VALUES ARE NOT VALID\n"
|
||||
u"\n * **ValueError** -- IF THE VALUES ARE OUT OF RANGE\n"
|
||||
u"\nclass class Cls5\n"
|
||||
u"\n Returns:"
|
||||
u'\n A NEW "Cls3" INSTANCE\n')
|
||||
yield assert_equal, result, expect
|
||||
|
||||
# --- admonitions
|
||||
# #1206: gettext did not translate admonition directive's title
|
||||
# seealso: http://docutils.sourceforge.net/docs/ref/rst/directives.html#admonitions
|
||||
|
||||
result = (app.outdir / 'admonitions.txt').text(encoding='utf-8')
|
||||
directives = (
|
||||
"attention", "caution", "danger", "error", "hint",
|
||||
"important", "note", "tip", "warning", "admonition")
|
||||
for d in directives:
|
||||
yield assert_in, d.upper() + " TITLE", result
|
||||
yield assert_in, d.upper() + " BODY", result
|
||||
|
||||
|
||||
@with_intl_app(buildername='html')
|
||||
def test_i18n_index_entries(app):
|
||||
# regression test for #976
|
||||
app.builder.build(['index_entries'])
|
||||
@gen_with_intl_app('html', freshenv=True)
|
||||
def test_html_builder(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
# --- test for #955 cant-build-html-with-footnotes-when-using
|
||||
|
||||
# expect no error by build
|
||||
(app.outdir / 'footnote.html').text(encoding='utf-8')
|
||||
|
||||
# --- links to undefined reference
|
||||
|
||||
result = (app.outdir / 'refs_inconsistency.html').text(encoding='utf-8')
|
||||
|
||||
expected_expr = ('<a class="reference external" '
|
||||
'href="http://www.example.com">reference</a>')
|
||||
yield assert_equal, len(re.findall(expected_expr, result)), 2
|
||||
|
||||
expected_expr = ('<a class="reference internal" '
|
||||
'href="#reference">reference</a>')
|
||||
yield assert_equal, len(re.findall(expected_expr, result)), 0
|
||||
|
||||
expected_expr = ('<a class="reference internal" '
|
||||
'href="#i18n-with-refs-inconsistency">I18N WITH '
|
||||
'REFS INCONSISTENCY</a>')
|
||||
yield assert_equal, len(re.findall(expected_expr, result)), 1
|
||||
|
||||
# --- index entries: regression test for #976
|
||||
|
||||
result = (app.outdir / 'genindex.html').text(encoding='utf-8')
|
||||
|
||||
def wrap(tag, keyword):
|
||||
@@ -586,12 +339,10 @@ def test_i18n_index_entries(app):
|
||||
wrap('a', 'BUILTIN'),
|
||||
]
|
||||
for expr in expected_exprs:
|
||||
assert re.search(expr, result, re.M)
|
||||
yield assert_re_search, expr, result, re.M
|
||||
|
||||
# --- versionchanges
|
||||
|
||||
@with_intl_app(buildername='html', cleanenv=True)
|
||||
def test_versionchange(app):
|
||||
app.builder.build(['versionchange'])
|
||||
result = (app.outdir / 'versionchange.html').text(encoding='utf-8')
|
||||
|
||||
def get_content(result, name):
|
||||
@@ -607,83 +358,266 @@ def test_versionchange(app):
|
||||
u"""THIS IS THE <em>FIRST</em> PARAGRAPH OF DEPRECATED.</p>\n"""
|
||||
u"""<p>THIS IS THE <em>SECOND</em> PARAGRAPH OF DEPRECATED.</p>\n""")
|
||||
matched_content = get_content(result, "deprecated")
|
||||
assert expect1 == matched_content
|
||||
yield assert_equal, expect1, matched_content
|
||||
|
||||
expect2 = (
|
||||
u"""<p><span class="versionmodified">New in version 1.0: </span>"""
|
||||
u"""THIS IS THE <em>FIRST</em> PARAGRAPH OF VERSIONADDED.</p>\n""")
|
||||
matched_content = get_content(result, "versionadded")
|
||||
assert expect2 == matched_content
|
||||
yield assert_equal, expect2, matched_content
|
||||
|
||||
expect3 = (
|
||||
u"""<p><span class="versionmodified">Changed in version 1.0: </span>"""
|
||||
u"""THIS IS THE <em>FIRST</em> PARAGRAPH OF VERSIONCHANGED.</p>\n""")
|
||||
matched_content = get_content(result, "versionchanged")
|
||||
assert expect3 == matched_content
|
||||
yield assert_equal, expect3, matched_content
|
||||
|
||||
# --- docfields
|
||||
|
||||
@with_intl_app(buildername='text', cleanenv=True)
|
||||
def test_i18n_docfields(app):
|
||||
app.builder.build(['docfields'])
|
||||
result = (app.outdir / 'docfields.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH DOCFIELDS"
|
||||
u"\n*******************\n"
|
||||
u"\nclass class Cls1\n"
|
||||
u"\n Parameters:"
|
||||
u"\n **param** -- DESCRIPTION OF PARAMETER param\n"
|
||||
u"\nclass class Cls2\n"
|
||||
u"\n Parameters:"
|
||||
u"\n * **foo** -- DESCRIPTION OF PARAMETER foo\n"
|
||||
u"\n * **bar** -- DESCRIPTION OF PARAMETER bar\n"
|
||||
u"\nclass class Cls3(values)\n"
|
||||
u"\n Raises ValueError:"
|
||||
u"\n IF THE VALUES ARE OUT OF RANGE\n"
|
||||
u"\nclass class Cls4(values)\n"
|
||||
u"\n Raises:"
|
||||
u"\n * **TypeError** -- IF THE VALUES ARE NOT VALID\n"
|
||||
u"\n * **ValueError** -- IF THE VALUES ARE OUT OF RANGE\n"
|
||||
u"\nclass class Cls5\n"
|
||||
u"\n Returns:"
|
||||
u'\n A NEW "Cls3" INSTANCE\n')
|
||||
assert result == expect
|
||||
|
||||
|
||||
@with_intl_app(buildername='text', cleanenv=True)
|
||||
def test_i18n_admonitions(app):
|
||||
# #1206: gettext did not translate admonition directive's title
|
||||
# seealso: http://docutils.sourceforge.net/docs/ref/rst/directives.html#admonitions
|
||||
app.builder.build(['admonitions'])
|
||||
result = (app.outdir / 'admonitions.txt').text(encoding='utf-8')
|
||||
directives = (
|
||||
"attention", "caution", "danger", "error", "hint",
|
||||
"important", "note", "tip", "warning", "admonition",)
|
||||
for d in directives:
|
||||
assert d.upper() + " TITLE" in result
|
||||
assert d.upper() + " BODY" in result
|
||||
|
||||
|
||||
@with_intl_app(buildername='html', cleanenv=True)
|
||||
def test_i18n_docfields_html(app):
|
||||
app.builder.build(['docfields'])
|
||||
result = (app.outdir / 'docfields.html').text(encoding='utf-8')
|
||||
# expect no error by build
|
||||
(app.outdir / 'docfields.html').text(encoding='utf-8')
|
||||
|
||||
# --- gettext template
|
||||
|
||||
@with_intl_app(buildername='html')
|
||||
def test_gettext_template(app):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'index.html').text(encoding='utf-8')
|
||||
assert "WELCOME" in result
|
||||
assert "SPHINX 2013.120" in result
|
||||
yield assert_in, "WELCOME", result
|
||||
yield assert_in, "SPHINX 2013.120", result
|
||||
|
||||
# --- rebuild by .mo mtime
|
||||
|
||||
@with_intl_app(buildername='html')
|
||||
def test_rebuild_by_mo_mtime(app):
|
||||
app.builder.build_update()
|
||||
_, count, _ = app.env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
assert count == 0
|
||||
updated = app.env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
yield assert_equal, len(updated), 0
|
||||
|
||||
mo = (app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').bytes()
|
||||
(app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').write_bytes(mo)
|
||||
_, count, _ = app.env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
assert count == 1
|
||||
(app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').utime(None)
|
||||
updated = app.env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
yield assert_equal, len(updated), 1
|
||||
|
||||
|
||||
@gen_with_intl_app('xml', freshenv=True)
|
||||
def test_xml_builder(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
# --- footnotes: regression test for fix #955, #1176
|
||||
|
||||
et = ElementTree.parse(app.outdir / 'footnote.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
para0 = secs[0].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para0[0],
|
||||
['I18N WITH FOOTNOTE', 'INCLUDE THIS CONTENTS',
|
||||
'2', '[ref]', '1', '100', '.'],
|
||||
['i18n-with-footnote', 'ref'])
|
||||
|
||||
footnote0 = secs[0].findall('footnote')
|
||||
yield (assert_elem,
|
||||
footnote0[0],
|
||||
['1', 'THIS IS A AUTO NUMBERED FOOTNOTE.'],
|
||||
None,
|
||||
['1'])
|
||||
yield (assert_elem,
|
||||
footnote0[1],
|
||||
['100', 'THIS IS A NUMBERED FOOTNOTE.'],
|
||||
None,
|
||||
['100'])
|
||||
yield (assert_elem,
|
||||
footnote0[2],
|
||||
['2', 'THIS IS A AUTO NUMBERED NAMED FOOTNOTE.'],
|
||||
None,
|
||||
['named'])
|
||||
|
||||
citation0 = secs[0].findall('citation')
|
||||
yield (assert_elem,
|
||||
citation0[0],
|
||||
['ref', 'THIS IS A NAMED FOOTNOTE.'],
|
||||
None,
|
||||
['ref'])
|
||||
|
||||
warnings = warning.getvalue().replace(os.sep, '/')
|
||||
warning_expr = u'.*/footnote.xml:\\d*: SEVERE: Duplicate ID: ".*".\n'
|
||||
yield assert_not_re_search, warning_expr, warnings
|
||||
|
||||
# --- footnote backlinks: i18n test for #1058
|
||||
|
||||
et = ElementTree.parse(app.outdir / 'footnote.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
para0 = secs[0].findall('paragraph')
|
||||
refs0 = para0[0].findall('footnote_reference')
|
||||
refid2id = dict([
|
||||
(r.attrib.get('refid'), r.attrib.get('ids')) for r in refs0])
|
||||
|
||||
footnote0 = secs[0].findall('footnote')
|
||||
for footnote in footnote0:
|
||||
ids = footnote.attrib.get('ids')
|
||||
backrefs = footnote.attrib.get('backrefs')
|
||||
yield assert_equal, refid2id[ids], backrefs
|
||||
|
||||
# --- refs in the Python domain
|
||||
|
||||
et = ElementTree.parse(app.outdir / 'refs_python_domain.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
# regression test for fix #1363
|
||||
para0 = secs[0].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para0[0],
|
||||
['SEE THIS DECORATOR:', 'sensitive_variables()', '.'],
|
||||
['sensitive.sensitive_variables'])
|
||||
|
||||
# --- keep external links: regression test for #1044
|
||||
|
||||
et = ElementTree.parse(app.outdir / 'external_links.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
para0 = secs[0].findall('paragraph')
|
||||
# external link check
|
||||
yield (assert_elem,
|
||||
para0[0],
|
||||
['EXTERNAL LINK TO', 'Python', '.'],
|
||||
['http://python.org/index.html'])
|
||||
|
||||
# internal link check
|
||||
yield (assert_elem,
|
||||
para0[1],
|
||||
['EXTERNAL LINKS', 'IS INTERNAL LINK.'],
|
||||
['i18n-with-external-links'])
|
||||
|
||||
# inline link check
|
||||
yield (assert_elem,
|
||||
para0[2],
|
||||
['INLINE LINK BY', 'THE SPHINX SITE', '.'],
|
||||
['http://sphinx-doc.org'])
|
||||
|
||||
# unnamed link check
|
||||
yield (assert_elem,
|
||||
para0[3],
|
||||
['UNNAMED', 'LINK', '.'],
|
||||
['http://google.com'])
|
||||
|
||||
# link target swapped translation
|
||||
para1 = secs[1].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para1[0],
|
||||
['LINK TO', 'external2', 'AND', 'external1', '.'],
|
||||
['http://example.com/external2',
|
||||
'http://example.com/external1'])
|
||||
yield (assert_elem,
|
||||
para1[1],
|
||||
['LINK TO', 'THE PYTHON SITE', 'AND', 'THE SPHINX SITE', '.'],
|
||||
['http://python.org', 'http://sphinx-doc.org'])
|
||||
|
||||
# multiple references in the same line
|
||||
para2 = secs[2].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para2[0],
|
||||
['LINK TO', 'EXTERNAL LINKS', ',', 'Python', ',',
|
||||
'THE SPHINX SITE', ',', 'UNNAMED', 'AND',
|
||||
'THE PYTHON SITE', '.'],
|
||||
['i18n-with-external-links', 'http://python.org/index.html',
|
||||
'http://sphinx-doc.org', 'http://google.com',
|
||||
'http://python.org'])
|
||||
|
||||
# --- role xref: regression test for #1090, #1193
|
||||
|
||||
et = ElementTree.parse(app.outdir / 'role_xref.xml')
|
||||
sec1, sec2 = et.findall('section')
|
||||
|
||||
para1, = sec1.findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para1,
|
||||
['LINK TO', "I18N ROCK'N ROLE XREF", ',', 'CONTENTS', ',',
|
||||
'SOME NEW TERM', '.'],
|
||||
['i18n-role-xref', 'contents',
|
||||
'glossary_terms#term-some-term'])
|
||||
|
||||
para2 = sec2.findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para2[0],
|
||||
['LINK TO', 'SOME OTHER NEW TERM', 'AND', 'SOME NEW TERM', '.'],
|
||||
['glossary_terms#term-some-other-term',
|
||||
'glossary_terms#term-some-term'])
|
||||
yield(assert_elem,
|
||||
para2[1],
|
||||
['LINK TO', 'SAME TYPE LINKS', 'AND',
|
||||
"I18N ROCK'N ROLE XREF", '.'],
|
||||
['same-type-links', 'i18n-role-xref'])
|
||||
yield (assert_elem,
|
||||
para2[2],
|
||||
['LINK TO', 'I18N WITH GLOSSARY TERMS', 'AND', 'CONTENTS', '.'],
|
||||
['glossary_terms', 'contents'])
|
||||
yield (assert_elem,
|
||||
para2[3],
|
||||
['LINK TO', '--module', 'AND', '-m', '.'],
|
||||
['cmdoption--module', 'cmdoption-m'])
|
||||
yield (assert_elem,
|
||||
para2[4],
|
||||
['LINK TO', 'env2', 'AND', 'env1', '.'],
|
||||
['envvar-env2', 'envvar-env1'])
|
||||
yield (assert_elem,
|
||||
para2[5],
|
||||
['LINK TO', 'token2', 'AND', 'token1', '.'],
|
||||
[]) # TODO: how do I link token role to productionlist?
|
||||
yield (assert_elem,
|
||||
para2[6],
|
||||
['LINK TO', 'same-type-links', 'AND', "i18n-role-xref", '.'],
|
||||
['same-type-links', 'i18n-role-xref'])
|
||||
|
||||
# warnings
|
||||
warnings = warning.getvalue().replace(os.sep, '/')
|
||||
yield assert_not_in, 'term not in glossary', warnings
|
||||
yield assert_not_in, 'undefined label', warnings
|
||||
yield assert_not_in, 'unknown document', warnings
|
||||
|
||||
# --- label targets: regression test for #1193, #1265
|
||||
|
||||
et = ElementTree.parse(app.outdir / 'label_target.xml')
|
||||
secs = et.findall('section')
|
||||
|
||||
para0 = secs[0].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para0[0],
|
||||
['X SECTION AND LABEL', 'POINT TO', 'implicit-target', 'AND',
|
||||
'X SECTION AND LABEL', 'POINT TO', 'section-and-label', '.'],
|
||||
['implicit-target', 'section-and-label'])
|
||||
|
||||
para1 = secs[1].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para1[0],
|
||||
['X EXPLICIT-TARGET', 'POINT TO', 'explicit-target', 'AND',
|
||||
'X EXPLICIT-TARGET', 'POINT TO DUPLICATED ID LIKE', 'id1',
|
||||
'.'],
|
||||
['explicit-target', 'id1'])
|
||||
|
||||
para2 = secs[2].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para2[0],
|
||||
['X IMPLICIT SECTION NAME', 'POINT TO',
|
||||
'implicit-section-name', '.'],
|
||||
['implicit-section-name'])
|
||||
|
||||
sec2 = secs[2].findall('section')
|
||||
|
||||
para2_0 = sec2[0].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para2_0[0],
|
||||
['`X DUPLICATED SUB SECTION`_', 'IS BROKEN LINK.'],
|
||||
[])
|
||||
|
||||
para3 = secs[3].findall('paragraph')
|
||||
yield (assert_elem,
|
||||
para3[0],
|
||||
['X', 'bridge label',
|
||||
'IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED ' +
|
||||
'SECTION TITLE.'],
|
||||
['label-bridged-target-section'])
|
||||
yield (assert_elem,
|
||||
para3[1],
|
||||
['X', 'bridge label', 'POINT TO',
|
||||
'LABEL BRIDGED TARGET SECTION', 'AND', 'bridge label2',
|
||||
'POINT TO', 'SECTION AND LABEL', '. THE SECOND APPEARED',
|
||||
'bridge label2', 'POINT TO CORRECT TARGET.'],
|
||||
['label-bridged-target-section',
|
||||
'section-and-label',
|
||||
'section-and-label'])
|
||||
@@ -1,25 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_linkcode
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Test the sphinx.ext.linkcode extension.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
from util import with_app
|
||||
|
||||
|
||||
@with_app(buildername='html', tags=['test_linkcode'], _copy_to_temp=True)
|
||||
def test_html(app):
|
||||
app.builder.build_all()
|
||||
|
||||
stuff = (app.outdir / 'objects.html').text(encoding='utf-8')
|
||||
|
||||
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
|
||||
@@ -23,10 +23,11 @@ from util import TestApp
|
||||
|
||||
app = settings = parser = None
|
||||
|
||||
|
||||
def setup_module():
|
||||
global app, settings, parser
|
||||
texescape.init() # otherwise done by the latex builder
|
||||
app = TestApp(cleanenv=True)
|
||||
app = TestApp()
|
||||
optparser = frontend.OptionParser(
|
||||
components=(rst.Parser, HTMLWriter, LaTeXWriter))
|
||||
settings = optparser.get_default_values()
|
||||
@@ -35,6 +36,7 @@ def setup_module():
|
||||
settings.env.temp_data['docname'] = 'dummy'
|
||||
parser = rst.Parser()
|
||||
|
||||
|
||||
def teardown_module():
|
||||
app.cleanup()
|
||||
|
||||
@@ -42,12 +44,15 @@ def teardown_module():
|
||||
class ForgivingTranslator:
|
||||
def visit_pending_xref(self, node):
|
||||
pass
|
||||
|
||||
def depart_pending_xref(self, node):
|
||||
pass
|
||||
|
||||
|
||||
class ForgivingHTMLTranslator(SmartyPantsHTMLTranslator, ForgivingTranslator):
|
||||
pass
|
||||
|
||||
|
||||
class ForgivingLaTeXTranslator(LaTeXTranslator, ForgivingTranslator):
|
||||
pass
|
||||
|
||||
@@ -108,8 +113,9 @@ def test_inline():
|
||||
|
||||
# non-interpolation of dashes in option role
|
||||
yield (verify_re, ':option:`--with-option`',
|
||||
'<p><em( class="xref std std-option")?>--with-option</em></p>$',
|
||||
r'\\emph{\\texttt{-{-}with-option}}$')
|
||||
'<p><code( class="xref std std-option docutils literal")?>'
|
||||
'<span class="pre">--with-option</span></code></p>$',
|
||||
r'\\code{-{-}with-option}$')
|
||||
|
||||
# verify smarty-pants quotes
|
||||
yield verify, '"John"', '<p>“John”</p>', "``John''"
|
||||
|
||||
+5
-17
@@ -12,27 +12,13 @@
|
||||
# adapted from an example of bibliographic metadata at
|
||||
# http://docutils.sourceforge.net/docs/user/rst/demo.txt
|
||||
|
||||
from util import TestApp
|
||||
from util import with_app
|
||||
|
||||
from nose.tools import assert_equal
|
||||
|
||||
|
||||
app = env = None
|
||||
warnings = []
|
||||
|
||||
def setup_module():
|
||||
# Is there a better way of generating this doctree than manually iterating?
|
||||
global app, env
|
||||
app = TestApp(_copy_to_temp=True)
|
||||
env = app.env
|
||||
msg, num, it = env.update(app.config, app.srcdir, app.doctreedir, app)
|
||||
for docname in it:
|
||||
pass
|
||||
|
||||
def teardown_module():
|
||||
app.cleanup()
|
||||
|
||||
def test_docinfo():
|
||||
@with_app('pseudoxml')
|
||||
def test_docinfo(app, status, warning):
|
||||
"""
|
||||
Inspect the 'docinfo' metadata stored in the first node of the document.
|
||||
Note this doesn't give us access to data stored in subsequence blocks
|
||||
@@ -40,6 +26,8 @@ def test_docinfo():
|
||||
'dedication' blocks, or the 'meta' role. Doing otherwise is probably more
|
||||
messing with the internals of sphinx than this rare use case merits.
|
||||
"""
|
||||
app.builder.build(['metadata'])
|
||||
env = app.env
|
||||
exampledocinfo = env.metadata['metadata']
|
||||
expecteddocinfo = {
|
||||
'author': u'David Goodger',
|
||||
|
||||
+15
-11
@@ -29,8 +29,10 @@ warnfile = StringIO()
|
||||
def setup_module():
|
||||
nocolor()
|
||||
|
||||
|
||||
def mock_input(answers, needanswer=False):
|
||||
called = set()
|
||||
|
||||
def input_(prompt):
|
||||
if prompt in called:
|
||||
raise AssertionError('answer for %r missing and no default '
|
||||
@@ -50,8 +52,10 @@ def mock_input(answers, needanswer=False):
|
||||
return ''
|
||||
return input_
|
||||
|
||||
|
||||
real_input = input
|
||||
|
||||
|
||||
def teardown_module():
|
||||
qs.term_input = real_input
|
||||
qs.TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
|
||||
@@ -200,7 +204,7 @@ def test_quickstart_all_answers(tempdir):
|
||||
assert ns['master_doc'] == 'contents'
|
||||
assert ns['project'] == u'STASI™'
|
||||
assert ns['copyright'] == u'%s, Wolfgang Schäuble & G\'Beckstein' % \
|
||||
time.strftime('%Y')
|
||||
time.strftime('%Y')
|
||||
assert ns['version'] == '2.0'
|
||||
assert ns['release'] == '2.0.1'
|
||||
assert ns['html_static_path'] == ['.static']
|
||||
@@ -214,7 +218,7 @@ def test_quickstart_all_answers(tempdir):
|
||||
assert ns['texinfo_documents'] == [
|
||||
('contents', 'STASI', u'STASI™ Documentation',
|
||||
u'Wolfgang Schäuble & G\'Beckstein', 'STASI',
|
||||
'One line description of project.', 'Miscellaneous'),]
|
||||
'One line description of project.', 'Miscellaneous')]
|
||||
|
||||
assert (tempdir / 'build').isdir()
|
||||
assert (tempdir / 'source' / '.static').isdir()
|
||||
@@ -237,7 +241,7 @@ def test_generated_files_eol(tempdir):
|
||||
|
||||
def assert_eol(filename, eol):
|
||||
content = filename.bytes().decode('unicode-escape')
|
||||
assert all([l[-len(eol):]==eol for l in content.splitlines(True)])
|
||||
assert all([l[-len(eol):] == eol for l in content.splitlines(True)])
|
||||
|
||||
assert_eol(tempdir / 'make.bat', '\r\n')
|
||||
assert_eol(tempdir / 'Makefile', '\n')
|
||||
@@ -257,13 +261,13 @@ def test_quickstart_and_build(tempdir):
|
||||
qs.generate(d)
|
||||
|
||||
app = application.Sphinx(
|
||||
tempdir, #srcdir
|
||||
tempdir, #confdir
|
||||
(tempdir / '_build' / 'html'), #outdir
|
||||
(tempdir / '_build' / '.doctree'), #doctreedir
|
||||
'html', #buildername
|
||||
status=StringIO(),
|
||||
warning=warnfile)
|
||||
tempdir, # srcdir
|
||||
tempdir, # confdir
|
||||
(tempdir / '_build' / 'html'), # outdir
|
||||
(tempdir / '_build' / '.doctree'), # doctreedir
|
||||
'html', # buildername
|
||||
status=StringIO(),
|
||||
warning=warnfile)
|
||||
app.builder.build_all()
|
||||
warnings = warnfile.getvalue()
|
||||
assert not warnings
|
||||
@@ -273,7 +277,7 @@ def test_quickstart_and_build(tempdir):
|
||||
def test_default_filename(tempdir):
|
||||
answers = {
|
||||
'Root path': tempdir,
|
||||
'Project name': u'\u30c9\u30a4\u30c4', #Fullwidth characters only
|
||||
'Project name': u'\u30c9\u30a4\u30c4', # Fullwidth characters only
|
||||
'Author name': 'Georg Brandl',
|
||||
'Project version': '0.1',
|
||||
}
|
||||
|
||||
@@ -9,33 +9,24 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from six import StringIO
|
||||
|
||||
from sphinx.websupport import WebSupport
|
||||
|
||||
from test_websupport import sqlalchemy_missing
|
||||
from util import test_root, skip_if, skip_unless_importable
|
||||
|
||||
|
||||
def clear_builddir():
|
||||
(test_root / 'websupport').rmtree(True)
|
||||
from util import rootdir, tempdir, skip_if, skip_unless_importable
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_root / 'generated').rmtree(True)
|
||||
clear_builddir()
|
||||
(tempdir / 'websupport').rmtree(True)
|
||||
|
||||
|
||||
def search_adapter_helper(adapter):
|
||||
clear_builddir()
|
||||
|
||||
settings = {'builddir': os.path.join(test_root, 'websupport'),
|
||||
settings = {'srcdir': rootdir / 'root',
|
||||
'builddir': tempdir / 'websupport',
|
||||
'status': StringIO(),
|
||||
'warning': StringIO()}
|
||||
settings.update({'srcdir': test_root,
|
||||
'search': adapter})
|
||||
'warning': StringIO(),
|
||||
'search': adapter}
|
||||
support = WebSupport(**settings)
|
||||
support.build()
|
||||
|
||||
@@ -63,7 +54,7 @@ def search_adapter_helper(adapter):
|
||||
'%s search adapter returned %s search result(s), should have been 1'\
|
||||
% (adapter, len(results))
|
||||
# Make sure it works through the WebSupport API
|
||||
html = support.get_search_results(u'SomeLongRandomWord')
|
||||
support.get_search_results(u'SomeLongRandomWord')
|
||||
|
||||
|
||||
@skip_unless_importable('xapian', 'needs xapian bindings installed')
|
||||
|
||||
@@ -16,11 +16,16 @@ from functools import wraps
|
||||
import tempfile
|
||||
import sphinx
|
||||
|
||||
from util import with_tempdir, test_roots, SkipTest
|
||||
from util import rootdir, tempdir, SkipTest
|
||||
from path import path
|
||||
from textwrap import dedent
|
||||
|
||||
root = test_roots / 'test-setup'
|
||||
root = tempdir / 'test-setup'
|
||||
|
||||
|
||||
def setup_module():
|
||||
if not root.exists():
|
||||
(rootdir / 'roots' / 'test-setup').copytree(root)
|
||||
|
||||
|
||||
def with_setup_command(root, *args, **kwds):
|
||||
|
||||
@@ -9,28 +9,23 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from util import test_roots, with_app
|
||||
from util import with_app
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_roots / 'test-templating' / '_build').rmtree(True),
|
||||
|
||||
|
||||
@with_app(buildername='html', srcdir=(test_roots / 'test-templating'))
|
||||
def test_layout_overloading(app):
|
||||
app.builder.build_all()
|
||||
@with_app('html', testroot='templating')
|
||||
def test_layout_overloading(app, status, warning):
|
||||
app.builder.build_update()
|
||||
|
||||
result = (app.outdir / 'contents.html').text(encoding='utf-8')
|
||||
|
||||
assert '<!-- layout overloading -->' in result
|
||||
|
||||
|
||||
@with_app(buildername='html', srcdir=(test_roots / 'test-templating'))
|
||||
def test_autosummary_class_template_overloading(app):
|
||||
app.builder.build_all()
|
||||
@with_app('html', testroot='templating')
|
||||
def test_autosummary_class_template_overloading(app, status, warning):
|
||||
app.builder.build_update()
|
||||
|
||||
result = (app.outdir / 'generated' / 'sphinx.application.Sphinx.html').text(
|
||||
encoding='utf-8')
|
||||
result = (app.outdir / 'generated' / 'sphinx.application.TemplateBridge.html').text(
|
||||
encoding='utf-8')
|
||||
|
||||
assert 'autosummary/class.rst method block overloading' in result
|
||||
|
||||
@@ -19,14 +19,14 @@ from util import with_app, raises
|
||||
|
||||
@with_app(confoverrides={'html_theme': 'ziptheme',
|
||||
'html_theme_options.testopt': 'foo'})
|
||||
def test_theme_api(app):
|
||||
def test_theme_api(app, status, warning):
|
||||
cfg = app.config
|
||||
|
||||
# test Theme class API
|
||||
assert set(Theme.themes.keys()) == \
|
||||
set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku',
|
||||
'traditional', 'testtheme', 'ziptheme', 'epub', 'nature',
|
||||
'pyramid', 'bizstyle'])
|
||||
set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku',
|
||||
'traditional', 'testtheme', 'ziptheme', 'epub', 'nature',
|
||||
'pyramid', 'bizstyle'])
|
||||
assert Theme.themes['testtheme'][1] is None
|
||||
assert isinstance(Theme.themes['ziptheme'][1], zipfile.ZipFile)
|
||||
|
||||
@@ -56,14 +56,15 @@ def test_theme_api(app):
|
||||
theme.cleanup()
|
||||
assert not os.path.exists(themedir)
|
||||
|
||||
@with_app(buildername='html')
|
||||
def test_js_source(app):
|
||||
|
||||
@with_app(testroot='tocdepth') # a minimal root
|
||||
def test_js_source(app, status, warning):
|
||||
# Now sphinx provides non-minified JS files for jquery.js and underscore.js
|
||||
# to clarify the source of the minified files. see also #1434.
|
||||
# If you update the version of the JS file, please update the source of the
|
||||
# JS file and version number in this test.
|
||||
|
||||
app.builder.build_all()
|
||||
app.builder.build(['contents'])
|
||||
|
||||
v = '1.8.3'
|
||||
msg = 'jquery.js version does not match to {v}'.format(v=v)
|
||||
|
||||
+163
-163
@@ -1,163 +1,163 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_util_i18n
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Test i18n util.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
from os import path
|
||||
|
||||
from babel.messages.mofile import read_mo
|
||||
from sphinx.util import i18n
|
||||
|
||||
from util import with_tempdir
|
||||
|
||||
|
||||
def test_catalog_info_for_file_and_path():
|
||||
cat = i18n.CatalogInfo('path', 'domain')
|
||||
assert cat.po_file == 'domain.po'
|
||||
assert cat.mo_file == 'domain.mo'
|
||||
assert cat.po_path == path.join('path', 'domain.po')
|
||||
assert cat.mo_path == path.join('path', 'domain.mo')
|
||||
|
||||
|
||||
def test_catalog_info_for_sub_domain_file_and_path():
|
||||
cat = i18n.CatalogInfo('path', 'sub/domain')
|
||||
assert cat.po_file == 'sub/domain.po'
|
||||
assert cat.mo_file == 'sub/domain.mo'
|
||||
assert cat.po_path == path.join('path', 'sub/domain.po')
|
||||
assert cat.mo_path == path.join('path', 'sub/domain.mo')
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_catalog_outdated(dir):
|
||||
(dir / 'test.po').write_text('#')
|
||||
cat = i18n.CatalogInfo(dir, 'test')
|
||||
assert cat.is_outdated() # if mo is not exist
|
||||
|
||||
mo_file = (dir / 'test.mo')
|
||||
mo_file.write_text('#')
|
||||
assert not cat.is_outdated() # if mo is exist and newer than po
|
||||
|
||||
os.utime(mo_file, (os.stat(mo_file).st_mtime - 10,) * 2) # to be outdate
|
||||
assert cat.is_outdated() # if mo is exist and older than po
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_catalog_write_mo(dir):
|
||||
(dir / 'test.po').write_text('#')
|
||||
cat = i18n.CatalogInfo(dir, 'test')
|
||||
cat.write_mo('en')
|
||||
assert path.exists(cat.mo_path)
|
||||
assert read_mo(open(cat.mo_path, 'rb')) is not None
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_for_xx(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
|
||||
(dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'test6.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_ALL').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_ALL' / 'test7.po').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=False)
|
||||
domains = set(c.domain for c in catalogs)
|
||||
assert domains == set([
|
||||
'test1',
|
||||
'test2',
|
||||
path.normpath('sub/test4'),
|
||||
path.normpath('sub/test5'),
|
||||
])
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_for_en(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'xx_dom.po').write_text('#')
|
||||
(dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'en', force_all=False)
|
||||
domains = set(c.domain for c in catalogs)
|
||||
assert domains == set(['en_dom'])
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_with_non_existent_locale(dir):
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx')
|
||||
assert not catalogs
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], None)
|
||||
assert not catalogs
|
||||
|
||||
|
||||
def test_get_catalogs_with_non_existent_locale_dirs():
|
||||
catalogs = i18n.get_catalogs(['dummy'], 'xx')
|
||||
assert not catalogs
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_for_xx_without_outdated(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.mo').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.mo').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.mo').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.mo').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.mo').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=False)
|
||||
assert not catalogs
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=True)
|
||||
domains = set(c.domain for c in catalogs)
|
||||
assert domains == set([
|
||||
'test1',
|
||||
'test2',
|
||||
path.normpath('sub/test4'),
|
||||
path.normpath('sub/test5'),
|
||||
])
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_from_multiple_locale_dirs(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1', dir / 'loc2'], 'xx')
|
||||
domains = sorted(c.domain for c in catalogs)
|
||||
assert domains == ['test1', 'test1', 'test2']
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_with_compact(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', gettext_compact=True)
|
||||
domains = set(c.domain for c in catalogs)
|
||||
assert domains == set(['test1', 'test2', 'sub'])
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_util_i18n
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Test i18n util.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
from os import path
|
||||
|
||||
from babel.messages.mofile import read_mo
|
||||
from sphinx.util import i18n
|
||||
|
||||
from util import with_tempdir
|
||||
|
||||
|
||||
def test_catalog_info_for_file_and_path():
|
||||
cat = i18n.CatalogInfo('path', 'domain')
|
||||
assert cat.po_file == 'domain.po'
|
||||
assert cat.mo_file == 'domain.mo'
|
||||
assert cat.po_path == path.join('path', 'domain.po')
|
||||
assert cat.mo_path == path.join('path', 'domain.mo')
|
||||
|
||||
|
||||
def test_catalog_info_for_sub_domain_file_and_path():
|
||||
cat = i18n.CatalogInfo('path', 'sub/domain')
|
||||
assert cat.po_file == 'sub/domain.po'
|
||||
assert cat.mo_file == 'sub/domain.mo'
|
||||
assert cat.po_path == path.join('path', 'sub/domain.po')
|
||||
assert cat.mo_path == path.join('path', 'sub/domain.mo')
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_catalog_outdated(dir):
|
||||
(dir / 'test.po').write_text('#')
|
||||
cat = i18n.CatalogInfo(dir, 'test')
|
||||
assert cat.is_outdated() # if mo is not exist
|
||||
|
||||
mo_file = (dir / 'test.mo')
|
||||
mo_file.write_text('#')
|
||||
assert not cat.is_outdated() # if mo is exist and newer than po
|
||||
|
||||
os.utime(mo_file, (os.stat(mo_file).st_mtime - 10,) * 2) # to be outdate
|
||||
assert cat.is_outdated() # if mo is exist and older than po
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_catalog_write_mo(dir):
|
||||
(dir / 'test.po').write_text('#')
|
||||
cat = i18n.CatalogInfo(dir, 'test')
|
||||
cat.write_mo('en')
|
||||
assert path.exists(cat.mo_path)
|
||||
assert read_mo(open(cat.mo_path, 'rb')) is not None
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_for_xx(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
|
||||
(dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'test6.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_ALL').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_ALL' / 'test7.po').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=False)
|
||||
domains = set(c.domain for c in catalogs)
|
||||
assert domains == set([
|
||||
'test1',
|
||||
'test2',
|
||||
path.normpath('sub/test4'),
|
||||
path.normpath('sub/test5'),
|
||||
])
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_for_en(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'xx_dom.po').write_text('#')
|
||||
(dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'en', force_all=False)
|
||||
domains = set(c.domain for c in catalogs)
|
||||
assert domains == set(['en_dom'])
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_with_non_existent_locale(dir):
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx')
|
||||
assert not catalogs
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], None)
|
||||
assert not catalogs
|
||||
|
||||
|
||||
def test_get_catalogs_with_non_existent_locale_dirs():
|
||||
catalogs = i18n.get_catalogs(['dummy'], 'xx')
|
||||
assert not catalogs
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_for_xx_without_outdated(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.mo').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.mo').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.mo').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.mo').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.mo').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=False)
|
||||
assert not catalogs
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=True)
|
||||
domains = set(c.domain for c in catalogs)
|
||||
assert domains == set([
|
||||
'test1',
|
||||
'test2',
|
||||
path.normpath('sub/test4'),
|
||||
path.normpath('sub/test5'),
|
||||
])
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_from_multiple_locale_dirs(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1', dir / 'loc2'], 'xx')
|
||||
domains = sorted(c.domain for c in catalogs)
|
||||
assert domains == ['test1', 'test1', 'test2']
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_get_catalogs_with_compact(dir):
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#')
|
||||
(dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
||||
|
||||
catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', gettext_compact=True)
|
||||
domains = set(c.domain for c in catalogs)
|
||||
assert domains == set(['test1', 'test2', 'sub'])
|
||||
+121
-121
@@ -1,121 +1,121 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_util_nodes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Tests uti.nodes functions.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from textwrap import dedent
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
from docutils.utils import new_document
|
||||
from docutils import frontend
|
||||
|
||||
from sphinx.util.nodes import extract_messages
|
||||
|
||||
|
||||
def _get_doctree(text):
|
||||
settings = frontend.OptionParser(
|
||||
components=(rst.Parser,)).get_default_values()
|
||||
document = new_document('dummy.txt', settings)
|
||||
rst.Parser().parse(text, document)
|
||||
return document
|
||||
|
||||
|
||||
def assert_node_count(messages, node_type, expect_count):
|
||||
count = 0
|
||||
node_list = [node for node, msg in messages]
|
||||
for node in node_list:
|
||||
if isinstance(node, node_type):
|
||||
count += 1
|
||||
|
||||
assert count == expect_count, (
|
||||
"Count of %r in the %r is %d instead of %d"
|
||||
% (node_type, node_list, count, expect_count))
|
||||
|
||||
|
||||
def test_extract_messages():
|
||||
text = dedent(
|
||||
"""
|
||||
.. admonition:: admonition title
|
||||
|
||||
admonition body
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.title, 1,
|
||||
)
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
.. figure:: foo.jpg
|
||||
|
||||
this is title
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.caption, 1,
|
||||
)
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
.. rubric:: spam
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.rubric, 1,
|
||||
)
|
||||
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
| spam
|
||||
| egg
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.line, 2,
|
||||
)
|
||||
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
section
|
||||
=======
|
||||
|
||||
+----------------+
|
||||
| | **Title 1** |
|
||||
| | Message 1 |
|
||||
+----------------+
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.line, 2,
|
||||
)
|
||||
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
* | **Title 1**
|
||||
| Message 1
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.line, 2,
|
||||
)
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_util_nodes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Tests uti.nodes functions.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from textwrap import dedent
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
from docutils.utils import new_document
|
||||
from docutils import frontend
|
||||
|
||||
from sphinx.util.nodes import extract_messages
|
||||
|
||||
|
||||
def _get_doctree(text):
|
||||
settings = frontend.OptionParser(
|
||||
components=(rst.Parser,)).get_default_values()
|
||||
document = new_document('dummy.txt', settings)
|
||||
rst.Parser().parse(text, document)
|
||||
return document
|
||||
|
||||
|
||||
def assert_node_count(messages, node_type, expect_count):
|
||||
count = 0
|
||||
node_list = [node for node, msg in messages]
|
||||
for node in node_list:
|
||||
if isinstance(node, node_type):
|
||||
count += 1
|
||||
|
||||
assert count == expect_count, (
|
||||
"Count of %r in the %r is %d instead of %d"
|
||||
% (node_type, node_list, count, expect_count))
|
||||
|
||||
|
||||
def test_extract_messages():
|
||||
text = dedent(
|
||||
"""
|
||||
.. admonition:: admonition title
|
||||
|
||||
admonition body
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.title, 1,
|
||||
)
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
.. figure:: foo.jpg
|
||||
|
||||
this is title
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.caption, 1,
|
||||
)
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
.. rubric:: spam
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.rubric, 1,
|
||||
)
|
||||
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
| spam
|
||||
| egg
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.line, 2,
|
||||
)
|
||||
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
section
|
||||
=======
|
||||
|
||||
+----------------+
|
||||
| | **Title 1** |
|
||||
| | Message 1 |
|
||||
+----------------+
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.line, 2,
|
||||
)
|
||||
|
||||
|
||||
text = dedent(
|
||||
"""
|
||||
* | **Title 1**
|
||||
| Message 1
|
||||
"""
|
||||
)
|
||||
yield (
|
||||
assert_node_count,
|
||||
extract_messages(_get_doctree(text)),
|
||||
nodes.line, 2,
|
||||
)
|
||||
+25
-11
@@ -16,39 +16,46 @@ from docutils.parsers.rst.directives.html import MetaBody
|
||||
from sphinx import addnodes
|
||||
from sphinx.versioning import add_uids, merge_doctrees, get_ratio
|
||||
|
||||
from util import test_root, TestApp
|
||||
from util import TestApp
|
||||
|
||||
|
||||
app = original = original_uids = None
|
||||
|
||||
|
||||
def setup_module():
|
||||
global app, original, original_uids
|
||||
app = TestApp()
|
||||
app = TestApp(testroot='versioning')
|
||||
app.builder.env.app = app
|
||||
app.connect('doctree-resolved', on_doctree_resolved)
|
||||
app.build()
|
||||
original = doctrees['versioning/original']
|
||||
original = doctrees['original']
|
||||
original_uids = [n.uid for n in add_uids(original, is_paragraph)]
|
||||
|
||||
|
||||
def teardown_module():
|
||||
app.cleanup()
|
||||
(test_root / '_build').rmtree(True)
|
||||
|
||||
|
||||
doctrees = {}
|
||||
|
||||
|
||||
def on_doctree_resolved(app, doctree, docname):
|
||||
doctrees[docname] = doctree
|
||||
|
||||
|
||||
def is_paragraph(node):
|
||||
return node.__class__.__name__ == 'paragraph'
|
||||
|
||||
|
||||
def test_get_ratio():
|
||||
assert get_ratio('', 'a')
|
||||
assert get_ratio('a', '')
|
||||
|
||||
|
||||
def test_add_uids():
|
||||
assert len(original_uids) == 3
|
||||
|
||||
|
||||
def test_picklablility():
|
||||
# we have to modify the doctree so we can pickle it
|
||||
copy = original.copy()
|
||||
@@ -62,44 +69,50 @@ def test_picklablility():
|
||||
loaded = pickle.loads(pickle.dumps(copy, pickle.HIGHEST_PROTOCOL))
|
||||
assert all(getattr(n, 'uid', False) for n in loaded.traverse(is_paragraph))
|
||||
|
||||
|
||||
def test_modified():
|
||||
modified = doctrees['versioning/modified']
|
||||
modified = doctrees['modified']
|
||||
new_nodes = list(merge_doctrees(original, modified, is_paragraph))
|
||||
uids = [n.uid for n in modified.traverse(is_paragraph)]
|
||||
assert not new_nodes
|
||||
assert original_uids == uids
|
||||
|
||||
|
||||
def test_added():
|
||||
added = doctrees['versioning/added']
|
||||
added = doctrees['added']
|
||||
new_nodes = list(merge_doctrees(original, added, is_paragraph))
|
||||
uids = [n.uid for n in added.traverse(is_paragraph)]
|
||||
assert len(new_nodes) == 1
|
||||
assert original_uids == uids[:-1]
|
||||
|
||||
|
||||
def test_deleted():
|
||||
deleted = doctrees['versioning/deleted']
|
||||
deleted = doctrees['deleted']
|
||||
new_nodes = list(merge_doctrees(original, deleted, is_paragraph))
|
||||
uids = [n.uid for n in deleted.traverse(is_paragraph)]
|
||||
assert not new_nodes
|
||||
assert original_uids[::2] == uids
|
||||
|
||||
|
||||
def test_deleted_end():
|
||||
deleted_end = doctrees['versioning/deleted_end']
|
||||
deleted_end = doctrees['deleted_end']
|
||||
new_nodes = list(merge_doctrees(original, deleted_end, is_paragraph))
|
||||
uids = [n.uid for n in deleted_end.traverse(is_paragraph)]
|
||||
assert not new_nodes
|
||||
assert original_uids[:-1] == uids
|
||||
|
||||
|
||||
def test_insert():
|
||||
insert = doctrees['versioning/insert']
|
||||
insert = doctrees['insert']
|
||||
new_nodes = list(merge_doctrees(original, insert, is_paragraph))
|
||||
uids = [n.uid for n in insert.traverse(is_paragraph)]
|
||||
assert len(new_nodes) == 1
|
||||
assert original_uids[0] == uids[0]
|
||||
assert original_uids[1:] == uids[2:]
|
||||
|
||||
|
||||
def test_insert_beginning():
|
||||
insert_beginning = doctrees['versioning/insert_beginning']
|
||||
insert_beginning = doctrees['insert_beginning']
|
||||
new_nodes = list(merge_doctrees(original, insert_beginning, is_paragraph))
|
||||
uids = [n.uid for n in insert_beginning.traverse(is_paragraph)]
|
||||
assert len(new_nodes) == 1
|
||||
@@ -107,8 +120,9 @@ def test_insert_beginning():
|
||||
assert original_uids == uids[1:]
|
||||
assert original_uids[0] != uids[0]
|
||||
|
||||
|
||||
def test_insert_similar():
|
||||
insert_similar = doctrees['versioning/insert_similar']
|
||||
insert_similar = doctrees['insert_similar']
|
||||
new_nodes = list(merge_doctrees(original, insert_similar, is_paragraph))
|
||||
uids = [n.uid for n in insert_similar.traverse(is_paragraph)]
|
||||
assert len(new_nodes) == 1
|
||||
|
||||
+14
-13
@@ -9,34 +9,33 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
from functools import wraps
|
||||
|
||||
from six import StringIO
|
||||
|
||||
from sphinx.websupport import WebSupport
|
||||
from sphinx.websupport.errors import DocumentNotFoundError, \
|
||||
CommentNotAllowedError, UserNotAuthorizedError
|
||||
CommentNotAllowedError, UserNotAuthorizedError
|
||||
from sphinx.websupport.storage import StorageBackend
|
||||
from sphinx.websupport.storage.differ import CombinedHtmlDiff
|
||||
try:
|
||||
from sphinx.websupport.storage.sqlalchemystorage import Session, \
|
||||
Comment, CommentVote
|
||||
Comment, CommentVote
|
||||
from sphinx.websupport.storage.sqlalchemy_db import Node
|
||||
sqlalchemy_missing = False
|
||||
except ImportError:
|
||||
sqlalchemy_missing = True
|
||||
|
||||
from util import test_root, raises, skip_if
|
||||
from util import rootdir, tempdir, raises, skip_if
|
||||
|
||||
|
||||
default_settings = {'builddir': os.path.join(test_root, 'websupport'),
|
||||
default_settings = {'builddir': tempdir / 'websupport',
|
||||
'status': StringIO(),
|
||||
'warning': StringIO()}
|
||||
|
||||
|
||||
def teardown_module():
|
||||
(test_root / 'generated').rmtree(True)
|
||||
(test_root / 'websupport').rmtree(True)
|
||||
(tempdir / 'websupport').rmtree(True)
|
||||
|
||||
|
||||
def with_support(*args, **kwargs):
|
||||
@@ -59,12 +58,12 @@ class NullStorage(StorageBackend):
|
||||
|
||||
@with_support(storage=NullStorage())
|
||||
def test_no_srcdir(support):
|
||||
"""Make sure the correct exception is raised if srcdir is not given."""
|
||||
# make sure the correct exception is raised if srcdir is not given.
|
||||
raises(RuntimeError, support.build)
|
||||
|
||||
|
||||
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
|
||||
@with_support(srcdir=test_root)
|
||||
@with_support(srcdir=rootdir / 'root')
|
||||
def test_build(support):
|
||||
support.build()
|
||||
|
||||
@@ -173,9 +172,9 @@ def test_proposals(support):
|
||||
source = data['source']
|
||||
proposal = source[:5] + source[10:15] + 'asdf' + source[15:]
|
||||
|
||||
comment = support.add_comment('Proposal comment',
|
||||
node_id=node.id,
|
||||
proposal=proposal)
|
||||
support.add_comment('Proposal comment',
|
||||
node_id=node.id,
|
||||
proposal=proposal)
|
||||
|
||||
|
||||
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
|
||||
@@ -234,6 +233,8 @@ def test_update_username(support):
|
||||
|
||||
|
||||
called = False
|
||||
|
||||
|
||||
def moderation_callback(comment):
|
||||
global called
|
||||
called = True
|
||||
@@ -251,7 +252,7 @@ def test_moderation(support):
|
||||
deleted = support.add_comment('Comment to delete', node_id=node.id,
|
||||
displayed=False)
|
||||
# Make sure the moderation_callback is called.
|
||||
assert called == True
|
||||
assert called
|
||||
# Make sure the user must be a moderator.
|
||||
raises(UserNotAuthorizedError, support.accept_comment, accepted['id'])
|
||||
raises(UserNotAuthorizedError, support.delete_comment, deleted['id'])
|
||||
|
||||
+96
-72
@@ -8,22 +8,22 @@
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import shutil
|
||||
import re
|
||||
from functools import wraps
|
||||
|
||||
from six import StringIO
|
||||
|
||||
from nose import tools, SkipTest
|
||||
|
||||
from sphinx import application
|
||||
from sphinx.theming import Theme
|
||||
from sphinx.ext.autodoc import AutoDirective
|
||||
from sphinx.pycode import ModuleAnalyzer
|
||||
|
||||
from path import path
|
||||
|
||||
from nose import tools, SkipTest
|
||||
|
||||
try:
|
||||
# Python >=3.3
|
||||
from unittest import mock
|
||||
@@ -32,7 +32,7 @@ except ImportError:
|
||||
|
||||
|
||||
__all__ = [
|
||||
'test_root', 'test_roots', 'raises', 'raises_msg',
|
||||
'rootdir', 'tempdir', 'raises', 'raises_msg',
|
||||
'skip_if', 'skip_unless', 'skip_unless_importable', 'Struct',
|
||||
'ListOutput', 'TestApp', 'with_app', 'gen_with_app',
|
||||
'path', 'with_tempdir',
|
||||
@@ -41,8 +41,8 @@ __all__ = [
|
||||
]
|
||||
|
||||
|
||||
test_root = path(__file__).parent.joinpath('root').abspath()
|
||||
test_roots = path(__file__).parent.joinpath('roots').abspath()
|
||||
rootdir = path(os.path.dirname(__file__) or '.').abspath()
|
||||
tempdir = path(os.environ['SPHINX_TEST_TEMPDIR']).abspath()
|
||||
|
||||
|
||||
def _excstr(exc):
|
||||
@@ -50,11 +50,9 @@ def _excstr(exc):
|
||||
return str(tuple(map(_excstr, exc)))
|
||||
return exc.__name__
|
||||
|
||||
|
||||
def raises(exc, func, *args, **kwds):
|
||||
"""
|
||||
Raise :exc:`AssertionError` if ``func(*args, **kwds)`` does not
|
||||
raise *exc*.
|
||||
"""
|
||||
"""Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*."""
|
||||
try:
|
||||
func(*args, **kwds)
|
||||
except exc:
|
||||
@@ -63,10 +61,10 @@ def raises(exc, func, *args, **kwds):
|
||||
raise AssertionError('%s did not raise %s' %
|
||||
(func.__name__, _excstr(exc)))
|
||||
|
||||
|
||||
def raises_msg(exc, msg, func, *args, **kwds):
|
||||
"""
|
||||
Raise :exc:`AssertionError` if ``func(*args, **kwds)`` does not
|
||||
raise *exc*, and check if the message contains *msg*.
|
||||
"""Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*,
|
||||
and check if the message contains *msg*.
|
||||
"""
|
||||
try:
|
||||
func(*args, **kwds)
|
||||
@@ -76,6 +74,32 @@ def raises_msg(exc, msg, func, *args, **kwds):
|
||||
raise AssertionError('%s did not raise %s' %
|
||||
(func.__name__, _excstr(exc)))
|
||||
|
||||
|
||||
def assert_re_search(regex, text, flags=0):
|
||||
if not re.search(regex, text, flags):
|
||||
assert False, '%r did not match %r' % (regex, text)
|
||||
|
||||
|
||||
def assert_not_re_search(regex, text, flags=0):
|
||||
if re.search(regex, text, flags):
|
||||
assert False, '%r did match %r' % (regex, text)
|
||||
|
||||
|
||||
def assert_startswith(thing, prefix):
|
||||
if not thing.startswith(prefix):
|
||||
assert False, '%r does not start with %r' % (thing, prefix)
|
||||
|
||||
|
||||
def assert_in(x, thing):
|
||||
if x not in thing:
|
||||
assert False, '%r is not in %r' % (x, thing)
|
||||
|
||||
|
||||
def assert_not_in(x, thing):
|
||||
if x in thing:
|
||||
assert False, '%r is in %r' % (x, thing)
|
||||
|
||||
|
||||
def skip_if(condition, msg=None):
|
||||
"""Decorator to skip test if condition is true."""
|
||||
def deco(test):
|
||||
@@ -87,10 +111,12 @@ def skip_if(condition, msg=None):
|
||||
return skipper
|
||||
return deco
|
||||
|
||||
|
||||
def skip_unless(condition, msg=None):
|
||||
"""Decorator to skip test if condition is false."""
|
||||
return skip_if(not condition, msg)
|
||||
|
||||
|
||||
def skip_unless_importable(module, msg=None):
|
||||
"""Decorator to skip test if module is not importable."""
|
||||
try:
|
||||
@@ -127,61 +153,47 @@ class TestApp(application.Sphinx):
|
||||
better default values for the initialization parameters.
|
||||
"""
|
||||
|
||||
def __init__(self, srcdir=None, confdir=None, outdir=None, doctreedir=None,
|
||||
buildername='html', confoverrides=None,
|
||||
status=None, warning=None, freshenv=None,
|
||||
warningiserror=None, tags=None,
|
||||
confname='conf.py', cleanenv=False,
|
||||
_copy_to_temp=False,
|
||||
):
|
||||
|
||||
application.CONFIG_FILENAME = confname
|
||||
|
||||
self.cleanup_trees = [test_root / 'generated']
|
||||
|
||||
if srcdir is None:
|
||||
srcdir = test_root
|
||||
elif srcdir == '(empty)':
|
||||
tempdir = path(tempfile.mkdtemp())
|
||||
self.cleanup_trees.append(tempdir)
|
||||
temproot = tempdir / 'root'
|
||||
temproot.makedirs()
|
||||
(temproot / 'conf.py').write_text('')
|
||||
srcdir = temproot
|
||||
def __init__(self, buildername='html', testroot=None, srcdir=None,
|
||||
freshenv=False, confoverrides=None, status=None, warning=None,
|
||||
tags=None, docutilsconf=None):
|
||||
if testroot is None:
|
||||
defaultsrcdir = 'root'
|
||||
testroot = rootdir / 'root'
|
||||
else:
|
||||
srcdir = path(srcdir)
|
||||
defaultsrcdir = 'test-' + testroot
|
||||
testroot = rootdir / 'roots' / ('test-' + testroot)
|
||||
if srcdir is None:
|
||||
srcdir = tempdir / defaultsrcdir
|
||||
else:
|
||||
srcdir = tempdir / srcdir
|
||||
|
||||
if _copy_to_temp:
|
||||
tempdir = path(tempfile.mkdtemp())
|
||||
self.cleanup_trees.append(tempdir)
|
||||
temproot = tempdir / srcdir.basename()
|
||||
srcdir.copytree(temproot)
|
||||
srcdir = temproot
|
||||
if not srcdir.exists():
|
||||
testroot.copytree(srcdir)
|
||||
|
||||
self.builddir = srcdir.joinpath('_build')
|
||||
if confdir is None:
|
||||
confdir = srcdir
|
||||
if outdir is None:
|
||||
outdir = srcdir.joinpath(self.builddir, buildername)
|
||||
if not outdir.isdir():
|
||||
outdir.makedirs()
|
||||
self.cleanup_trees.insert(0, outdir)
|
||||
if doctreedir is None:
|
||||
doctreedir = srcdir.joinpath(srcdir, self.builddir, 'doctrees')
|
||||
if not doctreedir.isdir():
|
||||
doctreedir.makedirs()
|
||||
if cleanenv:
|
||||
self.cleanup_trees.insert(0, doctreedir)
|
||||
if docutilsconf is not None:
|
||||
(srcdir / 'docutils.conf').write_text(docutilsconf)
|
||||
|
||||
builddir = srcdir / '_build'
|
||||
# if confdir is None:
|
||||
confdir = srcdir
|
||||
# if outdir is None:
|
||||
outdir = builddir.joinpath(buildername)
|
||||
if not outdir.isdir():
|
||||
outdir.makedirs()
|
||||
# if doctreedir is None:
|
||||
doctreedir = builddir.joinpath('doctrees')
|
||||
if not doctreedir.isdir():
|
||||
doctreedir.makedirs()
|
||||
if confoverrides is None:
|
||||
confoverrides = {}
|
||||
if status is None:
|
||||
status = StringIO()
|
||||
if warning is None:
|
||||
warning = ListOutput('stderr')
|
||||
if freshenv is None:
|
||||
freshenv = False
|
||||
if warningiserror is None:
|
||||
warningiserror = False
|
||||
# if warningiserror is None:
|
||||
warningiserror = False
|
||||
|
||||
self._saved_path = sys.path[:]
|
||||
|
||||
application.Sphinx.__init__(self, srcdir, confdir, outdir, doctreedir,
|
||||
buildername, confoverrides, status, warning,
|
||||
@@ -190,8 +202,9 @@ class TestApp(application.Sphinx):
|
||||
def cleanup(self, doctrees=False):
|
||||
Theme.themes.clear()
|
||||
AutoDirective._registry.clear()
|
||||
for tree in self.cleanup_trees:
|
||||
shutil.rmtree(tree, True)
|
||||
ModuleAnalyzer.cache.clear()
|
||||
sys.path[:] = self._saved_path
|
||||
sys.modules.pop('autodoc_fodder', None)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s buildername=%r>' % (self.__class__.__name__, self.builder.name)
|
||||
@@ -205,10 +218,14 @@ def with_app(*args, **kwargs):
|
||||
def generator(func):
|
||||
@wraps(func)
|
||||
def deco(*args2, **kwargs2):
|
||||
status, warning = StringIO(), StringIO()
|
||||
kwargs['status'] = status
|
||||
kwargs['warning'] = warning
|
||||
app = TestApp(*args, **kwargs)
|
||||
func(app, *args2, **kwargs2)
|
||||
# don't execute cleanup if test failed
|
||||
app.cleanup()
|
||||
try:
|
||||
func(app, status, warning, *args2, **kwargs2)
|
||||
finally:
|
||||
app.cleanup()
|
||||
return deco
|
||||
return generator
|
||||
|
||||
@@ -221,20 +238,24 @@ def gen_with_app(*args, **kwargs):
|
||||
def generator(func):
|
||||
@wraps(func)
|
||||
def deco(*args2, **kwargs2):
|
||||
status, warning = StringIO(), StringIO()
|
||||
kwargs['status'] = status
|
||||
kwargs['warning'] = warning
|
||||
app = TestApp(*args, **kwargs)
|
||||
for item in func(app, *args2, **kwargs2):
|
||||
yield item
|
||||
# don't execute cleanup if test failed
|
||||
app.cleanup()
|
||||
try:
|
||||
for item in func(app, status, warning, *args2, **kwargs2):
|
||||
yield item
|
||||
finally:
|
||||
app.cleanup()
|
||||
return deco
|
||||
return generator
|
||||
|
||||
|
||||
def with_tempdir(func):
|
||||
def new_func(*args, **kwds):
|
||||
tempdir = path(tempfile.mkdtemp())
|
||||
func(tempdir, *args, **kwds)
|
||||
tempdir.rmtree()
|
||||
new_tempdir = path(tempfile.mkdtemp(dir=tempdir))
|
||||
func(new_tempdir, *args, **kwds)
|
||||
new_tempdir.rmtree() # not when test fails...
|
||||
new_func.__name__ = func.__name__
|
||||
return new_func
|
||||
|
||||
@@ -242,7 +263,10 @@ def with_tempdir(func):
|
||||
def sprint(*args):
|
||||
sys.stderr.write(' '.join(map(str, args)) + '\n')
|
||||
|
||||
|
||||
_unicode_literals_re = re.compile(r'u(".*?")|u(\'.*?\')')
|
||||
|
||||
|
||||
def remove_unicode_literals(s):
|
||||
return _unicode_literals_re.sub(lambda x: x.group(1) or x.group(2), s)
|
||||
|
||||
|
||||
Reference in new issue
Block a user