⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 typeobject.c

📁 python s60 1.4.5版本的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				return 1;
			a = a->tp_base;
		} while (a != NULL);
		return b == &PyBaseObject_Type;
	}
}

/* Internal routines to do a method lookup in the type
   without looking in the instance dictionary
   (so we can't use PyObject_GetAttr) but still binding
   it to the instance.  The arguments are the object,
   the method name as a C string, and the address of a
   static variable used to cache the interned Python string.

   Two variants:

   - lookup_maybe() returns NULL without raising an exception
     when the _PyType_Lookup() call fails;

   - lookup_method() always raises an exception upon errors.
*/

static PyObject *
lookup_maybe(PyObject *self, char *attrstr, PyObject **attrobj)
{
	PyObject *res;

	if (*attrobj == NULL) {
		*attrobj = PyString_InternFromString(attrstr);
		if (*attrobj == NULL)
			return NULL;
	}
	res = _PyType_Lookup(self->ob_type, *attrobj);
	if (res != NULL) {
		descrgetfunc f;
		if ((f = res->ob_type->tp_descr_get) == NULL)
			Py_INCREF(res);
		else
			res = f(res, self, (PyObject *)(self->ob_type));
	}
	return res;
}

static PyObject *
lookup_method(PyObject *self, char *attrstr, PyObject **attrobj)
{
	PyObject *res = lookup_maybe(self, attrstr, attrobj);
	if (res == NULL && !PyErr_Occurred())
		PyErr_SetObject(PyExc_AttributeError, *attrobj);
	return res;
}

/* A variation of PyObject_CallMethod that uses lookup_method()
   instead of PyObject_GetAttrString().  This uses the same convention
   as lookup_method to cache the interned name string object. */

static PyObject *
call_method(PyObject *o, char *name, PyObject **nameobj, char *format, ...)
{
	va_list va;
	PyObject *args, *func = 0, *retval;
	va_start(va, format);

	func = lookup_maybe(o, name, nameobj);
	if (func == NULL) {
		va_end(va);
		if (!PyErr_Occurred())
			PyErr_SetObject(PyExc_AttributeError, *nameobj);
		return NULL;
	}

	if (format && *format)
		args = Py_VaBuildValue(format, va);
	else
		args = PyTuple_New(0);

	va_end(va);

	if (args == NULL)
		return NULL;

	assert(PyTuple_Check(args));
	retval = PyObject_Call(func, args, NULL);

	Py_DECREF(args);
	Py_DECREF(func);

	return retval;
}

/* Clone of call_method() that returns NotImplemented when the lookup fails. */

static PyObject *
call_maybe(PyObject *o, char *name, PyObject **nameobj, char *format, ...)
{
	va_list va;
	PyObject *args, *func = 0, *retval;
	va_start(va, format);

	func = lookup_maybe(o, name, nameobj);
	if (func == NULL) {
		va_end(va);
		if (!PyErr_Occurred()) {
			Py_INCREF(Py_NotImplemented);
			return Py_NotImplemented;
		}
		return NULL;
	}

	if (format && *format)
		args = Py_VaBuildValue(format, va);
	else
		args = PyTuple_New(0);

	va_end(va);

	if (args == NULL)
		return NULL;

	assert(PyTuple_Check(args));
	retval = PyObject_Call(func, args, NULL);

	Py_DECREF(args);
	Py_DECREF(func);

	return retval;
}

/* Method resolution order algorithm from "Putting Metaclasses to Work"
   by Forman and Danforth (Addison-Wesley 1999). */

static int
conservative_merge(PyObject *left, PyObject *right)
{
	int left_size;
	int right_size;
	int i, j, r, ok;
	PyObject *temp, *rr;

	assert(PyList_Check(left));
	assert(PyList_Check(right));

  again:
	left_size = PyList_GET_SIZE(left);
	right_size = PyList_GET_SIZE(right);
	for (i = 0; i < left_size; i++) {
		for (j = 0; j < right_size; j++) {
			if (PyList_GET_ITEM(left, i) ==
			    PyList_GET_ITEM(right, j)) {
				/* found a merge point */
				temp = PyList_New(0);
				if (temp == NULL)
					return -1;
				for (r = 0; r < j; r++) {
					rr = PyList_GET_ITEM(right, r);
					ok = PySequence_Contains(left, rr);
					if (ok < 0) {
						Py_DECREF(temp);
						return -1;
					}
					if (!ok) {
						ok = PyList_Append(temp, rr);
						if (ok < 0) {
							Py_DECREF(temp);
							return -1;
						}
					}
				}
				ok = PyList_SetSlice(left, i, i, temp);
				Py_DECREF(temp);
				if (ok < 0)
					return -1;
				ok = PyList_SetSlice(right, 0, j+1, NULL);
				if (ok < 0)
					return -1;
				goto again;
			}
		}
	}
	return PyList_SetSlice(left, left_size, left_size, right);
}

static int
serious_order_disagreements(PyObject *left, PyObject *right)
{
	return 0; /* XXX later -- for now, we cheat: "don't do that" */
}

static int
fill_classic_mro(PyObject *mro, PyObject *cls)
{
	PyObject *bases, *base;
	int i, n;

	assert(PyList_Check(mro));
	assert(PyClass_Check(cls));
	i = PySequence_Contains(mro, cls);
	if (i < 0)
		return -1;
	if (!i) {
		if (PyList_Append(mro, cls) < 0)
			return -1;
	}
	bases = ((PyClassObject *)cls)->cl_bases;
	assert(bases && PyTuple_Check(bases));
	n = PyTuple_GET_SIZE(bases);
	for (i = 0; i < n; i++) {
		base = PyTuple_GET_ITEM(bases, i);
		if (fill_classic_mro(mro, base) < 0)
			return -1;
	}
	return 0;
}

static PyObject *
classic_mro(PyObject *cls)
{
	PyObject *mro;

	assert(PyClass_Check(cls));
	mro = PyList_New(0);
	if (mro != NULL) {
		if (fill_classic_mro(mro, cls) == 0)
			return mro;
		Py_DECREF(mro);
	}
	return NULL;
}

static PyObject *
mro_implementation(PyTypeObject *type)
{
	int i, n, ok;
	PyObject *bases, *result;

	if(type->tp_dict == NULL) {
		if(PyType_Ready(type) < 0)
			return NULL;
	}

	bases = type->tp_bases;
	n = PyTuple_GET_SIZE(bases);
	result = Py_BuildValue("[O]", (PyObject *)type);
	if (result == NULL)
		return NULL;
	for (i = 0; i < n; i++) {
		PyObject *base = PyTuple_GET_ITEM(bases, i);
		PyObject *parentMRO;
		if (PyType_Check(base))
			parentMRO = PySequence_List(
				((PyTypeObject*)base)->tp_mro);
		else
			parentMRO = classic_mro(base);
		if (parentMRO == NULL) {
			Py_DECREF(result);
			return NULL;
		}
		if (serious_order_disagreements(result, parentMRO)) {
			Py_DECREF(result);
			return NULL;
		}
		ok = conservative_merge(result, parentMRO);
		Py_DECREF(parentMRO);
		if (ok < 0) {
			Py_DECREF(result);
			return NULL;
		}
	}
	return result;
}

static PyObject *
mro_external(PyObject *self)
{
	PyTypeObject *type = (PyTypeObject *)self;

	return mro_implementation(type);
}

static int
mro_internal(PyTypeObject *type)
{
	PyObject *mro, *result, *tuple;

	if (type->ob_type == &PyType_Type) {
		result = mro_implementation(type);
	}
	else {
#ifndef SYMBIAN
		static PyObject *mro_str;
#else
#define mro_str (PYTHON_GLOBALS->mro_str)
#endif
		mro = lookup_method((PyObject *)type, "mro", &mro_str);
		if (mro == NULL)
			return -1;
		result = PyObject_CallObject(mro, NULL);
		Py_DECREF(mro);
	}
	if (result == NULL)
		return -1;
	tuple = PySequence_Tuple(result);
	Py_DECREF(result);
	type->tp_mro = tuple;
	return 0;
}


/* Calculate the best base amongst multiple base classes.
   This is the first one that's on the path to the "solid base". */

static PyTypeObject *
best_base(PyObject *bases)
{
	int i, n;
	PyTypeObject *base, *winner, *candidate, *base_i;
	PyObject *base_proto;

	assert(PyTuple_Check(bases));
	n = PyTuple_GET_SIZE(bases);
	assert(n > 0);
	base = NULL;
	winner = NULL;
	for (i = 0; i < n; i++) {
		base_proto = PyTuple_GET_ITEM(bases, i);
		if (PyClass_Check(base_proto))
			continue;
		if (!PyType_Check(base_proto)) {
			PyErr_SetString(
				PyExc_TypeError,
				"bases must be types");
			return NULL;
		}
		base_i = (PyTypeObject *)base_proto;
		if (base_i->tp_dict == NULL) {
			if (PyType_Ready(base_i) < 0)
				return NULL;
		}
		candidate = solid_base(base_i);
		if (winner == NULL) {
			winner = candidate;
			base = base_i;
		}
		else if (PyType_IsSubtype(winner, candidate))
			;
		else if (PyType_IsSubtype(candidate, winner)) {
			winner = candidate;
			base = base_i;
		}
		else {
			PyErr_SetString(
				PyExc_TypeError,
				"multiple bases have "
				"instance lay-out conflict");
			return NULL;
		}
	}
	if (base == NULL)
		PyErr_SetString(PyExc_TypeError,
			"a new-style class can't have only classic bases");
	return base;
}

static int
extra_ivars(PyTypeObject *type, PyTypeObject *base)
{
	size_t t_size = type->tp_basicsize;
	size_t b_size = base->tp_basicsize;

	assert(t_size >= b_size); /* Else type smaller than base! */
	if (type->tp_itemsize || base->tp_itemsize) {
		/* If itemsize is involved, stricter rules */
		return t_size != b_size ||
			type->tp_itemsize != base->tp_itemsize;
	}
	if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 &&
	    type->tp_weaklistoffset + sizeof(PyObject *) == t_size)
		t_size -= sizeof(PyObject *);
	if (type->tp_dictoffset && base->tp_dictoffset == 0 &&
	    type->tp_dictoffset + sizeof(PyObject *) == t_size)
		t_size -= sizeof(PyObject *);

	return t_size != b_size;
}

static PyTypeObject *
solid_base(PyTypeObject *type)
{
	PyTypeObject *base;

	if (type->tp_base)
		base = solid_base(type->tp_base);
	else
		base = &PyBaseObject_Type;
	if (extra_ivars(type, base))
		return type;
	else
		return base;
}

staticforward void object_dealloc(PyObject *);
staticforward int object_init(PyObject *, PyObject *, PyObject *);
staticforward int update_slot(PyTypeObject *, PyObject *);
staticforward void fixup_slot_dispatchers(PyTypeObject *);

static PyObject *
subtype_dict(PyObject *obj, void *context)
{
	PyObject **dictptr = _PyObject_GetDictPtr(obj);
	PyObject *dict;

	if (dictptr == NULL) {
		PyErr_SetString(PyExc_AttributeError,
				"This object has no __dict__");
		return NULL;
	}
	dict = *dictptr;
	if (dict == NULL)
		*dictptr = dict = PyDict_New();
	Py_XINCREF(dict);
	return dict;
}

static int
subtype_setdict(PyObject *obj, PyObject *value, void *context)
{
	PyObject **dictptr = _PyObject_GetDictPtr(obj);
	PyObject *dict;

	if (dictptr == NULL) {
		PyErr_SetString(PyExc_AttributeError,
				"This object has no __dict__");
		return -1;
	}
	if (value != NULL && !PyDict_Check(value)) {
		PyErr_SetString(PyExc_TypeError,
				"__dict__ must be set to a dictionary");
		return -1;
	}
	dict = *dictptr;
	Py_XINCREF(value);
	*dictptr = value;
	Py_XDECREF(dict);
	return 0;
}

const static PyGetSetDef subtype_getsets[] = {
	{"__dict__", subtype_dict, subtype_setdict, NULL},
	{0},
};

/* bozo: __getstate__ that raises TypeError */

static PyObject *
bozo_func(PyObject *self, PyObject *args)
{
	PyErr_SetString(PyExc_TypeError,
			"a class that defines __slots__ without "
			"defining __getstate__ cannot be pickled");
	return NULL;
}

const static PyMethodDef bozo_ml = {"__getstate__", bozo_func};

#ifndef SYMBIAN
static PyObject *bozo_obj = NULL;
#else
#define bozo_obj (PYTHON_GLOBALS->bozo_obj)
#endif

static PyObject *
type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
{
	PyObject *name, *bases, *dict;
	static const char *const kwlist[] = {"name", "bases", "dict", 0};
	PyObject *slots, *tmp;
	PyTypeObject *type, *base, *tmptype, *winner;
	etype *et;
	PyMemberDef *mp;
	int i, nbases, nslots, slotoffset, add_dict, add_weak;

	assert(args != NULL && PyTuple_Check(args));
	assert(kwds == NULL || PyDict_Check(kwds));

	/* Special case: type(x) should return x->ob_type */
	{
		const int nargs = PyTuple_GET_SIZE(args);
		const int nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);

		if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {
			PyObject *x = PyTuple_GET_ITEM(args, 0);
			Py_INCREF(x->ob_type);
			return (PyObject *) x->ob_type;
		}

		/* SF bug 475327 -- if that didn't trigger, we need 3
		   arguments. but PyArg_ParseTupleAndKeywords below may give
		   a msg saying type() needs exactly 3. */
		if (nargs + nkwds != 3) {
			PyErr_SetString(PyExc_TypeError,
					"type() takes 1 or 3 arguments");
			return NULL;
		}
	}

	/* Check arguments: (name, bases, dict) */
	if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:type", kwlist,
					 &name,
					 &PyTuple_Type, &bases,
					 &PyDict_Type, &dict))
		return NULL;

	/* Determine the proper metatype to deal with this,
	   and check for metatype conflicts while we're at it.
	   Note that if some other metatype wins to contract,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -