diff --git a/newsfragments/+mkdir-p-file.bugfix.rst b/newsfragments/+mkdir-p-file.bugfix.rst new file mode 100644 index 0000000..d8f4512 --- /dev/null +++ b/newsfragments/+mkdir-p-file.bugfix.rst @@ -0,0 +1 @@ +``Path.mkdir_p`` and ``Path.makedirs_p`` now raise ``FileExistsError`` when the path already exists as a file. diff --git a/path/__init__.py b/path/__init__.py index 33dd979..587f8d8 100644 --- a/path/__init__.py +++ b/path/__init__.py @@ -1369,8 +1369,11 @@ def mkdir(self, mode: int = 0o777) -> Self: def mkdir_p(self, mode: int = 0o777) -> Self: """Like :meth:`mkdir`, but does not raise an exception if the directory already exists.""" - with contextlib.suppress(FileExistsError): + try: self.mkdir(mode) + except FileExistsError: + if not self.is_dir(): + raise return self def makedirs(self, mode: int = 0o777) -> Self: @@ -1381,8 +1384,11 @@ def makedirs(self, mode: int = 0o777) -> Self: def makedirs_p(self, mode: int = 0o777) -> Self: """Like :meth:`makedirs`, but does not raise an exception if the directory already exists.""" - with contextlib.suppress(FileExistsError): + try: self.makedirs(mode) + except FileExistsError: + if not self.is_dir(): + raise return self def rmdir(self) -> Self: diff --git a/tests/test_path.py b/tests/test_path.py index b424bb6..3c1cde3 100644 --- a/tests/test_path.py +++ b/tests/test_path.py @@ -294,6 +294,18 @@ def test_renames(self, tmpdir): def test_mkdir_p(self, tmpdir): Path(tmpdir).mkdir_p() + @pytest.mark.parametrize('method', ['mkdir_p', 'makedirs_p']) + def test_mkdir_p_existing_file(self, tmpdir, method): + file = (Path(tmpdir) / 'file').touch() + with pytest.raises(FileExistsError): + getattr(file, method)() + assert file.is_file() + + def test_mkdir_p_new_directory(self, tmpdir): + directory = Path(tmpdir) / 'new' + assert directory.mkdir_p() == directory + assert directory.is_dir() + def test_removedirs_p(self, tmpdir): dir = Path(tmpdir) / 'somedir' dir.mkdir()