From 4c3a0a35cd80a0abb9628dc8d4ade911fe2d5015 Mon Sep 17 00:00:00 2001
From: Tim Peters <tim.peters@gmail.com>
Date: Mon, 10 Sep 2001 23:37:46 +0000
Subject: [PATCH] More on SF bug [#460020] bug or feature: unicode() and
 subclasses. tuple(i) repaired to return a true tuple when i is an instance of
 a tuple subclass. Added PyTuple_CheckExact macro. PySequence_Tuple():  if a
 tuple-like object isn't exactly a tuple, it's not safe to return the object
 as-is -- make a new tuple of it instead.

---
 Include/tupleobject.h  | 1 +
 Lib/test/test_descr.py | 2 +-
 Objects/abstract.c     | 6 +++++-
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/Include/tupleobject.h b/Include/tupleobject.h
index 3da3fe0a49..c5ec1c2cec 100644
--- a/Include/tupleobject.h
+++ b/Include/tupleobject.h
@@ -27,6 +27,7 @@ typedef struct {
 extern DL_IMPORT(PyTypeObject) PyTuple_Type;
 
 #define PyTuple_Check(op) PyObject_TypeCheck(op, &PyTuple_Type)
+#define PyTuple_CheckExact(op) ((op)->ob_type == &PyTuple_Type)
 
 extern DL_IMPORT(PyObject *) PyTuple_New(int size);
 extern DL_IMPORT(int) PyTuple_Size(PyObject *);
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 0bed6750ee..d756dc57d0 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1416,7 +1416,7 @@ def inherits():
         verify(v == t)
     a = madtuple((1,2,3,4,5))
     verify(tuple(a) == (1,2,3,4,5))
-    #XXX verify(tuple(a).__class__ is tuple)
+    verify(tuple(a).__class__ is tuple)
     a = madtuple(())
     verify(tuple(a) == ())
     #XXX verify(tuple(a).__class__ is tuple)
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 37f7eeab05..3609948bee 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1235,7 +1235,11 @@ PySequence_Tuple(PyObject *v)
 		return null_error();
 
 	/* Special-case the common tuple and list cases, for efficiency. */
-	if (PyTuple_Check(v)) {
+	if (PyTuple_CheckExact(v)) {
+		/* Note that we can't know whether it's safe to return
+		   a tuple *subclass* instance as-is, hence the restriction
+		   to exact tuples here.  In contrasts, lists always make
+		   a copy, so there's need for exactness below. */
 		Py_INCREF(v);
 		return v;
 	}
-- 
2.49.0