Kaydet (Commit) add98eb4 authored tarafından Antoine Pietri's avatar Antoine Pietri Kaydeden (comit) Steve Dower

bpo-30177: pathlib: include the full path in resolve(strict=False) (#1893)

üst ff48739e
...@@ -183,19 +183,18 @@ class _WindowsFlavour(_Flavour): ...@@ -183,19 +183,18 @@ class _WindowsFlavour(_Flavour):
if strict: if strict:
return self._ext_to_normal(_getfinalpathname(s)) return self._ext_to_normal(_getfinalpathname(s))
else: else:
tail_parts = [] # End of the path after the first one not found
while True: while True:
try: try:
s = self._ext_to_normal(_getfinalpathname(s)) s = self._ext_to_normal(_getfinalpathname(s))
except FileNotFoundError: except FileNotFoundError:
previous_s = s previous_s = s
s = os.path.dirname(s) s, tail = os.path.split(s)
tail_parts.append(tail)
if previous_s == s: if previous_s == s:
return path return path
else: else:
if previous_s is None: return os.path.join(s, *reversed(tail_parts))
return s
else:
return s + os.path.sep + os.path.basename(previous_s)
# Means fallback on absolute # Means fallback on absolute
return None return None
...@@ -326,12 +325,10 @@ class _PosixFlavour(_Flavour): ...@@ -326,12 +325,10 @@ class _PosixFlavour(_Flavour):
try: try:
target = accessor.readlink(newpath) target = accessor.readlink(newpath)
except OSError as e: except OSError as e:
if e.errno != EINVAL: if e.errno != EINVAL and strict:
if strict: raise
raise # Not a symlink, or non-strict mode. We just leave the path
else: # untouched.
return newpath
# Not a symlink
path = newpath path = newpath
else: else:
seen[newpath] = None # not resolved symlink seen[newpath] = None # not resolved symlink
......
...@@ -1492,10 +1492,10 @@ class _BasePathTest(object): ...@@ -1492,10 +1492,10 @@ class _BasePathTest(object):
os.path.join(BASE, 'foo')) os.path.join(BASE, 'foo'))
p = P(BASE, 'foo', 'in', 'spam') p = P(BASE, 'foo', 'in', 'spam')
self.assertEqual(str(p.resolve(strict=False)), self.assertEqual(str(p.resolve(strict=False)),
os.path.join(BASE, 'foo')) os.path.join(BASE, 'foo', 'in', 'spam'))
p = P(BASE, '..', 'foo', 'in', 'spam') p = P(BASE, '..', 'foo', 'in', 'spam')
self.assertEqual(str(p.resolve(strict=False)), self.assertEqual(str(p.resolve(strict=False)),
os.path.abspath(os.path.join('foo'))) os.path.abspath(os.path.join('foo', 'in', 'spam')))
# These are all relative symlinks # These are all relative symlinks
p = P(BASE, 'dirB', 'fileB') p = P(BASE, 'dirB', 'fileB')
self._check_resolve_relative(p, p) self._check_resolve_relative(p, p)
...@@ -1507,16 +1507,18 @@ class _BasePathTest(object): ...@@ -1507,16 +1507,18 @@ class _BasePathTest(object):
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB')) self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB'))
# Non-strict # Non-strict
p = P(BASE, 'dirA', 'linkC', 'fileB', 'foo', 'in', 'spam') p = P(BASE, 'dirA', 'linkC', 'fileB', 'foo', 'in', 'spam')
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB', 'foo'), False) self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB', 'foo', 'in',
'spam'), False)
p = P(BASE, 'dirA', 'linkC', '..', 'foo', 'in', 'spam') p = P(BASE, 'dirA', 'linkC', '..', 'foo', 'in', 'spam')
if os.name == 'nt': if os.name == 'nt':
# In Windows, if linkY points to dirB, 'dirA\linkY\..' # In Windows, if linkY points to dirB, 'dirA\linkY\..'
# resolves to 'dirA' without resolving linkY first. # resolves to 'dirA' without resolving linkY first.
self._check_resolve_relative(p, P(BASE, 'dirA', 'foo'), False) self._check_resolve_relative(p, P(BASE, 'dirA', 'foo', 'in',
'spam'), False)
else: else:
# In Posix, if linkY points to dirB, 'dirA/linkY/..' # In Posix, if linkY points to dirB, 'dirA/linkY/..'
# resolves to 'dirB/..' first before resolving to parent of dirB. # resolves to 'dirB/..' first before resolving to parent of dirB.
self._check_resolve_relative(p, P(BASE, 'foo'), False) self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False)
# Now create absolute symlinks # Now create absolute symlinks
d = tempfile.mkdtemp(suffix='-dirD') d = tempfile.mkdtemp(suffix='-dirD')
self.addCleanup(support.rmtree, d) self.addCleanup(support.rmtree, d)
...@@ -1526,16 +1528,17 @@ class _BasePathTest(object): ...@@ -1526,16 +1528,17 @@ class _BasePathTest(object):
self._check_resolve_absolute(p, P(BASE, 'dirB', 'fileB')) self._check_resolve_absolute(p, P(BASE, 'dirB', 'fileB'))
# Non-strict # Non-strict
p = P(BASE, 'dirA', 'linkX', 'linkY', 'foo', 'in', 'spam') p = P(BASE, 'dirA', 'linkX', 'linkY', 'foo', 'in', 'spam')
self._check_resolve_relative(p, P(BASE, 'dirB', 'foo'), False) self._check_resolve_relative(p, P(BASE, 'dirB', 'foo', 'in', 'spam'),
False)
p = P(BASE, 'dirA', 'linkX', 'linkY', '..', 'foo', 'in', 'spam') p = P(BASE, 'dirA', 'linkX', 'linkY', '..', 'foo', 'in', 'spam')
if os.name == 'nt': if os.name == 'nt':
# In Windows, if linkY points to dirB, 'dirA\linkY\..' # In Windows, if linkY points to dirB, 'dirA\linkY\..'
# resolves to 'dirA' without resolving linkY first. # resolves to 'dirA' without resolving linkY first.
self._check_resolve_relative(p, P(d, 'foo'), False) self._check_resolve_relative(p, P(d, 'foo', 'in', 'spam'), False)
else: else:
# In Posix, if linkY points to dirB, 'dirA/linkY/..' # In Posix, if linkY points to dirB, 'dirA/linkY/..'
# resolves to 'dirB/..' first before resolving to parent of dirB. # resolves to 'dirB/..' first before resolving to parent of dirB.
self._check_resolve_relative(p, P(BASE, 'foo'), False) self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False)
@support.skip_unless_symlink @support.skip_unless_symlink
def test_resolve_dot(self): def test_resolve_dot(self):
...@@ -1549,7 +1552,7 @@ class _BasePathTest(object): ...@@ -1549,7 +1552,7 @@ class _BasePathTest(object):
r = q / '3' / '4' r = q / '3' / '4'
self.assertRaises(FileNotFoundError, r.resolve, strict=True) self.assertRaises(FileNotFoundError, r.resolve, strict=True)
# Non-strict # Non-strict
self.assertEqual(r.resolve(strict=False), p / '3') self.assertEqual(r.resolve(strict=False), p / '3' / '4')
def test_with(self): def test_with(self):
p = self.cls(BASE) p = self.cls(BASE)
......
...@@ -1201,6 +1201,7 @@ Steve Piercy ...@@ -1201,6 +1201,7 @@ Steve Piercy
Jim St. Pierre Jim St. Pierre
Dan Pierson Dan Pierson
Martijn Pieters Martijn Pieters
Antoine Pietri
Anand B. Pillai Anand B. Pillai
François Pinard François Pinard
Tom Pinckney Tom Pinckney
......
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