Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.12] gh-104231: Add more tests for str(), repr(), ascii(), and bytes() (GH-112551) #112555

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 59 additions & 22 deletions Lib/test/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def __index__(self):

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)
Expand Down Expand Up @@ -1023,36 +1027,63 @@ def test_buffer_is_readonly(self):
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):
Expand Down Expand Up @@ -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
Expand Down
90 changes: 62 additions & 28 deletions Lib/test/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 UnicodeTest(string_tests.CommonTest,
string_tests.MixinStrUnicodeUserStringTest,
string_tests.MixinStrUnicodeTest,
Expand Down Expand Up @@ -84,6 +99,10 @@ def __repr__(self):
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')
Expand Down Expand Up @@ -128,10 +147,13 @@ def test_ascii(self):
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()
Expand Down Expand Up @@ -169,10 +191,13 @@ def test_repr(self):
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
Expand Down Expand Up @@ -2378,28 +2403,37 @@ def test_ucs4(self):

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:
Expand Down
Loading