diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 9058ee69500..d23b0329f36 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -808,13 +808,14 @@ class _BufferedIOMixin(BufferedIOBase): .format(self.__class__.__name__)) def __repr__(self): - clsname = self.__class__.__name__ + modname = self.__class__.__module__ + clsname = self.__class__.__qualname__ try: name = self.name except AttributeError: - return "<_pyio.{0}>".format(clsname) + return "<{}.{}>".format(modname, clsname) else: - return "<_pyio.{0} name={1!r}>".format(clsname, name) + return "<{}.{} name={!r}>".format(modname, clsname, name) ### Lower-level APIs ### @@ -1635,7 +1636,8 @@ class TextIOWrapper(TextIOBase): # - "chars_..." for integer variables that count decoded characters def __repr__(self): - result = "<_pyio.TextIOWrapper" + result = "<{}.{}".format(self.__class__.__module__, + self.__class__.__qualname__) try: name = self.name except AttributeError: diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index acd05d0b2aa..c13b3b6b290 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -302,17 +302,20 @@ class Future(object): with self._condition: if self._state == FINISHED: if self._exception: - return '' % ( - hex(id(self)), + return '<%s at %#x state=%s raised %s>' % ( + self.__class__.__name__, + id(self), _STATE_TO_DESCRIPTION_MAP[self._state], self._exception.__class__.__name__) else: - return '' % ( - hex(id(self)), + return '<%s at %#x state=%s returned %s>' % ( + self.__class__.__name__, + id(self), _STATE_TO_DESCRIPTION_MAP[self._state], self._result.__class__.__name__) - return '' % ( - hex(id(self)), + return '<%s at %#x state=%s>' % ( + self.__class__.__name__, + id(self), _STATE_TO_DESCRIPTION_MAP[self._state]) def cancel(self): diff --git a/Lib/datetime.py b/Lib/datetime.py index 3c534d09f26..64a3d5ac5a1 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -414,15 +414,19 @@ class timedelta: def __repr__(self): if self._microseconds: - return "%s(%d, %d, %d)" % ('datetime.' + self.__class__.__name__, - self._days, - self._seconds, - self._microseconds) + return "%s.%s(%d, %d, %d)" % (self.__class__.__module__, + self.__class__.__qualname__, + self._days, + self._seconds, + self._microseconds) if self._seconds: - return "%s(%d, %d)" % ('datetime.' + self.__class__.__name__, - self._days, - self._seconds) - return "%s(%d)" % ('datetime.' + self.__class__.__name__, self._days) + return "%s.%s(%d, %d)" % (self.__class__.__module__, + self.__class__.__qualname__, + self._days, + self._seconds) + return "%s.%s(%d)" % (self.__class__.__module__, + self.__class__.__qualname__, + self._days) def __str__(self): mm, ss = divmod(self._seconds, 60) @@ -700,10 +704,11 @@ class date: >>> repr(dt) 'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)' """ - return "%s(%d, %d, %d)" % ('datetime.' + self.__class__.__name__, - self._year, - self._month, - self._day) + return "%s.%s(%d, %d, %d)" % (self.__class__.__module__, + self.__class__.__qualname__, + self._year, + self._month, + self._day) # XXX These shouldn't depend on time.localtime(), because that # clips the usable dates to [1970 .. 2038). At least ctime() is # easily done without using strftime() -- that's better too because @@ -1155,8 +1160,9 @@ class time: s = ", %d" % self._second else: s = "" - s= "%s(%d, %d%s)" % ('datetime.' + self.__class__.__name__, - self._hour, self._minute, s) + s= "%s.%s(%d, %d%s)" % (self.__class__.__module__, + self.__class__.__qualname__, + self._hour, self._minute, s) if self._tzinfo is not None: assert s[-1:] == ")" s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")" @@ -1569,8 +1575,9 @@ class datetime(date): del L[-1] if L[-1] == 0: del L[-1] - s = ", ".join(map(str, L)) - s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s) + s = "%s.%s(%s)" % (self.__class__.__module__, + self.__class__.__qualname__, + ", ".join(map(str, L))) if self._tzinfo is not None: assert s[-1:] == ")" s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")" @@ -1857,10 +1864,12 @@ class timezone(tzinfo): if self is self.utc: return 'datetime.timezone.utc' if self._name is None: - return "%s(%r)" % ('datetime.' + self.__class__.__name__, - self._offset) - return "%s(%r, %r)" % ('datetime.' + self.__class__.__name__, - self._offset, self._name) + return "%s.%s(%r)" % (self.__class__.__module__, + self.__class__.__qualname__, + self._offset) + return "%s.%s(%r, %r)" % (self.__class__.__module__, + self.__class__.__qualname__, + self._offset, self._name) def __str__(self): return self.tzname(None) diff --git a/Lib/doctest.py b/Lib/doctest.py index be824f45d8b..b2279524e14 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -533,8 +533,9 @@ class DocTest: examples = '1 example' else: examples = '%d examples' % len(self.examples) - return ('' % - (self.name, self.filename, self.lineno, examples)) + return ('<%s %s from %s:%s (%s)>' % + (self.__class__.__name__, + self.name, self.filename, self.lineno, examples)) def __eq__(self, other): if type(self) is not type(other): diff --git a/Lib/email/headerregistry.py b/Lib/email/headerregistry.py index 1fae950820a..2bdae6cdeb4 100644 --- a/Lib/email/headerregistry.py +++ b/Lib/email/headerregistry.py @@ -80,7 +80,8 @@ class Address: return lp def __repr__(self): - return "Address(display_name={!r}, username={!r}, domain={!r})".format( + return "{}(display_name={!r}, username={!r}, domain={!r})".format( + self.__class__.__name__, self.display_name, self.username, self.domain) def __str__(self): @@ -131,7 +132,8 @@ class Group: return self._addresses def __repr__(self): - return "Group(display_name={!r}, addresses={!r}".format( + return "{}(display_name={!r}, addresses={!r}".format( + self.__class__.__name__, self.display_name, self.addresses) def __str__(self): diff --git a/Lib/fractions.py b/Lib/fractions.py index 43f146f9391..57bf7f50431 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -280,7 +280,8 @@ class Fraction(numbers.Rational): def __repr__(self): """repr(self)""" - return ('Fraction(%s, %s)' % (self._numerator, self._denominator)) + return '%s(%s, %s)' % (self.__class__.__name__, + self._numerator, self._denominator) def __str__(self): """str(self)""" diff --git a/Lib/http/client.py b/Lib/http/client.py index ad5590c45ec..57e932d2292 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -1334,7 +1334,8 @@ class IncompleteRead(HTTPException): e = ', %i more expected' % self.expected else: e = '' - return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e) + return '%s(%i bytes read%s)' % (self.__class__.__name__, + len(self.partial), e) def __str__(self): return repr(self) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 2ddd523bbaf..d5633506c6e 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -805,7 +805,7 @@ class Cookie: args.append("%s=%s" % (name, repr(attr))) args.append("rest=%s" % repr(self._rest)) args.append("rfc2109=%s" % repr(self.rfc2109)) - return "Cookie(%s)" % ", ".join(args) + return "%s(%s)" % (self.__class__.__name__, ", ".join(args)) class CookiePolicy: diff --git a/Lib/idlelib/WidgetRedirector.py b/Lib/idlelib/WidgetRedirector.py index b3d7bfa3c40..67d7f61e623 100644 --- a/Lib/idlelib/WidgetRedirector.py +++ b/Lib/idlelib/WidgetRedirector.py @@ -47,8 +47,9 @@ class WidgetRedirector: tk.createcommand(w, self.dispatch) def __repr__(self): - return "WidgetRedirector(%s<%s>)" % (self.widget.__class__.__name__, - self.widget._w) + return "%s(%s<%s>)" % (self.__class__.__name__, + self.widget.__class__.__name__, + self.widget._w) def close(self): "Unregister operations and revert redirection created by .__init__." @@ -142,7 +143,8 @@ class OriginalCommand: self.orig_and_operation = (redir.orig, operation) def __repr__(self): - return "OriginalCommand(%r, %r)" % (self.redir, self.operation) + return "%s(%r, %r)" % (self.__class__.__name__, + self.redir, self.operation) def __call__(self, *args): return self.tk_call(self.orig_and_operation + args) diff --git a/Lib/multiprocessing/dummy/__init__.py b/Lib/multiprocessing/dummy/__init__.py index 135db7f77f9..1abea64419b 100644 --- a/Lib/multiprocessing/dummy/__init__.py +++ b/Lib/multiprocessing/dummy/__init__.py @@ -86,7 +86,7 @@ class Namespace(object): if not name.startswith('_'): temp.append('%s=%r' % (name, value)) temp.sort() - return 'Namespace(%s)' % str.join(', ', temp) + return '%s(%s)' % (self.__class__.__name__, ', '.join(temp)) dict = dict list = list diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index 820ae917641..776656ea176 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -65,8 +65,8 @@ class Token(object): (self.typeid, self.address, self.id) = state def __repr__(self): - return 'Token(typeid=%r, address=%r, id=%r)' % \ - (self.typeid, self.address, self.id) + return '%s(typeid=%r, address=%r, id=%r)' % \ + (self.__class__.__name__, self.typeid, self.address, self.id) # # Function for communication with a manager's server process @@ -803,8 +803,8 @@ class BaseProxy(object): return self._getvalue() def __repr__(self): - return '<%s object, typeid %r at %s>' % \ - (type(self).__name__, self._token.typeid, '0x%x' % id(self)) + return '<%s object, typeid %r at %#x>' % \ + (type(self).__name__, self._token.typeid, id(self)) def __str__(self): ''' @@ -901,7 +901,7 @@ class Namespace(object): if not name.startswith('_'): temp.append('%s=%r' % (name, value)) temp.sort() - return 'Namespace(%s)' % str.join(', ', temp) + return '%s(%s)' % (self.__class__.__name__, ', '.join(temp)) class Value(object): def __init__(self, typecode, value, lock=True): diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py index 77eb817c3da..75a76a46790 100644 --- a/Lib/multiprocessing/pool.py +++ b/Lib/multiprocessing/pool.py @@ -87,7 +87,7 @@ class MaybeEncodingError(Exception): self.exc) def __repr__(self): - return "" % str(self) + return "<%s: %s>" % (self.__class__.__name__, self) def worker(inqueue, outqueue, initializer=None, initargs=(), maxtasks=None, diff --git a/Lib/multiprocessing/synchronize.py b/Lib/multiprocessing/synchronize.py index 7d443307313..d4bdf0e8b17 100644 --- a/Lib/multiprocessing/synchronize.py +++ b/Lib/multiprocessing/synchronize.py @@ -134,7 +134,7 @@ class Semaphore(SemLock): value = self._semlock._get_value() except Exception: value = 'unknown' - return '' % value + return '<%s(value=%s)>' % (self.__class__.__name__, value) # # Bounded semaphore @@ -150,8 +150,8 @@ class BoundedSemaphore(Semaphore): value = self._semlock._get_value() except Exception: value = 'unknown' - return '' % \ - (value, self._semlock.maxvalue) + return '<%s(value=%s, maxvalue=%s)>' % \ + (self.__class__.__name__, value, self._semlock.maxvalue) # # Non-recursive lock @@ -176,7 +176,7 @@ class Lock(SemLock): name = 'SomeOtherProcess' except Exception: name = 'unknown' - return '' % name + return '<%s(owner=%s)>' % (self.__class__.__name__, name) # # Recursive lock @@ -202,7 +202,7 @@ class RLock(SemLock): name, count = 'SomeOtherProcess', 'nonzero' except Exception: name, count = 'unknown', 'unknown' - return '' % (name, count) + return '<%s(%s, %s)>' % (self.__class__.__name__, name, count) # # Condition variable @@ -243,7 +243,7 @@ class Condition(object): self._woken_count._semlock._get_value()) except Exception: num_waiters = 'unknown' - return '' % (self._lock, num_waiters) + return '<%s(%s, %s)>' % (self.__class__.__name__, self._lock, num_waiters) def wait(self, timeout=None): assert self._lock._semlock._is_mine(), \ diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py index 8760c823df3..ea5443d6322 100644 --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -212,10 +212,11 @@ class Finalize(object): obj = None if obj is None: - return '' + return '<%s object, dead>' % self.__class__.__name__ - x = '' + return '<%s.%s instance>' % (self.__class__.__module__, + self.__class__.__qualname__) _GoInteractive = object() def __call__(self, request=_GoInteractive): diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 49aa6ab9836..6dfa40b4b90 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -464,7 +464,7 @@ if mswindows: raise ValueError("already closed") def __repr__(self): - return "Handle(%d)" % int(self) + return "%s(%d)" % (self.__class__.__name__, int(self)) __del__ = Close __str__ = __repr__ diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index a2a912d2abc..dfb947c3201 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -641,7 +641,7 @@ class Quoter(collections.defaultdict): def __repr__(self): # Without this, will just display as a defaultdict - return "" % dict(self) + return "<%s %r>" % (self.__class__.__name__, dict(self)) def __missing__(self, b): # Handle a cache miss. Store quoted string in cache and return. diff --git a/Lib/uuid.py b/Lib/uuid.py index a4e553247d9..a43bffa4c5a 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -222,7 +222,7 @@ class UUID(object): return self.int def __repr__(self): - return 'UUID(%r)' % str(self) + return '%s(%r)' % (self.__class__.__name__, str(self)) def __setattr__(self, name, value): raise TypeError('UUID objects are immutable') diff --git a/Lib/weakref.py b/Lib/weakref.py index f780e7a4692..33b8cbc3778 100644 --- a/Lib/weakref.py +++ b/Lib/weakref.py @@ -144,7 +144,7 @@ class WeakValueDictionary(collections.MutableMapping): return o is not None def __repr__(self): - return "" % id(self) + return "<%s at %#x>" % (self.__class__.__name__, id(self)) def __setitem__(self, key, value): if self._pending_removals: @@ -348,7 +348,7 @@ class WeakKeyDictionary(collections.MutableMapping): return len(self.data) - len(self._pending_removals) def __repr__(self): - return "" % id(self) + return "<%s at %#x>" % (self.__class__.__name__, id(self)) def __setitem__(self, key, value): self.data[ref(key, self._remove)] = value diff --git a/Lib/wsgiref/headers.py b/Lib/wsgiref/headers.py index 7931bc79189..7e670b3caf1 100644 --- a/Lib/wsgiref/headers.py +++ b/Lib/wsgiref/headers.py @@ -131,7 +131,7 @@ class Headers: return self._headers[:] def __repr__(self): - return "Headers(%r)" % self._headers + return "%s(%r)" % (self.__class__.__name__, self._headers) def __str__(self): """str() returns the formatted headers, complete with end line, diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index c379a332e1d..c76b14d6a4c 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -648,9 +648,10 @@ class TypeInfo(object): def __repr__(self): if self.namespace: - return "" % (self.name, self.namespace) + return "<%s %r (from %r)>" % (self.__class__.__name__, self.name, + self.namespace) else: - return "" % self.name + return "<%s %r>" % (self.__class__.__name__, self.name) def _get_name(self): return self.name diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index d9e98078c8e..6c1345a5ad6 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -174,7 +174,7 @@ class Element: self._children = [] def __repr__(self): - return "" % (repr(self.tag), id(self)) + return "<%s %r at %#x>" % (self.__class__.__name__, self.tag, id(self)) def makeelement(self, tag, attrib): """Create a new element with the same type. @@ -509,7 +509,7 @@ class QName: def __str__(self): return self.text def __repr__(self): - return '' % (self.text,) + return '<%s %r>' % (self.__class__.__name__, self.text) def __hash__(self): return hash(self.text) def __le__(self, other): diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index d46f32c8df7..3a1435d6111 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -207,8 +207,8 @@ class ProtocolError(Error): self.headers = headers def __repr__(self): return ( - "" % - (self.url, self.errcode, self.errmsg) + "<%s for %s: %s %s>" % + (self.__class__.__name__, self.url, self.errcode, self.errmsg) ) ## @@ -236,7 +236,8 @@ class Fault(Error): self.faultCode = faultCode self.faultString = faultString def __repr__(self): - return "" % (self.faultCode, self.faultString) + return "<%s %s: %r>" % (self.__class__.__name__, + self.faultCode, self.faultString) # -------------------------------------------------------------------- # Special values @@ -354,7 +355,7 @@ class DateTime: return self.value def __repr__(self): - return "" % (self.value, id(self)) + return "<%s %r at %#x>" % (self.__class__.__name__, self.value, id(self)) def decode(self, data): self.value = str(data).strip() @@ -846,7 +847,7 @@ class MultiCall: self.__call_list = [] def __repr__(self): - return "" % id(self) + return "<%s at %#x>" % (self.__class__.__name__, id(self)) __str__ = __repr__ @@ -1426,8 +1427,8 @@ class ServerProxy: def __repr__(self): return ( - "" % - (self.__host, self.__handler) + "<%s for %s%s>" % + (self.__class__.__name__, self.__host, self.__handler) ) __str__ = __repr__ diff --git a/Misc/NEWS b/Misc/NEWS index f1db374a540..705988808a8 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -108,6 +108,9 @@ Core and Builtins Library ------- +- Issue #22033: Reprs of most Python implemened classes now contain actual + class name instead of hardcoded one. + - Issue #21947: The dis module can now disassemble generator-iterator objects based on their gi_code attribute. Patch by Clement Rouault.