Commit b186f343 authored by Amaury Forgeot d'Arc's avatar Amaury Forgeot d'Arc

Issue3187 for Macintosh platform:

macpath.py now accepts both unicode string and bytes as file names.
Also add more tests for these functions.

Reviewed by Benjamin.
parent f60fe810
...@@ -13,6 +13,7 @@ __all__ = ["normcase","isabs","join","splitdrive","split","splitext", ...@@ -13,6 +13,7 @@ __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
"devnull","realpath","supports_unicode_filenames"] "devnull","realpath","supports_unicode_filenames"]
# strings representing various path-related bits and pieces # strings representing various path-related bits and pieces
# These are primarily for export; internally, they are hardcoded.
curdir = ':' curdir = ':'
pardir = '::' pardir = '::'
extsep = '.' extsep = '.'
...@@ -22,6 +23,12 @@ defpath = ':' ...@@ -22,6 +23,12 @@ defpath = ':'
altsep = None altsep = None
devnull = 'Dev:Null' devnull = 'Dev:Null'
def _get_colon(path):
if isinstance(path, bytes):
return b':'
else:
return ':'
# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here. # Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here.
def normcase(path): def normcase(path):
...@@ -35,21 +42,23 @@ def isabs(s): ...@@ -35,21 +42,23 @@ def isabs(s):
Anything else is absolute (the string up to the first colon is the Anything else is absolute (the string up to the first colon is the
volume name).""" volume name)."""
return ':' in s and s[0] != ':' colon = _get_colon(s)
return colon in s and s[:1] != colon
def join(s, *p): def join(s, *p):
colon = _get_colon(s)
path = s path = s
for t in p: for t in p:
if (not s) or isabs(t): if (not s) or isabs(t):
path = t path = t
continue continue
if t[:1] == ':': if t[:1] == colon:
t = t[1:] t = t[1:]
if ':' not in path: if colon not in path:
path = ':' + path path = colon + path
if path[-1:] != ':': if path[-1:] != colon:
path = path + ':' path = path + colon
path = path + t path = path + t
return path return path
...@@ -59,17 +68,21 @@ def split(s): ...@@ -59,17 +68,21 @@ def split(s):
bit, and the basename (the filename, without colons, in that directory). bit, and the basename (the filename, without colons, in that directory).
The result (s, t) is such that join(s, t) yields the original argument.""" The result (s, t) is such that join(s, t) yields the original argument."""
if ':' not in s: return '', s colon = _get_colon(s)
colon = 0 if colon not in s: return s[:0], s
col = 0
for i in range(len(s)): for i in range(len(s)):
if s[i] == ':': colon = i + 1 if s[i:i+1] == colon: col = i + 1
path, file = s[:colon-1], s[colon:] path, file = s[:col-1], s[col:]
if path and not ':' in path: if path and not colon in path:
path = path + ':' path = path + colon
return path, file return path, file
def splitext(p): def splitext(p):
if isinstance(p, bytes):
return genericpath._splitext(p, b':', altsep, b'.')
else:
return genericpath._splitext(p, sep, altsep, extsep) return genericpath._splitext(p, sep, altsep, extsep)
splitext.__doc__ = genericpath._splitext.__doc__ splitext.__doc__ = genericpath._splitext.__doc__
...@@ -80,7 +93,7 @@ def splitdrive(p): ...@@ -80,7 +93,7 @@ def splitdrive(p):
syntactic and semantic oddities as DOS drive letters, such as there syntactic and semantic oddities as DOS drive letters, such as there
being a separate current directory per drive).""" being a separate current directory per drive)."""
return '', p return p[:0], p
# Short interfaces to split() # Short interfaces to split()
...@@ -92,7 +105,7 @@ def ismount(s): ...@@ -92,7 +105,7 @@ def ismount(s):
if not isabs(s): if not isabs(s):
return False return False
components = split(s) components = split(s)
return len(components) == 2 and components[1] == '' return len(components) == 2 and not components[1]
def islink(s): def islink(s):
"""Return true if the pathname refers to a symbolic link.""" """Return true if the pathname refers to a symbolic link."""
...@@ -131,13 +144,15 @@ def normpath(s): ...@@ -131,13 +144,15 @@ def normpath(s):
"""Normalize a pathname. Will return the same result for """Normalize a pathname. Will return the same result for
equivalent paths.""" equivalent paths."""
if ":" not in s: colon = _get_colon(s)
return ":"+s
if colon not in s:
return colon + s
comps = s.split(":") comps = s.split(colon)
i = 1 i = 1
while i < len(comps)-1: while i < len(comps)-1:
if comps[i] == "" and comps[i-1] != "": if not comps[i] and comps[i-1]:
if i > 1: if i > 1:
del comps[i-1:i+1] del comps[i-1:i+1]
i = i - 1 i = i - 1
...@@ -147,10 +162,10 @@ def normpath(s): ...@@ -147,10 +162,10 @@ def normpath(s):
else: else:
i = i + 1 i = i + 1
s = ":".join(comps) s = colon.join(comps)
# remove trailing ":" except for ":" and "Volume:" # remove trailing ":" except for ":" and "Volume:"
if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s): if s[-1:] == colon and len(comps) > 2 and s != colon*len(s):
s = s[:-1] s = s[:-1]
return s return s
...@@ -169,8 +184,9 @@ def realpath(path): ...@@ -169,8 +184,9 @@ def realpath(path):
return path return path
if not path: if not path:
return path return path
components = path.split(':') colon = _get_colon(path)
path = components[0] + ':' components = path.split(colon)
path = components[0] + colon
for c in components[1:]: for c in components[1:]:
path = join(path, c) path = join(path, c)
path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname() path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
......
...@@ -18,6 +18,14 @@ class MacPathTestCase(unittest.TestCase): ...@@ -18,6 +18,14 @@ class MacPathTestCase(unittest.TestCase):
self.failIf(isabs(":foo:bar")) self.failIf(isabs(":foo:bar"))
self.failIf(isabs(":foo:bar:")) self.failIf(isabs(":foo:bar:"))
self.assert_(isabs(b"xx:yy"))
self.assert_(isabs(b"xx:yy:"))
self.assert_(isabs(b"xx:"))
self.failIf(isabs(b"foo"))
self.failIf(isabs(b":foo"))
self.failIf(isabs(b":foo:bar"))
self.failIf(isabs(b":foo:bar:"))
def test_commonprefix(self): def test_commonprefix(self):
commonprefix = macpath.commonprefix commonprefix = macpath.commonprefix
...@@ -28,6 +36,13 @@ class MacPathTestCase(unittest.TestCase): ...@@ -28,6 +36,13 @@ class MacPathTestCase(unittest.TestCase):
self.assert_(commonprefix([":home:swen:spam", ":home:swen:spam"]) self.assert_(commonprefix([":home:swen:spam", ":home:swen:spam"])
== ":home:swen:spam") == ":home:swen:spam")
self.assert_(commonprefix([b"home:swenson:spam", b"home:swen:spam"])
== b"home:swen")
self.assert_(commonprefix([b":home:swen:spam", b":home:swen:eggs"])
== b":home:swen:")
self.assert_(commonprefix([b":home:swen:spam", b":home:swen:spam"])
== b":home:swen:spam")
def test_split(self): def test_split(self):
split = macpath.split split = macpath.split
self.assertEquals(split("foo:bar"), self.assertEquals(split("foo:bar"),
...@@ -39,11 +54,37 @@ class MacPathTestCase(unittest.TestCase): ...@@ -39,11 +54,37 @@ class MacPathTestCase(unittest.TestCase):
self.assertEquals(split(":conky:mountpoint:"), self.assertEquals(split(":conky:mountpoint:"),
(':conky:mountpoint', '')) (':conky:mountpoint', ''))
self.assertEquals(split(b"foo:bar"),
(b'foo:', b'bar'))
self.assertEquals(split(b"conky:mountpoint:foo:bar"),
(b'conky:mountpoint:foo', b'bar'))
self.assertEquals(split(b":"), (b'', b''))
self.assertEquals(split(b":conky:mountpoint:"),
(b':conky:mountpoint', b''))
def test_join(self):
join = macpath.join
self.assertEquals(join('a', 'b'), ':a:b')
self.assertEquals(join('', 'a:b'), 'a:b')
self.assertEquals(join('a:b', 'c'), 'a:b:c')
self.assertEquals(join('a:b', ':c'), 'a:b:c')
self.assertEquals(join('a', ':b', ':c'), ':a:b:c')
self.assertEquals(join(b'a', b'b'), b':a:b')
self.assertEquals(join(b'', b'a:b'), b'a:b')
self.assertEquals(join(b'a:b', b'c'), b'a:b:c')
self.assertEquals(join(b'a:b', b':c'), b'a:b:c')
self.assertEquals(join(b'a', b':b', b':c'), b':a:b:c')
def test_splitdrive(self): def test_splitdrive(self):
splitdrive = macpath.splitdrive splitdrive = macpath.splitdrive
self.assertEquals(splitdrive("foo:bar"), ('', 'foo:bar')) self.assertEquals(splitdrive("foo:bar"), ('', 'foo:bar'))
self.assertEquals(splitdrive(":foo:bar"), ('', ':foo:bar')) self.assertEquals(splitdrive(":foo:bar"), ('', ':foo:bar'))
self.assertEquals(splitdrive(b"foo:bar"), (b'', b'foo:bar'))
self.assertEquals(splitdrive(b":foo:bar"), (b'', b':foo:bar'))
def test_splitext(self): def test_splitext(self):
splitext = macpath.splitext splitext = macpath.splitext
self.assertEquals(splitext(":foo.ext"), (':foo', '.ext')) self.assertEquals(splitext(":foo.ext"), (':foo', '.ext'))
...@@ -54,6 +95,49 @@ class MacPathTestCase(unittest.TestCase): ...@@ -54,6 +95,49 @@ class MacPathTestCase(unittest.TestCase):
self.assertEquals(splitext(""), ('', '')) self.assertEquals(splitext(""), ('', ''))
self.assertEquals(splitext("foo.bar.ext"), ('foo.bar', '.ext')) self.assertEquals(splitext("foo.bar.ext"), ('foo.bar', '.ext'))
self.assertEquals(splitext(b":foo.ext"), (b':foo', b'.ext'))
self.assertEquals(splitext(b"foo:foo.ext"), (b'foo:foo', b'.ext'))
self.assertEquals(splitext(b".ext"), (b'.ext', b''))
self.assertEquals(splitext(b"foo.ext:foo"), (b'foo.ext:foo', b''))
self.assertEquals(splitext(b":foo.ext:"), (b':foo.ext:', b''))
self.assertEquals(splitext(b""), (b'', b''))
self.assertEquals(splitext(b"foo.bar.ext"), (b'foo.bar', b'.ext'))
def test_ismount(self):
ismount = macpath.ismount
self.assertEquals(ismount("a:"), True)
self.assertEquals(ismount("a:b"), False)
self.assertEquals(ismount("a:b:"), True)
self.assertEquals(ismount(""), False)
self.assertEquals(ismount(":"), False)
self.assertEquals(ismount(b"a:"), True)
self.assertEquals(ismount(b"a:b"), False)
self.assertEquals(ismount(b"a:b:"), True)
self.assertEquals(ismount(b""), False)
self.assertEquals(ismount(b":"), False)
def test_normpath(self):
normpath = macpath.normpath
self.assertEqual(normpath("a:b"), "a:b")
self.assertEqual(normpath("a"), ":a")
self.assertEqual(normpath("a:b::c"), "a:c")
self.assertEqual(normpath("a:b:c:::d"), "a:d")
self.assertRaises(macpath.norm_error, normpath, "a::b")
self.assertRaises(macpath.norm_error, normpath, "a:b:::c")
self.assertEqual(normpath(":"), ":")
self.assertEqual(normpath("a:"), "a:")
self.assertEqual(normpath("a:b:"), "a:b")
self.assertEqual(normpath(b"a:b"), b"a:b")
self.assertEqual(normpath(b"a"), b":a")
self.assertEqual(normpath(b"a:b::c"), b"a:c")
self.assertEqual(normpath(b"a:b:c:::d"), b"a:d")
self.assertRaises(macpath.norm_error, normpath, b"a::b")
self.assertRaises(macpath.norm_error, normpath, b"a:b:::c")
self.assertEqual(normpath(b":"), b":")
self.assertEqual(normpath(b"a:"), b"a:")
self.assertEqual(normpath(b"a:b:"), b"a:b")
def test_main(): def test_main():
support.run_unittest(MacPathTestCase) support.run_unittest(MacPathTestCase)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment