From 96aeaec64738b730c719562125070a52ed570210 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 May 2019 22:29:40 +0300 Subject: [PATCH] bpo-36793: Remove unneeded __str__ definitions. (GH-13081) Classes that define __str__ the same as __repr__ can just inherit it from object. --- Doc/whatsnew/3.8.rst | 7 +++++++ Lib/_pydecimal.py | 2 -- Lib/asyncore.py | 2 -- Lib/doctest.py | 3 +-- Lib/email/charset.py | 4 +--- Lib/http/client.py | 3 +-- Lib/json/encoder.py | 4 ++-- Lib/logging/__init__.py | 4 +--- Lib/sre_constants.py | 4 +--- Lib/subprocess.py | 1 - Lib/xmlrpc/client.py | 7 +------ .../2019-05-04-16-15-33.bpo-36793.Izog4Z.rst | 3 +++ Modules/_decimal/_decimal.c | 2 +- Modules/_json.c | 4 ++-- Objects/boolobject.c | 2 +- Objects/complexobject.c | 2 +- Objects/floatobject.c | 2 +- Objects/longobject.c | 2 +- 18 files changed, 25 insertions(+), 33 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-05-04-16-15-33.bpo-36793.Izog4Z.rst diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 64ef6e18406..d6388f8faab 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -811,6 +811,13 @@ Changes in Python behavior raised when getting the attribute from the type dictionary are no longer ignored. (Contributed by Serhiy Storchaka in :issue:`35459`.) +* Removed ``__str__`` implementations from builtin types :class:`bool`, + :class:`int`, :class:`float`, :class:`complex` and few classes from + the standard library. They now inherit ``__str__()`` from :class:`object`. + As result, defining the ``__repr__()`` method in the subclass of these + classes will affect they string representation. + (Contributed by Serhiy Storchaka in :issue:`36793`.) + * On AIX, :attr:`sys.platform` doesn't contain the major version anymore. It is always ``'aix'``, instead of ``'aix3'`` .. ``'aix7'``. Since older Python versions include the version number, it is recommended to diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index 44ea5b41b2a..c14d8ca86a1 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -5631,8 +5631,6 @@ class _WorkRep(object): def __repr__(self): return "(%r, %r, %r)" % (self.sign, self.int, self.exp) - __str__ = __repr__ - def _normalize(op1, op2, prec = 0): diff --git a/Lib/asyncore.py b/Lib/asyncore.py index 828f4d4fe78..0e92be3ad19 100644 --- a/Lib/asyncore.py +++ b/Lib/asyncore.py @@ -262,8 +262,6 @@ class dispatcher: status.append(repr(self.addr)) return '<%s at %#x>' % (' '.join(status), id(self)) - __str__ = __repr__ - def add_channel(self, map=None): #self.log_info('adding channel %s' % self) if map is None: diff --git a/Lib/doctest.py b/Lib/doctest.py index 79d91a040c2..bf4889f59e0 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2300,7 +2300,7 @@ class DocTestCase(unittest.TestCase): name = self._dt_test.name.split('.') return "%s (%s)" % (name[-1], '.'.join(name[:-1])) - __str__ = __repr__ + __str__ = object.__str__ def shortDescription(self): return "Doctest: " + self._dt_test.name @@ -2399,7 +2399,6 @@ class DocFileCase(DocTestCase): def __repr__(self): return self._dt_test.filename - __str__ = __repr__ def format_failure(self, err): return ('Failed doctest test for %s\n File "%s", line 0\n\n%s' diff --git a/Lib/email/charset.py b/Lib/email/charset.py index ee564040c68..d3d759ad911 100644 --- a/Lib/email/charset.py +++ b/Lib/email/charset.py @@ -241,11 +241,9 @@ class Charset: self.output_codec = CODEC_MAP.get(self.output_charset, self.output_charset) - def __str__(self): + def __repr__(self): return self.input_charset.lower() - __repr__ = __str__ - def __eq__(self, other): return str(self) == str(other).lower() diff --git a/Lib/http/client.py b/Lib/http/client.py index f71a062d2b5..82908ebe3af 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -1419,8 +1419,7 @@ class IncompleteRead(HTTPException): e = '' return '%s(%i bytes read%s)' % (self.__class__.__name__, len(self.partial), e) - def __str__(self): - return repr(self) + __str__ = object.__str__ class ImproperConnectionState(HTTPException): pass diff --git a/Lib/json/encoder.py b/Lib/json/encoder.py index 2d7b8989c71..c8c78b9c237 100644 --- a/Lib/json/encoder.py +++ b/Lib/json/encoder.py @@ -268,7 +268,7 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, list=list, str=str, tuple=tuple, - _intstr=int.__str__, + _intstr=int.__repr__, ): if _indent is not None and not isinstance(_indent, str): @@ -307,7 +307,7 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, elif value is False: yield buf + 'false' elif isinstance(value, int): - # Subclasses of int/float may override __str__, but we still + # Subclasses of int/float may override __repr__, but we still # want to encode them as integers/floats in JSON. One example # within the standard library is IntEnum. yield buf + _intstr(value) diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 7355396541a..e093982a0cd 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -364,12 +364,10 @@ class LogRecord(object): else: self.process = None - def __str__(self): + def __repr__(self): return ''%(self.name, self.levelno, self.pathname, self.lineno, self.msg) - __repr__ = __str__ - def getMessage(self): """ Return the message for this LogRecord. diff --git a/Lib/sre_constants.py b/Lib/sre_constants.py index 13deb00bc81..8e613cb3fa5 100644 --- a/Lib/sre_constants.py +++ b/Lib/sre_constants.py @@ -59,11 +59,9 @@ class _NamedIntConstant(int): self.name = name return self - def __str__(self): + def __repr__(self): return self.name - __repr__ = __str__ - MAXREPEAT = _NamedIntConstant(MAXREPEAT, 'MAXREPEAT') def _makecodes(names): diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 0496b447e8e..6cc9eb322e2 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -203,7 +203,6 @@ if _mswindows: return "%s(%d)" % (self.__class__.__name__, int(self)) __del__ = Close - __str__ = __repr__ else: # When select or poll has indicated that the file is writable, # we can write up to _PIPE_BUF bytes without risk of blocking. diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index a0e923a2032..b9875745000 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -186,8 +186,7 @@ INTERNAL_ERROR = -32603 class Error(Exception): """Base class for client errors.""" - def __str__(self): - return repr(self) + __str__ = object.__str__ ## # Indicates an HTTP-level protocol error. This is raised by the HTTP @@ -869,8 +868,6 @@ class MultiCall: def __repr__(self): return "<%s at %#x>" % (self.__class__.__name__, id(self)) - __str__ = __repr__ - def __getattr__(self, name): return _MultiCallMethod(self.__call_list, name) @@ -1468,8 +1465,6 @@ class ServerProxy: (self.__class__.__name__, self.__host, self.__handler) ) - __str__ = __repr__ - def __getattr__(self, name): # magic method dispatcher return _Method(self.__request, name) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-05-04-16-15-33.bpo-36793.Izog4Z.rst b/Misc/NEWS.d/next/Core and Builtins/2019-05-04-16-15-33.bpo-36793.Izog4Z.rst new file mode 100644 index 00000000000..6c79f97daca --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-05-04-16-15-33.bpo-36793.Izog4Z.rst @@ -0,0 +1,3 @@ +Removed ``__str__`` implementations from builtin types :class:`bool`, +:class:`int`, :class:`float`, :class:`complex` and few classes from the +standard library. They now inherit ``__str__()`` from :class:`object`. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 51aed2c67dc..d977b14f5b0 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -5390,7 +5390,7 @@ static PyTypeObject PyDecContext_Type = 0, /* tp_as_mapping */ (hashfunc) 0, /* tp_hash */ 0, /* tp_call */ - (reprfunc) context_repr, /* tp_str */ + 0, /* tp_str */ (getattrofunc) context_getattr, /* tp_getattro */ (setattrofunc) context_setattr, /* tp_setattro */ (PyBufferProcs *) 0, /* tp_as_buffer */ diff --git a/Modules/_json.c b/Modules/_json.c index 2d7c1bf1e1c..4faa9cc22ed 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1482,7 +1482,7 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc, return _steal_accumulate(acc, encoded); } else if (PyLong_Check(obj)) { - PyObject *encoded = PyLong_Type.tp_str(obj); + PyObject *encoded = PyLong_Type.tp_repr(obj); if (encoded == NULL) return -1; return _steal_accumulate(acc, encoded); @@ -1646,7 +1646,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, goto bail; } else if (PyLong_Check(key)) { - kstr = PyLong_Type.tp_str(key); + kstr = PyLong_Type.tp_repr(key); if (kstr == NULL) { goto bail; } diff --git a/Objects/boolobject.c b/Objects/boolobject.c index b92fafe620c..508ea61f180 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -147,7 +147,7 @@ PyTypeObject PyBool_Type = { 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ - bool_repr, /* tp_str */ + 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 6e3d47b62d1..cae2bf11dc9 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -1129,7 +1129,7 @@ PyTypeObject PyComplex_Type = { 0, /* tp_as_mapping */ (hashfunc)complex_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)complex_repr, /* tp_str */ + 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ diff --git a/Objects/floatobject.c b/Objects/floatobject.c index b952df88072..adb9b80c271 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1923,7 +1923,7 @@ PyTypeObject PyFloat_Type = { 0, /* tp_as_mapping */ (hashfunc)float_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)float_repr, /* tp_str */ + 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ diff --git a/Objects/longobject.c b/Objects/longobject.c index da697a784fa..9fb1fb02c27 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5592,7 +5592,7 @@ PyTypeObject PyLong_Type = { 0, /* tp_as_mapping */ (hashfunc)long_hash, /* tp_hash */ 0, /* tp_call */ - long_to_decimal_string, /* tp_str */ + 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */