Skip to content

Commit ae1ea41

Browse files
[3.12] gh-104231: Add more tests for str(), repr(), ascii(), and bytes() (GH-112551) (GH-112555)
(cherry picked from commit 2223899)
1 parent 88d9142 commit ae1ea41

File tree

2 files changed

+121
-50
lines changed

2 files changed

+121
-50
lines changed

Lib/test/test_bytes.py

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ def __index__(self):
4646

4747
class BaseBytesTest:
4848

49+
def assertTypedEqual(self, actual, expected):
50+
self.assertIs(type(actual), type(expected))
51+
self.assertEqual(actual, expected)
52+
4953
def test_basics(self):
5054
b = self.type2test()
5155
self.assertEqual(type(b), self.type2test)
@@ -1023,36 +1027,63 @@ def test_buffer_is_readonly(self):
10231027
self.assertRaises(TypeError, f.readinto, b"")
10241028

10251029
def test_custom(self):
1026-
class A:
1027-
def __bytes__(self):
1028-
return b'abc'
1029-
self.assertEqual(bytes(A()), b'abc')
1030-
class A: pass
1031-
self.assertRaises(TypeError, bytes, A())
1032-
class A:
1033-
def __bytes__(self):
1034-
return None
1035-
self.assertRaises(TypeError, bytes, A())
1036-
class A:
1030+
self.assertEqual(bytes(BytesSubclass(b'abc')), b'abc')
1031+
self.assertEqual(BytesSubclass(OtherBytesSubclass(b'abc')),
1032+
BytesSubclass(b'abc'))
1033+
self.assertEqual(bytes(WithBytes(b'abc')), b'abc')
1034+
self.assertEqual(BytesSubclass(WithBytes(b'abc')), BytesSubclass(b'abc'))
1035+
1036+
class NoBytes: pass
1037+
self.assertRaises(TypeError, bytes, NoBytes())
1038+
self.assertRaises(TypeError, bytes, WithBytes('abc'))
1039+
self.assertRaises(TypeError, bytes, WithBytes(None))
1040+
class IndexWithBytes:
10371041
def __bytes__(self):
10381042
return b'a'
10391043
def __index__(self):
10401044
return 42
1041-
self.assertEqual(bytes(A()), b'a')
1045+
self.assertEqual(bytes(IndexWithBytes()), b'a')
10421046
# Issue #25766
1043-
class A(str):
1047+
class StrWithBytes(str):
1048+
def __new__(cls, value):
1049+
self = str.__new__(cls, '\u20ac')
1050+
self.value = value
1051+
return self
10441052
def __bytes__(self):
1045-
return b'abc'
1046-
self.assertEqual(bytes(A('\u20ac')), b'abc')
1047-
self.assertEqual(bytes(A('\u20ac'), 'iso8859-15'), b'\xa4')
1053+
return self.value
1054+
self.assertEqual(bytes(StrWithBytes(b'abc')), b'abc')
1055+
self.assertEqual(bytes(StrWithBytes(b'abc'), 'iso8859-15'), b'\xa4')
1056+
self.assertEqual(bytes(StrWithBytes(BytesSubclass(b'abc'))), b'abc')
1057+
self.assertEqual(BytesSubclass(StrWithBytes(b'abc')), BytesSubclass(b'abc'))
1058+
self.assertEqual(BytesSubclass(StrWithBytes(b'abc'), 'iso8859-15'),
1059+
BytesSubclass(b'\xa4'))
1060+
self.assertEqual(BytesSubclass(StrWithBytes(BytesSubclass(b'abc'))),
1061+
BytesSubclass(b'abc'))
1062+
self.assertEqual(BytesSubclass(StrWithBytes(OtherBytesSubclass(b'abc'))),
1063+
BytesSubclass(b'abc'))
10481064
# Issue #24731
1049-
class A:
1065+
self.assertTypedEqual(bytes(WithBytes(BytesSubclass(b'abc'))), BytesSubclass(b'abc'))
1066+
self.assertTypedEqual(BytesSubclass(WithBytes(BytesSubclass(b'abc'))),
1067+
BytesSubclass(b'abc'))
1068+
self.assertTypedEqual(BytesSubclass(WithBytes(OtherBytesSubclass(b'abc'))),
1069+
BytesSubclass(b'abc'))
1070+
1071+
class BytesWithBytes(bytes):
1072+
def __new__(cls, value):
1073+
self = bytes.__new__(cls, b'\xa4')
1074+
self.value = value
1075+
return self
10501076
def __bytes__(self):
1051-
return OtherBytesSubclass(b'abc')
1052-
self.assertEqual(bytes(A()), b'abc')
1053-
self.assertIs(type(bytes(A())), OtherBytesSubclass)
1054-
self.assertEqual(BytesSubclass(A()), b'abc')
1055-
self.assertIs(type(BytesSubclass(A())), BytesSubclass)
1077+
return self.value
1078+
self.assertTypedEqual(bytes(BytesWithBytes(b'abc')), b'abc')
1079+
self.assertTypedEqual(BytesSubclass(BytesWithBytes(b'abc')),
1080+
BytesSubclass(b'abc'))
1081+
self.assertTypedEqual(bytes(BytesWithBytes(BytesSubclass(b'abc'))),
1082+
BytesSubclass(b'abc'))
1083+
self.assertTypedEqual(BytesSubclass(BytesWithBytes(BytesSubclass(b'abc'))),
1084+
BytesSubclass(b'abc'))
1085+
self.assertTypedEqual(BytesSubclass(BytesWithBytes(OtherBytesSubclass(b'abc'))),
1086+
BytesSubclass(b'abc'))
10561087

10571088
# Test PyBytes_FromFormat()
10581089
def test_from_format(self):
@@ -2069,6 +2100,12 @@ class BytesSubclass(bytes):
20692100
class OtherBytesSubclass(bytes):
20702101
pass
20712102

2103+
class WithBytes:
2104+
def __init__(self, value):
2105+
self.value = value
2106+
def __bytes__(self):
2107+
return self.value
2108+
20722109
class ByteArraySubclassTest(SubclassTest, unittest.TestCase):
20732110
basetype = bytearray
20742111
type2test = ByteArraySubclass

Lib/test/test_unicode.py

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@ def duplicate_string(text):
5555
class StrSubclass(str):
5656
pass
5757

58+
class OtherStrSubclass(str):
59+
pass
60+
61+
class WithStr:
62+
def __init__(self, value):
63+
self.value = value
64+
def __str__(self):
65+
return self.value
66+
67+
class WithRepr:
68+
def __init__(self, value):
69+
self.value = value
70+
def __repr__(self):
71+
return self.value
72+
5873
class UnicodeTest(string_tests.CommonTest,
5974
string_tests.MixinStrUnicodeUserStringTest,
6075
string_tests.MixinStrUnicodeTest,
@@ -84,6 +99,10 @@ def __repr__(self):
8499
self.assertEqual(realresult, result)
85100
self.assertTrue(object is not realresult)
86101

102+
def assertTypedEqual(self, actual, expected):
103+
self.assertIs(type(actual), type(expected))
104+
self.assertEqual(actual, expected)
105+
87106
def test_literals(self):
88107
self.assertEqual('\xff', '\u00ff')
89108
self.assertEqual('\uffff', '\U0000ffff')
@@ -128,10 +147,13 @@ def test_ascii(self):
128147
self.assertEqual(ascii("\U00010000" * 39 + "\uffff" * 4096),
129148
ascii("\U00010000" * 39 + "\uffff" * 4096))
130149

131-
class WrongRepr:
132-
def __repr__(self):
133-
return b'byte-repr'
134-
self.assertRaises(TypeError, ascii, WrongRepr())
150+
self.assertTypedEqual(ascii('\U0001f40d'), r"'\U0001f40d'")
151+
self.assertTypedEqual(ascii(StrSubclass('abc')), "'abc'")
152+
self.assertTypedEqual(ascii(WithRepr('<abc>')), '<abc>')
153+
self.assertTypedEqual(ascii(WithRepr(StrSubclass('<abc>'))), StrSubclass('<abc>'))
154+
self.assertTypedEqual(ascii(WithRepr('<\U0001f40d>')), r'<\U0001f40d>')
155+
self.assertTypedEqual(ascii(WithRepr(StrSubclass('<\U0001f40d>'))), r'<\U0001f40d>')
156+
self.assertRaises(TypeError, ascii, WithRepr(b'byte-repr'))
135157

136158
def test_repr(self):
137159
# Test basic sanity of repr()
@@ -169,10 +191,13 @@ def test_repr(self):
169191
self.assertEqual(repr("\U00010000" * 39 + "\uffff" * 4096),
170192
repr("\U00010000" * 39 + "\uffff" * 4096))
171193

172-
class WrongRepr:
173-
def __repr__(self):
174-
return b'byte-repr'
175-
self.assertRaises(TypeError, repr, WrongRepr())
194+
self.assertTypedEqual(repr('\U0001f40d'), "'\U0001f40d'")
195+
self.assertTypedEqual(repr(StrSubclass('abc')), "'abc'")
196+
self.assertTypedEqual(repr(WithRepr('<abc>')), '<abc>')
197+
self.assertTypedEqual(repr(WithRepr(StrSubclass('<abc>'))), StrSubclass('<abc>'))
198+
self.assertTypedEqual(repr(WithRepr('<\U0001f40d>')), '<\U0001f40d>')
199+
self.assertTypedEqual(repr(WithRepr(StrSubclass('<\U0001f40d>'))), StrSubclass('<\U0001f40d>'))
200+
self.assertRaises(TypeError, repr, WithRepr(b'byte-repr'))
176201

177202
def test_iterators(self):
178203
# Make sure unicode objects have an __iter__ method
@@ -2378,28 +2403,37 @@ def test_ucs4(self):
23782403

23792404
def test_conversion(self):
23802405
# Make sure __str__() works properly
2381-
class ObjectToStr:
2382-
def __str__(self):
2383-
return "foo"
2384-
2385-
class StrSubclassToStr(str):
2386-
def __str__(self):
2387-
return "foo"
2388-
2389-
class StrSubclassToStrSubclass(str):
2390-
def __new__(cls, content=""):
2391-
return str.__new__(cls, 2*content)
2392-
def __str__(self):
2406+
class StrWithStr(str):
2407+
def __new__(cls, value):
2408+
self = str.__new__(cls, "")
2409+
self.value = value
23932410
return self
2411+
def __str__(self):
2412+
return self.value
23942413

2395-
self.assertEqual(str(ObjectToStr()), "foo")
2396-
self.assertEqual(str(StrSubclassToStr("bar")), "foo")
2397-
s = str(StrSubclassToStrSubclass("foo"))
2398-
self.assertEqual(s, "foofoo")
2399-
self.assertIs(type(s), StrSubclassToStrSubclass)
2400-
s = StrSubclass(StrSubclassToStrSubclass("foo"))
2401-
self.assertEqual(s, "foofoo")
2402-
self.assertIs(type(s), StrSubclass)
2414+
self.assertTypedEqual(str(WithStr('abc')), 'abc')
2415+
self.assertTypedEqual(str(WithStr(StrSubclass('abc'))), StrSubclass('abc'))
2416+
self.assertTypedEqual(StrSubclass(WithStr('abc')), StrSubclass('abc'))
2417+
self.assertTypedEqual(StrSubclass(WithStr(StrSubclass('abc'))),
2418+
StrSubclass('abc'))
2419+
self.assertTypedEqual(StrSubclass(WithStr(OtherStrSubclass('abc'))),
2420+
StrSubclass('abc'))
2421+
2422+
self.assertTypedEqual(str(StrWithStr('abc')), 'abc')
2423+
self.assertTypedEqual(str(StrWithStr(StrSubclass('abc'))), StrSubclass('abc'))
2424+
self.assertTypedEqual(StrSubclass(StrWithStr('abc')), StrSubclass('abc'))
2425+
self.assertTypedEqual(StrSubclass(StrWithStr(StrSubclass('abc'))),
2426+
StrSubclass('abc'))
2427+
self.assertTypedEqual(StrSubclass(StrWithStr(OtherStrSubclass('abc'))),
2428+
StrSubclass('abc'))
2429+
2430+
self.assertTypedEqual(str(WithRepr('<abc>')), '<abc>')
2431+
self.assertTypedEqual(str(WithRepr(StrSubclass('<abc>'))), StrSubclass('<abc>'))
2432+
self.assertTypedEqual(StrSubclass(WithRepr('<abc>')), StrSubclass('<abc>'))
2433+
self.assertTypedEqual(StrSubclass(WithRepr(StrSubclass('<abc>'))),
2434+
StrSubclass('<abc>'))
2435+
self.assertTypedEqual(StrSubclass(WithRepr(OtherStrSubclass('<abc>'))),
2436+
StrSubclass('<abc>'))
24032437

24042438
def test_unicode_repr(self):
24052439
class s1:

0 commit comments

Comments
 (0)