Skip to content

Commit c99097e

Browse files
authored
gh-159868: Accept UserString arguments in startswith and endswith (#159869)
1 parent f3d863a commit c99097e

3 files changed

Lines changed: 33 additions & 0 deletions

File tree

‎Lib/collections/__init__.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,8 @@ def encode(self, encoding='utf-8', errors='strict'):
15361536
return self.data.encode(encoding, errors)
15371537

15381538
def endswith(self, suffix, start=0, end=_sys.maxsize):
1539+
if isinstance(suffix, UserString):
1540+
suffix = suffix.data
15391541
return self.data.endswith(suffix, start, end)
15401542

15411543
def expandtabs(self, tabsize=8):
@@ -1646,6 +1648,8 @@ def splitlines(self, keepends=False):
16461648
return self.data.splitlines(keepends)
16471649

16481650
def startswith(self, prefix, start=0, end=_sys.maxsize):
1651+
if isinstance(prefix, UserString):
1652+
prefix = prefix.data
16491653
return self.data.startswith(prefix, start, end)
16501654

16511655
def strip(self, chars=None):

‎Lib/test/test_userstring.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,32 @@ def test_mixed_cmp(self):
121121
self._assert_cmp(a, 'a', 1)
122122
self._assert_cmp(a, 'ac', -1)
123123

124+
@support.subTests('str_class', (UserString, UserStringSubclass))
125+
def test_startswith_userstring(self, str_class):
126+
s = UserString('hello world')
127+
self.assertTrue(s.startswith(str_class('hello')))
128+
self.assertFalse(s.startswith(str_class('world')))
129+
self.assertTrue(s.startswith(str_class('')))
130+
self.assertFalse(s.startswith(str_class('hello world!')))
131+
self.assertTrue(s.startswith(str_class('world'), 6))
132+
self.assertTrue(s.startswith(str_class('world'), 6, 11))
133+
self.assertFalse(s.startswith(str_class('world'), 6, 10))
134+
self.assertTrue(s.startswith(str_class('world'), -5))
135+
self.assertTrue(s.startswith(str_class('world'), start=6, end=11))
136+
137+
@support.subTests('str_class', (UserString, UserStringSubclass))
138+
def test_endswith_userstring(self, str_class):
139+
s = UserString('hello world')
140+
self.assertTrue(s.endswith(str_class('world')))
141+
self.assertFalse(s.endswith(str_class('hello')))
142+
self.assertTrue(s.endswith(str_class('')))
143+
self.assertFalse(s.endswith(str_class('hello world!')))
144+
self.assertTrue(s.endswith(str_class('world'), 6))
145+
self.assertTrue(s.endswith(str_class('hello'), 0, 5))
146+
self.assertFalse(s.endswith(str_class('hello'), 1, 5))
147+
self.assertTrue(s.endswith(str_class('hello'), -11, -6))
148+
self.assertTrue(s.endswith(str_class('hello'), start=0, end=5))
149+
124150
def test_rmod(self):
125151
class ustr2(UserString):
126152
pass
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Allow :meth:`!collections.UserString.startswith` and
2+
:meth:`!collections.UserString.endswith` to accept a
3+
:class:`~collections.UserString` instance as the prefix or suffix argument.

0 commit comments

Comments
 (0)