25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 

54 satır
1.5 KiB

  1. """Convenience layer on top of stdlib's shutil and os"""
  2. import os
  3. import stat
  4. from typing import Callable, TypeVar
  5. from .compat import py311
  6. from distutils import log
  7. try:
  8. from os import chmod # pyright: ignore[reportAssignmentType]
  9. # Losing type-safety w/ pyright, but that's ok
  10. except ImportError: # pragma: no cover
  11. # Jython compatibility
  12. def chmod(*args: object, **kwargs: object) -> None: # type: ignore[misc] # Mypy reuses the imported definition anyway
  13. pass
  14. _T = TypeVar("_T")
  15. def attempt_chmod_verbose(path, mode):
  16. log.debug("changing mode of %s to %o", path, mode)
  17. try:
  18. chmod(path, mode)
  19. except OSError as e: # pragma: no cover
  20. log.debug("chmod failed: %s", e)
  21. # Must match shutil._OnExcCallback
  22. def _auto_chmod(
  23. func: Callable[..., _T], arg: str, exc: BaseException
  24. ) -> _T: # pragma: no cover
  25. """shutils onexc callback to automatically call chmod for certain functions."""
  26. # Only retry for scenarios known to have an issue
  27. if func in [os.unlink, os.remove] and os.name == 'nt':
  28. attempt_chmod_verbose(arg, stat.S_IWRITE)
  29. return func(arg)
  30. raise exc
  31. def rmtree(path, ignore_errors=False, onexc=_auto_chmod):
  32. """
  33. Similar to ``shutil.rmtree`` but automatically executes ``chmod``
  34. for well know Windows failure scenarios.
  35. """
  36. return py311.shutil_rmtree(path, ignore_errors, onexc)
  37. def rmdir(path, **opts):
  38. if os.path.isdir(path):
  39. rmtree(path, **opts)