Skip to content

Commit

Permalink
feat: rmtree() test helper
Browse files Browse the repository at this point in the history
This is no more than a wrapper around `shutil.rmtree()`, but with an
error handler that tries to set write permissions on error.

This is a common-enough fix needed on the windows platform that it
seems worth providing a helper for.

Legacy DataLad also has one, but it's implementation seems to be very
much stuck in Python 2 times.
  • Loading branch information
mih committed Nov 1, 2024
1 parent 9b2bb1f commit 5a4541a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
4 changes: 2 additions & 2 deletions datalad_core/repo/tests/test_repo.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from shutil import rmtree

import pytest

from datalad_core.tests import rmtree

from ..repo import Repo


Expand Down
6 changes: 5 additions & 1 deletion datalad_core/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
__all__ = [
'call_git_addcommit',
'rmtree',
]

from .utils import call_git_addcommit
from .utils import (
call_git_addcommit,
rmtree,
)
31 changes: 30 additions & 1 deletion datalad_core/tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import os
from typing import TYPE_CHECKING

if TYPE_CHECKING:
Expand All @@ -8,7 +9,7 @@
PurePath,
)

from shutil import rmtree
from shutil import rmtree as shutil_rmtree

from datalad_core.repo import Worktree
from datalad_core.runners import (
Expand Down Expand Up @@ -149,3 +150,31 @@ def modify_dataset(path: Path) -> str:
file_am_obj.write_text('modified')

return modify_dataset_promise


def _rmtree_onerror(func, path, exc_info): # noqa: ARG001
"""
Error handler for ``shutil.rmtree``.
If the error is due to an access error (read only file)
it attempts to add write permission and then retries.
If the error is for another reason it re-raises the error.
"""
import stat

# Is the error an access error?
if not os.access(path, os.W_OK):
os.chmod(path, stat.S_IWUSR)
func(path)
else:
raise


def rmtree(path: Path) -> None:
"""``shutil.rmtree()`` with an error handler that sets write permissions"""
shutil_rmtree(
path,
# deprecated with PY3.12 -> onexc=
onerror=_rmtree_onerror,
)

0 comments on commit 5a4541a

Please sign in to comment.