add Py3k warnings to oct and hex. backport hex behavior (because it's not different)
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 15d80a3..4264a99 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -632,6 +632,10 @@
         self.assertEqual(hex(-16L), '-0x10L')
         self.assertRaises(TypeError, hex, {})
 
+        class Spam(object):
+            def __index__(self): return 23
+        self.assertEqual(hex(Spam()), "0x17")
+
     def test_id(self):
         id(None)
         id(1)
diff --git a/Lib/test/test_py3kwarn.py b/Lib/test/test_py3kwarn.py
index 2c8f509..e6d38f2 100644
--- a/Lib/test/test_py3kwarn.py
+++ b/Lib/test/test_py3kwarn.py
@@ -123,6 +123,20 @@
         with catch_warning() as w:
             self.assertWarning(buffer('a'), w, expected)
 
+    def test_hex_and_oct(self):
+        class Spam(object):
+            def __hex__(self): return "0x17"
+            def __oct__(self): return "07"
+
+        expected = 'In 3.x, oct() converts the result of __index__ to octal; ' \
+                   'Use future_builtins.oct for this behavior. ' \
+                   'Also, note the returned format is different.'
+        with catch_warning() as w:
+            self.assertWarning(oct(Spam()), w, expected)
+        expected = 'In 3.x, hex() converts the result of __index__ to hexidecimal.'
+        with catch_warning() as w:
+            self.assertWarning(hex(Spam()), w, expected)
+
 
 class TestStdlibRemovals(unittest.TestCase):
 
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 0234b6b..5c30e03 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1181,22 +1181,29 @@
 {
 	PyNumberMethods *nb;
 	PyObject *res;
-
-	if ((nb = v->ob_type->tp_as_number) == NULL ||
-	    nb->nb_hex == NULL) {
-		PyErr_SetString(PyExc_TypeError,
-			   "hex() argument can't be converted to hex");
-		return NULL;
+	
+	nb = Py_TYPE(v)->tp_as_number;
+	
+	if (nb != NULL && nb->nb_hex != NULL) {
+		if (PyErr_WarnPy3k("In 3.x, hex() converts "
+				   "the result of __index__ to hexidecimal.",
+				   1) < 0)
+			return NULL;
+		res = (*nb->nb_hex)(v);
+		if (res && !PyString_Check(res)) {
+			PyErr_Format(PyExc_TypeError,
+				     "__hex__ returned non-string (type %.200s)",
+				     res->ob_type->tp_name);
+			Py_DECREF(res);
+			return NULL;
+		}
+		return res;
 	}
-	res = (*nb->nb_hex)(v);
-	if (res && !PyString_Check(res)) {
-		PyErr_Format(PyExc_TypeError,
-			     "__hex__ returned non-string (type %.200s)",
-			     res->ob_type->tp_name);
-		Py_DECREF(res);
-		return NULL;
-	}
-	return res;
+	else if (PyIndex_Check(v))
+		return PyNumber_ToBase(v, 16);
+	PyErr_SetString(PyExc_TypeError,
+			"hex() argument can't be converted to hex");
+	return NULL;
 }
 
 PyDoc_STRVAR(hex_doc,
@@ -1456,6 +1463,11 @@
 			   "oct() argument can't be converted to oct");
 		return NULL;
 	}
+	if (PyErr_WarnPy3k("In 3.x, oct() converts the result of __index__ to octal; "
+			   "Use future_builtins.oct for this behavior. "
+                            "Also, note the returned format is different.",
+                           1) < 0)
+		return NULL;
 	res = (*nb->nb_oct)(v);
 	if (res && !PyString_Check(res)) {
 		PyErr_Format(PyExc_TypeError,