summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pietri <seirl@users.noreply.github.com>2017-06-07 15:29:17 (GMT)
committerSteve Dower <steve.dower@microsoft.com>2017-06-07 15:29:17 (GMT)
commitadd98eb4fe41baeaa70fbd4ccc020833740609a4 (patch)
tree947ad36447e92d8b1b14705ff1641d0df31765a9
parentff48739ed0a3f366c4d56d3c86a37cbdeec600de (diff)
downloadcpython-add98eb4fe41baeaa70fbd4ccc020833740609a4.zip
cpython-add98eb4fe41baeaa70fbd4ccc020833740609a4.tar.gz
cpython-add98eb4fe41baeaa70fbd4ccc020833740609a4.tar.bz2
bpo-30177: pathlib: include the full path in resolve(strict=False) (#1893)
-rw-r--r--Lib/pathlib.py19
-rw-r--r--Lib/test/test_pathlib.py21
-rw-r--r--Misc/ACKS1
3 files changed, 21 insertions, 20 deletions
diff --git a/Lib/pathlib.py b/Lib/pathlib.py
index 4d89436..0e65c61 100644
--- a/Lib/pathlib.py
+++ b/Lib/pathlib.py
@@ -183,19 +183,18 @@ class _WindowsFlavour(_Flavour):
if strict:
return self._ext_to_normal(_getfinalpathname(s))
else:
+ tail_parts = [] # End of the path after the first one not found
while True:
try:
s = self._ext_to_normal(_getfinalpathname(s))
except FileNotFoundError:
previous_s = s
- s = os.path.dirname(s)
+ s, tail = os.path.split(s)
+ tail_parts.append(tail)
if previous_s == s:
return path
else:
- if previous_s is None:
- return s
- else:
- return s + os.path.sep + os.path.basename(previous_s)
+ return os.path.join(s, *reversed(tail_parts))
# Means fallback on absolute
return None
@@ -326,12 +325,10 @@ class _PosixFlavour(_Flavour):
try:
target = accessor.readlink(newpath)
except OSError as e:
- if e.errno != EINVAL:
- if strict:
- raise
- else:
- return newpath
- # Not a symlink
+ if e.errno != EINVAL and strict:
+ raise
+ # Not a symlink, or non-strict mode. We just leave the path
+ # untouched.
path = newpath
else:
seen[newpath] = None # not resolved symlink
diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py
index 138bc06..16bfee0 100644
--- a/Lib/test/test_pathlib.py
+++ b/Lib/test/test_pathlib.py
@@ -1492,10 +1492,10 @@ class _BasePathTest(object):
os.path.join(BASE, 'foo'))
p = P(BASE, 'foo', 'in', 'spam')
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')
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
p = P(BASE, 'dirB', 'fileB')
self._check_resolve_relative(p, p)
@@ -1507,16 +1507,18 @@ class _BasePathTest(object):
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB'))
# Non-strict
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')
if os.name == 'nt':
# In Windows, if linkY points to dirB, 'dirA\linkY\..'
# 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:
# In Posix, if linkY points to dirB, 'dirA/linkY/..'
# 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
d = tempfile.mkdtemp(suffix='-dirD')
self.addCleanup(support.rmtree, d)
@@ -1526,16 +1528,17 @@ class _BasePathTest(object):
self._check_resolve_absolute(p, P(BASE, 'dirB', 'fileB'))
# Non-strict
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')
if os.name == 'nt':
# In Windows, if linkY points to dirB, 'dirA\linkY\..'
# 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:
# In Posix, if linkY points to dirB, 'dirA/linkY/..'
# 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
def test_resolve_dot(self):
@@ -1549,7 +1552,7 @@ class _BasePathTest(object):
r = q / '3' / '4'
self.assertRaises(FileNotFoundError, r.resolve, strict=True)
# Non-strict
- self.assertEqual(r.resolve(strict=False), p / '3')
+ self.assertEqual(r.resolve(strict=False), p / '3' / '4')
def test_with(self):
p = self.cls(BASE)
diff --git a/Misc/ACKS b/Misc/ACKS
index 85d2fc6..8a5bf6e 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1201,6 +1201,7 @@ Steve Piercy
Jim St. Pierre
Dan Pierson
Martijn Pieters
+Antoine Pietri
Anand B. Pillai
François Pinard
Tom Pinckney