Merge branch 'master' into graphviz_width_of_svg

This commit is contained in:
Takeshi KOMIYA 2018-08-07 23:16:37 +09:00 committed by GitHub
commit b09c54e669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 296 additions and 211 deletions

View File

@ -12,6 +12,9 @@ Dependencies
Incompatible changes Incompatible changes
-------------------- --------------------
* #5156: the :py:mod:`sphinx.ext.graphviz: extension runs `dot` in the
directory of the document being built instead of in the root directory of
the documentation.
* #4460: extensions which stores any data to environment should return the * #4460: extensions which stores any data to environment should return the
version of its env data structure as metadata. In detail, please see version of its env data structure as metadata. In detail, please see
:ref:`ext-metadata`. :ref:`ext-metadata`.
@ -55,6 +58,7 @@ Deprecated
---------- ----------
* :confval:`source_parsers` is deprecated * :confval:`source_parsers` is deprecated
* quickstart: ``--epub`` option becomes default, so it is deprecated
* Drop function based directive support. For now, Sphinx only supports class * Drop function based directive support. For now, Sphinx only supports class
based directives. based directives.
* ``sphinx.util.docutils.directive_helper()`` is deprecated * ``sphinx.util.docutils.directive_helper()`` is deprecated
@ -186,6 +190,7 @@ Features added
* #5140: linkcheck: Add better Accept header to HTTP client * #5140: linkcheck: Add better Accept header to HTTP client
* #4614: sphinx-build: Add ``--keep-going`` option to show all warnings * #4614: sphinx-build: Add ``--keep-going`` option to show all warnings
* Add :rst:role:`math:numref` role to refer equations (Same as :rst:role:`eq`) * Add :rst:role:`math:numref` role to refer equations (Same as :rst:role:`eq`)
* quickstart: epub builder is enabled by default
Bugs fixed Bugs fixed
---------- ----------
@ -200,6 +205,7 @@ Bugs fixed
* #5114: sphinx-build: Handle errors on scanning documents * #5114: sphinx-build: Handle errors on scanning documents
* epub: spine has been broken when "self" is listed on toctree (refs: #4611) * epub: spine has been broken when "self" is listed on toctree (refs: #4611)
* #344: autosummary does not understand docstring of module level attributes * #344: autosummary does not understand docstring of module level attributes
* #5191: C++, prevent nested declarations in functions to avoid lookup problems.
* #5002: graphviz: SVGs do not adapt to the column width * #5002: graphviz: SVGs do not adapt to the column width
Testing Testing

View File

@ -74,7 +74,6 @@ DEFAULTS = {
'language': None, 'language': None,
'suffix': '.rst', 'suffix': '.rst',
'master': 'index', 'master': 'index',
'epub': False,
'makefile': True, 'makefile': True,
'batchfile': True, 'batchfile': True,
} }
@ -246,7 +245,6 @@ def ask_user(d):
* language: document language * language: document language
* suffix: source file suffix * suffix: source file suffix
* master: master document name * master: master document name
* epub: use epub (bool)
* extensions: extensions to use (list) * extensions: extensions to use (list)
* makefile: make Makefile * makefile: make Makefile
* batchfile: make command file * batchfile: make command file
@ -347,12 +345,6 @@ document is a custom template, you can also set this to another filename.'''))
d['master'] = do_prompt(__('Please enter a new file name, or rename the ' d['master'] = do_prompt(__('Please enter a new file name, or rename the '
'existing file and press Enter'), d['master']) 'existing file and press Enter'), d['master'])
if 'epub' not in d:
print(__('''
Sphinx can also add configuration for epub output:'''))
d['epub'] = do_prompt(__('Do you want to use the epub builder (y/n)'),
'n', boolean)
if 'extensions' not in d: if 'extensions' not in d:
print(__('Indicate which of the following Sphinx extensions should be ' print(__('Indicate which of the following Sphinx extensions should be '
'enabled:')) 'enabled:'))

View File

@ -2085,7 +2085,7 @@ class ASTTrailingTypeSpecName(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> Any # type: () -> ASTNestedName
return self.nestedName return self.nestedName
def get_id(self, version): def get_id(self, version):
@ -2379,7 +2379,7 @@ class ASTDeclSpecs(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.trailingTypeSpec.name return self.trailingTypeSpec.name
def get_id(self, version): def get_id(self, version):
@ -2487,7 +2487,7 @@ class ASTDeclaratorPtr(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.next.name return self.next.name
@property @property
@ -2583,7 +2583,7 @@ class ASTDeclaratorRef(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.next.name return self.next.name
@property @property
@ -2638,7 +2638,7 @@ class ASTDeclaratorParamPack(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.next.name return self.next.name
@property @property
@ -2702,7 +2702,7 @@ class ASTDeclaratorMemPtr(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.next.name return self.next.name
@property @property
@ -2798,7 +2798,7 @@ class ASTDeclaratorParen(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.inner.name return self.inner.name
@property @property
@ -2864,7 +2864,7 @@ class ASTDeclaratorNameParamQual(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.declId return self.declId
@property @property
@ -2962,9 +2962,8 @@ class ASTType(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
name = self.decl.name return self.decl.name
return name
@property @property
def function_params(self): def function_params(self):
@ -3054,7 +3053,7 @@ class ASTTypeWithInit(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.type.name return self.type.name
def get_id(self, version, objectType=None, symbol=None): def get_id(self, version, objectType=None, symbol=None):
@ -3122,7 +3121,7 @@ class ASTConcept(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.nestedName return self.nestedName
def get_id(self, version, objectType=None, symbol=None): def get_id(self, version, objectType=None, symbol=None):
@ -3326,7 +3325,7 @@ class ASTDeclaration(ASTBase):
@property @property
def name(self): def name(self):
# type: () -> unicode # type: () -> ASTNestedName
return self.declaration.name return self.declaration.name
@property @property
@ -5791,12 +5790,37 @@ class CPPObject(ObjectDescription):
# type: (addnodes.desc_signature, Any, Dict) -> None # type: (addnodes.desc_signature, Any, Dict) -> None
ast.describe_signature(signode, 'lastIsName', self.env, options) ast.describe_signature(signode, 'lastIsName', self.env, options)
def run(self):
env = self.state.document.settings.env # from ObjectDescription.run
if 'cpp:parent_symbol' not in env.temp_data:
root = env.domaindata['cpp']['root_symbol']
env.temp_data['cpp:parent_symbol'] = root
env.ref_context['cpp:parent_key'] = root.get_lookup_key()
# The lookup keys assume that no nested scopes exists inside overloaded functions.
# (see also #5191)
# Example:
# .. cpp:function:: void f(int)
# .. cpp:function:: void f(double)
#
# .. cpp:function:: void g()
#
# :cpp:any:`boom`
#
# So we disallow any signatures inside functions.
parentSymbol = env.temp_data['cpp:parent_symbol']
parentDecl = parentSymbol.declaration
if parentDecl is not None and parentDecl.objectType == 'function':
self.warn("C++ declarations inside functions are not supported." +
" Parent function is " + text_type(parentSymbol.get_full_nested_name()))
name = _make_phony_error_name()
symbol = parentSymbol.add_name(name)
env.temp_data['cpp:last_symbol'] = symbol
return []
return ObjectDescription.run(self)
def handle_signature(self, sig, signode): def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> Any # type: (unicode, addnodes.desc_signature) -> Any
if 'cpp:parent_symbol' not in self.env.temp_data:
root = self.env.domaindata['cpp']['root_symbol']
self.env.temp_data['cpp:parent_symbol'] = root
self.env.ref_context['cpp:parent_key'] = root.get_lookup_key()
parentSymbol = self.env.temp_data['cpp:parent_symbol'] parentSymbol = self.env.temp_data['cpp:parent_symbol']
parser = DefinitionParser(sig, self, self.env.config) parser = DefinitionParser(sig, self, self.env.config)

View File

@ -156,7 +156,10 @@ class Graphviz(SphinxDirective):
line=self.lineno)] line=self.lineno)]
node = graphviz() node = graphviz()
node['code'] = dotcode node['code'] = dotcode
node['options'] = {} node['options'] = {
'docname': path.splitext(self.state.document.current_source)[0],
}
if 'graphviz_dot' in self.options: if 'graphviz_dot' in self.options:
node['options']['graphviz_dot'] = self.options['graphviz_dot'] node['options']['graphviz_dot'] = self.options['graphviz_dot']
if 'alt' in self.options: if 'alt' in self.options:
@ -193,7 +196,9 @@ class GraphvizSimple(SphinxDirective):
node = graphviz() node = graphviz()
node['code'] = '%s %s {\n%s\n}\n' % \ node['code'] = '%s %s {\n%s\n}\n' % \
(self.name, self.arguments[0], '\n'.join(self.content)) (self.name, self.arguments[0], '\n'.join(self.content))
node['options'] = {} node['options'] = {
'docname': path.splitext(self.state.document.current_source)[0],
}
if 'graphviz_dot' in self.options: if 'graphviz_dot' in self.options:
node['options']['graphviz_dot'] = self.options['graphviz_dot'] node['options']['graphviz_dot'] = self.options['graphviz_dot']
if 'alt' in self.options: if 'alt' in self.options:
@ -236,10 +241,14 @@ def render_dot(self, code, options, format, prefix='graphviz'):
dot_args = [graphviz_dot] dot_args = [graphviz_dot]
dot_args.extend(self.builder.config.graphviz_dot_args) dot_args.extend(self.builder.config.graphviz_dot_args)
dot_args.extend(['-T' + format, '-o' + outfn]) dot_args.extend(['-T' + format, '-o' + outfn])
docname = options.get('docname', 'index')
cwd = path.dirname(path.join(self.builder.srcdir, docname))
if format == 'png': if format == 'png':
dot_args.extend(['-Tcmapx', '-o%s.map' % outfn]) dot_args.extend(['-Tcmapx', '-o%s.map' % outfn])
try: try:
p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE) p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE, cwd=cwd)
except OSError as err: except OSError as err:
if err.errno != ENOENT: # No such file or directory if err.errno != ENOENT: # No such file or directory
raise raise

View File

@ -165,16 +165,12 @@ texinfo_documents = [
author, '{{ project_fn }}', 'One line description of project.', author, '{{ project_fn }}', 'One line description of project.',
'Miscellaneous'), 'Miscellaneous'),
] ]
{%- if epub %}
# -- Options for Epub output ------------------------------------------------- # -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info. # Bibliographic Dublin Core info.
epub_title = project epub_title = project
epub_author = author
epub_publisher = author
epub_copyright = copyright
# The unique identifier of the text. This can be a ISBN number # The unique identifier of the text. This can be a ISBN number
# or the project homepage. # or the project homepage.
@ -187,7 +183,6 @@ epub_copyright = copyright
# A list of files that should not be packed into the epub file. # A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html'] epub_exclude_files = ['search.html']
{%- endif %}
{%- if extensions %} {%- if extensions %}

View File

@ -19,7 +19,7 @@ from docutils.statemachine import ViewList
from six import PY3 from six import PY3
from sphinx.ext.autodoc import ( from sphinx.ext.autodoc import (
AutoDirective, ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL AutoDirective, ModuleLevelDocumenter, cut_lines, between, ALL
) )
from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options
from sphinx.testing.util import SphinxTestApp, Struct # NOQA from sphinx.testing.util import SphinxTestApp, Struct # NOQA
@ -28,6 +28,11 @@ from sphinx.util.docutils import LoggingReporter
app = None app = None
if PY3:
ROGER_METHOD = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)'
else:
ROGER_METHOD = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
def do_autodoc(app, objtype, name, options={}): def do_autodoc(app, objtype, name, options={}):
doccls = app.registry.documenters[objtype] doccls = app.registry.documenters[objtype]
@ -512,43 +517,6 @@ def test_docstring_processing():
app.disconnect(lid) app.disconnect(lid)
@pytest.mark.usefixtures('setup_test')
def test_docstring_property_processing():
def genarate_docstring(objtype, name, **kw):
del processed_docstrings[:]
del processed_signatures[:]
inst = app.registry.documenters[objtype](directive, name)
inst.generate(**kw)
results = list(directive.result)
docstrings = inst.get_doc()[0]
del directive.result[:]
return results, docstrings
directive.env.config.autodoc_docstring_signature = False
results, docstrings = \
genarate_docstring('attribute', 'target.DocstringSig.prop1')
assert '.. py:attribute:: DocstringSig.prop1' in results
assert 'First line of docstring' in docstrings
assert 'DocstringSig.prop1(self)' in docstrings
results, docstrings = \
genarate_docstring('attribute', 'target.DocstringSig.prop2')
assert '.. py:attribute:: DocstringSig.prop2' in results
assert 'First line of docstring' in docstrings
assert 'Second line of docstring' in docstrings
directive.env.config.autodoc_docstring_signature = True
results, docstrings = \
genarate_docstring('attribute', 'target.DocstringSig.prop1')
assert '.. py:attribute:: DocstringSig.prop1' in results
assert 'First line of docstring' in docstrings
assert 'DocstringSig.prop1(self)' not in docstrings
results, docstrings = \
genarate_docstring('attribute', 'target.DocstringSig.prop2')
assert '.. py:attribute:: DocstringSig.prop2' in results
assert 'First line of docstring' in docstrings
assert 'Second line of docstring' in docstrings
@pytest.mark.usefixtures('setup_test') @pytest.mark.usefixtures('setup_test')
def test_new_documenter(): def test_new_documenter():
logging.setup(app, app._status, app._warning) logging.setup(app, app._status, app._warning)
@ -617,73 +585,12 @@ def test_attrgetter_using():
@pytest.mark.usefixtures('setup_test') @pytest.mark.usefixtures('setup_test')
def test_generate(): def test_generate():
logging.setup(app, app._status, app._warning)
def assert_warns(warn_str, objtype, name, **kw):
inst = app.registry.documenters[objtype](directive, name)
inst.generate(**kw)
assert len(directive.result) == 0, directive.result
assert warn_str in app._warning.getvalue()
app._warning.truncate(0)
def assert_works(objtype, name, **kw):
inst = app.registry.documenters[objtype](directive, name)
inst.generate(**kw)
assert directive.result
# print '\n'.join(directive.result)
assert app._warning.getvalue() == ''
del directive.result[:]
def assert_processes(items, objtype, name, **kw):
del processed_docstrings[:]
del processed_signatures[:]
assert_works(objtype, name, **kw)
assert set(processed_docstrings) | set(processed_signatures) == set(items)
def assert_result_contains(item, objtype, name, **kw): def assert_result_contains(item, objtype, name, **kw):
inst = app.registry.documenters[objtype](directive, name) inst = app.registry.documenters[objtype](directive, name)
inst.generate(**kw) inst.generate(**kw)
# print '\n'.join(directive.result)
assert app._warning.getvalue() == ''
assert item in directive.result assert item in directive.result
del directive.result[:] del directive.result[:]
def assert_order(items, objtype, name, member_order, **kw):
inst = app.registry.documenters[objtype](directive, name)
inst.options.member_order = member_order
inst.generate(**kw)
assert app._warning.getvalue() == ''
items = list(reversed(items))
lineiter = iter(directive.result)
# for line in directive.result:
# if line.strip():
# print repr(line)
while items:
item = items.pop()
for line in lineiter:
if line == item:
break
else: # ran out of items!
assert False, ('item %r not found in result or not in the '
' correct order' % item)
del directive.result[:]
options.members = []
# no module found?
assert_warns("import for autodocumenting 'foobar'",
'function', 'foobar', more_content=None)
# importing
assert_warns("failed to import module 'test_foobar'",
'module', 'test_foobar', more_content=None)
# attributes missing
assert_warns("failed to import function 'foobar' from module 'util'",
'function', 'util.foobar', more_content=None)
# method missing
assert_warns("failed to import method 'Class.foobar' from module 'target';",
'method', 'target.Class.foobar', more_content=None)
# test auto and given content mixing # test auto and given content mixing
directive.env.ref_context['py:module'] = 'target' directive.env.ref_context['py:module'] = 'target'
assert_result_contains(' Function.', 'method', 'Class.meth') assert_result_contains(' Function.', 'method', 'Class.meth')
@ -694,80 +601,238 @@ def test_generate():
assert_result_contains(' Content.', 'method', assert_result_contains(' Content.', 'method',
'Class.meth', more_content=add_content) 'Class.meth', more_content=add_content)
# test check_module
inst = FunctionDocumenter(directive, 'add_documenter')
inst.generate(check_module=True)
assert len(directive.result) == 0
# assert that exceptions can be documented @pytest.mark.sphinx('html', testroot='ext-autodoc')
assert_works('exception', 'target.CustomEx', all_members=True) def test_autodoc_exception(app):
assert_works('exception', 'target.CustomEx') actual = do_autodoc(app, 'exception', 'target.CustomEx')
assert list(actual) == [
'',
'.. py:exception:: CustomEx',
' :module: target',
'',
' My custom exception.',
' '
]
# test diverse inclusion settings for members
should = [('class', 'target.Class')]
assert_processes(should, 'class', 'Class')
should.extend([('method', 'target.Class.meth')])
options.members = ['meth']
options.exclude_members = set(['excludemeth'])
assert_processes(should, 'class', 'Class')
should.extend([('attribute', 'target.Class.prop'),
('attribute', 'target.Class.descr'),
('attribute', 'target.Class.attr'),
('attribute', 'target.Class.docattr'),
('attribute', 'target.Class.udocattr'),
('attribute', 'target.Class.mdocattr'),
('attribute', 'target.Class.inst_attr_comment'),
('attribute', 'target.Class.inst_attr_inline'),
('attribute', 'target.Class.inst_attr_string'),
('method', 'target.Class.moore'),
])
options.members = ALL
assert_processes(should, 'class', 'Class')
options.undoc_members = True
should.extend((('attribute', 'target.Class.skipattr'),
('method', 'target.Class.undocmeth'),
('method', 'target.Class.roger')))
assert_processes(should, 'class', 'Class')
options.inherited_members = True
should.append(('method', 'target.Class.inheritedmeth'))
should.append(('method', 'target.Class.inheritedclassmeth'))
should.append(('method', 'target.Class.inheritedstaticmeth'))
assert_processes(should, 'class', 'Class')
# test special members @pytest.mark.sphinx('html', testroot='ext-autodoc')
options.special_members = ['__special1__'] def test_autodoc_warnings(app, warning):
should.append(('method', 'target.Class.__special1__')) app.env.temp_data['docname'] = 'dummy'
assert_processes(should, 'class', 'Class')
options.special_members = ALL
should.append(('method', 'target.Class.__special2__'))
assert_processes(should, 'class', 'Class')
options.special_members = False
options.members = [] # can't import module
# test module flags do_autodoc(app, 'module', 'unknown')
assert_result_contains('.. py:module:: target', assert "failed to import module 'unknown'" in warning.getvalue()
'module', 'target')
options.synopsis = 'Synopsis'
assert_result_contains(' :synopsis: Synopsis', 'module', 'target')
options.deprecated = True
assert_result_contains(' :deprecated:', 'module', 'target')
options.platform = 'Platform'
assert_result_contains(' :platform: Platform', 'module', 'target')
# test if __all__ is respected for modules
options.members = ALL
assert_result_contains('.. py:class:: Class(arg)', 'module', 'target')
try:
assert_result_contains('.. py:exception:: CustomEx',
'module', 'target')
except AssertionError:
pass
else:
assert False, 'documented CustomEx which is not in __all__'
# test ignore-module-all # missing function
options.ignore_module_all = True do_autodoc(app, 'function', 'unknown')
assert_result_contains('.. py:class:: Class(arg)', 'module', 'target') assert "import for autodocumenting 'unknown'" in warning.getvalue()
assert_result_contains('.. py:exception:: CustomEx', 'module', 'target')
do_autodoc(app, 'function', 'target.unknown')
assert "failed to import function 'unknown' from module 'target'" in warning.getvalue()
# missing method
do_autodoc(app, 'method', 'target.Class.unknown')
assert "failed to import method 'Class.unknown' from module 'target'" in warning.getvalue()
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_attributes(app):
options = {"synopsis": 'Synopsis',
"platform": "Platform",
"deprecated": None}
actual = do_autodoc(app, 'module', 'target', options)
assert list(actual) == [
'',
'.. py:module:: target',
' :synopsis: Synopsis',
' :platform: Platform',
' :deprecated:',
''
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_members(app):
# default (no-members)
actual = do_autodoc(app, 'class', 'target.Base')
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Base',
]
# default ALL-members
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.Base', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Base',
' .. py:classmethod:: Base.inheritedclassmeth()',
' .. py:method:: Base.inheritedmeth()',
' .. py:staticmethod:: Base.inheritedstaticmeth(cls)'
]
# default specific-members
options = {"members": "inheritedmeth,inheritedstaticmeth"}
actual = do_autodoc(app, 'class', 'target.Base', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Base',
' .. py:method:: Base.inheritedmeth()',
' .. py:staticmethod:: Base.inheritedstaticmeth(cls)'
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_exclude_members(app):
options = {"members": None,
"exclude-members": "inheritedmeth,inheritedstaticmeth"}
actual = do_autodoc(app, 'class', 'target.Base', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Base',
' .. py:classmethod:: Base.inheritedclassmeth()'
]
# members vs exclude-members
options = {"members": "inheritedmeth",
"exclude-members": "inheritedmeth"}
actual = do_autodoc(app, 'class', 'target.Base', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Base',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_undoc_members(app):
options = {"members": None,
"undoc-members": None}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class.mdocattr',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop',
ROGER_METHOD,
' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr',
' .. py:method:: Class.undocmeth()'
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_inherited_members(app):
options = {"members": None,
"inherited-members": None}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: 'method::' in l, actual)) == [
' .. py:method:: Class.excludemeth()',
' .. py:classmethod:: Class.inheritedclassmeth()',
' .. py:method:: Class.inheritedmeth()',
' .. py:staticmethod:: Class.inheritedstaticmeth(cls)',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:method:: Class.skipmeth()'
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_imported_members(app):
options = {"members": None,
"imported-members": None,
"ignore-module-all": None}
actual = do_autodoc(app, 'module', 'target', options)
assert '.. py:function:: add_documenter(cls)' in actual
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_special_members(app):
# all special methods
options = {"members": None,
"undoc-members": None,
"special-members": None}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:method:: Class.__init__(arg)',
' .. py:attribute:: Class.__module__',
' .. py:method:: Class.__special1__()',
' .. py:method:: Class.__special2__()',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class.mdocattr',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop',
ROGER_METHOD,
' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr',
' .. py:method:: Class.undocmeth()'
]
# specific special methods
options = {"members": None,
"undoc-members": None,
"special-members": "__init__,__special1__"}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:method:: Class.__init__(arg)',
' .. py:method:: Class.__special1__()',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class.mdocattr',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop',
ROGER_METHOD,
' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr',
' .. py:method:: Class.undocmeth()'
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_ignore_module_all(app):
# default (no-ignore-module-all)
options = {"members": None}
actual = do_autodoc(app, 'module', 'target', options)
assert list(filter(lambda l: 'class::' in l, actual)) == [
'.. py:class:: Class(arg)',
]
# ignore-module-all
options = {"members": None,
"ignore-module-all": None}
actual = do_autodoc(app, 'module', 'target', options)
assert list(filter(lambda l: 'class::' in l, actual)) == [
'.. py:class:: Class(arg)',
'.. py:class:: CustomDataDescriptor(doc)',
'.. py:class:: CustomDataDescriptor2(doc)',
'.. py:class:: CustomDataDescriptorMeta',
'.. py:class:: CustomDict',
'.. py:class:: EnumCls',
'.. py:class:: InstAttCls()',
'.. py:class:: Outer',
' .. py:class:: Outer.Inner',
'.. py:class:: StrRepr'
]
@pytest.mark.sphinx('html', testroot='ext-autodoc') @pytest.mark.sphinx('html', testroot='ext-autodoc')
@ -889,11 +954,6 @@ def test_autodoc_c_module(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc') @pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_member_order(app): def test_autodoc_member_order(app):
if PY3:
roger_method = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)'
else:
roger_method = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
# case member-order='bysource' # case member-order='bysource'
options = {"members": None, options = {"members": None,
'member-order': 'bysource', 'member-order': 'bysource',
@ -913,7 +973,7 @@ def test_autodoc_member_order(app):
' .. py:attribute:: Class.docattr', ' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.udocattr', ' .. py:attribute:: Class.udocattr',
' .. py:attribute:: Class.mdocattr', ' .. py:attribute:: Class.mdocattr',
roger_method, ROGER_METHOD,
' .. py:classmethod:: Class.moore(a, e, f) -> happiness', ' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.inst_attr_inline', ' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_comment', ' .. py:attribute:: Class.inst_attr_comment',
@ -932,7 +992,7 @@ def test_autodoc_member_order(app):
' .. py:method:: Class.excludemeth()', ' .. py:method:: Class.excludemeth()',
' .. py:method:: Class.meth()', ' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness', ' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
roger_method, ROGER_METHOD,
' .. py:method:: Class.skipmeth()', ' .. py:method:: Class.skipmeth()',
' .. py:method:: Class.undocmeth()', ' .. py:method:: Class.undocmeth()',
' .. py:attribute:: Class._private_inst_attr', ' .. py:attribute:: Class._private_inst_attr',
@ -967,7 +1027,7 @@ def test_autodoc_member_order(app):
' .. py:method:: Class.meth()', ' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness', ' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop', ' .. py:attribute:: Class.prop',
roger_method, ROGER_METHOD,
' .. py:attribute:: Class.skipattr', ' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()', ' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr', ' .. py:attribute:: Class.udocattr',

View File

@ -197,7 +197,6 @@ def test_quickstart_all_answers(tempdir):
assert ns['latex_documents'] == [ assert ns['latex_documents'] == [
('contents', 'STASI.tex', u'STASI™ Documentation', ('contents', 'STASI.tex', u'STASI™ Documentation',
u'Wolfgang Schäuble \\& G\'Beckstein', 'manual')] u'Wolfgang Schäuble \\& G\'Beckstein', 'manual')]
assert ns['epub_author'] == u'Wolfgang Schäuble & G\'Beckstein'
assert ns['man_pages'] == [ assert ns['man_pages'] == [
('contents', 'stasi', u'STASI™ Documentation', ('contents', 'stasi', u'STASI™ Documentation',
[u'Wolfgang Schäuble & G\'Beckstein'], 1)] [u'Wolfgang Schäuble & G\'Beckstein'], 1)]