Implement the round functionality for PEP 3141, and add tests for it.
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 @@
 
         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 @@
 	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)