mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
pytest migration
This commit is contained in:
parent
54c8c01222
commit
5b7d237db3
@ -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:
|
||||
|
7
Makefile
7
Makefile
@ -72,14 +72,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
|
||||
|
@ -1,6 +1,6 @@
|
||||
flake8
|
||||
nose
|
||||
nose-timer
|
||||
pytest>=3.0
|
||||
pytest-cov
|
||||
mock
|
||||
six>=1.4
|
||||
Jinja2>=2.3
|
||||
|
231
tests/conftest.py
Normal file
231
tests/conftest.py
Normal file
@ -0,0 +1,231 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
from six import StringIO, string_types
|
||||
|
||||
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
|
||||
def test_params(request):
|
||||
"""
|
||||
test parameters that is specified by 'pytest.mark.testenv'
|
||||
|
||||
:param bool build:
|
||||
If True, 'app' fixture will be build before test function is called.
|
||||
Default is False.
|
||||
:param Union[str, bool, None] specific_srcdir:
|
||||
If True, testroot directory will be copied into
|
||||
'<TMPDIR>/<TEST FUNCTION NAME>'.
|
||||
If string is specified, it copied into '<TMPDIR>/<THE STRING>'.
|
||||
You can used this feature for providing special crafted source
|
||||
directory. Also you can used for sharing source directory for
|
||||
parametrized testing and/or inter test functions. Default is None.
|
||||
:param Union[str, bool, None] shared_result:
|
||||
If True, app._status and app._warning objects will be shared in the
|
||||
parametrized test functions. If string is specified, the objects will
|
||||
be shred in the test functions that have same 'shared_result' value.
|
||||
If you don't specify specific_srcdir, this option override
|
||||
specific_srcdir param by 'shared_result' value. Default is None.
|
||||
"""
|
||||
env = request.node.get_marker('testenv')
|
||||
kwargs = env.kwargs if env else {}
|
||||
result = {
|
||||
'build': False, # pre build in fixture
|
||||
'specific_srcdir': None,
|
||||
'shared_result': None,
|
||||
}
|
||||
result.update(kwargs)
|
||||
|
||||
if (result['shared_result'] and
|
||||
not isinstance(result['shared_result'], string_types)):
|
||||
r = result['shared_result'] = request.node.originalname or request.node.name
|
||||
|
||||
if result['shared_result'] and not result['specific_srcdir']:
|
||||
result['specific_srcdir'] = result['shared_result']
|
||||
|
||||
if (result['specific_srcdir'] and
|
||||
not isinstance(result['specific_srcdir'], string_types)):
|
||||
result['specific_srcdir'] = request.node.originalname or request.node.name
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def app(test_params, app_params, make_app, shared_result):
|
||||
"""
|
||||
provides sphinx.application.Sphinx object
|
||||
"""
|
||||
args, kwargs = app_params
|
||||
if test_params['specific_srcdir'] and 'srcdir' not in kwargs:
|
||||
kwargs['srcdir'] = test_params['specific_srcdir']
|
||||
|
||||
if test_params['shared_result']:
|
||||
restore = shared_result.restore(test_params['shared_result'])
|
||||
kwargs.update(restore)
|
||||
|
||||
app_ = make_app(*args, **kwargs)
|
||||
|
||||
if test_params['build']:
|
||||
# if listdir is not empty, we can use built cache
|
||||
if not app_.outdir.listdir():
|
||||
app_.build()
|
||||
yield app_
|
||||
|
||||
if test_params['shared_result']:
|
||||
shared_result.store(test_params['shared_result'], 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()
|
||||
|
||||
|
||||
class SharedResult(object):
|
||||
cache = {}
|
||||
|
||||
def store(self, key, app_):
|
||||
if key in self.cache:
|
||||
return
|
||||
data = {
|
||||
'status': app_._status.getvalue(),
|
||||
'warning': app_._warning.getvalue(),
|
||||
}
|
||||
self.cache[key] = data
|
||||
|
||||
def restore(self, key):
|
||||
if key not in self.cache:
|
||||
return {}
|
||||
data = self.cache[key]
|
||||
return {
|
||||
'status': StringIO(data['status']),
|
||||
'warning': StringIO(data['warning']),
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def shared_result():
|
||||
return SharedResult()
|
||||
|
||||
|
||||
@pytest.fixture(scope='module', autouse=True)
|
||||
def _shared_result_cache():
|
||||
SharedResult.cache.clear()
|
||||
|
||||
|
||||
@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)
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
"""
|
||||
the test that have pytest.mark.env('foobar') will be skipped when
|
||||
'-S foobar' command-line option is provided.
|
||||
"""
|
||||
parser.addoption("-S", action="store", metavar="NAME",
|
||||
help="skip tests matching the environment NAME.")
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
"""
|
||||
the test that have pytest.mark.env('foobar') will be skipped when
|
||||
'-S foobar' command-line option is provided.
|
||||
"""
|
||||
# register an additional marker
|
||||
config.addinivalue_line("markers",
|
||||
"env(name): mark test to run only on named environment")
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
"""
|
||||
the test that have pytest.mark.env('foobar') will be skipped when
|
||||
'-S foobar' command-line option is provided.
|
||||
"""
|
||||
envmarker = item.get_marker("env")
|
||||
if envmarker is not None:
|
||||
envname = envmarker.args[0]
|
||||
if envname == item.config.getoption("-S"):
|
||||
pytest.skip("skip test %r" % envname)
|
1158
tests/coverage.py
1158
tests/coverage.py
File diff suppressed because it is too large
Load Diff
@ -145,7 +145,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())
|
||||
contents = repr_as(text, '<%s contents: %r>' % (self.basename(), text))
|
||||
return contents
|
||||
|
||||
def bytes(self):
|
||||
|
@ -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)
|
@ -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
|
||||
|
@ -11,7 +11,7 @@ class DummyTestParser(Parser):
|
||||
pass
|
||||
|
||||
|
||||
extensions = ['test_source_parser']
|
||||
extensions = ['source_parser']
|
||||
source_suffix = ['.rst', '.test']
|
||||
source_parsers = {
|
||||
'.test': DummyTestParser
|
||||
|
@ -11,7 +11,7 @@ class DummyMarkdownParser(Parser):
|
||||
pass
|
||||
|
||||
|
||||
extensions = ['test_source_parser']
|
||||
extensions = ['source_parser']
|
||||
source_suffix = ['.rst', '.md']
|
||||
source_parsers = {
|
||||
'.md': DummyMarkdownParser
|
||||
|
16
tests/run.py
16
tests/run.py
@ -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))
|
||||
|
@ -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())
|
||||
|
@ -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')
|
||||
|
@ -78,12 +78,12 @@ def test_build_all():
|
||||
|
||||
|
||||
@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:
|
||||
|
@ -15,9 +15,9 @@ import re
|
||||
import gettext
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from nose.tools import assert_true, assert_equal
|
||||
|
||||
from util import with_app, gen_with_app, SkipTest, assert_in
|
||||
from util import (
|
||||
with_app, gen_with_app, SkipTest, assert_in, assert_true, assert_equal
|
||||
)
|
||||
|
||||
|
||||
@gen_with_app('gettext', srcdir='root-gettext')
|
||||
@ -76,7 +76,7 @@ def test_all(app, status, warning):
|
||||
yield assert_equal, _("Testing various markup"), u"Testing various markup"
|
||||
|
||||
|
||||
@with_app('gettext', testroot='intl',
|
||||
@with_app('gettext', testroot='intl', srcdir='gettext',
|
||||
confoverrides={'gettext_compact': False})
|
||||
def test_gettext_index_entries(app, status, warning):
|
||||
# regression test for #976
|
||||
@ -123,7 +123,7 @@ def test_gettext_index_entries(app, status, warning):
|
||||
assert msgids == []
|
||||
|
||||
|
||||
@with_app('gettext', testroot='intl',
|
||||
@with_app('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
|
||||
@ -155,7 +155,7 @@ def test_gettext_disable_index_entries(app, status, warning):
|
||||
assert msgids == []
|
||||
|
||||
|
||||
@with_app(buildername='gettext', testroot='intl')
|
||||
@with_app(buildername='gettext', testroot='intl', srcdir='gettext')
|
||||
def test_gettext_template(app, status, warning):
|
||||
app.builder.build_all()
|
||||
assert (app.outdir / 'sphinx.pot').isfile()
|
||||
|
@ -24,10 +24,7 @@ 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 +33,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 + """\
|
||||
@ -662,7 +659,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 +760,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 +865,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 +966,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()
|
||||
|
@ -12,11 +12,11 @@ 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
|
||||
@ -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,)
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
"""
|
||||
import shutil
|
||||
|
||||
from nose.tools import with_setup
|
||||
import pytest
|
||||
|
||||
from util import with_app, find_files, rootdir, tempdir
|
||||
|
||||
@ -19,6 +19,7 @@ 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,12 +31,12 @@ 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)
|
||||
@pytest.mark.usefixtures('setup_test')
|
||||
@with_app(buildername='html', testroot='intl',
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_all_catalogs(app, status, warning):
|
||||
@ -51,7 +52,7 @@ def test_compile_all_catalogs(app, status, warning):
|
||||
assert actual == expect
|
||||
|
||||
|
||||
@with_setup(setup_test, teardown_test)
|
||||
@pytest.mark.usefixtures('setup_test')
|
||||
@with_app(buildername='html', testroot='intl',
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_specific_catalogs(app, status, warning):
|
||||
@ -66,7 +67,7 @@ def test_compile_specific_catalogs(app, status, warning):
|
||||
assert actual == set(['admonitions.mo'])
|
||||
|
||||
|
||||
@with_setup(setup_test, teardown_test)
|
||||
@pytest.mark.usefixtures('setup_test')
|
||||
@with_app(buildername='html', testroot='intl',
|
||||
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
|
||||
def test_compile_update_catalogs(app, status, warning):
|
||||
|
@ -87,16 +87,16 @@ def test_extension_values(app, status, warning):
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_errors_warnings(dir):
|
||||
def test_errors_warnings(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')
|
||||
raises_msg(ConfigError, 'conf.py', Config, tempdir, 'conf.py', {}, None)
|
||||
|
||||
# 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(lambda warning: 1/0)
|
||||
assert cfg.project == u'Jägermeister'
|
||||
|
||||
@ -105,9 +105,9 @@ def test_errors_warnings(dir):
|
||||
# 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)
|
||||
warned = [False]
|
||||
|
||||
def warn(msg):
|
||||
@ -118,10 +118,10 @@ def test_errors_warnings(dir):
|
||||
|
||||
|
||||
@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')
|
||||
raises_msg(ConfigError, 'callable', TestApp, srcdir=tempdir)
|
||||
|
||||
|
||||
@mock.patch.object(sphinx, '__display_version__', '1.3.4')
|
||||
@ -152,12 +152,12 @@ def test_needs_sphinx():
|
||||
|
||||
|
||||
@with_tempdir
|
||||
def test_config_eol(tmpdir):
|
||||
def test_config_eol(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(lambda warning: 1/0)
|
||||
assert cfg.project == u'spam'
|
||||
|
||||
|
@ -54,7 +54,6 @@ def test_images():
|
||||
'http://www.python.org/logo.png')
|
||||
|
||||
tree = env.get_doctree('images')
|
||||
app._warning.reset()
|
||||
htmlbuilder = StandaloneHTMLBuilder(app)
|
||||
htmlbuilder.imgpath = 'dummy'
|
||||
htmlbuilder.post_process_images(tree)
|
||||
@ -64,7 +63,6 @@ def test_images():
|
||||
assert set(htmlbuilder.images.values()) == \
|
||||
set(['img.png', 'img1.png', 'simg.png', 'svgimg.svg', 'img.foo.png'])
|
||||
|
||||
app._warning.reset()
|
||||
latexbuilder = LaTeXBuilder(app)
|
||||
latexbuilder.post_process_images(tree)
|
||||
assert set(latexbuilder.images.keys()) == \
|
||||
|
@ -10,37 +10,14 @@
|
||||
"""
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
from functools import wraps
|
||||
|
||||
import pytest
|
||||
|
||||
from util import with_app, SkipTest
|
||||
|
||||
|
||||
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.usefixtures('if_graphviz_found')
|
||||
def test_graphviz_html(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
@ -61,7 +38,7 @@ def test_graphviz_html(app, status, warning):
|
||||
|
||||
|
||||
@with_app('latex', testroot='ext-graphviz')
|
||||
@skip_if_graphviz_not_found
|
||||
@pytest.mark.usefixtures('if_graphviz_found')
|
||||
def test_graphviz_latex(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
@ -81,7 +58,7 @@ def test_graphviz_latex(app, status, warning):
|
||||
|
||||
|
||||
@with_app('html', testroot='ext-graphviz', confoverrides={'language': 'xx'})
|
||||
@skip_if_graphviz_not_found
|
||||
@pytest.mark.usefixtures('if_graphviz_found')
|
||||
def test_graphviz_i18n(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
|
@ -12,12 +12,12 @@
|
||||
import re
|
||||
import sys
|
||||
from util import with_app, rootdir, raises
|
||||
from test_ext_graphviz import skip_if_graphviz_not_found
|
||||
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.usefixtures('if_graphviz_found')
|
||||
def test_inheritance_diagram_html(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
@ -32,7 +32,7 @@ def test_inheritance_diagram_html(app, status, warning):
|
||||
|
||||
|
||||
@with_app('latex', testroot='ext-inheritance_diagram')
|
||||
@skip_if_graphviz_not_found
|
||||
@pytest.mark.usefixtures('if_graphviz_found')
|
||||
def test_inheritance_diagram_latex(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
|
@ -85,7 +85,7 @@ def test_read_inventory_v2():
|
||||
@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')
|
||||
|
||||
|
@ -18,12 +18,11 @@ 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
|
||||
|
||||
from util import tempdir, rootdir, path, gen_with_app, with_app, SkipTest, \
|
||||
assert_re_search, assert_not_re_search, assert_in, assert_not_in, \
|
||||
assert_startswith, assert_node, repr_as, etree_parse
|
||||
assert_startswith, assert_node, repr_as, etree_parse, assert_equal
|
||||
|
||||
|
||||
root = tempdir / 'test-intl'
|
||||
|
@ -14,8 +14,6 @@
|
||||
|
||||
from util import with_app
|
||||
|
||||
from nose.tools import assert_equal
|
||||
|
||||
|
||||
@with_app('pseudoxml')
|
||||
def test_docinfo(app, status, warning):
|
||||
@ -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
|
||||
|
@ -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,46 @@ def test_build_sphinx_with_nonascii_path(pkgroot, proc):
|
||||
|
||||
%(mb_name)s/%(mb_name)s
|
||||
""" % locals())
|
||||
).encode('utf-8'))
|
||||
).encode('utf-8'))
|
||||
|
||||
|
||||
def test_build_sphinx_with_nonascii_path(setup_command, nonascii_srcdir):
|
||||
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)
|
||||
|
@ -83,7 +83,8 @@ def test_js_source(app, status, warning):
|
||||
assert 'Underscore.js {v}'.format(v=v) in underscore_src, msg
|
||||
|
||||
|
||||
def test_double_inheriting_theme():
|
||||
@with_app(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 +93,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)
|
||||
|
@ -25,32 +25,32 @@ class DummyTemplateLoader(BuiltinTemplateLoader):
|
||||
|
||||
|
||||
@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 +58,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)
|
||||
@ -69,11 +69,11 @@ def test_copy_asset_file(tmpdir):
|
||||
|
||||
|
||||
@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 +84,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 +104,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()
|
||||
|
@ -38,12 +38,12 @@ def test_catalog_info_for_sub_domain_file_and_path():
|
||||
|
||||
|
||||
@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
|
||||
|
||||
@ -52,9 +52,9 @@ def test_catalog_outdated(dir):
|
||||
|
||||
|
||||
@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:
|
||||
@ -62,20 +62,20 @@ def test_catalog_write_mo(dir):
|
||||
|
||||
|
||||
@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',
|
||||
@ -86,23 +86,23 @@ 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
|
||||
|
||||
|
||||
@ -112,24 +112,24 @@ def test_get_catalogs_with_non_existent_locale_dirs():
|
||||
|
||||
|
||||
@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',
|
||||
@ -140,28 +140,28 @@ 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'])
|
||||
|
||||
|
@ -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
|
||||
|
||||
import pytest
|
||||
from util import rootdir, tempdir, raises, 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):
|
||||
@ -59,7 +57,7 @@ def test_no_srcdir(support):
|
||||
|
||||
|
||||
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
|
||||
@with_support(srcdir=rootdir / 'root')
|
||||
@with_support()
|
||||
def test_build(support):
|
||||
support.build()
|
||||
|
||||
@ -123,56 +121,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):
|
||||
@ -194,6 +142,38 @@ def test_user_delete_comments(support):
|
||||
assert comment['text'] == '[deleted]'
|
||||
|
||||
|
||||
called = False
|
||||
|
||||
|
||||
def moderation_callback(comment):
|
||||
global called
|
||||
called = True
|
||||
|
||||
|
||||
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
|
||||
@with_support(moderation_callback=moderation_callback)
|
||||
def test_moderation(support):
|
||||
session = Session()
|
||||
nodes = session.query(Node).all()
|
||||
node = nodes[7]
|
||||
session.close()
|
||||
accepted = support.add_comment('Accepted Comment', node_id=node.id,
|
||||
displayed=False)
|
||||
deleted = support.add_comment('Comment to delete', node_id=node.id,
|
||||
displayed=False)
|
||||
# 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'])
|
||||
support.accept_comment(accepted['id'], moderator=True)
|
||||
support.delete_comment(deleted['id'], moderator=True)
|
||||
comments = support.get_data(node.id)['comments']
|
||||
assert len(comments) == 1
|
||||
comments = support.get_data(node.id, moderator=True)['comments']
|
||||
assert len(comments) == 1
|
||||
|
||||
|
||||
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
|
||||
@with_support()
|
||||
def test_moderator_delete_comments(support):
|
||||
@ -228,36 +208,54 @@ def test_update_username(support):
|
||||
assert len(votes) == 0
|
||||
|
||||
|
||||
called = False
|
||||
@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)
|
||||
|
||||
def moderation_callback(comment):
|
||||
global called
|
||||
called = True
|
||||
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(moderation_callback=moderation_callback)
|
||||
def test_moderation(support):
|
||||
@with_support()
|
||||
def test_voting(support):
|
||||
session = Session()
|
||||
nodes = session.query(Node).all()
|
||||
node = nodes[7]
|
||||
session.close()
|
||||
accepted = support.add_comment('Accepted Comment', node_id=node.id,
|
||||
displayed=False)
|
||||
deleted = support.add_comment('Comment to delete', node_id=node.id,
|
||||
displayed=False)
|
||||
# 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'])
|
||||
support.accept_comment(accepted['id'], moderator=True)
|
||||
support.delete_comment(deleted['id'], moderator=True)
|
||||
comments = support.get_data(node.id)['comments']
|
||||
assert len(comments) == 1
|
||||
comments = support.get_data(node.id, moderator=True)['comments']
|
||||
assert len(comments) == 1
|
||||
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']
|
||||
|
||||
|
||||
def test_differ():
|
||||
|
313
tests/util.py
313
tests/util.py
@ -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
|
||||
|
||||
|
||||
__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'),
|
||||
))
|
||||
|
Loading…
Reference in New Issue
Block a user