Skip to content

Commit

Permalink
gh-107782: Use _testcapi to test non-representable signatures (GH-109325
Browse files Browse the repository at this point in the history
)

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.
  • Loading branch information
serhiy-storchaka authored Sep 14, 2023
1 parent a806e92 commit 1f885df
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 2 deletions.
39 changes: 37 additions & 2 deletions Lib/test/test_pydoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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=<x>)")

@support.cpython_only
def test_builtin_staticmethod_unrepresentable_default(self):
self.assertEqual(self._get_summary_line(str.maketrans),
"maketrans(x, y=<unrepresentable>, z=<unrepresentable>, /)")
import _testcapi
cls = _testcapi.DocStringUnrepresentableSignatureTest
self.assertEqual(self._get_summary_line(cls.staticmeth),
"staticmeth(a, b=<x>)")

@support.cpython_only
def test_unbound_builtin_method_unrepresentable_default(self):
self.assertEqual(self._get_summary_line(dict.pop),
"pop(self, key, default=<unrepresentable>, /)")
import _testcapi
cls = _testcapi.DocStringUnrepresentableSignatureTest
self.assertEqual(self._get_summary_line(cls.meth),
"meth(self, /, a, b=<x>)")

@support.cpython_only
def test_bound_builtin_method_unrepresentable_default(self):
self.assertEqual(self._get_summary_line({}.pop),
"pop(key, default=<unrepresentable>, /) "
"method of builtins.dict instance")
import _testcapi
obj = _testcapi.DocStringUnrepresentableSignatureTest()
self.assertEqual(self._get_summary_line(obj.meth),
"meth(a, b=<x>) "
"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=<x>)")

@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=<x>) method of builtins.type instance")

def test_overridden_text_signature(self):
class C:
Expand Down
44 changes: 44 additions & 0 deletions Modules/_testcapi/docstring.c
Original file line number Diff line number Diff line change
Expand Up @@ -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=<x>)\n"
"--\n\n"
"This docstring has a signature with unrepresentable default."
)},
{NULL},
};

Expand Down Expand Up @@ -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=<x>)\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=<x>)\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=<x>)\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)
{
Expand All @@ -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;
}
1 change: 1 addition & 0 deletions Tools/c-analyzer/cpython/ignored.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -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 -
Expand Down

0 comments on commit 1f885df

Please sign in to comment.