Generalize tuple() to work nicely with iterators.
NEEDS DOC CHANGES.
This one surprised me!  While I expected tuple() to be a no-brainer, turns
out it's actually dripping with consequences:
1. It will *allow* the popular PySequence_Fast() to work with any iterable
   object (code for that not yet checked in, but should be trivial).
2. It caused two std tests to fail.  This because some places used
   PyTuple_Sequence() (the C spelling of tuple()) as an indirect way to test
   whether something *is* a sequence.  But tuple() code only looked for the
   existence of sq->item to determine that, and e.g. an instance passed
   that test whether or not it supported the other operations tuple()
   needed (e.g., __len__).  So some things the tests *expected* to fail
   with an AttributeError now fail with a TypeError instead.  This looks
   like an improvement to me; e.g., test_coercion used to produce 559
   TypeErrors and 2 AttributeErrors, and now they're all TypeErrors.  The
   error details are more informative too, because the places calling this
   were *looking* for TypeErrors in order to replace the generic tuple()
   "not a sequence" msg with their own more specific text, and
   AttributeErrors snuck by that.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 7133867..2fe6b1f 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1176,61 +1176,68 @@
 PyObject *
 PySequence_Tuple(PyObject *v)
 {
-	PySequenceMethods *m;
+	PyObject *it;  /* iter(v) */
+	int n;         /* guess for result tuple size */
+	PyObject *result;
+	int j;
 
 	if (v == NULL)
 		return null_error();
 
+	/* Special-case the common tuple and list cases, for efficiency. */
 	if (PyTuple_Check(v)) {
 		Py_INCREF(v);
 		return v;
 	}
-
 	if (PyList_Check(v))
 		return PyList_AsTuple(v);
 
-	/* There used to be code for strings here, but tuplifying strings is
-	   not a common activity, so I nuked it.  Down with code bloat! */
+	/* Get iterator. */
+	it = PyObject_GetIter(v);
+	if (it == NULL)
+		return type_error("tuple() argument must support iteration");
 
-	/* Generic sequence object */
-	m = v->ob_type->tp_as_sequence;
-	if (m && m->sq_item) {
-		int i;
-		PyObject *t;
-		int n = PySequence_Size(v);
-		if (n < 0)
-			return NULL;
-		t = PyTuple_New(n);
-		if (t == NULL)
-			return NULL;
-		for (i = 0; ; i++) {
-			PyObject *item = (*m->sq_item)(v, i);
-			if (item == NULL) {
-				if (PyErr_ExceptionMatches(PyExc_IndexError))
-					PyErr_Clear();
-				else {
-					Py_DECREF(t);
-					t = NULL;
-				}
-				break;
-			}
-			if (i >= n) {
-				if (n < 500)
-					n += 10;
-				else
-					n += 100;
-				if (_PyTuple_Resize(&t, n, 0) != 0)
-					break;
-			}
-			PyTuple_SET_ITEM(t, i, item);
+	/* Guess result size and allocate space. */
+	n = PySequence_Size(v);
+	if (n < 0) {
+		PyErr_Clear();
+		n = 10;  /* arbitrary */
+	}
+	result = PyTuple_New(n);
+	if (result == NULL)
+		goto Fail;
+
+	/* Fill the tuple. */
+	for (j = 0; ; ++j) {
+		PyObject *item = PyIter_Next(it);
+		if (item == NULL) {
+			if (PyErr_Occurred())
+				goto Fail;
+			break;
 		}
-		if (i < n && t != NULL)
-			_PyTuple_Resize(&t, i, 0);
-		return t;
+		if (j >= n) {
+			if (n < 500)
+				n += 10;
+			else
+				n += 100;
+			if (_PyTuple_Resize(&result, n, 0) != 0)
+				goto Fail;
+		}
+		PyTuple_SET_ITEM(result, j, item);
 	}
 
-	/* None of the above */
-	return type_error("tuple() argument must be a sequence");
+	/* Cut tuple back if guess was too large. */
+	if (j < n &&
+	    _PyTuple_Resize(&result, j, 0) != 0)
+		goto Fail;
+
+	Py_DECREF(it);
+	return result;
+
+Fail:
+	Py_XDECREF(result);
+	Py_DECREF(it);
+	return NULL;
 }
 
 PyObject *