[pypy-commit] pypy py3.7-bpo-27541: Implement bpo-27541: Reprs of subclasses of some classes now contain actual type name

Yannick_Jadoul pypy.commits at gmail.com
Mon Dec 30 17:29:23 EST 2019


Author: Yannick Jadoul <yannick.jadoul at belgacom.net>
Branch: py3.7-bpo-27541
Changeset: r98418:fc33829c0465
Date: 2019-12-30 23:28 +0100
http://bitbucket.org/pypy/pypy/changeset/fc33829c0465/

Log:	Implement bpo-27541: Reprs of subclasses of some classes now contain
	actual type name

diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py
--- a/lib_pypy/_collections.py
+++ b/lib_pypy/_collections.py
@@ -211,14 +211,14 @@
     def __repr__(self):
         threadlocalattr = '__repr' + str(_thread_ident())
         if threadlocalattr in self.__dict__:
-            return 'deque([...])'
+            return '%s([...])' % (self.__class__.__name__,)
         else:
             self.__dict__[threadlocalattr] = True
             try:
                 if self.maxlen is not None:
-                    return 'deque(%r, maxlen=%s)' % (list(self), self.maxlen)
+                    return '%s(%r, maxlen=%s)' % (self.__class__.__name__, list(self), self.maxlen)
                 else:
-                    return 'deque(%r)' % (list(self),)
+                    return '%s(%r)' % (self.__class__.__name__, list(self))
             finally:
                 del self.__dict__[threadlocalattr]
 
@@ -411,10 +411,10 @@
 
     def __repr__(self, recurse=set()):
         if id(self) in recurse:
-            return "defaultdict(...)"
+            return "%s(...)" % (self.__class__.__name__,)
         try:
             recurse.add(id(self))
-            return "defaultdict(%s, %s)" % (repr(self.default_factory), super(defaultdict, self).__repr__())
+            return "%s(%s, %s)" % (self.__class__.__name__, repr(self.default_factory), super(defaultdict, self).__repr__())
         finally:
             recurse.remove(id(self))
 
diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py
--- a/pypy/module/_collections/app_defaultdict.py
+++ b/pypy/module/_collections/app_defaultdict.py
@@ -40,7 +40,7 @@
                 factoryrepr = repr(self.default_factory)
             finally:
                 recurse.remove(id(self))
-        return "defaultdict(%s, %s)" % (factoryrepr, dictrepr)
+        return "%s(%s, %s)" % (self.__class__.__name__, factoryrepr, dictrepr)
 
     def copy(self):
         return type(self)(self.default_factory, self)
diff --git a/pypy/module/_collections/interp_deque.py b/pypy/module/_collections/interp_deque.py
--- a/pypy/module/_collections/interp_deque.py
+++ b/pypy/module/_collections/interp_deque.py
@@ -536,7 +536,7 @@
             maxlenrepr = ''
         else:
             maxlenrepr = ', maxlen=%d' % (d.maxlen,)
-        return 'deque(%s%s)' % (listrepr, maxlenrepr)
+        return '%s(%s%s)' % (d.__class__.__name__, listrepr, maxlenrepr)
 """, filename=__file__)
 
 dequerepr = app.interphook("dequerepr")
diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py
--- a/pypy/module/_collections/test/test_defaultdict.py
+++ b/pypy/module/_collections/test/test_defaultdict.py
@@ -98,4 +98,10 @@
                 pass
         d = X.__new__(X)
         d.__init__(d.mydefault)
-        assert repr(d).endswith('defaultdict(..., {})>, {})')
+        assert repr(d).endswith('X(..., {})>, {})')
+
+    def test_subclass_repr(self):
+        import _collections
+        class subclass(_collections.defaultdict):
+            pass
+        assert repr(subclass()) == 'subclass(None, {})'
diff --git a/pypy/module/_collections/test/test_deque.py b/pypy/module/_collections/test/test_deque.py
--- a/pypy/module/_collections/test/test_deque.py
+++ b/pypy/module/_collections/test/test_deque.py
@@ -448,3 +448,9 @@
         elements = 'ABCDEFGHI'
         d = deque([-2, -1, 0, 0, 1, 2])
         assert d.index(0, -4*sys.maxsize, 4*sys.maxsize) == 2
+
+    def test_subclass_repr(self):
+        from _collections import deque
+        class subclass(deque):
+            pass
+        assert repr(subclass()) == 'subclass([])'
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -766,8 +766,9 @@
     # Misc methods
 
     def descr_repr(self, space):
+        cls_name = space.type(self).getname(space)
         if self.len == 0:
-            return space.newtext("array('%s')" % self.typecode)
+            return space.newtext("%s('%s')" % (cls_name, self.typecode))
         elif self.typecode == "u":
             try:
                 w_unicode = self.descr_tounicode(space)
@@ -778,11 +779,11 @@
                 r = "<%s>" % (space.text_w(w_exc_value),)
             else:
                 r = space.text_w(space.repr(w_unicode))
-            s = "array('%s', %s)" % (self.typecode, r)
+            s = "%s('%s', %s)" % (cls_name, self.typecode, r)
             return space.newtext(s)
         else:
             r = space.repr(self.descr_tolist(space))
-            s = "array('%s', %s)" % (self.typecode, space.text_w(r))
+            s = "%s('%s', %s)" % (cls_name, self.typecode, space.text_w(r))
             return space.newtext(s)
 
     def check_valid_unicode(self, space, s):
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -864,25 +864,25 @@
             def extend(self, lst):
                 self.append(10)
 
-        assert repr(mya('u', 'hi')) == "array('u', 'hi')"
-        assert repr(mya('i', [1, 2, 3])) == "array('i', [1, 2, 3])"
-        assert repr(mya('i', (1, 2, 3))) == "array('i', [1, 2, 3])"
+        assert repr(mya('u', 'hi')) == "mya('u', 'hi')"
+        assert repr(mya('i', [1, 2, 3])) == "mya('i', [1, 2, 3])"
+        assert repr(mya('i', (1, 2, 3))) == "mya('i', [1, 2, 3])"
 
         a = mya('i')
         a.fromlist([1, 2, 3])
-        assert repr(a) == "array('i', [7])"
+        assert repr(a) == "mya('i', [7])"
 
         a = mya('b')
         a.fromstring(b'hi')
-        assert repr(a) == "array('b', [8])"
+        assert repr(a) == "mya('b', [8])"
 
         a = mya('u')
         a.fromunicode('hi')
-        assert repr(a) == "array('u', '9')"
+        assert repr(a) == "mya('u', '9')"
 
         a = mya('i')
         a.extend([1, 2, 3])
-        assert repr(a) == "array('i', [10])"
+        assert repr(a) == "mya('i', [10])"
 
     def test_override_to(self):
         class mya(self.array):
@@ -899,9 +899,9 @@
         assert mya('u', 'hi').tobytes() == 'str'
         assert mya('u', 'hi').tounicode() == 'unicode'
 
-        assert repr(mya('u', 'hi')) == "array('u', 'hi')"
-        assert repr(mya('i', [1, 2, 3])) == "array('i', [1, 2, 3])"
-        assert repr(mya('i', (1, 2, 3))) == "array('i', [1, 2, 3])"
+        assert repr(mya('u', 'hi')) == "mya('u', 'hi')"
+        assert repr(mya('i', [1, 2, 3])) == "mya('i', [1, 2, 3])"
+        assert repr(mya('i', (1, 2, 3))) == "mya('i', [1, 2, 3])"
 
     def test_unicode_outofrange(self):
         input_unicode = u'\x01\u263a\x00\ufeff'
@@ -1111,6 +1111,12 @@
         struct.pack_into('>H', view, 1, 0x1234)
         assert a.tobytes() == b'ab\x12\x34ef'
 
+    def test_subclass_repr(self):
+        import array
+        class subclass(self.array):
+            pass
+        assert repr(subclass('i')) == "subclass('i')"
+
 
 class AppTestArrayReconstructor:
     spaceconfig = dict(usemodules=('array', 'struct'))
diff --git a/pypy/module/itertools/interp_itertools.py b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -27,12 +27,13 @@
 
     def repr_w(self):
         space = self.space
+        cls_name = space.type(self).getname(space)
         c = space.text_w(space.repr(self.w_c))
         if self.single_argument():
-            s = 'count(%s)' % (c,)
+            s = '%s(%s)' % (cls_name, c)
         else:
             step = space.text_w(space.repr(self.w_step))
-            s = 'count(%s, %s)' % (c, step)
+            s = '%s(%s, %s)' % (cls_name, c, step)
         return self.space.newtext(s)
 
     def reduce_w(self):
@@ -107,11 +108,13 @@
         return self.space.newint(self.count)
 
     def repr_w(self):
-        objrepr = self.space.text_w(self.space.repr(self.w_obj))
+        space = self.space
+        cls_name = space.type(self).getname(space)
+        objrepr = self.space.text_w(space.repr(self.w_obj))
         if self.counting:
-            s = 'repeat(%s, %d)' % (objrepr, self.count)
+            s = '%s(%s, %d)' % (cls_name, objrepr, self.count)
         else:
-            s = 'repeat(%s)' % (objrepr,)
+            s = '%s(%s)' % (cls_name, objrepr)
         return self.space.newtext(s)
 
     def descr_reduce(self):
diff --git a/pypy/module/itertools/test/test_itertools.py b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -36,6 +36,12 @@
         raises(TypeError, itertools.count, 'a')
         raises(TypeError, itertools.count, [])
 
+    def test_count_subclass_repr(self):
+        import itertools
+        class subclass(itertools.count):
+            pass
+        assert repr(subclass(123)) == 'subclass(123)'
+
     def test_repeat(self):
         import itertools
 
@@ -99,6 +105,12 @@
         r = itertools.repeat('a', -3)
         assert operator.length_hint(r, 3) == 0
 
+    def test_repeat_subclass_repr(self):
+        import itertools
+        class subclass(itertools.repeat):
+            pass
+        assert repr(subclass('foobar')) == "subclass('foobar')"
+
     def test_takewhile(self):
         import itertools
 
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -222,11 +222,13 @@
 
     def descr_repr(self, space):
         s, start, end, _ = self._convert_idx_params(space, None, None)
+        cls_name = space.type(self).getname(space)
 
         # Good default if there are no replacements.
-        buf = StringBuilder(len("bytearray(b'')") + (end - start))
+        buf = StringBuilder(len(cls_name) + len("(b'')") + (end - start))
 
-        buf.append("bytearray(b")
+        buf.append(cls_name)
+        buf.append("(b")
         quote = "'"
         for i in range(start, end):
             c = s[i]
diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py
--- a/pypy/objspace/std/test/test_bytearrayobject.py
+++ b/pypy/objspace/std/test/test_bytearrayobject.py
@@ -764,3 +764,8 @@
         assert x.find(b'fe') == -1
         assert x.index(b'f', 2, 11) == 5
         assert x.__alloc__() == 14
+
+    def test_subclass_repr(self):
+        class subclass(bytearray):
+            pass
+        assert repr(subclass(b'test')) == "subclass(b'test')"


More information about the pypy-commit mailing list