]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-104231: Add more tests for str(), repr(), ascii(), and bytes() (GH-112551)
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 30 Nov 2023 15:22:04 +0000 (17:22 +0200)
committerGitHub <noreply@github.com>
Thu, 30 Nov 2023 15:22:04 +0000 (17:22 +0200)
Lib/test/test_bytes.py
Lib/test/test_str.py

index afd506f07520d85ca99a0c5de9831670bb3df4ca..a3804a945f2e3a4fe7d80c69bb3a4e2e3880d6dc 100644 (file)
@@ -46,6 +46,10 @@ class Indexable:
 
 class BaseBytesTest:
 
+    def assertTypedEqual(self, actual, expected):
+        self.assertIs(type(actual), type(expected))
+        self.assertEqual(actual, expected)
+
     def test_basics(self):
         b = self.type2test()
         self.assertEqual(type(b), self.type2test)
@@ -1023,36 +1027,63 @@ class BytesTest(BaseBytesTest, unittest.TestCase):
             self.assertRaises(TypeError, f.readinto, b"")
 
     def test_custom(self):
-        class A:
-            def __bytes__(self):
-                return b'abc'
-        self.assertEqual(bytes(A()), b'abc')
-        class A: pass
-        self.assertRaises(TypeError, bytes, A())
-        class A:
-            def __bytes__(self):
-                return None
-        self.assertRaises(TypeError, bytes, A())
-        class A:
+        self.assertEqual(bytes(BytesSubclass(b'abc')), b'abc')
+        self.assertEqual(BytesSubclass(OtherBytesSubclass(b'abc')),
+                         BytesSubclass(b'abc'))
+        self.assertEqual(bytes(WithBytes(b'abc')), b'abc')
+        self.assertEqual(BytesSubclass(WithBytes(b'abc')), BytesSubclass(b'abc'))
+
+        class NoBytes: pass
+        self.assertRaises(TypeError, bytes, NoBytes())
+        self.assertRaises(TypeError, bytes, WithBytes('abc'))
+        self.assertRaises(TypeError, bytes, WithBytes(None))
+        class IndexWithBytes:
             def __bytes__(self):
                 return b'a'
             def __index__(self):
                 return 42
-        self.assertEqual(bytes(A()), b'a')
+        self.assertEqual(bytes(IndexWithBytes()), b'a')
         # Issue #25766
-        class A(str):
+        class StrWithBytes(str):
+            def __new__(cls, value):
+                self = str.__new__(cls, '\u20ac')
+                self.value = value
+                return self
             def __bytes__(self):
-                return b'abc'
-        self.assertEqual(bytes(A('\u20ac')), b'abc')
-        self.assertEqual(bytes(A('\u20ac'), 'iso8859-15'), b'\xa4')
+                return self.value
+        self.assertEqual(bytes(StrWithBytes(b'abc')), b'abc')
+        self.assertEqual(bytes(StrWithBytes(b'abc'), 'iso8859-15'), b'\xa4')
+        self.assertEqual(bytes(StrWithBytes(BytesSubclass(b'abc'))), b'abc')
+        self.assertEqual(BytesSubclass(StrWithBytes(b'abc')), BytesSubclass(b'abc'))
+        self.assertEqual(BytesSubclass(StrWithBytes(b'abc'), 'iso8859-15'),
+                         BytesSubclass(b'\xa4'))
+        self.assertEqual(BytesSubclass(StrWithBytes(BytesSubclass(b'abc'))),
+                         BytesSubclass(b'abc'))
+        self.assertEqual(BytesSubclass(StrWithBytes(OtherBytesSubclass(b'abc'))),
+                         BytesSubclass(b'abc'))
         # Issue #24731
-        class A:
+        self.assertTypedEqual(bytes(WithBytes(BytesSubclass(b'abc'))), BytesSubclass(b'abc'))
+        self.assertTypedEqual(BytesSubclass(WithBytes(BytesSubclass(b'abc'))),
+                              BytesSubclass(b'abc'))
+        self.assertTypedEqual(BytesSubclass(WithBytes(OtherBytesSubclass(b'abc'))),
+                              BytesSubclass(b'abc'))
+
+        class BytesWithBytes(bytes):
+            def __new__(cls, value):
+                self = bytes.__new__(cls, b'\xa4')
+                self.value = value
+                return self
             def __bytes__(self):
-                return OtherBytesSubclass(b'abc')
-        self.assertEqual(bytes(A()), b'abc')
-        self.assertIs(type(bytes(A())), OtherBytesSubclass)
-        self.assertEqual(BytesSubclass(A()), b'abc')
-        self.assertIs(type(BytesSubclass(A())), BytesSubclass)
+                return self.value
+        self.assertTypedEqual(bytes(BytesWithBytes(b'abc')), b'abc')
+        self.assertTypedEqual(BytesSubclass(BytesWithBytes(b'abc')),
+                              BytesSubclass(b'abc'))
+        self.assertTypedEqual(bytes(BytesWithBytes(BytesSubclass(b'abc'))),
+                              BytesSubclass(b'abc'))
+        self.assertTypedEqual(BytesSubclass(BytesWithBytes(BytesSubclass(b'abc'))),
+                              BytesSubclass(b'abc'))
+        self.assertTypedEqual(BytesSubclass(BytesWithBytes(OtherBytesSubclass(b'abc'))),
+                              BytesSubclass(b'abc'))
 
     # Test PyBytes_FromFormat()
     def test_from_format(self):
@@ -2069,6 +2100,12 @@ class BytesSubclass(bytes):
 class OtherBytesSubclass(bytes):
     pass
 
+class WithBytes:
+    def __init__(self, value):
+        self.value = value
+    def __bytes__(self):
+        return self.value
+
 class ByteArraySubclassTest(SubclassTest, unittest.TestCase):
     basetype = bytearray
     type2test = ByteArraySubclass
index 814ef111c5bec8d3fcdc154706d3f806b09e3bd9..b4927113db44e3eea1e21acab3634f1f6aa99175 100644 (file)
@@ -55,6 +55,21 @@ def duplicate_string(text):
 class StrSubclass(str):
     pass
 
+class OtherStrSubclass(str):
+    pass
+
+class WithStr:
+    def __init__(self, value):
+        self.value = value
+    def __str__(self):
+        return self.value
+
+class WithRepr:
+    def __init__(self, value):
+        self.value = value
+    def __repr__(self):
+        return self.value
+
 class StrTest(string_tests.StringLikeTest,
         string_tests.MixinStrUnicodeTest,
         unittest.TestCase):
@@ -83,6 +98,10 @@ class StrTest(string_tests.StringLikeTest,
             self.assertEqual(realresult, result)
             self.assertTrue(object is not realresult)
 
+    def assertTypedEqual(self, actual, expected):
+        self.assertIs(type(actual), type(expected))
+        self.assertEqual(actual, expected)
+
     def test_literals(self):
         self.assertEqual('\xff', '\u00ff')
         self.assertEqual('\uffff', '\U0000ffff')
@@ -127,10 +146,13 @@ class StrTest(string_tests.StringLikeTest,
         self.assertEqual(ascii("\U00010000" * 39 + "\uffff" * 4096),
                             ascii("\U00010000" * 39 + "\uffff" * 4096))
 
-        class WrongRepr:
-            def __repr__(self):
-                return b'byte-repr'
-        self.assertRaises(TypeError, ascii, WrongRepr())
+        self.assertTypedEqual(ascii('\U0001f40d'), r"'\U0001f40d'")
+        self.assertTypedEqual(ascii(StrSubclass('abc')), "'abc'")
+        self.assertTypedEqual(ascii(WithRepr('<abc>')), '<abc>')
+        self.assertTypedEqual(ascii(WithRepr(StrSubclass('<abc>'))), StrSubclass('<abc>'))
+        self.assertTypedEqual(ascii(WithRepr('<\U0001f40d>')), r'<\U0001f40d>')
+        self.assertTypedEqual(ascii(WithRepr(StrSubclass('<\U0001f40d>'))), r'<\U0001f40d>')
+        self.assertRaises(TypeError, ascii, WithRepr(b'byte-repr'))
 
     def test_repr(self):
         # Test basic sanity of repr()
@@ -168,10 +190,13 @@ class StrTest(string_tests.StringLikeTest,
         self.assertEqual(repr("\U00010000" * 39 + "\uffff" * 4096),
                             repr("\U00010000" * 39 + "\uffff" * 4096))
 
-        class WrongRepr:
-            def __repr__(self):
-                return b'byte-repr'
-        self.assertRaises(TypeError, repr, WrongRepr())
+        self.assertTypedEqual(repr('\U0001f40d'), "'\U0001f40d'")
+        self.assertTypedEqual(repr(StrSubclass('abc')), "'abc'")
+        self.assertTypedEqual(repr(WithRepr('<abc>')), '<abc>')
+        self.assertTypedEqual(repr(WithRepr(StrSubclass('<abc>'))), StrSubclass('<abc>'))
+        self.assertTypedEqual(repr(WithRepr('<\U0001f40d>')), '<\U0001f40d>')
+        self.assertTypedEqual(repr(WithRepr(StrSubclass('<\U0001f40d>'))), StrSubclass('<\U0001f40d>'))
+        self.assertRaises(TypeError, repr, WithRepr(b'byte-repr'))
 
     def test_iterators(self):
         # Make sure unicode objects have an __iter__ method
@@ -2367,28 +2392,37 @@ class StrTest(string_tests.StringLikeTest,
 
     def test_conversion(self):
         # Make sure __str__() works properly
-        class ObjectToStr:
-            def __str__(self):
-                return "foo"
-
-        class StrSubclassToStr(str):
-            def __str__(self):
-                return "foo"
-
-        class StrSubclassToStrSubclass(str):
-            def __new__(cls, content=""):
-                return str.__new__(cls, 2*content)
-            def __str__(self):
+        class StrWithStr(str):
+            def __new__(cls, value):
+                self = str.__new__(cls, "")
+                self.value = value
                 return self
+            def __str__(self):
+                return self.value
 
-        self.assertEqual(str(ObjectToStr()), "foo")
-        self.assertEqual(str(StrSubclassToStr("bar")), "foo")
-        s = str(StrSubclassToStrSubclass("foo"))
-        self.assertEqual(s, "foofoo")
-        self.assertIs(type(s), StrSubclassToStrSubclass)
-        s = StrSubclass(StrSubclassToStrSubclass("foo"))
-        self.assertEqual(s, "foofoo")
-        self.assertIs(type(s), StrSubclass)
+        self.assertTypedEqual(str(WithStr('abc')), 'abc')
+        self.assertTypedEqual(str(WithStr(StrSubclass('abc'))), StrSubclass('abc'))
+        self.assertTypedEqual(StrSubclass(WithStr('abc')), StrSubclass('abc'))
+        self.assertTypedEqual(StrSubclass(WithStr(StrSubclass('abc'))),
+                              StrSubclass('abc'))
+        self.assertTypedEqual(StrSubclass(WithStr(OtherStrSubclass('abc'))),
+                              StrSubclass('abc'))
+
+        self.assertTypedEqual(str(StrWithStr('abc')), 'abc')
+        self.assertTypedEqual(str(StrWithStr(StrSubclass('abc'))), StrSubclass('abc'))
+        self.assertTypedEqual(StrSubclass(StrWithStr('abc')), StrSubclass('abc'))
+        self.assertTypedEqual(StrSubclass(StrWithStr(StrSubclass('abc'))),
+                              StrSubclass('abc'))
+        self.assertTypedEqual(StrSubclass(StrWithStr(OtherStrSubclass('abc'))),
+                              StrSubclass('abc'))
+
+        self.assertTypedEqual(str(WithRepr('<abc>')), '<abc>')
+        self.assertTypedEqual(str(WithRepr(StrSubclass('<abc>'))), StrSubclass('<abc>'))
+        self.assertTypedEqual(StrSubclass(WithRepr('<abc>')), StrSubclass('<abc>'))
+        self.assertTypedEqual(StrSubclass(WithRepr(StrSubclass('<abc>'))),
+                              StrSubclass('<abc>'))
+        self.assertTypedEqual(StrSubclass(WithRepr(OtherStrSubclass('<abc>'))),
+                              StrSubclass('<abc>'))
 
     def test_unicode_repr(self):
         class s1: