Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f104429

Browse files
committed
Patch # 1145 by Thomas Lee:
str.join(...) now applies str() to the sequence elements if they're not strings alraedy, except for bytes, which still raise TypeError (for the same reasons why ""==b"" raises it).
1 parent 4e02c50 commit f104429

5 files changed

Lines changed: 28 additions & 16 deletions

File tree

Doc/library/stdtypes.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,8 +789,11 @@ functions based on regular expressions.
789789

790790
.. method:: str.join(seq)
791791

792-
Return a string which is the concatenation of the strings in the sequence *seq*.
793-
The separator between elements is the string providing this method.
792+
Return a string which is the concatenation of the values in the sequence
793+
*seq*. Non-string values in *seq* will be converted to a string using their
794+
respective ``str()`` value. If there are any :class:`bytes` objects in
795+
*seq*, a :exc:`TypeError` will be raised. The separator between elements is
796+
the string providing this method.
794797

795798

796799
.. method:: str.ljust(width[, fillchar])

Lib/test/string_tests.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def __getitem__(self, i): return self.seq[i]
1313

1414
class BadSeq1(Sequence):
1515
def __init__(self): self.seq = [7, 'hello', 123]
16+
def __str__(self): return '{0} {1} {2}'.format(*self.seq)
1617

1718
class BadSeq2(Sequence):
1819
def __init__(self): self.seq = ['a', 'b', 'c']
@@ -987,19 +988,19 @@ def test_join(self):
987988
self.checkequal('abc', 'a', 'join', ('abc',))
988989
self.checkequal('z', 'a', 'join', UserList(['z']))
989990
self.checkequal('a.b.c', '.', 'join', ['a', 'b', 'c'])
990-
self.checkraises(TypeError, '.', 'join', ['a', 'b', 3])
991+
self.checkequal('a.b.3', '.', 'join', ['a', 'b', 3])
991992
for i in [5, 25, 125]:
992993
self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join',
993994
['a' * i] * i)
994995
self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join',
995996
('a' * i,) * i)
996997

997-
self.checkraises(TypeError, ' ', 'join', BadSeq1())
998+
self.checkequal(str(BadSeq1()), ' ', 'join', BadSeq1())
998999
self.checkequal('a b c', ' ', 'join', BadSeq2())
9991000

10001001
self.checkraises(TypeError, ' ', 'join')
10011002
self.checkraises(TypeError, ' ', 'join', 7)
1002-
self.checkraises(TypeError, ' ', 'join', Sequence([7, 'hello', 123]))
1003+
self.checkraises(TypeError, ' ', 'join', [1, 2, bytes()])
10031004
try:
10041005
def f():
10051006
yield 4 + ""

Lib/test/test_descr.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,10 +3238,6 @@ def strops():
32383238
except ValueError: pass
32393239
else: raise TestFailed("''.split('') doesn't raise ValueError")
32403240

3241-
try: ''.join([0])
3242-
except TypeError: pass
3243-
else: raise TestFailed("''.join([0]) doesn't raise TypeError")
3244-
32453241
try: ''.rindex('5')
32463242
except ValueError: pass
32473243
else: raise TestFailed("''.rindex('5') doesn't raise ValueError")

Lib/test/test_unicode.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ def test_split(self):
178178
def test_join(self):
179179
string_tests.MixinStrUnicodeUserStringTest.test_join(self)
180180

181+
class MyWrapper:
182+
def __init__(self, sval): self.sval = sval
183+
def __str__(self): return self.sval
184+
181185
# mixed arguments
182186
self.checkequalnofix('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
183187
self.checkequalnofix('abcd', '', 'join', ('a', 'b', 'c', 'd'))
@@ -186,6 +190,8 @@ def test_join(self):
186190
self.checkequalnofix('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
187191
self.checkequalnofix('abcd', '', 'join', ('a', 'b', 'c', 'd'))
188192
self.checkequalnofix('w x y z', ' ', 'join', string_tests.Sequence('wxyz'))
193+
self.checkequalnofix('1 2 foo', ' ', 'join', [1, 2, MyWrapper('foo')])
194+
self.checkraises(TypeError, ' ', 'join', [1, 2, 3, bytes()])
189195

190196
def test_replace(self):
191197
string_tests.CommonTest.test_replace(self)

Objects/unicodeobject.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5412,14 +5412,20 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
54125412

54135413
item = PySequence_Fast_GET_ITEM(fseq, i);
54145414
/* Convert item to Unicode. */
5415-
if (! PyUnicode_Check(item) && ! PyString_Check(item)) {
5416-
PyErr_Format(PyExc_TypeError,
5417-
"sequence item %zd: expected string or Unicode,"
5418-
" %.80s found",
5419-
i, Py_Type(item)->tp_name);
5420-
goto onError;
5415+
if (!PyString_Check(item) && !PyUnicode_Check(item))
5416+
{
5417+
if (PyBytes_Check(item))
5418+
{
5419+
PyErr_Format(PyExc_TypeError,
5420+
"sequence item %d: join() will not operate on "
5421+
"bytes objects", i);
5422+
goto onError;
5423+
}
5424+
item = PyObject_Unicode(item);
54215425
}
5422-
item = PyUnicode_FromObject(item);
5426+
else
5427+
item = PyUnicode_FromObject(item);
5428+
54235429
if (item == NULL)
54245430
goto onError;
54255431
/* We own a reference to item from here on. */

0 commit comments

Comments
 (0)