Merge branch 'stable' into 3256_update_release_script

This commit is contained in:
Takeshi KOMIYA
2017-01-14 00:26:03 +09:00
committed by GitHub
126 changed files with 3203 additions and 3832 deletions

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@
*.swp
.dir-locals.el
.cache/
.mypy_cache/
.ropeproject/
TAGS

View File

@@ -4,15 +4,15 @@ cache:
directories:
- $HOME/.cache/pip
python:
- "pypy"
- "2.7"
- "3.4"
- "3.5"
- "3.6"
- "nightly"
- "pypy"
env:
global:
- TEST='-v --with-timer --timer-top-n 25'
- TEST='-v --durations 25'
- PYTHONFAULTHANDLER=x
- PYTHONWARNINGS=all
matrix:

12
CHANGES
View File

@@ -1,12 +1,18 @@
Release 1.5.2 (in development)
===============================
Incompatible changes
--------------------
* Dependency requirement updates: requests 2.4.0 or above (refs: #3268, #3310)
Features added
--------------
* #3241: emit latex warning if buggy titlesec (ref #3210)
* #3194: Refer the $MAKE environment variable to determine ``make`` command
* Emit warning for nested numbered toctrees (refs: #3142)
* #978: `intersphinx_mapping` also allows a list as a parameter
Bugs fixed
----------
@@ -21,6 +27,12 @@ Bugs fixed
* The warning type ``misc.highlighting_failure`` does not work
* #3294: ``add_latex_package()`` make crashes non-LaTeX builders
* The caption of table are rendered as invalid HTML (refs: #3287)
* #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'
* #3328: Could not refer rubric implicitly
* #3329: emit warnings if po file is invalid and can't read it. Also writing mo too.
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 \
@@ -65,6 +65,7 @@ clean-testfiles:
rm -rf tests/.coverage
rm -rf tests/build
rm -rf .tox/
rm -rf .cache/
clean-buildfiles:
rm -rf build
@@ -79,14 +80,13 @@ reindent:
@$(PYTHON) utils/reindent.py -r -n .
test:
@cd tests; $(PYTHON) run.py -I py35 -d -m '^[tT]est' $(TEST)
@cd tests; $(PYTHON) run.py --ignore py35 -v $(TEST)
test-async:
@cd tests; $(PYTHON) run.py -d -m '^[tT]est' $(TEST)
@cd tests; $(PYTHON) run.py -v $(TEST)
covertest:
@cd tests; $(PYTHON) run.py -d -m '^[tT]est' --with-coverage \
--cover-package=sphinx $(TEST)
@cd tests; $(PYTHON) run.py -v --cov=sphinx --junitxml=.junit.xml $(TEST)
build:
@$(PYTHON) setup.py build

View File

@@ -94,14 +94,14 @@ This section describe a easy way to translate with sphinx-intl.
$ make gettext
As a result, many pot files are generated under ``_build/locale``
As a result, many pot files are generated under ``_build/gettext``
directory.
#. Setup/Update your `locale_dir`:
.. code-block:: console
$ sphinx-intl update -p _build/locale -l de -l ja
$ sphinx-intl update -p _build/gettext -l de -l ja
Done. You got these directories that contain po files:

View File

@@ -25,5 +25,5 @@ universal = 1
[flake8]
max-line-length = 95
ignore = E113,E116,E221,E226,E241,E251,E901
ignore = E116,E241,E251
exclude = .git,.tox,tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*,doc/ext/example*.py

View File

@@ -50,7 +50,7 @@ requires = [
'babel>=1.3,!=2.0',
'alabaster>=0.7,<0.8',
'imagesize',
'requests',
'requests>=2.4.0',
]
extras_require = {
# Environment Marker works for wheel 0.24 or later

View File

@@ -30,7 +30,7 @@ if 'PYTHONWARNINGS' not in os.environ:
warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io')
__version__ = '1.5.2+'
__version__ = '1.5.2+'
__released__ = '1.5.2' # used when Sphinx builds its own docs
# version info for better programmatic use

View File

@@ -368,8 +368,8 @@ Note: By default this script will not overwrite already created files.""")
text += ' %s\n' % module
d = dict(
path = opts.destdir,
sep = False,
dot = '_',
sep = False,
dot = '_',
project = opts.header,
author = opts.author or 'Author',
version = opts.version or '',

View File

@@ -258,7 +258,7 @@ class Sphinx(object):
for catinfo in find_catalog_source_files(
user_locale_dirs, self.config.language, domains=['sphinx'],
charset=self.config.source_encoding):
catinfo.write_mo(self.config.language)
catinfo.write_mo(self.config.language, self.warn)
locale_dirs = [None, path.join(package_dir, 'locale')] + user_locale_dirs
else:
locale_dirs = []
@@ -484,7 +484,7 @@ class Sphinx(object):
summary = bold(summary)
for item in iterable:
l += 1
s = '%s[%3d%%] %s' % (summary, 100*l/length,
s = '%s[%3d%%] %s' % (summary, 100 * l / length,
colorfunc(stringify_func(item)))
if self.verbosity:
s += '\n'
@@ -660,9 +660,9 @@ class Sphinx(object):
else:
# ignore invalid keys for compatibility
continue
setattr(translator, 'visit_'+node.__name__, visit)
setattr(translator, 'visit_' + node.__name__, visit)
if depart:
setattr(translator, 'depart_'+node.__name__, depart)
setattr(translator, 'depart_' + node.__name__, depart)
def add_enumerable_node(self, node, figtype, title_getter=None, **kwds):
self.enumerable_nodes[node] = (figtype, title_getter)

View File

@@ -167,7 +167,7 @@ class Builder(object):
for catalog in self.app.status_iterator(
catalogs, 'writing output... ', darkgreen, len(catalogs),
cat2relpath):
catalog.write_mo(self.config.language)
catalog.write_mo(self.config.language, self.warn)
def compile_all_catalogs(self):
catalogs = i18n.find_catalog_source_files(

View File

@@ -130,7 +130,7 @@ class ChangesBuilder(Builder):
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
ensuredir(path.dirname(targetfn))
with codecs.open(targetfn, 'w', 'utf-8') as f:
text = ''.join(hl(i+1, line) for (i, line) in enumerate(lines))
text = ''.join(hl(i + 1, line) for (i, line) in enumerate(lines))
ctx = {
'filename': self.env.doc2path(docname, None),
'text': text

View File

@@ -498,7 +498,7 @@ class StandaloneHTMLBuilder(Builder):
# additional pages from conf.py
for pagename, template in self.config.html_additional_pages.items():
self.info(' '+pagename, nonl=1)
self.info(' ' + pagename, nonl=1)
self.handle_page(pagename, {}, template)
# the search page
@@ -953,7 +953,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
hashindex = refuri.find('#')
if hashindex < 0:
continue
hashindex = refuri.find('#', hashindex+1)
hashindex = refuri.find('#', hashindex + 1)
if hashindex >= 0:
refnode['refuri'] = fname + refuri[hashindex:]
@@ -1059,7 +1059,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
# additional pages from conf.py
for pagename, template in self.config.html_additional_pages.items():
self.info(' '+pagename, nonl=1)
self.info(' ' + pagename, nonl=1)
self.handle_page(pagename, {}, template)
if self.config.html_use_opensearch:

View File

@@ -208,12 +208,12 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
def build_hhx(self, outdir, outname):
self.info('dumping stopword list...')
with self.open_file(outdir, outname+'.stp') as f:
with self.open_file(outdir, outname + '.stp') as f:
for word in sorted(stopwords):
print(word, file=f)
self.info('writing project file...')
with self.open_file(outdir, outname+'.hhp') as f:
with self.open_file(outdir, outname + '.hhp') as f:
f.write(project_template % {
'outname': outname,
'title': self.config.html_title,
@@ -234,7 +234,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
file=f)
self.info('writing TOC file...')
with self.open_file(outdir, outname+'.hhc') as f:
with self.open_file(outdir, outname + '.hhc') as f:
f.write(contents_header)
# special books
f.write('<LI> ' + object_sitemap % (self.config.html_short_title,
@@ -259,7 +259,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
if ullevel != 0:
f.write('<UL>\n')
for subnode in node:
write_toc(subnode, ullevel+1)
write_toc(subnode, ullevel + 1)
if ullevel != 0:
f.write('</UL>\n')
elif isinstance(node, addnodes.compact_paragraph):
@@ -275,7 +275,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
self.info('writing index file...')
index = self.env.create_index(self)
with self.open_file(outdir, outname+'.hhk') as f:
with self.open_file(outdir, outname + '.hhk') as f:
f.write('<UL>\n')
def write_index(title, refs, subitems):

View File

@@ -74,7 +74,7 @@ class LaTeXBuilder(Builder):
'document %s' % docname)
continue
self.document_data.append(entry)
if docname.endswith(SEP+'index'):
if docname.endswith(SEP + 'index'):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
@@ -188,7 +188,7 @@ class LaTeXBuilder(Builder):
if self.images:
self.info(bold('copying images...'), nonl=1)
for src, dest in iteritems(self.images):
self.info(' '+src, nonl=1)
self.info(' ' + src, nonl=1)
copy_asset_file(path.join(self.srcdir, src),
path.join(self.outdir, dest))
self.info()
@@ -206,7 +206,7 @@ class LaTeXBuilder(Builder):
if self.config.latex_additional_files:
self.info(bold('copying additional files...'), nonl=1)
for filename in self.config.latex_additional_files:
self.info(' '+filename, nonl=1)
self.info(' ' + filename, nonl=1)
copy_asset_file(path.join(self.confdir, filename), self.outdir)
self.info()

View File

@@ -225,7 +225,7 @@ class CheckExternalLinksBuilder(Builder):
self.info(darkgray('-local- ') + uri)
self.write_entry('local', docname, lineno, uri)
elif status == 'working':
self.info(darkgreen('ok ') + uri + info)
self.info(darkgreen('ok ') + uri + info)
elif status == 'broken':
self.write_entry('broken', docname, lineno, uri + ': ' + info)
if self.app.quiet or self.app.warningiserror:
@@ -243,7 +243,7 @@ class CheckExternalLinksBuilder(Builder):
}[code]
self.write_entry('redirected ' + text, docname, lineno,
uri + ' to ' + info)
self.info(color('redirect ') + uri + color(' - ' + text + ' to ' + info))
self.info(color('redirect ') + uri + color(' - ' + text + ' to ' + info))
def get_target_uri(self, docname, typ=None):
return ''

View File

@@ -89,7 +89,7 @@ project_template = u'''\
'''
section_template = '<section title="%(title)s" ref="%(ref)s"/>'
file_template = ' '*12 + '<file>%(filename)s</file>'
file_template = ' ' * 12 + '<file>%(filename)s</file>'
class QtHelpBuilder(StandaloneHTMLBuilder):
@@ -190,7 +190,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
nspace = nspace.lower()
# write the project file
with codecs.open(path.join(outdir, outname+'.qhp'), 'w', 'utf-8') as f:
with codecs.open(path.join(outdir, outname + '.qhp'), 'w', 'utf-8') as f:
f.write(project_template % {
'outname': htmlescape(outname),
'title': htmlescape(self.config.html_title),
@@ -207,7 +207,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
startpage = 'qthelp://' + posixpath.join(nspace, 'doc', 'index.html')
self.info('writing collection project file...')
with codecs.open(path.join(outdir, outname+'.qhcp'), 'w', 'utf-8') as f:
with codecs.open(path.join(outdir, outname + '.qhcp'), 'w', 'utf-8') as f:
f.write(collection_template % {
'outname': htmlescape(outname),
'title': htmlescape(self.config.html_short_title),
@@ -236,10 +236,10 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
title = htmlescape(refnode.astext()).replace('"', '&quot;')
item = '<section title="%(title)s" ref="%(ref)s">' % \
{'title': title, 'ref': link}
parts.append(' '*4*indentlevel + item)
parts.append(' ' * 4 * indentlevel + item)
for subnode in node.children[1]:
parts.extend(self.write_toc(subnode, indentlevel+1))
parts.append(' '*4*indentlevel + '</section>')
parts.extend(self.write_toc(subnode, indentlevel + 1))
parts.append(' ' * 4 * indentlevel + '</section>')
elif isinstance(node, nodes.list_item):
for subnode in node:
parts.extend(self.write_toc(subnode, indentlevel))
@@ -272,10 +272,10 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
id = None
if id:
item = ' '*12 + '<keyword name="%s" id="%s" ref="%s"/>' % (
item = ' ' * 12 + '<keyword name="%s" id="%s" ref="%s"/>' % (
name, id, ref[1])
else:
item = ' '*12 + '<keyword name="%s" ref="%s"/>' % (name, ref[1])
item = ' ' * 12 + '<keyword name="%s" ref="%s"/>' % (name, ref[1])
item.encode('ascii', 'xmlcharrefreplace')
return item

View File

@@ -122,7 +122,7 @@ class TexinfoBuilder(Builder):
'document %s' % docname)
continue
self.document_data.append(entry)
if docname.endswith(SEP+'index'):
if docname.endswith(SEP + 'index'):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
@@ -210,7 +210,7 @@ class TexinfoBuilder(Builder):
if self.images:
self.info(bold('copying images...'), nonl=1)
for src, dest in iteritems(self.images):
self.info(' '+src, nonl=1)
self.info(' ' + src, nonl=1)
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, dest))
self.info()

View File

@@ -141,7 +141,7 @@ class WebSupportBuilder(PickleHTMLBuilder):
# "show source" link
if ctx.get('sourcename'):
source_name = path.join(self.staticdir,
'_sources', os_path(ctx['sourcename']))
'_sources', os_path(ctx['sourcename']))
ensuredir(path.dirname(source_name))
copyfile(self.env.doc2path(pagename), source_name)

View File

@@ -107,7 +107,7 @@ class CodeBlock(Directive):
if linespec:
try:
nlines = len(self.content)
hl_lines = [x+1 for x in parselinenos(linespec, nlines)]
hl_lines = [x + 1 for x in parselinenos(linespec, nlines)]
except ValueError as err:
document = self.state.document
return [document.reporter.warning(str(err), line=self.lineno)]
@@ -266,7 +266,7 @@ class LiteralInclude(Directive):
'Object named %r not found in include file %r' %
(objectname, filename), line=self.lineno)]
else:
lines = lines[tags[objectname][1]-1: tags[objectname][2]-1]
lines = lines[tags[objectname][1] - 1: tags[objectname][2] - 1]
if 'lineno-match' in self.options:
linenostart = tags[objectname][1]
@@ -298,7 +298,7 @@ class LiteralInclude(Directive):
linespec = self.options.get('emphasize-lines')
if linespec:
try:
hl_lines = [x+1 for x in parselinenos(linespec, len(lines))]
hl_lines = [x + 1 for x in parselinenos(linespec, len(lines))]
except ValueError as err:
return [document.reporter.warning(str(err), line=self.lineno)]
else:

View File

@@ -204,7 +204,7 @@ class VersionChange(Directive):
text = versionlabels[self.name] % self.arguments[0]
if len(self.arguments) == 2:
inodes, messages = self.state.inline_text(self.arguments[1],
self.lineno+1)
self.lineno + 1)
para = nodes.paragraph(self.arguments[1], '', *inodes, translatable=False)
set_source_info(self, para)
node.append(para)
@@ -325,7 +325,7 @@ class HList(Directive):
index = 0
newnode = addnodes.hlist()
for column in range(ncolumns):
endindex = index + (column < nmore and (npercol+1) or npercol)
endindex = index + (column < nmore and (npercol + 1) or npercol)
col = addnodes.hlistcol()
col += nodes.bullet_list()
col[0] += fulllist.children[index:endindex]

View File

@@ -77,7 +77,7 @@ class CObject(ObjectDescription):
# add cross-ref nodes for all words
for part in [_f for _f in wsplit_re.split(ctype) if _f]:
tnode = nodes.Text(part, part)
if part[0] in string.ascii_letters+'_' and \
if part[0] in string.ascii_letters + '_' and \
part not in self.stopwords:
pnode = addnodes.pending_xref(
'', refdomain='c', reftype='type', reftarget=part,
@@ -162,7 +162,7 @@ class CObject(ObjectDescription):
ctype, argname = arg.rsplit(' ', 1)
self._parse_type(param, ctype)
# separate by non-breaking space in the output
param += nodes.emphasis(' '+argname, u'\xa0'+argname)
param += nodes.emphasis(' ' + argname, u'\xa0' + argname)
except ValueError:
# no argument name given, only the type
self._parse_type(param, arg)
@@ -230,7 +230,7 @@ class CXRefRole(XRefRole):
title = title[1:]
dot = title.rfind('.')
if dot != -1:
title = title[dot+1:]
title = title[dot + 1:]
return title, target

View File

@@ -2885,14 +2885,14 @@ class Symbol(object):
assert False # should have returned in the loop
def to_string(self, indent):
res = ['\t'*indent]
res = ['\t' * indent]
if not self.parent:
res.append('::')
else:
if self.templateParams:
res.append(text_type(self.templateParams))
res.append('\n')
res.append('\t'*indent)
res.append('\t' * indent)
if self.identifier:
res.append(text_type(self.identifier))
else:

View File

@@ -148,7 +148,7 @@ class JSXRefRole(XRefRole):
title = title[1:]
dot = title.rfind('.')
if dot != -1:
title = title[dot+1:]
title = title[dot + 1:]
if target[0:1] == '.':
target = target[1:]
refnode['refspecific'] = True

View File

@@ -527,7 +527,7 @@ class PyXRefRole(XRefRole):
title = title[1:]
dot = title.rfind('.')
if dot != -1:
title = title[dot+1:]
title = title[dot + 1:]
# if the first character is a dot, search more specific namespaces first
# else search builtins first
if target[0:1] == '.':

View File

@@ -58,7 +58,7 @@ class GenericObject(ObjectDescription):
colon = self.indextemplate.find(':')
if colon != -1:
indextype = self.indextemplate[:colon].strip()
indexentry = self.indextemplate[colon+1:].strip() % (name,)
indexentry = self.indextemplate[colon + 1:].strip() % (name,)
else:
indextype = 'single'
indexentry = self.indextemplate % (name,)
@@ -118,7 +118,7 @@ class Target(Directive):
colon = indexentry.find(':')
if colon != -1:
indextype = indexentry[:colon].strip()
indexentry = indexentry[colon+1:].strip()
indexentry = indexentry[colon + 1:].strip()
inode = addnodes.index(entries=[(indextype, indexentry,
targetname, '', None)])
ret.insert(0, inode)
@@ -566,7 +566,7 @@ class StandardDomain(Domain):
env.warn_node('duplicate label %s, ' % name + 'other instance '
'in ' + env.doc2path(labels[name][0]), node)
anonlabels[name] = docname, labelid
if node.tagname == 'section':
if node.tagname in ('section', 'rubric'):
sectname = clean_astext(node[0]) # node[0] == title node
elif self.is_enumerable_node(node):
sectname = self.get_numfig_title(node)
@@ -673,13 +673,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:
env.warn_node('the link has no caption: %s' % title, 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

@@ -632,7 +632,7 @@ class BuildEnvironment(object):
lineno = error.object.count(b'\n', 0, error.start) + 1
self.warn(self.docname, 'undecodable source characters, '
'replacing with "?": %r' %
(error.object[linestart+1:error.start] + b'>>>' +
(error.object[linestart + 1:error.start] + b'>>>' +
error.object[error.start:error.end] + b'<<<' +
error.object[error.end:lineend]), lineno)
return (u'?', error.end)

View File

@@ -224,11 +224,11 @@ class Toctree(EnvironmentManager):
if isinstance(subnode, (addnodes.compact_paragraph,
nodes.list_item)):
# for <p> and <li>, indicate the depth level and recurse
subnode['classes'].append('toctree-l%d' % (depth-1))
subnode['classes'].append('toctree-l%d' % (depth - 1))
_toctree_add_classes(subnode, depth)
elif isinstance(subnode, nodes.bullet_list):
# for <ul>, just recurse
_toctree_add_classes(subnode, depth+1)
_toctree_add_classes(subnode, depth + 1)
elif isinstance(subnode, nodes.reference):
# for <a>, identify which entries point to the current
# document and therefore may not be collapsed
@@ -417,7 +417,7 @@ class Toctree(EnvironmentManager):
subnode.parent.remove(subnode)
else:
# recurse on visible children
self._toctree_prune(subnode, depth+1, maxdepth, collapse)
self._toctree_prune(subnode, depth + 1, maxdepth, collapse)
def assign_section_numbers(self):
"""Assign a section number to each heading under a numbered toctree."""
@@ -434,7 +434,7 @@ class Toctree(EnvironmentManager):
for subnode in node.children:
if isinstance(subnode, nodes.bullet_list):
numstack.append(0)
_walk_toc(subnode, secnums, depth-1, titlenode)
_walk_toc(subnode, secnums, depth - 1, titlenode)
numstack.pop()
titlenode = None
elif isinstance(subnode, nodes.list_item):

View File

@@ -10,8 +10,6 @@
:license: BSD, see LICENSE for details.
"""
import traceback
class SphinxError(Exception):
"""
@@ -71,10 +69,9 @@ class SphinxParallelError(SphinxError):
category = 'Sphinx parallel build error'
def __init__(self, orig_exc, traceback):
self.orig_exc = orig_exc
def __init__(self, message, traceback):
self.message = message
self.traceback = traceback
def __str__(self):
return traceback.format_exception_only(
self.orig_exc.__class__, self.orig_exc)[0].strip()
return self.message

View File

@@ -100,7 +100,7 @@ def process_autosummary_toc(app, doctree):
if not isinstance(subnode, nodes.section):
continue
if subnode not in crawled:
crawl_toc(subnode, depth+1)
crawl_toc(subnode, depth + 1)
crawl_toc(doctree)
@@ -266,7 +266,7 @@ class Autosummary(Directive):
if not isinstance(obj, ModuleType):
# give explicitly separated module name, so that members
# of inner classes can be documented
full_name = modname + '::' + full_name[len(modname)+1:]
full_name = modname + '::' + full_name[len(modname) + 1:]
# NB. using full_name here is important, since Documenters
# handle module prefixes slightly differently
documenter = get_documenter(obj, parent)(self, full_name)
@@ -403,13 +403,13 @@ def mangle_signature(sig, max_chars=30):
s = m.group(1)[:-2]
# Produce a more compact signature
sig = limited_join(", ", args, max_chars=max_chars-2)
sig = limited_join(", ", args, max_chars=max_chars - 2)
if opts:
if not sig:
sig = "[%s]" % limited_join(", ", opts, max_chars=max_chars-4)
sig = "[%s]" % limited_join(", ", opts, max_chars=max_chars - 4)
elif len(sig) < max_chars - 4 - 2 - 3:
sig += "[, %s]" % limited_join(", ", opts,
max_chars=max_chars-len(sig)-4-2)
max_chars=max_chars - len(sig) - 4 - 2)
return u"(%s)" % sig
@@ -497,7 +497,7 @@ def _import_by_name(name):
# ... then as MODNAME, MODNAME.OBJ1, MODNAME.OBJ1.OBJ2, ...
last_j = 0
modname = None
for j in reversed(range(1, len(name_parts)+1)):
for j in reversed(range(1, len(name_parts) + 1)):
last_j = j
modname = '.'.join(name_parts[:j])
try:

View File

@@ -241,7 +241,7 @@ class DocTestBuilder(Builder):
self.outfile.write('''\
Results of doctest builder run on %s
==================================%s
''' % (date, '='*len(date)))
''' % (date, '=' * len(date)))
def _out(self, text):
self.info(text, nonl=True)
@@ -348,7 +348,7 @@ Doctest summary
return
self._out('\nDocument: %s\n----------%s\n' %
(docname, '-'*len(docname)))
(docname, '-' * len(docname)))
for group in itervalues(groups):
self.test_group(group, self.env.doc2path(docname, base=None))
# Separately count results from setup code

View File

@@ -217,7 +217,7 @@ def get_tooltip(self, node):
def html_visit_math(self, node):
try:
fname, depth = render_math(self, '$'+node['latex']+'$')
fname, depth = render_math(self, '$' + node['latex'] + '$')
except MathExtError as exc:
msg = text_type(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,

View File

@@ -68,7 +68,7 @@ def read_inventory_v1(f, uri, join):
return invdata
def read_inventory_v2(f, uri, join, bufsize=16*1024):
def read_inventory_v2(f, uri, join, bufsize=16 * 1024):
invdata = {}
line = f.readline()
projname = line.rstrip()[11:].decode('utf-8')
@@ -91,7 +91,7 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
lineend = buf.find(b'\n')
while lineend != -1:
yield buf[:lineend].decode('utf-8')
buf = buf[lineend+1:]
buf = buf[lineend + 1:]
lineend = buf.find(b'\n')
assert not buf
@@ -116,7 +116,7 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
return invdata
def read_inventory(f, uri, join, bufsize=16*1024):
def read_inventory(f, uri, join, bufsize=16 * 1024):
line = f.readline().rstrip().decode('utf-8')
if line == '# Sphinx inventory version 1':
return read_inventory_v1(f, uri, join)
@@ -221,8 +221,8 @@ def fetch_inventory(app, uri, inv):
try:
join = localuri and path.join or posixpath.join
invdata = read_inventory(f, uri, join)
except ValueError:
raise ValueError('unknown or unsupported inventory version')
except ValueError as exc:
raise ValueError('unknown or unsupported inventory version: %r' % exc)
except Exception as err:
app.warn('intersphinx inventory %r not readable due to '
'%s: %s' % (inv, err.__class__.__name__, err))
@@ -242,7 +242,7 @@ def load_mappings(app):
cache = env.intersphinx_cache
update = False
for key, value in iteritems(app.config.intersphinx_mapping):
if isinstance(value, tuple):
if isinstance(value, (list, tuple)):
# new format
name, (uri, inv) = key, value
if not isinstance(name, string_types):
@@ -342,9 +342,9 @@ def missing_reference(app, env, node, contnode):
(domain == 'std' and node['reftype'] == 'keyword'):
# use whatever title was given, but strip prefix
title = contnode.astext()
if in_set and title.startswith(in_set+':'):
newnode.append(contnode.__class__(title[len(in_set)+1:],
title[len(in_set)+1:]))
if in_set and title.startswith(in_set + ':'):
newnode.append(contnode.__class__(title[len(in_set) + 1:],
title[len(in_set) + 1:]))
else:
newnode.append(contnode)
else:

View File

@@ -189,7 +189,7 @@ def get_tooltip(self, node):
def html_visit_math(self, node):
try:
fname, depth = render_math(self, '$'+node['latex']+'$')
fname, depth = render_math(self, '$' + node['latex'] + '$')
except MathExtError as exc:
msg = text_type(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,

View File

@@ -138,7 +138,7 @@ def process_todo_nodes(app, doctree, fromdocname):
(todo_info['source'], todo_info['lineno'])
)
desc1 = description[:description.find('<<')]
desc2 = description[description.find('>>')+2:]
desc2 = description[description.find('>>') + 2:]
para += nodes.Text(desc1, desc1)
# Create a reference

View File

@@ -79,7 +79,7 @@ class Make(object):
def build_help(self):
print(bold("Sphinx v%s" % sphinx.__display_version__))
print("Please use `make %s' where %s is one of" % ((blue('target'),)*2))
print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2))
for osname, bname, description in BUILDERS:
if not osname or os.name == osname:
print(' %s %s' % (blue(bname.ljust(10)), description))

View File

@@ -364,4 +364,4 @@ if __name__ == '__main__':
pprint.pprint(ma.find_tags())
x3 = time.time()
# print nodes.nice_repr(ma.parsetree, number2name)
print("tokenizing %.4f, parsing %.4f, finding %.4f" % (x1-x0, x2-x1, x3-x2))
print("tokenizing %.4f, parsing %.4f, finding %.4f" % (x1 - x0, x2 - x1, x3 - x2))

View File

@@ -39,7 +39,7 @@ class BaseNode(object):
if child is self:
if i == 0:
return None
return self.parent.children[i-1]
return self.parent.children[i - 1]
def get_next_sibling(self):
"""Return next child in parent's children, or None."""
@@ -48,7 +48,7 @@ class BaseNode(object):
for i, child in enumerate(self.parent.children):
if child is self:
try:
return self.parent.children[i+1]
return self.parent.children[i + 1]
except IndexError:
return None

View File

@@ -301,11 +301,11 @@ document is a custom template, you can also set this to another filename.''')
do_prompt(d, 'master', 'Name of your master document (without suffix)',
'index')
while path.isfile(path.join(d['path'], d['master']+d['suffix'])) or \
path.isfile(path.join(d['path'], 'source', d['master']+d['suffix'])):
while path.isfile(path.join(d['path'], d['master'] + d['suffix'])) or \
path.isfile(path.join(d['path'], 'source', d['master'] + d['suffix'])):
print()
print(bold('Error: the master file %s has already been found in the '
'selected root path.' % (d['master']+d['suffix'])))
'selected root path.' % (d['master'] + d['suffix'])))
print('sphinx-quickstart will not overwrite the existing file.')
print()
do_prompt(d, 'master', 'Please enter a new file name, or rename the '
@@ -632,7 +632,7 @@ def main(argv=sys.argv):
d.setdefault('version', '')
d.setdefault('release', d['version'])
d2 = DEFAULT_VALUE.copy()
d2.update(dict(("ext_"+ext, False) for ext in EXTENSIONS))
d2.update(dict(("ext_" + ext, False) for ext in EXTENSIONS))
d2.update(d)
d = d2
if 'no_makefile' in d:

View File

@@ -201,7 +201,7 @@ def indexmarkup_role(typ, rawtext, text, lineno, inliner,
return [prb], [msg]
ref = inliner.document.settings.pep_base_url + 'pep-%04d' % pepnum
sn = nodes.strong(title, title)
rn = nodes.reference('', '', internal=False, refuri=ref+anchor,
rn = nodes.reference('', '', internal=False, refuri=ref + anchor,
classes=[typ])
rn += sn
return [indexnode, targetnode, rn], []
@@ -223,7 +223,7 @@ def indexmarkup_role(typ, rawtext, text, lineno, inliner,
return [prb], [msg]
ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
sn = nodes.strong(title, title)
rn = nodes.reference('', '', internal=False, refuri=ref+anchor,
rn = nodes.reference('', '', internal=False, refuri=ref + anchor,
classes=[typ])
rn += sn
return [indexnode, targetnode, rn], []

View File

@@ -6,7 +6,7 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{sphinx}[2016/12/14 v1.5.2 LaTeX package (Sphinx markup)]
\ProvidesPackage{sphinx}[2017/01/09 v1.5.2 LaTeX package (Sphinx markup)]
% we delay handling of options to after having loaded packages, because
% of the need to use \definecolor.
@@ -1090,8 +1090,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
@@ -1122,7 +1128,7 @@
\expandafter\let
\csname @list\romannumeral\the\count@\expandafter\endcsname
\csname @list\romannumeral\the\numexpr\count@-\@ne\endcsname
% higher \leftmargin... needed to fix issue with babel-french (v2.6--...)
% work around 2.6--3.2d babel-french issue (fixed in 3.2e; no change needed)
\spx@ifundefined{leftmargin\romannumeral\the\count@}
{\expandafter\let
\csname leftmargin\romannumeral\the\count@\expandafter\endcsname

View File

@@ -112,7 +112,7 @@ class Locale(Transform):
# literalblock need literal block notation to avoid it become
# paragraph.
if isinstance(node, LITERAL_TYPE_NODES):
msgstr = '::\n\n' + indent(msgstr, ' '*3)
msgstr = '::\n\n' + indent(msgstr, ' ' * 3)
patch = publish_msgstr(
env.app, msgstr, source, node.line, env.config, settings)
@@ -237,7 +237,7 @@ class Locale(Transform):
# literalblock need literal block notation to avoid it become
# paragraph.
if isinstance(node, LITERAL_TYPE_NODES):
msgstr = '::\n\n' + indent(msgstr, ' '*3)
msgstr = '::\n\n' + indent(msgstr, ' ' * 3)
patch = publish_msgstr(
env.app, msgstr, source, node.line, env.config, settings)

View File

@@ -98,7 +98,7 @@ def get_matching_docs(dirname, suffixes, exclude_matchers=()):
for filename in get_matching_files(dirname, exclude_matchers):
for suffixpattern in suffixpatterns:
if fnmatch.fnmatch(filename, suffixpattern):
yield filename[:-len(suffixpattern)+1]
yield filename[:-len(suffixpattern) + 1]
break
@@ -167,7 +167,7 @@ def copy_static_entry(source, targetdir, builder, context={},
if path.isdir(path.join(source, entry)):
newtarget = path.join(targetdir, entry)
copy_static_entry(path.join(source, entry), newtarget,
builder, context, level=level+1,
builder, context, level=level + 1,
exclude_matchers=exclude_matchers)
@@ -360,9 +360,9 @@ def parselinenos(spec, total):
if len(begend) > 2:
raise ValueError
if len(begend) == 1:
items.append(int(begend[0])-1)
items.append(int(begend[0]) - 1)
else:
start = (begend[0] == '') and 0 or int(begend[0])-1
start = (begend[0] == '') and 0 or int(begend[0]) - 1
end = (begend[1] == '') and total or int(begend[1])
items.extend(range(start, end))
except Exception:
@@ -400,13 +400,13 @@ def rpartition(s, t):
"""Similar to str.rpartition from 2.5, but doesn't return the separator."""
i = s.rfind(t)
if i != -1:
return s[:i], s[i+len(t):]
return s[:i], s[i + len(t):]
return '', s
def split_into(n, type, value):
"""Split an index entry into a given number of parts at semicolons."""
parts = [x.strip() for x in value.split(';', n-1)]
parts = [x.strip() for x in value.split(';', n - 1)]
if sum(1 for part in parts if part) < n:
raise ValueError('invalid %s index entry %r' % (type, value))
return parts

View File

@@ -115,8 +115,8 @@ _colors = [
]
for i, (dark, light) in enumerate(_colors):
codes[dark] = '\x1b[%im' % (i+30)
codes[light] = '\x1b[%i;01m' % (i+30)
codes[dark] = '\x1b[%im' % (i + 30)
codes[light] = '\x1b[%i;01m' % (i + 30)
_orig_codes = codes.copy()

View File

@@ -16,7 +16,7 @@ import docutils
from docutils.parsers.rst import directives, roles
__version_info__ = tuple(map(int, docutils.__version__.split('.')))
__version_info__ = tuple(map(int, docutils.__version__.split('.')))
@contextmanager

View File

@@ -41,7 +41,9 @@ def copy_asset_file(source, destination, context=None, renderer=None):
renderer = SphinxRenderer()
with codecs.open(source, 'r', encoding='utf-8') as fsrc:
with codecs.open(destination[:-2], 'w', encoding='utf-8') as fdst:
if destination.lower().endswith('_t'):
destination = destination[:-2]
with codecs.open(destination, 'w', encoding='utf-8') as fdst:
fdst.write(renderer.render_string(fsrc.read(), context))
else:
copyfile(source, destination)

View File

@@ -53,10 +53,19 @@ class CatalogInfo(LocaleFileInfoBase):
not path.exists(self.mo_path) or
path.getmtime(self.mo_path) < path.getmtime(self.po_path))
def write_mo(self, locale):
with io.open(self.po_path, 'rt', encoding=self.charset) as po:
with io.open(self.mo_path, 'wb') as mo:
write_mo(mo, read_po(po, locale))
def write_mo(self, locale, warnfunc):
with io.open(self.po_path, 'rt', encoding=self.charset) as file_po:
try:
po = read_po(file_po, locale)
except Exception:
warnfunc('reading error: %s' % self.po_path)
return
with io.open(self.mo_path, 'wb') as file_mo:
try:
write_mo(file_mo, po)
except Exception:
warnfunc('writing error: %s' % self.mo_path)
def find_catalog(docname, compaction):

View File

@@ -16,8 +16,8 @@ from six import iteritems, integer_types, string_types
from sphinx.util.pycompat import u
_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
_int_re = re.compile(r'\d+')
_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
_int_re = re.compile(r'\d+')
_name_re = re.compile(r'[a-zA-Z_]\w*')
_nameonly_re = re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*$')

View File

@@ -243,15 +243,15 @@ def process_index_entry(entry, targetid):
main = 'main'
entry = entry[1:].lstrip()
for type in pairindextypes:
if entry.startswith(type+':'):
value = entry[len(type)+1:].strip()
if entry.startswith(type + ':'):
value = entry[len(type) + 1:].strip()
value = pairindextypes[type] + '; ' + value
indexentries.append(('pair', value, targetid, main, None))
break
else:
for type in indextypes:
if entry.startswith(type+':'):
value = entry[len(type)+1:].strip()
if entry.startswith(type + ':'):
value = entry[len(type) + 1:].strip()
if type == 'double':
type = 'pair'
indexentries.append((type, value, targetid, main, None))

View File

@@ -27,7 +27,7 @@ from six import PY2, text_type
# Errnos that we need.
EEXIST = getattr(errno, 'EEXIST', 0)
ENOENT = getattr(errno, 'ENOENT', 0)
EPIPE = getattr(errno, 'EPIPE', 0)
EPIPE = getattr(errno, 'EPIPE', 0)
EINVAL = getattr(errno, 'EINVAL', 0)
# SEP separates path elements in the canonical file names
@@ -67,7 +67,7 @@ def relative_uri(base, to):
# Special case: relative_uri('f/index.html','f/') should
# return './', not ''
return '.' + SEP
return ('..' + SEP) * (len(b2)-1) + SEP.join(t2)
return ('..' + SEP) * (len(b2) - 1) + SEP.join(t2)
def ensuredir(path):

View File

@@ -73,7 +73,8 @@ class ParallelTasks(object):
ret = func(arg)
pipe.send((False, ret))
except BaseException as err:
pipe.send((True, (err, traceback.format_exc())))
errmsg = traceback.format_exception_only(err.__class__, err)[0].strip()
pipe.send((True, (errmsg, traceback.format_exc())))
def add_task(self, task_func, arg=None, result_func=None):
tid = self._taskid
@@ -116,11 +117,11 @@ def make_chunks(arguments, nproc, maxbatch=10):
chunksize = nargs // nproc
if chunksize >= maxbatch:
# try to improve batch size vs. number of batches
chunksize = int(sqrt(nargs/nproc * maxbatch))
chunksize = int(sqrt(nargs / nproc * maxbatch))
if chunksize == 0:
chunksize = 1
nchunks, rest = divmod(nargs, chunksize)
if rest:
nchunks += 1
# partition documents in "chunks" that will be written by one Process
return [arguments[i*chunksize:(i+1)*chunksize] for i in range(nchunks)]
return [arguments[i * chunksize:(i + 1) * chunksize] for i in range(nchunks)]

View File

@@ -17,7 +17,12 @@ import pkg_resources
from six import string_types
from six.moves.urllib.parse import urlsplit
from requests.packages.urllib3.exceptions import SSLError, InsecureRequestWarning
try:
from requests.packages.urllib3.exceptions import SSLError, InsecureRequestWarning
except ImportError:
# python-requests package in Debian jessie does not provide ``requests.packages.urllib3``.
# So try to import the exceptions from urllib3 package.
from urllib3.exceptions import SSLError, InsecureRequestWarning
# try to load requests[security]
try:

View File

@@ -107,7 +107,7 @@ class PorterStemmer(object):
"""doublec(j) is TRUE <=> j,(j-1) contain a double consonant."""
if j < (self.k0 + 1):
return 0
if (self.b[j] != self.b[j-1]):
if (self.b[j] != self.b[j - 1]):
return 0
return self.cons(j)
@@ -120,8 +120,8 @@ class PorterStemmer(object):
cav(e), lov(e), hop(e), crim(e), but
snow, box, tray.
"""
if i < (self.k0 + 2) or not self.cons(i) or self.cons(i-1) \
or not self.cons(i-2):
if i < (self.k0 + 2) or not self.cons(i) or self.cons(i - 1) \
or not self.cons(i - 2):
return 0
ch = self.b[i]
if ch == 'w' or ch == 'x' or ch == 'y':
@@ -135,7 +135,7 @@ class PorterStemmer(object):
return 0
if length > (self.k - self.k0 + 1):
return 0
if self.b[self.k-length+1:self.k+1] != s:
if self.b[self.k - length + 1:self.k + 1] != s:
return 0
self.j = self.k - length
return 1
@@ -144,7 +144,7 @@ class PorterStemmer(object):
"""setto(s) sets (j+1),...k to the characters in the string s,
readjusting k."""
length = len(s)
self.b = self.b[:self.j+1] + s + self.b[self.j+length+1:]
self.b = self.b[:self.j + 1] + s + self.b[self.j + length + 1:]
self.k = self.j + length
def r(self, s):
@@ -203,7 +203,7 @@ class PorterStemmer(object):
"""step1c() turns terminal y to i when there is another vowel in
the stem."""
if (self.ends("y") and self.vowelinstem()):
self.b = self.b[:self.k] + 'i' + self.b[self.k+1:]
self.b = self.b[:self.k] + 'i' + self.b[self.k + 1:]
def step2(self):
"""step2() maps double suffices to single ones.
@@ -376,7 +376,7 @@ class PorterStemmer(object):
self.j = self.k
if self.b[self.k] == 'e':
a = self.m()
if a > 1 or (a == 1 and not self.cvc(self.k-1)):
if a > 1 or (a == 1 and not self.cvc(self.k - 1)):
self.k = self.k - 1
if self.b[self.k] == 'l' and self.doublec(self.k) and self.m() > 1:
self.k = self.k - 1
@@ -408,4 +408,4 @@ class PorterStemmer(object):
self.step3()
self.step4()
self.step5()
return self.b[self.k0:self.k+1]
return self.b[self.k0:self.k + 1]

View File

@@ -106,7 +106,7 @@ class BaseSearch(object):
res = self.context_re.search(text)
if res is None:
return ''
context_start = max(res.start() - int(length/2), 0)
context_start = max(res.start() - int(length / 2), 0)
context_end = context_start + length
context = ''.join([context_start > 0 and '...' or '',
text[context_start:context_end],

View File

@@ -454,7 +454,7 @@ class HTMLTranslator(BaseTranslator):
self.body.append(self.starttag(production, 'strong', ''))
self.body.append(lastname + '</strong> ::= ')
elif lastname is not None:
self.body.append('%s ' % (' '*len(lastname)))
self.body.append('%s ' % (' ' * len(lastname)))
production.walkabout(self)
self.body.append('\n')
self.body.append('</pre>\n')
@@ -614,7 +614,7 @@ class HTMLTranslator(BaseTranslator):
self.body.append(token)
else:
# protect runs of multiple spaces; the last one can wrap
self.body.append('&#160;' * (len(token)-1) + ' ')
self.body.append('&#160;' * (len(token) - 1) + ' ')
else:
if self.in_mailto and self.settings.cloak_email_addresses:
encoded = self.cloak_email(encoded)

View File

@@ -1641,7 +1641,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
parindex = node.parent.index(node)
try:
try:
next = node.parent[parindex+1]
next = node.parent[parindex + 1]
except IndexError:
# last node in parent, look at next after parent
# (for section of equal level) if it exists
@@ -1700,14 +1700,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
elif type == 'pair':
p1, p2 = [self.encode(x) for x in split_into(2, 'pair', string)]
self.body.append(r'\index{%s!%s%s}\index{%s!%s%s}' %
(p1, p2, m, p2, p1, m))
(p1, p2, m, p2, p1, m))
elif type == 'triple':
p1, p2, p3 = [self.encode(x)
for x in split_into(3, 'triple', string)]
self.body.append(
r'\index{%s!%s %s%s}\index{%s!%s, %s%s}'
r'\index{%s!%s %s%s}' %
(p1, p2, p3, m, p2, p3, p1, m, p3, p1, p2, m))
(p1, p2, p3, m, p2, p3, p1, m, p3, p1, p2, m))
elif type == 'see':
p1, p2 = [self.encode(x) for x in split_into(2, 'see', string)]
self.body.append(r'\index{%s|see{%s}}' % (p1, p2))

View File

@@ -271,7 +271,7 @@ class ManualPageTranslator(BaseTranslator):
self.body.append(self.defs['strong'][1])
self.body.append(' ::= ')
elif lastname is not None:
self.body.append('%s ' % (' '*len(lastname)))
self.body.append('%s ' % (' ' * len(lastname)))
production.walkabout(self)
self.body.append('\n')
self.body.append('\n.fi\n')

View File

@@ -318,10 +318,10 @@ class TexinfoTranslator(nodes.NodeVisitor):
for i, id in enumerate(entries):
# First child's prev is empty
if i != 0:
rellinks[id][1] = entries[i-1]
rellinks[id][1] = entries[i - 1]
# Last child's next is empty
if i != len(entries) - 1:
rellinks[id][0] = entries[i+1]
rellinks[id][0] = entries[i + 1]
# top's next is its first child
try:
first = node_menus['Top'][0]
@@ -383,7 +383,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
s = '* %s: %s. ' % (name, node_name)
offset = max((24, (len(name) + 4) % 78))
wdesc = '\n'.join(' ' * offset + l for l in
textwrap.wrap(desc, width=78-offset))
textwrap.wrap(desc, width=78 - offset))
return s + wdesc.strip() + '\n'
def add_menu_entries(self, entries, reg=re.compile(r'\s+---?\s+')):
@@ -641,7 +641,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
parindex = node.parent.index(node)
try:
try:
next = node.parent[parindex+1]
next = node.parent[parindex + 1]
except IndexError:
# last node in parent, look at next after parent
# (for section of equal level)
@@ -996,7 +996,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
return
self.body.append('\n\n@multitable ')
for i, n in enumerate(self.colwidths):
self.body.append('{%s} ' % ('x' * (n+2)))
self.body.append('{%s} ' % ('x' * (n + 2)))
def depart_colspec(self, node):
pass
@@ -1274,7 +1274,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
self.add_anchor(id, production)
s = production['tokenname'].ljust(maxlen) + ' ::='
else:
s = '%s ' % (' '*maxlen)
s = '%s ' % (' ' * maxlen)
self.body.append(self.escape(s))
self.body.append(self.escape(production.astext() + '\n'))
self.depart_literal_block(None)

View File

@@ -90,7 +90,7 @@ class TextWrapper(textwrap.TextWrapper):
for i, c in enumerate(word):
total += column_width(c)
if total > space_left:
return word[:i-1], word[i-1:]
return word[:i - 1], word[i - 1:]
return word, ''
def _split(self, text):
@@ -194,7 +194,7 @@ class TextTranslator(nodes.NodeVisitor):
if not toformat:
return
if wrap:
res = my_wrap(''.join(toformat), width=MAXWIDTH-maxindent)
res = my_wrap(''.join(toformat), width=MAXWIDTH - maxindent)
else:
res = ''.join(toformat).splitlines()
if end:
@@ -225,7 +225,7 @@ class TextTranslator(nodes.NodeVisitor):
def depart_document(self, node):
self.end_state()
self.body = self.nl.join(line and (' '*indent + line)
self.body = self.nl.join(line and (' ' * indent + line)
for indent, lines in self.states[0]
for line in lines)
# XXX header/footer?
@@ -271,7 +271,7 @@ class TextTranslator(nodes.NodeVisitor):
def visit_title(self, node):
if isinstance(node.parent, nodes.Admonition):
self.add_text(node.astext()+': ')
self.add_text(node.astext() + ': ')
raise nodes.SkipNode
self.new_state(0)
@@ -401,7 +401,7 @@ class TextTranslator(nodes.NodeVisitor):
self.add_text(production['tokenname'].ljust(maxlen) + ' ::=')
lastname = production['tokenname']
elif lastname is not None:
self.add_text('%s ' % (' '*len(lastname)))
self.add_text('%s ' % (' ' * len(lastname)))
self.add_text(production.astext() + self.nl)
self.end_state(wrap=False)
raise nodes.SkipNode
@@ -552,7 +552,7 @@ class TextTranslator(nodes.NodeVisitor):
def writesep(char='-'):
out = ['+']
for width in realwidths:
out.append(char * (width+2))
out.append(char * (width + 2))
out.append('+')
self.add_text(''.join(out) + self.nl)

View File

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

230
tests/conftest.py Normal file
View File

@@ -0,0 +1,230 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys
import subprocess
from collections import namedtuple
import pytest
from six import StringIO, string_types
import util
@pytest.fixture
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 = {}
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())]
# ##### 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(test_params, app_params, make_app, shared_result):
"""
provides sphinx.application.Sphinx object
"""
args, kwargs = app_params
app_ = make_app(*args, **kwargs)
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')
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(test_params):
"""
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_ = util.SphinxTestApp(*args, **kwargs)
apps.append(app_)
if test_params['shared_result']:
app_ = SphinxTestAppWrapperForSkipBuilding(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 util.path(tmpdir)

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -13,8 +13,8 @@
# "raises" imported for usage by autodoc
import six
import sys
from util import TestApp, Struct, raises, SkipTest
from nose.tools import with_setup, eq_
from util import SphinxTestApp, Struct
import pytest
from six import StringIO
from docutils.statemachine import ViewList
@@ -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)
@@ -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)
@@ -184,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

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

View File

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

View File

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

View File

@@ -17,14 +17,18 @@ import warnings
import traceback
from path import path
import nose
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 ('nose', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
for modname in ('pytest', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
'snowballstemmer', 'babel', 'html5lib'):
try:
__import__(modname)
@@ -49,8 +53,14 @@ 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='nose.util')
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))
for sub in ('root', 'roots')
]
args = sys.argv[1:]
for path in ignore_paths:
args.extend(['--ignore', path])
nose.main(argv=sys.argv)
import pytest
sys.exit(pytest.main(args))

View File

@@ -11,7 +11,8 @@
import sys
from util import with_app, rootdir
import pytest
from util import rootdir
def setup_module():
@@ -22,7 +23,7 @@ def teardown_module():
sys.path.remove(rootdir / 'roots' / 'test-api-set-translator')
@with_app('html')
@pytest.mark.sphinx('html')
def test_html_translator(app, status, warning):
# no set_translator(), no html_translator_class
translator_class = app.builder.translator_class
@@ -30,7 +31,7 @@ def test_html_translator(app, status, warning):
assert translator_class.__name__ == 'SmartyPantsHTMLTranslator'
@with_app('html', confoverrides={
@pytest.mark.sphinx('html', confoverrides={
'html_translator_class': 'translator.ExtHTMLTranslator'})
def test_html_with_html_translator_class(app, status, warning):
# no set_translator(), but html_translator_class
@@ -39,8 +40,8 @@ def test_html_with_html_translator_class(app, status, warning):
assert translator_class.__name__ == 'ExtHTMLTranslator'
@with_app('html',
confoverrides={'html_use_smartypants': False})
@pytest.mark.sphinx('html', confoverrides={
'html_use_smartypants': False})
def test_html_with_smartypants(app, status, warning):
# no set_translator(), html_use_smartypants=False
translator_class = app.builder.translator_class
@@ -48,7 +49,7 @@ def test_html_with_smartypants(app, status, warning):
assert translator_class.__name__ == 'HTMLTranslator'
@with_app('html', testroot='api-set-translator')
@pytest.mark.sphinx('html', testroot='api-set-translator')
def test_html_with_set_translator_for_html_(app, status, warning):
# use set_translator(), no html_translator_class
translator_class = app.builder.translator_class
@@ -56,8 +57,8 @@ def test_html_with_set_translator_for_html_(app, status, warning):
assert translator_class.__name__ == 'ConfHTMLTranslator'
@with_app('html', testroot='api-set-translator',
confoverrides={'html_translator_class': 'translator.ExtHTMLTranslator'})
@pytest.mark.sphinx('html', testroot='api-set-translator', confoverrides={
'html_translator_class': 'translator.ExtHTMLTranslator'})
def test_html_with_set_translator_for_html_and_html_translator_class(
app, status, warning):
# use set_translator() and html_translator_class.
@@ -68,7 +69,7 @@ def test_html_with_set_translator_for_html_and_html_translator_class(
# this test break test_websupport.test_comments test. why?
# @with_app(
# @pytest.mark.sphinx(
# buildername='dirhtml',
# srcdir=(test_roots / 'test-api-set-translator'),
# )
@@ -78,63 +79,63 @@ def test_html_with_set_translator_for_html_and_html_translator_class(
# assert translator_class.__name__ == 'ConfDirHTMLTranslator'
@with_app('singlehtml', testroot='api-set-translator')
@pytest.mark.sphinx('singlehtml', testroot='api-set-translator')
def test_singlehtml_set_translator_for_singlehtml(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class
assert translator_class.__name__ == 'ConfSingleHTMLTranslator'
@with_app('pickle', testroot='api-set-translator')
@pytest.mark.sphinx('pickle', testroot='api-set-translator')
def test_pickle_set_translator_for_pickle(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class
assert translator_class.__name__ == 'ConfPickleTranslator'
@with_app('json', testroot='api-set-translator')
@pytest.mark.sphinx('json', testroot='api-set-translator')
def test_json_set_translator_for_json(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class
assert translator_class.__name__ == 'ConfJsonTranslator'
@with_app('latex', testroot='api-set-translator')
@pytest.mark.sphinx('latex', testroot='api-set-translator')
def test_html_with_set_translator_for_latex(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class
assert translator_class.__name__ == 'ConfLaTeXTranslator'
@with_app('man', testroot='api-set-translator')
@pytest.mark.sphinx('man', testroot='api-set-translator')
def test_html_with_set_translator_for_man(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class
assert translator_class.__name__ == 'ConfManualPageTranslator'
@with_app('texinfo', testroot='api-set-translator')
@pytest.mark.sphinx('texinfo', testroot='api-set-translator')
def test_html_with_set_translator_for_texinfo(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class
assert translator_class.__name__ == 'ConfTexinfoTranslator'
@with_app('text', testroot='api-set-translator')
@pytest.mark.sphinx('text', testroot='api-set-translator')
def test_html_with_set_translator_for_text(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class
assert translator_class.__name__ == 'ConfTextTranslator'
@with_app('xml', testroot='api-set-translator')
@pytest.mark.sphinx('xml', testroot='api-set-translator')
def test_html_with_set_translator_for_xml(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class
assert translator_class.__name__ == 'ConfXMLTranslator'
@with_app('pseudoxml', testroot='api-set-translator')
@pytest.mark.sphinx('pseudoxml', testroot='api-set-translator')
def test_html_with_set_translator_for_pseudoxml(app, status, warning):
translator_class = app.builder.translator_class
assert translator_class

View File

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

View File

@@ -15,19 +15,21 @@ from docutils import nodes
from sphinx.application import ExtensionError
from sphinx.domains import Domain
from util import with_app, raises_msg, strip_escseq
from util import strip_escseq
import pytest
@with_app()
def test_events(app, status, warning):
def empty():
pass
raises_msg(ExtensionError, "Unknown event name: invalid",
app.connect, "invalid", empty)
with pytest.raises(ExtensionError) as excinfo:
app.connect("invalid", empty)
assert "Unknown event name: invalid" in str(excinfo.value)
app.add_event("my_event")
raises_msg(ExtensionError, "Event 'my_event' already present",
app.add_event, "my_event")
with pytest.raises(ExtensionError) as excinfo:
app.add_event("my_event")
assert "Event 'my_event' already present" in str(excinfo.value)
def mock_callback(a_app, *args):
assert a_app is app
@@ -42,13 +44,11 @@ def test_events(app, status, warning):
"Callback called when disconnected"
@with_app()
def test_emit_with_nonascii_name_node(app, status, warning):
node = nodes.section(names=[u'\u65e5\u672c\u8a9e'])
app.emit('my_event', node)
@with_app()
def test_output(app, status, warning):
# info with newline
status.truncate(0) # __init__ writes to status
@@ -68,7 +68,6 @@ def test_output(app, status, warning):
assert app._warncount == old_count + 1
@with_app()
def test_output_with_unencodable_char(app, status, warning):
class StreamWriter(codecs.StreamWriter):
@@ -84,20 +83,17 @@ def test_output_with_unencodable_char(app, status, warning):
assert status.getvalue() == "unicode ?...\n"
@with_app()
def test_extensions(app, status, warning):
app.setup_extension('shutil')
assert strip_escseq(warning.getvalue()).startswith("WARNING: extension 'shutil'")
@with_app()
def test_extension_in_blacklist(app, status, warning):
app.setup_extension('sphinxjp.themecore')
msg = strip_escseq(warning.getvalue())
assert msg.startswith("WARNING: the extension 'sphinxjp.themecore' was")
@with_app()
def test_domain_override(app, status, warning):
class A(Domain):
name = 'foo'
@@ -109,15 +105,18 @@ def test_domain_override(app, status, warning):
name = 'foo'
# No domain know named foo.
raises_msg(ExtensionError, 'domain foo not yet registered',
app.override_domain, A)
with pytest.raises(ExtensionError) as excinfo:
app.override_domain(A)
assert 'domain foo not yet registered' in str(excinfo.value)
assert app.add_domain(A) is None
assert app.override_domain(B) is None
raises_msg(ExtensionError, 'new domain not a subclass of registered '
'foo domain', app.override_domain, C)
with pytest.raises(ExtensionError) as excinfo:
app.override_domain(C)
assert 'new domain not a subclass of registered foo domain' in str(excinfo.value)
@with_app(testroot='add_source_parser')
@pytest.mark.sphinx(testroot='add_source_parser')
def test_add_source_parser(app, status, warning):
assert set(app.config.source_suffix) == set(['.rst', '.md', '.test'])
assert set(app.config.source_parsers.keys()) == set(['.md', '.test'])
@@ -125,7 +124,7 @@ def test_add_source_parser(app, status, warning):
assert app.config.source_parsers['.test'].__name__ == 'TestSourceParser'
@with_app(testroot='add_source_parser-conflicts-with-users-setting')
@pytest.mark.sphinx(testroot='add_source_parser-conflicts-with-users-setting')
def test_add_source_parser_conflicts_with_users_setting(app, status, warning):
assert set(app.config.source_suffix) == set(['.rst', '.test'])
assert set(app.config.source_parsers.keys()) == set(['.test'])

View File

@@ -10,9 +10,8 @@
:license: BSD, see LICENSE for details.
"""
# "raises" imported for usage by autodoc
from util import TestApp, Struct, raises, SkipTest # NOQA
from nose.tools import with_setup, eq_
from util import SphinxTestApp, Struct # NOQA
import pytest
import enum
from six import StringIO, add_metaclass
@@ -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)
@@ -41,6 +40,7 @@ def teardown_module():
directive = options = None
@pytest.fixture
def setup_test():
global options, directive
global processed_docstrings, processed_signatures, _warnings
@@ -74,6 +74,10 @@ def setup_test():
processed_signatures = []
_warnings = []
yield
AutoDirective._special_attrgetters.clear()
_warnings = []
processed_docstrings = []
@@ -105,7 +109,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)
@@ -120,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']
@@ -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)
@@ -653,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
@@ -873,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."""
@@ -1081,10 +1091,10 @@ 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):
eq_(formatargspec(f, *getargspec(f)), expected)
assert formatargspec(f, *getargspec(f)) == expected
# Class annotations
verify_arg_spec(f0, '(x: int, y: numbers.Integral) -> None')

View File

@@ -9,21 +9,14 @@
:license: BSD, see LICENSE for details.
"""
from six import BytesIO
import pickle
from docutils import nodes
import mock
import pytest
from textwrap import dedent
from sphinx.errors import SphinxError
import sphinx.builders.linkcheck
from util import with_app, with_tempdir, rootdir, tempdir, SkipTest, TestApp, path
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):
@@ -33,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("""
@@ -64,35 +50,36 @@ 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()
@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, make_app):
(tempdir / 'conf.py').write_text('master_doc = "index"')
assert tempdir.listdir() == ['conf.py']
try:
app = TestApp(buildername='dummy', srcdir=tmpdir)
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()
@with_app(buildername='text', testroot='circular')
@pytest.mark.sphinx(buildername='text', testroot='circular')
def test_circular_toctree(app, status, warning):
app.builder.build_all()
warnings = warning.getvalue()
@@ -104,7 +91,7 @@ def test_circular_toctree(app, status, warning):
'contents <- sub <- contents') in warnings
@with_app(buildername='text', testroot='numbered-circular')
@pytest.mark.sphinx(buildername='text', testroot='numbered-circular')
def test_numbered_circular_toctree(app, status, warning):
app.builder.build_all()
warnings = warning.getvalue()
@@ -116,7 +103,7 @@ def test_numbered_circular_toctree(app, status, warning):
'contents <- sub <- contents') in warnings
@with_app(buildername='dummy', testroot='image-glob')
@pytest.mark.sphinx(buildername='dummy', testroot='image-glob')
def test_image_glob(app, status, warning):
app.builder.build_all()

View File

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

View File

@@ -15,36 +15,38 @@ import re
import gettext
from subprocess import Popen, PIPE
from nose.tools import assert_true, assert_equal
import pytest
from util import with_app, gen_with_app, SkipTest, assert_in
from 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:
@@ -52,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:
@@ -66,19 +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"
@with_app('gettext', testroot='intl',
confoverrides={'gettext_compact': False})
def test_gettext_index_entries(app, status, warning):
@pytest.mark.sphinx(
'gettext', testroot='intl', srcdir='gettext',
confoverrides={'gettext_compact': False})
def test_gettext_index_entries(app):
# regression test for #976
app.builder.build(['index_entries'])
@@ -123,9 +123,11 @@ def test_gettext_index_entries(app, status, warning):
assert msgids == []
@with_app('gettext', testroot='intl',
confoverrides={'gettext_compact': False, 'gettext_additional_targets': []})
def test_gettext_disable_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):
# regression test for #976
app.builder.build(['index_entries'])
@@ -155,8 +157,8 @@ def test_gettext_disable_index_entries(app, status, warning):
assert msgids == []
@with_app(buildername='gettext', testroot='intl')
def test_gettext_template(app, status, warning):
@pytest.mark.sphinx('gettext', testroot='intl', srcdir='gettext')
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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,19 +10,19 @@
:license: BSD, see LICENSE for details.
"""
from six import PY3, iteritems
import pytest
import mock
from util import TestApp, with_app, gen_with_app, with_tempdir, \
raises, raises_msg, assert_in, assert_not_in
import sphinx
from sphinx.config import Config
from sphinx.errors import ExtensionError, ConfigError, VersionRequirementError
@with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True',
'latex_elements.docclass': 'scrartcl',
'modindex_common_prefix': 'path1,path2'})
@pytest.mark.sphinx(confoverrides={
'master_doc': 'master',
'nonexisting_value': 'True',
'latex_elements.docclass': 'scrartcl',
'modindex_common_prefix': 'path1,path2'})
def test_core_config(app, status, warning):
cfg = app.config
@@ -55,11 +55,14 @@ def test_core_config(app, status, warning):
assert 'nonexisting_value' not in cfg
# invalid values
raises(AttributeError, getattr, cfg, '_value')
raises(AttributeError, getattr, cfg, 'nonexisting_value')
with pytest.raises(AttributeError):
getattr(cfg, '_value')
with pytest.raises(AttributeError):
getattr(cfg, 'nonexisting_value')
# non-value attributes are deleted from the namespace
raises(AttributeError, getattr, cfg, 'sys')
with pytest.raises(AttributeError):
getattr(cfg, 'sys')
# setting attributes
cfg.project = 'Foo'
@@ -70,7 +73,6 @@ def test_core_config(app, status, warning):
assert cfg['project'] == cfg.project == 'Sphinx Tests'
@with_app()
def test_extension_values(app, status, warning):
cfg = app.config
@@ -80,23 +82,26 @@ def test_extension_values(app, status, warning):
assert cfg.value_from_conf_py == 84
# no duplicate values allowed
raises_msg(ExtensionError, 'already present', app.add_config_value,
'html_title', 'x', True)
raises_msg(ExtensionError, 'already present', app.add_config_value,
'value_from_ext', 'x', True)
with pytest.raises(ExtensionError) as excinfo:
app.add_config_value('html_title', 'x', True)
assert 'already present' in str(excinfo.value)
with pytest.raises(ExtensionError) as excinfo:
app.add_config_value('value_from_ext', 'x', True)
assert 'already present' in str(excinfo.value)
@with_tempdir
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')
with pytest.raises(ConfigError) as excinfo:
Config(tempdir, 'conf.py', {}, None)
assert 'conf.py' in str(excinfo.value)
# test the automatic conversion of 2.x only code in configs
(dir / 'conf.py').write_text(
(tempdir / 'conf.py').write_text(
u'# -*- coding: utf-8\n\nproject = u"Jägermeister"\n',
encoding='utf-8')
cfg = Config(dir, 'conf.py', {}, None)
cfg = Config(tempdir, 'conf.py', {}, None)
cfg.init_values(lambda warning: 1/0)
assert cfg.project == u'Jägermeister'
@@ -105,9 +110,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):
@@ -117,62 +122,64 @@ def test_errors_warnings(dir):
assert warned[0]
@with_tempdir
def test_errors_if_setup_is_not_callable(dir):
def test_errors_if_setup_is_not_callable(tempdir, make_app):
# test the error to call setup() in the config file
(dir / 'conf.py').write_text(u'setup = 1')
raises_msg(ConfigError, 'callable', TestApp, srcdir=dir)
(tempdir / 'conf.py').write_text(u'setup = 1')
with pytest.raises(ConfigError) as excinfo:
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()
raises(VersionRequirementError, TestApp,
confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
with pytest.raises(VersionRequirementError):
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()
raises(VersionRequirementError, TestApp,
confoverrides={'needs_sphinx': '1.4'}) # NG: greater
with pytest.raises(VersionRequirementError):
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()
raises(VersionRequirementError, TestApp,
confoverrides={'needs_sphinx': '2'}) # NG: greater
with pytest.raises(VersionRequirementError):
make_app(confoverrides={'needs_sphinx': '2'}) # NG: greater
@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'
@with_app(confoverrides={'master_doc': 123,
@pytest.mark.sphinx(confoverrides={'master_doc': 123,
'language': 'foo',
'primary_domain': None})
def test_builtin_conf(app, status, warning):
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.
@@ -187,7 +194,7 @@ TYPECHECK_WARNINGS = {
'value8': False,
'value9': False,
'value10': False,
'value11': True,
'value11': False if PY3 else True,
'value12': False,
'value13': False,
'value14': False,
@@ -196,25 +203,27 @@ 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
)
@with_app(testroot='config')
@pytest.mark.sphinx(testroot='config')
def test_check_enum(app, status, warning):
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
not in warning.getvalue()
@with_app(testroot='config', confoverrides={'value17': 'invalid'})
@pytest.mark.sphinx(testroot='config', confoverrides={'value17': 'invalid'})
def test_check_enum_failed(app, status, warning):
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
"but `invalid` is given." in warning.getvalue()

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,9 +9,7 @@
:license: BSD, see LICENSE for details.
"""
from six import PY3
from util import TestApp, remove_unicode_literals, path
from util import SphinxTestApp, path
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.builders.latex import LaTeXBuilder
@@ -22,7 +20,7 @@ warnings = []
def setup_module():
global app, env
app = TestApp(srcdir='root-envtest')
app = SphinxTestApp(srcdir='root-envtest')
env = app.env
env.set_warnfunc(lambda *args, **kwargs: warnings.append(args))
@@ -54,7 +52,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 +61,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()) == \

View File

@@ -14,24 +14,15 @@ from docutils.nodes import bullet_list, list_item, caption, comment, reference
from sphinx import addnodes
from sphinx.addnodes import compact_paragraph, only
from sphinx.builders.html import StandaloneHTMLBuilder
import pytest
from util import with_app, gen_with_app, assert_node
from util import 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,
@@ -97,8 +88,8 @@ def _test_process_doc(app):
assert 'qux' not in app.env.toctree_includes
@with_app('dummy', testroot='toctree-glob')
def test_glob(app, status, warning):
@pytest.mark.sphinx('dummy', testroot='toctree-glob')
def test_glob(app):
includefiles = ['foo', 'bar/index', 'bar/bar_1', 'bar/bar_2',
'bar/bar_3', 'baz', 'qux/index']
@@ -143,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,
@@ -166,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)
@@ -193,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,
@@ -205,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"],
@@ -239,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"],
@@ -264,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"],
@@ -303,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,

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ from six import iteritems, StringIO
from sphinx.ext.autosummary import mangle_signature
from util import with_app
import pytest
html_warnfile = StringIO()
@@ -54,7 +54,7 @@ def test_mangle_signature():
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
@with_app(buildername='dummy', **default_kw)
@pytest.mark.sphinx('dummy', **default_kw)
def test_get_items_summary(app, status, warning):
# monkey-patch Autosummary.get_items so we can easily get access to it's
# results..

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More