Merge branch 'stable'

This commit is contained in:
shimizukawa 2017-01-07 02:13:50 +09:00
commit 4c22cd10ca
67 changed files with 1090 additions and 2113 deletions

View File

@ -12,7 +12,7 @@ python:
- "pypy"
env:
global:
- TEST='-v --with-timer --timer-top-n 25'
- TEST='-v --durations 25'
- PYTHONFAULTHANDLER=x
- PYTHONWARNINGS=all
matrix:

View File

@ -58,6 +58,7 @@ Features added
* #3241: emit latex warning if buggy titlesec (ref #3210)
* #3194: Refer the $MAKE environment variable to determine ``make`` command
* Emit warning for nested numbered toctrees (refs: #3142)
Bugs fixed
----------
@ -70,6 +71,9 @@ Bugs fixed
attributes of Enum class correctly.
* #3261: ``latex_use_parts`` makes sphinx crash
* The warning type ``misc.highlighting_failure`` does not work
* #3294: ``add_latex_package()`` make crashes non-LaTeX builders
* The caption of table are rendered as invalid HTML (refs: #3287)
Release 1.5.1 (released Dec 13, 2016)
=====================================

View File

@ -75,14 +75,13 @@ reindent:
@$(PYTHON) utils/reindent.py -r -n .
test:
@cd tests; $(PYTHON) run.py -I py35 -d -m '^[tT]est' $(TEST)
@cd tests; $(PYTHON) run.py --ignore py35 -v $(TEST)
test-async:
@cd tests; $(PYTHON) run.py -d -m '^[tT]est' $(TEST)
@cd tests; $(PYTHON) run.py -v $(TEST)
covertest:
@cd tests; $(PYTHON) run.py -d -m '^[tT]est' --with-coverage \
--cover-package=sphinx $(TEST)
@cd tests; $(PYTHON) run.py -v --cov=sphinx --junitxml=.junit.xml $(TEST)
build:
@$(PYTHON) setup.py build

View File

@ -233,6 +233,7 @@ General configuration
* ref.citation
* ref.doc
* misc.highlighting_failure
* toc.secnum
* epub.unknown_project_files
You can choose from these types.

View File

@ -812,7 +812,8 @@ class Sphinx(object):
def add_latex_package(self, packagename, options=None):
# type: (unicode, unicode) -> None
logger.debug('[app] adding latex package: %r', packagename)
self.builder.usepackages.append((packagename, options))
if hasattr(self.builder, 'usepackages'): # only for LaTeX builder
self.builder.usepackages.append((packagename, options))
def add_lexer(self, alias, lexer):
# type: (unicode, Any) -> None

View File

@ -483,10 +483,14 @@ class Toctree(EnvironmentManager):
if depth == 0:
return
for (title, ref) in toctreenode['entries']:
if url_re.match(ref) or ref == 'self' or ref in assigned:
if url_re.match(ref) or ref == 'self':
# don't mess with those
continue
if ref in self.tocs:
elif ref in assigned:
logger.warning('%s is already assigned section numbers '
'(nested numbered toctree?)', ref,
location=toctreenode, type='toc', subtype='secnum')
elif ref in self.tocs:
secnums = self.toc_secnumbers[ref] = {}
assigned.add(ref)
_walk_toc(self.tocs[ref], secnums, depth,

View File

@ -228,9 +228,10 @@ def save_traceback(app):
modfile = getattr(extmod, '__file__', 'unknown')
if isinstance(modfile, bytes):
modfile = modfile.decode(fs_encoding, 'replace')
os.write(fd, ('# %s (%s) from %s\n' % (
extname, app._extension_metadata[extname]['version'],
modfile)).encode('utf-8'))
version = app._extension_metadata[extname]['version']
if version != 'builtin':
os.write(fd, ('# %s (%s) from %s\n' %
(extname, version, modfile)).encode('utf-8'))
os.write(fd, exc_format.encode('utf-8'))
os.close(fd)
return path

View File

@ -344,6 +344,27 @@ class HTMLTranslator(BaseTranslator):
if isinstance(node.parent, nodes.table):
self.body.append('<span class="caption-text">')
def depart_title(self, node):
close_tag = self.context[-1]
if (self.permalink_text and self.builder.add_permalinks and
node.parent.hasattr('ids') and node.parent['ids']):
# add permalink anchor
if close_tag.startswith('</h'):
self.add_permalink_ref(node.parent, _('Permalink to this headline'))
elif close_tag.startswith('</a></h'):
self.body.append(u'</a><a class="headerlink" href="#%s" ' %
node.parent['ids'][0] +
u'title="%s">%s' % (
_('Permalink to this headline'),
self.permalink_text))
elif isinstance(node.parent, nodes.table):
self.body.append('</span>')
self.add_permalink_ref(node.parent, _('Permalink to this table'))
elif isinstance(node.parent, nodes.table):
self.body.append('</span>')
BaseTranslator.depart_title(self, node)
# overwritten
def visit_literal_block(self, node):
if node.rawsource != node.astext():
@ -701,25 +722,6 @@ class HTMLTranslator(BaseTranslator):
def depart_manpage(self, node):
return self.depart_literal_emphasis(node)
def depart_title(self, node):
close_tag = self.context[-1]
if (self.permalink_text and self.builder.add_permalinks and
node.parent.hasattr('ids') and node.parent['ids']):
# add permalink anchor
if close_tag.startswith('</h'):
self.add_permalink_ref(node.parent, _('Permalink to this headline'))
elif close_tag.startswith('</a></h'):
self.body.append(u'</a><a class="headerlink" href="#%s" ' %
node.parent['ids'][0] +
u'title="%s">%s' % (
_('Permalink to this headline'),
self.permalink_text))
elif isinstance(node.parent, nodes.table):
self.body.append('</span>')
self.add_permalink_ref(node.parent, _('Permalink to this table'))
BaseTranslator.depart_title(self, node)
# overwritten to add even/odd classes
def visit_table(self, node):

View File

@ -1,6 +1,6 @@
flake8
nose
nose-timer
pytest>=3.0
pytest-cov
mock
six>=1.4
Jinja2>=2.3

108
tests/conftest.py Normal file
View File

@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
import sys
import subprocess
import pytest
from six import StringIO
from util import SphinxTestApp, path
@pytest.fixture
def app_params(request):
"""
parameters that is specified by 'pytest.mark.sphinx' for
sphinx.application.Sphinx initialization
"""
markers = request.node.get_marker("sphinx")
pargs = {}
kwargs = {}
if markers is not None:
# to avoid stacking positional args
for info in reversed(list(markers)):
for i, a in enumerate(info.args):
pargs[i] = a
kwargs.update(info.kwargs)
args = [pargs[i] for i in sorted(pargs.keys())]
return args, kwargs
@pytest.fixture(scope='function')
def app(app_params, make_app):
"""
provides sphinx.application.Sphinx object
"""
args, kwargs = app_params
app_ = make_app(*args, **kwargs)
return app_
@pytest.fixture(scope='function')
def status(app):
"""
compat for testing with previous @with_app decorator
"""
return app._status
@pytest.fixture(scope='function')
def warning(app):
"""
compat for testing with previous @with_app decorator
"""
return app._warning
@pytest.fixture()
def make_app():
"""
provides make_app function to initialize SphinxTestApp instance.
if you want to initialize 'app' in your test function. please use this
instead of using SphinxTestApp class directory.
"""
apps = []
syspath = sys.path[:]
def make(*args, **kwargs):
status, warning = StringIO(), StringIO()
kwargs.setdefault('status', status)
kwargs.setdefault('warning', warning)
app_ = SphinxTestApp(*args, **kwargs)
apps.append(app_)
return app_
yield make
sys.path[:] = syspath
for app_ in apps:
app_.cleanup()
@pytest.fixture
def if_graphviz_found(app):
"""
The test will be skipped when using 'if_graphviz_found' fixture and graphviz
dot command is not found.
"""
graphviz_dot = getattr(app.config, 'graphviz_dot', '')
try:
if graphviz_dot:
dot = subprocess.Popen([graphviz_dot, '-V'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE) # show version
dot.communicate()
return
except OSError: # No such file or directory
pass
pytest.skip('graphviz "dot" is not available')
@pytest.fixture
def tempdir(tmpdir):
"""
temporary directory that wrapped with `path` class.
this fixture is for compat with old test implementation.
"""
return path(tmpdir)

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ import sys
import shutil
from io import open
from six import PY2, text_type, binary_type
from six import PY2, text_type
FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
@ -144,9 +144,7 @@ class path(text_type):
"""
mode = 'rU' if PY2 else 'r'
with open(self, mode=mode, encoding=encoding, **kwargs) as f:
text = f.read()
contents = repr_as(text, '<%s contents>' % self.basename())
return contents
return f.read()
def bytes(self):
"""
@ -201,21 +199,3 @@ class path(text_type):
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, text_type.__repr__(self))
# Lives here only to avoid circular references; use it from util.py!
class _repr_text(text_type):
def __repr__(self):
return self._repr
class _repr_bin(binary_type):
def __repr__(self):
return self._repr
def repr_as(string, repr_):
wrapper = _repr_text if isinstance(string, text_type) else _repr_bin
proxy = wrapper(string)
proxy._repr = repr_
return proxy

View File

@ -14,7 +14,7 @@
import six
import sys
from util import TestApp, Struct, raises, SkipTest
from nose.tools import with_setup, eq_
import pytest
from six import StringIO
from docutils.statemachine import ViewList
@ -42,6 +42,7 @@ def teardown_module():
directive = options = None
@pytest.fixture
def setup_test():
global options, directive
global processed_docstrings, processed_signatures, _warnings
@ -106,7 +107,7 @@ def skip_member(app, what, name, obj, skip, options):
return True
@with_setup(setup_test)
@pytest.mark.usefixtures('setup_test')
def test_generate():
def assert_warns(warn_str, objtype, name, **kw):
inst = AutoDirective._registry[objtype](directive, name)

View File

@ -4,7 +4,7 @@ import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = ['test_enumerable_node']
extensions = ['enumerable_node']
master_doc = 'index'
numfig = True

View File

@ -11,7 +11,7 @@ class DummyTestParser(Parser):
pass
extensions = ['test_source_parser']
extensions = ['source_parser']
source_suffix = ['.rst', '.test']
source_parsers = {
'.test': DummyTestParser

View File

@ -11,7 +11,7 @@ class DummyMarkdownParser(Parser):
pass
extensions = ['test_source_parser']
extensions = ['source_parser']
source_suffix = ['.rst', '.md']
source_parsers = {
'.md': DummyMarkdownParser

View File

@ -17,14 +17,14 @@ import warnings
import traceback
from path import path
import nose
import pytest
testroot = os.path.dirname(__file__) or '.'
sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
# check dependencies before testing
print('Checking dependencies...')
for modname in ('nose', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
for modname in ('pytest', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
'snowballstemmer', 'babel', 'html5lib'):
try:
__import__(modname)
@ -50,7 +50,15 @@ print('Running Sphinx test suite (with Python %s)...' % sys.version.split()[0])
sys.stdout.flush()
# filter warnings of test dependencies
warnings.filterwarnings('ignore', category=DeprecationWarning, module='nose.util')
warnings.filterwarnings('ignore', category=DeprecationWarning, module='site') # virtualenv
nose.main(argv=sys.argv)
# exclude 'root' and 'roots' dirs for pytest test collector
ignore_paths = [
os.path.relpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), sub))
for sub in ('root', 'roots')
]
args = sys.argv[1:]
for path in ignore_paths:
args.extend(['--ignore', path])
sys.exit(pytest.main(args))

View File

@ -11,7 +11,8 @@
import sys
from util import with_app, rootdir
import pytest
from util import rootdir
def setup_module():
@ -22,7 +23,7 @@ def teardown_module():
sys.path.remove(rootdir / 'roots' / 'test-api-set-translator')
@with_app('html')
@pytest.mark.sphinx('html')
def test_html_translator(app, status, warning):
# no set_translator()
translator_class = app.builder.translator_class
@ -30,8 +31,8 @@ def test_html_translator(app, status, warning):
assert translator_class.__name__ == 'SmartyPantsHTMLTranslator'
@with_app('html',
confoverrides={'html_use_smartypants': False})
@pytest.mark.sphinx('html', confoverrides={
'html_use_smartypants': False})
def test_html_with_smartypants(app, status, warning):
# no set_translator(), html_use_smartypants=False
translator_class = app.builder.translator_class
@ -39,7 +40,7 @@ def test_html_with_smartypants(app, status, warning):
assert translator_class.__name__ == 'HTMLTranslator'
@with_app('html', testroot='api-set-translator')
@pytest.mark.sphinx('html', testroot='api-set-translator')
def test_html_with_set_translator_for_html_(app, status, warning):
# use set_translator()
translator_class = app.builder.translator_class
@ -48,7 +49,7 @@ def test_html_with_set_translator_for_html_(app, status, warning):
# this test break test_websupport.test_comments test. why?
# @with_app(
# @pytest.mark.sphinx(
# buildername='dirhtml',
# srcdir=(test_roots / 'test-api-set-translator'),
# )
@ -58,63 +59,63 @@ def test_html_with_set_translator_for_html_(app, status, warning):
# assert translator_class.__name__ == 'ConfDirHTMLTranslator'
@with_app('singlehtml', testroot='api-set-translator')
@pytest.mark.sphinx('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('pickle', testroot='api-set-translator')
@pytest.mark.sphinx('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('json', testroot='api-set-translator')
@pytest.mark.sphinx('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('latex', testroot='api-set-translator')
@pytest.mark.sphinx('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('man', testroot='api-set-translator')
@pytest.mark.sphinx('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('texinfo', testroot='api-set-translator')
@pytest.mark.sphinx('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('text', testroot='api-set-translator')
@pytest.mark.sphinx('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_app('xml', testroot='api-set-translator')
@pytest.mark.sphinx('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('pseudoxml', testroot='api-set-translator')
@pytest.mark.sphinx('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

View File

@ -11,45 +11,60 @@
from __future__ import print_function
import sys
from six import PY2
from collections import namedtuple
from sphinx import apidoc
import pytest
from util import with_tempdir, with_app, rootdir
from sphinx.apidoc import main as apidoc_main
from util import rootdir, remove_unicode_literals
@with_tempdir
def test_simple(tempdir):
codedir = rootdir / 'root'
@pytest.fixture()
def apidoc(tempdir, apidoc_params):
_, kwargs = apidoc_params
coderoot = kwargs.get('coderoot', (rootdir / 'root'))
outdir = tempdir / 'out'
args = ['sphinx-apidoc', '-o', outdir, '-F', codedir]
apidoc.main(args)
args = ['sphinx-apidoc', '-o', outdir, '-F', coderoot] + kwargs.get('options', [])
apidoc_main(args)
return namedtuple('apidoc', 'coderoot,outdir')(coderoot, outdir)
@pytest.fixture
def apidoc_params(request):
markers = request.node.get_marker("apidoc")
pargs = {}
kwargs = {}
if markers is not None:
for info in reversed(list(markers)):
for i, a in enumerate(info.args):
pargs[i] = a
kwargs.update(info.kwargs)
args = [pargs[i] for i in sorted(pargs.keys())]
return args, kwargs
@pytest.mark.apidoc(coderoot=(rootdir / 'root'))
def test_simple(make_app, apidoc):
outdir = apidoc.outdir
assert (outdir / 'conf.py').isfile()
assert (outdir / 'autodoc_fodder.rst').isfile()
assert (outdir / 'index.rst').isfile()
@with_app('text', srcdir=outdir)
def assert_build(app, status, warning):
app.build()
print(status.getvalue())
print(warning.getvalue())
sys.path.append(codedir)
try:
assert_build()
finally:
sys.path.remove(codedir)
app = make_app('text', srcdir=outdir)
app.build()
print(app._status.getvalue())
print(app._warning.getvalue())
@with_tempdir
def test_pep_0420_enabled(tempdir):
codedir = rootdir / 'root' / 'pep_0420'
outdir = tempdir / 'out'
args = ['sphinx-apidoc', '-o', outdir, '-F', codedir, "--implicit-namespaces"]
apidoc.main(args)
@pytest.mark.apidoc(
coderoot=(rootdir / 'root' / 'pep_0420'),
options=["--implicit-namespaces"],
)
def test_pep_0420_enabled(make_app, apidoc):
outdir = apidoc.outdir
assert (outdir / 'conf.py').isfile()
assert (outdir / 'a.b.c.rst').isfile()
assert (outdir / 'a.b.x.rst').isfile()
@ -66,49 +81,28 @@ def test_pep_0420_enabled(tempdir):
assert "automodule:: a.b.x.y\n" in rst
assert "automodule:: a.b.x\n" not in rst
@with_app('text', srcdir=outdir)
def assert_build(app, status, warning):
app.build()
print(status.getvalue())
print(warning.getvalue())
sys.path.append(codedir)
try:
assert_build()
finally:
sys.path.remove(codedir)
app = make_app('text', srcdir=outdir)
app.build()
print(app._status.getvalue())
print(app._warning.getvalue())
@with_tempdir
def test_pep_0420_disabled(tempdir):
codedir = rootdir / 'root' / 'pep_0420'
outdir = tempdir / 'out'
args = ['sphinx-apidoc', '-o', outdir, '-F', codedir]
apidoc.main(args)
@pytest.mark.apidoc(coderoot=(rootdir / 'root' / 'pep_0420'))
def test_pep_0420_disabled(make_app, apidoc):
outdir = apidoc.outdir
assert (outdir / 'conf.py').isfile()
assert not (outdir / 'a.b.c.rst').exists()
assert not (outdir / 'a.b.x.rst').exists()
@with_app('text', srcdir=outdir)
def assert_build(app, status, warning):
app.build()
print(status.getvalue())
print(warning.getvalue())
app = make_app('text', srcdir=outdir)
app.build()
print(app._status.getvalue())
print(app._warning.getvalue())
sys.path.append(codedir)
try:
assert_build()
finally:
sys.path.remove(codedir)
@with_tempdir
def test_pep_0420_disabled_top_level_verify(tempdir):
codedir = rootdir / 'root' / 'pep_0420' / 'a' / 'b'
outdir = tempdir / 'out'
args = ['sphinx-apidoc', '-o', outdir, '-F', codedir]
apidoc.main(args)
@pytest.mark.apidoc(coderoot=(rootdir / 'root' / 'pep_0420' / 'a' / 'b'))
def test_pep_0420_disabled_top_level_verify(make_app, apidoc):
outdir = apidoc.outdir
assert (outdir / 'conf.py').isfile()
assert (outdir / 'c.rst').isfile()
assert not (outdir / 'x.rst').exists()
@ -119,53 +113,35 @@ def test_pep_0420_disabled_top_level_verify(tempdir):
assert "automodule:: c.d\n" in rst
assert "automodule:: c\n" in rst
@with_app('text', srcdir=outdir)
def assert_build(app, status, warning):
app.build()
print(status.getvalue())
print(warning.getvalue())
app = make_app('text', srcdir=outdir)
app.build()
print(app._status.getvalue())
print(app._warning.getvalue())
sys.path.append(codedir)
try:
assert_build()
finally:
sys.path.remove(codedir)
@with_tempdir
def test_multibyte_parameters(tempdir):
codedir = rootdir / 'root'
outdir = tempdir / 'out'
args = ['sphinx-apidoc', '-o', outdir, '-F', codedir,
'--doc-project', u'プロジェクト名'.encode('utf-8'),
'--doc-author', u'著者名'.encode('utf-8'),
'--doc-version', u'バージョン'.encode('utf-8'),
'--doc-release', u'リリース'.encode('utf-8')]
apidoc.main(args)
@pytest.mark.apidoc(
coderoot=(rootdir / 'root'),
options=[
'--doc-project', u'プロジェクト名'.encode('utf-8'),
'--doc-author', u'著者名'.encode('utf-8'),
'--doc-version', u'バージョン'.encode('utf-8'),
'--doc-release', u'リリース'.encode('utf-8'),
],
)
def test_multibyte_parameters(make_app, apidoc):
outdir = apidoc.outdir
assert (outdir / 'conf.py').isfile()
assert (outdir / 'autodoc_fodder.rst').isfile()
assert (outdir / 'index.rst').isfile()
conf_py = (outdir / 'conf.py').text()
if PY2:
assert u"project = u'プロジェクト名'" in conf_py
assert u"author = u'著者名'" in conf_py
assert u"version = u'バージョン'" in conf_py
assert u"release = u'リリース'" in conf_py
else:
assert u"project = 'プロジェクト名'" in conf_py
assert u"author = '著者名'" in conf_py
assert u"version = 'バージョン'" in conf_py
assert u"release = 'リリース'" in conf_py
conf_py_ = remove_unicode_literals(conf_py)
assert u"project = 'プロジェクト名'" in conf_py_
assert u"author = '著者名'" in conf_py_
assert u"version = 'バージョン'" in conf_py_
assert u"release = 'リリース'" in conf_py_
@with_app('text', srcdir=outdir)
def assert_build(app, status, warning):
app.build()
print(status.getvalue())
print(warning.getvalue())
sys.path.append(codedir)
try:
assert_build()
finally:
sys.path.remove(codedir)
app = make_app('text', srcdir=outdir)
app.build()
print(app._status.getvalue())
print(app._warning.getvalue())

View File

@ -8,25 +8,28 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import codecs
from docutils import nodes
from sphinx.application import ExtensionError
from sphinx.domains import Domain
from util import with_app, raises_msg, strip_escseq
from util import strip_escseq
import pytest
@with_app()
def test_events(app, status, warning):
def empty():
pass
raises_msg(ExtensionError, "Unknown event name: invalid",
app.connect, "invalid", empty)
with pytest.raises(ExtensionError) as excinfo:
app.connect("invalid", empty)
assert "Unknown event name: invalid" in str(excinfo.value)
app.add_event("my_event")
raises_msg(ExtensionError, "Event 'my_event' already present",
app.add_event, "my_event")
with pytest.raises(ExtensionError) as excinfo:
app.add_event("my_event")
assert "Event 'my_event' already present" in str(excinfo.value)
def mock_callback(a_app, *args):
assert a_app is app
@ -41,26 +44,22 @@ def test_events(app, status, warning):
"Callback called when disconnected"
@with_app()
def test_emit_with_nonascii_name_node(app, status, warning):
node = nodes.section(names=[u'\u65e5\u672c\u8a9e'])
app.emit('my_event', node)
@with_app()
def test_extensions(app, status, warning):
app.setup_extension('shutil')
assert strip_escseq(warning.getvalue()).startswith("WARNING: extension 'shutil'")
@with_app()
def test_extension_in_blacklist(app, status, warning):
app.setup_extension('sphinxjp.themecore')
msg = strip_escseq(warning.getvalue())
assert msg.startswith("WARNING: the extension 'sphinxjp.themecore' was")
@with_app()
def test_domain_override(app, status, warning):
class A(Domain):
name = 'foo'
@ -72,15 +71,18 @@ def test_domain_override(app, status, warning):
name = 'foo'
# No domain know named foo.
raises_msg(ExtensionError, 'domain foo not yet registered',
app.override_domain, A)
with pytest.raises(ExtensionError) as excinfo:
app.override_domain(A)
assert 'domain foo not yet registered' in str(excinfo.value)
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)
with pytest.raises(ExtensionError) as excinfo:
app.override_domain(C)
assert 'new domain not a subclass of registered foo domain' in str(excinfo.value)
@with_app(testroot='add_source_parser')
@pytest.mark.sphinx(testroot='add_source_parser')
def test_add_source_parser(app, status, warning):
assert set(app.config.source_suffix) == set(['.rst', '.md', '.test'])
assert set(app.config.source_parsers.keys()) == set(['.md', '.test'])
@ -88,7 +90,7 @@ def test_add_source_parser(app, status, warning):
assert app.config.source_parsers['.test'].__name__ == 'TestSourceParser'
@with_app(testroot='add_source_parser-conflicts-with-users-setting')
@pytest.mark.sphinx(testroot='add_source_parser-conflicts-with-users-setting')
def test_add_source_parser_conflicts_with_users_setting(app, status, warning):
assert set(app.config.source_suffix) == set(['.rst', '.test'])
assert set(app.config.source_parsers.keys()) == set(['.test'])

View File

@ -12,7 +12,7 @@
# "raises" imported for usage by autodoc
from util import TestApp, Struct, raises, SkipTest # NOQA
from nose.tools import with_setup, eq_
import pytest
import enum
from six import StringIO, add_metaclass
@ -41,6 +41,7 @@ def teardown_module():
directive = options = None
@pytest.fixture
def setup_test():
global options, directive
global processed_docstrings, processed_signatures, _warnings
@ -74,6 +75,10 @@ def setup_test():
processed_signatures = []
_warnings = []
yield
AutoDirective._special_attrgetters.clear()
_warnings = []
processed_docstrings = []
@ -105,7 +110,7 @@ def skip_member(app, what, name, obj, skip, options):
return True
@with_setup(setup_test)
@pytest.mark.usefixtures('setup_test')
def test_parse_name():
def verify(objtype, name, result):
inst = AutoDirective._registry[objtype](directive, name)
@ -147,7 +152,7 @@ def test_parse_name():
del directive.env.temp_data['autodoc:class']
@with_setup(setup_test)
@pytest.mark.usefixtures('setup_test')
def test_format_signature():
def formatsig(objtype, name, obj, args, retann):
inst = AutoDirective._registry[objtype](directive, name)
@ -253,7 +258,7 @@ def test_format_signature():
'(b, c=42, *d, **e)'
@with_setup(setup_test)
@pytest.mark.usefixtures('setup_test')
def test_get_doc():
def getdocl(objtype, obj, encoding=None):
inst = AutoDirective._registry[objtype](directive, 'tmp')
@ -423,7 +428,7 @@ def test_get_doc():
assert getdocl('class', I) == ['Class docstring', '', 'New docstring']
@with_setup(setup_test)
@pytest.mark.usefixtures('setup_test')
def test_docstring_processing():
def process(objtype, name, obj):
inst = AutoDirective._registry[objtype](directive, name)
@ -478,7 +483,7 @@ def test_docstring_processing():
app.disconnect(lid)
@with_setup(setup_test)
@pytest.mark.usefixtures('setup_test')
def test_docstring_property_processing():
def genarate_docstring(objtype, name, **kw):
del processed_docstrings[:]
@ -515,7 +520,7 @@ def test_docstring_property_processing():
assert 'Second line of docstring' in docstrings
@with_setup(setup_test)
@pytest.mark.usefixtures('setup_test')
def test_new_documenter():
class MyDocumenter(ModuleLevelDocumenter):
objtype = 'integer'
@ -543,7 +548,7 @@ def test_new_documenter():
assert_result_contains('.. py:data:: integer', 'module', 'test_autodoc')
@with_setup(setup_test, AutoDirective._special_attrgetters.clear)
@pytest.mark.usefixtures('setup_test')
def test_attrgetter_using():
def assert_getter_works(objtype, name, obj, attrs=[], **kw):
getattr_spy = []
@ -575,7 +580,7 @@ def test_attrgetter_using():
assert_getter_works('class', 'test_autodoc.Class', Class, ['meth', 'inheritedmeth'])
@with_setup(setup_test)
@pytest.mark.usefixtures('setup_test')
def test_generate():
def assert_warns(warn_str, objtype, name, **kw):
inst = AutoDirective._registry[objtype](directive, name)
@ -1084,7 +1089,7 @@ def test_type_hints():
raise SkipTest('Cannot import Python code with function annotations')
def verify_arg_spec(f, expected):
eq_(formatargspec(f, *getargspec(f)), expected)
assert formatargspec(f, *getargspec(f)) == expected
# Class annotations
verify_arg_spec(f0, '(x: int, y: numbers.Integral) -> None')

View File

@ -9,16 +9,15 @@
:license: BSD, see LICENSE for details.
"""
from six import BytesIO
import pickle
from docutils import nodes
import mock
import pytest
from textwrap import dedent
from sphinx.errors import SphinxError
import sphinx.builders.linkcheck
from util import with_app, with_tempdir, rootdir, tempdir, SkipTest, TestApp, path
from util import rootdir, tempdir, SkipTest, TestApp, path
try:
from docutils.writers.manpage import Writer as ManWriter
@ -77,13 +76,12 @@ def test_build_all():
yield verify_build, buildername, srcdir
@with_tempdir
def test_master_doc_not_found(tmpdir):
(tmpdir / 'conf.py').write_text('master_doc = "index"')
assert tmpdir.listdir() == ['conf.py']
def test_master_doc_not_found(tempdir):
(tempdir / 'conf.py').write_text('master_doc = "index"')
assert tempdir.listdir() == ['conf.py']
try:
app = TestApp(buildername='dummy', srcdir=tmpdir)
app = TestApp(buildername='dummy', srcdir=tempdir)
app.builder.build_all()
assert False # SphinxError not raised
except Exception as exc:
@ -92,7 +90,7 @@ def test_master_doc_not_found(tmpdir):
app.cleanup()
@with_app(buildername='text', testroot='circular')
@pytest.mark.sphinx(buildername='text', testroot='circular')
def test_circular_toctree(app, status, warning):
app.builder.build_all()
warnings = warning.getvalue()
@ -104,7 +102,7 @@ def test_circular_toctree(app, status, warning):
'contents <- sub <- contents') in warnings
@with_app(buildername='text', testroot='numbered-circular')
@pytest.mark.sphinx(buildername='text', testroot='numbered-circular')
def test_numbered_circular_toctree(app, status, warning):
app.builder.build_all()
warnings = warning.getvalue()
@ -116,7 +114,7 @@ def test_numbered_circular_toctree(app, status, warning):
'contents <- sub <- contents') in warnings
@with_app(buildername='dummy', testroot='image-glob')
@pytest.mark.sphinx(buildername='dummy', testroot='image-glob')
def test_image_glob(app, status, warning):
app.builder.build_all()

View File

@ -13,7 +13,7 @@
import plistlib
from util import with_app
import pytest
from path import path
# Use plistlib.load in 3.4 and above
@ -43,9 +43,10 @@ def check_localization(outdir):
assert (lprojdir / 'localized.txt').isfile()
@with_app(buildername='applehelp', testroot='basic', srcdir='applehelp_output',
confoverrides={'applehelp_bundle_id': 'org.sphinx-doc.Sphinx.help',
'applehelp_disable_external_tools': True})
@pytest.mark.sphinx(
'applehelp', testroot='basic', srcdir='applehelp_output',
confoverrides={'applehelp_bundle_id': 'org.sphinx-doc.Sphinx.help',
'applehelp_disable_external_tools': True})
def test_applehelp_output(app, status, warning):
(app.srcdir / 'en.lproj').makedirs()
(app.srcdir / 'en.lproj' / 'localized.txt').write_text('')

View File

@ -15,9 +15,11 @@ import re
import gettext
from subprocess import Popen, PIPE
from nose.tools import assert_true, assert_equal
import pytest
from util import with_app, gen_with_app, SkipTest, assert_in
from util import (
gen_with_app, SkipTest, assert_in, assert_true, assert_equal
)
@gen_with_app('gettext', srcdir='root-gettext')
@ -76,8 +78,9 @@ def test_all(app, status, warning):
yield assert_equal, _("Testing various markup"), u"Testing various markup"
@with_app('gettext', testroot='intl',
confoverrides={'gettext_compact': False})
@pytest.mark.sphinx(
'gettext', testroot='intl', srcdir='gettext',
confoverrides={'gettext_compact': False})
def test_gettext_index_entries(app, status, warning):
# regression test for #976
app.builder.build(['index_entries'])
@ -123,8 +126,9 @@ def test_gettext_index_entries(app, status, warning):
assert msgids == []
@with_app('gettext', testroot='intl',
confoverrides={'gettext_compact': False, 'gettext_additional_targets': []})
@pytest.mark.sphinx(
'gettext', testroot='intl', srcdir='gettext',
confoverrides={'gettext_compact': False, 'gettext_additional_targets': []})
def test_gettext_disable_index_entries(app, status, warning):
# regression test for #976
app.builder.build(['index_entries'])
@ -155,7 +159,7 @@ def test_gettext_disable_index_entries(app, status, warning):
assert msgids == []
@with_app(buildername='gettext', testroot='intl')
@pytest.mark.sphinx('gettext', testroot='intl', srcdir='gettext')
def test_gettext_template(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'sphinx.pot').isfile()

View File

@ -15,19 +15,17 @@ import re
from six import PY3, iteritems
from sphinx import __display_version__
from util import remove_unicode_literals, gen_with_app, with_app, strip_escseq
from util import remove_unicode_literals, gen_with_app, strip_escseq
from etree13 import ElementTree
from html5lib import getTreeBuilder, HTMLParser
import pytest
TREE_BUILDER = getTreeBuilder('etree', implementation=ElementTree)
HTML_PARSER = HTMLParser(TREE_BUILDER, namespaceHTMLElements=False)
ENV_WARNINGS = """\
(%(root)s/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
WARNING: duplicate object description of autodoc_fodder.MarkupError, other \
instance in %(root)s/autodoc.rst, use :noindex: for one of them
)?%(root)s/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
%(root)s/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
WARNING: Explicit markup ends without a blank line; unexpected unindent.
%(root)s/index.rst:\\d+: WARNING: Encoding 'utf-8-sig' used for reading included \
file u'%(root)s/wrongenc.inc' seems to be wrong, try giving an :encoding: option
@ -36,7 +34,7 @@ file u'%(root)s/wrongenc.inc' seems to be wrong, try giving an :encoding: option
%(root)s/index.rst:\\d+: WARNING: download file not readable: %(root)s/nonexisting.png
%(root)s/index.rst:\\d+: WARNING: invalid single index entry u''
%(root)s/undecodable.rst:\\d+: WARNING: undecodable source characters, replacing \
with "\\?": b?'here: >>>(\\\\|/)xbb<<<'
with "\\?": b?'here: >>>(\\\\|/)xbb<<<((\\\\|/)r)?'
"""
HTML_WARNINGS = ENV_WARNINGS + """\
@ -387,7 +385,7 @@ def check_extra_entries(outdir):
assert (outdir / 'robots.txt').isfile()
@with_app(buildername='html', testroot='warnings', freshenv=True)
@pytest.mark.sphinx('html', testroot='warnings', freshenv=True)
def test_html_warnings(app, status, warning):
app.builder.build_all()
html_warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
@ -662,7 +660,7 @@ def test_numfig_without_numbered_toctree(app, status, warning):
yield check_xpath, etree, fname, xpath, check, be_found
@gen_with_app(buildername='html', testroot='numfig',
@gen_with_app(buildername='html', testroot='numfig', srcdir='test_build_html_numfig_on',
confoverrides={'numfig': True})
def test_numfig_with_numbered_toctree(app, status, warning):
app.builder.build_all()
@ -763,6 +761,7 @@ def test_numfig_with_numbered_toctree(app, status, warning):
@gen_with_app(buildername='html', testroot='numfig',
srcdir='test_build_html_numfig_format_warn',
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s',
'table': 'Tab_%s',
@ -867,6 +866,7 @@ def test_numfig_with_prefix(app, status, warning):
@gen_with_app(buildername='html', testroot='numfig',
srcdir='test_build_html_numfig_depth_2',
confoverrides={'numfig': True, 'numfig_secnum_depth': 2})
def test_numfig_with_secnum_depth(app, status, warning):
app.builder.build_all()
@ -967,6 +967,7 @@ def test_numfig_with_secnum_depth(app, status, warning):
@gen_with_app(buildername='singlehtml', testroot='numfig',
srcdir='test_build_html_numfig_on',
confoverrides={'numfig': True})
def test_numfig_with_singlehtml(app, status, warning):
app.builder.build_all()
@ -1084,7 +1085,7 @@ def test_enumerable_node(app, status, warning):
yield check_xpath, etree, fname, xpath, check, be_found
@with_app(buildername='html', testroot='html_assets')
@pytest.mark.sphinx('html', testroot='html_assets')
def test_html_assets(app, status, warning):
app.builder.build_all()
@ -1112,7 +1113,7 @@ def test_html_assets(app, status, warning):
assert not (app.outdir / 'subdir' / '.htpasswd').exists()
@with_app(buildername='html', confoverrides={'html_sourcelink_suffix': ''})
@pytest.mark.sphinx('html', confoverrides={'html_sourcelink_suffix': ''})
def test_html_sourcelink_suffix(app, status, warning):
app.builder.build_all()
content_otherext = (app.outdir / 'otherext.html').text()

View File

@ -12,17 +12,17 @@ from __future__ import print_function
import os
import re
from functools import wraps
from itertools import product
from subprocess import Popen, PIPE
from six import PY3
import pytest
from sphinx.errors import SphinxError
from sphinx.util.osutil import cd, ensuredir
from sphinx.writers.latex import LaTeXTranslator
from util import SkipTest, remove_unicode_literals, with_app, strip_escseq, skip_if
from util import SkipTest, remove_unicode_literals, strip_escseq, skip_if
from test_build_html import ENV_WARNINGS
@ -90,14 +90,13 @@ def skip_if_stylefiles_notfound(testfunc):
return testfunc
def test_latex():
for engine, docclass in product(LATEX_ENGINES, DOCCLASSES):
yield build_latex_doc, engine, docclass
@skip_if_stylefiles_notfound
@with_app(buildername='latex')
def build_latex_doc(app, status, warning, engine, docclass):
@pytest.mark.parametrize(
"engine,docclass",
product(LATEX_ENGINES, DOCCLASSES),
)
@pytest.mark.sphinx('latex')
def test_build_latex_doc(app, status, warning, engine, docclass):
app.config.latex_engine = engine
app.config.latex_documents[0] = app.config.latex_documents[0][:4] + (docclass,)
@ -110,7 +109,7 @@ def build_latex_doc(app, status, warning, engine, docclass):
compile_latex_document(app)
@with_app(buildername='latex')
@pytest.mark.sphinx('latex')
def test_writer(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
@ -138,7 +137,7 @@ def test_writer(app, status, warning):
'\\end{wrapfigure}' in result)
@with_app(buildername='latex', testroot='warnings', freshenv=True)
@pytest.mark.sphinx('latex', testroot='warnings', freshenv=True)
def test_latex_warnings(app, status, warning):
app.builder.build_all()
@ -151,7 +150,7 @@ def test_latex_warnings(app, status, warning):
'--- Got:\n' + warnings
@with_app(buildername='latex', testroot='basic')
@pytest.mark.sphinx('latex', testroot='basic')
def test_latex_title(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
@ -161,7 +160,7 @@ def test_latex_title(app, status, warning):
assert '\\title{The basic Sphinx documentation for testing}' in result
@with_app(buildername='latex', testroot='latex-title')
@pytest.mark.sphinx('latex', testroot='latex-title')
def test_latex_title_after_admonitions(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
@ -171,7 +170,7 @@ def test_latex_title_after_admonitions(app, status, warning):
assert '\\title{test-latex-title}' in result
@with_app(buildername='latex', testroot='numfig',
@pytest.mark.sphinx('latex', testroot='numfig',
confoverrides={'numfig': True})
def test_numref(app, status, warning):
app.builder.build_all()
@ -204,12 +203,13 @@ def test_numref(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
@with_app(buildername='latex', testroot='numfig',
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s',
'table': 'Tab_%s',
'code-block': 'Code-%s',
'section': 'SECTION-%s'}})
@pytest.mark.sphinx(
'latex', testroot='numfig',
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s',
'table': 'Tab_%s',
'code-block': 'Code-%s',
'section': 'SECTION-%s'}})
def test_numref_with_prefix1(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -247,12 +247,13 @@ def test_numref_with_prefix1(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
@with_app(buildername='latex', testroot='numfig',
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s.',
'table': 'Tab_%s:',
'code-block': 'Code-%s | ',
'section': 'SECTION_%s_'}})
@pytest.mark.sphinx(
'latex', testroot='numfig',
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s.',
'table': 'Tab_%s:',
'code-block': 'Code-%s | ',
'section': 'SECTION_%s_'}})
def test_numref_with_prefix2(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -286,8 +287,9 @@ def test_numref_with_prefix2(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
@with_app(buildername='latex', testroot='numfig',
confoverrides={'numfig': True, 'language': 'ja'})
@pytest.mark.sphinx(
'latex', testroot='numfig',
confoverrides={'numfig': True, 'language': 'ja'})
def test_numref_with_language_ja(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -319,7 +321,7 @@ def test_numref_with_language_ja(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
@with_app(buildername='latex')
@pytest.mark.sphinx('latex')
def test_latex_add_latex_package(app, status, warning):
app.add_latex_package('foo')
app.add_latex_package('bar', 'baz')
@ -329,7 +331,7 @@ def test_latex_add_latex_package(app, status, warning):
assert '\\usepackage[baz]{bar}' in result
@with_app(buildername='latex', testroot='latex-babel')
@pytest.mark.sphinx('latex', testroot='latex-babel')
def test_babel_with_no_language_settings(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -348,8 +350,9 @@ def test_babel_with_no_language_settings(app, status, warning):
assert '\\shorthandoff' not in result
@with_app(buildername='latex', testroot='latex-babel',
confoverrides={'language': 'de'})
@pytest.mark.sphinx(
'latex', testroot='latex-babel',
confoverrides={'language': 'de'})
def test_babel_with_language_de(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -368,8 +371,9 @@ def test_babel_with_language_de(app, status, warning):
assert '\\shorthandoff{"}' in result
@with_app(buildername='latex', testroot='latex-babel',
confoverrides={'language': 'ru'})
@pytest.mark.sphinx(
'latex', testroot='latex-babel',
confoverrides={'language': 'ru'})
def test_babel_with_language_ru(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -389,8 +393,9 @@ def test_babel_with_language_ru(app, status, warning):
assert '\\shorthandoff' not in result
@with_app(buildername='latex', testroot='latex-babel',
confoverrides={'language': 'tr'})
@pytest.mark.sphinx(
'latex', testroot='latex-babel',
confoverrides={'language': 'tr'})
def test_babel_with_language_tr(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -409,8 +414,9 @@ def test_babel_with_language_tr(app, status, warning):
assert '\\shorthandoff{=}' in result
@with_app(buildername='latex', testroot='latex-babel',
confoverrides={'language': 'ja'})
@pytest.mark.sphinx(
'latex', testroot='latex-babel',
confoverrides={'language': 'ja'})
def test_babel_with_language_ja(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -428,8 +434,9 @@ def test_babel_with_language_ja(app, status, warning):
assert '\\shorthandoff' not in result
@with_app(buildername='latex', testroot='latex-babel',
confoverrides={'language': 'unknown'})
@pytest.mark.sphinx(
'latex', testroot='latex-babel',
confoverrides={'language': 'unknown'})
def test_babel_with_unknown_language(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -450,7 +457,7 @@ def test_babel_with_unknown_language(app, status, warning):
assert "WARNING: no Babel option known for language 'unknown'" in warning.getvalue()
@with_app(buildername='latex')
@pytest.mark.sphinx('latex')
def test_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
@ -480,7 +487,7 @@ def test_footnote(app, status, warning):
'footnotes in table\n%\n\\end{footnotetext}') in result
@with_app(buildername='latex', testroot='footnotes')
@pytest.mark.sphinx('latex', testroot='footnotes')
def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -517,8 +524,9 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
assert '\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]' in result
@with_app(buildername='latex', testroot='footnotes',
confoverrides={'latex_show_urls': 'inline'})
@pytest.mark.sphinx(
'latex', testroot='footnotes',
confoverrides={'latex_show_urls': 'inline'})
def test_latex_show_urls_is_inline(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -560,8 +568,9 @@ def test_latex_show_urls_is_inline(app, status, warning):
'{sphinx-dev@googlegroups.com}') in result
@with_app(buildername='latex', testroot='footnotes',
confoverrides={'latex_show_urls': 'footnote'})
@pytest.mark.sphinx(
'latex', testroot='footnotes',
confoverrides={'latex_show_urls': 'footnote'})
def test_latex_show_urls_is_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -611,8 +620,9 @@ def test_latex_show_urls_is_footnote(app, status, warning):
'{sphinx-dev@googlegroups.com}\n') in result
@with_app(buildername='latex', testroot='footnotes',
confoverrides={'latex_show_urls': 'no'})
@pytest.mark.sphinx(
'latex', testroot='footnotes',
confoverrides={'latex_show_urls': 'no'})
def test_latex_show_urls_is_no(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -652,7 +662,7 @@ def test_latex_show_urls_is_no(app, status, warning):
'{sphinx-dev@googlegroups.com}\n') in result
@with_app(buildername='latex', testroot='image-in-section')
@pytest.mark.sphinx('latex', testroot='image-in-section')
def test_image_in_section(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -668,7 +678,7 @@ def test_image_in_section(app, status, warning):
assert ('\\chapter{Another section}' in result)
@with_app(buildername='latex', confoverrides={'latex_logo': 'notfound.jpg'})
@pytest.mark.sphinx('latex', confoverrides={'latex_logo': 'notfound.jpg'})
def test_latex_logo_if_not_found(app, status, warning):
try:
app.builder.build_all()
@ -677,7 +687,7 @@ def test_latex_logo_if_not_found(app, status, warning):
assert isinstance(exc, SphinxError)
@with_app(buildername='latex', testroot='toctree-maxdepth',
@pytest.mark.sphinx('latex', testroot='toctree-maxdepth',
confoverrides={'latex_documents': [
('index', 'SphinxTests.tex', 'Sphinx Tests Documentation',
'Georg Brandl', 'manual'),
@ -692,11 +702,12 @@ def test_toctree_maxdepth_manual(app, status, warning):
assert '\\setcounter{secnumdepth}' not in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'latex_documents': [
('index', 'SphinxTests.tex', 'Sphinx Tests Documentation',
'Georg Brandl', 'howto'),
]})
@pytest.mark.sphinx(
'latex', testroot='toctree-maxdepth',
confoverrides={'latex_documents': [
('index', 'SphinxTests.tex', 'Sphinx Tests Documentation',
'Georg Brandl', 'howto'),
]})
def test_toctree_maxdepth_howto(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
@ -707,8 +718,9 @@ def test_toctree_maxdepth_howto(app, status, warning):
assert '\\setcounter{secnumdepth}' not in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'master_doc': 'foo'})
@pytest.mark.sphinx(
'latex', testroot='toctree-maxdepth',
confoverrides={'master_doc': 'foo'})
def test_toctree_not_found(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -719,8 +731,9 @@ def test_toctree_not_found(app, status, warning):
assert '\\setcounter{secnumdepth}' not in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'master_doc': 'bar'})
@pytest.mark.sphinx(
'latex', testroot='toctree-maxdepth',
confoverrides={'master_doc': 'bar'})
def test_toctree_without_maxdepth(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -731,8 +744,9 @@ def test_toctree_without_maxdepth(app, status, warning):
assert '\\setcounter{secnumdepth}' not in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'master_doc': 'qux'})
@pytest.mark.sphinx(
'latex', testroot='toctree-maxdepth',
confoverrides={'master_doc': 'qux'})
def test_toctree_with_deeper_maxdepth(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -743,8 +757,9 @@ def test_toctree_with_deeper_maxdepth(app, status, warning):
assert '\\setcounter{secnumdepth}{3}' in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'latex_toplevel_sectioning': None})
@pytest.mark.sphinx(
'latex', testroot='toctree-maxdepth',
confoverrides={'latex_toplevel_sectioning': None})
def test_latex_toplevel_sectioning_is_None(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -754,8 +769,9 @@ def test_latex_toplevel_sectioning_is_None(app, status, warning):
assert '\\chapter{Foo}' in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'latex_toplevel_sectioning': 'part'})
@pytest.mark.sphinx(
'latex', testroot='toctree-maxdepth',
confoverrides={'latex_toplevel_sectioning': 'part'})
def test_latex_toplevel_sectioning_is_part(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -765,8 +781,9 @@ def test_latex_toplevel_sectioning_is_part(app, status, warning):
assert '\\part{Foo}' in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'latex_toplevel_sectioning': 'chapter'})
@pytest.mark.sphinx(
'latex', testroot='toctree-maxdepth',
confoverrides={'latex_toplevel_sectioning': 'chapter'})
def test_latex_toplevel_sectioning_is_chapter(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -776,8 +793,9 @@ def test_latex_toplevel_sectioning_is_chapter(app, status, warning):
assert '\\chapter{Foo}' in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'latex_toplevel_sectioning': 'section'})
@pytest.mark.sphinx(
'latex', testroot='toctree-maxdepth',
confoverrides={'latex_toplevel_sectioning': 'section'})
def test_latex_toplevel_sectioning_is_section(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@ -787,7 +805,7 @@ def test_latex_toplevel_sectioning_is_section(app, status, warning):
assert '\\section{Foo}' in result
@skip_if_stylefiles_notfound
@with_app(buildername='latex', testroot='maxlistdepth')
@pytest.mark.sphinx('latex', testroot='maxlistdepth')
def test_maxlistdepth_at_ten(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')

View File

@ -10,10 +10,10 @@
"""
from __future__ import print_function
from util import with_app
import pytest
@with_app('linkcheck', testroot='linkcheck', freshenv=True)
@pytest.mark.sphinx('linkcheck', testroot='linkcheck', freshenv=True)
def test_defaults(app, status, warning):
app.builder.build_all()
@ -26,8 +26,9 @@ def test_defaults(app, status, warning):
assert len(content.splitlines()) == 1
@with_app('linkcheck', testroot='linkcheck', freshenv=True,
confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"]})
@pytest.mark.sphinx(
'linkcheck', testroot='linkcheck', freshenv=True,
confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"]})
def test_anchors_ignored(app, status, warning):
app.builder.build_all()

View File

@ -10,10 +10,10 @@
"""
from __future__ import print_function
from util import with_app
import pytest
@with_app(buildername='man')
@pytest.mark.sphinx('man')
def test_all(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'SphinxTests.1').exists()

View File

@ -15,10 +15,11 @@ import re
from subprocess import Popen, PIPE
from six import PY3
import pytest
from sphinx.writers.texinfo import TexinfoTranslator
from util import SkipTest, remove_unicode_literals, with_app, strip_escseq
from util import SkipTest, remove_unicode_literals, strip_escseq
from test_build_html import ENV_WARNINGS
@ -33,7 +34,7 @@ if PY3:
TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
@with_app(buildername='texinfo', testroot='warnings', freshenv=True)
@pytest.mark.sphinx('texinfo', testroot='warnings', freshenv=True)
def test_texinfo_warnings(app, status, warning):
app.builder.build_all()
warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
@ -45,7 +46,7 @@ def test_texinfo_warnings(app, status, warning):
'--- Got:\n' + warnings
@with_app(buildername='texinfo')
@pytest.mark.sphinx('texinfo')
def test_texinfo(app, status, warning):
TexinfoTranslator.ignore_missing_images = True
app.builder.build_all()

View File

@ -10,15 +10,16 @@
"""
import shutil
from nose.tools import with_setup
import pytest
from util import with_app, find_files, rootdir, tempdir
from util import find_files, rootdir, tempdir
root = tempdir / 'test-intl'
build_dir = root / '_build'
locale_dir = build_dir / 'locale'
@pytest.fixture
def setup_test():
# delete remnants left over after failed build
root.rmtree(True)
@ -30,14 +31,15 @@ def setup_test():
copy_po.parent.makedirs()
shutil.copy(root / po, copy_po)
yield
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]})
@pytest.mark.usefixtures('setup_test')
@pytest.mark.sphinx(
'html', testroot='intl',
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
def test_compile_all_catalogs(app, status, warning):
app.builder.compile_all_catalogs()
@ -51,9 +53,10 @@ def test_compile_all_catalogs(app, status, warning):
assert actual == expect
@with_setup(setup_test, teardown_test)
@with_app(buildername='html', testroot='intl',
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
@pytest.mark.usefixtures('setup_test')
@pytest.mark.sphinx(
'html', testroot='intl',
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
def test_compile_specific_catalogs(app, status, warning):
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
@ -66,9 +69,10 @@ def test_compile_specific_catalogs(app, status, warning):
assert actual == set(['admonitions.mo'])
@with_setup(setup_test, teardown_test)
@with_app(buildername='html', testroot='intl',
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
@pytest.mark.usefixtures('setup_test')
@pytest.mark.sphinx(
'html', testroot='intl',
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
def test_compile_update_catalogs(app, status, warning):
app.builder.compile_update_catalogs()

View File

@ -10,19 +10,22 @@
:license: BSD, see LICENSE for details.
"""
from six import PY3, iteritems
import pytest
import mock
from util import TestApp, with_app, gen_with_app, with_tempdir, \
raises, raises_msg, assert_in, assert_not_in
from util import TestApp, gen_with_app, \
assert_in, assert_not_in
import sphinx
from sphinx.config import Config
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'})
@pytest.mark.sphinx(confoverrides={
'master_doc': 'master',
'nonexisting_value': 'True',
'latex_elements.docclass': 'scrartcl',
'modindex_common_prefix': 'path1,path2'})
def test_core_config(app, status, warning):
cfg = app.config
@ -55,11 +58,14 @@ def test_core_config(app, status, warning):
assert 'nonexisting_value' not in cfg
# invalid values
raises(AttributeError, getattr, cfg, '_value')
raises(AttributeError, getattr, cfg, 'nonexisting_value')
with pytest.raises(AttributeError):
getattr(cfg, '_value')
with pytest.raises(AttributeError):
getattr(cfg, 'nonexisting_value')
# non-value attributes are deleted from the namespace
raises(AttributeError, getattr, cfg, 'sys')
with pytest.raises(AttributeError):
getattr(cfg, 'sys')
# setting attributes
cfg.project = 'Foo'
@ -70,7 +76,7 @@ def test_core_config(app, status, warning):
assert cfg['project'] == cfg.project == 'Sphinx Tests'
@with_app()
@pytest.mark.sphinx()
def test_extension_values(app, status, warning):
cfg = app.config
@ -80,24 +86,27 @@ def test_extension_values(app, status, warning):
assert cfg.value_from_conf_py == 84
# no duplicate values allowed
raises_msg(ExtensionError, 'already present', app.add_config_value,
'html_title', 'x', True)
raises_msg(ExtensionError, 'already present', app.add_config_value,
'value_from_ext', 'x', True)
with pytest.raises(ExtensionError) as excinfo:
app.add_config_value('html_title', 'x', True)
assert 'already present' in str(excinfo.value)
with pytest.raises(ExtensionError) as excinfo:
app.add_config_value('value_from_ext', 'x', True)
assert 'already present' in str(excinfo.value)
@with_tempdir
@mock.patch("sphinx.config.logger")
def test_errors_warnings(dir, logger):
def test_errors_warnings(logger, tempdir):
# test the error for syntax errors in the config file
(dir / 'conf.py').write_text(u'project = \n', encoding='ascii')
raises_msg(ConfigError, 'conf.py', Config, dir, 'conf.py', {}, None)
(tempdir / 'conf.py').write_text(u'project = \n', encoding='ascii')
with pytest.raises(ConfigError) as excinfo:
Config(tempdir, 'conf.py', {}, None)
assert 'conf.py' in str(excinfo.value)
# test the automatic conversion of 2.x only code in configs
(dir / 'conf.py').write_text(
(tempdir / 'conf.py').write_text(
u'# -*- coding: utf-8\n\nproject = u"Jägermeister"\n',
encoding='utf-8')
cfg = Config(dir, 'conf.py', {}, None)
cfg = Config(tempdir, 'conf.py', {}, None)
cfg.init_values()
assert cfg.project == u'Jägermeister'
assert logger.called is False
@ -107,20 +116,21 @@ def test_errors_warnings(dir, logger):
# skip the test there
if PY3:
return
(dir / 'conf.py').write_text(
(tempdir / 'conf.py').write_text(
u'# -*- coding: latin-1\nproject = "fooä"\n', encoding='latin-1')
cfg = Config(dir, 'conf.py', {}, None)
cfg = Config(tempdir, 'conf.py', {}, None)
assert logger.warning.called is False
cfg.check_unicode()
assert logger.warning.called is True
@with_tempdir
def test_errors_if_setup_is_not_callable(dir):
def test_errors_if_setup_is_not_callable(tempdir):
# test the error to call setup() in the config file
(dir / 'conf.py').write_text(u'setup = 1')
raises_msg(ConfigError, 'callable', TestApp, srcdir=dir)
(tempdir / 'conf.py').write_text(u'setup = 1')
with pytest.raises(ConfigError) as excinfo:
TestApp(srcdir=tempdir)
assert 'callable' in str(excinfo.value)
@mock.patch.object(sphinx, '__display_version__', '1.3.4')
@ -130,40 +140,39 @@ def test_needs_sphinx():
app.cleanup()
app = TestApp(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
app.cleanup()
raises(VersionRequirementError, TestApp,
confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
with pytest.raises(VersionRequirementError):
TestApp(confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
# minor version
app = TestApp(confoverrides={'needs_sphinx': '1.2'}) # OK: less
app.cleanup()
app = TestApp(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
app.cleanup()
raises(VersionRequirementError, TestApp,
confoverrides={'needs_sphinx': '1.4'}) # NG: greater
with pytest.raises(VersionRequirementError):
TestApp(confoverrides={'needs_sphinx': '1.4'}) # NG: greater
# major version
app = TestApp(confoverrides={'needs_sphinx': '0'}) # OK: less
app.cleanup()
app = TestApp(confoverrides={'needs_sphinx': '1'}) # OK: equals
app.cleanup()
raises(VersionRequirementError, TestApp,
confoverrides={'needs_sphinx': '2'}) # NG: greater
with pytest.raises(VersionRequirementError):
TestApp(confoverrides={'needs_sphinx': '2'}) # NG: greater
@with_tempdir
@mock.patch("sphinx.config.logger")
def test_config_eol(tmpdir, logger):
def test_config_eol(logger, tempdir):
# test config file's eol patterns: LF, CRLF
configfile = tmpdir / 'conf.py'
configfile = tempdir / 'conf.py'
for eol in (b'\n', b'\r\n'):
configfile.write_bytes(b'project = "spam"' + eol)
cfg = Config(tmpdir, 'conf.py', {}, None)
cfg = Config(tempdir, 'conf.py', {}, None)
cfg.init_values()
assert cfg.project == u'spam'
assert logger.called is False
@with_app(confoverrides={'master_doc': 123,
@pytest.mark.sphinx(confoverrides={'master_doc': 123,
'language': 'foo',
'primary_domain': None})
def test_builtin_conf(app, status, warning):
@ -209,13 +218,13 @@ def test_gen_check_types(app, status, warning):
)
@with_app(testroot='config')
@pytest.mark.sphinx(testroot='config')
def test_check_enum(app, status, warning):
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
not in warning.getvalue()
@with_app(testroot='config', confoverrides={'value17': 'invalid'})
@pytest.mark.sphinx(testroot='config', confoverrides={'value17': 'invalid'})
def test_check_enum_failed(app, status, warning):
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
"but `invalid` is given." in warning.getvalue()

View File

@ -9,10 +9,12 @@
:license: BSD, see LICENSE for details.
"""
from util import with_app, etree_parse
import pytest
from util import etree_parse
@with_app('xml', testroot='directive-code')
@pytest.mark.sphinx('xml', testroot='directive-code')
def test_code_block(app, status, warning):
app.builder.build('index')
et = etree_parse(app.outdir / 'index.xml')
@ -28,7 +30,7 @@ def test_code_block(app, status, warning):
assert actual == expect
@with_app('xml', testroot='directive-code')
@pytest.mark.sphinx('xml', testroot='directive-code')
def test_code_block_dedent(app, status, warning):
app.builder.build(['dedent_code'])
et = etree_parse(app.outdir / 'dedent_code.xml')
@ -47,7 +49,7 @@ def test_code_block_dedent(app, status, warning):
assert blocks[5].text == '\n\n' # dedent: 1000
@with_app('html', testroot='directive-code')
@pytest.mark.sphinx('html', testroot='directive-code')
def test_code_block_caption_html(app, status, warning):
app.builder.build(['caption'])
html = (app.outdir / 'caption.html').text(encoding='utf-8')
@ -59,7 +61,7 @@ def test_code_block_caption_html(app, status, warning):
assert caption in html
@with_app('latex', testroot='directive-code')
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_code_block_caption_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
@ -72,7 +74,7 @@ def test_code_block_caption_latex(app, status, warning):
assert link in latex
@with_app('latex', testroot='directive-code')
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_code_block_namedlink_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
@ -89,7 +91,7 @@ def test_code_block_namedlink_latex(app, status, warning):
assert link2 in latex
@with_app('xml', testroot='directive-code')
@pytest.mark.sphinx('xml', testroot='directive-code')
def test_literal_include(app, status, warning):
app.builder.build(['index'])
et = etree_parse(app.outdir / 'index.xml')
@ -101,7 +103,7 @@ def test_literal_include(app, status, warning):
assert actual == literal_src
@with_app('xml', testroot='directive-code')
@pytest.mark.sphinx('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]]
@ -119,7 +121,7 @@ def test_literal_include_dedent(app, status, warning):
assert blocks[5].text == '\n\n' # dedent: 1000
@with_app('xml', testroot='directive-code')
@pytest.mark.sphinx('xml', testroot='directive-code')
def test_literal_include_block_start_with_comment_or_brank(app, status, warning):
app.builder.build(['python'])
et = etree_parse(app.outdir / 'python.xml')
@ -143,7 +145,7 @@ def test_literal_include_block_start_with_comment_or_brank(app, status, warning)
assert actual == expect
@with_app('html', testroot='directive-code')
@pytest.mark.sphinx('html', testroot='directive-code')
def test_literal_include_linenos(app, status, warning):
app.builder.build(['linenos'])
html = (app.outdir / 'linenos.html').text(encoding='utf-8')
@ -166,7 +168,7 @@ def test_literal_include_linenos(app, status, warning):
assert linenos in html
@with_app('html', testroot='directive-code')
@pytest.mark.sphinx('html', testroot='directive-code')
def test_literal_include_lineno_start(app, status, warning):
app.builder.build(['lineno_start'])
html = (app.outdir / 'lineno_start.html').text(encoding='utf-8')
@ -189,7 +191,7 @@ def test_literal_include_lineno_start(app, status, warning):
assert linenos in html
@with_app('html', testroot='directive-code')
@pytest.mark.sphinx('html', testroot='directive-code')
def test_literal_include_lineno_match(app, status, warning):
app.builder.build(['lineno_match'])
html = (app.outdir / 'lineno_match.html').text(encoding='utf-8')
@ -229,7 +231,7 @@ def test_literal_include_lineno_match(app, status, warning):
assert start_at_end_at in html
@with_app('latex', testroot='directive-code')
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_file_whole_of_emptyline(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8').replace('\r\n', '\n')
@ -243,7 +245,7 @@ def test_literalinclude_file_whole_of_emptyline(app, status, warning):
assert includes in latex
@with_app('html', testroot='directive-code')
@pytest.mark.sphinx('html', testroot='directive-code')
def test_literalinclude_caption_html(app, status, warning):
app.builder.build('index')
html = (app.outdir / 'caption.html').text(encoding='utf-8')
@ -255,7 +257,7 @@ def test_literalinclude_caption_html(app, status, warning):
assert caption in html
@with_app('latex', testroot='directive-code')
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_caption_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
@ -268,7 +270,7 @@ def test_literalinclude_caption_latex(app, status, warning):
assert link in latex
@with_app('latex', testroot='directive-code')
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_namedlink_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
@ -285,7 +287,7 @@ def test_literalinclude_namedlink_latex(app, status, warning):
assert link2 in latex
@with_app('xml', testroot='directive-code')
@pytest.mark.sphinx('xml', testroot='directive-code')
def test_literalinclude_classes(app, status, warning):
app.builder.build(['classes'])
et = etree_parse(app.outdir / 'classes.xml')

View File

@ -13,11 +13,10 @@ import re
from docutils import nodes
from sphinx.util.nodes import process_only_nodes
from util import with_app
import pytest
@with_app('text', testroot='directive-only')
@pytest.mark.sphinx('text', testroot='directive-only')
def test_sectioning(app, status, warning):
def getsects(section):

View File

@ -11,14 +11,15 @@
import re
from util import with_app, path, SkipTest
import pytest
from util import path, SkipTest
def regex_count(expr, result):
return len(re.findall(expr, result))
@with_app('html', testroot='docutilsconf', freshenv=True, docutilsconf='')
@pytest.mark.sphinx('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')
@ -29,7 +30,7 @@ def test_html_with_default_docutilsconf(app, status, warning):
assert regex_count(r'<td class="option-group" colspan="2">', result) == 1
@with_app('html', testroot='docutilsconf', freshenv=True, docutilsconf=(
@pytest.mark.sphinx('html', testroot='docutilsconf', freshenv=True, docutilsconf=(
'\n[html4css1 writer]'
'\noption-limit:1'
'\nfield-name-limit:1'
@ -45,31 +46,31 @@ def test_html_with_docutilsconf(app, status, warning):
assert regex_count(r'<td class="option-group" colspan="2">', result) == 2
@with_app('html', testroot='docutilsconf')
@pytest.mark.sphinx('html', testroot='docutilsconf')
def test_html(app, status, warning):
app.builder.build(['contents'])
assert warning.getvalue() == ''
@with_app('latex', testroot='docutilsconf')
@pytest.mark.sphinx('latex', testroot='docutilsconf')
def test_latex(app, status, warning):
app.builder.build(['contents'])
assert warning.getvalue() == ''
@with_app('man', testroot='docutilsconf')
@pytest.mark.sphinx('man', testroot='docutilsconf')
def test_man(app, status, warning):
app.builder.build(['contents'])
assert warning.getvalue() == ''
@with_app('texinfo', testroot='docutilsconf')
@pytest.mark.sphinx('texinfo', testroot='docutilsconf')
def test_texinfo(app, status, warning):
app.builder.build(['contents'])
@with_app('html', testroot='docutilsconf',
docutilsconf='[general]\nsource_link=true\n')
@pytest.mark.sphinx('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'

View File

@ -12,8 +12,7 @@
import re
from six import text_type
from util import raises, with_app
import pytest
from sphinx import addnodes
from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError
@ -150,9 +149,10 @@ def test_concept_definitions():
None, 'I0EN1A1B7ConceptE')
check('concept', 'template<typename A, typename B, typename ...C> Foo()',
None, 'I00DpE3Foo')
raises(DefinitionError, parse, 'concept', 'Foo')
raises(DefinitionError, parse, 'concept',
'template<typename T> template<typename U> Foo')
with pytest.raises(DefinitionError):
parse('concept', 'Foo')
with pytest.raises(DefinitionError):
parse('concept', 'template<typename T> template<typename U> Foo')
def test_member_definitions():
@ -259,9 +259,12 @@ def test_function_definitions():
'int foo(Foo f = Foo(double(), std::make_pair(int(2), double(3.4))))',
"foo__Foo", "3foo3Foo")
check('function', 'int foo(A a = x(a))', "foo__A", "3foo1A")
raises(DefinitionError, parse, 'function', 'int foo(B b=x(a)')
raises(DefinitionError, parse, 'function', 'int foo)C c=x(a))')
raises(DefinitionError, parse, 'function', 'int foo(D d=x(a')
with pytest.raises(DefinitionError):
parse('function', 'int foo(B b=x(a)')
with pytest.raises(DefinitionError):
parse('function', 'int foo)C c=x(a))')
with pytest.raises(DefinitionError):
parse('function', 'int foo(D d=x(a')
check('function', 'int foo(const A&... a)', "foo__ACRDp", "3fooDpRK1A")
check('function', 'virtual void f()', "f", "1fv")
# test for ::nestedName, from issue 1738
@ -382,8 +385,10 @@ def test_templates():
check('function', "template<> void A()", None, "IE1Av")
check('member', "template<> A a", None, "IE1a")
check('type', "template<> a = A", None, "IE1a")
raises(DefinitionError, parse, 'enum', "template<> A")
raises(DefinitionError, parse, 'enumerator', "template<> A")
with pytest.raises(DefinitionError):
parse('enum', "template<> A")
with pytest.raises(DefinitionError):
parse('enumerator', "template<> A")
# then all the real tests
check('class', "template<typename T1, typename T2> A", None, "I00E1A")
check('type', "template<> a", None, "IE1a")
@ -419,8 +424,10 @@ def test_templates():
"RK18c_string_view_baseIK4Char6TraitsE")
# template introductions
raises(DefinitionError, parse, 'enum', 'abc::ns::foo{id_0, id_1, id_2} A')
raises(DefinitionError, parse, 'enumerator', 'abc::ns::foo{id_0, id_1, id_2} A')
with pytest.raises(DefinitionError):
parse('enum', 'abc::ns::foo{id_0, id_1, id_2} A')
with pytest.raises(DefinitionError):
parse('enumerator', 'abc::ns::foo{id_0, id_1, id_2} A')
check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar',
None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE')
check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar',
@ -469,12 +476,18 @@ def test_attributes():
check('member', 'paren_attr(a) int f', 'f__i', '1f')
check('member', 'paren_attr("") int f', 'f__i', '1f')
check('member', 'paren_attr(()[{}][]{}) int f', 'f__i', '1f')
raises(DefinitionError, parse, 'member', 'paren_attr(() int f')
raises(DefinitionError, parse, 'member', 'paren_attr([) int f')
raises(DefinitionError, parse, 'member', 'paren_attr({) int f')
raises(DefinitionError, parse, 'member', 'paren_attr([)]) int f')
raises(DefinitionError, parse, 'member', 'paren_attr((])) int f')
raises(DefinitionError, parse, 'member', 'paren_attr({]}) int f')
with pytest.raises(DefinitionError):
parse('member', 'paren_attr(() int f')
with pytest.raises(DefinitionError):
parse('member', 'paren_attr([) int f')
with pytest.raises(DefinitionError):
parse('member', 'paren_attr({) int f')
with pytest.raises(DefinitionError):
parse('member', 'paren_attr([)]) int f')
with pytest.raises(DefinitionError):
parse('member', 'paren_attr((])) int f')
with pytest.raises(DefinitionError):
parse('member', 'paren_attr({]}) int f')
# position: decl specs
check('function', 'static inline __attribute__(()) void f()',
@ -490,7 +503,7 @@ def test_attributes():
# raise DefinitionError("")
@with_app(testroot='domain-cpp', confoverrides={'add_function_parentheses': True})
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'add_function_parentheses': True})
def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, warning):
app.builder.build_all()
@ -527,7 +540,8 @@ def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, war
check(s, t, f)
@with_app(testroot='domain-cpp', confoverrides={'add_function_parentheses': False})
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={
'add_function_parentheses': False})
def test_build_domain_cpp_with_add_function_parentheses_is_False(app, status, warning):
app.builder.build_all()

View File

@ -14,8 +14,9 @@ from docutils.nodes import bullet_list, list_item, caption, comment, reference
from sphinx import addnodes
from sphinx.addnodes import compact_paragraph, only
from sphinx.builders.html import StandaloneHTMLBuilder
import pytest
from util import with_app, gen_with_app, assert_node
from util import gen_with_app, assert_node
@gen_with_app('xml', testroot='toctree')
@ -97,7 +98,7 @@ def _test_process_doc(app):
assert 'qux' not in app.env.toctree_includes
@with_app('dummy', testroot='toctree-glob')
@pytest.mark.sphinx('dummy', testroot='toctree-glob')
def test_glob(app, status, warning):
includefiles = ['foo', 'bar/index', 'bar/bar_1', 'bar/bar_2',
'bar/bar_3', 'baz', 'qux/index']

View File

@ -10,12 +10,11 @@
"""
import pickle
from docutils import nodes
import pytest
from sphinx import addnodes
from util import with_app
@with_app(buildername='dummy', testroot='ext-autodoc')
@pytest.mark.sphinx('dummy', testroot='ext-autodoc')
def test_autodoc(app, status, warning):
app.builder.build_all()

View File

@ -11,10 +11,10 @@
import re
from util import with_app
import pytest
@with_app('html', testroot='ext-autosectionlabel')
@pytest.mark.sphinx('html', testroot='ext-autosectionlabel')
def test_autosectionlabel_html(app, status, warning):
app.builder.build_all()

View File

@ -13,7 +13,7 @@ from six import iteritems, StringIO
from sphinx.ext.autosummary import mangle_signature
from util import with_app
import pytest
html_warnfile = StringIO()
@ -54,7 +54,7 @@ def test_mangle_signature():
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
@with_app(buildername='dummy', **default_kw)
@pytest.mark.sphinx('dummy', **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..

View File

@ -11,10 +11,10 @@
import pickle
from util import with_app
import pytest
@with_app(buildername='coverage')
@pytest.mark.sphinx('coverage')
def test_build(app, status, warning):
app.builder.build_all()

View File

@ -8,13 +8,12 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from util import with_app
import pytest
cleanup_called = 0
@with_app(buildername='doctest', testroot='doctest')
@pytest.mark.sphinx('doctest', testroot='doctest')
def test_build(app, status, warning):
global cleanup_called
cleanup_called = 0

View File

@ -9,10 +9,10 @@
:license: BSD, see LICENSE for details.
"""
from util import with_app
import pytest
@with_app('html', testroot='ext-githubpages')
@pytest.mark.sphinx('html', testroot='ext-githubpages')
def test_githubpages(app, status, warning):
app.builder.build_all()
assert (app.outdir / '.nojekyll').exists()

View File

@ -10,37 +10,12 @@
"""
import re
import subprocess
from functools import wraps
from util import with_app, SkipTest
import pytest
def skip_if_graphviz_not_found(fn):
@wraps(fn)
def decorator(app, *args, **kwargs):
found = False
graphviz_dot = getattr(app.config, 'graphviz_dot', '')
try:
if graphviz_dot:
dot = subprocess.Popen([graphviz_dot, '-V'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE) # show version
dot.communicate()
found = True
except OSError: # No such file or directory
pass
if not found:
raise SkipTest('graphviz "dot" is not available')
return fn(app, *args, **kwargs)
return decorator
@with_app('html', testroot='ext-graphviz')
@skip_if_graphviz_not_found
@pytest.mark.sphinx('html', testroot='ext-graphviz')
@pytest.mark.usefixtures('if_graphviz_found')
def test_graphviz_html(app, status, warning):
app.builder.build_all()
@ -60,8 +35,8 @@ def test_graphviz_html(app, status, warning):
assert re.search(html, content, re.S)
@with_app('latex', testroot='ext-graphviz')
@skip_if_graphviz_not_found
@pytest.mark.sphinx('latex', testroot='ext-graphviz')
@pytest.mark.usefixtures('if_graphviz_found')
def test_graphviz_latex(app, status, warning):
app.builder.build_all()
@ -80,8 +55,8 @@ def test_graphviz_latex(app, status, warning):
assert re.search(macro, content, re.S)
@with_app('html', testroot='ext-graphviz', confoverrides={'language': 'xx'})
@skip_if_graphviz_not_found
@pytest.mark.sphinx('html', testroot='ext-graphviz', confoverrides={'language': 'xx'})
@pytest.mark.usefixtures('if_graphviz_found')
def test_graphviz_i18n(app, status, warning):
app.builder.build_all()

View File

@ -9,10 +9,10 @@
:license: BSD, see LICENSE for details.
"""
from util import with_app
import pytest
@with_app(buildername='text', testroot='ext-ifconfig')
@pytest.mark.sphinx('text', testroot='ext-ifconfig')
def test_ifconfig(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'index.txt').text()

View File

@ -11,13 +11,13 @@
import re
import sys
from util import with_app, rootdir, raises
from test_ext_graphviz import skip_if_graphviz_not_found
from util import rootdir
from sphinx.ext.inheritance_diagram import InheritanceException, import_classes
import pytest
@with_app('html', testroot='ext-inheritance_diagram')
@skip_if_graphviz_not_found
@pytest.mark.sphinx('html', testroot='ext-inheritance_diagram')
@pytest.mark.usefixtures('if_graphviz_found')
def test_inheritance_diagram_html(app, status, warning):
app.builder.build_all()
@ -31,8 +31,8 @@ def test_inheritance_diagram_html(app, status, warning):
assert re.search(pattern, content, re.M)
@with_app('latex', testroot='ext-inheritance_diagram')
@skip_if_graphviz_not_found
@pytest.mark.sphinx('latex', testroot='ext-inheritance_diagram')
@pytest.mark.usefixtures('if_graphviz_found')
def test_inheritance_diagram_latex(app, status, warning):
app.builder.build_all()
@ -53,8 +53,10 @@ def test_import_classes():
from example.sphinx import DummyClass
# got exception for unknown class or module
raises(InheritanceException, import_classes, 'unknown', None)
raises(InheritanceException, import_classes, 'unknown.Unknown', None)
with pytest.raises(InheritanceException):
import_classes('unknown', None)
with pytest.raises(InheritanceException):
import_classes('unknown.Unknown', None)
# a module having no classes
classes = import_classes('sphinx', None)
@ -80,7 +82,8 @@ def test_import_classes():
assert classes == [CatalogInfo]
# got exception for functions
raises(InheritanceException, import_classes, 'encode_uri', 'sphinx.util')
with pytest.raises(InheritanceException):
import_classes('encode_uri', 'sphinx.util')
# import submodule on current module (refs: #3164)
classes = import_classes('sphinx', 'example')

View File

@ -23,8 +23,6 @@ from sphinx.ext.intersphinx import read_inventory, \
load_mappings, missing_reference, _strip_basic_auth, _read_from_url, \
_get_safe_url, fetch_inventory, INVENTORY_FILENAME
from util import with_app, with_tempdir
inventory_v1 = '''\
# Sphinx inventory version 1
@ -82,10 +80,9 @@ def test_read_inventory_v2():
'/util/glossary.html#term-a-term-including-colon'
@with_app()
@mock.patch('sphinx.ext.intersphinx.read_inventory')
@mock.patch('sphinx.ext.intersphinx._read_from_url')
def test_fetch_inventory_redirection(app, status, warning, _read_from_url, read_inventory):
def test_fetch_inventory_redirection(_read_from_url, read_inventory, app, status, warning):
intersphinx_setup(app)
_read_from_url().readline.return_value = '# Sphinx inventory version 2'.encode('utf-8')
@ -127,8 +124,6 @@ def test_fetch_inventory_redirection(app, status, warning, _read_from_url, read_
assert read_inventory.call_args[0][1] == 'http://hostname/'
@with_app()
@with_tempdir
def test_missing_reference(tempdir, app, status, warning):
inv_file = tempdir / 'inventory'
inv_file.write_bytes(inventory_v2)
@ -218,8 +213,6 @@ def test_missing_reference(tempdir, app, status, warning):
assert rn['refuri'] == '../../../../py3k/foo.html#module-module1'
@with_app()
@with_tempdir
def test_load_mappings_warnings(tempdir, app, status, warning):
"""
load_mappings issues a warning if new-style mapping

View File

@ -11,11 +11,13 @@
import re
from util import with_app, SkipTest
import pytest
from util import SkipTest
@with_app(buildername='html', testroot='ext-math',
confoverrides = {'extensions': ['sphinx.ext.jsmath'], 'jsmath_path': 'dummy.js'})
@pytest.mark.sphinx(
'html', testroot='ext-math',
confoverrides = {'extensions': ['sphinx.ext.jsmath'], 'jsmath_path': 'dummy.js'})
def test_jsmath(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'math.html').text()
@ -33,7 +35,7 @@ def test_jsmath(app, status, warning):
assert '<div class="math">\na + 1 &lt; b</div>' in content
@with_app('html', testroot='ext-math-simple',
@pytest.mark.sphinx('html', testroot='ext-math-simple',
confoverrides = {'extensions': ['sphinx.ext.imgmath']})
def test_imgmath_png(app, status, warning):
app.builder.build_all()
@ -48,7 +50,7 @@ def test_imgmath_png(app, status, warning):
assert re.search(html, content, re.S)
@with_app('html', testroot='ext-math-simple',
@pytest.mark.sphinx('html', testroot='ext-math-simple',
confoverrides={'extensions': ['sphinx.ext.imgmath'],
'imgmath_image_format': 'svg'})
def test_imgmath_svg(app, status, warning):
@ -64,7 +66,7 @@ def test_imgmath_svg(app, status, warning):
assert re.search(html, content, re.S)
@with_app('html', testroot='ext-math',
@pytest.mark.sphinx('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_mathjax_align(app, status, warning):
app.builder.build_all()
@ -76,7 +78,7 @@ def test_mathjax_align(app, status, warning):
assert re.search(html, content, re.S)
@with_app('html', testroot='ext-math',
@pytest.mark.sphinx('html', testroot='ext-math',
confoverrides={'math_number_all': True,
'extensions': ['sphinx.ext.mathjax']})
def test_math_number_all_mathjax(app, status, warning):
@ -88,7 +90,7 @@ def test_math_number_all_mathjax(app, status, warning):
assert re.search(html, content, re.S)
@with_app('latex', testroot='ext-math',
@pytest.mark.sphinx('latex', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_math_number_all_latex(app, status, warning):
app.builder.build_all()

View File

@ -10,10 +10,11 @@
"""
import re
from util import with_app
import pytest
@with_app('html', testroot='ext-todo', freshenv=True,
@pytest.mark.sphinx('html', testroot='ext-todo', freshenv=True,
confoverrides={'todo_include_todos': True, 'todo_emit_warnings': True})
def test_todo(app, status, warning):
todos = []
@ -49,7 +50,7 @@ def test_todo(app, status, warning):
assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar'])
@with_app('html', testroot='ext-todo', freshenv=True,
@pytest.mark.sphinx('html', testroot='ext-todo', freshenv=True,
confoverrides={'todo_include_todos': False, 'todo_emit_warnings': True})
def test_todo_not_included(app, status, warning):
todos = []

View File

@ -11,10 +11,10 @@
import re
from util import with_app
import pytest
@with_app(testroot='ext-viewcode')
@pytest.mark.sphinx(testroot='ext-viewcode')
def test_viewcode(app, status, warning):
app.builder.build_all()
@ -32,7 +32,7 @@ def test_viewcode(app, status, warning):
assert result.count('href="_modules/spam/mod2.html#Class2"') == 2
@with_app(testroot='ext-viewcode', tags=['test_linkcode'])
@pytest.mark.sphinx(testroot='ext-viewcode', tags=['test_linkcode'])
def test_linkcode(app, status, warning):
app.builder.build(['objects'])

View File

@ -16,8 +16,6 @@ from pygments.formatters.html import HtmlFormatter
from sphinx.highlighting import PygmentsBridge
from util import with_app
class MyLexer(RegexLexer):
name = 'testlexer'
@ -41,7 +39,6 @@ class ComplainOnUnhighlighted(PygmentsBridge):
raise AssertionError("should highlight %r" % source)
@with_app()
def test_add_lexer(app, status, warning):
app.add_lexer('test', MyLexer())

View File

@ -18,12 +18,12 @@ from docutils import nodes
from subprocess import Popen, PIPE
from babel.messages import pofile
from nose.tools import assert_equal
from six import string_types
import pytest
from util import tempdir, rootdir, path, gen_with_app, 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, assert_node, repr_as, etree_parse, strip_escseq
assert_startswith, assert_node, etree_parse, strip_escseq, assert_equal
root = tempdir / 'test-intl'
@ -846,7 +846,7 @@ def test_references(app, status, warning):
yield assert_count(warning_expr, warnings, 0)
@with_app(buildername='dummy', testroot='image-glob', confoverrides={'language': 'xx'})
@pytest.mark.sphinx('dummy', testroot='image-glob', confoverrides={'language': 'xx'})
def test_image_glob_intl(app, status, warning):
app.builder.build_all()
@ -887,7 +887,7 @@ def test_image_glob_intl(app, status, warning):
'image/svg+xml': 'subdir/svgimg.xx.svg'})
@with_app(buildername='dummy', testroot='image-glob',
@pytest.mark.sphinx('dummy', testroot='image-glob',
confoverrides={'language': 'xx',
'figure_language_filename': u'{root}{ext}.{language}'})
def test_image_glob_intl_using_figure_language_filename(app, status, warning):
@ -931,4 +931,4 @@ def test_image_glob_intl_using_figure_language_filename(app, status, warning):
def getwarning(warnings):
return repr_as(strip_escseq(warnings.getvalue().replace(os.sep, '/')), '<warnings>')
return strip_escseq(warnings.getvalue().replace(os.sep, '/'))

View File

@ -20,8 +20,9 @@ from sphinx.util import texescape
from sphinx.util.docutils import sphinx_domains
from sphinx.writers.html import HTMLWriter, SmartyPantsHTMLTranslator
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
import pytest
from util import TestApp, with_app, assert_node
from util import TestApp, assert_node
app = settings = parser = domain_context = None
@ -152,7 +153,7 @@ def test_latex_escaping():
r'\\href{http://example.com/~me/}{test}.*')
@with_app(buildername='dummy', testroot='prolog')
@pytest.mark.sphinx('dummy', testroot='prolog')
def test_rst_prolog(app, status, warning):
app.builder.build_all()
rst = pickle.loads((app.doctreedir / 'restructuredtext.doctree').bytes())
@ -176,7 +177,7 @@ def test_rst_prolog(app, status, warning):
assert not md.rawsource.endswith('*Good-bye world*.\n')
@with_app(buildername='dummy', testroot='keep_warnings')
@pytest.mark.sphinx('dummy', testroot='keep_warnings')
def test_keep_warnings_is_True(app, status, warning):
app.builder.build_all()
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
@ -185,7 +186,7 @@ def test_keep_warnings_is_True(app, status, warning):
assert_node(doctree[0][1], nodes.system_message)
@with_app(buildername='dummy', testroot='keep_warnings',
@pytest.mark.sphinx('dummy', testroot='keep_warnings',
confoverrides={'keep_warnings': False})
def test_keep_warnings_is_False(app, status, warning):
app.builder.build_all()
@ -194,7 +195,7 @@ def test_keep_warnings_is_False(app, status, warning):
assert len(doctree[0]) == 1
@with_app(buildername='dummy', testroot='refonly_bullet_list')
@pytest.mark.sphinx('dummy', testroot='refonly_bullet_list')
def test_compact_refonly_bullet_list(app, status, warning):
app.builder.build_all()
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())

View File

@ -12,12 +12,10 @@
# adapted from an example of bibliographic metadata at
# http://docutils.sourceforge.net/docs/user/rst/demo.txt
from util import with_app
from nose.tools import assert_equal
import pytest
@with_app('pseudoxml')
@pytest.mark.sphinx('pseudoxml')
def test_docinfo(app, status, warning):
"""
Inspect the 'docinfo' metadata stored in the first node of the document.
@ -53,8 +51,4 @@ def test_docinfo(app, status, warning):
'orphan': u'',
'nocomments': u'',
}
# I like this way of comparing dicts - easier to see the error.
for key in exampledocinfo:
yield assert_equal, exampledocinfo.get(key), expecteddocinfo.get(key)
# but then we still have to check for missing keys
yield assert_equal, set(expecteddocinfo.keys()), set(exampledocinfo.keys())
assert exampledocinfo == expecteddocinfo

View File

@ -14,8 +14,9 @@ import time
from six import PY2, text_type, StringIO
from six.moves import input
import pytest
from util import raises, with_tempdir, SkipTest
from util import SkipTest
from sphinx import application
from sphinx import quickstart as qs
@ -107,7 +108,8 @@ def test_do_prompt():
assert d['k4'] is True
qs.do_prompt(d, 'k5', 'Q5', validator=qs.boolean)
assert d['k5'] is False
raises(AssertionError, qs.do_prompt, d, 'k6', 'Q6', validator=qs.boolean)
with pytest.raises(AssertionError):
qs.do_prompt(d, 'k6', 'Q6', validator=qs.boolean)
def test_do_prompt_with_nonascii():
@ -125,7 +127,6 @@ def test_do_prompt_with_nonascii():
assert d['k1'] == u'\u30c9\u30a4\u30c4'
@with_tempdir
def test_quickstart_defaults(tempdir):
answers = {
'Root path': tempdir,
@ -163,7 +164,6 @@ def test_quickstart_defaults(tempdir):
assert (tempdir / 'make.bat').isfile()
@with_tempdir
def test_quickstart_all_answers(tempdir):
answers = {
'Root path': tempdir,
@ -231,7 +231,6 @@ def test_quickstart_all_answers(tempdir):
assert (tempdir / 'source' / 'contents.txt').isfile()
@with_tempdir
def test_generated_files_eol(tempdir):
answers = {
'Root path': tempdir,
@ -252,7 +251,6 @@ def test_generated_files_eol(tempdir):
assert_eol(tempdir / 'Makefile', '\n')
@with_tempdir
def test_quickstart_and_build(tempdir):
answers = {
'Root path': tempdir,
@ -278,7 +276,6 @@ def test_quickstart_and_build(tempdir):
assert not warnings
@with_tempdir
def test_default_filename(tempdir):
answers = {
'Root path': tempdir,
@ -300,7 +297,6 @@ def test_default_filename(tempdir):
assert ns['texinfo_documents'][0][1] == 'sphinx'
@with_tempdir
def test_extensions(tempdir):
qs.main(['sphinx-quickstart', '-q',
'-p', 'project_name', '-a', 'author',

View File

@ -15,8 +15,7 @@ from docutils.parsers import rst
from sphinx.search import IndexBuilder
from sphinx.util import jsdump
from util import with_app
import pytest
settings = parser = None
@ -58,7 +57,7 @@ def test_wordcollector():
assert 'fermion' in ix._mapping
@with_app(testroot='ext-viewcode')
@pytest.mark.sphinx(testroot='ext-viewcode')
def test_objects_are_escaped(app, status, warning):
app.builder.build_all()
searchindex = (app.outdir / 'searchindex.js').text()
@ -68,7 +67,7 @@ def test_objects_are_escaped(app, status, warning):
assert 'n::Array&lt;T, d&gt;' in index.get('objects').get('') # n::Array<T,d> is escaped
@with_app(testroot='search')
@pytest.mark.sphinx(testroot='search')
def test_meta_keys_are_handled_for_language_en(app, status, warning):
app.builder.build_all()
searchindex = jsload(app.outdir / 'searchindex.js')
@ -81,7 +80,7 @@ def test_meta_keys_are_handled_for_language_en(app, status, warning):
assert not is_registered_term(searchindex, 'onlytoogerman')
@with_app(testroot='search', confoverrides={'html_search_language': 'de'})
@pytest.mark.sphinx(testroot='search', confoverrides={'html_search_language': 'de'})
def test_meta_keys_are_handled_for_language_de(app, status, warning):
app.builder.build_all()
searchindex = jsload(app.outdir / 'searchindex.js')
@ -94,14 +93,14 @@ def test_meta_keys_are_handled_for_language_de(app, status, warning):
assert is_registered_term(searchindex, 'onlytoogerman')
@with_app(testroot='search')
@pytest.mark.sphinx(testroot='search')
def test_stemmer_does_not_remove_short_words(app, status, warning):
app.builder.build_all()
searchindex = (app.outdir / 'searchindex.js').text()
assert 'zfs' in searchindex
@with_app(testroot='search')
@pytest.mark.sphinx(testroot='search')
def test_stemmer(app, status, warning):
searchindex = jsload(app.outdir / 'searchindex.js')
print(searchindex)
@ -109,7 +108,7 @@ def test_stemmer(app, status, warning):
assert is_registered_term(searchindex, 'intern')
@with_app(testroot='search')
@pytest.mark.sphinx(testroot='search')
def test_term_in_heading_and_section(app, status, warning):
searchindex = (app.outdir / 'searchindex.js').text()
# if search term is in the title of one doc and in the text of another
@ -119,7 +118,7 @@ def test_term_in_heading_and_section(app, status, warning):
assert 'textinhead:0' in searchindex
@with_app(testroot='search')
@pytest.mark.sphinx(testroot='search')
def test_term_in_raw_directive(app, status, warning):
searchindex = jsload(app.outdir / 'searchindex.js')
assert not is_registered_term(searchindex, 'raw')

View File

@ -12,12 +12,13 @@
import os
import sys
import subprocess
from functools import wraps
import tempfile
from collections import namedtuple
import sphinx
from util import rootdir, tempdir, SkipTest
from path import path
import pytest
from sphinx.util.osutil import cd
from util import rootdir, tempdir
from textwrap import dedent
root = tempdir / 'test-setup'
@ -28,57 +29,52 @@ def setup_module():
(rootdir / 'roots' / 'test-setup').copytree(root)
def with_setup_command(root, *args, **kwds):
@pytest.fixture
def setup_command(request, tempdir):
"""
Run `setup.py build_sphinx` with args and kwargs,
pass it to the test and clean up properly.
"""
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
tempdir = path(tempfile.mkdtemp())
pkgrootdir = (tempdir / 'root')
root.copytree(pkgrootdir)
cwd = os.getcwd()
os.chdir(pkgrootdir)
pythonpath = os.path.dirname(os.path.dirname(sphinx.__file__))
if os.getenv('PYTHONPATH'):
pythonpath = os.getenv('PYTHONPATH') + os.pathsep + pythonpath
command = [sys.executable, 'setup.py', 'build_sphinx']
command.extend(args)
try:
proc = subprocess.Popen(
command,
env=dict(os.environ, PYTHONPATH=pythonpath),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
func(pkgrootdir, proc)
finally:
tempdir.rmtree(ignore_errors=True)
os.chdir(cwd)
return deco
return generator
marker = request.node.get_marker('setup_command')
args = marker.args if marker else []
pkgrootdir = tempdir / 'root'
root.copytree(pkgrootdir)
with cd(pkgrootdir):
pythonpath = os.path.dirname(os.path.dirname(sphinx.__file__))
if os.getenv('PYTHONPATH'):
pythonpath = os.getenv('PYTHONPATH') + os.pathsep + pythonpath
command = [sys.executable, 'setup.py', 'build_sphinx']
command.extend(args)
proc = subprocess.Popen(
command,
env=dict(os.environ, PYTHONPATH=pythonpath),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
yield namedtuple('setup', 'pkgroot,proc')(pkgrootdir, proc)
@with_setup_command(root)
def test_build_sphinx(pkgroot, proc):
def test_build_sphinx(setup_command):
proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
assert proc.returncode == 0
@with_setup_command(root)
def test_build_sphinx_with_nonascii_path(pkgroot, proc):
@pytest.fixture
def nonascii_srcdir(request, setup_command):
mb_name = u'\u65e5\u672c\u8a9e'
srcdir = (pkgroot / 'doc')
srcdir = (setup_command.pkgroot / 'doc')
try:
(srcdir / mb_name).makedirs()
except UnicodeEncodeError:
from path import FILESYSTEMENCODING
raise SkipTest(
pytest.skip(
'non-ASCII filename not supported on this filesystem encoding: '
'%s', FILESYSTEMENCODING)
'%s' % FILESYSTEMENCODING)
(srcdir / mb_name / (mb_name + '.txt')).write_text(dedent("""
multi byte file name page
@ -91,41 +87,47 @@ def test_build_sphinx_with_nonascii_path(pkgroot, proc):
%(mb_name)s/%(mb_name)s
""" % locals())
).encode('utf-8'))
).encode('utf-8'))
@pytest.mark.usefixtures('nonascii_srcdir')
def test_build_sphinx_with_nonascii_path(setup_command):
proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
assert proc.returncode == 0
@with_setup_command(root, '-b', 'linkcheck')
def test_build_sphinx_return_nonzero_status(pkgroot, proc):
srcdir = (pkgroot / 'doc')
@pytest.mark.setup_command('-b', 'linkcheck')
def test_build_sphinx_return_nonzero_status(setup_command):
srcdir = (setup_command.pkgroot / 'doc')
(srcdir / 'contents.txt').write_text(
'http://localhost.unexistentdomain/index.html')
proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
assert proc.returncode != 0, 'expect non-zero status for setup.py'
@with_setup_command(root)
def test_build_sphinx_warning_return_zero_status(pkgroot, proc):
srcdir = (pkgroot / 'doc')
def test_build_sphinx_warning_return_zero_status(setup_command):
srcdir = (setup_command.pkgroot / 'doc')
(srcdir / 'contents.txt').write_text(
'See :ref:`unexisting-reference-label`')
proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
assert proc.returncode == 0
@with_setup_command(root, '--warning-is-error')
def test_build_sphinx_warning_is_error_return_nonzero_status(pkgroot, proc):
srcdir = (pkgroot / 'doc')
@pytest.mark.setup_command('--warning-is-error')
def test_build_sphinx_warning_is_error_return_nonzero_status(setup_command):
srcdir = (setup_command.pkgroot / 'doc')
(srcdir / 'contents.txt').write_text(
'See :ref:`unexisting-reference-label`')
proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)

View File

@ -9,10 +9,10 @@
:license: BSD, see LICENSE for details.
"""
from util import with_app
import pytest
@with_app('html', testroot='templating')
@pytest.mark.sphinx('html', testroot='templating')
def test_layout_overloading(app, status, warning):
app.builder.build_update()
@ -21,7 +21,7 @@ def test_layout_overloading(app, status, warning):
assert '<!-- layout overloading -->' in result
@with_app('html', testroot='templating')
@pytest.mark.sphinx('html', testroot='templating')
def test_autosummary_class_template_overloading(app, status, warning):
app.builder.build_update()

View File

@ -13,14 +13,16 @@ import os
import zipfile
import mock
import pytest
from sphinx.theming import Theme, ThemeError
from util import with_app, raises, path
from util import with_app, path
@with_app(confoverrides={'html_theme': 'ziptheme',
'html_theme_options.testopt': 'foo'})
@pytest.mark.sphinx(
confoverrides={'html_theme': 'ziptheme',
'html_theme_options.testopt': 'foo'})
def test_theme_api(app, status, warning):
cfg = app.config
@ -46,10 +48,12 @@ def test_theme_api(app, status, warning):
assert theme.get_confstr('options', 'nosidebar') == 'false'
# nonexisting setting
assert theme.get_confstr('theme', 'foobar', 'def') == 'def'
raises(ThemeError, theme.get_confstr, 'theme', 'foobar')
with pytest.raises(ThemeError):
theme.get_confstr('theme', 'foobar')
# options API
raises(ThemeError, theme.get_options, {'nonexisting': 'foo'})
with pytest.raises(ThemeError):
theme.get_options({'nonexisting': 'foo'})
options = theme.get_options(cfg.html_theme_options)
assert options['testopt'] == 'foo'
assert options['nosidebar'] == 'false'
@ -59,7 +63,7 @@ def test_theme_api(app, status, warning):
assert not os.path.exists(themedir)
@with_app(testroot='tocdepth') # a minimal root
@pytest.mark.sphinx(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.
@ -83,7 +87,8 @@ def test_js_source(app, status, warning):
assert 'Underscore.js {v}'.format(v=v) in underscore_src, msg
def test_double_inheriting_theme():
@pytest.mark.sphinx(testroot='double-inheriting-theme')
def test_double_inheriting_theme(make_app, app_params):
from sphinx.theming import load_theme_plugins # load original before patching
def load_themes():
@ -92,8 +97,6 @@ def test_double_inheriting_theme():
for t in load_theme_plugins():
yield t
@mock.patch('sphinx.theming.load_theme_plugins', side_effect=load_themes)
@with_app(testroot='double-inheriting-theme')
def test_double_inheriting_theme_(app, status, warning, m_):
pass
yield test_double_inheriting_theme_
with mock.patch('sphinx.theming.load_theme_plugins', side_effect=load_themes):
args, kwargs = app_params
make_app(*args, **kwargs)

View File

@ -8,11 +8,9 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import pytest
from util import with_app
@with_app(testroot='toctree-glob')
@pytest.mark.sphinx(testroot='toctree-glob')
def test_relations(app, status, warning):
app.builder.build_all()
assert app.builder.relations['index'] == [None, None, 'foo']

View File

@ -12,7 +12,6 @@ from sphinx.util.fileutil import copy_asset, copy_asset_file
from sphinx.jinja2glue import BuiltinTemplateLoader
import mock
from util import with_tempdir
class DummyTemplateLoader(BuiltinTemplateLoader):
@ -24,33 +23,32 @@ class DummyTemplateLoader(BuiltinTemplateLoader):
self.init(builder)
@with_tempdir
def test_copy_asset_file(tmpdir):
def test_copy_asset_file(tempdir):
renderer = DummyTemplateLoader()
# copy normal file
src = (tmpdir / 'asset.txt')
src = (tempdir / 'asset.txt')
src.write_text('# test data')
dest = (tmpdir / 'output.txt')
dest = (tempdir / 'output.txt')
copy_asset_file(src, dest)
assert dest.exists()
assert src.text() == dest.text()
# copy template file
src = (tmpdir / 'asset.txt_t')
src = (tempdir / 'asset.txt_t')
src.write_text('# {{var1}} data')
dest = (tmpdir / 'output.txt_t')
dest = (tempdir / 'output.txt_t')
copy_asset_file(src, dest, {'var1': 'template'}, renderer)
assert not dest.exists()
assert (tmpdir / 'output.txt').exists()
assert (tmpdir / 'output.txt').text() == '# template data'
assert (tempdir / 'output.txt').exists()
assert (tempdir / 'output.txt').text() == '# template data'
# copy template file to subdir
src = (tmpdir / 'asset.txt_t')
src = (tempdir / 'asset.txt_t')
src.write_text('# {{var1}} data')
subdir1 = (tmpdir / 'subdir')
subdir1 = (tempdir / 'subdir')
subdir1.makedirs()
copy_asset_file(src, subdir1, {'var1': 'template'}, renderer)
@ -58,8 +56,8 @@ def test_copy_asset_file(tmpdir):
assert (subdir1 / 'asset.txt').text() == '# template data'
# copy template file without context
src = (tmpdir / 'asset.txt_t')
subdir2 = (tmpdir / 'subdir2')
src = (tempdir / 'asset.txt_t')
subdir2 = (tempdir / 'subdir2')
subdir2.makedirs()
copy_asset_file(src, subdir2)
@ -68,12 +66,11 @@ def test_copy_asset_file(tmpdir):
assert (subdir2 / 'asset.txt_t').text() == '# {{var1}} data'
@with_tempdir
def test_copy_asset(tmpdir):
def test_copy_asset(tempdir):
renderer = DummyTemplateLoader()
# prepare source files
source = (tmpdir / 'source')
source = (tempdir / 'source')
source.makedirs()
(source / 'index.rst').write_text('index.rst')
(source / 'foo.rst_t').write_text('{{var1}}.rst')
@ -84,13 +81,13 @@ def test_copy_asset(tmpdir):
(source / '_templates' / 'sidebar.html_t').write_text('sidebar: {{var2}}')
# copy a single file
assert not (tmpdir / 'test1').exists()
copy_asset(source / 'index.rst', tmpdir / 'test1')
assert (tmpdir / 'test1').exists()
assert (tmpdir / 'test1/index.rst').exists()
assert not (tempdir / 'test1').exists()
copy_asset(source / 'index.rst', tempdir / 'test1')
assert (tempdir / 'test1').exists()
assert (tempdir / 'test1/index.rst').exists()
# copy directories
destdir = tmpdir / 'test2'
destdir = tempdir / 'test2'
copy_asset(source, destdir, context=dict(var1='bar', var2='baz'), renderer=renderer)
assert (destdir / 'index.rst').exists()
assert (destdir / 'foo.rst').exists()
@ -104,7 +101,7 @@ def test_copy_asset(tmpdir):
def excluded(path):
return ('sidebar.html' in path or 'basic.css' in path)
destdir = tmpdir / 'test3'
destdir = tempdir / 'test3'
copy_asset(source, destdir, excluded,
context=dict(var1='bar', var2='baz'), renderer=renderer)
assert (destdir / 'index.rst').exists()

View File

@ -17,8 +17,9 @@ from os import path
from babel.messages.mofile import read_mo
from sphinx.util import i18n
from sphinx.errors import SphinxError
import pytest
from util import TestApp, with_tempdir, raises
from util import TestApp
def test_catalog_info_for_file_and_path():
@ -37,13 +38,12 @@ def test_catalog_info_for_sub_domain_file_and_path():
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', 'utf-8')
def test_catalog_outdated(tempdir):
(tempdir / 'test.po').write_text('#')
cat = i18n.CatalogInfo(tempdir, 'test', 'utf-8')
assert cat.is_outdated() # if mo is not exist
mo_file = (dir / 'test.mo')
mo_file = (tempdir / 'test.mo')
mo_file.write_text('#')
assert not cat.is_outdated() # if mo is exist and newer than po
@ -51,31 +51,29 @@ def test_catalog_outdated(dir):
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', 'utf-8')
def test_catalog_write_mo(tempdir):
(tempdir / 'test.po').write_text('#')
cat = i18n.CatalogInfo(tempdir, 'test', 'utf-8')
cat.write_mo('en')
assert path.exists(cat.mo_path)
with open(cat.mo_path, 'rb') as f:
assert read_mo(f) 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('#')
def test_get_catalogs_for_xx(tempdir):
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / 'test6.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_ALL').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_ALL' / 'test7.po').write_text('#')
catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=False)
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=False)
domains = set(c.domain for c in catalogs)
assert domains == set([
'test1',
@ -85,24 +83,22 @@ def test_get_catalogs_for_xx(dir):
])
@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('#')
def test_get_catalogs_for_en(tempdir):
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'xx_dom.po').write_text('#')
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'en', force_all=False)
catalogs = i18n.find_catalog_source_files([tempdir / '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.find_catalog_source_files([dir / 'loc1'], 'xx')
def test_get_catalogs_with_non_existent_locale(tempdir):
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx')
assert not catalogs
catalogs = i18n.find_catalog_source_files([dir / 'loc1'], None)
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], None)
assert not catalogs
@ -111,25 +107,24 @@ def test_get_catalogs_with_non_existent_locale_dirs():
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('#')
def test_get_catalogs_for_xx_without_outdated(tempdir):
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.mo').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.mo').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.mo').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.mo').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.mo').write_text('#')
catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=False)
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=False)
assert not catalogs
catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=True)
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=True)
domains = set(c.domain for c in catalogs)
assert domains == set([
'test1',
@ -139,29 +134,27 @@ def test_get_catalogs_for_xx_without_outdated(dir):
])
@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('#')
def test_get_catalogs_from_multiple_locale_dirs(tempdir):
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
catalogs = i18n.find_catalog_source_files([dir / 'loc1', dir / 'loc2'], 'xx')
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1', tempdir / '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('#')
def test_get_catalogs_with_compact(tempdir):
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#')
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', gettext_compact=True)
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', gettext_compact=True)
domains = set(c.domain for c in catalogs)
assert domains == set(['test1', 'test2', 'sub'])
@ -251,4 +244,5 @@ def test_get_filename_for_language():
# invalid figure_language_filename
app.env.config.figure_language_filename = '{root}.{invalid}{ext}'
raises(SphinxError, i18n.get_image_filename_for_language, 'foo.png', app.env)
with pytest.raises(SphinxError):
i18n.get_image_filename_for_language('foo.png', app.env)

View File

@ -9,10 +9,6 @@
:license: BSD, see LICENSE for details.
"""
from functools import wraps
from six import StringIO
from sphinx.websupport import WebSupport
from sphinx.websupport.errors import DocumentNotFoundError, \
CommentNotAllowedError, UserNotAuthorizedError
@ -26,26 +22,28 @@ try:
except ImportError:
sqlalchemy_missing = True
from util import rootdir, tempdir, raises, skip_if
import pytest
from util import rootdir, tempdir, skip_if
default_settings = {'builddir': tempdir / 'websupport',
'status': StringIO(),
'warning': StringIO()}
@pytest.fixture
def support(request):
settings = {
'srcdir': rootdir / 'root',
# to use same directory for 'builddir' in each 'support' fixture, using
# 'tempdir' (static) value instead of 'tempdir' fixture value.
# each test expect result of db value at previous test case.
'builddir': tempdir / 'websupport'
}
marker = request.node.get_marker('support')
if marker:
settings.update(marker.kwargs)
support = WebSupport(**settings)
yield support
def with_support(*args, **kwargs):
"""Make a WebSupport object and pass it the test."""
settings = default_settings.copy()
settings.update(kwargs)
def generator(func):
@wraps(func)
def new_func(*args2, **kwargs2):
support = WebSupport(**settings)
func(support, *args2, **kwargs2)
return new_func
return generator
with_support = pytest.mark.support
class NullStorage(StorageBackend):
@ -55,11 +53,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.
raises(RuntimeError, support.build)
with pytest.raises(RuntimeError):
support.build()
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support(srcdir=rootdir / 'root')
@with_support()
def test_build(support):
support.build()
@ -67,7 +66,8 @@ def test_build(support):
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_get_document(support):
raises(DocumentNotFoundError, support.get_document, 'nonexisting')
with pytest.raises(DocumentNotFoundError):
support.get_document('nonexisting')
contents = support.get_document('contents')
assert contents['title'] and contents['body'] \
@ -92,8 +92,8 @@ def test_comments(support):
# Make sure that comments can't be added to a comment where
# displayed == False, since it could break the algorithm that
# converts a nodes comments to a tree.
raises(CommentNotAllowedError, support.add_comment, 'Not allowed',
parent_id=str(hidden_comment['id']))
with pytest.raises(CommentNotAllowedError):
support.add_comment('Not allowed', parent_id=str(hidden_comment['id']))
# Add a displayed and not displayed child to the displayed comment.
support.add_comment('Child test comment', parent_id=str(comment['id']),
username='user_one')
@ -123,56 +123,6 @@ def test_comments(support):
assert children[0]['text'] == '<p>Child test comment</p>\n'
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_voting(support):
session = Session()
nodes = session.query(Node).all()
node = nodes[0]
comment = support.get_data(node.id)['comments'][0]
def check_rating(val):
data = support.get_data(node.id)
comment = data['comments'][0]
assert comment['rating'] == val, '%s != %s' % (comment['rating'], val)
support.process_vote(comment['id'], 'user_one', '1')
support.process_vote(comment['id'], 'user_two', '1')
support.process_vote(comment['id'], 'user_three', '1')
check_rating(3)
support.process_vote(comment['id'], 'user_one', '-1')
check_rating(1)
support.process_vote(comment['id'], 'user_one', '0')
check_rating(2)
# Make sure a vote with value > 1 or < -1 can't be cast.
raises(ValueError, support.process_vote, comment['id'], 'user_one', '2')
raises(ValueError, support.process_vote, comment['id'], 'user_one', '-2')
# Make sure past voting data is associated with comments when they are
# fetched.
data = support.get_data(str(node.id), username='user_two')
comment = data['comments'][0]
assert comment['vote'] == 1, '%s != 1' % comment['vote']
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_proposals(support):
session = Session()
node = session.query(Node).first()
data = support.get_data(node.id)
source = data['source']
proposal = source[:5] + source[10:15] + 'asdf' + source[15:]
support.add_comment('Proposal comment',
node_id=node.id,
proposal=proposal)
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_user_delete_comments(support):
@ -185,8 +135,8 @@ def test_user_delete_comments(support):
comment = get_comment()
assert comment['username'] == 'user_one'
# Make sure other normal users can't delete someone elses comments.
raises(UserNotAuthorizedError, support.delete_comment,
comment['id'], username='user_two')
with pytest.raises(UserNotAuthorizedError):
support.delete_comment(comment['id'], username='user_two')
# Now delete the comment using the correct username.
support.delete_comment(comment['id'], username='user_one')
comment = get_comment()
@ -194,40 +144,6 @@ def test_user_delete_comments(support):
assert comment['text'] == '[deleted]'
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_moderator_delete_comments(support):
def get_comment():
session = Session()
node = session.query(Node).first()
session.close()
return support.get_data(node.id, moderator=True)['comments'][1]
comment = get_comment()
support.delete_comment(comment['id'], username='user_two',
moderator=True)
raises(IndexError, get_comment)
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_update_username(support):
support.update_username('user_two', 'new_user_two')
session = Session()
comments = session.query(Comment).\
filter(Comment.username == 'user_two').all()
assert len(comments) == 0
votes = session.query(CommentVote).\
filter(CommentVote.username == 'user_two').all()
assert len(votes) == 0
comments = session.query(Comment).\
filter(Comment.username == 'new_user_two').all()
assert len(comments) == 1
votes = session.query(CommentVote).\
filter(CommentVote.username == 'new_user_two').all()
assert len(votes) == 0
called = False
@ -250,8 +166,10 @@ def test_moderation(support):
# Make sure the moderation_callback is called.
assert called
# Make sure the user must be a moderator.
raises(UserNotAuthorizedError, support.accept_comment, accepted['id'])
raises(UserNotAuthorizedError, support.delete_comment, deleted['id'])
with pytest.raises(UserNotAuthorizedError):
support.accept_comment(accepted['id'])
with pytest.raises(UserNotAuthorizedError):
support.delete_comment(deleted['id'])
support.accept_comment(accepted['id'], moderator=True)
support.delete_comment(deleted['id'], moderator=True)
comments = support.get_data(node.id)['comments']
@ -260,6 +178,93 @@ def test_moderation(support):
assert len(comments) == 1
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_moderator_delete_comments(support):
def get_comment():
session = Session()
node = session.query(Node).first()
session.close()
return support.get_data(node.id, moderator=True)['comments'][1]
comment = get_comment()
support.delete_comment(comment['id'], username='user_two',
moderator=True)
with pytest.raises(IndexError):
get_comment()
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_update_username(support):
support.update_username('user_two', 'new_user_two')
session = Session()
comments = session.query(Comment).\
filter(Comment.username == 'user_two').all()
assert len(comments) == 0
votes = session.query(CommentVote).\
filter(CommentVote.username == 'user_two').all()
assert len(votes) == 0
comments = session.query(Comment).\
filter(Comment.username == 'new_user_two').all()
assert len(comments) == 1
votes = session.query(CommentVote).\
filter(CommentVote.username == 'new_user_two').all()
assert len(votes) == 0
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_proposals(support):
session = Session()
node = session.query(Node).first()
data = support.get_data(node.id)
source = data['source']
proposal = source[:5] + source[10:15] + 'asdf' + source[15:]
support.add_comment('Proposal comment',
node_id=node.id,
proposal=proposal)
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@with_support()
def test_voting(support):
session = Session()
nodes = session.query(Node).all()
node = nodes[0]
comment = support.get_data(node.id)['comments'][0]
def check_rating(val):
data = support.get_data(node.id)
comment = data['comments'][0]
assert comment['rating'] == val, '%s != %s' % (comment['rating'], val)
support.process_vote(comment['id'], 'user_one', '1')
support.process_vote(comment['id'], 'user_two', '1')
support.process_vote(comment['id'], 'user_three', '1')
check_rating(3)
support.process_vote(comment['id'], 'user_one', '-1')
check_rating(1)
support.process_vote(comment['id'], 'user_one', '0')
check_rating(2)
# Make sure a vote with value > 1 or < -1 can't be cast.
with pytest.raises(ValueError):
support.process_vote(comment['id'], 'user_one', '2')
with pytest.raises(ValueError):
support.process_vote(comment['id'], 'user_one', '-2')
# Make sure past voting data is associated with comments when they are
# fetched.
data = support.get_data(str(node.id), username='user_two')
comment = data['comments'][0]
assert comment['vote'] == 1, '%s != 1' % comment['vote']
def test_differ():
source = 'Lorem ipsum dolor sit amet,\nconsectetur adipisicing elit,\n' \
'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'

View File

@ -11,7 +11,7 @@
from __future__ import print_function
from sphinx.writers.latex import rstdim_to_latexdim
from util import raises
import pytest
def test_rstdim_to_latexdim():
@ -32,5 +32,6 @@ def test_rstdim_to_latexdim():
assert rstdim_to_latexdim('.5em') == '.5em'
# unknown values (it might be generated by 3rd party extension)
raises(ValueError, rstdim_to_latexdim, 'unknown')
with pytest.raises(ValueError):
rstdim_to_latexdim('unknown')
assert rstdim_to_latexdim('160.0unknown') == '160.0unknown'

View File

@ -10,14 +10,13 @@
import os
import re
import sys
import tempfile
import warnings
from functools import wraps
from xml.etree import ElementTree
from six import StringIO, string_types
from six import string_types
from nose import tools, SkipTest
import pytest
from docutils import nodes
from docutils.parsers.rst import directives, roles
@ -27,16 +26,17 @@ from sphinx.builders.latex import LaTeXBuilder
from sphinx.theming import Theme
from sphinx.ext.autodoc import AutoDirective
from sphinx.pycode import ModuleAnalyzer
from sphinx.deprecation import RemovedInSphinx17Warning
from path import path, repr_as # NOQA
from path import path
__all__ = [
'rootdir', 'tempdir', 'raises', 'raises_msg',
'skip_if', 'skip_unless', 'skip_unless_importable', 'Struct',
'ListOutput', 'TestApp', 'with_app', 'gen_with_app',
'path', 'with_tempdir',
'sprint', 'remove_unicode_literals',
'rootdir', 'tempdir',
'skip_unless_importable', 'Struct',
'SphinxTestApp',
'path',
'remove_unicode_literals',
]
@ -44,36 +44,6 @@ rootdir = path(os.path.dirname(__file__) or '.').abspath()
tempdir = path(os.environ['SPHINX_TEST_TEMPDIR']).abspath()
def _excstr(exc):
if type(exc) is tuple:
return str(tuple(map(_excstr, exc)))
return exc.__name__
def raises(exc, func, *args, **kwds):
"""Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*."""
try:
func(*args, **kwds)
except exc:
pass
else:
raise AssertionError('%s did not raise %s' %
(func.__name__, _excstr(exc)))
def raises_msg(exc, msg, func, *args, **kwds):
"""Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*,
and check if the message contains *msg*.
"""
try:
func(*args, **kwds)
except exc as err:
assert msg in str(err), "\"%s\" not in \"%s\"" % (msg, err)
else:
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)
@ -118,43 +88,14 @@ def assert_node(node, cls=None, xpath="", **kwargs):
'The node%s[%s] is not %r: %r' % (xpath, key, value, node[key])
try:
from nose.tools import assert_in, assert_not_in
except ImportError:
def assert_in(x, thing, msg=''):
if x not in thing:
assert False, msg or '%r is not in %r' % (x, thing)
def assert_not_in(x, thing, msg=''):
if x in thing:
assert False, msg or '%r is in %r' % (x, thing)
def skip_if(condition, msg=None):
"""Decorator to skip test if condition is true."""
def deco(test):
@tools.make_decorator(test)
def skipper(*args, **kwds):
if condition:
raise SkipTest(msg or 'conditional skip')
return test(*args, **kwds)
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:
__import__(module)
except ImportError:
return skip_if(True, msg)
return pytest.mark.skipif(True, reason=(msg or 'conditional skip'))
else:
return skip_if(False, msg)
return pytest.mark.skipif(False, reason=(msg or 'conditional skip'))
def etree_parse(path):
@ -168,22 +109,7 @@ class Struct(object):
self.__dict__.update(kwds)
class ListOutput(object):
"""
File-like object that collects written text in a list.
"""
def __init__(self, name):
self.name = name
self.content = []
def reset(self):
del self.content[:]
def write(self, text):
self.content.append(text)
class TestApp(application.Sphinx):
class SphinxTestApp(application.Sphinx):
"""
A subclass of :class:`Sphinx` that runs on the test root, with some
better default values for the initialization parameters.
@ -222,10 +148,6 @@ class TestApp(application.Sphinx):
doctreedir.makedirs()
if confoverrides is None:
confoverrides = {}
if status is None:
status = StringIO()
if warning is None:
warning = ListOutput('stderr')
# if warningiserror is None:
warningiserror = False
@ -263,59 +185,6 @@ class TestApp(application.Sphinx):
return '<%s buildername=%r>' % (self.__class__.__name__, self.builder.name)
def with_app(*args, **kwargs):
"""
Make a TestApp with args and kwargs, pass it to the test and clean up
properly.
"""
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
status, warning = StringIO(), StringIO()
kwargs['status'] = status
kwargs['warning'] = warning
app = TestApp(*args, **kwargs)
try:
func(app, status, warning, *args2, **kwargs2)
finally:
app.cleanup()
return deco
return generator
def gen_with_app(*args, **kwargs):
"""
Decorate a test generator to pass a TestApp as the first argument to the
test generator when it's executed.
"""
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
status, warning = StringIO(), StringIO()
kwargs['status'] = status
kwargs['warning'] = warning
app = TestApp(*args, **kwargs)
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):
new_tempdir = path(tempfile.mkdtemp(dir=tempdir))
func(new_tempdir, *args, **kwds)
new_func.__name__ = func.__name__
return new_func
def sprint(*args):
sys.stderr.write(' '.join(map(str, args)) + '\n')
_unicode_literals_re = re.compile(r'u(".*?")|u(\'.*?\')')
@ -333,3 +202,163 @@ def find_files(root, suffix=None):
def strip_escseq(text):
return re.sub('\x1b.*?m', '', text)
# #############################################
# DEPRECATED implementations
import tempfile
from six import StringIO
def gen_with_app(*args, **kwargs):
"""
**DEPRECATED**: use pytest.mark.parametrize instead.
Decorate a test generator to pass a SphinxTestApp as the first argument to
the test generator when it's executed.
"""
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
status, warning = StringIO(), StringIO()
kwargs['status'] = status
kwargs['warning'] = warning
app = SphinxTestApp(*args, **kwargs)
try:
for item in func(app, status, warning, *args2, **kwargs2):
yield item
finally:
app.cleanup()
return deco
return generator
def skip_if(condition, msg=None):
"""
**DEPRECATED**: use pytest.mark.skipif instead.
Decorator to skip test if condition is true.
"""
return pytest.mark.skipif(condition, reason=(msg or 'conditional skip'))
def skip_unless(condition, msg=None):
"""
**DEPRECATED**: use pytest.mark.skipif instead.
Decorator to skip test if condition is false.
"""
return pytest.mark.skipif(not condition, reason=(msg or 'conditional skip'))
def with_tempdir(func):
"""
**DEPRECATED**: use tempdir fixture instead.
"""
return func
def raises(exc, func, *args, **kwds):
"""
**DEPRECATED**: use pytest.raises instead.
Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*.
"""
with pytest.raises(exc):
func(*args, **kwds)
def raises_msg(exc, msg, func, *args, **kwds):
"""
**DEPRECATED**: use pytest.raises instead.
Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*,
and check if the message contains *msg*.
"""
with pytest.raises(exc) as excinfo:
func(*args, **kwds)
assert msg in str(excinfo.value)
def assert_true(v1, msg=''):
"""
**DEPRECATED**: use assert instead.
"""
assert v1, msg
def assert_equal(v1, v2, msg=''):
"""
**DEPRECATED**: use assert instead.
"""
assert v1 == v2, msg
def assert_in(x, thing, msg=''):
"""
**DEPRECATED**: use assert instead.
"""
if x not in thing:
assert False, msg or '%r is not in %r' % (x, thing)
def assert_not_in(x, thing, msg=''):
"""
**DEPRECATED**: use assert instead.
"""
if x in thing:
assert False, msg or '%r is in %r' % (x, thing)
class ListOutput(object):
"""
File-like object that collects written text in a list.
"""
def __init__(self, name):
self.name = name
self.content = []
def reset(self):
del self.content[:]
def write(self, text):
self.content.append(text)
# **DEPRECATED**: use pytest.skip instead.
SkipTest = pytest.skip.Exception
class _DeprecationWrapper(object):
def __init__(self, mod, deprecated):
self._mod = mod
self._deprecated = deprecated
def __getattr__(self, attr):
if attr in self._deprecated:
obj, instead = self._deprecated[attr]
warnings.warn("tests/util.py::%s is deprecated and will be "
"removed in Sphinx 1.7, please use %s instead."
% (attr, instead),
RemovedInSphinx17Warning, stacklevel=2)
return obj
return getattr(self._mod, attr)
sys.modules[__name__] = _DeprecationWrapper(sys.modules[__name__], dict( # type: ignore
with_app=(pytest.mark.sphinx, 'pytest.mark.sphinx'),
TestApp=(SphinxTestApp, 'SphinxTestApp'),
gen_with_app=(gen_with_app, 'pytest.mark.parametrize'),
skip_if=(skip_if, 'pytest.skipif'),
skip_unless=(skip_unless, 'pytest.skipif'),
with_tempdir=(with_tempdir, 'tmpdir pytest fixture'),
raises=(raises, 'pytest.raises'),
raises_msg=(raises_msg, 'pytest.raises'),
assert_true=(assert_true, 'assert'),
assert_equal=(assert_equal, 'assert'),
assert_in=(assert_in, 'assert'),
assert_not_in=(assert_not_in, 'assert'),
ListOutput=(ListOutput, 'StringIO'),
SkipTest=(SkipTest, 'pytest.skip'),
))