📄 abstract.c
字号:
/* Operations on mappings */
DL_EXPORT(int)
PyMapping_Check(PyObject *o)
{
return o && o->ob_type->tp_as_mapping &&
o->ob_type->tp_as_mapping->mp_subscript;
}
DL_EXPORT(int)
PyMapping_Size(PyObject *o)
{
PyMappingMethods *m;
if (o == NULL) {
null_error();
return -1;
}
// XXX:CW32
m = (PyMappingMethods *)o->ob_type->tp_as_mapping;
if (m && m->mp_length)
return m->mp_length(o);
type_error("len() of unsized object");
return -1;
}
#undef PyMapping_Length
DL_EXPORT(int)
PyMapping_Length(PyObject *o)
{
return PyMapping_Size(o);
}
#define PyMapping_Length PyMapping_Size
DL_EXPORT(PyObject *)
PyMapping_GetItemString(PyObject *o, char *key)
{
PyObject *okey, *r;
if (key == NULL)
return null_error();
okey = PyString_FromString(key);
if (okey == NULL)
return NULL;
r = PyObject_GetItem(o, okey);
Py_DECREF(okey);
return r;
}
DL_EXPORT(int)
PyMapping_SetItemString(PyObject *o, char *key, PyObject *value)
{
PyObject *okey;
int r;
if (key == NULL) {
null_error();
return -1;
}
okey = PyString_FromString(key);
if (okey == NULL)
return -1;
r = PyObject_SetItem(o, okey, value);
Py_DECREF(okey);
return r;
}
DL_EXPORT(int)
PyMapping_HasKeyString(PyObject *o, char *key)
{
PyObject *v;
v = PyMapping_GetItemString(o, key);
if (v) {
Py_DECREF(v);
return 1;
}
PyErr_Clear();
return 0;
}
DL_EXPORT(int)
PyMapping_HasKey(PyObject *o, PyObject *key)
{
PyObject *v;
v = PyObject_GetItem(o, key);
if (v) {
Py_DECREF(v);
return 1;
}
PyErr_Clear();
return 0;
}
/* Operations on callable objects */
/* XXX PyCallable_Check() is in object.c */
DL_EXPORT(PyObject *)
PyObject_CallObject(PyObject *o, PyObject *a)
{
return PyEval_CallObjectWithKeywords(o, a, NULL);
}
DL_EXPORT(PyObject *)
PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
ternaryfunc call;
if ((call = func->ob_type->tp_call) != NULL) {
PyObject *result = (*call)(func, arg, kw);
if (result == NULL && !PyErr_Occurred())
PyErr_SetString(
PyExc_SystemError,
"NULL result without error in PyObject_Call");
return result;
}
PyErr_Format(PyExc_TypeError, "'%s' object is not callable",
func->ob_type->tp_name);
return NULL;
}
DL_EXPORT(PyObject *)
PyObject_CallFunction(PyObject *callable, char *format, ...)
{
va_list va;
PyObject *args, *retval;
if (callable == NULL)
return null_error();
if (format && *format) {
va_start(va, format);
args = Py_VaBuildValue(format, va);
va_end(va);
}
else
args = PyTuple_New(0);
if (args == NULL)
return NULL;
if (!PyTuple_Check(args)) {
PyObject *a;
a = PyTuple_New(1);
if (a == NULL)
return NULL;
if (PyTuple_SetItem(a, 0, args) < 0)
return NULL;
args = a;
}
retval = PyObject_CallObject(callable, args);
Py_DECREF(args);
return retval;
}
DL_EXPORT(PyObject *)
PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
{
va_list va;
PyObject *args, *func = 0, *retval;
if (o == NULL || name == NULL)
return null_error();
func = PyObject_GetAttrString(o, name);
if (func == NULL) {
PyErr_SetString(PyExc_AttributeError, name);
return 0;
}
if (!PyCallable_Check(func))
return type_error("call of non-callable attribute");
if (format && *format) {
va_start(va, format);
args = Py_VaBuildValue(format, va);
va_end(va);
}
else
args = PyTuple_New(0);
if (!args)
return NULL;
if (!PyTuple_Check(args)) {
PyObject *a;
a = PyTuple_New(1);
if (a == NULL)
return NULL;
if (PyTuple_SetItem(a, 0, args) < 0)
return NULL;
args = a;
}
retval = PyObject_CallObject(func, args);
Py_DECREF(args);
Py_DECREF(func);
return retval;
}
static PyObject *
objargs_mktuple(va_list va)
{
int i, n = 0;
va_list countva;
PyObject *result, *tmp;
#ifdef VA_LIST_IS_ARRAY
memcpy(countva, va, sizeof(va_list));
#else
#ifdef __va_copy
__va_copy(countva, va);
#else
countva = va;
#endif
#endif
while (((PyObject *)va_arg(countva, PyObject *)) != NULL)
++n;
result = PyTuple_New(n);
if (result != NULL && n > 0) {
for (i = 0; i < n; ++i) {
tmp = (PyObject *)va_arg(va, PyObject *);
PyTuple_SET_ITEM(result, i, tmp);
Py_INCREF(tmp);
}
}
return result;
}
DL_EXPORT(PyObject *)
PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
{
PyObject *args, *tmp;
va_list vargs;
if (callable == NULL || name == NULL)
return null_error();
callable = PyObject_GetAttr(callable, name);
if (callable == NULL)
return NULL;
/* count the args */
va_start(vargs, name);
args = objargs_mktuple(vargs);
va_end(vargs);
if (args == NULL) {
Py_DECREF(callable);
return NULL;
}
tmp = PyObject_Call(callable, args, NULL);
Py_DECREF(args);
Py_DECREF(callable);
return tmp;
}
DL_EXPORT(PyObject *)
PyObject_CallFunctionObjArgs(PyObject *callable, ...)
{
PyObject *args, *tmp;
va_list vargs;
if (callable == NULL)
return null_error();
/* count the args */
va_start(vargs, callable);
args = objargs_mktuple(vargs);
va_end(vargs);
if (args == NULL)
return NULL;
tmp = PyObject_Call(callable, args, NULL);
Py_DECREF(args);
return tmp;
}
/* isinstance(), issubclass() */
/* abstract_get_bases() has logically 4 return states, with a sort of 0th
* state that will almost never happen.
*
* 0. creating the __bases__ static string could get a MemoryError
* 1. getattr(cls, '__bases__') could raise an AttributeError
* 2. getattr(cls, '__bases__') could raise some other exception
* 3. getattr(cls, '__bases__') could return a tuple
* 4. getattr(cls, '__bases__') could return something other than a tuple
*
* Only state #3 is a non-error state and only it returns a non-NULL object
* (it returns the retrieved tuple).
*
* Any raised AttributeErrors are masked by clearing the exception and
* returning NULL. If an object other than a tuple comes out of __bases__,
* then again, the return value is NULL. So yes, these two situations
* produce exactly the same results: NULL is returned and no error is set.
*
* If some exception other than AttributeError is raised, then NULL is also
* returned, but the exception is not cleared. That's because we want the
* exception to be propagated along.
*
* Callers are expected to test for PyErr_Occurred() when the return value
* is NULL to decide whether a valid exception should be propagated or not.
* When there's no exception to propagate, it's customary for the caller to
* set a TypeError.
*/
static PyObject *
abstract_get_bases(PyObject *cls)
{
#ifndef SYMBIAN
static PyObject *s__bases__ = NULL;
#else
#define s__bases__ (PYTHON_GLOBALS->__bases__)
#endif
PyObject *bases;
if (s__bases__ == NULL) {
s__bases__ = PyString_FromString("__bases__");
if (s__bases__ == NULL)
return NULL;
}
bases = PyObject_GetAttr(cls, s__bases__);
if (bases == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
return NULL;
}
if (!PyTuple_Check(bases)) {
Py_DECREF(bases);
return NULL;
}
return bases;
}
static int
abstract_issubclass(PyObject *derived, PyObject *cls)
{
PyObject *bases;
int i, n;
int r = 0;
if (derived == cls)
return 1;
bases = abstract_get_bases(derived);
if (bases == NULL) {
if (PyErr_Occurred())
return -1;
return 0;
}
n = PyTuple_GET_SIZE(bases);
for (i = 0; i < n; i++) {
r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls);
if (r != 0)
break;
}
Py_DECREF(bases);
return r;
}
DL_EXPORT(int)
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
PyObject *icls;
#ifndef SYMBIAN
static PyObject *s__class__ = NULL;
#else
#define s__class__ (PYTHON_GLOBALS->__class__)
#endif
int retval = 0;
if (PyClass_Check(cls) && PyInstance_Check(inst)) {
PyObject *inclass =
(PyObject*)((PyInstanceObject*)inst)->in_class;
retval = PyClass_IsSubclass(inclass, cls);
}
else if (PyType_Check(cls)) {
retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
}
else if (PyTuple_Check(cls)) {
/* Not a general sequence -- that opens up the road to
recursion and stack overflow. */
int i, n;
n = PyTuple_GET_SIZE(cls);
for (i = 0; i < n; i++) {
retval = PyObject_IsInstance(
inst, PyTuple_GET_ITEM(cls, i));
if (retval != 0)
break;
}
return retval;
}
else {
PyObject *cls_bases = abstract_get_bases(cls);
if (cls_bases == NULL) {
/* Do not mask errors. */
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError,
"isinstance() arg 2 must be a class, type,"
" or tuple of classes and types");
return -1;
}
Py_DECREF(cls_bases);
if (s__class__ == NULL) {
s__class__ = PyString_FromString("__class__");
if (s__class__ == NULL)
return -1;
}
icls = PyObject_GetAttr(inst, s__class__);
if (icls == NULL) {
PyErr_Clear();
retval = 0;
}
else {
retval = abstract_issubclass(icls, cls);
Py_DECREF(icls);
}
}
return retval;
}
DL_EXPORT(int)
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
{
int retval;
if (!PyClass_Check(derived) || !PyClass_Check(cls)) {
PyObject *derived_bases;
PyObject *cls_bases;
derived_bases = abstract_get_bases(derived);
if (derived_bases == NULL) {
/* Do not mask errors */
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError,
"issubclass() arg 1 must be a class");
return -1;
}
Py_DECREF(derived_bases);
cls_bases = abstract_get_bases(cls);
if (cls_bases == NULL) {
/* Do not mask errors */
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError,
"issubclass() arg 2 must be a class");
return -1;
}
Py_DECREF(cls_bases);
retval = abstract_issubclass(derived, cls);
}
else {
/* shortcut */
if (!(retval = (derived == cls)))
retval = PyClass_IsSubclass(derived, cls);
}
return retval;
}
DL_EXPORT(PyObject *)
PyObject_GetIter(PyObject *o)
{
PyTypeObject *t = o->ob_type;
getiterfunc f = NULL;
if (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER))
f = t->tp_iter;
if (f == NULL) {
if (PySequence_Check(o))
return PySeqIter_New(o);
PyErr_SetString(PyExc_TypeError,
"iteration over non-sequence");
return NULL;
}
else {
PyObject *res = (*f)(o);
if (res != NULL && !PyIter_Check(res)) {
PyErr_Format(PyExc_TypeError,
"iter() returned non-iterator "
"of type '%.100s'",
res->ob_type->tp_name);
Py_DECREF(res);
res = NULL;
}
return res;
}
}
/* Return next item.
* If an error occurs, return NULL. PyErr_Occurred() will be true.
* If the iteration terminates normally, return NULL and clear the
* PyExc_StopIteration exception (if it was set). PyErr_Occurred()
* will be false.
* Else return the next object. PyErr_Occurred() will be false.
*/
DL_EXPORT(PyObject *)
PyIter_Next(PyObject *iter)
{
PyObject *result;
if (!PyIter_Check(iter)) {
PyErr_Format(PyExc_TypeError,
"'%.100s' object is not an iterator",
iter->ob_type->tp_name);
return NULL;
}
result = (*iter->ob_type->tp_iternext)(iter);
if (result == NULL &&
PyErr_Occurred() &&
PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -