https://github.com/python/cpython/commit/623b338adf2645b09c546e7a17f2648d3a900620
commit: 623b338adf2645b09c546e7a17f2648d3a900620
branch: main
author: AN Long <[email protected]>
committer: erlend-aasland <[email protected]>
date: 2024-01-09T21:39:36+01:00
summary:

gh-66060: Use actual class name in _io type's __repr__ (#30824)

Use the object's actual class name in the following _io type's __repr__:
- FileIO
- TextIOWrapper
- _WindowsConsoleIO

files:
A Misc/NEWS.d/next/Core and Builtins/2022-01-23-18-00-10.bpo-21861.N8E1zw.rst
M Lib/test/test_fileio.py
M Lib/test/test_io.py
M Lib/test/test_winconsoleio.py
M Modules/_io/fileio.c
M Modules/_io/textio.c
M Modules/_io/winconsoleio.c

diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py
index f490485cdaf3eb..06d9b454add34c 100644
--- a/Lib/test/test_fileio.py
+++ b/Lib/test/test_fileio.py
@@ -174,6 +174,16 @@ def testRepr(self):
         self.assertEqual(repr(self.f),
                          "<%s.FileIO [closed]>" % (self.modulename,))
 
+    def test_subclass_repr(self):
+        class TestSubclass(self.FileIO):
+            pass
+
+        f = TestSubclass(TESTFN)
+        with f:
+            self.assertIn(TestSubclass.__name__, repr(f))
+
+        self.assertIn(TestSubclass.__name__, repr(f))
+
     def testReprNoCloseFD(self):
         fd = os.open(TESTFN, os.O_RDONLY)
         try:
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index ca31b9dad2631a..936edea3cad70c 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -2806,6 +2806,13 @@ def test_recursive_repr(self):
             with self.assertRaises(RuntimeError):
                 repr(t)  # Should not crash
 
+    def test_subclass_repr(self):
+        class TestSubclass(self.TextIOWrapper):
+            pass
+
+        f = TestSubclass(self.StringIO())
+        self.assertIn(TestSubclass.__name__, repr(f))
+
     def test_line_buffering(self):
         r = self.BytesIO()
         b = self.BufferedWriter(r, 1000)
diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py
index 70a85552cc03b0..72ff9606908ed5 100644
--- a/Lib/test/test_winconsoleio.py
+++ b/Lib/test/test_winconsoleio.py
@@ -98,6 +98,16 @@ def test_open_name(self):
             self.assertIsInstance(f, ConIO)
             f.close()
 
+    def test_subclass_repr(self):
+        class TestSubclass(ConIO):
+            pass
+
+        f = TestSubclass("CON")
+        with f:
+            self.assertIn(TestSubclass.__name__, repr(f))
+
+        self.assertIn(TestSubclass.__name__, repr(f))
+
     @unittest.skipIf(sys.getwindowsversion()[:2] <= (6, 1),
         "test does not work on Windows 7 and earlier")
     def test_conin_conout_names(self):
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2022-01-23-18-00-10.bpo-21861.N8E1zw.rst b/Misc/NEWS.d/next/Core and 
Builtins/2022-01-23-18-00-10.bpo-21861.N8E1zw.rst
new file mode 100644
index 00000000000000..5d99845912caf3
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2022-01-23-18-00-10.bpo-21861.N8E1zw.rst       
@@ -0,0 +1,3 @@
+Use the object's actual class name in :meth:`_io.FileIO.__repr__`,
+:meth:`_io._WindowsConsoleIO` and :meth:`_io.TextIOWrapper.__repr__`, to
+make these methods subclass friendly.
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 8a73ea0365b7a3..af4375c3640679 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -1100,31 +1100,32 @@ static PyObject *
 fileio_repr(fileio *self)
 {
     PyObject *nameobj, *res;
+    const char *type_name = Py_TYPE((PyObject *) self)->tp_name;
 
-    if (self->fd < 0)
-        return PyUnicode_FromFormat("<_io.FileIO [closed]>");
+    if (self->fd < 0) {
+        return PyUnicode_FromFormat("<%.100s [closed]>", type_name);
+    }
 
     if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 
0) {
         return NULL;
     }
     if (nameobj == NULL) {
         res = PyUnicode_FromFormat(
-            "<_io.FileIO fd=%d mode='%s' closefd=%s>",
-            self->fd, mode_string(self), self->closefd ? "True" : "False");
+            "<%.100s fd=%d mode='%s' closefd=%s>",
+            type_name, self->fd, mode_string(self), self->closefd ? "True" : 
"False");
     }
     else {
         int status = Py_ReprEnter((PyObject *)self);
         res = NULL;
         if (status == 0) {
             res = PyUnicode_FromFormat(
-                "<_io.FileIO name=%R mode='%s' closefd=%s>",
-                nameobj, mode_string(self), self->closefd ? "True" : "False");
+                "<%.100s name=%R mode='%s' closefd=%s>",
+                type_name, nameobj, mode_string(self), self->closefd ? "True" 
: "False");
             Py_ReprLeave((PyObject *)self);
         }
         else if (status > 0) {
             PyErr_Format(PyExc_RuntimeError,
-                         "reentrant call inside %s.__repr__",
-                         Py_TYPE(self)->tp_name);
+                         "reentrant call inside %.100s.__repr__", type_name);
         }
         Py_DECREF(nameobj);
     }
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index e93c3e091549db..d794af8de2b8f0 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -2948,10 +2948,11 @@ textiowrapper_repr(textio *self)
 {
     PyObject *nameobj, *modeobj, *res, *s;
     int status;
+    const char *type_name = Py_TYPE(self)->tp_name;
 
     CHECK_INITIALIZED(self);
 
-    res = PyUnicode_FromString("<_io.TextIOWrapper");
+    res = PyUnicode_FromFormat("<%.100s", type_name);
     if (res == NULL)
         return NULL;
 
@@ -2959,8 +2960,8 @@ textiowrapper_repr(textio *self)
     if (status != 0) {
         if (status > 0) {
             PyErr_Format(PyExc_RuntimeError,
-                         "reentrant call inside %s.__repr__",
-                         Py_TYPE(self)->tp_name);
+                         "reentrant call inside %.100s.__repr__",
+                         type_name);
         }
         goto error;
     }
diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c
index 6680488b740cfc..fecb3389570780 100644
--- a/Modules/_io/winconsoleio.c
+++ b/Modules/_io/winconsoleio.c
@@ -1070,15 +1070,22 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, 
PyTypeObject *cls,
 static PyObject *
 winconsoleio_repr(winconsoleio *self)
 {
-    if (self->fd == -1)
-        return PyUnicode_FromFormat("<_io._WindowsConsoleIO [closed]>");
-
-    if (self->readable)
-        return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='rb' 
closefd=%s>",
-            self->closefd ? "True" : "False");
-    if (self->writable)
-        return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='wb' 
closefd=%s>",
-            self->closefd ? "True" : "False");
+    const char *type_name = (Py_TYPE((PyObject *)self)->tp_name);
+
+    if (self->fd == -1) {
+        return PyUnicode_FromFormat("<%.100s [closed]>", type_name);
+    }
+
+    if (self->readable) {
+        return PyUnicode_FromFormat("<%.100s mode='rb' closefd=%s>",
+                                    type_name,
+                                    self->closefd ? "True" : "False");
+    }
+    if (self->writable) {
+        return PyUnicode_FromFormat("<%.100s mode='wb' closefd=%s>",
+                                    type_name,
+                                    self->closefd ? "True" : "False");
+    }
 
     PyErr_SetString(PyExc_SystemError, "_WindowsConsoleIO has invalid mode");
     return NULL;

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to