[Zope-Checkins] CVS: Zope3/lib/python/Zope/ContextWrapper - proxy.c:1.1.2.4
Fred L. Drake, Jr.
fdrake@acm.org
Fri, 26 Apr 2002 14:52:24 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/ContextWrapper
In directory cvs.zope.org:/tmp/cvs-serv3457
Modified Files:
Tag: SecurityProxy-branch
proxy.c
Log Message:
Port the math ops from Security.Proxy to the base proxy.
=== Zope3/lib/python/Zope/ContextWrapper/proxy.c 1.1.2.3 => 1.1.2.4 ===
*/
+/*
+ * Number methods.
+ */
+
+static PyObject *
+call_int(PyObject *self)
+{
+ 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");
+ return NULL;
+ }
+ return nb->nb_int(self);
+}
+
+static PyObject *
+call_long(PyObject *self)
+{
+ 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");
+ return NULL;
+ }
+ return nb->nb_long(self);
+}
+
+static PyObject *
+call_float(PyObject *self)
+{
+ 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");
+ return NULL;
+ }
+ return nb->nb_float(self);
+}
+
+static PyObject *
+call_oct(PyObject *self)
+{
+ 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");
+ return NULL;
+ }
+ return nb->nb_oct(self);
+}
+
+static PyObject *
+call_hex(PyObject *self)
+{
+ 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");
+ 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);
+}
+
+typedef PyObject *(*function1)(PyObject *);
+
+static PyObject *
+check1(ProxyObject *self, char *opname, function1 operation)
+{
+ PyObject *result = NULL;
+
+ result = operation(Proxy_GET_OBJECT(self));
+#if 0
+ if (result != NULL)
+ /* XXX create proxy for result? */
+ ;
+#endif
+ return result;
+}
+
+static PyObject *
+check2(PyObject *self, PyObject *other,
+ char *opname, char *ropname, binaryfunc operation)
+{
+ PyObject *result = NULL;
+ PyObject *object;
+
+ if (Proxy_Check(self)) {
+ object = Proxy_GET_OBJECT(self);
+ result = operation(object, other);
+ }
+ else if (Proxy_Check(other)) {
+ object = Proxy_GET_OBJECT(other);
+ result = operation(self, object);
+ }
+ else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+#if 0
+ if (result != NULL)
+ /* XXX create proxy for result? */
+ ;
+#endif
+ return result;
+}
+
+static PyObject *
+check2i(ProxyObject *self, PyObject *other,
+ char *opname, binaryfunc operation)
+{
+ PyObject *result = NULL;
+ PyObject *object = Proxy_GET_OBJECT(self);
+
+ 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_INCREF(self);
+ Py_DECREF(object);
+ result = (PyObject *)self;
+ }
+#if 0
+ else if (result != NULL)
+ /* XXX create proxy for result? */
+ ;
+#endif
+ return result;
+}
+
+#define UNOP(NAME, CALL) \
+ static PyObject *wrap_##NAME(PyObject *self) \
+ { return check1((ProxyObject *)self, "__"#NAME"__", CALL); }
+
+#define BINOP(NAME, CALL) \
+ static PyObject *wrap_##NAME(PyObject *self, PyObject *other) \
+ { return check2(self, other, "__"#NAME"__", "__r"#NAME"__", CALL); }
+
+#define INPLACE(NAME, CALL) \
+ static PyObject *wrap_i##NAME(PyObject *self, PyObject *other) \
+ { return check2i((ProxyObject *)self, other, "__i"#NAME"__", CALL); }
+
+BINOP(add, PyNumber_Add)
+BINOP(sub, PyNumber_Subtract)
+BINOP(mul, PyNumber_Multiply)
+BINOP(div, PyNumber_Divide)
+BINOP(mod, PyNumber_Remainder)
+BINOP(divmod, PyNumber_Divmod)
+
+static PyObject *
+wrap_pow(PyObject *self, PyObject *other, PyObject *modulus)
+{
+ PyObject *result = NULL;
+ PyObject *object;
+
+ if (Proxy_Check(self)) {
+ object = Proxy_GET_OBJECT(self);
+ result = PyNumber_Power(object, other, modulus);
+ }
+ else if (Proxy_Check(other)) {
+ object = Proxy_GET_OBJECT(other);
+ result = PyNumber_Power(self, object, modulus);
+ }
+ else if (modulus != NULL && Proxy_Check(modulus)) {
+ object = Proxy_GET_OBJECT(modulus);
+ result = PyNumber_Power(self, other, modulus);
+ }
+ else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ return result;
+}
+
+BINOP(lshift, PyNumber_Lshift)
+BINOP(rshift, PyNumber_Rshift)
+BINOP(and, PyNumber_And)
+BINOP(xor, PyNumber_Xor)
+BINOP(or, PyNumber_Or)
+
+static int
+wrap_coerce(PyObject **p_self, PyObject **p_other)
+{
+ PyObject *self = *p_self;
+ PyObject *other = *p_other;
+ PyObject *object;
+ PyObject *left;
+ PyObject *right;
+ int r;
+
+ assert(Proxy_Check(self));
+ object = Proxy_GET_OBJECT(self);
+
+ left = object;
+ right = other;
+ 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_INCREF(self);
+ Py_DECREF(left);
+ left = self;
+ }
+#if 0
+ else {
+ /* XXX create proxy for left? */
+ }
+ if (right != other) {
+ /* XXX create proxy for right? */
+ }
+#endif
+ *p_self = left;
+ *p_other = right;
+ return 0;
+}
+
+UNOP(neg, PyNumber_Negative)
+UNOP(pos, PyNumber_Positive)
+UNOP(abs, PyNumber_Absolute)
+UNOP(invert, PyNumber_Invert)
+
+UNOP(int, call_int)
+UNOP(long, call_long)
+UNOP(float, call_float)
+UNOP(oct, call_oct)
+UNOP(hex, call_hex)
+
+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)
+
static int
wrap_nonzero(PyObject *self)
{
@@ -227,17 +481,50 @@
static PyNumberMethods
wrap_as_number = {
- 0, /* nb_add */
- 0, /* nb_subtract */
- 0, /* nb_multiply */
- 0, /* nb_divide */
- 0, /* nb_remainder */
- 0, /* nb_divmod */
- 0, /* nb_power */
- 0, /* nb_negative */
- 0, /* nb_positive */
- 0, /* nb_absolute */
+ wrap_add, /* nb_add */
+ wrap_sub, /* nb_subtract */
+ wrap_mul, /* nb_multiply */
+ wrap_div, /* nb_divide */
+ wrap_mod, /* nb_remainder */
+ wrap_divmod, /* nb_divmod */
+ wrap_pow, /* nb_power */
+ wrap_neg, /* nb_negative */
+ wrap_pos, /* nb_positive */
+ wrap_abs, /* nb_absolute */
wrap_nonzero, /* nb_nonzero */
+ wrap_invert, /* nb_invert */
+ wrap_lshift, /* nb_lshift */
+ wrap_rshift, /* nb_rshift */
+ wrap_and, /* nb_and */
+ wrap_xor, /* nb_xor */
+ wrap_or, /* nb_or */
+ wrap_coerce, /* nb_coerce */
+ wrap_int, /* nb_int */
+ wrap_long, /* nb_long */
+ wrap_float, /* nb_float */
+ wrap_oct, /* nb_oct */
+ wrap_hex, /* nb_hex */
+
+ /* Added in release 2.0 */
+ /* These require the Py_TPFLAGS_HAVE_INPLACEOPS flag */
+ wrap_iadd, /* nb_inplace_add */
+ wrap_isub, /* nb_inplace_subtract */
+ wrap_imul, /* nb_inplace_multiply */
+ wrap_idiv, /* nb_inplace_divide */
+ wrap_imod, /* nb_inplace_remainder */
+ (ternaryfunc)wrap_ipow, /* nb_inplace_power */
+ wrap_ilshift, /* nb_inplace_lshift */
+ wrap_irshift, /* nb_inplace_rshift */
+ wrap_iand, /* nb_inplace_and */
+ wrap_ixor, /* nb_inplace_xor */
+ wrap_ior, /* nb_inplace_or */
+
+ /* Added in release 2.2 */
+ /* These require the Py_TPFLAGS_HAVE_CLASS flag */
+ wrap_floordiv, /* nb_floor_divide */
+ wrap_truediv, /* nb_true_divide */
+ wrap_ifloordiv, /* nb_inplace_floor_divide */
+ wrap_itruediv, /* nb_inplace_true_divide */
};
static PySequenceMethods
@@ -298,7 +585,7 @@
wrap_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
- | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
wrap_traverse, /* tp_traverse */
wrap_clear, /* tp_clear */