pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/072011b3c38f871cdc3ab62630ea2234d09456d1

48faa60c69660fa.css" /> gh-100809: Fix handling of drive-relative paths in pathlib.Path.absol… · python/cpython@072011b · GitHub
Skip to content

Commit 072011b

Browse files
authored
gh-100809: Fix handling of drive-relative paths in pathlib.Path.absolute() (GH-100812)
Resolving the drive independently uses the OS API, which ensures it starts from the current directory on that drive.
1 parent d401b20 commit 072011b

4 files changed

Lines changed: 64 additions & 1 deletion

File tree

Lib/pathlib.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,12 @@ def absolute(self):
816816
"""
817817
if self.is_absolute():
818818
return self
819-
return self._from_parts([os.getcwd()] + self._parts)
819+
elif self._drv:
820+
# There is a CWD on each drive-letter drive.
821+
cwd = self._flavour.abspath(self._drv)
822+
else:
823+
cwd = os.getcwd()
824+
return self._from_parts([cwd] + self._parts)
820825

821826
def resolve(self, strict=False):
822827
"""

Lib/test/support/os_helper.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import re
66
import stat
7+
import string
78
import sys
89
import time
910
import unittest
@@ -716,3 +717,37 @@ def __exit__(self, *ignore_exc):
716717
else:
717718
self._environ[k] = v
718719
os.environ = self._environ
720+
721+
722+
try:
723+
import ctypes
724+
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
725+
726+
ERROR_FILE_NOT_FOUND = 2
727+
DDD_REMOVE_DEFINITION = 2
728+
DDD_EXACT_MATCH_ON_REMOVE = 4
729+
DDD_NO_BROADCAST_SYSTEM = 8
730+
except (ImportError, AttributeError):
731+
def subst_drive(path):
732+
raise unittest.SkipTest('ctypes or kernel32 is not available')
733+
else:
734+
@contextlib.contextmanager
735+
def subst_drive(path):
736+
"""Temporarily yield a substitute drive for a given path."""
737+
for c in reversed(string.ascii_uppercase):
738+
drive = f'{c}:'
739+
if (not kernel32.QueryDosDeviceW(drive, None, 0) and
740+
ctypes.get_last_error() == ERROR_FILE_NOT_FOUND):
741+
break
742+
else:
743+
raise unittest.SkipTest('no available logical drive')
744+
if not kernel32.DefineDosDeviceW(
745+
DDD_NO_BROADCAST_SYSTEM, drive, path):
746+
raise ctypes.WinError(ctypes.get_last_error())
747+
try:
748+
yield drive
749+
finally:
750+
if not kernel32.DefineDosDeviceW(
751+
DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
752+
drive, path):
753+
raise ctypes.WinError(ctypes.get_last_error())

Lib/test/test_pathlib.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2973,6 +2973,26 @@ def test_absolute(self):
29732973
self.assertEqual(str(P('a', 'b', 'c').absolute()),
29742974
os.path.join(share, 'a', 'b', 'c'))
29752975

2976+
drive = os.path.splitdrive(BASE)[0]
2977+
with os_helper.change_cwd(BASE):
2978+
# Relative path with root
2979+
self.assertEqual(str(P('\\').absolute()), drive + '\\')
2980+
self.assertEqual(str(P('\\foo').absolute()), drive + '\\foo')
2981+
2982+
# Relative path on current drive
2983+
self.assertEqual(str(P(drive).absolute()), BASE)
2984+
self.assertEqual(str(P(drive + 'foo').absolute()), os.path.join(BASE, 'foo'))
2985+
2986+
with os_helper.subst_drive(BASE) as other_drive:
2987+
# Set the working directory on the substitute drive
2988+
saved_cwd = os.getcwd()
2989+
other_cwd = f'{other_drive}\\dirA'
2990+
os.chdir(other_cwd)
2991+
os.chdir(saved_cwd)
2992+
2993+
# Relative path on another drive
2994+
self.assertEqual(str(P(other_drive).absolute()), other_cwd)
2995+
self.assertEqual(str(P(other_drive + 'foo').absolute()), other_cwd + '\\foo')
29762996

29772997
def test_glob(self):
29782998
P = self.cls
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix handling of drive-relative paths (like 'C:' and 'C:foo') in
2+
:meth:`pathlib.Path.absolute`. This method now uses the OS API
3+
to retrieve the correct current working directory for the drive.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy