diff --git a/Lib/posixpath.py b/Lib/posixpath.py --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -83,11 +83,18 @@ else: path += sep + b except TypeError: + if a is None: + raise TypeError("None isn't a valid path component.") strs = [isinstance(s, str) for s in (a, ) + p] if any(strs) and not all(strs): raise TypeError("Can't mix strings and bytes in path components.") else: raise + except AttributeError: + if b is None: + raise TypeError("None isn't a valid path component.") + else: + raise return path diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -1,6 +1,7 @@ import unittest from test import support, test_genericpath +import itertools import posixpath import os import sys @@ -56,18 +57,18 @@ self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"), b"/foo/bar/baz/") - # Check for friendly str/bytes mixing message - for args in [[b'bytes', 'str'], - [bytearray(b'bytes'), 'str']]: - for _ in range(2): + 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( - "Can't mix strings and bytes in path components.", - cm.exception.args[0] - ) - args.reverse() # check both orders + 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.") + check_error_msg([[None, 'str'], [None, b'bytes']], + "None isn't a valid path component.") def test_split(self): self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))