Skip to content

Commit ceabf9a

Browse files
seirlzooba
authored andcommitted
bpo-30177: pathlib: include the full path in resolve(strict=False) (#1893) (#1985)
1 parent 09b6c0c commit ceabf9a

File tree

3 files changed

+21
-20
lines changed

3 files changed

+21
-20
lines changed

Lib/pathlib.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,19 +187,18 @@ def resolve(self, path, strict=False):
187187
if strict:
188188
return self._ext_to_normal(_getfinalpathname(s))
189189
else:
190+
tail_parts = [] # End of the path after the first one not found
190191
while True:
191192
try:
192193
s = self._ext_to_normal(_getfinalpathname(s))
193194
except FileNotFoundError:
194195
previous_s = s
195-
s = os.path.dirname(s)
196+
s, tail = os.path.split(s)
197+
tail_parts.append(tail)
196198
if previous_s == s:
197199
return path
198200
else:
199-
if previous_s is None:
200-
return s
201-
else:
202-
return s + os.path.sep + os.path.basename(previous_s)
201+
return os.path.join(s, *reversed(tail_parts))
203202
# Means fallback on absolute
204203
return None
205204

@@ -330,12 +329,10 @@ def _resolve(path, rest):
330329
try:
331330
target = accessor.readlink(newpath)
332331
except OSError as e:
333-
if e.errno != EINVAL:
334-
if strict:
335-
raise
336-
else:
337-
return newpath
338-
# Not a symlink
332+
if e.errno != EINVAL and strict:
333+
raise
334+
# Not a symlink, or non-strict mode. We just leave the path
335+
# untouched.
339336
path = newpath
340337
else:
341338
seen[newpath] = None # not resolved symlink

Lib/test/test_pathlib.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,10 +1507,10 @@ def test_resolve_common(self):
15071507
os.path.join(BASE, 'foo'))
15081508
p = P(BASE, 'foo', 'in', 'spam')
15091509
self.assertEqual(str(p.resolve(strict=False)),
1510-
os.path.join(BASE, 'foo'))
1510+
os.path.join(BASE, 'foo', 'in', 'spam'))
15111511
p = P(BASE, '..', 'foo', 'in', 'spam')
15121512
self.assertEqual(str(p.resolve(strict=False)),
1513-
os.path.abspath(os.path.join('foo')))
1513+
os.path.abspath(os.path.join('foo', 'in', 'spam')))
15141514
# These are all relative symlinks
15151515
p = P(BASE, 'dirB', 'fileB')
15161516
self._check_resolve_relative(p, p)
@@ -1522,16 +1522,18 @@ def test_resolve_common(self):
15221522
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB'))
15231523
# Non-strict
15241524
p = P(BASE, 'dirA', 'linkC', 'fileB', 'foo', 'in', 'spam')
1525-
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB', 'foo'), False)
1525+
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB', 'foo', 'in',
1526+
'spam'), False)
15261527
p = P(BASE, 'dirA', 'linkC', '..', 'foo', 'in', 'spam')
15271528
if os.name == 'nt':
15281529
# In Windows, if linkY points to dirB, 'dirA\linkY\..'
15291530
# resolves to 'dirA' without resolving linkY first.
1530-
self._check_resolve_relative(p, P(BASE, 'dirA', 'foo'), False)
1531+
self._check_resolve_relative(p, P(BASE, 'dirA', 'foo', 'in',
1532+
'spam'), False)
15311533
else:
15321534
# In Posix, if linkY points to dirB, 'dirA/linkY/..'
15331535
# resolves to 'dirB/..' first before resolving to parent of dirB.
1534-
self._check_resolve_relative(p, P(BASE, 'foo'), False)
1536+
self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False)
15351537
# Now create absolute symlinks
15361538
d = tempfile.mkdtemp(suffix='-dirD')
15371539
self.addCleanup(support.rmtree, d)
@@ -1541,16 +1543,17 @@ def test_resolve_common(self):
15411543
self._check_resolve_absolute(p, P(BASE, 'dirB', 'fileB'))
15421544
# Non-strict
15431545
p = P(BASE, 'dirA', 'linkX', 'linkY', 'foo', 'in', 'spam')
1544-
self._check_resolve_relative(p, P(BASE, 'dirB', 'foo'), False)
1546+
self._check_resolve_relative(p, P(BASE, 'dirB', 'foo', 'in', 'spam'),
1547+
False)
15451548
p = P(BASE, 'dirA', 'linkX', 'linkY', '..', 'foo', 'in', 'spam')
15461549
if os.name == 'nt':
15471550
# In Windows, if linkY points to dirB, 'dirA\linkY\..'
15481551
# resolves to 'dirA' without resolving linkY first.
1549-
self._check_resolve_relative(p, P(d, 'foo'), False)
1552+
self._check_resolve_relative(p, P(d, 'foo', 'in', 'spam'), False)
15501553
else:
15511554
# In Posix, if linkY points to dirB, 'dirA/linkY/..'
15521555
# resolves to 'dirB/..' first before resolving to parent of dirB.
1553-
self._check_resolve_relative(p, P(BASE, 'foo'), False)
1556+
self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False)
15541557

15551558
@with_symlinks
15561559
def test_resolve_dot(self):
@@ -1564,7 +1567,7 @@ def test_resolve_dot(self):
15641567
r = q / '3' / '4'
15651568
self.assertRaises(FileNotFoundError, r.resolve, strict=True)
15661569
# Non-strict
1567-
self.assertEqual(r.resolve(strict=False), p / '3')
1570+
self.assertEqual(r.resolve(strict=False), p / '3' / '4')
15681571

15691572
def test_with(self):
15701573
p = self.cls(BASE)

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,7 @@ Steve Piercy
11901190
Jim St. Pierre
11911191
Dan Pierson
11921192
Martijn Pieters
1193+
Antoine Pietri
11931194
Anand B. Pillai
11941195
François Pinard
11951196
Tom Pinckney

0 commit comments

Comments
 (0)