sphinx-doc / sphinx

The Sphinx documentation generator
https://www.sphinx-doc.org/
Other
6.48k stars 2.11k forks source link

autodoc uses a wrapper's signature for a decorated class #8105

Closed harupy closed 3 years ago

harupy commented 4 years ago

Describe the bug

autodoc uses a wrapper's signature for a decorated class.

To Reproduce

Branch: https://github.com/harupy/sphinx/tree/decorated-class

Steps to reproduce the behavior:

In tests/roots/test-ext-autodoc/target/decorator.py, add:.


def deco(cls):
    _original_init = cls.__init__

    @wraps(_original_init)
    def wrapped(self, *args, **kwargs):
        _original_init(self, *args, **kwargs)

    cls.__init__ = wrapped
    return cls

@deco
class Bar2:
    def __init__(self, name=None, age=None):
        pass

In tests/test_ext_autodoc.py, add:

@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_decorated_class(app):
    print(do_autodoc(app, 'class', 'target.decorator.Bar2'))
    raise Exception  # fails this test to see stdout

Then, run:

tox -e py37 tests/test_ext_autodoc.py::test_decorated_class

This outputs:

--- Captured stdout call ---
['', '.. py:class:: Bar2(*args, **kwargs)', '   :module: target.decorator', '']

Expected behavior A clear and concise description of what you expected to happen.

--- Captured stdout call ---
['', '.. py:class:: Bar2(self, name=None, age=None)', '   :module: target.decorator', '']

Your project Link to your sphinx project, or attach zipped small project sample.

Screenshots If applicable, add screenshots to help explain your problem.

Environment info

Additional context Add any other context about the problem here.

harupy commented 4 years ago

ClassDocumenter doesn't seem to set follow_wrapped to True when extracting a signature.

https://github.com/sphinx-doc/sphinx/blob/38b868cc0d0583d9a58496cd121f0bc345bf9eaa/sphinx/ext/autodoc/__init__.py#L1401

harupy commented 4 years ago

The same thing occurs here:

https://github.com/sphinx-doc/sphinx/blob/38b868cc0d0583d9a58496cd121f0bc345bf9eaa/sphinx/ext/autodoc/type_comment.py#L120-L122

This causes type_sig and sig to have different parameters and throw KeyError here:

https://github.com/sphinx-doc/sphinx/blob/38b868cc0d0583d9a58496cd121f0bc345bf9eaa/sphinx/ext/autodoc/type_comment.py#L125

harupy commented 4 years ago

@tk0miya Correct me if I'm wrong. It looks like just specifying follow_wrapped=True solves the issue. If so, I'd be happy to open a PR (that makes the change and adds some tests to verify it).

tk0miya commented 4 years ago

@harupy You're right! Could you make a PR, please? Additionally, cases of __call__ and __new__ are also needed to add follow_wrapped=True, I think. Could you check them too if possible?

harupy commented 4 years ago

@tk0miya Created a PR: https://github.com/sphinx-doc/sphinx/pull/8115 😄

untitaker commented 4 years ago

This issue prevents me from upgrading from 3.0 to 3.2.1, the bugfix by @harupy works perfectly.

harupy commented 4 years ago

@tk0miya Could you review #8115?