From 5fe56f05f723caa8d16fd6dd8f786947b8faff49 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 12 Sep 2023 16:11:25 +0300 Subject: [PATCH 1/3] gh-107782: Use _testcapi to test non-representable signatures Builtin functions and methods that have non-representable signatures today will have representable signatures yesterday, and they will become unusable for testing this feature. So we need to add special functions and methods to the _testcapi module that always have non-representable signatures. --- Lib/test/test_pydoc.py | 39 +++++++++++++++++++++++++++++-- Modules/_testcapi/docstring.c | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 499eeb98ad6138..70c5ebd694ca88 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -24,6 +24,7 @@ from io import StringIO from collections import namedtuple from urllib.request import urlopen, urlcleanup +from test import support from test.support import import_helper from test.support import os_helper from test.support.script_helper import (assert_python_ok, @@ -1236,22 +1237,56 @@ def test_bound_builtin_classmethod_o(self): self.assertEqual(self._get_summary_line(dict.__class_getitem__), "__class_getitem__(object, /) method of builtins.type instance") + @support.cpython_only def test_module_level_callable_unrepresentable_default(self): - self.assertEqual(self._get_summary_line(getattr), - "getattr(...)") + import _testcapi + builtin = _testcapi.func_with_unrepresentable_signature + self.assertEqual(self._get_summary_line(builtin), + "func_with_unrepresentable_signature(a, b=)") + @support.cpython_only def test_builtin_staticmethod_unrepresentable_default(self): self.assertEqual(self._get_summary_line(str.maketrans), "maketrans(x, y=, z=, /)") + import _testcapi + cls = _testcapi.DocStringUnrepresentableSignatureTest + self.assertEqual(self._get_summary_line(cls.staticmeth), + "staticmeth(a, b=)") + @support.cpython_only def test_unbound_builtin_method_unrepresentable_default(self): self.assertEqual(self._get_summary_line(dict.pop), "pop(self, key, default=, /)") + import _testcapi + cls = _testcapi.DocStringUnrepresentableSignatureTest + self.assertEqual(self._get_summary_line(cls.meth), + "meth(self, /, a, b=)") + @support.cpython_only def test_bound_builtin_method_unrepresentable_default(self): self.assertEqual(self._get_summary_line({}.pop), "pop(key, default=, /) " "method of builtins.dict instance") + import _testcapi + obj = _testcapi.DocStringUnrepresentableSignatureTest() + self.assertEqual(self._get_summary_line(obj.meth), + "meth(a, b=) " + "method of _testcapi.DocStringUnrepresentableSignatureTest instance") + + @support.cpython_only + def test_unbound_builtin_classmethod_unrepresentable_default(self): + import _testcapi + cls = _testcapi.DocStringUnrepresentableSignatureTest + descr = cls.__dict__['classmeth'] + self.assertEqual(self._get_summary_line(descr), + "classmeth(type, /, a, b=)") + + @support.cpython_only + def test_bound_builtin_classmethod_unrepresentable_default(self): + import _testcapi + cls = _testcapi.DocStringUnrepresentableSignatureTest + self.assertEqual(self._get_summary_line(cls.classmeth), + "classmeth(a, b=) method of builtins.type instance") def test_overridden_text_signature(self): class C: diff --git a/Modules/_testcapi/docstring.c b/Modules/_testcapi/docstring.c index b680171cc1437a..d99fbdd904b594 100644 --- a/Modules/_testcapi/docstring.c +++ b/Modules/_testcapi/docstring.c @@ -100,6 +100,13 @@ static PyMethodDef test_methods[] = { {"test_with_docstring", test_with_docstring, METH_VARARGS, PyDoc_STR("This is a pretty normal docstring.")}, + {"func_with_unrepresentable_signature", + (PyCFunction)test_with_docstring, METH_VARARGS, + PyDoc_STR( + "func_with_unrepresentable_signature($module, /, a, b=)\n" + "--\n\n" + "This docstring has a signature with unrepresentable default." + )}, {NULL}, }; @@ -140,6 +147,40 @@ static PyTypeObject DocStringNoSignatureTest = { .tp_new = PyType_GenericNew, }; +static PyMethodDef DocStringUnrepresentableSignatureTest_methods[] = { + {"meth", + (PyCFunction)test_with_docstring, METH_VARARGS, + PyDoc_STR( + "meth($self, /, a, b=)\n" + "--\n\n" + "This docstring has a signature with unrepresentable default." + )}, + {"classmeth", + (PyCFunction)test_with_docstring, METH_VARARGS|METH_CLASS, + PyDoc_STR( + "classmeth($type, /, a, b=)\n" + "--\n\n" + "This docstring has a signature with unrepresentable default." + )}, + {"staticmeth", + (PyCFunction)test_with_docstring, METH_VARARGS|METH_STATIC, + PyDoc_STR( + "staticmeth(a, b=)\n" + "--\n\n" + "This docstring has a signature with unrepresentable default." + )}, + {NULL}, +}; + +static PyTypeObject DocStringUnrepresentableSignatureTest = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testcapi.DocStringUnrepresentableSignatureTest", + .tp_basicsize = sizeof(PyObject), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_methods = DocStringUnrepresentableSignatureTest_methods, + .tp_new = PyType_GenericNew, +}; + int _PyTestCapi_Init_Docstring(PyObject *mod) { @@ -149,5 +190,8 @@ _PyTestCapi_Init_Docstring(PyObject *mod) if (PyModule_AddType(mod, &DocStringNoSignatureTest) < 0) { return -1; } + if (PyModule_AddType(mod, &DocStringUnrepresentableSignatureTest) < 0) { + return -1; + } return 0; } From 820f4cf8b61034a18224388fcb52c4fde8d1ba37 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 13 Sep 2023 08:30:10 +0300 Subject: [PATCH 2/3] Silence Tools/c-analyzer/check-c-globals.py. --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index bb85fba895bc25..50f261541e14de 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -318,6 +318,7 @@ Python/instrumentation.c - _PyInstrumentation_MISSING - ##----------------------- ## static types +Modules/_testcapi/docstring.c - DocStringUnrepresentableSignatureTest - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type - From a126bc9c83d53fe8248e73fcec132a9f5c253713 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 13 Sep 2023 21:38:34 +0300 Subject: [PATCH 3/3] Move from globals-to-fix.tsv to ignored.tsv. --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - Tools/c-analyzer/cpython/ignored.tsv | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 50f261541e14de..bb85fba895bc25 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -318,7 +318,6 @@ Python/instrumentation.c - _PyInstrumentation_MISSING - ##----------------------- ## static types -Modules/_testcapi/docstring.c - DocStringUnrepresentableSignatureTest - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type - diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index d1ac0410619c96..8c2be44b5171e6 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -420,6 +420,7 @@ 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/docstring.c - DocStringUnrepresentableSignatureTest - Modules/_testcapi/exceptions.c - PyRecursingInfinitelyError_Type - Modules/_testcapi/heaptype.c - _testcapimodule - Modules/_testcapi/mem.c - FmData -