[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