aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Objects/classobject.c
diff options
context:
space:
mode:
authornkozlovskiy <nmk@ydb.tech>2023-09-29 12:24:06 +0300
committernkozlovskiy <nmk@ydb.tech>2023-09-29 12:41:34 +0300
commite0e3e1717e3d33762ce61950504f9637a6e669ed (patch)
treebca3ff6939b10ed60c3d5c12439963a1146b9711 /contrib/tools/python3/src/Objects/classobject.c
parent38f2c5852db84c7b4d83adfcb009eb61541d1ccd (diff)
downloadydb-e0e3e1717e3d33762ce61950504f9637a6e669ed.tar.gz
add ydb deps
Diffstat (limited to 'contrib/tools/python3/src/Objects/classobject.c')
-rw-r--r--contrib/tools/python3/src/Objects/classobject.c545
1 files changed, 545 insertions, 0 deletions
diff --git a/contrib/tools/python3/src/Objects/classobject.c b/contrib/tools/python3/src/Objects/classobject.c
new file mode 100644
index 0000000000..b9708ba0e4
--- /dev/null
+++ b/contrib/tools/python3/src/Objects/classobject.c
@@ -0,0 +1,545 @@
+/* Class object implementation (dead now except for methods) */
+
+#include "Python.h"
+#include "pycore_call.h" // _PyObject_VectorcallTstate()
+#include "pycore_object.h"
+#include "pycore_pyerrors.h"
+#include "pycore_pystate.h" // _PyThreadState_GET()
+#include "structmember.h" // PyMemberDef
+
+#include "clinic/classobject.c.h"
+
+#define TP_DESCR_GET(t) ((t)->tp_descr_get)
+
+/*[clinic input]
+class method "PyMethodObject *" "&PyMethod_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b16e47edf6107c23]*/
+
+
+PyObject *
+PyMethod_Function(PyObject *im)
+{
+ if (!PyMethod_Check(im)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ return ((PyMethodObject *)im)->im_func;
+}
+
+PyObject *
+PyMethod_Self(PyObject *im)
+{
+ if (!PyMethod_Check(im)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ return ((PyMethodObject *)im)->im_self;
+}
+
+
+static PyObject *
+method_vectorcall(PyObject *method, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames)
+{
+ assert(Py_IS_TYPE(method, &PyMethod_Type));
+
+ PyThreadState *tstate = _PyThreadState_GET();
+ PyObject *self = PyMethod_GET_SELF(method);
+ PyObject *func = PyMethod_GET_FUNCTION(method);
+ Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
+
+ PyObject *result;
+ if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
+ /* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */
+ PyObject **newargs = (PyObject**)args - 1;
+ nargs += 1;
+ PyObject *tmp = newargs[0];
+ newargs[0] = self;
+ result = _PyObject_VectorcallTstate(tstate, func, newargs,
+ nargs, kwnames);
+ newargs[0] = tmp;
+ }
+ else {
+ Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
+ Py_ssize_t totalargs = nargs + nkwargs;
+ if (totalargs == 0) {
+ return _PyObject_VectorcallTstate(tstate, func, &self, 1, NULL);
+ }
+
+ PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK];
+ PyObject **newargs;
+ if (totalargs <= (Py_ssize_t)Py_ARRAY_LENGTH(newargs_stack) - 1) {
+ newargs = newargs_stack;
+ }
+ else {
+ newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
+ if (newargs == NULL) {
+ _PyErr_NoMemory(tstate);
+ return NULL;
+ }
+ }
+ /* use borrowed references */
+ newargs[0] = self;
+ /* bpo-37138: since totalargs > 0, it's impossible that args is NULL.
+ * We need this, since calling memcpy() with a NULL pointer is
+ * undefined behaviour. */
+ assert(args != NULL);
+ memcpy(newargs + 1, args, totalargs * sizeof(PyObject *));
+ result = _PyObject_VectorcallTstate(tstate, func,
+ newargs, nargs+1, kwnames);
+ if (newargs != newargs_stack) {
+ PyMem_Free(newargs);
+ }
+ }
+ return result;
+}
+
+
+/* Method objects are used for bound instance methods returned by
+ instancename.methodname. ClassName.methodname returns an ordinary
+ function.
+*/
+
+PyObject *
+PyMethod_New(PyObject *func, PyObject *self)
+{
+ if (self == NULL) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
+ if (im == NULL) {
+ return NULL;
+ }
+ im->im_weakreflist = NULL;
+ Py_INCREF(func);
+ im->im_func = func;
+ Py_INCREF(self);
+ im->im_self = self;
+ im->vectorcall = method_vectorcall;
+ _PyObject_GC_TRACK(im);
+ return (PyObject *)im;
+}
+
+/*[clinic input]
+method.__reduce__
+[clinic start generated code]*/
+
+static PyObject *
+method___reduce___impl(PyMethodObject *self)
+/*[clinic end generated code: output=6c04506d0fa6fdcb input=143a0bf5e96de6e8]*/
+{
+ PyObject *funcself = PyMethod_GET_SELF(self);
+ PyObject *func = PyMethod_GET_FUNCTION(self);
+ PyObject *funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
+ if (funcname == NULL) {
+ return NULL;
+ }
+ return Py_BuildValue(
+ "N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), funcself, funcname);
+}
+
+static PyMethodDef method_methods[] = {
+ METHOD___REDUCE___METHODDEF
+ {NULL, NULL}
+};
+
+/* Descriptors for PyMethod attributes */
+
+/* im_func and im_self are stored in the PyMethod object */
+
+#define MO_OFF(x) offsetof(PyMethodObject, x)
+
+static PyMemberDef method_memberlist[] = {
+ {"__func__", T_OBJECT, MO_OFF(im_func), READONLY,
+ "the function (or other callable) implementing a method"},
+ {"__self__", T_OBJECT, MO_OFF(im_self), READONLY,
+ "the instance to which a method is bound"},
+ {NULL} /* Sentinel */
+};
+
+/* Christian Tismer argued convincingly that method attributes should
+ (nearly) always override function attributes.
+ The one exception is __doc__; there's a default __doc__ which
+ should only be used for the class, not for instances */
+
+static PyObject *
+method_get_doc(PyMethodObject *im, void *context)
+{
+ return PyObject_GetAttr(im->im_func, &_Py_ID(__doc__));
+}
+
+static PyGetSetDef method_getset[] = {
+ {"__doc__", (getter)method_get_doc, NULL, NULL},
+ {0}
+};
+
+static PyObject *
+method_getattro(PyObject *obj, PyObject *name)
+{
+ PyMethodObject *im = (PyMethodObject *)obj;
+ PyTypeObject *tp = Py_TYPE(obj);
+ PyObject *descr = NULL;
+
+ {
+ if (tp->tp_dict == NULL) {
+ if (PyType_Ready(tp) < 0)
+ return NULL;
+ }
+ descr = _PyType_Lookup(tp, name);
+ }
+
+ if (descr != NULL) {
+ descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
+ if (f != NULL)
+ return f(descr, obj, (PyObject *)Py_TYPE(obj));
+ else {
+ Py_INCREF(descr);
+ return descr;
+ }
+ }
+
+ return PyObject_GetAttr(im->im_func, name);
+}
+
+/*[clinic input]
+@classmethod
+method.__new__ as method_new
+ function: object
+ instance: object
+ /
+
+Create a bound instance method object.
+[clinic start generated code]*/
+
+static PyObject *
+method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance)
+/*[clinic end generated code: output=d33ef4ebf702e1f7 input=4e32facc3c3108ae]*/
+{
+ if (!PyCallable_Check(function)) {
+ PyErr_SetString(PyExc_TypeError,
+ "first argument must be callable");
+ return NULL;
+ }
+ if (instance == NULL || instance == Py_None) {
+ PyErr_SetString(PyExc_TypeError,
+ "instance must not be None");
+ return NULL;
+ }
+
+ return PyMethod_New(function, instance);
+}
+
+static void
+method_dealloc(PyMethodObject *im)
+{
+ _PyObject_GC_UNTRACK(im);
+ if (im->im_weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject *)im);
+ Py_DECREF(im->im_func);
+ Py_XDECREF(im->im_self);
+ PyObject_GC_Del(im);
+}
+
+static PyObject *
+method_richcompare(PyObject *self, PyObject *other, int op)
+{
+ PyMethodObject *a, *b;
+ PyObject *res;
+ int eq;
+
+ if ((op != Py_EQ && op != Py_NE) ||
+ !PyMethod_Check(self) ||
+ !PyMethod_Check(other))
+ {
+ Py_RETURN_NOTIMPLEMENTED;
+ }
+ a = (PyMethodObject *)self;
+ b = (PyMethodObject *)other;
+ eq = PyObject_RichCompareBool(a->im_func, b->im_func, Py_EQ);
+ if (eq == 1) {
+ eq = (a->im_self == b->im_self);
+ }
+ else if (eq < 0)
+ return NULL;
+ if (op == Py_EQ)
+ res = eq ? Py_True : Py_False;
+ else
+ res = eq ? Py_False : Py_True;
+ Py_INCREF(res);
+ return res;
+}
+
+static PyObject *
+method_repr(PyMethodObject *a)
+{
+ PyObject *self = a->im_self;
+ PyObject *func = a->im_func;
+ PyObject *funcname, *result;
+ const char *defname = "?";
+
+ if (_PyObject_LookupAttr(func, &_Py_ID(__qualname__), &funcname) < 0 ||
+ (funcname == NULL &&
+ _PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0))
+ {
+ return NULL;
+ }
+
+ if (funcname != NULL && !PyUnicode_Check(funcname)) {
+ Py_DECREF(funcname);
+ funcname = NULL;
+ }
+
+ /* XXX Shouldn't use repr()/%R here! */
+ result = PyUnicode_FromFormat("<bound method %V of %R>",
+ funcname, defname, self);
+
+ Py_XDECREF(funcname);
+ return result;
+}
+
+static Py_hash_t
+method_hash(PyMethodObject *a)
+{
+ Py_hash_t x, y;
+ x = _Py_HashPointer(a->im_self);
+ y = PyObject_Hash(a->im_func);
+ if (y == -1)
+ return -1;
+ x = x ^ y;
+ if (x == -1)
+ x = -2;
+ return x;
+}
+
+static int
+method_traverse(PyMethodObject *im, visitproc visit, void *arg)
+{
+ Py_VISIT(im->im_func);
+ Py_VISIT(im->im_self);
+ return 0;
+}
+
+PyTypeObject PyMethod_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ .tp_name = "method",
+ .tp_basicsize = sizeof(PyMethodObject),
+ .tp_dealloc = (destructor)method_dealloc,
+ .tp_vectorcall_offset = offsetof(PyMethodObject, vectorcall),
+ .tp_repr = (reprfunc)method_repr,
+ .tp_hash = (hashfunc)method_hash,
+ .tp_call = PyVectorcall_Call,
+ .tp_getattro = method_getattro,
+ .tp_setattro = PyObject_GenericSetAttr,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_HAVE_VECTORCALL,
+ .tp_doc = method_new__doc__,
+ .tp_traverse = (traverseproc)method_traverse,
+ .tp_richcompare = method_richcompare,
+ .tp_weaklistoffset = offsetof(PyMethodObject, im_weakreflist),
+ .tp_methods = method_methods,
+ .tp_members = method_memberlist,
+ .tp_getset = method_getset,
+ .tp_new = method_new,
+};
+
+/* ------------------------------------------------------------------------
+ * instance method
+ */
+
+/*[clinic input]
+class instancemethod "PyInstanceMethodObject *" "&PyInstanceMethod_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=28c9762a9016f4d2]*/
+
+PyObject *
+PyInstanceMethod_New(PyObject *func) {
+ PyInstanceMethodObject *method;
+ method = PyObject_GC_New(PyInstanceMethodObject,
+ &PyInstanceMethod_Type);
+ if (method == NULL) return NULL;
+ Py_INCREF(func);
+ method->func = func;
+ _PyObject_GC_TRACK(method);
+ return (PyObject *)method;
+}
+
+PyObject *
+PyInstanceMethod_Function(PyObject *im)
+{
+ if (!PyInstanceMethod_Check(im)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ return PyInstanceMethod_GET_FUNCTION(im);
+}
+
+#define IMO_OFF(x) offsetof(PyInstanceMethodObject, x)
+
+static PyMemberDef instancemethod_memberlist[] = {
+ {"__func__", T_OBJECT, IMO_OFF(func), READONLY,
+ "the function (or other callable) implementing a method"},
+ {NULL} /* Sentinel */
+};
+
+static PyObject *
+instancemethod_get_doc(PyObject *self, void *context)
+{
+ return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self),
+ &_Py_ID(__doc__));
+}
+
+static PyGetSetDef instancemethod_getset[] = {
+ {"__doc__", (getter)instancemethod_get_doc, NULL, NULL},
+ {0}
+};
+
+static PyObject *
+instancemethod_getattro(PyObject *self, PyObject *name)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject *descr = NULL;
+
+ if (tp->tp_dict == NULL) {
+ if (PyType_Ready(tp) < 0)
+ return NULL;
+ }
+ descr = _PyType_Lookup(tp, name);
+
+ if (descr != NULL) {
+ descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
+ if (f != NULL)
+ return f(descr, self, (PyObject *)Py_TYPE(self));
+ else {
+ Py_INCREF(descr);
+ return descr;
+ }
+ }
+
+ return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self), name);
+}
+
+static void
+instancemethod_dealloc(PyObject *self) {
+ _PyObject_GC_UNTRACK(self);
+ Py_DECREF(PyInstanceMethod_GET_FUNCTION(self));
+ PyObject_GC_Del(self);
+}
+
+static int
+instancemethod_traverse(PyObject *self, visitproc visit, void *arg) {
+ Py_VISIT(PyInstanceMethod_GET_FUNCTION(self));
+ return 0;
+}
+
+static PyObject *
+instancemethod_call(PyObject *self, PyObject *arg, PyObject *kw)
+{
+ return PyObject_Call(PyInstanceMethod_GET_FUNCTION(self), arg, kw);
+}
+
+static PyObject *
+instancemethod_descr_get(PyObject *descr, PyObject *obj, PyObject *type) {
+ PyObject *func = PyInstanceMethod_GET_FUNCTION(descr);
+ if (obj == NULL) {
+ Py_INCREF(func);
+ return func;
+ }
+ else
+ return PyMethod_New(func, obj);
+}
+
+static PyObject *
+instancemethod_richcompare(PyObject *self, PyObject *other, int op)
+{
+ PyInstanceMethodObject *a, *b;
+ PyObject *res;
+ int eq;
+
+ if ((op != Py_EQ && op != Py_NE) ||
+ !PyInstanceMethod_Check(self) ||
+ !PyInstanceMethod_Check(other))
+ {
+ Py_RETURN_NOTIMPLEMENTED;
+ }
+ a = (PyInstanceMethodObject *)self;
+ b = (PyInstanceMethodObject *)other;
+ eq = PyObject_RichCompareBool(a->func, b->func, Py_EQ);
+ if (eq < 0)
+ return NULL;
+ if (op == Py_EQ)
+ res = eq ? Py_True : Py_False;
+ else
+ res = eq ? Py_False : Py_True;
+ Py_INCREF(res);
+ return res;
+}
+
+static PyObject *
+instancemethod_repr(PyObject *self)
+{
+ PyObject *func = PyInstanceMethod_Function(self);
+ PyObject *funcname, *result;
+ const char *defname = "?";
+
+ if (func == NULL) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+
+ if (_PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0) {
+ return NULL;
+ }
+ if (funcname != NULL && !PyUnicode_Check(funcname)) {
+ Py_DECREF(funcname);
+ funcname = NULL;
+ }
+
+ result = PyUnicode_FromFormat("<instancemethod %V at %p>",
+ funcname, defname, self);
+
+ Py_XDECREF(funcname);
+ return result;
+}
+
+/*[clinic input]
+@classmethod
+instancemethod.__new__ as instancemethod_new
+ function: object
+ /
+
+Bind a function to a class.
+[clinic start generated code]*/
+
+static PyObject *
+instancemethod_new_impl(PyTypeObject *type, PyObject *function)
+/*[clinic end generated code: output=5e0397b2bdb750be input=cfc54e8b973664a8]*/
+{
+ if (!PyCallable_Check(function)) {
+ PyErr_SetString(PyExc_TypeError,
+ "first argument must be callable");
+ return NULL;
+ }
+
+ return PyInstanceMethod_New(function);
+}
+
+PyTypeObject PyInstanceMethod_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ .tp_name = "instancemethod",
+ .tp_basicsize = sizeof(PyInstanceMethodObject),
+ .tp_dealloc = instancemethod_dealloc,
+ .tp_repr = (reprfunc)instancemethod_repr,
+ .tp_call = instancemethod_call,
+ .tp_getattro = instancemethod_getattro,
+ .tp_setattro = PyObject_GenericSetAttr,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+ .tp_doc = instancemethod_new__doc__,
+ .tp_traverse = instancemethod_traverse,
+ .tp_richcompare = instancemethod_richcompare,
+ .tp_members = instancemethod_memberlist,
+ .tp_getset = instancemethod_getset,
+ .tp_descr_get = instancemethod_descr_get,
+ .tp_new = instancemethod_new,
+};