From f6f3a3544783496301537bc5c946b58b0e5cbac8 Mon Sep 17 00:00:00 2001
From: Benjamin Peterson <benjamin@python.org>
Date: Sat, 3 Sep 2011 09:26:20 -0400
Subject: add a __dict__ descr for IOBase (closes #12878)

---
 Lib/test/test_io.py  | 11 +++++++++++
 Misc/NEWS            |  2 ++
 Modules/_io/iobase.c | 14 ++++++++++++++
 3 files changed, 27 insertions(+)

diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 72c9a2d..0dc9d6d 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -610,6 +610,17 @@ class IOTest(unittest.TestCase):
         self.assertEqual(rawio.read(2), None)
         self.assertEqual(rawio.read(2), b"")
 
+    def test_types_have_dict(self):
+        test = (
+            self.IOBase(),
+            self.RawIOBase(),
+            self.TextIOBase(),
+            self.StringIO(),
+            self.BytesIO()
+        )
+        for obj in test:
+            self.assertTrue(hasattr(obj, "__dict__"))
+
 class CIOTest(IOTest):
 
     def test_IOBase_finalize(self):
diff --git a/Misc/NEWS b/Misc/NEWS
index f489ab257..514d19a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -28,6 +28,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #12878: Expose a __dict__ attribute on io.IOBase and its subclasses.
+
 - Issue #12636: IDLE reads the coding cookie when executing a Python script.
 
 - Issue #10946: The distutils commands bdist_dumb, bdist_wininst and bdist_msi
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index f06f562..2c59d42 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -156,6 +156,19 @@ iobase_closed_get(PyObject *self, void *context)
     return PyBool_FromLong(IS_CLOSED(self));
 }
 
+static PyObject *
+iobase_get_dict(PyObject *self)
+{
+    PyObject **dictptr = _PyObject_GetDictPtr(self);
+    PyObject *dict;
+    assert(dictptr);
+    dict = *dictptr;
+    if (dict == NULL)
+        dict = *dictptr = PyDict_New();
+    Py_XINCREF(dict);
+    return dict;
+}
+
 PyObject *
 _PyIOBase_check_closed(PyObject *self, PyObject *args)
 {
@@ -691,6 +704,7 @@ static PyMethodDef iobase_methods[] = {
 };
 
 static PyGetSetDef iobase_getset[] = {
+    {"__dict__", iobase_get_dict, NULL, NULL},
     {"closed", (getter)iobase_closed_get, NULL, NULL},
     {NULL}
 };
-- 
cgit v0.12