The attached patch fixes math.ceil to delegate to x.__ceil__() if it
is defined, according to PEP 3141, and adds tests to cover the new
cases. Patch is against r57303.

No new test failures are introduced.

Keir
Index: Lib/test/test_math.py
===================================================================
--- Lib/test/test_math.py	(revision 57303)
+++ Lib/test/test_math.py	(working copy)
@@ -58,6 +58,14 @@
         self.ftest('ceil(-1.0)', math.ceil(-1.0), -1)
         self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
 
+        class TestCeil:
+            def __ceil__(self):
+                return 42
+        class TestNoCeil:
+            pass
+        self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
+        self.assertRaises(TypeError, math.ceil, TestNoCeil())
+
     def testCos(self):
         self.assertRaises(TypeError, math.cos)
         self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0)
Index: Modules/mathmodule.c
===================================================================
--- Modules/mathmodule.c	(revision 57303)
+++ Modules/mathmodule.c	(working copy)
@@ -107,9 +107,24 @@
 FUNC2(atan2, atan2,
       "atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
       "Unlike atan(y/x), the signs of both x and y are considered.")
-FUNC1(ceil, ceil,
-      "ceil(x)\n\nReturn the ceiling of x as a float.\n"
-      "This is the smallest integral value >= x.")
+static PyObject * math_ceil(PyObject *self, PyObject *args) {
+	PyObject* d = PyObject_GetAttrString(args, "__ceil__");
+	if (d == NULL) {
+		if (!PyFloat_Check(args)) {
+			PyErr_SetString(PyExc_TypeError,
+			                "ceil() argument must have __ceil__ attribute or be a float");
+			return NULL;
+		}
+		PyErr_Clear();
+		return math_1(args, ceil);
+	} 
+	PyObject *res = PyObject_CallFunction(d, "");
+	Py_DECREF(d);
+	return res;
+}
+PyDoc_STRVAR(math_ceil_doc,
+"ceil(x)\n\nReturn the ceiling of x as a float.\n"
+"This is the smallest integral value >= x.");
 FUNC1(cos, cos,
       "cos(x)\n\nReturn the cosine of x (measured in radians).")
 FUNC1(cosh, cosh,
_______________________________________________
Python-3000 mailing list
Python-3000@python.org
http://mail.python.org/mailman/listinfo/python-3000
Unsubscribe: 
http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com

Reply via email to