mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
merge with stable
This commit is contained in:
commit
da20c3713b
11
CHANGES
11
CHANGES
@ -179,6 +179,17 @@ Bugs fixed
|
|||||||
object to str implicitly" error when link target url has a hash part.
|
object to str implicitly" error when link target url has a hash part.
|
||||||
Thanks to Jorge_C.
|
Thanks to Jorge_C.
|
||||||
* #1467: Exception on Python3 if nonexistent method is specified by automethod
|
* #1467: Exception on Python3 if nonexistent method is specified by automethod
|
||||||
|
* #1441: autosummary can't handle nested classes correctly.
|
||||||
|
* #1499: With non-callable `setup` in a conf.py, now sphinx-build emits
|
||||||
|
user-friendly error message.
|
||||||
|
* #1502: In autodoc, fix display of parameter defaults containing backslashes.
|
||||||
|
* #1226: autodoc, autosummary: importing setup.py by automodule will invoke
|
||||||
|
setup process and execute `sys.exit()`. Now sphinx avoids SystemExit
|
||||||
|
exception and emits warnings without unexpected termination.
|
||||||
|
* #1503: py:function directive generate incorrectly signature when specifying
|
||||||
|
a default parameter with an empty list `[]`. Thanks to Geert Jansen.
|
||||||
|
* #1508: Non-ASCII filename raise exception on make singlehtml, latex, man,
|
||||||
|
texinfo and changes.
|
||||||
|
|
||||||
Release 1.2.2 (released Mar 2, 2014)
|
Release 1.2.2 (released Mar 2, 2014)
|
||||||
====================================
|
====================================
|
||||||
|
@ -30,7 +30,7 @@ from sphinx import package_dir, locale
|
|||||||
from sphinx.roles import XRefRole
|
from sphinx.roles import XRefRole
|
||||||
from sphinx.config import Config
|
from sphinx.config import Config
|
||||||
from sphinx.errors import SphinxError, SphinxWarning, ExtensionError, \
|
from sphinx.errors import SphinxError, SphinxWarning, ExtensionError, \
|
||||||
VersionRequirementError
|
VersionRequirementError, ConfigError
|
||||||
from sphinx.domains import ObjType, BUILTIN_DOMAINS
|
from sphinx.domains import ObjType, BUILTIN_DOMAINS
|
||||||
from sphinx.domains.std import GenericObject, Target, StandardDomain
|
from sphinx.domains.std import GenericObject, Target, StandardDomain
|
||||||
from sphinx.builders import BUILTIN_BUILDERS
|
from sphinx.builders import BUILTIN_BUILDERS
|
||||||
@ -122,7 +122,15 @@ class Sphinx(object):
|
|||||||
self.setup_extension(extension)
|
self.setup_extension(extension)
|
||||||
# the config file itself can be an extension
|
# the config file itself can be an extension
|
||||||
if self.config.setup:
|
if self.config.setup:
|
||||||
self.config.setup(self)
|
# py31 doesn't have 'callable' function for bellow check
|
||||||
|
if hasattr(self.config.setup, '__call__'):
|
||||||
|
self.config.setup(self)
|
||||||
|
else:
|
||||||
|
raise ConfigError(
|
||||||
|
"'setup' that is specified in the conf.py has not been " +
|
||||||
|
"callable. Please provide a callable `setup` function " +
|
||||||
|
"in order to behave as a sphinx extension conf.py itself."
|
||||||
|
)
|
||||||
|
|
||||||
# now that we know all config values, collect them from conf.py
|
# now that we know all config values, collect them from conf.py
|
||||||
self.config.init_values(self.warn)
|
self.config.init_values(self.warn)
|
||||||
|
@ -126,14 +126,15 @@ class ChangesBuilder(Builder):
|
|||||||
|
|
||||||
self.info(bold('copying source files...'))
|
self.info(bold('copying source files...'))
|
||||||
for docname in self.env.all_docs:
|
for docname in self.env.all_docs:
|
||||||
f = codecs.open(self.env.doc2path(docname), 'r', 'latin1')
|
f = codecs.open(self.env.doc2path(docname), 'r',
|
||||||
|
self.env.config.source_encoding)
|
||||||
try:
|
try:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
finally:
|
finally:
|
||||||
f.close()
|
f.close()
|
||||||
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
|
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
|
||||||
ensuredir(path.dirname(targetfn))
|
ensuredir(path.dirname(targetfn))
|
||||||
f = codecs.open(targetfn, 'w', 'latin1')
|
f = codecs.open(targetfn, 'w', 'utf-8')
|
||||||
try:
|
try:
|
||||||
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 = {
|
ctx = {
|
||||||
|
@ -55,7 +55,7 @@ def _pseudo_parse_arglist(signode, arglist):
|
|||||||
while argument.startswith(']'):
|
while argument.startswith(']'):
|
||||||
stack.pop()
|
stack.pop()
|
||||||
argument = argument[1:].strip()
|
argument = argument[1:].strip()
|
||||||
while argument.endswith(']'):
|
while argument.endswith(']') and not argument.endswith('[]'):
|
||||||
ends_close += 1
|
ends_close += 1
|
||||||
argument = argument[:-1].strip()
|
argument = argument[:-1].strip()
|
||||||
while argument.endswith('['):
|
while argument.endswith('['):
|
||||||
|
@ -380,15 +380,19 @@ class Documenter(object):
|
|||||||
return True
|
return True
|
||||||
# this used to only catch SyntaxError, ImportError and AttributeError,
|
# this used to only catch SyntaxError, ImportError and AttributeError,
|
||||||
# but importing modules with side effects can raise all kinds of errors
|
# but importing modules with side effects can raise all kinds of errors
|
||||||
except Exception:
|
except (Exception, SystemExit) as e:
|
||||||
if self.objpath:
|
if self.objpath:
|
||||||
errmsg = 'autodoc: failed to import %s %r from module %r' % \
|
errmsg = 'autodoc: failed to import %s %r from module %r' % \
|
||||||
(self.objtype, '.'.join(self.objpath), self.modname)
|
(self.objtype, '.'.join(self.objpath), self.modname)
|
||||||
else:
|
else:
|
||||||
errmsg = 'autodoc: failed to import %s %r' % \
|
errmsg = 'autodoc: failed to import %s %r' % \
|
||||||
(self.objtype, self.fullname)
|
(self.objtype, self.fullname)
|
||||||
errmsg += '; the following exception was raised:\n%s' % \
|
if isinstance(e, SystemExit):
|
||||||
traceback.format_exc()
|
errmsg += ('; the module executes module level statement ' +
|
||||||
|
'and it might call sys.exit().')
|
||||||
|
else:
|
||||||
|
errmsg += '; the following exception was raised:\n%s' % \
|
||||||
|
traceback.format_exc()
|
||||||
dbg(errmsg)
|
dbg(errmsg)
|
||||||
self.directive.warn(errmsg)
|
self.directive.warn(errmsg)
|
||||||
self.env.note_reread()
|
self.env.note_reread()
|
||||||
@ -1258,7 +1262,10 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
|
|||||||
argspec = getargspec(self.object)
|
argspec = getargspec(self.object)
|
||||||
if argspec[0] and argspec[0][0] in ('cls', 'self'):
|
if argspec[0] and argspec[0][0] in ('cls', 'self'):
|
||||||
del argspec[0][0]
|
del argspec[0][0]
|
||||||
return inspect.formatargspec(*argspec)
|
args = inspect.formatargspec(*argspec)
|
||||||
|
# escape backslashes for reST
|
||||||
|
args = args.replace('\\', '\\\\')
|
||||||
|
return args
|
||||||
|
|
||||||
def document_members(self, all_members=False):
|
def document_members(self, all_members=False):
|
||||||
pass
|
pass
|
||||||
|
@ -244,16 +244,21 @@ class Autosummary(Directive):
|
|||||||
display_name = name.split('.')[-1]
|
display_name = name.split('.')[-1]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
real_name, obj, parent = import_by_name(name, prefixes=prefixes)
|
real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
self.warn('failed to import %s' % name)
|
self.warn('failed to import %s' % name)
|
||||||
items.append((name, '', '', name))
|
items.append((name, '', '', name))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# NB. using real_name here is important, since Documenters
|
|
||||||
# handle module prefixes slightly differently
|
|
||||||
self.result = ViewList() # initialize for each documenter
|
self.result = ViewList() # initialize for each documenter
|
||||||
documenter = get_documenter(obj, parent)(self, real_name)
|
full_name = real_name
|
||||||
|
if full_name.startswith(modname + '.'):
|
||||||
|
# give explicitly separated module name, so that members
|
||||||
|
# of inner classes can be documented
|
||||||
|
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)
|
||||||
if not documenter.parse_name():
|
if not documenter.parse_name():
|
||||||
self.warn('failed to parse name %s' % real_name)
|
self.warn('failed to parse name %s' % real_name)
|
||||||
items.append((display_name, '', '', real_name))
|
items.append((display_name, '', '', real_name))
|
||||||
@ -449,8 +454,8 @@ def import_by_name(name, prefixes=[None]):
|
|||||||
prefixed_name = '.'.join([prefix, name])
|
prefixed_name = '.'.join([prefix, name])
|
||||||
else:
|
else:
|
||||||
prefixed_name = name
|
prefixed_name = name
|
||||||
obj, parent = _import_by_name(prefixed_name)
|
obj, parent, modname = _import_by_name(prefixed_name)
|
||||||
return prefixed_name, obj, parent
|
return prefixed_name, obj, parent, modname
|
||||||
except ImportError:
|
except ImportError:
|
||||||
tried.append(prefixed_name)
|
tried.append(prefixed_name)
|
||||||
raise ImportError('no module named %s' % ' or '.join(tried))
|
raise ImportError('no module named %s' % ' or '.join(tried))
|
||||||
@ -466,7 +471,7 @@ def _import_by_name(name):
|
|||||||
try:
|
try:
|
||||||
__import__(modname)
|
__import__(modname)
|
||||||
mod = sys.modules[modname]
|
mod = sys.modules[modname]
|
||||||
return getattr(mod, name_parts[-1]), mod
|
return getattr(mod, name_parts[-1]), mod, modname
|
||||||
except (ImportError, IndexError, AttributeError):
|
except (ImportError, IndexError, AttributeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -489,9 +494,9 @@ def _import_by_name(name):
|
|||||||
for obj_name in name_parts[last_j:]:
|
for obj_name in name_parts[last_j:]:
|
||||||
parent = obj
|
parent = obj
|
||||||
obj = getattr(obj, obj_name)
|
obj = getattr(obj, obj_name)
|
||||||
return obj, parent
|
return obj, parent, modname
|
||||||
else:
|
else:
|
||||||
return sys.modules[modname], None
|
return sys.modules[modname], None, modname
|
||||||
except (ValueError, ImportError, AttributeError, KeyError) as e:
|
except (ValueError, ImportError, AttributeError, KeyError) as e:
|
||||||
raise ImportError(*e.args)
|
raise ImportError(*e.args)
|
||||||
|
|
||||||
@ -512,7 +517,7 @@ def autolink_role(typ, rawtext, etext, lineno, inliner,
|
|||||||
|
|
||||||
prefixes = get_import_prefixes_from_env(env)
|
prefixes = get_import_prefixes_from_env(env)
|
||||||
try:
|
try:
|
||||||
name, obj, parent = import_by_name(pnode['reftarget'], prefixes)
|
name, obj, parent, modname = import_by_name(pnode['reftarget'], prefixes)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
content = pnode[0]
|
content = pnode[0]
|
||||||
r[0][0] = nodes.emphasis(rawtext, content[0].astext(),
|
r[0][0] = nodes.emphasis(rawtext, content[0].astext(),
|
||||||
|
@ -124,7 +124,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
|||||||
ensuredir(path)
|
ensuredir(path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
name, obj, parent = import_by_name(name)
|
name, obj, parent, mod_name = import_by_name(name)
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
warn('[autosummary] failed to import %r: %s' % (name, e))
|
warn('[autosummary] failed to import %r: %s' % (name, e))
|
||||||
continue
|
continue
|
||||||
@ -233,13 +233,16 @@ def find_autosummary_in_docstring(name, module=None, filename=None):
|
|||||||
See `find_autosummary_in_lines`.
|
See `find_autosummary_in_lines`.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
real_name, obj, parent = import_by_name(name)
|
real_name, obj, parent, modname = import_by_name(name)
|
||||||
lines = pydoc.getdoc(obj).splitlines()
|
lines = pydoc.getdoc(obj).splitlines()
|
||||||
return find_autosummary_in_lines(lines, module=name, filename=filename)
|
return find_autosummary_in_lines(lines, module=name, filename=filename)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print("Failed to import '%s': %s" % (name, e))
|
print("Failed to import '%s': %s" % (name, e))
|
||||||
|
except SystemExit as e:
|
||||||
|
print("Failed to import '%s'; the module executes module level "
|
||||||
|
"statement and it might call sys.exit()." % name)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def find_autosummary_in_lines(lines, module=None, filename=None):
|
def find_autosummary_in_lines(lines, module=None, filename=None):
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from six import text_type
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
@ -185,7 +186,7 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc):
|
|||||||
tree = tree.deepcopy()
|
tree = tree.deepcopy()
|
||||||
for toctreenode in tree.traverse(addnodes.toctree):
|
for toctreenode in tree.traverse(addnodes.toctree):
|
||||||
newnodes = []
|
newnodes = []
|
||||||
includefiles = map(str, toctreenode['includefiles'])
|
includefiles = map(text_type, toctreenode['includefiles'])
|
||||||
for includefile in includefiles:
|
for includefile in includefiles:
|
||||||
try:
|
try:
|
||||||
builder.info(colorfunc(includefile) + " ", nonl=1)
|
builder.info(colorfunc(includefile) + " ", nonl=1)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
C.class_attr
|
C.class_attr
|
||||||
C.prop_attr1
|
C.prop_attr1
|
||||||
C.prop_attr2
|
C.prop_attr2
|
||||||
|
C.C2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def withSentence():
|
def withSentence():
|
||||||
@ -63,3 +64,8 @@ class C:
|
|||||||
|
|
||||||
value is string.
|
value is string.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
class C2:
|
||||||
|
'''
|
||||||
|
This is a nested inner class docstring
|
||||||
|
'''
|
||||||
|
@ -161,10 +161,13 @@ def test_format_signature():
|
|||||||
# test for functions
|
# test for functions
|
||||||
def f(a, b, c=1, **d):
|
def f(a, b, c=1, **d):
|
||||||
pass
|
pass
|
||||||
|
def g(a='\n'):
|
||||||
|
pass
|
||||||
assert formatsig('function', 'f', f, None, None) == '(a, b, c=1, **d)'
|
assert formatsig('function', 'f', f, None, None) == '(a, b, c=1, **d)'
|
||||||
assert formatsig('function', 'f', f, 'a, b, c, d', None) == '(a, b, c, d)'
|
assert formatsig('function', 'f', f, 'a, b, c, d', None) == '(a, b, c, d)'
|
||||||
assert formatsig('function', 'f', f, None, 'None') == \
|
assert formatsig('function', 'f', f, None, 'None') == \
|
||||||
'(a, b, c=1, **d) -> None'
|
'(a, b, c=1, **d) -> None'
|
||||||
|
assert formatsig('function', 'g', g, None, None) == r"(a='\\n')"
|
||||||
|
|
||||||
# test for classes
|
# test for classes
|
||||||
class D:
|
class D:
|
||||||
@ -204,9 +207,12 @@ def test_format_signature():
|
|||||||
pass
|
pass
|
||||||
def foo2(b, *c):
|
def foo2(b, *c):
|
||||||
pass
|
pass
|
||||||
|
def foo3(self, d='\n'):
|
||||||
|
pass
|
||||||
assert formatsig('method', 'H.foo', H.foo1, None, None) == '(b, *c)'
|
assert formatsig('method', 'H.foo', H.foo1, None, None) == '(b, *c)'
|
||||||
assert formatsig('method', 'H.foo', H.foo1, 'a', None) == '(a)'
|
assert formatsig('method', 'H.foo', H.foo1, 'a', None) == '(a)'
|
||||||
assert formatsig('method', 'H.foo', H.foo2, None, None) == '(b, *c)'
|
assert formatsig('method', 'H.foo', H.foo2, None, None) == '(b, *c)'
|
||||||
|
assert formatsig('method', 'H.foo', H.foo3, None, None) == r"(d='\\n')"
|
||||||
|
|
||||||
# test exception handling (exception is caught and args is '')
|
# test exception handling (exception is caught and args is '')
|
||||||
assert formatsig('function', 'int', int, None, None) == ''
|
assert formatsig('function', 'int', int, None, None) == ''
|
||||||
|
@ -11,12 +11,14 @@
|
|||||||
import sys
|
import sys
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from six import iteritems
|
from six import iteritems, StringIO
|
||||||
|
|
||||||
from sphinx.ext.autosummary import mangle_signature
|
from sphinx.ext.autosummary import mangle_signature
|
||||||
|
|
||||||
from util import test_roots, TestApp
|
from util import test_roots, TestApp
|
||||||
|
|
||||||
|
html_warnfile = StringIO()
|
||||||
|
|
||||||
|
|
||||||
def with_autosummary_app(*args, **kw):
|
def with_autosummary_app(*args, **kw):
|
||||||
default_kw = {
|
default_kw = {
|
||||||
@ -77,7 +79,7 @@ def test_mangle_signature():
|
|||||||
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
|
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
|
||||||
|
|
||||||
|
|
||||||
@with_autosummary_app(buildername='html')
|
@with_autosummary_app(buildername='html', warning=html_warnfile)
|
||||||
def test_get_items_summary(app):
|
def test_get_items_summary(app):
|
||||||
app.builddir.rmtree(True)
|
app.builddir.rmtree(True)
|
||||||
|
|
||||||
@ -100,6 +102,9 @@ def test_get_items_summary(app):
|
|||||||
finally:
|
finally:
|
||||||
sphinx.ext.autosummary.Autosummary.get_items = orig_get_items
|
sphinx.ext.autosummary.Autosummary.get_items = orig_get_items
|
||||||
|
|
||||||
|
html_warnings = html_warnfile.getvalue()
|
||||||
|
assert html_warnings == ''
|
||||||
|
|
||||||
expected_values = {
|
expected_values = {
|
||||||
'withSentence': 'I have a sentence which spans multiple lines.',
|
'withSentence': 'I have a sentence which spans multiple lines.',
|
||||||
'noSentence': "this doesn't start with a",
|
'noSentence': "this doesn't start with a",
|
||||||
@ -108,6 +113,7 @@ def test_get_items_summary(app):
|
|||||||
'C.class_attr': 'This is a class attribute',
|
'C.class_attr': 'This is a class attribute',
|
||||||
'C.prop_attr1': 'This is a function docstring',
|
'C.prop_attr1': 'This is a function docstring',
|
||||||
'C.prop_attr2': 'This is a attribute docstring',
|
'C.prop_attr2': 'This is a attribute docstring',
|
||||||
|
'C.C2': 'This is a nested inner class docstring',
|
||||||
}
|
}
|
||||||
for key, expected in iteritems(expected_values):
|
for key, expected in iteritems(expected_values):
|
||||||
assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
|
assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
|
||||||
|
@ -9,71 +9,37 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from util import with_app, test_root, path, SkipTest
|
from util import with_app, test_root, path, SkipTest, TestApp
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
|
try:
|
||||||
|
from docutils.writers.manpage import Writer as ManWriter
|
||||||
|
except ImportError:
|
||||||
|
ManWriter = None
|
||||||
|
|
||||||
|
|
||||||
def teardown_module():
|
def teardown_module():
|
||||||
(test_root / '_build').rmtree(True)
|
(test_root / '_build').rmtree(True)
|
||||||
|
|
||||||
# just let the remaining ones run for now
|
|
||||||
|
|
||||||
@with_app(buildername='pickle')
|
def test_build():
|
||||||
def test_pickle(app):
|
for buildername in ('pickle', 'json', 'linkcheck', 'text', 'htmlhelp',
|
||||||
|
'qthelp', 'epub', 'changes', 'singlehtml', 'xml',
|
||||||
|
'pseudoxml'):
|
||||||
|
app = TestApp(buildername=buildername)
|
||||||
|
yield lambda app: app.builder.build_all(), app
|
||||||
|
app.cleanup()
|
||||||
|
|
||||||
|
|
||||||
|
@with_app(buildername='man')
|
||||||
|
def test_man(app):
|
||||||
|
if ManWriter is None:
|
||||||
|
raise SkipTest('man writer is not available')
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
assert (app.outdir / 'SphinxTests.1').exists()
|
||||||
|
|
||||||
@with_app(buildername='json')
|
|
||||||
def test_json(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='linkcheck')
|
def _test_nonascii_path(app):
|
||||||
def test_linkcheck(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='text')
|
|
||||||
def test_text(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='htmlhelp')
|
|
||||||
def test_htmlhelp(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='qthelp')
|
|
||||||
def test_qthelp(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='epub')
|
|
||||||
def test_epub(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='changes')
|
|
||||||
def test_changes(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
try:
|
|
||||||
from docutils.writers.manpage import Writer
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
@with_app(buildername='man')
|
|
||||||
def test_man(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
assert (app.outdir / 'SphinxTests.1').exists()
|
|
||||||
|
|
||||||
@with_app(buildername='singlehtml', cleanenv=True)
|
|
||||||
def test_singlehtml(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='xml')
|
|
||||||
def test_xml(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='pseudoxml')
|
|
||||||
def test_pseudoxml(app):
|
|
||||||
app.builder.build_all()
|
|
||||||
|
|
||||||
@with_app(buildername='html', srcdir='(temp)')
|
|
||||||
def test_nonascii_path(app):
|
|
||||||
srcdir = path(app.srcdir)
|
srcdir = path(app.srcdir)
|
||||||
mb_name = u'\u65e5\u672c\u8a9e'
|
mb_name = u'\u65e5\u672c\u8a9e'
|
||||||
try:
|
try:
|
||||||
@ -94,6 +60,22 @@ def test_nonascii_path(app):
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
||||||
%(mb_name)s/%(mb_name)s
|
%(mb_name)s/%(mb_name)s
|
||||||
""" % locals())
|
""" % {'mb_name': mb_name})
|
||||||
).encode('utf-8'))
|
).encode('utf-8'))
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
|
||||||
|
|
||||||
|
def test_nonascii_path():
|
||||||
|
(test_root / '_build').rmtree(True) #keep this to build first gettext
|
||||||
|
|
||||||
|
builder_names = ['gettext', 'html', 'dirhtml', 'singlehtml', 'latex',
|
||||||
|
'texinfo', 'pickle', 'json', 'linkcheck', 'text',
|
||||||
|
'htmlhelp', 'qthelp', 'epub', 'changes', 'xml',
|
||||||
|
'pseudoxml']
|
||||||
|
if ManWriter is not None:
|
||||||
|
builder_names.append('man')
|
||||||
|
|
||||||
|
for buildername in builder_names:
|
||||||
|
app = TestApp(buildername=buildername, srcdir='(temp)')
|
||||||
|
yield _test_nonascii_path, app
|
||||||
|
app.cleanup()
|
||||||
|
@ -112,6 +112,13 @@ def test_errors_warnings(dir):
|
|||||||
assert warned[0]
|
assert warned[0]
|
||||||
|
|
||||||
|
|
||||||
|
@with_tempdir
|
||||||
|
def test_errors_if_setup_is_not_callable(dir):
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
|
||||||
def test_needs_sphinx():
|
def test_needs_sphinx():
|
||||||
raises(VersionRequirementError, TestApp,
|
raises(VersionRequirementError, TestApp,
|
||||||
confoverrides={'needs_sphinx': '9.9'})
|
confoverrides={'needs_sphinx': '9.9'})
|
||||||
|
46
tests/test_py_domain.py
Normal file
46
tests/test_py_domain.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
test_py_domain
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Tests the Python Domain
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from six import text_type
|
||||||
|
|
||||||
|
from sphinx import addnodes
|
||||||
|
from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist
|
||||||
|
|
||||||
|
|
||||||
|
def parse(sig):
|
||||||
|
m = py_sig_re.match(sig)
|
||||||
|
if m is None:
|
||||||
|
raise ValueError
|
||||||
|
name_prefix, name, arglist, retann = m.groups()
|
||||||
|
signode = addnodes.desc_signature(sig, '')
|
||||||
|
_pseudo_parse_arglist(signode, arglist)
|
||||||
|
return signode.astext()
|
||||||
|
|
||||||
|
|
||||||
|
def test_function_signatures():
|
||||||
|
|
||||||
|
rv = parse('func(a=1) -> int object')
|
||||||
|
assert text_type(rv) == u'a=1'
|
||||||
|
|
||||||
|
rv = parse('func(a=1, [b=None])')
|
||||||
|
assert text_type(rv) == u'a=1, [b=None]'
|
||||||
|
|
||||||
|
rv = parse('func(a=1[, b=None])')
|
||||||
|
assert text_type(rv) == u'a=1, [b=None]'
|
||||||
|
|
||||||
|
rv = parse("compile(source : string, filename, symbol='file')")
|
||||||
|
assert text_type(rv) == u"source : string, filename, symbol='file'"
|
||||||
|
|
||||||
|
rv = parse('func(a=[], [b=None])')
|
||||||
|
assert text_type(rv) == u'a=[], [b=None]'
|
||||||
|
|
||||||
|
rv = parse('func(a=[][, b=None])')
|
||||||
|
assert text_type(rv) == u'a=[], [b=None]'
|
@ -181,6 +181,9 @@ class TestApp(application.Sphinx):
|
|||||||
for tree in self.cleanup_trees:
|
for tree in self.cleanup_trees:
|
||||||
shutil.rmtree(tree, True)
|
shutil.rmtree(tree, True)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<%s buildername=%r>' % (self.__class__.__name__, self.builder.name)
|
||||||
|
|
||||||
|
|
||||||
def with_app(*args, **kwargs):
|
def with_app(*args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user