[Zope-Checkins] CVS: Zope3/lib/python/Zope/Security - _Proxy.c:1.1.2.14
Guido van Rossum
guido@python.org
Thu, 25 Apr 2002 22:31:06 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Security
In directory cvs.zope.org:/tmp/cvs-serv17346
Modified Files:
Tag: SecurityProxy-branch
_Proxy.c
Log Message:
- Add pow().
- Add inplace operators.
- Add coerce().
- Fold some long lines.
- Rearrange some code.
- Tidy up the proxy_as_number initializer.
=== Zope3/lib/python/Zope/Security/_Proxy.c 1.1.2.13 => 1.1.2.14 ===
}
-#define BINOP(NAME, CALL) \
- static PyObject *proxy_##NAME(PyObject *self, PyObject *other) \
- { return check2(self, other, "__" #NAME "__", "__r" #NAME "__", CALL); }
+static PyObject *
+check2i(ProxyObject *self, PyObject *other,
+ char *opname, binaryfunc operation)
+{
+ PyObject *result = NULL;
+ PyObject *object = self->proxy_object;
+ PyObject *checker = self->proxy_checker;
+
+ if (check(checker, opname, object)) {
+ result = operation(object, other);
+ if (result == object) {
+ /* If the operation was really carried out inplace,
+ don't create a new proxy, but use the old one. */
+ Py_DECREF(object);
+ Py_INCREF(self);
+ result = (PyObject *)self;
+ }
+ else if (result != NULL)
+ result = PyObject_CallMethod(checker, "proxy",
+ "(N)", result);
+ }
+ return result;
+}
#define UNOP(NAME, CALL) \
static PyObject *proxy_##NAME(PyObject *self) \
- { return check1((ProxyObject *)self, "__" #NAME "__", CALL); }
+ { return check1((ProxyObject *)self, "__"#NAME"__", CALL); }
+
+#define BINOP(NAME, CALL) \
+ static PyObject *proxy_##NAME(PyObject *self, PyObject *other) \
+ { return check2(self, other, "__"#NAME"__", "__r"#NAME"__", CALL); }
+
+#define INPLACE(NAME, CALL) \
+ static PyObject *proxy_i##NAME(PyObject *self, PyObject *other) \
+ { return check2i((ProxyObject *)self, other, "__i"#NAME"__", CALL); }
/*
@@ -291,7 +319,8 @@
{
PyNumberMethods *nb = self->ob_type->tp_as_number;
if (nb == NULL || nb->nb_int == NULL) {
- PyErr_SetString(PyExc_TypeError, "object can't be converted to int");
+ PyErr_SetString(PyExc_TypeError,
+ "object can't be converted to int");
return NULL;
}
return nb->nb_int(self);
@@ -302,7 +331,8 @@
{
PyNumberMethods *nb = self->ob_type->tp_as_number;
if (nb == NULL || nb->nb_long == NULL) {
- PyErr_SetString(PyExc_TypeError, "object can't be converted to long");
+ PyErr_SetString(PyExc_TypeError,
+ "object can't be converted to long");
return NULL;
}
return nb->nb_long(self);
@@ -313,7 +343,8 @@
{
PyNumberMethods *nb = self->ob_type->tp_as_number;
if (nb == NULL || nb->nb_float== NULL) {
- PyErr_SetString(PyExc_TypeError, "object can't be converted to float");
+ PyErr_SetString(PyExc_TypeError,
+ "object can't be converted to float");
return NULL;
}
return nb->nb_float(self);
@@ -324,7 +355,8 @@
{
PyNumberMethods *nb = self->ob_type->tp_as_number;
if (nb == NULL || nb->nb_oct== NULL) {
- PyErr_SetString(PyExc_TypeError, "object can't be converted to oct");
+ PyErr_SetString(PyExc_TypeError,
+ "object can't be converted to oct");
return NULL;
}
return nb->nb_oct(self);
@@ -335,24 +367,118 @@
{
PyNumberMethods *nb = self->ob_type->tp_as_number;
if (nb == NULL || nb->nb_hex == NULL) {
- PyErr_SetString(PyExc_TypeError, "object can't be converted to hex");
+ PyErr_SetString(PyExc_TypeError,
+ "object can't be converted to hex");
return NULL;
}
return nb->nb_hex(self);
}
+static PyObject *
+call_ipow(PyObject *self, PyObject *other)
+{
+ /* PyNumber_InPlacePower has three args. How silly. :-) */
+ return PyNumber_InPlacePower(self, other, Py_None);
+}
+
BINOP(add, PyNumber_Add)
BINOP(sub, PyNumber_Subtract)
BINOP(mul, PyNumber_Multiply)
BINOP(div, PyNumber_Divide)
BINOP(mod, PyNumber_Remainder)
BINOP(divmod, PyNumber_Divmod)
-#define proxy_pow 0
+
+static PyObject *
+proxy_pow(PyObject *self, PyObject *other, PyObject *modulus)
+{
+ PyObject *result = NULL;
+ PyObject *object;
+ PyObject *checker;
+
+ if (Proxy_Check(self)) {
+ object = Proxy_GetObject(self);
+ checker = Proxy_GetChecker(self);
+ if (check(checker, "__pow__", object))
+ result = PyNumber_Power(object, other, modulus);
+ }
+ else if (Proxy_Check(other)) {
+ object = Proxy_GetObject(other);
+ checker = Proxy_GetChecker(other);
+ if (check(checker, "__rpow__", object))
+ result = PyNumber_Power(self, object, modulus);
+ }
+ else if (modulus != NULL && Proxy_Check(modulus)) {
+ object = Proxy_GetObject(modulus);
+ checker = Proxy_GetChecker(modulus);
+ if (check(checker, "__3pow__", object))
+ result = PyNumber_Power(self, other, modulus);
+ }
+ else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ if (result != NULL)
+ result = PyObject_CallMethod(checker, "proxy", "(N)", result);
+ return result;
+}
+
BINOP(lshift, PyNumber_Lshift)
BINOP(rshift, PyNumber_Rshift)
BINOP(and, PyNumber_And)
BINOP(xor, PyNumber_Xor)
BINOP(or, PyNumber_Or)
+
+static int
+proxy_coerce(PyObject **p_self, PyObject **p_other)
+{
+ PyObject *self = *p_self;
+ PyObject *other = *p_other;
+ PyObject *object;
+ PyObject *checker;
+
+ assert(Proxy_Check(self));
+ object = Proxy_GetObject(self);
+ checker = Proxy_GetChecker(self);
+
+ if (check(checker, "__coerce__", object)) {
+ PyObject *left = object;
+ PyObject *right = other;
+ int r;
+ r = PyNumber_CoerceEx(&left, &right);
+ if (r != 0)
+ return r;
+ /* Now left and right have been INCREF'ed.
+ Any new value that comes out is proxied;
+ any unchanged value is left unchanged. */
+ if (left == object) {
+ /* Keep the old proxy */
+ Py_DECREF(left);
+ Py_INCREF(self);
+ left = self;
+ }
+ else {
+ left = PyObject_CallMethod(checker, "proxy",
+ "(N)", left);
+ if (left == NULL) {
+ Py_DECREF(right);
+ return -1;
+ }
+ }
+ if (right != other) {
+ right = PyObject_CallMethod(checker, "proxy",
+ "(N)", right);
+ if (right == NULL) {
+ Py_DECREF(left);
+ return -1;
+ }
+ }
+ *p_self = left;
+ *p_other = right;
+ return 0;
+ }
+ return -1;
+}
+
UNOP(neg, PyNumber_Negative)
UNOP(pos, PyNumber_Positive)
UNOP(abs, PyNumber_Absolute)
@@ -375,22 +501,22 @@
UNOP(oct, call_oct)
UNOP(hex, call_hex)
-#define proxy_inplace_add 0
-#define proxy_inplace_subtract 0
-#define proxy_inplace_multiply 0
-#define proxy_inplace_divide 0
-#define proxy_inplace_remainder 0
-#define proxy_inplace_power 0
-#define proxy_inplace_lshift 0
-#define proxy_inplace_rshift 0
-#define proxy_inplace_and 0
-#define proxy_inplace_xor 0
-#define proxy_inplace_or 0
-
-BINOP(floor_divide, PyNumber_FloorDivide)
-BINOP(true_divide, PyNumber_TrueDivide)
-#define proxy_inplace_floor_divide 0
-#define proxy_inplace_true_divide 0
+INPLACE(add, PyNumber_InPlaceAdd)
+INPLACE(sub, PyNumber_InPlaceSubtract)
+INPLACE(mul, PyNumber_InPlaceMultiply)
+INPLACE(div, PyNumber_InPlaceDivide)
+INPLACE(mod, PyNumber_InPlaceRemainder)
+INPLACE(pow, call_ipow)
+INPLACE(lshift, PyNumber_InPlaceLshift)
+INPLACE(rshift, PyNumber_InPlaceRshift)
+INPLACE(and, PyNumber_InPlaceAnd)
+INPLACE(xor, PyNumber_InPlaceXor)
+INPLACE(or, PyNumber_InPlaceOr)
+
+BINOP(floordiv, PyNumber_FloorDivide)
+BINOP(truediv, PyNumber_TrueDivide)
+INPLACE(floordiv, PyNumber_InPlaceFloorDivide)
+INPLACE(truediv, PyNumber_InPlaceTrueDivide)
/*
* Sequence methods.
@@ -484,50 +610,50 @@
static PyNumberMethods
proxy_as_number = {
- proxy_add, /* nb_add */
- proxy_sub, /* nb_subtract */
- proxy_mul, /* nb_multiply */
- proxy_div, /* nb_divide */
- proxy_mod, /* nb_remainder */
- proxy_divmod, /* nb_divmod */
- proxy_pow, /* nb_power */
- proxy_neg, /* nb_negative */
- proxy_pos, /* nb_positive */
- proxy_abs, /* nb_absolute */
- proxy_nonzero, /* nb_nonzero */
- proxy_invert, /* nb_invert */
- proxy_lshift, /* nb_lshift */
- proxy_rshift, /* nb_rshift */
- proxy_and, /* nb_and */
- proxy_xor, /* nb_xor */
- proxy_or, /* nb_or */
- 0, /* nb_coerce */
- proxy_int, /* nb_int */
- proxy_long, /* nb_long */
- proxy_float, /* nb_float */
- proxy_oct, /* nb_oct */
- proxy_hex, /* nb_hex */
+ proxy_add, /* nb_add */
+ proxy_sub, /* nb_subtract */
+ proxy_mul, /* nb_multiply */
+ proxy_div, /* nb_divide */
+ proxy_mod, /* nb_remainder */
+ proxy_divmod, /* nb_divmod */
+ proxy_pow, /* nb_power */
+ proxy_neg, /* nb_negative */
+ proxy_pos, /* nb_positive */
+ proxy_abs, /* nb_absolute */
+ proxy_nonzero, /* nb_nonzero */
+ proxy_invert, /* nb_invert */
+ proxy_lshift, /* nb_lshift */
+ proxy_rshift, /* nb_rshift */
+ proxy_and, /* nb_and */
+ proxy_xor, /* nb_xor */
+ proxy_or, /* nb_or */
+ proxy_coerce, /* nb_coerce */
+ proxy_int, /* nb_int */
+ proxy_long, /* nb_long */
+ proxy_float, /* nb_float */
+ proxy_oct, /* nb_oct */
+ proxy_hex, /* nb_hex */
/* Added in release 2.0 */
/* These require the Py_TPFLAGS_HAVE_INPLACEOPS flag */
- proxy_inplace_add, /* nb_inplace_add */
- proxy_inplace_subtract, /* nb_inplace_subtract */
- proxy_inplace_multiply, /* nb_inplace_multiply */
- proxy_inplace_divide, /* nb_inplace_divide */
- proxy_inplace_remainder, /* nb_inplace_remainder */
- proxy_inplace_power, /* nb_inplace_power */
- proxy_inplace_lshift, /* nb_inplace_lshift */
- proxy_inplace_rshift, /* nb_inplace_rshift */
- proxy_inplace_and, /* nb_inplace_and */
- proxy_inplace_xor, /* nb_inplace_xor */
- proxy_inplace_or, /* nb_inplace_or */
+ proxy_iadd, /* nb_inplace_add */
+ proxy_isub, /* nb_inplace_subtract */
+ proxy_imul, /* nb_inplace_multiply */
+ proxy_idiv, /* nb_inplace_divide */
+ proxy_imod, /* nb_inplace_remainder */
+ (ternaryfunc)proxy_ipow, /* nb_inplace_power */
+ proxy_ilshift, /* nb_inplace_lshift */
+ proxy_irshift, /* nb_inplace_rshift */
+ proxy_iand, /* nb_inplace_and */
+ proxy_ixor, /* nb_inplace_xor */
+ proxy_ior, /* nb_inplace_or */
/* Added in release 2.2 */
/* These require the Py_TPFLAGS_HAVE_CLASS flag */
- proxy_floor_divide, /* nb_floor_divide */
- proxy_true_divide, /* nb_true_divide */
- proxy_inplace_floor_divide, /* nb_inplace_floor_divide */
- proxy_inplace_true_divide, /* nb_inplace_true_divide */
+ proxy_floordiv, /* nb_floor_divide */
+ proxy_truediv, /* nb_true_divide */
+ proxy_ifloordiv, /* nb_inplace_floor_divide */
+ proxy_itruediv, /* nb_inplace_true_divide */
};
static PySequenceMethods