[pypy-svn] pypy default: issue631 resolved (at least on posix) (I think).
arigo
commits-noreply at bitbucket.org
Sun Feb 6 19:04:11 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r41661:2ea70f35cc0e
Date: 2011-02-06 19:02 +0100
http://bitbucket.org/pypy/pypy/changeset/2ea70f35cc0e/
Log: issue631 resolved (at least on posix) (I think).
diff --git a/pypy/translator/goal/test2/test_nanos.py b/pypy/translator/goal/test2/test_nanos.py
--- a/pypy/translator/goal/test2/test_nanos.py
+++ b/pypy/translator/goal/test2/test_nanos.py
@@ -48,6 +48,14 @@
assert p2.abspath(base) == base
assert p2.abspath('x') == os.path.join(os.getcwd(), 'x')
+ def test_abspath_uses_normpath(self):
+ p1 = os.path
+ p2 = self.getnanos().path
+ base = str(udir)
+ assert p2.abspath(p1.join(base, '.')) == base
+ assert p2.abspath(p1.join(base, '.', '.', '.')) == base
+ assert p2.abspath(p1.join(base, 'foo', '..')) == base
+
def test_isfile(self):
p2 = self.getnanos().path
udir.join('test_isfile').write('\n')
diff --git a/pypy/translator/goal/nanos.py b/pypy/translator/goal/nanos.py
--- a/pypy/translator/goal/nanos.py
+++ b/pypy/translator/goal/nanos.py
@@ -47,12 +47,37 @@
path += '/' + b
return path
+ def normpath(path):
+ if path == '':
+ return '.'
+ initial_slashes = path.startswith('/')
+ # POSIX allows one or two initial slashes, but treats three or more
+ # as single slash.
+ if (initial_slashes and
+ path.startswith('//') and not path.startswith('///')):
+ initial_slashes = 2
+ comps = path.split('/')
+ new_comps = []
+ for comp in comps:
+ if comp in ('', '.'):
+ continue
+ if (comp != '..' or (not initial_slashes and not new_comps) or
+ (new_comps and new_comps[-1] == '..')):
+ new_comps.append(comp)
+ elif new_comps:
+ new_comps.pop()
+ comps = new_comps
+ path = '/'.join(comps)
+ if initial_slashes:
+ path = '/'*initial_slashes + path
+ return path or '.'
+
def abspath(path):
if not path.startswith('/'):
import posix
cwd = posix.getcwd()
path = join(cwd, path)
- return path # this version does not call normpath()!
+ return normpath(path)
def isfile(path):
import posix
@@ -84,7 +109,7 @@
elif os.name == 'nt':
# code copied from ntpath.py
- app_os_path = applevel("""
+ app_os_path = applevel(r"""
def splitdrive(p):
if p[1:2] == ':':
return p[0:2], p[2:]
@@ -158,6 +183,55 @@
return path
+ def normpath(path):
+ if path.startswith(('\\\\.\\', '\\\\?\\')):
+ # in the case of paths with these prefixes:
+ # \\.\ -> device names
+ # \\?\ -> literal paths
+ # do not do any normalization, but return the path unchanged
+ return path
+ path = path.replace('/', '\\')
+ prefix, path = splitdrive(path)
+ # We need to be careful here. If the prefix is empty, and
+ # the path starts with a backslash, it could either be an
+ # absolute path on the current drive (\dir1\dir2\file) or a
+ # UNC filename (\\server\mount\dir1\file). It is therefore
+ # imperative NOT to collapse multiple backslashes blindly in
+ # that case. The code below preserves multiple backslashes
+ # when there is no drive letter. This means that the invalid
+ # filename \\\a\b is preserved unchanged, where a\\\b is
+ # normalised to a\b. It's not clear that there is any better
+ # behaviour for such edge cases.
+ if prefix == '':
+ # No drive letter - preserve initial backslashes
+ while path[:1] == "\\":
+ prefix = prefix + '\\'
+ path = path[1:]
+ else:
+ # We have a drive letter - collapse initial backslashes
+ if path.startswith("\\"):
+ prefix = prefix + '\\'
+ path = path.lstrip("\\")
+ comps = path.split("\\")
+ i = 0
+ while i < len(comps):
+ if comps[i] in ('.', ''):
+ del comps[i]
+ elif comps[i] == '..':
+ if i > 0 and comps[i-1] != '..':
+ del comps[i-1:i+1]
+ i -= 1
+ elif i == 0 and prefix.endswith("\\"):
+ del comps[i]
+ else:
+ i += 1
+ else:
+ i += 1
+ # If the path is now empty, substitute '.'
+ if not prefix and not comps:
+ comps.append('.')
+ return prefix + '\\'.join(comps)
+
def abspath(path):
import nt
if path: # Empty path must return current working directory.
@@ -167,7 +241,7 @@
pass # Bad path - return unchanged.
else:
path = nt.getcwd()
- return path # this version does not call normpath()!
+ return normpath(path)
def isfile(path):
import nt
More information about the Pypy-commit
mailing list