Implement the round functionality for PEP 3141, and add tests for it.

This commit is contained in:
Alex Martelli 2007-08-22 23:21:33 +00:00
parent 1dd46a048f
commit ae211f9abf
2 changed files with 39 additions and 2 deletions

View File

@ -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)

View File

@ -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)