Merge branch 'stable'

This commit is contained in:
Takeshi KOMIYA 2017-01-10 01:04:21 +09:00
commit 8cbe1efe8d
23 changed files with 1973 additions and 1588 deletions

View File

@ -82,6 +82,7 @@ Bugs fixed
* #3268: Sphinx crashes with requests package from Debian jessie
* #3284: Sphinx crashes on parallel build with an extension which raises
unserializable exception
* #3315: Bibliography crashes on latex build with docclass 'memoir'
Release 1.5.1 (released Dec 13, 2016)

View File

@ -6,7 +6,7 @@ PYTHON ?= python
DONT_CHECK = -i build -i dist -i sphinx/style/jquery.js \
-i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py \
-i .ropeproject -i doc/_build -i tests/path.py \
-i tests/coverage.py -i utils/convert.py \
-i utils/convert.py \
-i tests/typing_test_data.py \
-i tests/test_autodoc_py35.py \
-i tests/roots/test-warnings/undecodable.rst \

View File

@ -712,13 +712,13 @@ class StandardDomain(Domain):
else:
title = env.config.numfig_format.get(figtype, '')
if figname is None and '%{name}' in title:
if figname is None and '{name}' in title:
logger.warning('the link has no caption: %s', title, location=node)
return contnode
else:
fignum = '.'.join(map(str, fignumber))
if '{name}' in title or 'number' in title:
# new style format (cf. "Fig.%{number}")
# new style format (cf. "Fig.{number}")
if figname:
newtitle = title.format(name=figname, number=fignum)
else:

View File

@ -1082,8 +1082,14 @@
% make commands known to non-Sphinx document classes
\providecommand*{\sphinxtableofcontents}{\tableofcontents}
\providecommand*{\sphinxthebibliography}{\thebibliography}
\providecommand*{\sphinxtheindex}{\theindex}
\spx@ifundefined{sphinxthebibliography}
{\newenvironment
{sphinxthebibliography}{\begin{thebibliography}}{\end{thebibliography}}%
}
{}% else clause of ifundefined
\spx@ifundefined{sphinxtheindex}
{\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}}%
{}% else clause of ifundefined
% remove LaTeX's cap on nesting depth if 'maxlistdepth' key used.
% This is a hack, which works with the standard classes: it assumes \@toodeep

View File

@ -3,7 +3,7 @@ pytest>=3.0
pytest-cov
mock
six>=1.4
Jinja2>=2.3,<2.9
Jinja2>=2.3
Pygments>=2.0
docutils>=0.11
snowballstemmer>=1.1

View File

@ -1,19 +1,25 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys
import subprocess
from collections import namedtuple
import pytest
from six import StringIO
from six import StringIO, string_types
from util import SphinxTestApp, path
import util
@pytest.fixture
def app_params(request):
def app_params(request, test_params, shared_result):
"""
parameters that is specified by 'pytest.mark.sphinx' for
sphinx.application.Sphinx initialization
"""
# ##### process pytest.mark.sphinx
markers = request.node.get_marker("sphinx")
pargs = {}
kwargs = {}
@ -26,17 +32,99 @@ def app_params(request):
kwargs.update(info.kwargs)
args = [pargs[i] for i in sorted(pargs.keys())]
return args, kwargs
# ##### process pytest.mark.test_params
if test_params['shared_result']:
if 'srcdir' in kwargs:
raise pytest.Exception('You can not spcify shared_result and '
'srcdir in same time.')
kwargs['srcdir'] = test_params['shared_result']
restore = shared_result.restore(test_params['shared_result'])
kwargs.update(restore)
# ##### prepare Application params
if 'srcdir' in kwargs:
srcdir = util.tempdir / kwargs['srcdir']
else:
srcdir = util.tempdir / kwargs.get('testroot', 'root')
kwargs['srcdir'] = srcdir
if kwargs.get('testroot') is None:
testroot_path = util.rootdir / 'root'
else:
testroot_path = util.rootdir / 'roots' / ('test-' + kwargs['testroot'])
if not srcdir.exists():
testroot_path.copytree(srcdir)
return namedtuple('app_params', 'args,kwargs')(args, kwargs)
@pytest.fixture
def test_params(request):
"""
test parameters that is specified by 'pytest.mark.test_params'
:param Union[str] shared_result:
If the value is provided, app._status and app._warning objects will be
shared in the parametrized test functions and/or test functions that
have same 'shared_result' value.
**NOTE**: You can not specify shared_result and srcdir in same time.
"""
env = request.node.get_marker('test_params')
kwargs = env.kwargs if env else {}
result = {
'shared_result': None,
}
result.update(kwargs)
if (result['shared_result'] and
not isinstance(result['shared_result'], string_types)):
raise pytest.Exception('You can only provide a string type of value '
'for "shared_result" ')
return result
class SphinxTestAppWrapperForSkipBuilding(object):
"""
This class is a wrapper for SphinxTestApp to speed up the test by skipping
`app.build` process if it is already built and there is even one output
file.
"""
def __init__(self, app_):
self.app = app_
def __getattr__(self, name):
return getattr(self.app, name)
def build(self, *args, **kw):
if not self.app.outdir.listdir():
# if listdir is empty, do build.
self.app.build(*args, **kw)
# otherwise, we can use built cache
@pytest.fixture(scope='function')
def app(app_params, make_app):
def app(test_params, app_params, make_app, shared_result):
"""
provides sphinx.application.Sphinx object
"""
args, kwargs = app_params
app_ = make_app(*args, **kwargs)
return app_
yield app_
print('# testroot:', kwargs.get('testroot', 'root'))
print('# builder:', app_.buildername)
print('# srcdir:', app_.srcdir)
print('# outdir:', app_.outdir)
print('# status:', '\n' + app_._status.getvalue())
print('# warning:', '\n' + app_._warning.getvalue())
if test_params['shared_result']:
shared_result.store(test_params['shared_result'], app_)
@pytest.fixture(scope='function')
@ -56,7 +144,7 @@ def warning(app):
@pytest.fixture()
def make_app():
def make_app(test_params):
"""
provides make_app function to initialize SphinxTestApp instance.
if you want to initialize 'app' in your test function. please use this
@ -69,8 +157,10 @@ def make_app():
status, warning = StringIO(), StringIO()
kwargs.setdefault('status', status)
kwargs.setdefault('warning', warning)
app_ = SphinxTestApp(*args, **kwargs)
app_ = util.SphinxTestApp(*args, **kwargs)
apps.append(app_)
if test_params['shared_result']:
app_ = SphinxTestAppWrapperForSkipBuilding(app_)
return app_
yield make
@ -79,6 +169,38 @@ def make_app():
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):
"""
@ -105,4 +227,4 @@ def tempdir(tmpdir):
temporary directory that wrapped with `path` class.
this fixture is for compat with old test implementation.
"""
return path(tmpdir)
return util.path(tmpdir)

View File

@ -13,7 +13,7 @@
# "raises" imported for usage by autodoc
import six
import sys
from util import TestApp, Struct, raises, SkipTest
from util import SphinxTestApp, Struct
import pytest
from six import StringIO
@ -27,7 +27,7 @@ app = None
def setup_module():
global app
app = TestApp()
app = SphinxTestApp()
app.builder.env.app = app
app.builder.env.temp_data['docname'] = 'dummy'
app.connect('autodoc-process-docstring', process_docstring)
@ -185,7 +185,7 @@ def test_generate():
'Class.meth', more_content=add_content)
# test check_module
inst = FunctionDocumenter(directive, 'raises')
inst = FunctionDocumenter(directive, 'add_documenter')
inst.generate(check_module=True)
assert len(directive.result) == 0

View File

@ -17,11 +17,15 @@ import warnings
import traceback
from path import path
import pytest
testroot = os.path.dirname(__file__) or '.'
sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
# filter warnings of test dependencies
warnings.filterwarnings('ignore', category=DeprecationWarning, module='site') # virtualenv
warnings.filterwarnings('ignore', category=ImportWarning, module='backports')
warnings.filterwarnings('ignore', category=PendingDeprecationWarning, module=r'_pytest\..*')
# check dependencies before testing
print('Checking dependencies...')
for modname in ('pytest', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
@ -49,9 +53,6 @@ tempdir.makedirs()
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='site') # virtualenv
# 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))
@ -61,4 +62,5 @@ args = sys.argv[1:]
for path in ignore_paths:
args.extend(['--ignore', path])
import pytest
sys.exit(pytest.main(args))

View File

@ -10,8 +10,7 @@
:license: BSD, see LICENSE for details.
"""
# "raises" imported for usage by autodoc
from util import TestApp, Struct, raises, SkipTest # NOQA
from util import SphinxTestApp, Struct # NOQA
import pytest
import enum
@ -26,7 +25,7 @@ app = None
def setup_module():
global app
app = TestApp()
app = SphinxTestApp()
app.builder.env.app = app
app.builder.env.temp_data['docname'] = 'dummy'
app.connect('autodoc-process-docstring', process_docstring)
@ -125,26 +124,27 @@ def test_parse_name():
del _warnings[:]
# for functions/classes
verify('function', 'util.raises', ('util', ['raises'], None, None))
verify('function', 'util.raises(exc) -> None',
('util', ['raises'], 'exc', 'None'))
directive.env.temp_data['autodoc:module'] = 'util'
verify('function', 'raises', ('util', ['raises'], None, None))
verify('function', 'test_autodoc.raises',
('test_autodoc', ['raises'], None, None))
verify('function', 'test_autodoc.raises(exc) -> None',
('test_autodoc', ['raises'], 'exc', 'None'))
directive.env.temp_data['autodoc:module'] = 'test_autodoc'
verify('function', 'raises', ('test_autodoc', ['raises'], None, None))
del directive.env.temp_data['autodoc:module']
directive.env.ref_context['py:module'] = 'util'
verify('function', 'raises', ('util', ['raises'], None, None))
verify('class', 'TestApp', ('util', ['TestApp'], None, None))
directive.env.ref_context['py:module'] = 'test_autodoc'
verify('function', 'raises', ('test_autodoc', ['raises'], None, None))
verify('class', 'Base', ('test_autodoc', ['Base'], None, None))
# for members
directive.env.ref_context['py:module'] = 'foo'
verify('method', 'util.TestApp.cleanup',
('util', ['TestApp', 'cleanup'], None, None))
verify('method', 'util.SphinxTestApp.cleanup',
('util', ['SphinxTestApp', 'cleanup'], None, None))
directive.env.ref_context['py:module'] = 'util'
directive.env.ref_context['py:class'] = 'Foo'
directive.env.temp_data['autodoc:class'] = 'TestApp'
verify('method', 'cleanup', ('util', ['TestApp', 'cleanup'], None, None))
verify('method', 'TestApp.cleanup',
('util', ['TestApp', 'cleanup'], None, None))
directive.env.temp_data['autodoc:class'] = 'SphinxTestApp'
verify('method', 'cleanup', ('util', ['SphinxTestApp', 'cleanup'], None, None))
verify('method', 'SphinxTestApp.cleanup',
('util', ['SphinxTestApp', 'cleanup'], None, None))
# and clean up
del directive.env.ref_context['py:module']
@ -658,7 +658,7 @@ def test_generate():
'Class.meth', more_content=add_content)
# test check_module
inst = FunctionDocumenter(directive, 'raises')
inst = FunctionDocumenter(directive, 'add_documenter')
inst.generate(check_module=True)
assert len(directive.result) == 0
@ -878,6 +878,11 @@ __all__ = ['Class']
integer = 1
def raises(exc, func, *args, **kwds):
"""Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*."""
pass
class CustomEx(Exception):
"""My custom exception."""
@ -1086,7 +1091,7 @@ def test_type_hints():
try:
from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11
except (ImportError, SyntaxError):
raise SkipTest('Cannot import Python code with function annotations')
pytest.skip('Cannot import Python code with function annotations')
def verify_arg_spec(f, expected):
assert formatargspec(f, *getargspec(f)) == expected

View File

@ -15,14 +15,8 @@ import mock
import pytest
from textwrap import dedent
from sphinx.errors import SphinxError
import sphinx.builders.linkcheck
from util import rootdir, tempdir, SkipTest, TestApp, path
try:
from docutils.writers.manpage import Writer as ManWriter
except ImportError:
ManWriter = None
from util import rootdir, tempdir, path
def request_session_head(url, **kwargs):
@ -32,24 +26,17 @@ def request_session_head(url, **kwargs):
return response
def verify_build(buildername, srcdir):
if buildername == 'man' and ManWriter is None:
raise SkipTest('man writer is not available')
app = TestApp(buildername=buildername, srcdir=srcdir)
try:
app.builder.build_all()
finally:
app.cleanup()
def test_build_all():
@pytest.fixture
def nonascii_srcdir(request):
# If supported, build in a non-ASCII source dir
test_name = u'\u65e5\u672c\u8a9e'
basedir = tempdir / request.node.originalname
try:
srcdir = tempdir / test_name
(rootdir / 'root').copytree(tempdir / test_name)
srcdir = basedir / test_name
if not srcdir.exists():
(rootdir / 'root').copytree(srcdir)
except UnicodeEncodeError:
srcdir = tempdir / 'all'
srcdir = basedir / 'all'
else:
# add a doc with a non-ASCII file name to the source dir
(srcdir / (test_name + '.txt')).write_text(dedent("""
@ -63,31 +50,33 @@ def test_build_all():
%(test_name)s/%(test_name)s
""" % {'test_name': test_name})
)
)
return srcdir
with mock.patch('sphinx.builders.linkcheck.requests') as requests:
requests.head = request_session_head
@pytest.mark.parametrize(
"buildername",
[
# note: no 'html' - if it's ok with dirhtml it's ok with html
for buildername in ['dirhtml', 'singlehtml', 'latex', 'texinfo', 'pickle',
'json', 'text', 'htmlhelp', 'qthelp', 'epub2', 'epub',
'applehelp', 'changes', 'xml', 'pseudoxml', 'man',
'linkcheck']:
yield verify_build, buildername, srcdir
'dirhtml', 'singlehtml', 'latex', 'texinfo', 'pickle', 'json', 'text',
'htmlhelp', 'qthelp', 'epub2', 'epub', 'applehelp', 'changes', 'xml',
'pseudoxml', 'man', 'linkcheck',
],
)
@mock.patch('sphinx.builders.linkcheck.requests.head',
side_effect=request_session_head)
def test_build_all(requests_head, make_app, nonascii_srcdir, buildername):
app = make_app(buildername, srcdir=nonascii_srcdir)
app.build()
def test_master_doc_not_found(tempdir):
def test_master_doc_not_found(tempdir, make_app):
(tempdir / 'conf.py').write_text('master_doc = "index"')
assert tempdir.listdir() == ['conf.py']
try:
app = TestApp(buildername='dummy', srcdir=tempdir)
app = make_app('dummy', srcdir=tempdir)
with pytest.raises(SphinxError):
app.builder.build_all()
assert False # SphinxError not raised
except Exception as exc:
assert isinstance(exc, SphinxError)
finally:
app.cleanup()
@pytest.mark.sphinx(buildername='text', testroot='circular')

View File

@ -17,36 +17,36 @@ from subprocess import Popen, PIPE
import pytest
from util import (
gen_with_app, SkipTest, assert_in, assert_true, assert_equal
)
from sphinx.util.osutil import cd
@gen_with_app('gettext', srcdir='root-gettext')
def test_all(app, status, warning):
@pytest.mark.sphinx('gettext', srcdir='root-gettext')
def test_build_gettext(app):
# Generic build; should fail only when the builder is horribly broken.
app.builder.build_all()
# Do messages end up in the correct location?
# top-level documents end up in a message catalog
yield assert_true, (app.outdir / 'extapi.pot').isfile()
assert (app.outdir / 'extapi.pot').isfile()
# directory items are grouped into sections
yield assert_true, (app.outdir / 'subdir.pot').isfile()
assert (app.outdir / 'subdir.pot').isfile()
# regression test for issue #960
catalog = (app.outdir / 'markup.pot').text(encoding='utf-8')
yield assert_in, 'msgid "something, something else, something more"', catalog
assert 'msgid "something, something else, something more"' in catalog
@pytest.mark.sphinx('gettext', srcdir='root-gettext')
def test_msgfmt(app):
app.builder.build_all()
(app.outdir / 'en' / 'LC_MESSAGES').makedirs()
cwd = os.getcwd()
os.chdir(app.outdir)
try:
with cd(app.outdir):
try:
p = Popen(['msginit', '--no-translator', '-i', 'markup.pot',
'--locale', 'en_US'],
stdout=PIPE, stderr=PIPE)
except OSError:
raise SkipTest # most likely msginit was not found
pytest.skip() # most likely msginit was not found
else:
stdout, stderr = p.communicate()
if p.returncode != 0:
@ -54,13 +54,13 @@ def test_all(app, status, warning):
print(stderr)
assert False, 'msginit exited with return code %s' % \
p.returncode
yield assert_true, (app.outdir / 'en_US.po').isfile(), 'msginit failed'
assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
try:
p = Popen(['msgfmt', 'en_US.po', '-o',
os.path.join('en', 'LC_MESSAGES', 'test_root.mo')],
stdout=PIPE, stderr=PIPE)
except OSError:
raise SkipTest # most likely msgfmt was not found
pytest.skip() # most likely msgfmt was not found
else:
stdout, stderr = p.communicate()
if p.returncode != 0:
@ -68,20 +68,17 @@ def test_all(app, status, warning):
print(stderr)
assert False, 'msgfmt exited with return code %s' % \
p.returncode
yield (assert_true,
(app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo').isfile(),
'msgfmt failed')
finally:
os.chdir(cwd)
mo = app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo'
assert mo.isfile(), 'msgfmt failed'
_ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
yield assert_equal, _("Testing various markup"), u"Testing various markup"
assert _("Testing various markup") == u"Testing various markup"
@pytest.mark.sphinx(
'gettext', testroot='intl', srcdir='gettext',
confoverrides={'gettext_compact': False})
def test_gettext_index_entries(app, status, warning):
def test_gettext_index_entries(app):
# regression test for #976
app.builder.build(['index_entries'])
@ -128,8 +125,9 @@ def test_gettext_index_entries(app, status, warning):
@pytest.mark.sphinx(
'gettext', testroot='intl', srcdir='gettext',
confoverrides={'gettext_compact': False, 'gettext_additional_targets': []})
def test_gettext_disable_index_entries(app, status, warning):
confoverrides={'gettext_compact': False,
'gettext_additional_targets': []})
def test_gettext_disable_index_entries(app):
# regression test for #976
app.builder.build(['index_entries'])
@ -160,7 +158,7 @@ def test_gettext_disable_index_entries(app, status, warning):
@pytest.mark.sphinx('gettext', testroot='intl', srcdir='gettext')
def test_gettext_template(app, status, warning):
def test_gettext_template(app):
app.builder.build_all()
assert (app.outdir / 'sphinx.pot').isfile()

File diff suppressed because it is too large Load Diff

View File

@ -13,9 +13,6 @@ from six import PY3, iteritems
import pytest
import mock
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
@ -76,7 +73,6 @@ def test_core_config(app, status, warning):
assert cfg['project'] == cfg.project == 'Sphinx Tests'
@pytest.mark.sphinx()
def test_extension_values(app, status, warning):
cfg = app.config
@ -125,39 +121,39 @@ def test_errors_warnings(logger, tempdir):
assert logger.warning.called is True
def test_errors_if_setup_is_not_callable(tempdir):
def test_errors_if_setup_is_not_callable(tempdir, make_app):
# test the error to call setup() in the config file
(tempdir / 'conf.py').write_text(u'setup = 1')
with pytest.raises(ConfigError) as excinfo:
TestApp(srcdir=tempdir)
make_app(srcdir=tempdir)
assert 'callable' in str(excinfo.value)
@mock.patch.object(sphinx, '__display_version__', '1.3.4')
def test_needs_sphinx():
def test_needs_sphinx(make_app):
# micro version
app = TestApp(confoverrides={'needs_sphinx': '1.3.3'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '1.3.3'}) # OK: less
app.cleanup()
app = TestApp(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
app = make_app(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
app.cleanup()
with pytest.raises(VersionRequirementError):
TestApp(confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
make_app(confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
# minor version
app = TestApp(confoverrides={'needs_sphinx': '1.2'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '1.2'}) # OK: less
app.cleanup()
app = TestApp(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
app = make_app(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
app.cleanup()
with pytest.raises(VersionRequirementError):
TestApp(confoverrides={'needs_sphinx': '1.4'}) # NG: greater
make_app(confoverrides={'needs_sphinx': '1.4'}) # NG: greater
# major version
app = TestApp(confoverrides={'needs_sphinx': '0'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '0'}) # OK: less
app.cleanup()
app = TestApp(confoverrides={'needs_sphinx': '1'}) # OK: equals
app = make_app(confoverrides={'needs_sphinx': '1'}) # OK: equals
app.cleanup()
with pytest.raises(VersionRequirementError):
TestApp(confoverrides={'needs_sphinx': '2'}) # NG: greater
make_app(confoverrides={'needs_sphinx': '2'}) # NG: greater
@mock.patch("sphinx.config.logger")
@ -177,12 +173,14 @@ def test_config_eol(logger, tempdir):
'primary_domain': None})
def test_builtin_conf(app, status, warning):
warnings = warning.getvalue()
assert_in('master_doc', warnings,
'override on builtin "master_doc" should raise a type warning')
assert_not_in('language', warnings, 'explicitly permitted '
'override on builtin "language" should NOT raise a type warning')
assert_not_in('primary_domain', warnings, 'override to None on builtin '
'"primary_domain" should NOT raise a type warning')
assert 'master_doc' in warnings, (
'override on builtin "master_doc" should raise a type warning')
assert 'language' not in warnings, (
'explicitly permitted override on builtin "language" should NOT raise '
'a type warning')
assert 'primary_domain' not in warnings, (
'override to None on builtin "primary_domain" should NOT raise a type '
'warning')
# See roots/test-config/conf.py.
@ -197,7 +195,7 @@ TYPECHECK_WARNINGS = {
'value8': False,
'value9': False,
'value10': False,
'value11': True,
'value11': False if PY3 else True,
'value12': False,
'value13': False,
'value14': False,
@ -206,15 +204,17 @@ TYPECHECK_WARNINGS = {
}
@gen_with_app(testroot='config')
def test_gen_check_types(app, status, warning):
if PY3:
TYPECHECK_WARNINGS['value11'] = False
for key, should in iteritems(TYPECHECK_WARNINGS):
yield assert_in if should else assert_not_in, key, warning.getvalue(), (
'override on "%s" should%s raise a type warning' %
(key, '' if should else ' NOT')
@pytest.mark.parametrize("key,should", iteritems(TYPECHECK_WARNINGS))
@pytest.mark.sphinx(testroot='config')
def test_check_types(warning, key, should):
warn = warning.getvalue()
if should:
assert key in warn, (
'override on "%s" should raise a type warning' % key
)
else:
assert key not in warn, (
'override on "%s" should NOT raise a type warning' % key
)

View File

@ -8,42 +8,30 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
from util import TestApp
import pytest
def test_correct_year():
try:
# save current value of SOURCE_DATE_EPOCH
sde = os.environ.pop('SOURCE_DATE_EPOCH', None)
@pytest.fixture(
params=[
# test with SOURCE_DATE_EPOCH unset: no modification
app = TestApp(buildername='html', testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
assert '2006-2009' in content
(None, '2006-2009'),
# test with SOURCE_DATE_EPOCH set: copyright year should be updated
('1293840000', '2006-2011'),
('1293839999', '2006-2010'),
],
# test with SOURCE_DATE_EPOCH set: copyright year should be
# updated
os.environ['SOURCE_DATE_EPOCH'] = "1293840000"
app = TestApp(buildername='html', testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
assert '2006-2011' in content
)
def expect_date(request, monkeypatch):
sde, expect = request.param
if sde:
monkeypatch.setenv('SOURCE_DATE_EPOCH', sde)
else:
monkeypatch.delenv('SOURCE_DATE_EPOCH', raising=False)
yield expect
os.environ['SOURCE_DATE_EPOCH'] = "1293839999"
app = TestApp(buildername='html', testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
assert '2006-2010' in content
finally:
# Restores SOURCE_DATE_EPOCH
if sde is None:
os.environ.pop('SOURCE_DATE_EPOCH', None)
else:
os.environ['SOURCE_DATE_EPOCH'] = sde
@pytest.mark.sphinx('html', testroot='correct-year')
def test_correct_year(expect_date, app):
app.build()
content = (app.outdir / 'contents.html').text()
assert expect_date in content

View File

@ -9,9 +9,7 @@
:license: BSD, see LICENSE for details.
"""
from six import StringIO
from util import TestApp, path
from util import SphinxTestApp, path
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.builders.latex import LaTeXBuilder
@ -21,7 +19,7 @@ app = env = None
def setup_module():
global app, env
app = TestApp(srcdir='root-envtest', warning=StringIO())
app = SphinxTestApp(srcdir='root-envtest')
env = app.env

View File

@ -16,23 +16,13 @@ from sphinx.addnodes import compact_paragraph, only
from sphinx.builders.html import StandaloneHTMLBuilder
import pytest
from util import gen_with_app, assert_node
from util import assert_node
@gen_with_app('xml', testroot='toctree')
def test_basic(app, status, warning):
@pytest.mark.sphinx('xml', testroot='toctree')
@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
def test_process_doc(app):
app.build()
yield _test_process_doc, app
yield _test_get_toc_for, app
yield _test_get_toc_for_only, app
yield _test_get_toc_for_tocdepth, app
yield _test_get_toctree_for, app
yield _test_get_toctree_for_collapse, app
yield _test_get_toctree_for_maxdepth, app
yield _test_get_toctree_for_includehidden, app
def _test_process_doc(app):
# tocs
toctree = app.env.tocs['index']
assert_node(toctree,
@ -99,7 +89,7 @@ def _test_process_doc(app):
@pytest.mark.sphinx('dummy', testroot='toctree-glob')
def test_glob(app, status, warning):
def test_glob(app):
includefiles = ['foo', 'bar/index', 'bar/bar_1', 'bar/bar_2',
'bar/bar_3', 'baz', 'qux/index']
@ -144,7 +134,10 @@ def test_glob(app, status, warning):
assert app.env.numbered_toctrees == set()
def _test_get_toc_for(app):
@pytest.mark.sphinx('xml', testroot='toctree')
@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
def test_get_toc_for(app):
app.build()
toctree = app.env.get_toc_for('index', app.builder)
assert_node(toctree,
@ -167,7 +160,10 @@ def _test_get_toc_for(app):
[compact_paragraph, reference, "Indices and tables"])
def _test_get_toc_for_only(app):
@pytest.mark.sphinx('xml', testroot='toctree')
@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
def test_get_toc_for_only(app):
app.build()
builder = StandaloneHTMLBuilder(app)
toctree = app.env.get_toc_for('index', builder)
@ -194,7 +190,10 @@ def _test_get_toc_for_only(app):
[compact_paragraph, reference, "Indices and tables"])
def _test_get_toc_for_tocdepth(app):
@pytest.mark.sphinx('xml', testroot='toctree')
@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
def test_get_toc_for_tocdepth(app):
app.build()
toctree = app.env.get_toc_for('tocdepth', app.builder)
assert_node(toctree,
@ -206,7 +205,10 @@ def _test_get_toc_for_tocdepth(app):
[bullet_list, list_item, compact_paragraph, reference, "level 2"])
def _test_get_toctree_for(app):
@pytest.mark.sphinx('xml', testroot='toctree')
@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
def test_get_toctree_for(app):
app.build()
toctree = app.env.get_toctree_for('index', app.builder, collapse=False)
assert_node(toctree,
[compact_paragraph, ([caption, "Table of Contents"],
@ -240,7 +242,10 @@ def _test_get_toctree_for(app):
assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
def _test_get_toctree_for_collapse(app):
@pytest.mark.sphinx('xml', testroot='toctree')
@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
def test_get_toctree_for_collapse(app):
app.build()
toctree = app.env.get_toctree_for('index', app.builder, collapse=True)
assert_node(toctree,
[compact_paragraph, ([caption, "Table of Contents"],
@ -265,7 +270,10 @@ def _test_get_toctree_for_collapse(app):
assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
def _test_get_toctree_for_maxdepth(app):
@pytest.mark.sphinx('xml', testroot='toctree')
@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
def test_get_toctree_for_maxdepth(app):
app.build()
toctree = app.env.get_toctree_for('index', app.builder, collapse=False, maxdepth=3)
assert_node(toctree,
[compact_paragraph, ([caption, "Table of Contents"],
@ -304,7 +312,10 @@ def _test_get_toctree_for_maxdepth(app):
assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
def _test_get_toctree_for_includehidden(app):
@pytest.mark.sphinx('xml', testroot='toctree')
@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
def test_get_toctree_for_includehidden(app):
app.build()
toctree = app.env.get_toctree_for('index', app.builder, collapse=False,
includehidden=False)
assert_node(toctree,

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ import re
import pickle
from docutils import frontend, utils, nodes
from docutils.parsers import rst
from docutils.parsers.rst import Parser as RstParser
from sphinx import addnodes
from sphinx.util import texescape
@ -22,31 +22,37 @@ from sphinx.writers.html import HTMLWriter, SmartyPantsHTMLTranslator
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
import pytest
from util import TestApp, assert_node
from util import assert_node
app = settings = parser = domain_context = None
def setup_module():
global app, settings, parser, domain_context
@pytest.fixture
def settings(app):
texescape.init() # otherwise done by the latex builder
app = TestApp()
optparser = frontend.OptionParser(
components=(rst.Parser, HTMLWriter, LaTeXWriter))
components=(RstParser, HTMLWriter, LaTeXWriter))
settings = optparser.get_default_values()
settings.env = app.builder.env
settings.env.temp_data['docname'] = 'dummy'
parser = rst.Parser()
domain_context = sphinx_domains(settings.env)
domain_context.enable()
def teardown_module():
app.cleanup()
yield settings
domain_context.disable()
@pytest.fixture
def parse(settings):
def parse_(rst):
document = utils.new_document(b'test data', settings)
document['file'] = 'dummy'
parser = RstParser()
parser.parse(rst, document)
for msg in document.traverse(nodes.system_message):
if msg['level'] == 1:
msg.replace_self([])
return document
return parse_
# since we're not resolving the markup afterwards, these nodes may remain
class ForgivingTranslator:
def visit_pending_xref(self, node):
@ -64,93 +70,158 @@ class ForgivingLaTeXTranslator(LaTeXTranslator, ForgivingTranslator):
pass
def verify_re(rst, html_expected, latex_expected):
document = utils.new_document(b'test data', settings)
document['file'] = 'dummy'
parser.parse(rst, document)
for msg in document.traverse(nodes.system_message):
if msg['level'] == 1:
msg.replace_self([])
if html_expected:
@pytest.fixture
def verify_re_html(app, parse):
def verify(rst, html_expected):
document = parse(rst)
html_translator = ForgivingHTMLTranslator(app.builder, document)
document.walkabout(html_translator)
html_translated = ''.join(html_translator.fragment).strip()
assert re.match(html_expected, html_translated), 'from ' + rst
return verify
if latex_expected:
@pytest.fixture
def verify_re_latex(app, parse):
def verify(rst, latex_expected):
document = parse(rst)
latex_translator = ForgivingLaTeXTranslator(document, app.builder)
latex_translator.first_document = -1 # don't write \begin{document}
document.walkabout(latex_translator)
latex_translated = ''.join(latex_translator.body).strip()
assert re.match(latex_expected, latex_translated), 'from ' + repr(rst)
return verify
def verify(rst, html_expected, latex_expected):
if html_expected:
html_expected = re.escape(html_expected) + '$'
if latex_expected:
latex_expected = re.escape(latex_expected) + '$'
verify_re(rst, html_expected, latex_expected)
@pytest.fixture
def verify_re(verify_re_html, verify_re_latex):
def verify_re_(rst, html_expected, latex_expected):
if html_expected:
return verify_re_html(rst, html_expected)
if latex_expected:
return verify_re_latex(rst, latex_expected)
return verify_re_
def test_inline():
# correct interpretation of code with whitespace
_html = ('<p><code class="(samp )?docutils literal"><span class="pre">'
'code</span>&#160;&#160; <span class="pre">sample</span></code></p>')
yield verify_re, '``code sample``', _html, r'\\sphinxcode{code sample}'
yield verify_re, ':samp:`code sample`', _html, r'\\sphinxcode{code sample}'
# interpolation of braces in samp and file roles (HTML only)
yield (verify, ':samp:`a{b}c`',
'<p><code class="samp docutils literal"><span class="pre">a</span>'
'<em><span class="pre">b</span></em>'
'<span class="pre">c</span></code></p>',
'\\sphinxcode{a\\sphinxstyleemphasis{b}c}')
# interpolation of arrows in menuselection
yield (verify, ':menuselection:`a --> b`',
u'<p><span class="menuselection">a \N{TRIANGULAR BULLET} b</span></p>',
'\\sphinxmenuselection{a \\(\\rightarrow\\) b}')
# interpolation of ampersands in guilabel/menuselection
yield (verify, ':guilabel:`&Foo -&&- &Bar`',
u'<p><span class="guilabel"><span class="accelerator">F</span>oo '
'-&amp;- <span class="accelerator">B</span>ar</span></p>',
r'\sphinxmenuselection{\sphinxaccelerator{F}oo -\&- \sphinxaccelerator{B}ar}')
# non-interpolation of dashes in option role
yield (verify_re, ':option:`--with-option`',
'<p><code( class="xref std std-option docutils literal")?>'
'<span class="pre">--with-option</span></code></p>$',
r'\\sphinxcode{-{-}with-option}$')
# verify smarty-pants quotes
yield verify, '"John"', '<p>&#8220;John&#8221;</p>', "``John''"
# ... but not in literal text
yield (verify, '``"John"``',
'<p><code class="docutils literal"><span class="pre">'
'&quot;John&quot;</span></code></p>',
'\\sphinxcode{"John"}')
# verify classes for inline roles
yield (verify, ':manpage:`mp(1)`',
'<p><em class="manpage">mp(1)</em></p>',
'\\sphinxstyleliteralemphasis{mp(1)}')
@pytest.fixture
def verify(verify_re_html, verify_re_latex):
def verify_(rst, html_expected, latex_expected):
if html_expected:
return verify_re_html(rst, re.escape(html_expected) + '$')
if latex_expected:
return verify_re_latex(rst, re.escape(latex_expected) + '$')
return verify_
def test_latex_escaping():
# correct escaping in normal mode
yield (verify, u'Γ\\\\∞$', None,
r'\(\Gamma\)\textbackslash{}\(\infty\)\$')
# in verbatim code fragments
yield (verify, u'::\n\n\\∞${}', None,
u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
u'\\end{sphinxVerbatim}')
# in URIs
yield (verify_re, u'`test <http://example.com/~me/>`_', None,
r'\\href{http://example.com/~me/}{test}.*')
@pytest.fixture
def get_verifier(verify, verify_re):
v = {
'verify': verify,
'verify_re': verify_re,
}
def get(name):
return v[name]
return get
@pytest.mark.parametrize('type,rst,html_expected,latex_expected', [
(
# correct interpretation of code with whitespace
'verify_re',
'``code sample``',
('<p><code class="(samp )?docutils literal"><span class="pre">'
'code</span>&#160;&#160; <span class="pre">sample</span></code></p>'),
r'\\sphinxcode{code sample}',
),
(
# correct interpretation of code with whitespace
'verify_re',
':samp:`code sample`',
('<p><code class="(samp )?docutils literal"><span class="pre">'
'code</span>&#160;&#160; <span class="pre">sample</span></code></p>'),
r'\\sphinxcode{code sample}',
),
(
# interpolation of braces in samp and file roles (HTML only)
'verify',
':samp:`a{b}c`',
('<p><code class="samp docutils literal"><span class="pre">a</span>'
'<em><span class="pre">b</span></em>'
'<span class="pre">c</span></code></p>'),
'\\sphinxcode{a\\sphinxstyleemphasis{b}c}',
),
(
# interpolation of arrows in menuselection
'verify',
':menuselection:`a --> b`',
(u'<p><span class="menuselection">a \N{TRIANGULAR BULLET} b</span></p>'),
'\\sphinxmenuselection{a \\(\\rightarrow\\) b}',
),
(
# interpolation of ampersands in guilabel/menuselection
'verify',
':guilabel:`&Foo -&&- &Bar`',
(u'<p><span class="guilabel"><span class="accelerator">F</span>oo '
'-&amp;- <span class="accelerator">B</span>ar</span></p>'),
r'\sphinxmenuselection{\sphinxaccelerator{F}oo -\&- \sphinxaccelerator{B}ar}',
),
(
# non-interpolation of dashes in option role
'verify_re',
':option:`--with-option`',
('<p><code( class="xref std std-option docutils literal")?>'
'<span class="pre">--with-option</span></code></p>$'),
r'\\sphinxcode{-{-}with-option}$',
),
(
# verify smarty-pants quotes
'verify',
'"John"',
'<p>&#8220;John&#8221;</p>',
"``John''",
),
(
# ... but not in literal text
'verify',
'``"John"``',
('<p><code class="docutils literal"><span class="pre">'
'&quot;John&quot;</span></code></p>'),
'\\sphinxcode{"John"}',
),
(
# verify classes for inline roles
'verify',
':manpage:`mp(1)`',
'<p><em class="manpage">mp(1)</em></p>',
'\\sphinxstyleliteralemphasis{mp(1)}',
),
(
# correct escaping in normal mode
'verify',
u'Γ\\\\∞$',
None,
r'\(\Gamma\)\textbackslash{}\(\infty\)\$',
),
(
# in verbatim code fragments
'verify',
u'::\n\n\\∞${}',
None,
(u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
u'\\end{sphinxVerbatim}'),
),
(
# in URIs
'verify_re',
u'`test <http://example.com/~me/>`_',
None,
r'\\href{http://example.com/~me/}{test}.*',
),
])
def test_inline(get_verifier, type, rst, html_expected, latex_expected):
verifier = get_verifier(type)
verifier(rst, html_expected, latex_expected)
@pytest.mark.sphinx('dummy', testroot='prolog')

View File

@ -12,30 +12,27 @@ from __future__ import print_function
import os
import datetime
from os import path
import pytest
from babel.messages.mofile import read_mo
from sphinx.util import i18n
from sphinx.errors import SphinxError
import pytest
from util import TestApp
def test_catalog_info_for_file_and_path():
cat = i18n.CatalogInfo('path', 'domain', 'utf-8')
assert cat.po_file == 'domain.po'
assert cat.mo_file == 'domain.mo'
assert cat.po_path == path.join('path', 'domain.po')
assert cat.mo_path == path.join('path', 'domain.mo')
assert cat.po_path == os.path.join('path', 'domain.po')
assert cat.mo_path == os.path.join('path', 'domain.mo')
def test_catalog_info_for_sub_domain_file_and_path():
cat = i18n.CatalogInfo('path', 'sub/domain', 'utf-8')
assert cat.po_file == 'sub/domain.po'
assert cat.mo_file == 'sub/domain.mo'
assert cat.po_path == path.join('path', 'sub/domain.po')
assert cat.mo_path == path.join('path', 'sub/domain.mo')
assert cat.po_path == os.path.join('path', 'sub/domain.po')
assert cat.mo_path == os.path.join('path', 'sub/domain.mo')
def test_catalog_outdated(tempdir):
@ -55,7 +52,7 @@ 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)
assert os.path.exists(cat.mo_path)
with open(cat.mo_path, 'rb') as f:
assert read_mo(f) is not None
@ -189,9 +186,7 @@ def test_format_date():
assert i18n.format_date(format, date=date) == 'Feb 7, 2016'
def test_get_filename_for_language():
app = TestApp()
def test_get_filename_for_language(app):
# language is None
app.env.config.language = None
assert app.env.config.language is None

View File

@ -17,6 +17,7 @@ from docutils import frontend
from sphinx.util.nodes import extract_messages, clean_astext
from sphinx.transforms import ApplySourceWorkaround
import pytest
def _transform(doctree):
@ -49,84 +50,63 @@ def assert_node_count(messages, node_type, expect_count):
% (node_type, node_list, count, expect_count))
def test_extract_messages():
text = dedent(
"""
.. admonition:: admonition title
@pytest.mark.parametrize(
'rst,node_cls,count',
[
(
"""
.. admonition:: admonition title
admonition body
"""
)
yield (
assert_node_count,
extract_messages(_get_doctree(text)),
nodes.title, 1,
)
admonition body
""",
nodes.title, 1
),
(
"""
.. figure:: foo.jpg
text = dedent(
"""
.. figure:: foo.jpg
this is title
""",
nodes.caption, 1,
),
(
"""
.. rubric:: spam
""",
nodes.rubric, 1,
),
(
"""
| spam
| egg
""",
nodes.line, 2,
),
(
"""
section
=======
this is title
"""
)
yield (
assert_node_count,
extract_messages(_get_doctree(text)),
nodes.caption, 1,
)
+----------------+
| | **Title 1** |
| | Message 1 |
+----------------+
""",
nodes.line, 2,
),
(
"""
* | **Title 1**
| Message 1
""",
nodes.line, 2,
text = dedent(
"""
.. rubric:: spam
"""
)
yield (
assert_node_count,
extract_messages(_get_doctree(text)),
nodes.rubric, 1,
)
text = dedent(
"""
| spam
| egg
"""
)
yield (
assert_node_count,
extract_messages(_get_doctree(text)),
nodes.line, 2,
)
text = dedent(
"""
section
=======
+----------------+
| | **Title 1** |
| | Message 1 |
+----------------+
"""
)
yield (
assert_node_count,
extract_messages(_get_doctree(text)),
nodes.line, 2,
)
text = dedent(
"""
* | **Title 1**
| Message 1
"""
)
yield (
assert_node_count,
extract_messages(_get_doctree(text)),
nodes.line, 2,
)
),
]
)
def test_extract_messages(rst, node_cls, count):
msg = extract_messages(_get_doctree(dedent(rst)))
assert_node_count(msg, node_cls, count)
def test_extract_messages_without_rawsource():

View File

@ -16,7 +16,7 @@ from docutils.parsers.rst.directives.html import MetaBody
from sphinx import addnodes
from sphinx.versioning import add_uids, merge_doctrees, get_ratio
from util import TestApp
from util import SphinxTestApp
app = original = original_uids = None
@ -24,7 +24,7 @@ app = original = original_uids = None
def setup_module():
global app, original, original_uids
app = TestApp(testroot='versioning')
app = SphinxTestApp(testroot='versioning')
app.builder.env.app = app
app.connect('doctree-resolved', on_doctree_resolved)
app.build()

View File

@ -23,7 +23,7 @@ except ImportError:
sqlalchemy_missing = True
import pytest
from util import rootdir, tempdir, skip_if
from util import rootdir, tempdir
@pytest.fixture
@ -57,13 +57,13 @@ def test_no_srcdir(support):
support.build()
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_build(support):
support.build()
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_get_document(support):
with pytest.raises(DocumentNotFoundError):
@ -74,7 +74,7 @@ def test_get_document(support):
and contents['sidebar'] and contents['relbar']
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_comments(support):
session = Session()
@ -123,7 +123,7 @@ def test_comments(support):
assert children[0]['text'] == '<p>Child test comment</p>\n'
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_user_delete_comments(support):
def get_comment():
@ -152,7 +152,7 @@ def moderation_callback(comment):
called = True
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support(moderation_callback=moderation_callback)
def test_moderation(support):
session = Session()
@ -178,7 +178,7 @@ def test_moderation(support):
assert len(comments) == 1
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_moderator_delete_comments(support):
def get_comment():
@ -194,7 +194,7 @@ def test_moderator_delete_comments(support):
get_comment()
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_update_username(support):
support.update_username('user_two', 'new_user_two')
@ -213,7 +213,7 @@ def test_update_username(support):
assert len(votes) == 0
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_proposals(support):
session = Session()
@ -229,7 +229,7 @@ def test_proposals(support):
proposal=proposal)
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_voting(support):
session = Session()

View File

@ -207,7 +207,6 @@ def strip_escseq(text):
# #############################################
# DEPRECATED implementations
import tempfile
from six import StringIO