Skip to content

Commit

Permalink
Merge pull request #4737 from pypa/feature/distutils-251797602
Browse files Browse the repository at this point in the history
Merge bugfixes from distutils
  • Loading branch information
jaraco authored Nov 7, 2024
2 parents 566e47d + 42e0625 commit 1f79847
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 8 deletions.
1 change: 1 addition & 0 deletions newsfragments/+f0b61194.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Merge with pypa/distutils@251797602, including fix for dirutil.mkpath handling in pypa/distutils#304.
11 changes: 3 additions & 8 deletions setuptools/_distutils/dir_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ def wrap(self, func):
def wrapper(path, *args, **kwargs):
if path.absolute() in self:
return
result = func(path, *args, **kwargs)
self.add(path.absolute())
return func(path, *args, **kwargs)
return result

return wrapper

Expand All @@ -44,29 +45,23 @@ def wrapper(path, *args, **kwargs):

@functools.singledispatch
@wrapper
def mkpath(name: pathlib.Path, mode=0o777, verbose=True, dry_run=False):
def mkpath(name: pathlib.Path, mode=0o777, verbose=True, dry_run=False) -> None:
"""Create a directory and any missing ancestor directories.
If the directory already exists (or if 'name' is the empty string, which
means the current directory, which of course exists), then do nothing.
Raise DistutilsFileError if unable to create some directory along the way
(eg. some sub-path exists, but is a file rather than a directory).
If 'verbose' is true, log the directory created.
Return the list of directories actually created.
"""
if verbose and not name.is_dir():
log.info("creating %s", name)

ancestry = itertools.chain((name,), name.parents)
missing = (path for path in ancestry if not path.is_dir())

try:
dry_run or name.mkdir(mode=mode, parents=True, exist_ok=True)
except OSError as exc:
raise DistutilsFileError(f"could not create '{name}': {exc.args[-1]}")

return list(map(str, missing))


@mkpath.register
def _(name: str, *args, **kwargs):
Expand Down
22 changes: 22 additions & 0 deletions setuptools/_distutils/tests/test_dir_util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Tests for distutils.dir_util."""

import os
import pathlib
import stat
import unittest.mock as mock
from distutils import dir_util, errors
Expand Down Expand Up @@ -110,3 +111,24 @@ def test_copy_tree_exception_in_listdir(self):
):
src = self.tempdirs[-1]
dir_util.copy_tree(src, None)

def test_mkpath_exception_uncached(self, monkeypatch, tmp_path):
"""
Caching should not remember failed attempts.
pypa/distutils#304
"""

class FailPath(pathlib.Path):
def mkdir(self, *args, **kwargs):
raise OSError("Failed to create directory")

target = tmp_path / 'foodir'

with pytest.raises(errors.DistutilsFileError):
mkpath(FailPath(target))

assert not target.exists()

mkpath(target)
assert target.exists()

0 comments on commit 1f79847

Please sign in to comment.