From 1d75ef6b6186619081c166b21c71c15b4f98beb8 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 13 Nov 2023 09:13:49 +0200 Subject: [PATCH] gh-111999: Add signatures and improve docstrings for builtins (GH-112000) --- Lib/test/test_inspect/test_inspect.py | 11 ++++-- Objects/boolobject.c | 5 +-- Objects/descrobject.c | 3 ++ Objects/funcobject.c | 6 ++-- Objects/setobject.c | 48 ++++++++++++++++++--------- Objects/typeobject.c | 6 ++-- Objects/unicodeobject.c | 12 ++++--- Python/bltinmodule.c | 22 +++++++----- 8 files changed, 74 insertions(+), 39 deletions(-) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index bfafb0ce90c..becbb0498bb 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -4734,12 +4734,13 @@ class TestSignatureDefinitions(unittest.TestCase): needs_null = {"anext"} no_signature |= needs_null # These need *args support in Argument Clinic - needs_varargs = {"breakpoint", "min", "max", "__build_class__"} + needs_varargs = {"min", "max", "__build_class__"} no_signature |= needs_varargs # These builtin types are expected to provide introspection info types_with_signatures = { - 'complex', 'enumerate', 'float', 'list', 'memoryview', 'object', - 'property', 'reversed', 'tuple', + 'bool', 'classmethod', 'complex', 'enumerate', 'filter', 'float', + 'frozenset', 'list', 'map', 'memoryview', 'object', 'property', + 'reversed', 'set', 'staticmethod', 'tuple', 'zip' } # Check the signatures we expect to be there ns = vars(builtins) @@ -4753,6 +4754,10 @@ class TestSignatureDefinitions(unittest.TestCase): if (name in no_signature): # Not yet converted continue + if name in {'classmethod', 'staticmethod'}: + # Bug gh-112006: inspect.unwrap() does not work with types + # with the __wrapped__ data descriptor. + continue with self.subTest(builtin=name): self.assertIsNotNone(inspect.signature(obj)) # Check callables that haven't been converted don't claim a signature diff --git a/Objects/boolobject.c b/Objects/boolobject.c index e2e359437f0..fb48dcbeca7 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -110,9 +110,10 @@ bool_xor(PyObject *a, PyObject *b) /* Doc string */ PyDoc_STRVAR(bool_doc, -"bool(x) -> bool\n\ +"bool(object=False, /)\n\ +--\n\ \n\ -Returns True when the argument x is true, False otherwise.\n\ +Returns True when the argument is true, False otherwise.\n\ The builtins True and False are the only two instances of the class bool.\n\ The class bool is a subclass of the class int, and cannot be subclassed."); diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 7f9f03d7dca..57921b11059 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1541,6 +1541,9 @@ property_deleter(PyObject *self, PyObject *deleter) PyDoc_STRVAR(set_name_doc, + "__set_name__($self, owner, name, /)\n" + "--\n" + "\n" "Method to set name of a property."); static PyObject * diff --git a/Objects/funcobject.c b/Objects/funcobject.c index b3701ebc9de..e2fd6f99e45 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -1164,7 +1164,8 @@ cm_repr(classmethod *cm) } PyDoc_STRVAR(classmethod_doc, -"classmethod(function) -> method\n\ +"classmethod(function, /)\n\ +--\n\ \n\ Convert a function to be a class method.\n\ \n\ @@ -1359,7 +1360,8 @@ sm_repr(staticmethod *sm) } PyDoc_STRVAR(staticmethod_doc, -"staticmethod(function) -> method\n\ +"staticmethod(function, /)\n\ +--\n\ \n\ Convert a function to be a static method.\n\ \n\ diff --git a/Objects/setobject.c b/Objects/setobject.c index 76449c6a2a9..88d20019bfb 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -942,7 +942,10 @@ set_update(PySetObject *so, PyObject *args) } PyDoc_STRVAR(update_doc, -"Update a set with the union of itself and others."); +"update($self, /, *others)\n\ +--\n\ +\n\ +Update the set, adding elements from all others."); /* XXX Todo: If aligned memory allocations become available, make the @@ -1141,9 +1144,10 @@ set_union(PySetObject *so, PyObject *args) } PyDoc_STRVAR(union_doc, - "Return the union of sets as a new set.\n\ +"union($self, /, *others)\n\ +--\n\ \n\ -(i.e. all elements that are in either set.)"); +Return a new set with elements from the set and all others."); static PyObject * set_or(PySetObject *so, PyObject *other) @@ -1281,9 +1285,10 @@ set_intersection_multi(PySetObject *so, PyObject *args) } PyDoc_STRVAR(intersection_doc, -"Return the intersection of two sets as a new set.\n\ +"intersection($self, /, *others)\n\ +--\n\ \n\ -(i.e. all elements that are in both sets.)"); +Return a new set with elements common to the set and all others."); static PyObject * set_intersection_update(PySetObject *so, PyObject *other) @@ -1312,7 +1317,10 @@ set_intersection_update_multi(PySetObject *so, PyObject *args) } PyDoc_STRVAR(intersection_update_doc, -"Update a set with the intersection of itself and another."); +"intersection_update($self, /, *others)\n\ +--\n\ +\n\ +Update the set, keeping only elements found in it and all others."); static PyObject * set_and(PySetObject *so, PyObject *other) @@ -1470,7 +1478,10 @@ set_difference_update(PySetObject *so, PyObject *args) } PyDoc_STRVAR(difference_update_doc, -"Remove all elements of another set from this set."); +"difference_update($self, /, *others)\n\ +--\n\ +\n\ +Update the set, removing elements found in others."); static PyObject * set_copy_and_difference(PySetObject *so, PyObject *other) @@ -1587,9 +1598,10 @@ set_difference_multi(PySetObject *so, PyObject *args) } PyDoc_STRVAR(difference_doc, -"Return the difference of two or more sets as a new set.\n\ +"difference($self, /, *others)\n\ +--\n\ \n\ -(i.e. all elements that are in this set but not the others.)"); +Return a new set with elements in the set that are not in the others."); static PyObject * set_sub(PySetObject *so, PyObject *other) { @@ -1673,7 +1685,10 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other) } PyDoc_STRVAR(symmetric_difference_update_doc, -"Update a set with the symmetric difference of itself and another."); +"symmetric_difference_update($self, other, /)\n\ +--\n\ +\n\ +Update the set, keeping only elements found in either set, but not in both."); static PyObject * set_symmetric_difference(PySetObject *so, PyObject *other) @@ -1694,9 +1709,10 @@ set_symmetric_difference(PySetObject *so, PyObject *other) } PyDoc_STRVAR(symmetric_difference_doc, -"Return the symmetric difference of two sets as a new set.\n\ +"symmetric_difference($self, other, /)\n\ +--\n\ \n\ -(i.e. all elements that are in exactly one of the sets.)"); +Return a new set with elements in either the set or other but not both."); static PyObject * set_xor(PySetObject *so, PyObject *other) @@ -2100,8 +2116,8 @@ static PyNumberMethods set_as_number = { }; PyDoc_STRVAR(set_doc, -"set() -> new empty set object\n\ -set(iterable) -> new set object\n\ +"set(iterable=(), /)\n\ +--\n\ \n\ Build an unordered collection of unique elements."); @@ -2201,8 +2217,8 @@ static PyNumberMethods frozenset_as_number = { }; PyDoc_STRVAR(frozenset_doc, -"frozenset() -> empty frozenset object\n\ -frozenset(iterable) -> frozenset object\n\ +"frozenset(iterable=(), /)\n\ +--\n\ \n\ Build an immutable unordered collection of unique elements."); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 557464c6740..c1a4cb9aaea 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5254,8 +5254,10 @@ static PyMethodDef type_methods[] = { TYPE___SUBCLASSES___METHODDEF {"__prepare__", _PyCFunction_CAST(type_prepare), METH_FASTCALL | METH_KEYWORDS | METH_CLASS, - PyDoc_STR("__prepare__() -> dict\n" - "used to create the namespace for the class statement")}, + PyDoc_STR("__prepare__($cls, name, bases, /, **kwds)\n" + "--\n" + "\n" + "Create the namespace for the class statement")}, TYPE___INSTANCECHECK___METHODDEF TYPE___SUBCLASSCHECK___METHODDEF TYPE___DIR___METHODDEF diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index f3f1305c5ca..cffc06297a9 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13390,15 +13390,17 @@ _PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer) #include "stringlib/unicode_format.h" PyDoc_STRVAR(format__doc__, - "S.format(*args, **kwargs) -> str\n\ + "format($self, /, *args, **kwargs)\n\ +--\n\ \n\ -Return a formatted version of S, using substitutions from args and kwargs.\n\ +Return a formatted version of the string, using substitutions from args and kwargs.\n\ The substitutions are identified by braces ('{' and '}')."); PyDoc_STRVAR(format_map__doc__, - "S.format_map(mapping) -> str\n\ + "format_map($self, /, mapping)\n\ +--\n\ \n\ -Return a formatted version of S, using substitutions from mapping.\n\ +Return a formatted version of the string, using substitutions from mapping.\n\ The substitutions are identified by braces ('{' and '}')."); /*[clinic input] @@ -14696,7 +14698,7 @@ errors is specified, then the object must expose a data buffer\n\ that will be decoded using the given encoding and error handler.\n\ Otherwise, returns the result of object.__str__() (if defined)\n\ or repr(object).\n\ -encoding defaults to sys.getdefaultencoding().\n\ +encoding defaults to 'utf-8'.\n\ errors defaults to 'strict'."); static PyObject *unicode_iter(PyObject *seq); diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index a1ecdcbbc5b..ff07c498263 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -482,6 +482,7 @@ builtin_breakpoint(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb PyDoc_STRVAR(breakpoint_doc, "breakpoint(*args, **kws)\n\ +--\n\ \n\ Call sys.breakpointhook(*args, **kws). sys.breakpointhook() must accept\n\ whatever arguments are passed.\n\ @@ -626,7 +627,8 @@ static PyMethodDef filter_methods[] = { }; PyDoc_STRVAR(filter_doc, -"filter(function or None, iterable) --> filter object\n\ +"filter(function, iterable, /)\n\ +--\n\ \n\ Return an iterator yielding those items of iterable for which function(item)\n\ is true. If function is None, return the items that are true."); @@ -1449,7 +1451,8 @@ static PyMethodDef map_methods[] = { PyDoc_STRVAR(map_doc, -"map(func, *iterables) --> map object\n\ +"map(function, /, *iterables)\n\ +--\n\ \n\ Make an iterator that computes the function using arguments from\n\ each of the iterables. Stops when the shortest iterable is exhausted."); @@ -1888,7 +1891,7 @@ min(arg1, arg2, *args, *[, key=func]) -> value\n\ With a single iterable argument, return its smallest item. The\n\ default keyword-only argument specifies an object to return if\n\ the provided iterable is empty.\n\ -With two or more arguments, return the smallest argument."); +With two or more positional arguments, return the smallest argument."); /* AC: cannot convert yet, waiting for *args support */ @@ -1905,7 +1908,7 @@ max(arg1, arg2, *args, *[, key=func]) -> value\n\ With a single iterable argument, return its biggest item. The\n\ default keyword-only argument specifies an object to return if\n\ the provided iterable is empty.\n\ -With two or more arguments, return the largest argument."); +With two or more positional arguments, return the largest argument."); /*[clinic input] @@ -2958,10 +2961,8 @@ static PyMethodDef zip_methods[] = { }; PyDoc_STRVAR(zip_doc, -"zip(*iterables, strict=False) --> Yield tuples until an input is exhausted.\n\ -\n\ - >>> list(zip('abcdefg', range(3), range(4)))\n\ - [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)]\n\ +"zip(*iterables, strict=False)\n\ +--\n\ \n\ The zip object yields n-length tuples, where n is the number of iterables\n\ passed as positional arguments to zip(). The i-th element in every tuple\n\ @@ -2969,7 +2970,10 @@ comes from the i-th iterable argument to zip(). This continues until the\n\ shortest argument is exhausted.\n\ \n\ If strict is true and one of the arguments is exhausted before the others,\n\ -raise a ValueError."); +raise a ValueError.\n\ +\n\ + >>> list(zip('abcdefg', range(3), range(4)))\n\ + [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)]"); PyTypeObject PyZip_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0)