From 5138255665f1c724bd0ac239add6cabd68f7a9d4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 22 Mar 2020 18:57:28 +0900 Subject: [PATCH 1/3] Fix a cyfunction was considered as an attribute descriptor --- sphinx/util/inspect.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index d22df7656..855b11d83 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -197,6 +197,14 @@ def isabstractmethod(obj: Any) -> bool: return safe_getattr(obj, '__isabstractmethod__', False) is True +def is_cython_function_or_method(obj: Any) -> bool: + """Check if the object is a function or method in cython.""" + try: + return obj.__class__.__name__ == 'cython_function_or_method' + except AttributeError: + return False + + def isattributedescriptor(obj: Any) -> bool: """Check if the object is an attribute like descriptor.""" if inspect.isdatadescriptor(object): @@ -207,6 +215,9 @@ def isattributedescriptor(obj: Any) -> bool: if isfunction(obj) or isbuiltin(obj) or inspect.ismethod(obj): # attribute must not be either function, builtin and method return False + elif is_cython_function_or_method(obj): + # attribute must not be either function and method (for cython) + return False elif inspect.isclass(obj): # attribute must not be a class return False From 5c396b6325349fe577f21bc7e1db8f96aaa4f5be Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 22 Mar 2020 18:58:26 +0900 Subject: [PATCH 2/3] Fix #7331: autodoc: a cython-function is not recognized as a function --- CHANGES | 1 + setup.py | 1 + sphinx/ext/autodoc/__init__.py | 3 ++- .../roots/test-ext-autodoc/target/cython.pyx | 4 +++ tests/test_autodoc.py | 26 +++++++++++++++++++ 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/roots/test-ext-autodoc/target/cython.pyx diff --git a/CHANGES b/CHANGES index c79f7c6fe..d4df88f30 100644 --- a/CHANGES +++ b/CHANGES @@ -132,6 +132,7 @@ Bugs fixed * #7267: autodoc: error message for invalid directive options has wrong location * #7329: autodoc: info-field-list is wrongly generated from type hints into the class description even if ``autoclass_content='class'`` set +* #7331: autodoc: a cython-function is not recognized as a function * #5637: inheritance_diagram: Incorrect handling of nested class names * #7139: ``code-block:: guess`` does not work * #7325: html: source_suffix containing dot leads to wrong source link diff --git a/setup.py b/setup.py index 088d5b8e7..a427d5493 100644 --- a/setup.py +++ b/setup.py @@ -52,6 +52,7 @@ extras_require = { 'pytest-cov', 'html5lib', 'typed_ast', # for py35-37 + 'cython', ], } diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index a81842c4a..becf2915e 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1011,7 +1011,8 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ if self.env.config.autodoc_typehints in ('none', 'description'): kwargs.setdefault('show_annotation', False) - if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object): + if ((inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object)) and + not inspect.is_cython_function_or_method(self.object)): # cannot introspect arguments of a C function or method return None try: diff --git a/tests/roots/test-ext-autodoc/target/cython.pyx b/tests/roots/test-ext-autodoc/target/cython.pyx new file mode 100644 index 000000000..a3714f4a6 --- /dev/null +++ b/tests/roots/test-ext-autodoc/target/cython.pyx @@ -0,0 +1,4 @@ +# cython: binding=True + +def foo(*args, **kwargs): + """Docstring.""" diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 012292999..26a157002 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -22,6 +22,13 @@ from sphinx.testing.util import SphinxTestApp, Struct # NOQA from sphinx.util import logging from sphinx.util.docutils import LoggingReporter +try: + # Enable pyximport to test cython module + import pyximport + pyximport.install() +except ImportError: + pyximport = None + app = None @@ -1609,3 +1616,22 @@ def test_singledispatchmethod(): ' A method for general use.', '', ] + + +@pytest.mark.usefixtures('setup_test') +@pytest.mark.skipif(pyximport is None, reason='cython is not installed') +def test_cython(): + options = {"members": None, + "undoc-members": None} + actual = do_autodoc(app, 'module', 'target.cython', options) + assert list(actual) == [ + '', + '.. py:module:: target.cython', + '', + '', + '.. py:function:: foo(*args, **kwargs)', + ' :module: target.cython', + '', + ' Docstring.', + '', + ] From dd70d9faac59c4367d3edc7a047c1951d54281a7 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 22 Mar 2020 19:06:22 +0900 Subject: [PATCH 3/3] Fix #7331: autodoc: a cython-method is not recognized as a method --- sphinx/ext/autodoc/__init__.py | 3 ++- tests/roots/test-ext-autodoc/target/cython.pyx | 8 ++++++++ tests/test_autodoc.py | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index becf2915e..7b6b3e4aa 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1431,7 +1431,8 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: if self.env.config.autodoc_typehints == 'none': kwargs.setdefault('show_annotation', False) - if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object): + if ((inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object)) and + not inspect.is_cython_function_or_method(self.object)): # can never get arguments of a C function or method return None if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name): diff --git a/tests/roots/test-ext-autodoc/target/cython.pyx b/tests/roots/test-ext-autodoc/target/cython.pyx index a3714f4a6..1457db3c9 100644 --- a/tests/roots/test-ext-autodoc/target/cython.pyx +++ b/tests/roots/test-ext-autodoc/target/cython.pyx @@ -2,3 +2,11 @@ def foo(*args, **kwargs): """Docstring.""" + + +class Class: + """Docstring.""" + + def meth(self, name: str, age: int = 0) -> None: + """Docstring.""" + pass diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 26a157002..741c4bb60 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -1629,6 +1629,18 @@ def test_cython(): '.. py:module:: target.cython', '', '', + '.. py:class:: Class', + ' :module: target.cython', + '', + ' Docstring.', + '', + '', + ' .. py:method:: Class.meth(name: str, age: int = 0) -> None', + ' :module: target.cython', + '', + ' Docstring.', + '', + '', '.. py:function:: foo(*args, **kwargs)', ' :module: target.cython', '',