From ae211f9abf811a28808667450109ca8e2ea53b49 Mon Sep 17 00:00:00 2001 From: Alex Martelli Date: Wed, 22 Aug 2007 23:21:33 +0000 Subject: Implement the round functionality for PEP 3141, and add tests for it. --- Lib/test/test_builtin.py | 13 +++++++++++++ Python/bltinmodule.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index d5fc85f..37ea8ba 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1474,6 +1474,19 @@ class BuiltinTest(unittest.TestCase): 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) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 2c163a1..b55dd51 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1378,10 +1378,34 @@ builtin_round(PyObject *self, PyObject *args, PyObject *kwds) 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) -- cgit v0.12