[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 */