diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 4b48880d6d9a18..4e386241114c35 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -1654,15 +1654,19 @@ Copying, moving and deleting Remove this file or symbolic link. If the path points to a directory, use :func:`Path.rmdir` instead. - If *missing_ok* is false (the default), :exc:`FileNotFoundError` is - raised if the path does not exist. + If *missing_ok* is false (the default), this method propagates any + :exc:`OSError` from the operating system. - If *missing_ok* is true, :exc:`FileNotFoundError` exceptions will be - ignored (same behavior as the POSIX ``rm -f`` command). + If *missing_ok* is true, :exc:`FileNotFoundError` and + :exc:`NotADirectoryError` exceptions will be ignored. This behavior is + similar to the POSIX ``rm -f`` command. .. versionchanged:: 3.8 The *missing_ok* parameter was added. + .. versionchanged:: 3.14 + Suppresses :exc:`NotADirectoryError` exceptions when *missing_ok* is + true. .. method:: Path.rmdir() diff --git a/Lib/pathlib/_local.py b/Lib/pathlib/_local.py index 2b42f3c22254b8..22e59f17588d16 100644 --- a/Lib/pathlib/_local.py +++ b/Lib/pathlib/_local.py @@ -1104,7 +1104,7 @@ def unlink(self, missing_ok=False): """ try: os.unlink(self) - except FileNotFoundError: + except (FileNotFoundError, NotADirectoryError): if not missing_ok: raise diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py index 866a2d07dd692a..68e73464b1cc96 100644 --- a/Lib/test/test_pathlib/test_pathlib.py +++ b/Lib/test/test_pathlib/test_pathlib.py @@ -1882,6 +1882,15 @@ def test_unlink_missing_ok(self): self.assertFileNotFound(p.unlink) p.unlink(missing_ok=True) + #Windows will raise FileNotFoundError - handling already tested above. + @needs_posix + def test_unlink_missing_ok_intermediate_file(self): + p = self.cls(self.base) / 'fileAAA' + p.touch() + p = p / 'fileBBB' + self.assertNotADirectory(p.unlink) + p.unlink(missing_ok=True) + def test_rmdir(self): p = self.cls(self.base) / 'dirA' for q in p.iterdir(): diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py b/Lib/test/test_pathlib/test_pathlib_abc.py index d60bb147b72971..21bcfc884dc4a2 100644 --- a/Lib/test/test_pathlib/test_pathlib_abc.py +++ b/Lib/test/test_pathlib/test_pathlib_abc.py @@ -1067,6 +1067,11 @@ def assertFileNotFound(self, func, *args, **kwargs): func(*args, **kwargs) self.assertEqual(cm.exception.errno, errno.ENOENT) + def assertNotADirectory(self, func, *args, **kwargs): + with self.assertRaises(NotADirectoryError) as cm: + func(*args, **kwargs) + self.assertEqual(cm.exception.errno, errno.ENOTDIR) + def assertEqualNormCase(self, path_a, path_b): normcase = self.parser.normcase self.assertEqual(normcase(path_a), normcase(path_b)) diff --git a/Misc/NEWS.d/next/Library/2024-07-04-11-55-15.gh-issue-119993._IXsOb.rst b/Misc/NEWS.d/next/Library/2024-07-04-11-55-15.gh-issue-119993._IXsOb.rst new file mode 100644 index 00000000000000..4199422ccabca8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-04-11-55-15.gh-issue-119993._IXsOb.rst @@ -0,0 +1,2 @@ +:meth:`pathlib.Path.unlink` will also ignore any :exc:`NotADirectoryError` +if *missing_ok* is true.