Index: Lib/posixpath.py =================================================================== --- Lib/posixpath.py (revision 76320) +++ Lib/posixpath.py (working copy) @@ -307,8 +307,10 @@ def normpath(path): """Normalize path, eliminating double slashes, etc.""" + # Preserve unicode (if path is unicode) + slash, dot = (u'/', u'.') if isinstance(path, unicode) else ('/', '.') if path == '': - return '.' + return dot initial_slashes = path.startswith('/') # POSIX allows one or two initial slashes, but treats three or more # as single slash. @@ -326,10 +328,10 @@ elif new_comps: new_comps.pop() comps = new_comps - path = '/'.join(comps) + path = slash.join(comps) if initial_slashes: - path = '/'*initial_slashes + path - return path or '.' + path = slash*initial_slashes + path + return path or dot def abspath(path): Index: Lib/ntpath.py =================================================================== --- Lib/ntpath.py (revision 76320) +++ Lib/ntpath.py (working copy) @@ -397,6 +397,8 @@ def normpath(path): """Normalize path, eliminating double slashes, etc.""" + # Preserve unicode (if path is unicode) + backslash, dot = (u'\\', u'.') if isinstance(path, unicode) else ('\\', '.') path = path.replace("/", "\\") prefix, path = splitdrive(path) # We need to be careful here. If the prefix is empty, and the path starts @@ -411,12 +413,12 @@ if prefix == '': # No drive letter - preserve initial backslashes while path[:1] == "\\": - prefix = prefix + "\\" + prefix = prefix + backslash path = path[1:] else: # We have a drive letter - collapse initial backslashes if path.startswith("\\"): - prefix = prefix + "\\" + prefix = prefix + backslash path = path.lstrip("\\") comps = path.split("\\") i = 0 @@ -435,8 +437,8 @@ i += 1 # If the path is now empty, substitute '.' if not prefix and not comps: - comps.append('.') - return prefix + "\\".join(comps) + comps.append(dot) + return prefix + backslash.join(comps) # Return an absolute path. Index: Lib/test/test_ntpath.py =================================================================== --- Lib/test/test_ntpath.py (revision 76320) +++ Lib/test/test_ntpath.py (working copy) @@ -123,6 +123,12 @@ tester("ntpath.normpath('C:////a/b')", r'C:\a\b') tester("ntpath.normpath('//machine/share//a/b')", r'\\machine\share\a\b') + # Make sure normpath preserves unicode + self.assertTrue(isinstance(ntpath.normpath(u""), unicode)) + self.assertTrue(isinstance(ntpath.normpath(u"."), unicode)) + self.assertTrue(isinstance(ntpath.normpath(u"/"), unicode)) + self.assertTrue(isinstance(ntpath.normpath(u"///foo/.//bar//"), unicode)) + def test_expandvars(self): with test_support.EnvironmentVarGuard() as env: env.clear() Index: Lib/test/test_posixpath.py =================================================================== --- Lib/test/test_posixpath.py (revision 76320) +++ Lib/test/test_posixpath.py (working copy) @@ -381,6 +381,12 @@ self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"), "/foo/baz") self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar") + # Make sure normpath preserves unicode + self.assertTrue(isinstance(posixpath.normpath(u""), unicode)) + self.assertTrue(isinstance(posixpath.normpath(u"."), unicode)) + self.assertTrue(isinstance(posixpath.normpath(u"/"), unicode)) + self.assertTrue(isinstance(posixpath.normpath(u"///foo/.//bar//"), unicode)) + self.assertRaises(TypeError, posixpath.normpath) def test_abspath(self):