diff options
author | Antoine Pietri <seirl@users.noreply.github.com> | 2017-06-07 15:29:17 (GMT) |
---|---|---|
committer | Steve Dower <steve.dower@microsoft.com> | 2017-06-07 15:29:17 (GMT) |
commit | add98eb4fe41baeaa70fbd4ccc020833740609a4 (patch) | |
tree | 947ad36447e92d8b1b14705ff1641d0df31765a9 | |
parent | ff48739ed0a3f366c4d56d3c86a37cbdeec600de (diff) | |
download | cpython-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.py | 19 | ||||
-rw-r--r-- | Lib/test/test_pathlib.py | 21 | ||||
-rw-r--r-- | Misc/ACKS | 1 |
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) @@ -1201,6 +1201,7 @@ Steve Piercy Jim St. Pierre Dan Pierson Martijn Pieters +Antoine Pietri Anand B. Pillai François Pinard Tom Pinckney |