📄 classobject.c
字号:
}
/* __coerce__ returned two new values */
*pv = PyTuple_GetItem(coerced, 0);
*pw = PyTuple_GetItem(coerced, 1);
Py_INCREF(*pv);
Py_INCREF(*pw);
Py_DECREF(coerced);
return 0;
}
#ifndef SYMBIAN
#define UNARY(funcname, methodname) \
static PyObject *funcname(PyInstanceObject *self) { \
static PyObject *o; \
if (o == NULL) o = PyString_InternFromString(methodname); \
return generic_unary_op(self, o); \
}
#else
#define UNARY(funcname, methodname) \
static PyObject *funcname(PyInstanceObject *self) { \
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; \
if ((pyglobals->funcname##_o) == NULL) \
(pyglobals->funcname##_o) = PyString_InternFromString(methodname); \
return generic_unary_op(self, (pyglobals->funcname##_o)); \
}
#endif /* SYMBIAN */
#define BINARY(f, m, n) \
static PyObject *f(PyObject *v, PyObject *w) { \
return do_binop(v, w, "__" m "__", "__r" m "__", n); \
}
#define BINARY_INPLACE(f, m, n) \
static PyObject *f(PyObject *v, PyObject *w) { \
return do_binop_inplace(v, w, "__i" m "__", "__" m "__", \
"__r" m "__", n); \
}
UNARY(instance_neg, "__neg__")
UNARY(instance_pos, "__pos__")
UNARY(instance_abs, "__abs__")
BINARY(instance_or, "or", PyNumber_Or)
BINARY(instance_and, "and", PyNumber_And)
BINARY(instance_xor, "xor", PyNumber_Xor)
BINARY(instance_lshift, "lshift", PyNumber_Lshift)
BINARY(instance_rshift, "rshift", PyNumber_Rshift)
BINARY(instance_add, "add", PyNumber_Add)
BINARY(instance_sub, "sub", PyNumber_Subtract)
BINARY(instance_mul, "mul", PyNumber_Multiply)
BINARY(instance_div, "div", PyNumber_Divide)
BINARY(instance_mod, "mod", PyNumber_Remainder)
BINARY(instance_divmod, "divmod", PyNumber_Divmod)
BINARY(instance_floordiv, "floordiv", PyNumber_FloorDivide)
BINARY(instance_truediv, "truediv", PyNumber_TrueDivide)
BINARY_INPLACE(instance_ior, "or", PyNumber_InPlaceOr)
BINARY_INPLACE(instance_ixor, "xor", PyNumber_InPlaceXor)
BINARY_INPLACE(instance_iand, "and", PyNumber_InPlaceAnd)
BINARY_INPLACE(instance_ilshift, "lshift", PyNumber_InPlaceLshift)
BINARY_INPLACE(instance_irshift, "rshift", PyNumber_InPlaceRshift)
BINARY_INPLACE(instance_iadd, "add", PyNumber_InPlaceAdd)
BINARY_INPLACE(instance_isub, "sub", PyNumber_InPlaceSubtract)
BINARY_INPLACE(instance_imul, "mul", PyNumber_InPlaceMultiply)
BINARY_INPLACE(instance_idiv, "div", PyNumber_InPlaceDivide)
BINARY_INPLACE(instance_imod, "mod", PyNumber_InPlaceRemainder)
BINARY_INPLACE(instance_ifloordiv, "floordiv", PyNumber_InPlaceFloorDivide)
BINARY_INPLACE(instance_itruediv, "truediv", PyNumber_InPlaceTrueDivide)
/* Try a 3-way comparison, returning an int; v is an instance. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w;
2 if this particular 3-way comparison is not implemented or undefined.
*/
static int
half_cmp(PyObject *v, PyObject *w)
{
PyObject *args;
PyObject *cmp_func;
PyObject *result;
long l;
#ifndef SYMBIAN
static PyObject *cmp_obj;
#else
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#define cmp_obj (pyglobals->cmp_obj)
#endif
assert(PyInstance_Check(v));
if (cmp_obj == NULL) {
cmp_obj = PyString_InternFromString("__cmp__");
if (cmp_obj == NULL)
return -2;
}
cmp_func = PyObject_GetAttr(v, cmp_obj);
if (cmp_func == NULL) {
PyErr_Clear();
return 2;
}
args = Py_BuildValue("(O)", w);
if (args == NULL)
return -2;
result = PyEval_CallObject(cmp_func, args);
Py_DECREF(args);
Py_DECREF(cmp_func);
if (result == NULL)
return -2;
if (result == Py_NotImplemented) {
Py_DECREF(result);
return 2;
}
l = PyInt_AsLong(result);
Py_DECREF(result);
if (l == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"comparison did not return an int");
return -2;
}
return l < 0 ? -1 : l > 0 ? 1 : 0;
}
/* Try a 3-way comparison, returning an int; either v or w is an instance.
We first try a coercion. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w;
2 if this particular 3-way comparison is not implemented or undefined.
THIS IS ONLY CALLED FROM object.c!
*/
static int
instance_compare(PyObject *v, PyObject *w)
{
int c;
c = PyNumber_CoerceEx(&v, &w);
if (c < 0)
return -2;
if (c == 0) {
/* If neither is now an instance, use regular comparison */
if (!PyInstance_Check(v) && !PyInstance_Check(w)) {
c = PyObject_Compare(v, w);
Py_DECREF(v);
Py_DECREF(w);
if (PyErr_Occurred())
return -2;
return c < 0 ? -1 : c > 0 ? 1 : 0;
}
}
else {
/* The coercion didn't do anything.
Treat this the same as returning v and w unchanged. */
Py_INCREF(v);
Py_INCREF(w);
}
if (PyInstance_Check(v)) {
c = half_cmp(v, w);
if (c <= 1) {
Py_DECREF(v);
Py_DECREF(w);
return c;
}
}
if (PyInstance_Check(w)) {
c = half_cmp(w, v);
if (c <= 1) {
Py_DECREF(v);
Py_DECREF(w);
if (c >= -1)
c = -c;
return c;
}
}
Py_DECREF(v);
Py_DECREF(w);
return 2;
}
static int
instance_nonzero(PyInstanceObject *self)
{
PyObject *func, *res;
long outcome;
#ifndef SYMBIAN
static PyObject *nonzerostr;
#else
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#define nonzerostr (pyglobals->nonzerostr)
#endif
if (nonzerostr == NULL)
nonzerostr = PyString_InternFromString("__nonzero__");
if ((func = instance_getattr(self, nonzerostr)) == NULL) {
PyErr_Clear();
if (lenstr == NULL)
lenstr = PyString_InternFromString("__len__");
if ((func = instance_getattr(self, lenstr)) == NULL) {
PyErr_Clear();
/* Fall back to the default behavior:
all instances are nonzero */
return 1;
}
}
res = PyEval_CallObject(func, (PyObject *)NULL);
Py_DECREF(func);
if (res == NULL)
return -1;
if (!PyInt_Check(res)) {
Py_DECREF(res);
PyErr_SetString(PyExc_TypeError,
"__nonzero__ should return an int");
return -1;
}
outcome = PyInt_AsLong(res);
Py_DECREF(res);
if (outcome < 0) {
PyErr_SetString(PyExc_ValueError,
"__nonzero__ should return >= 0");
return -1;
}
return outcome > 0;
}
UNARY(instance_invert, "__invert__")
UNARY(instance_int, "__int__")
UNARY(instance_long, "__long__")
UNARY(instance_float, "__float__")
UNARY(instance_oct, "__oct__")
UNARY(instance_hex, "__hex__")
static PyObject *
bin_power(PyObject *v, PyObject *w)
{
return PyNumber_Power(v, w, Py_None);
}
/* This version is for ternary calls only (z != None) */
static PyObject *
instance_pow(PyObject *v, PyObject *w, PyObject *z)
{
if (z == Py_None) {
return do_binop(v, w, "__pow__", "__rpow__", bin_power);
}
else {
PyObject *func;
PyObject *args;
PyObject *result;
/* XXX Doesn't do coercions... */
func = PyObject_GetAttrString(v, "__pow__");
if (func == NULL)
return NULL;
args = Py_BuildValue("(OO)", w, z);
if (args == NULL) {
Py_DECREF(func);
return NULL;
}
result = PyEval_CallObject(func, args);
Py_DECREF(func);
Py_DECREF(args);
return result;
}
}
static PyObject *
bin_inplace_power(PyObject *v, PyObject *w)
{
return PyNumber_InPlacePower(v, w, Py_None);
}
static PyObject *
instance_ipow(PyObject *v, PyObject *w, PyObject *z)
{
if (z == Py_None) {
return do_binop_inplace(v, w, "__ipow__", "__pow__",
"__rpow__", bin_inplace_power);
}
else {
/* XXX Doesn't do coercions... */
PyObject *func;
PyObject *args;
PyObject *result;
func = PyObject_GetAttrString(v, "__ipow__");
if (func == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return NULL;
PyErr_Clear();
return instance_pow(v, w, z);
}
args = Py_BuildValue("(OO)", w, z);
if (args == NULL) {
Py_DECREF(func);
return NULL;
}
result = PyEval_CallObject(func, args);
Py_DECREF(func);
Py_DECREF(args);
return result;
}
}
/* Map rich comparison operators to their __xx__ namesakes */
#define NAME_OPS 6
#ifndef SYMBIAN
static PyObject **name_op = NULL;
#else
#define name_op (pyglobals->name_op)
#endif
static int
init_name_op(void)
{
int i;
char *_name_op[] = {
"__lt__",
"__le__",
"__eq__",
"__ne__",
"__gt__",
"__ge__",
};
#ifdef SYMBIAN
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
name_op = (PyObject **)PyCore_MALLOC(sizeof(PyObject *) * NAME_OPS);
if (name_op == NULL)
return -1;
for (i = 0; i < NAME_OPS; ++i) {
name_op[i] = PyString_InternFromString(_name_op[i]);
if (name_op[i] == NULL)
return -1;
}
return 0;
}
static PyObject *
half_richcompare(PyObject *v, PyObject *w, int op)
{
PyObject *method;
PyObject *args;
PyObject *res;
#ifdef SYMBIAN
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
assert(PyInstance_Check(v));
if (name_op == NULL) {
if (init_name_op() < 0)
return NULL;
}
/* If the instance doesn't define an __getattr__ method, use
instance_getattr2 directly because it will not set an
exception on failure. */
if (((PyInstanceObject *)v)->in_class->cl_getattr == NULL) {
method = instance_getattr2((PyInstanceObject *)v,
name_op[op]);
if (method == NULL) {
assert(!PyErr_Occurred());
res = Py_NotImplemented;
Py_INCREF(res);
return res;
}
} else {
method = PyObject_GetAttr(v, name_op[op]);
if (method == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return NULL;
PyErr_Clear();
res = Py_NotImplemented;
Py_INCREF(res);
return res;
}
}
args = Py_BuildValue("(O)", w);
if (args == NULL) {
Py_DECREF(method);
return NULL;
}
res = PyEval_CallObject(method, args);
Py_DECREF(args);
Py_DECREF(method);
return res;
}
/* Map rich comparison operators to their swapped version, e.g. LT --> GT */
static const int swapped_op[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
static PyObject *
instance_richcompare(PyObject *v, PyObject *w, int op)
{
PyObject *res;
if (PyInstance_Check(v)) {
res = half_richcompare(v, w, op);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
if (PyInstance_Check(w)) {
res = half_richcompare(w, v, swapped_op[op]);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
/* Get the iterator */
static PyObject *
instance_getiter(PyInstanceObject *self)
{
PyObject *func;
#ifdef SYMBIAN
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
if (iterstr == NULL)
iterstr = PyString_InternFromString("__iter__");
if (getitemstr == NULL)
getitemstr = PyString_InternFromString("__getitem__");
if ((func = instance_getattr(self, iterstr)) != NULL) {
PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);
Py_DECREF(func);
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;
}
PyErr_Clear();
if ((func = instance_getattr(self, getitemstr)) == NULL) {
PyErr_SetString(PyExc_TypeError, "iteration over non-sequence");
return NULL;
}
Py_DECREF(func);
return PySeqIter_New((PyObject *)self);
}
/* Call the iterator's next */
static PyObject *
instance_iternext(PyInstanceObject *self)
{
PyObject *func;
#ifdef SYMBIAN
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
if (nextstr == NULL)
nextstr = PyString_InternFromString("next");
if ((func = instance_getattr(self, nextstr)) != NULL) {
PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);
Py_DECREF(func);
if (res != NULL) {
return res;
}
if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
PyErr_Clear();
return NULL;
}
return NULL;
}
PyErr_SetString(PyExc_TypeError, "instance has no next() method");
return NULL;
}
static PyObject *
instance_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyThreadState *tstate = PyThreadState_GET();
PyObject *res, *call = PyObject_GetAttrString(func, "__call__");
if (call == NULL) {
PyInstanceObject *inst = (PyInstanceObject*) func;
PyErr_Clear();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -