Feature: enhance autoclass:: to use the docstring of __new__

The method new is an alternative to __init__, but autoclass does not 
respect __new__. This commit enhances the directive autoclass:: to try
__new__ method's docstring, if __init__ method's docstring is missing or
empty.

The commit also adds tests and updates the documentation.
This commit is contained in:
Anselm Kruis 2016-02-05 19:09:43 +01:00
parent 50951bdc98
commit 0311f33347
3 changed files with 48 additions and 0 deletions

View File

@ -314,6 +314,12 @@ There are also new config values that you can set:
.. versionadded:: 0.3 .. versionadded:: 0.3
If the class has no ``__init__`` method or if the ``__init__`` method's
docstring is empty, but the class has a ``__new__`` method's docstring,
it is used instead.
.. versionadded:: 1.4
.. confval:: autodoc_member_order .. confval:: autodoc_member_order
This value selects if automatically documented members are sorted This value selects if automatically documented members are sorted

View File

@ -1163,6 +1163,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
(initdocstring == object.__init__.__doc__ or # for pypy (initdocstring == object.__init__.__doc__ or # for pypy
initdocstring.strip() == object.__init__.__doc__)): # for !pypy initdocstring.strip() == object.__init__.__doc__)): # for !pypy
initdocstring = None initdocstring = None
if not initdocstring:
# try __new__
initdocstring = self.get_attr(
self.get_attr(self.object, '__new__', None), '__doc__')
# for new-style classes, no __new__ means default __new__
if (initdocstring is not None and
(initdocstring == object.__new__.__doc__ or # for pypy
initdocstring.strip() == object.__new__.__doc__)): # for !pypy
initdocstring = None
if initdocstring: if initdocstring:
if content == 'init': if content == 'init':
docstrings = [initdocstring] docstrings = [initdocstring]

View File

@ -297,6 +297,9 @@ def test_get_doc():
"""Class docstring""" """Class docstring"""
def __init__(self): def __init__(self):
"""Init docstring""" """Init docstring"""
def __new__(cls):
"""New docstring"""
directive.env.config.autoclass_content = 'class' directive.env.config.autoclass_content = 'class'
assert getdocl('class', C) == ['Class docstring'] assert getdocl('class', C) == ['Class docstring']
directive.env.config.autoclass_content = 'init' directive.env.config.autoclass_content = 'init'
@ -380,6 +383,36 @@ def test_get_doc():
directive.env.config.autoclass_content = 'both' directive.env.config.autoclass_content = 'both'
assert getdocl('class', G) == ['Class docstring'] assert getdocl('class', G) == ['Class docstring']
# class has __new__ method with docstring
# class docstring: depends on config value which one is taken
class H:
"""Class docstring"""
def __init__(self):
pass
def __new__(cls):
"""New docstring"""
directive.env.config.autoclass_content = 'class'
assert getdocl('class', H) == ['Class docstring']
directive.env.config.autoclass_content = 'init'
assert getdocl('class', H) == ['New docstring']
directive.env.config.autoclass_content = 'both'
assert getdocl('class', H) == ['Class docstring', '', 'New docstring']
# class has __init__ method without docstring and
# __new__ method with docstring
# class docstring: depends on config value which one is taken
class I:
"""Class docstring"""
def __new__(cls):
"""New docstring"""
directive.env.config.autoclass_content = 'class'
assert getdocl('class', I) == ['Class docstring']
directive.env.config.autoclass_content = 'init'
assert getdocl('class', I) == ['New docstring']
directive.env.config.autoclass_content = 'both'
assert getdocl('class', I) == ['Class docstring', '', 'New docstring']
@with_setup(setup_test) @with_setup(setup_test)
def test_docstring_processing(): def test_docstring_processing():