[Zope-Checkins] CVS: Zope3/lib/python/Zope/Security - _Proxy.c:1.1.2.13
Guido van Rossum
guido@python.org
Wed, 24 Apr 2002 17:27:40 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Security
In directory cvs.zope.org:/tmp/cvs-serv22915
Modified Files:
Tag: SecurityProxy-branch
_Proxy.c
Log Message:
Add binary and unary numerical operators. Still to do: ternary, and inplace.
Fixed proxy_length(): it was calling check() with __nonzero__ instead
of __len__.
=== Zope3/lib/python/Zope/Security/_Proxy.c 1.1.2.12 => 1.1.2.13 ===
}
+static PyObject *
+check2(PyObject *self, PyObject *other,
+ char *opname, char *ropname, binaryfunc operation)
+{
+ PyObject *result = NULL;
+ PyObject *object;
+ PyObject *checker;
+
+ if (Proxy_Check(self)) {
+ object = Proxy_GetObject(self);
+ checker = Proxy_GetChecker(self);
+ if (check(checker, opname, object))
+ result = operation(object, other);
+ }
+ else if (Proxy_Check(other)) {
+ object = Proxy_GetObject(other);
+ checker = Proxy_GetChecker(other);
+ if (check(checker, ropname, object))
+ result = operation(self, object);
+ }
+ else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ if (result != NULL)
+ result = PyObject_CallMethod(checker, "proxy", "(N)", result);
+ return result;
+}
+
+#define BINOP(NAME, CALL) \
+ static PyObject *proxy_##NAME(PyObject *self, PyObject *other) \
+ { return check2(self, other, "__" #NAME "__", "__r" #NAME "__", CALL); }
+
+#define UNOP(NAME, CALL) \
+ static PyObject *proxy_##NAME(PyObject *self) \
+ { return check1((ProxyObject *)self, "__" #NAME "__", CALL); }
+
/*
* Slot methods.
@@ -203,17 +240,8 @@
return -1;
}
-static PyObject *
-proxy_str(PyObject *self)
-{
- return check1((ProxyObject *)self, "__str__", PyObject_Str);
-}
-
-static PyObject *
-proxy_repr(PyObject *self)
-{
- return check1((ProxyObject *)self, "__repr__", PyObject_Repr);
-}
+UNOP(str, PyObject_Str)
+UNOP(repr, PyObject_Repr)
static int
proxy_compare(PyObject *self, PyObject *other)
@@ -255,9 +283,80 @@
/*
* Number methods.
- * XXX need more :-)
+ * XXX The "#define proxy_xxx 0" lines mean that function is still TBD.
*/
+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);
+}
+
+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
+BINOP(lshift, PyNumber_Lshift)
+BINOP(rshift, PyNumber_Rshift)
+BINOP(and, PyNumber_And)
+BINOP(xor, PyNumber_Xor)
+BINOP(or, PyNumber_Or)
+UNOP(neg, PyNumber_Negative)
+UNOP(pos, PyNumber_Positive)
+UNOP(abs, PyNumber_Absolute)
+
static int
proxy_nonzero(PyObject *self)
{
@@ -269,6 +368,30 @@
return -1;
}
+UNOP(invert, PyNumber_Invert)
+UNOP(int, call_int)
+UNOP(long, call_long)
+UNOP(float, call_float)
+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
+
/*
* Sequence methods.
* (If you have mapping getitem/setitem, sequence getitem/setitem
@@ -281,7 +404,7 @@
PyObject *object = Proxy_GetObject(self);
PyObject *checker = Proxy_GetChecker(self);
- if (check(checker, "__nonzero__", object))
+ if (check(checker, "__len__", object))
return PyObject_Length(object);
return -1;
}
@@ -361,17 +484,50 @@
static PyNumberMethods
proxy_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 */
+ 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 */
+
+ /* 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 */
+
+ /* 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 */
};
static PySequenceMethods
@@ -429,7 +585,7 @@
proxy_getattro, /* tp_getattro */
proxy_setattro, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_HAVE_GC, /* tp_flags */
proxy_doc, /* tp_doc */
proxy_traverse, /* tp_traverse */