diff -r d943089af1c6 Lib/posixpath.py --- a/Lib/posixpath.py Mon Jun 30 04:04:52 2014 +0300 +++ b/Lib/posixpath.py Sun Jun 29 23:24:59 2014 -0400 @@ -34,6 +34,7 @@ defpath = ':/bin:/usr/bin' altsep = None devnull = '/dev/null' +mixed_string_binary_error = "Can't mix strings and bytes in path components." def _get_sep(path): if isinstance(path, bytes): @@ -87,8 +88,7 @@ for s in (a, ) + p) if valid_types: # Must have a mixture of text and binary data - raise TypeError("Can't mix strings and bytes in path " - "components.") from None + raise TypeError(mixed_string_binary_error) from None raise return path @@ -447,9 +447,15 @@ if start is None: start = curdir - start_list = [x for x in abspath(start).split(sep) if x] - path_list = [x for x in abspath(path).split(sep) if x] - + try: + start_list = [x for x in abspath(start).split(sep) if x] + path_list = [x for x in abspath(path).split(sep) if x] + except TypeError as e: + valid_types = all(isinstance(s, (str, bytes, bytearray)) + for s in [start, path]) + if valid_types: + raise TypeError(mixed_string_binary_error) from None + raise # Work out how much of the filepath is shared by start and path. i = len(commonprefix([start_list, path_list])) diff -r d943089af1c6 Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py Mon Jun 30 04:04:52 2014 +0300 +++ b/Lib/test/test_posixpath.py Sun Jun 29 23:24:59 2014 -0400 @@ -43,6 +43,15 @@ support.unlink(support.TESTFN + suffix) safe_rmdir(support.TESTFN + suffix) + def check_error_msg(self, list_of_args, func_to_call, msg= + "Can't mix strings and bytes in path components."): + """Check posixpath.join raises friendly TypeErrors.""" + for args in (item for perm in list_of_args + for item in itertools.permutations(perm)): + with self.assertRaises(TypeError) as cm: + func_to_call(*args) + self.assertEqual(msg, cm.exception.args[0]) + def test_join(self): self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"), "/bar/baz") @@ -56,17 +65,7 @@ b"/foo/bar/baz") self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"), b"/foo/bar/baz/") - - def check_error_msg(list_of_args, msg): - """Check posixpath.join raises friendly TypeErrors.""" - for args in (item for perm in list_of_args - for item in itertools.permutations(perm)): - with self.assertRaises(TypeError) as cm: - posixpath.join(*args) - self.assertEqual(msg, cm.exception.args[0]) - - check_error_msg([[b'bytes', 'str'], [bytearray(b'bytes'), 'str']], - "Can't mix strings and bytes in path components.") + self.check_error_msg([[b'bytes', 'str'], [bytearray(b'bytes'), 'str']], posixpath.join) # regression, see #15377 with self.assertRaises(TypeError) as cm: posixpath.join(None, 'str') @@ -487,6 +486,8 @@ try: curdir = os.path.split(os.getcwd())[-1] self.assertRaises(ValueError, posixpath.relpath, "") + self.assertRaises(TypeError, 'a', b'a/b') + self.check_error_msg([[b'bytes', 'str'], [bytearray(b'bytes'), 'str']], posixpath.relpath) self.assertEqual(posixpath.relpath("a"), "a") self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a") self.assertEqual(posixpath.relpath("a/b"), "a/b")