New submission from Thomas Lee:

The current implementation of str.join requires that the parameters
passed to it be string/unicode values. A suggestion to allow it to
accept parameters of any type came up in PEP 3100. Implemented for
Unicode using the attached patch.

It would be trivial to add this functionality to the old string object
too, but I haven't been following the string to unicode discussion too
closely and I'm unsure if the old string object will remain for too much
longer.

----------
components: Interpreter Core
files: join-autostr.patch
messages: 55820
nosy: thomas.lee
severity: minor
status: open
title: Allow str.join to join non-string types (as per PEP 3100)
type: behavior
versions: Python 3.0

__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1145>
__________________________________
Index: Objects/unicodeobject.c
===================================================================
--- Objects/unicodeobject.c	(revision 58102)
+++ Objects/unicodeobject.c	(working copy)
@@ -5412,14 +5412,16 @@
 
 	item = PySequence_Fast_GET_ITEM(fseq, i);
 	/* Convert item to Unicode. */
-	if (! PyUnicode_Check(item) && ! PyString_Check(item)) {
-	    PyErr_Format(PyExc_TypeError,
-			 "sequence item %zd: expected string or Unicode,"
-			 " %.80s found",
-			 i, Py_Type(item)->tp_name);
-	    goto onError;
+	if (!PyString_Check(item) && !PyUnicode_Check(item))
+	{
+		PyObject* sval;
+		sval = PyObject_Unicode(item);
+		item = PyUnicode_FromObject(sval);
+		Py_DECREF(sval);
 	}
-	item = PyUnicode_FromObject(item);
+	else
+		item = PyUnicode_FromObject(item);
+
 	if (item == NULL)
 	    goto onError;
 	/* We own a reference to item from here on. */
Index: Doc/library/stdtypes.rst
===================================================================
--- Doc/library/stdtypes.rst	(revision 58102)
+++ Doc/library/stdtypes.rst	(working copy)
@@ -786,8 +786,10 @@
 
 .. method:: str.join(seq)
 
-   Return a string which is the concatenation of the strings in the sequence *seq*.
-   The separator between elements is the string providing this method.
+   Return a string which is the concatenation of the values in the sequence *seq*.
+   Non-string values in *seq* will be converted to a string using their respective
+   implementation of :meth:`__str__`. The separator between elements is the string
+   providing this method.
 
 
 .. method:: str.ljust(width[, fillchar])
Index: Lib/test/test_descr.py
===================================================================
--- Lib/test/test_descr.py	(revision 58102)
+++ Lib/test/test_descr.py	(working copy)
@@ -3238,10 +3238,6 @@
     except ValueError: pass
     else: raise TestFailed("''.split('') doesn't raise ValueError")
 
-    try: ''.join([0])
-    except TypeError: pass
-    else: raise TestFailed("''.join([0]) doesn't raise TypeError")
-
     try: ''.rindex('5')
     except ValueError: pass
     else: raise TestFailed("''.rindex('5') doesn't raise ValueError")
Index: Lib/test/test_unicode.py
===================================================================
--- Lib/test/test_unicode.py	(revision 58102)
+++ Lib/test/test_unicode.py	(working copy)
@@ -178,6 +178,10 @@
     def test_join(self):
         string_tests.MixinStrUnicodeUserStringTest.test_join(self)
 
+        class MyWrapper:
+            def __init__(self, sval): self.sval = sval
+            def __str__(self): return self.sval
+
         # mixed arguments
         self.checkequalnofix('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
         self.checkequalnofix('abcd', '', 'join', ('a', 'b', 'c', 'd'))
@@ -186,6 +190,7 @@
         self.checkequalnofix('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
         self.checkequalnofix('abcd', '', 'join', ('a', 'b', 'c', 'd'))
         self.checkequalnofix('w x y z', ' ', 'join', string_tests.Sequence('wxyz'))
+        self.checkequalnofix('1 2 foo you', ' ', 'join', [1, 2, MyWrapper('foo'), 'you'])
 
     def test_replace(self):
         string_tests.CommonTest.test_replace(self)
Index: Lib/test/string_tests.py
===================================================================
--- Lib/test/string_tests.py	(revision 58102)
+++ Lib/test/string_tests.py	(working copy)
@@ -13,6 +13,7 @@
 
 class BadSeq1(Sequence):
     def __init__(self): self.seq = [7, 'hello', 123]
+    def __str__(self): return '{0} {1} {2}'.format(*self.seq)
 
 class BadSeq2(Sequence):
     def __init__(self): self.seq = ['a', 'b', 'c']
@@ -987,19 +988,19 @@
         self.checkequal('abc', 'a', 'join', ('abc',))
         self.checkequal('z', 'a', 'join', UserList(['z']))
         self.checkequal('a.b.c', '.', 'join', ['a', 'b', 'c'])
-        self.checkraises(TypeError, '.', 'join', ['a', 'b', 3])
+        self.checkequal('a.b.3', '.', 'join', ['a', 'b', 3])
         for i in [5, 25, 125]:
             self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join',
                  ['a' * i] * i)
             self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join',
                  ('a' * i,) * i)
 
-        self.checkraises(TypeError, ' ', 'join', BadSeq1())
+        self.checkequal(str(BadSeq1()), ' ', 'join', BadSeq1())
         self.checkequal('a b c', ' ', 'join', BadSeq2())
 
         self.checkraises(TypeError, ' ', 'join')
         self.checkraises(TypeError, ' ', 'join', 7)
-        self.checkraises(TypeError, ' ', 'join', Sequence([7, 'hello', 123]))
+        self.checkequal(str(BadSeq1()), ' ', 'join', BadSeq1())
         try:
             def f():
                 yield 4 + ""
_______________________________________________
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to