diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 37934c6038e1d1..1cb29a7d325110 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -15,7 +15,7 @@ if os.name == 'nt': - from nt import _getfinalpathname + from nt import _getfinalpathname, _getfullpathname else: _getfinalpathname = None @@ -189,26 +189,26 @@ def compile_pattern(self, pattern): def resolve(self, path, strict=False): s = str(path) if not s: - return path._accessor.getcwd() + s = path._accessor.getcwd() + if _getfinalpathname is None: + return None # Means fallback on absolute + if strict: + return self._ext_to_normal(_getfinalpathname(s)) + s = path = _getfullpathname(s) previous_s = None - if _getfinalpathname is not None: - if strict: - return self._ext_to_normal(_getfinalpathname(s)) + 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, tail = os.path.split(s) + tail_parts.append(tail) + if previous_s == s: + # Root reached, fallback to _getfullpathname() + return path 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, tail = os.path.split(s) - tail_parts.append(tail) - if previous_s == s: - return path - else: - return os.path.join(s, *reversed(tail_parts)) - # Means fallback on absolute - return None + return os.path.join(s, *reversed(tail_parts)) def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix): prefix = '' diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 6ed08f7e70ce3d..4fbd46f4923c88 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1799,6 +1799,16 @@ def test_resolve_dot(self): # Non-strict self.assertEqual(r.resolve(strict=False), p / '3' / '4') + def test_resolve_nonexist_relative_issue38671(self): + p = self.cls('non', 'exist') + + old_cwd = os.getcwd() + os.chdir(BASE) + try: + self.assertEqual(p.resolve(), self.cls(BASE, p)) + finally: + os.chdir(old_cwd) + def test_with(self): p = self.cls(BASE) it = p.iterdir() diff --git a/Misc/NEWS.d/next/Library/2019-12-28-02-50-12.bpo-38671.xT4R0P.rst b/Misc/NEWS.d/next/Library/2019-12-28-02-50-12.bpo-38671.xT4R0P.rst new file mode 100644 index 00000000000000..a012fa57c3d976 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-12-28-02-50-12.bpo-38671.xT4R0P.rst @@ -0,0 +1,2 @@ +Ensure pathlib.Path.resolve(strict=False) returns an absolute path on +Windows when the path is relative and does not exist.