Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 716c444

Browse files
committed
Issue #5761: Add the name of the underlying file to the repr() of various IO objects.
1 parent 744af44 commit 716c444

7 files changed

Lines changed: 106 additions & 13 deletions

File tree

Lib/_pyio.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,15 @@ def name(self):
736736
def mode(self):
737737
return self.raw.mode
738738

739+
def __repr__(self):
740+
clsname = self.__class__.__name__
741+
try:
742+
name = self.name
743+
except AttributeError:
744+
return "<_pyio.{0}>".format(clsname)
745+
else:
746+
return "<_pyio.{0} name={1!r}>".format(clsname, name)
747+
739748
### Lower-level APIs ###
740749

741750
def fileno(self):
@@ -1455,7 +1464,13 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None,
14551464
# - "chars_..." for integer variables that count decoded characters
14561465

14571466
def __repr__(self):
1458-
return "<TextIOWrapper encoding={0}>".format(self.encoding)
1467+
try:
1468+
name = self.name
1469+
except AttributeError:
1470+
return "<_pyio.TextIOWrapper encoding={0!r}>".format(self.encoding)
1471+
else:
1472+
return "<_pyio.TextIOWrapper name={0!r} encoding={1!r}>".format(
1473+
name, self.encoding)
14591474

14601475
@property
14611476
def encoding(self):

Lib/test/test_fileio.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,13 @@ def testReadinto(self):
7070
self.assertEquals(array('b', [1, 2]), a[:n])
7171

7272
def testRepr(self):
73-
self.assertEquals(repr(self.f),
74-
"io.FileIO(%d, %s)" % (self.f.fileno(),
75-
repr(self.f.mode)))
73+
self.assertEquals(repr(self.f), "<_io.FileIO name=%r mode=%r>"
74+
% (self.f.name, self.f.mode))
75+
del self.f.name
76+
self.assertEquals(repr(self.f), "<_io.FileIO fd=%r mode=%r>"
77+
% (self.f.fileno(), self.f.mode))
78+
self.f.close()
79+
self.assertEquals(repr(self.f), "<_io.FileIO [closed]>")
7680

7781
def testErrors(self):
7882
f = self.f

Lib/test/test_io.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,16 @@ def f():
618618
self.assert_(s.startswith("Exception IOError: "), s)
619619
self.assert_(s.endswith(" ignored"), s)
620620

621+
def test_repr(self):
622+
raw = self.MockRawIO()
623+
b = self.tp(raw)
624+
clsname = "%s.%s" % (self.tp.__module__, self.tp.__name__)
625+
self.assertEqual(repr(b), "<%s>" % clsname)
626+
raw.name = "dummy"
627+
self.assertEqual(repr(b), "<%s name='dummy'>" % clsname)
628+
raw.name = b"dummy"
629+
self.assertEqual(repr(b), "<%s name=b'dummy'>" % clsname)
630+
621631

622632
class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
623633
read_mode = "rb"
@@ -1528,7 +1538,15 @@ def test_repr(self):
15281538
raw = self.BytesIO("hello".encode("utf-8"))
15291539
b = self.BufferedReader(raw)
15301540
t = self.TextIOWrapper(b, encoding="utf-8")
1531-
self.assertEqual(repr(t), "<TextIOWrapper encoding=utf-8>")
1541+
modname = self.TextIOWrapper.__module__
1542+
self.assertEqual(repr(t),
1543+
"<%s.TextIOWrapper encoding='utf-8'>" % modname)
1544+
raw.name = "dummy"
1545+
self.assertEqual(repr(t),
1546+
"<%s.TextIOWrapper name='dummy' encoding='utf-8'>" % modname)
1547+
raw.name = b"dummy"
1548+
self.assertEqual(repr(t),
1549+
"<%s.TextIOWrapper name=b'dummy' encoding='utf-8'>" % modname)
15321550

15331551
def test_line_buffering(self):
15341552
r = self.BytesIO()

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ Core and Builtins
3232
Library
3333
-------
3434

35+
- Issue #5761: Add the name of the underlying file to the repr() of various
36+
IO objects.
37+
3538
- Issue #5259: smtplib plain auth login no longer gives a traceback. Fix
3639
by Musashi Tamura, tests by Marcin Bachry.
3740

Modules/_io/bufferedio.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,27 @@ Buffered_iternext(BufferedObject *self)
11231123
return line;
11241124
}
11251125

1126+
static PyObject *
1127+
Buffered_repr(BufferedObject *self)
1128+
{
1129+
PyObject *nameobj, *res;
1130+
1131+
nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1132+
if (nameobj == NULL) {
1133+
if (PyErr_ExceptionMatches(PyExc_AttributeError))
1134+
PyErr_Clear();
1135+
else
1136+
return NULL;
1137+
res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1138+
}
1139+
else {
1140+
res = PyUnicode_FromFormat("<%s name=%R>",
1141+
Py_TYPE(self)->tp_name, nameobj);
1142+
Py_DECREF(nameobj);
1143+
}
1144+
return res;
1145+
}
1146+
11261147
/*
11271148
* class BufferedReader
11281149
*/
@@ -1472,7 +1493,7 @@ PyTypeObject PyBufferedReader_Type = {
14721493
0, /*tp_getattr*/
14731494
0, /*tp_setattr*/
14741495
0, /*tp_compare */
1475-
0, /*tp_repr*/
1496+
(reprfunc)Buffered_repr, /*tp_repr*/
14761497
0, /*tp_as_number*/
14771498
0, /*tp_as_sequence*/
14781499
0, /*tp_as_mapping*/
@@ -1828,7 +1849,7 @@ PyTypeObject PyBufferedWriter_Type = {
18281849
0, /*tp_getattr*/
18291850
0, /*tp_setattr*/
18301851
0, /*tp_compare */
1831-
0, /*tp_repr*/
1852+
(reprfunc)Buffered_repr, /*tp_repr*/
18321853
0, /*tp_as_number*/
18331854
0, /*tp_as_sequence*/
18341855
0, /*tp_as_mapping*/
@@ -2219,7 +2240,7 @@ PyTypeObject PyBufferedRandom_Type = {
22192240
0, /*tp_getattr*/
22202241
0, /*tp_setattr*/
22212242
0, /*tp_compare */
2222-
0, /*tp_repr*/
2243+
(reprfunc)Buffered_repr, /*tp_repr*/
22232244
0, /*tp_as_number*/
22242245
0, /*tp_as_sequence*/
22252246
0, /*tp_as_mapping*/

Modules/_io/fileio.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -846,11 +846,26 @@ mode_string(PyFileIOObject *self)
846846
static PyObject *
847847
fileio_repr(PyFileIOObject *self)
848848
{
849+
PyObject *nameobj, *res;
850+
849851
if (self->fd < 0)
850-
return PyUnicode_FromFormat("io.FileIO(-1)");
852+
return PyUnicode_FromFormat("<_io.FileIO [closed]>");
851853

852-
return PyUnicode_FromFormat("io.FileIO(%d, '%s')",
853-
self->fd, mode_string(self));
854+
nameobj = PyObject_GetAttrString((PyObject *) self, "name");
855+
if (nameobj == NULL) {
856+
if (PyErr_ExceptionMatches(PyExc_AttributeError))
857+
PyErr_Clear();
858+
else
859+
return NULL;
860+
res = PyUnicode_FromFormat("<_io.FileIO fd=%d mode='%s'>",
861+
self->fd, mode_string(self));
862+
}
863+
else {
864+
res = PyUnicode_FromFormat("<_io.FileIO name=%R mode='%s'>",
865+
nameobj, mode_string(self));
866+
Py_DECREF(nameobj);
867+
}
868+
return res;
854869
}
855870

856871
static PyObject *

Modules/_io/textio.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,8 +2308,25 @@ TextIOWrapper_truncate(PyTextIOWrapperObject *self, PyObject *args)
23082308
static PyObject *
23092309
TextIOWrapper_repr(PyTextIOWrapperObject *self)
23102310
{
2311-
CHECK_INITIALIZED(self);
2312-
return PyUnicode_FromFormat("<TextIOWrapper encoding=%S>", self->encoding);
2311+
PyObject *nameobj, *res;
2312+
2313+
CHECK_INITIALIZED(self);
2314+
2315+
nameobj = PyObject_GetAttrString((PyObject *) self, "name");
2316+
if (nameobj == NULL) {
2317+
if (PyErr_ExceptionMatches(PyExc_AttributeError))
2318+
PyErr_Clear();
2319+
else
2320+
return NULL;
2321+
res = PyUnicode_FromFormat("<_io.TextIOWrapper encoding=%R>",
2322+
self->encoding);
2323+
}
2324+
else {
2325+
res = PyUnicode_FromFormat("<_io.TextIOWrapper name=%R encoding=%R>",
2326+
nameobj, self->encoding);
2327+
Py_DECREF(nameobj);
2328+
}
2329+
return res;
23132330
}
23142331

23152332

0 commit comments

Comments
 (0)