[Python-3000-checkins] r57302 - in python/branches/py3k: Lib/test/test_builtin.py Python/bltinmodule.c

alex.martelli python-3000-checkins at python.org
Thu Aug 23 01:21:34 CEST 2007


Author: alex.martelli
Date: Thu Aug 23 01:21:33 2007
New Revision: 57302

Modified:
   python/branches/py3k/Lib/test/test_builtin.py
   python/branches/py3k/Python/bltinmodule.c
Log:
Implement the round functionality for PEP 3141, and add tests for it.



Modified: python/branches/py3k/Lib/test/test_builtin.py
==============================================================================
--- python/branches/py3k/Lib/test/test_builtin.py	(original)
+++ python/branches/py3k/Lib/test/test_builtin.py	Thu Aug 23 01:21:33 2007
@@ -1474,6 +1474,19 @@
 
         self.assertRaises(TypeError, round)
 
+        # test generic rounding delegation for reals
+        class TestRound:
+            def __round__(self):
+                return 23
+
+        class TestNoRound:
+            pass
+
+        self.assertEqual(round(TestRound()), 23)
+
+        self.assertRaises(TypeError, round, 1, 2, 3)
+        self.assertRaises(TypeError, round, TestNoRound())
+
     def test_setattr(self):
         setattr(sys, 'spam', 1)
         self.assertEqual(sys.spam, 1)

Modified: python/branches/py3k/Python/bltinmodule.c
==============================================================================
--- python/branches/py3k/Python/bltinmodule.c	(original)
+++ python/branches/py3k/Python/bltinmodule.c	Thu Aug 23 01:21:33 2007
@@ -1378,10 +1378,34 @@
 	int ndigits = 0;
 	int i;
 	static char *kwlist[] = {"number", "ndigits", 0};
+	PyObject* real;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|i:round",
-                kwlist, &number, &ndigits))
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:round",
+                kwlist, &real, &ndigits))
                 return NULL;
+
+	if (ndigits == 0) {
+		PyObject *res;
+		PyObject *d = PyObject_GetAttrString(real, "__round__");
+		if (d == NULL && !PyFloat_Check(real)) {
+			PyErr_SetString(PyExc_TypeError,
+					"round() argument must have __round__ attribute or be a float");
+			return NULL;
+		} 
+		if (d == NULL) {
+			PyErr_Clear();
+		} else {
+			res = PyObject_CallFunction(d, "");
+			Py_DECREF(d);
+			return res;
+		} 
+	} else if (!PyFloat_Check(real)) {
+		PyErr_SetString(PyExc_TypeError,
+				"round() argument must have __round__ attribute or be a float");
+		return NULL;
+	}
+
+	number = PyFloat_AsDouble(real);
 	f = 1.0;
 	i = abs(ndigits);
 	while  (--i >= 0)


More information about the Python-3000-checkins mailing list