Issue #10872: The repr() of TextIOWrapper objects now includes the mode · python/cpython@a4815ca (original) (raw)

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -1504,13 +1504,20 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None,
1504 1504 # - "chars_..." for integer variables that count decoded characters
1505 1505
1506 1506 def __repr__(self):
1507 +result = "<_pyio.TextIOWrapper"
1507 1508 try:
1508 1509 name = self.name
1509 1510 except AttributeError:
1510 -return "<_pyio.TextIOWrapper encoding={0!r}>".format(self.encoding)
1511 +pass
1512 +else:
1513 +result += " name={0!r}".format(name)
1514 +try:
1515 +mode = self.mode
1516 +except AttributeError:
1517 +pass
1511 1518 else:
1512 -return "<_pyio.TextIOWrapper name={0!r} encoding={1!r}>".format(
1513 - name, self.encoding)
1519 +result += " mode={0!r}".format(mode)
1520 +return result + " encoding={0!r}>".format(self.encoding)
1514 1521
1515 1522 @property
1516 1523 def encoding(self):
Original file line number Diff line number Diff line change
@@ -1717,9 +1717,12 @@ def test_repr(self):
1717 1717 raw.name = "dummy"
1718 1718 self.assertEqual(repr(t),
1719 1719 "<%s.TextIOWrapper name='dummy' encoding='utf-8'>" % modname)
1720 +t.mode = "r"
1721 +self.assertEqual(repr(t),
1722 +"<%s.TextIOWrapper name='dummy' mode='r' encoding='utf-8'>" % modname)
1720 1723 raw.name = b"dummy"
1721 1724 self.assertEqual(repr(t),
1722 -"<%s.TextIOWrapper name=b'dummy' encoding='utf-8'>" % modname)
1725 +"<%s.TextIOWrapper name=b'dummy' mode='r' encoding='utf-8'>" % modname)
1723 1726
1724 1727 def test_line_buffering(self):
1725 1728 r = self.BytesIO()
Original file line number Diff line number Diff line change
@@ -40,6 +40,9 @@ Core and Builtins
40 40 Library
41 41 -------
42 42
43 +- Issue #10872: The repr() of TextIOWrapper objects now includes the mode
44 + if available.
45 +
43 46 - Issue #10869: Fixed bug where ast.increment_lineno modified the root
44 47 node twice.
45 48
Original file line number Diff line number Diff line change
@@ -2323,25 +2323,52 @@ textiowrapper_truncate(textio *self, PyObject *args)
2323 2323 static PyObject *
2324 2324 textiowrapper_repr(textio *self)
2325 2325 {
2326 -PyObject *nameobj, *res;
2326 +PyObject *nameobj, *modeobj, *res, *s;
2327 2327
2328 2328 CHECK_INITIALIZED(self);
2329 2329
2330 +res = PyUnicode_FromString("<_io.TextIOWrapper");
2331 +if (res == NULL)
2332 +return NULL;
2330 2333 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
2331 2334 if (nameobj == NULL) {
2332 2335 if (PyErr_ExceptionMatches(PyExc_AttributeError))
2333 2336 PyErr_Clear();
2334 2337 else
2335 -return NULL;
2336 -res = PyUnicode_FromFormat("<_io.TextIOWrapper encoding=%R>",
2337 -self->encoding);
2338 + goto error;
2338 2339 }
2339 2340 else {
2340 -res = PyUnicode_FromFormat("<_io.TextIOWrapper name=%R encoding=%R>",
2341 -nameobj, self->encoding);
2341 +s = PyUnicode_FromFormat(" name=%R", nameobj);
2342 2342 Py_DECREF(nameobj);
2343 +if (s == NULL)
2344 + goto error;
2345 +PyUnicode_AppendAndDel(&res, s);
2346 +if (res == NULL)
2347 +return NULL;
2343 2348 }
2344 -return res;
2349 +modeobj = PyObject_GetAttrString((PyObject *) self, "mode");
2350 +if (modeobj == NULL) {
2351 +if (PyErr_ExceptionMatches(PyExc_AttributeError))
2352 +PyErr_Clear();
2353 +else
2354 + goto error;
2355 + }
2356 +else {
2357 +s = PyUnicode_FromFormat(" mode=%R", modeobj);
2358 +Py_DECREF(modeobj);
2359 +if (s == NULL)
2360 + goto error;
2361 +PyUnicode_AppendAndDel(&res, s);
2362 +if (res == NULL)
2363 +return NULL;
2364 + }
2365 +s = PyUnicode_FromFormat("%U encoding=%R>",
2366 +res, self->encoding);
2367 +Py_DECREF(res);
2368 +return s;
2369 +error:
2370 +Py_XDECREF(res);
2371 +return NULL;
2345 2372 }
2346 2373
2347 2374