From 5c643a028ee86c613d7168ca5bcb8fc94477a09e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 19 Mar 2017 08:46:44 +0200 Subject: [PATCH] bpo-20185: Convert typeobject.c to Argument Clinic. (#544) Based on patch by Vajrasky Kok. --- Objects/clinic/typeobject.c.h | 259 ++++++++++++++++++++++++++++++++++ Objects/typeobject.c | 212 ++++++++++++++++++---------- 2 files changed, 393 insertions(+), 78 deletions(-) create mode 100644 Objects/clinic/typeobject.c.h diff --git a/Objects/clinic/typeobject.c.h b/Objects/clinic/typeobject.c.h new file mode 100644 index 00000000000..1b19ccf0615 --- /dev/null +++ b/Objects/clinic/typeobject.c.h @@ -0,0 +1,259 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(type___instancecheck____doc__, +"__instancecheck__($self, instance, /)\n" +"--\n" +"\n" +"Check if an object is an instance."); + +#define TYPE___INSTANCECHECK___METHODDEF \ + {"__instancecheck__", (PyCFunction)type___instancecheck__, METH_O, type___instancecheck____doc__}, + +static int +type___instancecheck___impl(PyTypeObject *self, PyObject *instance); + +static PyObject * +type___instancecheck__(PyTypeObject *self, PyObject *instance) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = type___instancecheck___impl(self, instance); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(type___subclasscheck____doc__, +"__subclasscheck__($self, subclass, /)\n" +"--\n" +"\n" +"Check if a class is a subclass."); + +#define TYPE___SUBCLASSCHECK___METHODDEF \ + {"__subclasscheck__", (PyCFunction)type___subclasscheck__, METH_O, type___subclasscheck____doc__}, + +static int +type___subclasscheck___impl(PyTypeObject *self, PyObject *subclass); + +static PyObject * +type___subclasscheck__(PyTypeObject *self, PyObject *subclass) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = type___subclasscheck___impl(self, subclass); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(type_mro__doc__, +"mro($self, /)\n" +"--\n" +"\n" +"Return a type\'s method resolution order."); + +#define TYPE_MRO_METHODDEF \ + {"mro", (PyCFunction)type_mro, METH_NOARGS, type_mro__doc__}, + +static PyObject * +type_mro_impl(PyTypeObject *self); + +static PyObject * +type_mro(PyTypeObject *self, PyObject *Py_UNUSED(ignored)) +{ + return type_mro_impl(self); +} + +PyDoc_STRVAR(type___subclasses____doc__, +"__subclasses__($self, /)\n" +"--\n" +"\n" +"Return a list of immediate subclasses."); + +#define TYPE___SUBCLASSES___METHODDEF \ + {"__subclasses__", (PyCFunction)type___subclasses__, METH_NOARGS, type___subclasses____doc__}, + +static PyObject * +type___subclasses___impl(PyTypeObject *self); + +static PyObject * +type___subclasses__(PyTypeObject *self, PyObject *Py_UNUSED(ignored)) +{ + return type___subclasses___impl(self); +} + +PyDoc_STRVAR(type___dir____doc__, +"__dir__($self, /)\n" +"--\n" +"\n" +"Specialized __dir__ implementation for types."); + +#define TYPE___DIR___METHODDEF \ + {"__dir__", (PyCFunction)type___dir__, METH_NOARGS, type___dir____doc__}, + +static PyObject * +type___dir___impl(PyTypeObject *self); + +static PyObject * +type___dir__(PyTypeObject *self, PyObject *Py_UNUSED(ignored)) +{ + return type___dir___impl(self); +} + +PyDoc_STRVAR(type___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n" +"Return memory consumption of the type object."); + +#define TYPE___SIZEOF___METHODDEF \ + {"__sizeof__", (PyCFunction)type___sizeof__, METH_NOARGS, type___sizeof____doc__}, + +static PyObject * +type___sizeof___impl(PyTypeObject *self); + +static PyObject * +type___sizeof__(PyTypeObject *self, PyObject *Py_UNUSED(ignored)) +{ + return type___sizeof___impl(self); +} + +PyDoc_STRVAR(object___reduce____doc__, +"__reduce__($self, protocol=0, /)\n" +"--\n" +"\n" +"Helper for pickle."); + +#define OBJECT___REDUCE___METHODDEF \ + {"__reduce__", (PyCFunction)object___reduce__, METH_FASTCALL, object___reduce____doc__}, + +static PyObject * +object___reduce___impl(PyObject *self, int protocol); + +static PyObject * +object___reduce__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + int protocol = 0; + + if (!_PyArg_ParseStack(args, nargs, "|i:__reduce__", + &protocol)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("__reduce__", kwnames)) { + goto exit; + } + return_value = object___reduce___impl(self, protocol); + +exit: + return return_value; +} + +PyDoc_STRVAR(object___reduce_ex____doc__, +"__reduce_ex__($self, protocol=0, /)\n" +"--\n" +"\n" +"Helper for pickle."); + +#define OBJECT___REDUCE_EX___METHODDEF \ + {"__reduce_ex__", (PyCFunction)object___reduce_ex__, METH_FASTCALL, object___reduce_ex____doc__}, + +static PyObject * +object___reduce_ex___impl(PyObject *self, int protocol); + +static PyObject * +object___reduce_ex__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + int protocol = 0; + + if (!_PyArg_ParseStack(args, nargs, "|i:__reduce_ex__", + &protocol)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("__reduce_ex__", kwnames)) { + goto exit; + } + return_value = object___reduce_ex___impl(self, protocol); + +exit: + return return_value; +} + +PyDoc_STRVAR(object___format____doc__, +"__format__($self, format_spec, /)\n" +"--\n" +"\n" +"Default object formatter."); + +#define OBJECT___FORMAT___METHODDEF \ + {"__format__", (PyCFunction)object___format__, METH_O, object___format____doc__}, + +static PyObject * +object___format___impl(PyObject *self, PyObject *format_spec); + +static PyObject * +object___format__(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *format_spec; + + if (!PyArg_Parse(arg, "U:__format__", &format_spec)) { + goto exit; + } + return_value = object___format___impl(self, format_spec); + +exit: + return return_value; +} + +PyDoc_STRVAR(object___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n" +"Size of object in memory, in bytes."); + +#define OBJECT___SIZEOF___METHODDEF \ + {"__sizeof__", (PyCFunction)object___sizeof__, METH_NOARGS, object___sizeof____doc__}, + +static PyObject * +object___sizeof___impl(PyObject *self); + +static PyObject * +object___sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return object___sizeof___impl(self); +} + +PyDoc_STRVAR(object___dir____doc__, +"__dir__($self, /)\n" +"--\n" +"\n" +"Default dir() implementation."); + +#define OBJECT___DIR___METHODDEF \ + {"__dir__", (PyCFunction)object___dir__, METH_NOARGS, object___dir____doc__}, + +static PyObject * +object___dir___impl(PyObject *self); + +static PyObject * +object___dir__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return object___dir___impl(self); +} +/*[clinic end generated code: output=ce354e436e2360a0 input=a9049054013a1b77]*/ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index d70ced04bfe..3e1e8d7725a 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6,6 +6,13 @@ #include +/*[clinic input] +class type "PyTypeObject *" "&PyType_Type" +class object "PyObject *" "&PyBaseObject_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b94608d231c434b]*/ + +#include "clinic/typeobject.c.h" /* Support type attribute cache */ @@ -579,7 +586,6 @@ static int update_subclasses(PyTypeObject *type, PyObject *name, update_callback callback, void *data); static int recurse_down_subclasses(PyTypeObject *type, PyObject *name, update_callback callback, void *data); -static PyObject *type_subclasses(PyTypeObject *type, PyObject *ignored); static int mro_hierarchy(PyTypeObject *type, PyObject *temp) @@ -624,7 +630,7 @@ mro_hierarchy(PyTypeObject *type, PyObject *temp) Finally, this makes things simple avoiding the need to deal with dictionary iterators and weak references. */ - subclasses = type_subclasses(type, NULL); + subclasses = type___subclasses___impl(type); if (subclasses == NULL) return -1; n = PyList_GET_SIZE(subclasses); @@ -819,31 +825,36 @@ type_set_doc(PyTypeObject *type, PyObject *value, void *context) return _PyDict_SetItemId(type->tp_dict, &PyId___doc__, value); } -static PyObject * -type___instancecheck__(PyObject *type, PyObject *inst) +/*[clinic input] +type.__instancecheck__ -> bool + + instance: object + / + +Check if an object is an instance. +[clinic start generated code]*/ + +static int +type___instancecheck___impl(PyTypeObject *self, PyObject *instance) +/*[clinic end generated code: output=08b6bf5f591c3618 input=cdbfeaee82c01a0f]*/ { - switch (_PyObject_RealIsInstance(inst, type)) { - case -1: - return NULL; - case 0: - Py_RETURN_FALSE; - default: - Py_RETURN_TRUE; - } + return _PyObject_RealIsInstance(instance, (PyObject *)self); } +/*[clinic input] +type.__subclasscheck__ -> bool -static PyObject * -type___subclasscheck__(PyObject *type, PyObject *inst) + subclass: object + / + +Check if a class is a subclass. +[clinic start generated code]*/ + +static int +type___subclasscheck___impl(PyTypeObject *self, PyObject *subclass) +/*[clinic end generated code: output=97a4e51694500941 input=071b2ca9e03355f4]*/ { - switch (_PyObject_RealIsSubclass(inst, type)) { - case -1: - return NULL; - case 0: - Py_RETURN_FALSE; - default: - Py_RETURN_TRUE; - } + return _PyObject_RealIsSubclass(subclass, (PyObject *)self); } @@ -1818,12 +1829,17 @@ mro_implementation(PyTypeObject *type) return result; } -static PyObject * -mro_external(PyObject *self) -{ - PyTypeObject *type = (PyTypeObject *)self; +/*[clinic input] +type.mro - return mro_implementation(type); +Return a type's method resolution order. +[clinic start generated code]*/ + +static PyObject * +type_mro_impl(PyTypeObject *self) +/*[clinic end generated code: output=bffc4a39b5b57027 input=28414f4e156db28d]*/ +{ + return mro_implementation(self); } static int @@ -3164,8 +3180,15 @@ type_dealloc(PyTypeObject *type) Py_TYPE(type)->tp_free((PyObject *)type); } +/*[clinic input] +type.__subclasses__ + +Return a list of immediate subclasses. +[clinic start generated code]*/ + static PyObject * -type_subclasses(PyTypeObject *type, PyObject *args_ignored) +type___subclasses___impl(PyTypeObject *self) +/*[clinic end generated code: output=eb5eb54485942819 input=5af66132436f9a7b]*/ { PyObject *list, *raw, *ref; Py_ssize_t i; @@ -3173,7 +3196,7 @@ type_subclasses(PyTypeObject *type, PyObject *args_ignored) list = PyList_New(0); if (list == NULL) return NULL; - raw = type->tp_subclasses; + raw = self->tp_subclasses; if (raw == NULL) return list; assert(PyDict_CheckExact(raw)); @@ -3262,26 +3285,39 @@ merge_class_dict(PyObject *dict, PyObject *aclass) We deliberately don't suck up its __class__, as methods belonging to the metaclass would probably be more confusing than helpful. */ +/*[clinic input] +type.__dir__ + +Specialized __dir__ implementation for types. +[clinic start generated code]*/ + static PyObject * -type_dir(PyObject *self, PyObject *args) +type___dir___impl(PyTypeObject *self) +/*[clinic end generated code: output=69d02fe92c0f15fa input=7733befbec645968]*/ { PyObject *result = NULL; PyObject *dict = PyDict_New(); - if (dict != NULL && merge_class_dict(dict, self) == 0) + if (dict != NULL && merge_class_dict(dict, (PyObject *)self) == 0) result = PyDict_Keys(dict); Py_XDECREF(dict); return result; } -static PyObject* -type_sizeof(PyObject *self, PyObject *args_unused) +/*[clinic input] +type.__sizeof__ + +Return memory consumption of the type object. +[clinic start generated code]*/ + +static PyObject * +type___sizeof___impl(PyTypeObject *self) +/*[clinic end generated code: output=766f4f16cd3b1854 input=99398f24b9cf45d6]*/ { Py_ssize_t size; - PyTypeObject *type = (PyTypeObject*)self; - if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { - PyHeapTypeObject* et = (PyHeapTypeObject*)type; + if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) { + PyHeapTypeObject* et = (PyHeapTypeObject*)self; size = sizeof(PyHeapTypeObject); if (et->ht_cached_keys) size += _PyDict_KeysSize(et->ht_cached_keys); @@ -3292,22 +3328,16 @@ type_sizeof(PyObject *self, PyObject *args_unused) } static PyMethodDef type_methods[] = { - {"mro", (PyCFunction)mro_external, METH_NOARGS, - PyDoc_STR("mro() -> list\nreturn a type's method resolution order")}, - {"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS, - PyDoc_STR("__subclasses__() -> list of immediate subclasses")}, + TYPE_MRO_METHODDEF + TYPE___SUBCLASSES___METHODDEF {"__prepare__", (PyCFunction)type_prepare, METH_FASTCALL | METH_CLASS, PyDoc_STR("__prepare__() -> dict\n" "used to create the namespace for the class statement")}, - {"__instancecheck__", type___instancecheck__, METH_O, - PyDoc_STR("__instancecheck__() -> bool\ncheck if an object is an instance")}, - {"__subclasscheck__", type___subclasscheck__, METH_O, - PyDoc_STR("__subclasscheck__() -> bool\ncheck if a class is a subclass")}, - {"__dir__", type_dir, METH_NOARGS, - PyDoc_STR("__dir__() -> list\nspecialized __dir__ implementation for types")}, - {"__sizeof__", type_sizeof, METH_NOARGS, - "__sizeof__() -> int\nreturn memory consumption of the type object"}, + TYPE___INSTANCECHECK___METHODDEF + TYPE___SUBCLASSCHECK___METHODDEF + TYPE___DIR___METHODDEF + TYPE___SIZEOF___METHODDEF {0} }; @@ -4360,28 +4390,39 @@ _common_reduce(PyObject *self, int proto) return res; } +/*[clinic input] +object.__reduce__ + + protocol: int = 0 + / + +Helper for pickle. +[clinic start generated code]*/ + static PyObject * -object_reduce(PyObject *self, PyObject *args) +object___reduce___impl(PyObject *self, int protocol) +/*[clinic end generated code: output=5572e699c467dd5b input=227f37ed68bd938a]*/ { - int proto = 0; - - if (!PyArg_ParseTuple(args, "|i:__reduce__", &proto)) - return NULL; - - return _common_reduce(self, proto); + return _common_reduce(self, protocol); } +/*[clinic input] +object.__reduce_ex__ + + protocol: int = 0 + / + +Helper for pickle. +[clinic start generated code]*/ + static PyObject * -object_reduce_ex(PyObject *self, PyObject *args) +object___reduce_ex___impl(PyObject *self, int protocol) +/*[clinic end generated code: output=2e157766f6b50094 input=8dd6a9602a12749e]*/ { static PyObject *objreduce; PyObject *reduce, *res; - int proto = 0; _Py_IDENTIFIER(__reduce__); - if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto)) - return NULL; - if (objreduce == NULL) { objreduce = _PyDict_GetItemId(PyBaseObject_Type.tp_dict, &PyId___reduce__); @@ -4413,7 +4454,7 @@ object_reduce_ex(PyObject *self, PyObject *args) Py_DECREF(reduce); } - return _common_reduce(self, proto); + return _common_reduce(self, protocol); } static PyObject * @@ -4442,16 +4483,22 @@ PyDoc_STRVAR(object_init_subclass_doc, "The default implementation does nothing. It may be\n" "overridden to extend subclasses.\n"); +/*[clinic input] +object.__format__ + + format_spec: unicode + / + +Default object formatter. +[clinic start generated code]*/ + static PyObject * -object_format(PyObject *self, PyObject *args) +object___format___impl(PyObject *self, PyObject *format_spec) +/*[clinic end generated code: output=34897efb543a974b input=7c3b3bc53a6fb7fa]*/ { - PyObject *format_spec; PyObject *self_as_str = NULL; PyObject *result = NULL; - if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) - return NULL; - /* Issue 7994: If we're converting to a string, we should reject format specifications */ if (PyUnicode_GET_LENGTH(format_spec) > 0) { @@ -4468,8 +4515,15 @@ object_format(PyObject *self, PyObject *args) return result; } +/*[clinic input] +object.__sizeof__ + +Size of object in memory, in bytes. +[clinic start generated code]*/ + static PyObject * -object_sizeof(PyObject *self, PyObject *args) +object___sizeof___impl(PyObject *self) +/*[clinic end generated code: output=73edab332f97d550 input=1200ff3dfe485306]*/ { Py_ssize_t res, isize; @@ -4485,8 +4539,15 @@ object_sizeof(PyObject *self, PyObject *args) /* __dir__ for generic objects: returns __dict__, __class__, and recursively up the __class__.__bases__ chain. */ +/*[clinic input] +object.__dir__ + +Default dir() implementation. +[clinic start generated code]*/ + static PyObject * -object_dir(PyObject *self, PyObject *args) +object___dir___impl(PyObject *self) +/*[clinic end generated code: output=66dd48ea62f26c90 input=0a89305bec669b10]*/ { PyObject *result = NULL; PyObject *dict = NULL; @@ -4530,20 +4591,15 @@ error: } static PyMethodDef object_methods[] = { - {"__reduce_ex__", object_reduce_ex, METH_VARARGS, - PyDoc_STR("helper for pickle")}, - {"__reduce__", object_reduce, METH_VARARGS, - PyDoc_STR("helper for pickle")}, + OBJECT___REDUCE_EX___METHODDEF + OBJECT___REDUCE___METHODDEF {"__subclasshook__", object_subclasshook, METH_CLASS | METH_VARARGS, object_subclasshook_doc}, {"__init_subclass__", object_init_subclass, METH_CLASS | METH_NOARGS, object_init_subclass_doc}, - {"__format__", object_format, METH_VARARGS, - PyDoc_STR("default object formatter")}, - {"__sizeof__", object_sizeof, METH_NOARGS, - PyDoc_STR("__sizeof__() -> int\nsize of object in memory, in bytes")}, - {"__dir__", object_dir, METH_NOARGS, - PyDoc_STR("__dir__() -> list\ndefault dir() implementation")}, + OBJECT___FORMAT___METHODDEF + OBJECT___SIZEOF___METHODDEF + OBJECT___DIR___METHODDEF {0} };