cinap_lenrekadd hg and python4bb9e2215 years agoHistory
2580 lines · 60.9 KB · C
RawDownload
 /* Class object implementation */ #include "Python.h"#include "structmember.h" #define TP_DESCR_GET(t) \    (PyType_HasFeature(t, Py_TPFLAGS_HAVE_CLASS) ? (t)->tp_descr_get : NULL)  /* Forward */static PyObject *class_lookup(PyClassObject *, PyObject *,			      PyClassObject **);static PyObject *instance_getattr1(PyInstanceObject *, PyObject *);static PyObject *instance_getattr2(PyInstanceObject *, PyObject *); static PyObject *getattrstr, *setattrstr, *delattrstr;  PyObject *PyClass_New(PyObject *bases, PyObject *dict, PyObject *name)     /* bases is NULL or tuple of classobjects! */{	PyClassObject *op, *dummy;	static PyObject *docstr, *modstr, *namestr;	if (docstr == NULL) {		docstr= PyString_InternFromString("__doc__");		if (docstr == NULL)			return NULL;	}	if (modstr == NULL) {		modstr= PyString_InternFromString("__module__");		if (modstr == NULL)			return NULL;	}	if (namestr == NULL) {		namestr= PyString_InternFromString("__name__");		if (namestr == NULL)			return NULL;	}	if (name == NULL || !PyString_Check(name)) {		PyErr_SetString(PyExc_TypeError,				"PyClass_New: name must be a string");		return NULL;	}	if (dict == NULL || !PyDict_Check(dict)) {		PyErr_SetString(PyExc_TypeError,				"PyClass_New: dict must be a dictionary");		return NULL;	}	if (PyDict_GetItem(dict, docstr) == NULL) {		if (PyDict_SetItem(dict, docstr, Py_None) < 0)			return NULL;	}	if (PyDict_GetItem(dict, modstr) == NULL) {		PyObject *globals = PyEval_GetGlobals();		if (globals != NULL) {			PyObject *modname = PyDict_GetItem(globals, namestr);			if (modname != NULL) {				if (PyDict_SetItem(dict, modstr, modname) < 0)					return NULL;			}		}	}	if (bases == NULL) {		bases = PyTuple_New(0);		if (bases == NULL)			return NULL;	}	else {		Py_ssize_t i, n;		PyObject *base;		if (!PyTuple_Check(bases)) {			PyErr_SetString(PyExc_TypeError,					"PyClass_New: bases must be a tuple");			return NULL;		}		n = PyTuple_Size(bases);		for (i = 0; i < n; i++) {			base = PyTuple_GET_ITEM(bases, i);			if (!PyClass_Check(base)) {				if (PyCallable_Check(					(PyObject *) base->ob_type))					return PyObject_CallFunctionObjArgs(						(PyObject *) base->ob_type,						name, bases, dict, NULL);				PyErr_SetString(PyExc_TypeError,					"PyClass_New: base must be a class");				return NULL;			}		}		Py_INCREF(bases);	} 	if (getattrstr == NULL) {		getattrstr = PyString_InternFromString("__getattr__");		if (getattrstr == NULL)			goto alloc_error;		setattrstr = PyString_InternFromString("__setattr__");		if (setattrstr == NULL)			goto alloc_error;		delattrstr = PyString_InternFromString("__delattr__");		if (delattrstr == NULL)			goto alloc_error;	} 	op = PyObject_GC_New(PyClassObject, &PyClass_Type);	if (op == NULL) {alloc_error:		Py_DECREF(bases);		return NULL;	}	op->cl_bases = bases;	Py_INCREF(dict);	op->cl_dict = dict;	Py_XINCREF(name);	op->cl_name = name; 	op->cl_getattr = class_lookup(op, getattrstr, &dummy);	op->cl_setattr = class_lookup(op, setattrstr, &dummy);	op->cl_delattr = class_lookup(op, delattrstr, &dummy);	Py_XINCREF(op->cl_getattr);	Py_XINCREF(op->cl_setattr);	Py_XINCREF(op->cl_delattr);	_PyObject_GC_TRACK(op);	return (PyObject *) op;} 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;} PyObject *PyMethod_Class(PyObject *im){	if (!PyMethod_Check(im)) {		PyErr_BadInternalCall();		return NULL;	}	return ((PyMethodObject *)im)->im_class;} PyDoc_STRVAR(class_doc,"classobj(name, bases, dict)\n\\n\Create a class object.  The name must be a string; the second argument\n\a tuple of classes, and the third a dictionary."); static PyObject *class_new(PyTypeObject *type, PyObject *args, PyObject *kwds){	PyObject *name, *bases, *dict;	static char *kwlist[] = {"name", "bases", "dict", 0}; 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist,					 &name, &bases, &dict))		return NULL;	return PyClass_New(bases, dict, name);} /* Class methods */ static voidclass_dealloc(PyClassObject *op){	_PyObject_GC_UNTRACK(op);	Py_DECREF(op->cl_bases);	Py_DECREF(op->cl_dict);	Py_XDECREF(op->cl_name);	Py_XDECREF(op->cl_getattr);	Py_XDECREF(op->cl_setattr);	Py_XDECREF(op->cl_delattr);	PyObject_GC_Del(op);} static PyObject *class_lookup(PyClassObject *cp, PyObject *name, PyClassObject **pclass){	Py_ssize_t i, n;	PyObject *value = PyDict_GetItem(cp->cl_dict, name);	if (value != NULL) {		*pclass = cp;		return value;	}	n = PyTuple_Size(cp->cl_bases);	for (i = 0; i < n; i++) {		/* XXX What if one of the bases is not a class? */		PyObject *v = class_lookup(			(PyClassObject *)			PyTuple_GetItem(cp->cl_bases, i), name, pclass);		if (v != NULL)			return v;	}	return NULL;} static PyObject *class_getattr(register PyClassObject *op, PyObject *name){	register PyObject *v;	register char *sname = PyString_AsString(name);	PyClassObject *klass;	descrgetfunc f; 	if (sname[0] == '_' && sname[1] == '_') {		if (strcmp(sname, "__dict__") == 0) {			if (PyEval_GetRestricted()) {				PyErr_SetString(PyExc_RuntimeError,			   "class.__dict__ not accessible in restricted mode");				return NULL;			}			Py_INCREF(op->cl_dict);			return op->cl_dict;		}		if (strcmp(sname, "__bases__") == 0) {			Py_INCREF(op->cl_bases);			return op->cl_bases;		}		if (strcmp(sname, "__name__") == 0) {			if (op->cl_name == NULL)				v = Py_None;			else				v = op->cl_name;			Py_INCREF(v);			return v;		}	}	v = class_lookup(op, name, &klass);	if (v == NULL) {		PyErr_Format(PyExc_AttributeError,			     "class %.50s has no attribute '%.400s'",			     PyString_AS_STRING(op->cl_name), sname);		return NULL;	}	f = TP_DESCR_GET(v->ob_type);	if (f == NULL)		Py_INCREF(v);	else		v = f(v, (PyObject *)NULL, (PyObject *)op);	return v;} static voidset_slot(PyObject **slot, PyObject *v){	PyObject *temp = *slot;	Py_XINCREF(v);	*slot = v;	Py_XDECREF(temp);} static voidset_attr_slots(PyClassObject *c){	PyClassObject *dummy; 	set_slot(&c->cl_getattr, class_lookup(c, getattrstr, &dummy));	set_slot(&c->cl_setattr, class_lookup(c, setattrstr, &dummy));	set_slot(&c->cl_delattr, class_lookup(c, delattrstr, &dummy));} static char *set_dict(PyClassObject *c, PyObject *v){	if (v == NULL || !PyDict_Check(v))		return "__dict__ must be a dictionary object";	set_slot(&c->cl_dict, v);	set_attr_slots(c);	return "";} static char *set_bases(PyClassObject *c, PyObject *v){	Py_ssize_t i, n; 	if (v == NULL || !PyTuple_Check(v))		return "__bases__ must be a tuple object";	n = PyTuple_Size(v);	for (i = 0; i < n; i++) {		PyObject *x = PyTuple_GET_ITEM(v, i);		if (!PyClass_Check(x))			return "__bases__ items must be classes";		if (PyClass_IsSubclass(x, (PyObject *)c))			return "a __bases__ item causes an inheritance cycle";	}	set_slot(&c->cl_bases, v);	set_attr_slots(c);	return "";} static char *set_name(PyClassObject *c, PyObject *v){	if (v == NULL || !PyString_Check(v))		return "__name__ must be a string object";	if (strlen(PyString_AS_STRING(v)) != (size_t)PyString_GET_SIZE(v))		return "__name__ must not contain null bytes";	set_slot(&c->cl_name, v);	return "";} static intclass_setattr(PyClassObject *op, PyObject *name, PyObject *v){	char *sname;	if (PyEval_GetRestricted()) {		PyErr_SetString(PyExc_RuntimeError,			   "classes are read-only in restricted mode");		return -1;	}	sname = PyString_AsString(name);	if (sname[0] == '_' && sname[1] == '_') {		Py_ssize_t n = PyString_Size(name);		if (sname[n-1] == '_' && sname[n-2] == '_') {			char *err = NULL;			if (strcmp(sname, "__dict__") == 0)				err = set_dict(op, v);			else if (strcmp(sname, "__bases__") == 0)				err = set_bases(op, v);			else if (strcmp(sname, "__name__") == 0)				err = set_name(op, v);			else if (strcmp(sname, "__getattr__") == 0)				set_slot(&op->cl_getattr, v);			else if (strcmp(sname, "__setattr__") == 0)				set_slot(&op->cl_setattr, v);			else if (strcmp(sname, "__delattr__") == 0)				set_slot(&op->cl_delattr, v);			/* For the last three, we fall through to update the			   dictionary as well. */			if (err != NULL) {				if (*err == '\0')					return 0;				PyErr_SetString(PyExc_TypeError, err);				return -1;			}		}	}	if (v == NULL) {		int rv = PyDict_DelItem(op->cl_dict, name);		if (rv < 0)			PyErr_Format(PyExc_AttributeError,				     "class %.50s has no attribute '%.400s'",				     PyString_AS_STRING(op->cl_name), sname);		return rv;	}	else		return PyDict_SetItem(op->cl_dict, name, v);} static PyObject *class_repr(PyClassObject *op){	PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__");	char *name;	if (op->cl_name == NULL || !PyString_Check(op->cl_name))		name = "?";	else		name = PyString_AsString(op->cl_name);	if (mod == NULL || !PyString_Check(mod))		return PyString_FromFormat("<class ?.%s at %p>", name, op);	else		return PyString_FromFormat("<class %s.%s at %p>",					   PyString_AsString(mod),					   name, op);} static PyObject *class_str(PyClassObject *op){	PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__");	PyObject *name = op->cl_name;	PyObject *res;	Py_ssize_t m, n; 	if (name == NULL || !PyString_Check(name))		return class_repr(op);	if (mod == NULL || !PyString_Check(mod)) {		Py_INCREF(name);		return name;	}	m = PyString_GET_SIZE(mod);	n = PyString_GET_SIZE(name);	res = PyString_FromStringAndSize((char *)NULL, m+1+n);	if (res != NULL) {		char *s = PyString_AS_STRING(res);		memcpy(s, PyString_AS_STRING(mod), m);		s += m;		*s++ = '.';		memcpy(s, PyString_AS_STRING(name), n);	}	return res;} static intclass_traverse(PyClassObject *o, visitproc visit, void *arg){	Py_VISIT(o->cl_bases);	Py_VISIT(o->cl_dict);	Py_VISIT(o->cl_name);	Py_VISIT(o->cl_getattr);	Py_VISIT(o->cl_setattr);	Py_VISIT(o->cl_delattr);	return 0;} PyTypeObject PyClass_Type = {	PyObject_HEAD_INIT(&PyType_Type)	0,	"classobj",	sizeof(PyClassObject),	0,	(destructor)class_dealloc,		/* tp_dealloc */	0,					/* tp_print */	0,					/* tp_getattr */	0,					/* tp_setattr */	0,					/* tp_compare */	(reprfunc)class_repr,			/* tp_repr */	0,					/* tp_as_number */	0,					/* tp_as_sequence */	0,					/* tp_as_mapping */	0,					/* tp_hash */	PyInstance_New,				/* tp_call */	(reprfunc)class_str,			/* tp_str */	(getattrofunc)class_getattr,		/* tp_getattro */	(setattrofunc)class_setattr,		/* tp_setattro */	0,					/* tp_as_buffer */	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */	class_doc,				/* tp_doc */	(traverseproc)class_traverse,		/* tp_traverse */ 	0,					/* tp_clear */	0,					/* tp_richcompare */	0,					/* tp_weaklistoffset */	0,					/* tp_iter */	0,					/* tp_iternext */	0,					/* tp_methods */	0,					/* tp_members */	0,					/* tp_getset */	0,					/* tp_base */	0,					/* tp_dict */	0,					/* tp_descr_get */	0,					/* tp_descr_set */	0,					/* tp_dictoffset */	0,					/* tp_init */	0,					/* tp_alloc */	class_new,				/* tp_new */}; intPyClass_IsSubclass(PyObject *klass, PyObject *base){	Py_ssize_t i, n;	PyClassObject *cp;	if (klass == base)		return 1;	if (PyTuple_Check(base)) {		n = PyTuple_GET_SIZE(base);		for (i = 0; i < n; i++) {			if (PyClass_IsSubclass(klass, PyTuple_GET_ITEM(base, i)))				return 1;		}		return 0;	}	if (klass == NULL || !PyClass_Check(klass))		return 0;	cp = (PyClassObject *)klass;	n = PyTuple_Size(cp->cl_bases);	for (i = 0; i < n; i++) {		if (PyClass_IsSubclass(PyTuple_GetItem(cp->cl_bases, i), base))			return 1;	}	return 0;}  /* Instance objects */ PyObject *PyInstance_NewRaw(PyObject *klass, PyObject *dict){	PyInstanceObject *inst; 	if (!PyClass_Check(klass)) {		PyErr_BadInternalCall();

Lines 1–500 of 2580.