[Zodb-checkins] CVS: ZODB3/ExtensionClass/src - Missing.c:1.20
Jeremy Hylton
jeremy at zope.com
Fri May 9 18:51:07 EDT 2003
Update of /cvs-repository/ZODB3/ExtensionClass/src
In directory cvs.zope.org:/tmp/cvs-serv23789/src
Modified Files:
Missing.c
Log Message:
Another fix for the coercion bug.
I'm hesitant to see this fix really works, except that I wrote a very
minimal test suite that covers all the cases I'm aware of. The
previous checkin caused numberic operations when the Missing object
was on the right-hand side.
=== ZODB3/ExtensionClass/src/Missing.c 1.19 => 1.20 ===
--- ZODB3/ExtensionClass/src/Missing.c:1.19 Fri May 9 16:57:10 2003
+++ ZODB3/ExtensionClass/src/Missing.c Fri May 9 17:50:36 2003
@@ -26,7 +26,7 @@
} Missing;
static PyObject *vname=0, *Missing_dot_Value=0, *empty_string=0, *reduce=0;
-static PyObject *theValue;
+static PyObject *theValue, *notMissing;
static void
Missing_dealloc(Missing *self)
@@ -49,20 +49,32 @@
return empty_string;
}
-/* Code to access Missing objects as numbers */
+/* Code to access Missing objects as numbers.
+
+ We must guarantee that notMissing is never returned to Python code,
+ because it would violate the guarantee that all Python-accessible
+ Missing values are equal to each other.
+
+*/
static PyObject *
Missing_bin(PyObject *v, PyObject *w)
{
- Py_INCREF(v);
- return v;
+ if (v == notMissing)
+ v = w;
+ assert(v != notMissing);
+ Py_INCREF(v);
+ return v;
}
static PyObject *
Missing_pow(PyObject *v, PyObject *w, PyObject *z)
{
- Py_INCREF(v);
- return v;
+ if (v == notMissing)
+ v = w;
+ assert(v != notMissing);
+ Py_INCREF(v);
+ return v;
}
static PyObject *
@@ -78,62 +90,20 @@
return 0;
}
-/* coerce should return two values of the same type.
-
- We violate that contract in a controlled way, by always coercing
- the other object to Py_None. We are guaranteed that our tp_compare
- will be called because Py_None does not define a tp_compare.
+/* Always return the distinguished notMissing object as the result
+ of the coercion. The notMissing object does not compare equal
+ to other Missing objects.
*/
static int
Missing_coerce(PyObject **pv, PyObject **pw)
{
Py_INCREF(*pv);
- Py_INCREF(Py_None);
- *pw = Py_None;
+ Py_INCREF(notMissing);
+ *pw = notMissing;
return 0;
}
-static PyObject *
-Missing_int(Missing *v)
-{
- PyErr_SetString(PyExc_TypeError,
- "Missing objects do not support conversion to integer");
- return NULL;
-}
-
-static PyObject *
-Missing_long(Missing *v)
-{
- PyErr_SetString(PyExc_TypeError,
- "Missing objects do not support conversion to long");
- return NULL;
-}
-
-static PyObject *
-Missing_float(Missing *v)
-{
- PyErr_SetString(PyExc_TypeError,
- "Missing objects do not support conversion to float");
- return NULL;
-}
-
-static PyObject *
-Missing_oct(Missing *v)
-{
- PyErr_SetString(PyExc_TypeError,
- "Missing objects do not support conversion to an octal string");
- return NULL;
-}
-
-static PyObject *
-Missing_hex(Missing *v)
-{
- PyErr_SetString(PyExc_TypeError,
- "Missing objects do not support conversion to hexadecimal strings");
- return NULL;
-}
-
static PyNumberMethods Missing_as_number = {
(binaryfunc)Missing_bin, /*nb_add*/
(binaryfunc)Missing_bin, /*nb_subtract*/
@@ -142,22 +112,39 @@
(binaryfunc)Missing_bin, /*nb_remainder*/
(binaryfunc)Missing_bin, /*nb_divmod*/
(ternaryfunc)Missing_pow, /*nb_power*/
- (unaryfunc)Missing_un, /*nb_negative*/
- (unaryfunc)Missing_un, /*nb_positive*/
- (unaryfunc)Missing_un, /*nb_absolute*/
+ (unaryfunc)Missing_un, /*nb_negative*/
+ (unaryfunc)Missing_un, /*nb_positive*/
+ (unaryfunc)Missing_un, /*nb_absolute*/
(inquiry)Missing_nonzero, /*nb_nonzero*/
- (unaryfunc)Missing_un, /*nb_invert*/
+ (unaryfunc)Missing_un, /*nb_invert*/
(binaryfunc)Missing_bin, /*nb_lshift*/
(binaryfunc)Missing_bin, /*nb_rshift*/
(binaryfunc)Missing_bin, /*nb_and*/
(binaryfunc)Missing_bin, /*nb_xor*/
(binaryfunc)Missing_bin, /*nb_or*/
(coercion)Missing_coerce, /*nb_coerce*/
- (unaryfunc)Missing_int, /*nb_int*/
- (unaryfunc)Missing_long, /*nb_long*/
- (unaryfunc)Missing_float, /*nb_float*/
- (unaryfunc)Missing_oct, /*nb_oct*/
- (unaryfunc)Missing_hex, /*nb_hex*/
+ 0, /*nb_int*/
+ 0, /*nb_long*/
+ 0, /*nb_float*/
+ 0, /*nb_oct*/
+ 0, /*nb_hex*/
+#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION != 1
+ 0, /* nb_inplace_add */
+ 0, /* nb_inplace_subtract */
+ 0, /* nb_inplace_multiply */
+ 0, /* nb_inplace_divide */
+ 0, /* nb_inplace_remainder */
+ 0, /* nb_inplace_power */
+ 0, /* nb_inplace_lshift */
+ 0, /* nb_inplace_rshift */
+ 0, /* nb_inplace_and */
+ 0, /* nb_inplace_xor */
+ 0, /* nb_inplace_or */
+ Missing_bin, /* nb_floor_divide */
+ Missing_bin, /* nb_true_divide */
+ 0, /* nb_inplace_floor_divide */
+ 0, /* nb_inplace_true_divide */
+#endif
};
/* ------------------------------------------------------- */
@@ -226,16 +213,17 @@
return self;
}
-/* All Missing objects are equal to each other, but we have
- specially arranged for Py_None to be passed as m2 via
- Missing_coerce(). So be prepared for Py_None where
- a Missing is expected.
+/* All Missing objects are equal to each other, except for the
+ special notMissing object. It is returned by coerce to
+ indicate that Missing is being compare to something else.
*/
static int
-Missing_cmp(Missing *m1, Missing *m2)
+Missing_cmp(PyObject *m1, PyObject *m2)
{
- return Py_None == (PyObject *)m2;
+ if (m1 == notMissing)
+ return -1;
+ return (m2 == notMissing);
}
static PyExtensionClass MissingType = {
@@ -249,7 +237,7 @@
(printfunc)0, /*tp_print*/
(getattrfunc)0, /*obsolete tp_getattr*/
(setattrfunc)0, /*obsolete tp_setattr*/
- (cmpfunc)Missing_cmp, /*tp_compare*/
+ Missing_cmp, /*tp_compare*/
(reprfunc)Missing_repr, /*tp_repr*/
&Missing_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
@@ -300,7 +288,8 @@
PyExtensionClass_Export(d,"Missing",MissingType);
- theValue=PyObject_CallObject((PyObject*)&MissingType, NULL);
+ theValue = PyObject_CallObject((PyObject*)&MissingType, NULL);
+ notMissing = PyObject_CallObject((PyObject*)&MissingType, NULL);
reduce=PyCFunction_New(reduce_ml, theValue);
PyDict_SetItemString(d, "Value", theValue);
More information about the Zodb-checkins
mailing list