From a7daee7fb60f36f6d04f0fdf03ca6ec4ee740545 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 9 Aug 2023 08:32:06 +0300 Subject: [PATCH 1/4] gh-84805: Autogenerate signature for METH_NOARGS and METH_O extension functions --- Include/internal/pycore_object.h | 2 +- Lib/test/test_inspect.py | 61 +++++++++++++++++++ Lib/test/test_pydoc.py | 50 +++++++++++++++ ...3-08-09-08-31-20.gh-issue-84805.7JRWua.rst | 2 + Modules/_testcapi/docstring.c | 43 ++++++++++--- Objects/descrobject.c | 10 ++- Objects/methodobject.c | 4 +- Objects/typeobject.c | 29 ++++++++- 8 files changed, 185 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-08-09-08-31-20.gh-issue-84805.7JRWua.rst diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 7cdf64bcdacb9f8..857d6efec3b3b1f 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -381,7 +381,7 @@ extern PyObject *_PyType_NewManagedObject(PyTypeObject *type); extern PyTypeObject* _PyType_CalculateMetaclass(PyTypeObject *, PyObject *); extern PyObject* _PyType_GetDocFromInternalDoc(const char *, const char *); -extern PyObject* _PyType_GetTextSignatureFromInternalDoc(const char *, const char *); +extern PyObject* _PyType_GetTextSignatureFromInternalDoc(const char *, const char *, int); extern int _PyObject_InitializeDict(PyObject *obj); int _PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp); diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 5c31748ce2caacd..1e8bdab6ba60d26 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -13,7 +13,9 @@ import _pickle import pickle import shutil +import stat import sys +import time import types import tempfile import textwrap @@ -22,6 +24,7 @@ import unittest.mock import warnings + try: from concurrent.futures import ThreadPoolExecutor except ImportError: @@ -136,6 +139,14 @@ def gen_coroutine_function_example(self): yield return 'spam' +def meth_noargs(): pass +def meth_o(object, /): pass +def meth_self_noargs(self, /): pass +def meth_self_o(self, object, /): pass +def meth_type_noargs(type, /): pass +def meth_type_o(type, object, /): pass + + class TestPredicates(IsTestBase): def test_excluding_predicates(self): @@ -1173,6 +1184,31 @@ def test_getfullargspec_builtin_func_no_signature(self): with self.assertRaises(TypeError): inspect.getfullargspec(builtin) + self.assertEqual(inspect.getfullargspec(time.time), + inspect.getfullargspec(meth_noargs)) + self.assertEqual(inspect.getfullargspec(stat.S_IMODE), + inspect.getfullargspec(meth_o)) + self.assertEqual(inspect.getfullargspec(str.lower), + inspect.getfullargspec(meth_self_noargs)) + self.assertEqual(inspect.getfullargspec(''.lower), + inspect.getfullargspec(meth_self_noargs)) + self.assertEqual(inspect.getfullargspec(set.add), + inspect.getfullargspec(meth_self_o)) + self.assertEqual(inspect.getfullargspec(set().add), + inspect.getfullargspec(meth_self_o)) + self.assertEqual(inspect.getfullargspec(set.__contains__), + inspect.getfullargspec(meth_self_o)) + self.assertEqual(inspect.getfullargspec(set().__contains__), + inspect.getfullargspec(meth_self_o)) + self.assertEqual(inspect.getfullargspec(datetime.datetime.__dict__['utcnow']), + inspect.getfullargspec(meth_type_noargs)) + self.assertEqual(inspect.getfullargspec(datetime.datetime.utcnow), + inspect.getfullargspec(meth_type_noargs)) + self.assertEqual(inspect.getfullargspec(dict.__dict__['__class_getitem__']), + inspect.getfullargspec(meth_type_o)) + self.assertEqual(inspect.getfullargspec(dict.__class_getitem__), + inspect.getfullargspec(meth_type_o)) + def test_getfullargspec_definition_order_preserved_on_kwonly(self): for fn in signatures_with_lexicographic_keyword_only_parameters(): signature = inspect.getfullargspec(fn) @@ -2888,6 +2924,31 @@ def test_signature_on_builtins_no_signature(self): 'no signature found for builtin'): inspect.signature(str) + self.assertEqual(inspect.signature(time.time), + inspect.signature(meth_noargs)) + self.assertEqual(inspect.signature(stat.S_IMODE), + inspect.signature(meth_o)) + self.assertEqual(inspect.signature(str.lower), + inspect.signature(meth_self_noargs)) + self.assertEqual(inspect.signature(''.lower), + inspect.signature(meth_noargs)) + self.assertEqual(inspect.signature(set.add), + inspect.signature(meth_self_o)) + self.assertEqual(inspect.signature(set().add), + inspect.signature(meth_o)) + self.assertEqual(inspect.signature(set.__contains__), + inspect.signature(meth_self_o)) + self.assertEqual(inspect.signature(set().__contains__), + inspect.signature(meth_o)) + self.assertEqual(inspect.signature(datetime.datetime.__dict__['utcnow']), + inspect.signature(meth_type_noargs)) + self.assertEqual(inspect.signature(datetime.datetime.utcnow), + inspect.signature(meth_noargs)) + self.assertEqual(inspect.signature(dict.__dict__['__class_getitem__']), + inspect.signature(meth_type_o)) + self.assertEqual(inspect.signature(dict.__class_getitem__), + inspect.signature(meth_o)) + def test_signature_on_non_function(self): with self.assertRaisesRegex(TypeError, 'is not a callable object'): inspect.signature(42) diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index ddb5187f90da9bc..8df8b608cf959d2 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -1,3 +1,4 @@ +import datetime import os import sys import contextlib @@ -12,6 +13,7 @@ import stat import tempfile import test.support +import time import types import typing import unittest @@ -1180,6 +1182,54 @@ def test_module_level_callable(self): self.assertEqual(self._get_summary_line(os.stat), "stat(path, *, dir_fd=None, follow_symlinks=True)") + def test_module_level_callable_noargs(self): + self.assertEqual(self._get_summary_line(time.time), + "time()") + + def test_module_level_callable_o(self): + self.assertEqual(self._get_summary_line(stat.S_IMODE), + "S_IMODE(object, /)") + + def test_unbound_builtin_method_noargs(self): + self.assertEqual(self._get_summary_line(str.lower), + "lower(self, /)") + + def test_bound_builtin_method_noargs(self): + self.assertEqual(self._get_summary_line(''.lower), + "lower() method of builtins.str instance") + + def test_unbound_builtin_method_o(self): + self.assertEqual(self._get_summary_line(set.add), + "add(self, object, /)") + + def test_bound_builtin_method_o(self): + self.assertEqual(self._get_summary_line(set().add), + "add(object, /) method of builtins.set instance") + + def test_unbound_builtin_method_coexist_o(self): + self.assertEqual(self._get_summary_line(set.__contains__), + "__contains__(self, object, /)") + + def test_bound_builtin_method_coexist_o(self): + self.assertEqual(self._get_summary_line(set().__contains__), + "__contains__(object, /) method of builtins.set instance") + + def test_unbound_builtin_classmethod_noargs(self): + self.assertEqual(self._get_summary_line(datetime.datetime.__dict__['utcnow']), + "utcnow(type, /)") + + def test_bound_builtin_classmethod_noargs(self): + self.assertEqual(self._get_summary_line(datetime.datetime.utcnow), + "utcnow() method of builtins.type instance") + + def test_unbound_builtin_classmethod_o(self): + self.assertEqual(self._get_summary_line(dict.__dict__['__class_getitem__']), + "__class_getitem__(type, object, /)") + + def test_bound_builtin_classmethod_o(self): + self.assertEqual(self._get_summary_line(dict.__class_getitem__), + "__class_getitem__(object, /) method of builtins.type instance") + @requires_docstrings def test_staticmethod(self): class X: diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-09-08-31-20.gh-issue-84805.7JRWua.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-09-08-31-20.gh-issue-84805.7JRWua.rst new file mode 100644 index 000000000000000..23dfba989fa5525 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-08-09-08-31-20.gh-issue-84805.7JRWua.rst @@ -0,0 +1,2 @@ +Autogenerate signature for :c:macro:`METH_NOARGS` and :c:macro:`METH_O` +extension functions. diff --git a/Modules/_testcapi/docstring.c b/Modules/_testcapi/docstring.c index a997c54a8a69c4d..a0d21db91cf3fc8 100644 --- a/Modules/_testcapi/docstring.c +++ b/Modules/_testcapi/docstring.c @@ -66,33 +66,58 @@ test_with_docstring(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyMethodDef test_methods[] = { {"docstring_empty", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_empty}, {"docstring_no_signature", + (PyCFunction)test_with_docstring, METH_VARARGS, + docstring_no_signature}, + {"docstring_no_signature_noargs", (PyCFunction)test_with_docstring, METH_NOARGS, docstring_no_signature}, + {"docstring_no_signature_o", + (PyCFunction)test_with_docstring, METH_O, + docstring_no_signature}, +// {"docstring_no_signature_noargs_class", +// (PyCFunction)test_with_docstring, METH_NOARGS|METH_CLASS, +// docstring_no_signature}, +// {"docstring_no_signature_o_class", +// (PyCFunction)test_with_docstring, METH_O|METH_CLASS, +// docstring_no_signature}, +// {"docstring_no_signature_noargs_static", +// (PyCFunction)test_with_docstring, METH_NOARGS|METH_STATIC, +// docstring_no_signature}, +// {"docstring_no_signature_o_static", +// (PyCFunction)test_with_docstring, METH_O|METH_STATIC, +// docstring_no_signature}, +// {"docstring_no_signature_noargs_coexist", +// (PyCFunction)test_with_docstring, METH_NOARGS|METH_COEXIST, +// docstring_no_signature}, +// {"docstring_no_signature_o_coexist", +// (PyCFunction)test_with_docstring, METH_O|METH_COEXIST, +// docstring_no_signature}, + {"docstring_with_invalid_signature", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_invalid_signature}, {"docstring_with_invalid_signature2", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_invalid_signature2}, {"docstring_with_signature", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_signature}, {"docstring_with_signature_and_extra_newlines", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_signature_and_extra_newlines}, {"docstring_with_signature_but_no_doc", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_signature_but_no_doc}, {"docstring_with_signature_with_defaults", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_signature_with_defaults}, {"no_docstring", - (PyCFunction)test_with_docstring, METH_NOARGS}, + (PyCFunction)test_with_docstring, METH_VARARGS}, {"test_with_docstring", - test_with_docstring, METH_NOARGS, + test_with_docstring, METH_VARARGS, PyDoc_STR("This is a pretty normal docstring.")}, {NULL}, }; diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 60383dd06d1add8..a744c3d1e586589 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -588,7 +588,9 @@ method_get_doc(PyMethodDescrObject *descr, void *closure) static PyObject * method_get_text_signature(PyMethodDescrObject *descr, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc); + return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, + descr->d_method->ml_doc, + descr->d_method->ml_flags); } static PyObject * @@ -691,7 +693,8 @@ wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure) static PyObject * wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc); + return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, + descr->d_base->doc, 0); } static PyGetSetDef wrapperdescr_getset[] = { @@ -1384,7 +1387,8 @@ wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored)) static PyObject * wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored)) { - return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc); + return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, + wp->descr->d_base->doc, 0); } static PyObject * diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 628d227ef33c394..521c9059770acb9 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -192,7 +192,9 @@ static PyMethodDef meth_methods[] = { static PyObject * meth_get__text_signature__(PyCFunctionObject *m, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc); + return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, + m->m_ml->ml_doc, + m->m_ml->ml_flags); } static PyObject * diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 76809494dd88174..ef933564ee7ebe6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -586,8 +586,29 @@ _PyType_GetDocFromInternalDoc(const char *name, const char *internal_doc) return PyUnicode_FromString(doc); } +static const char * +signature_from_flags(int flags) +{ + switch (flags & ~METH_COEXIST) { + case METH_NOARGS: + return "($self, /)"; + case METH_NOARGS|METH_CLASS: + return "($type, /)"; + case METH_NOARGS|METH_STATIC: + return "()"; + case METH_O: + return "($self, object, /)"; + case METH_O|METH_CLASS: + return "($type, object, /)"; + case METH_O|METH_STATIC: + return "(object, /)"; + default: + return NULL; + } +} + PyObject * -_PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_doc) +_PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_doc, int flags) { const char *start = find_signature(name, internal_doc); const char *end; @@ -597,6 +618,10 @@ _PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_d else end = NULL; if (!end) { + start = signature_from_flags(flags); + if (start) { + return PyUnicode_FromString(start); + } Py_RETURN_NONE; } @@ -1429,7 +1454,7 @@ type_get_doc(PyTypeObject *type, void *context) static PyObject * type_get_text_signature(PyTypeObject *type, void *context) { - return _PyType_GetTextSignatureFromInternalDoc(type->tp_name, type->tp_doc); + return _PyType_GetTextSignatureFromInternalDoc(type->tp_name, type->tp_doc, 0); } static int From d6b7022cc8e79369c3625c9e5bbc5e5e5f2388e6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 9 Aug 2023 10:18:52 +0300 Subject: [PATCH 2/4] Fix test_rlcompleter. --- Lib/test/test_rlcompleter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_rlcompleter.py b/Lib/test/test_rlcompleter.py index 6b5fc9a0247f4b5..7347fca71be2fe5 100644 --- a/Lib/test/test_rlcompleter.py +++ b/Lib/test/test_rlcompleter.py @@ -53,7 +53,10 @@ def test_attr_matches(self): ['str.{}('.format(x) for x in dir(str) if x.startswith('s')]) self.assertEqual(self.stdcompleter.attr_matches('tuple.foospamegg'), []) - expected = sorted({'None.%s%s' % (x, '(' if x != '__doc__' else '') + expected = sorted({'None.%s%s' % (x, + '()' if x == '__init_subclass__' + else '' if x == '__doc__' + else '(') for x in dir(None)}) self.assertEqual(self.stdcompleter.attr_matches('None.'), expected) self.assertEqual(self.stdcompleter.attr_matches('None._'), expected) From 4183cb598d0f709029fb2e59bfd1d218f46823c3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 11 Aug 2023 14:21:35 +0300 Subject: [PATCH 3/4] Add more tests. --- Lib/test/test_inspect.py | 112 +++++++++++++++++++--------------- Modules/_testcapi/docstring.c | 59 ++++++++++++------ 2 files changed, 104 insertions(+), 67 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 1e8bdab6ba60d26..07c48eac5b48b03 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1184,30 +1184,38 @@ def test_getfullargspec_builtin_func_no_signature(self): with self.assertRaises(TypeError): inspect.getfullargspec(builtin) - self.assertEqual(inspect.getfullargspec(time.time), - inspect.getfullargspec(meth_noargs)) - self.assertEqual(inspect.getfullargspec(stat.S_IMODE), - inspect.getfullargspec(meth_o)) - self.assertEqual(inspect.getfullargspec(str.lower), - inspect.getfullargspec(meth_self_noargs)) - self.assertEqual(inspect.getfullargspec(''.lower), - inspect.getfullargspec(meth_self_noargs)) - self.assertEqual(inspect.getfullargspec(set.add), - inspect.getfullargspec(meth_self_o)) - self.assertEqual(inspect.getfullargspec(set().add), - inspect.getfullargspec(meth_self_o)) - self.assertEqual(inspect.getfullargspec(set.__contains__), - inspect.getfullargspec(meth_self_o)) - self.assertEqual(inspect.getfullargspec(set().__contains__), - inspect.getfullargspec(meth_self_o)) - self.assertEqual(inspect.getfullargspec(datetime.datetime.__dict__['utcnow']), - inspect.getfullargspec(meth_type_noargs)) - self.assertEqual(inspect.getfullargspec(datetime.datetime.utcnow), - inspect.getfullargspec(meth_type_noargs)) - self.assertEqual(inspect.getfullargspec(dict.__dict__['__class_getitem__']), - inspect.getfullargspec(meth_type_o)) - self.assertEqual(inspect.getfullargspec(dict.__class_getitem__), - inspect.getfullargspec(meth_type_o)) + cls = _testcapi.DocStringNoSignatureTest + obj = _testcapi.DocStringNoSignatureTest() + for builtin, template in [ + (_testcapi.docstring_no_signature_noargs, meth_noargs), + (_testcapi.docstring_no_signature_o, meth_o), + (cls.meth_noargs, meth_self_noargs), + (cls.meth_o, meth_self_o), + (obj.meth_noargs, meth_self_noargs), + (obj.meth_o, meth_self_o), + (cls.meth_noargs_class, meth_type_noargs), + (cls.meth_o_class, meth_type_o), + (cls.meth_noargs_static, meth_noargs), + (cls.meth_o_static, meth_o), + (cls.meth_noargs_coexist, meth_self_noargs), + (cls.meth_o_coexist, meth_self_o), + + (time.time, meth_noargs), + (stat.S_IMODE, meth_o), + (str.lower, meth_self_noargs), + (''.lower, meth_self_noargs), + (set.add, meth_self_o), + (set().add, meth_self_o), + (set.__contains__, meth_self_o), + (set().__contains__, meth_self_o), + (datetime.datetime.__dict__['utcnow'], meth_type_noargs), + (datetime.datetime.utcnow, meth_type_noargs), + (dict.__dict__['__class_getitem__'], meth_type_o), + (dict.__class_getitem__, meth_type_o), + ]: + with self.subTest(builtin): + self.assertEqual(inspect.getfullargspec(builtin), + inspect.getfullargspec(template)) def test_getfullargspec_definition_order_preserved_on_kwonly(self): for fn in signatures_with_lexicographic_keyword_only_parameters(): @@ -2924,30 +2932,38 @@ def test_signature_on_builtins_no_signature(self): 'no signature found for builtin'): inspect.signature(str) - self.assertEqual(inspect.signature(time.time), - inspect.signature(meth_noargs)) - self.assertEqual(inspect.signature(stat.S_IMODE), - inspect.signature(meth_o)) - self.assertEqual(inspect.signature(str.lower), - inspect.signature(meth_self_noargs)) - self.assertEqual(inspect.signature(''.lower), - inspect.signature(meth_noargs)) - self.assertEqual(inspect.signature(set.add), - inspect.signature(meth_self_o)) - self.assertEqual(inspect.signature(set().add), - inspect.signature(meth_o)) - self.assertEqual(inspect.signature(set.__contains__), - inspect.signature(meth_self_o)) - self.assertEqual(inspect.signature(set().__contains__), - inspect.signature(meth_o)) - self.assertEqual(inspect.signature(datetime.datetime.__dict__['utcnow']), - inspect.signature(meth_type_noargs)) - self.assertEqual(inspect.signature(datetime.datetime.utcnow), - inspect.signature(meth_noargs)) - self.assertEqual(inspect.signature(dict.__dict__['__class_getitem__']), - inspect.signature(meth_type_o)) - self.assertEqual(inspect.signature(dict.__class_getitem__), - inspect.signature(meth_o)) + cls = _testcapi.DocStringNoSignatureTest + obj = _testcapi.DocStringNoSignatureTest() + for builtin, template in [ + (_testcapi.docstring_no_signature_noargs, meth_noargs), + (_testcapi.docstring_no_signature_o, meth_o), + (cls.meth_noargs, meth_self_noargs), + (cls.meth_o, meth_self_o), + (obj.meth_noargs, meth_noargs), + (obj.meth_o, meth_o), + (cls.meth_noargs_class, meth_noargs), + (cls.meth_o_class, meth_o), + (cls.meth_noargs_static, meth_noargs), + (cls.meth_o_static, meth_o), + (cls.meth_noargs_coexist, meth_self_noargs), + (cls.meth_o_coexist, meth_self_o), + + (time.time, meth_noargs), + (stat.S_IMODE, meth_o), + (str.lower, meth_self_noargs), + (''.lower, meth_noargs), + (set.add, meth_self_o), + (set().add, meth_o), + (set.__contains__, meth_self_o), + (set().__contains__, meth_o), + (datetime.datetime.__dict__['utcnow'], meth_type_noargs), + (datetime.datetime.utcnow, meth_noargs), + (dict.__dict__['__class_getitem__'], meth_type_o), + (dict.__class_getitem__, meth_o), + ]: + with self.subTest(builtin): + self.assertEqual(inspect.signature(builtin), + inspect.signature(template)) def test_signature_on_non_function(self): with self.assertRaisesRegex(TypeError, 'is not a callable object'): diff --git a/Modules/_testcapi/docstring.c b/Modules/_testcapi/docstring.c index a0d21db91cf3fc8..b680171cc1437a5 100644 --- a/Modules/_testcapi/docstring.c +++ b/Modules/_testcapi/docstring.c @@ -77,25 +77,6 @@ static PyMethodDef test_methods[] = { {"docstring_no_signature_o", (PyCFunction)test_with_docstring, METH_O, docstring_no_signature}, -// {"docstring_no_signature_noargs_class", -// (PyCFunction)test_with_docstring, METH_NOARGS|METH_CLASS, -// docstring_no_signature}, -// {"docstring_no_signature_o_class", -// (PyCFunction)test_with_docstring, METH_O|METH_CLASS, -// docstring_no_signature}, -// {"docstring_no_signature_noargs_static", -// (PyCFunction)test_with_docstring, METH_NOARGS|METH_STATIC, -// docstring_no_signature}, -// {"docstring_no_signature_o_static", -// (PyCFunction)test_with_docstring, METH_O|METH_STATIC, -// docstring_no_signature}, -// {"docstring_no_signature_noargs_coexist", -// (PyCFunction)test_with_docstring, METH_NOARGS|METH_COEXIST, -// docstring_no_signature}, -// {"docstring_no_signature_o_coexist", -// (PyCFunction)test_with_docstring, METH_O|METH_COEXIST, -// docstring_no_signature}, - {"docstring_with_invalid_signature", (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_invalid_signature}, @@ -122,11 +103,51 @@ static PyMethodDef test_methods[] = { {NULL}, }; +static PyMethodDef DocStringNoSignatureTest_methods[] = { + {"meth_noargs", + (PyCFunction)test_with_docstring, METH_NOARGS, + docstring_no_signature}, + {"meth_o", + (PyCFunction)test_with_docstring, METH_O, + docstring_no_signature}, + {"meth_noargs_class", + (PyCFunction)test_with_docstring, METH_NOARGS|METH_CLASS, + docstring_no_signature}, + {"meth_o_class", + (PyCFunction)test_with_docstring, METH_O|METH_CLASS, + docstring_no_signature}, + {"meth_noargs_static", + (PyCFunction)test_with_docstring, METH_NOARGS|METH_STATIC, + docstring_no_signature}, + {"meth_o_static", + (PyCFunction)test_with_docstring, METH_O|METH_STATIC, + docstring_no_signature}, + {"meth_noargs_coexist", + (PyCFunction)test_with_docstring, METH_NOARGS|METH_COEXIST, + docstring_no_signature}, + {"meth_o_coexist", + (PyCFunction)test_with_docstring, METH_O|METH_COEXIST, + docstring_no_signature}, + {NULL}, +}; + +static PyTypeObject DocStringNoSignatureTest = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testcapi.DocStringNoSignatureTest", + .tp_basicsize = sizeof(PyObject), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_methods = DocStringNoSignatureTest_methods, + .tp_new = PyType_GenericNew, +}; + int _PyTestCapi_Init_Docstring(PyObject *mod) { if (PyModule_AddFunctions(mod, test_methods) < 0) { return -1; } + if (PyModule_AddType(mod, &DocStringNoSignatureTest) < 0) { + return -1; + } return 0; } From 4b3e6ed13af964b3e9ff932c6b81137cf062f4ab Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 11 Aug 2023 14:51:37 +0300 Subject: [PATCH 4/4] Update Tools/c-analyzer/cpython/ignored.tsv. --- Tools/c-analyzer/cpython/ignored.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 66815c72ffbc636..c64d391bae13bd8 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -419,6 +419,7 @@ Modules/_testbuffer.c staticarray_init kwlist - Modules/_testcapi/buffer.c - testBufType - Modules/_testcapi/code.c get_code_extra_index key - Modules/_testcapi/datetime.c - test_run_counter - +Modules/_testcapi/docstring.c - DocStringNoSignatureTest - Modules/_testcapi/exceptions.c - PyRecursingInfinitelyError_Type - Modules/_testcapi/heaptype.c - _testcapimodule - Modules/_testcapi/mem.c - FmData -