You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fileutil.py 1.4KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. from contextlib import contextmanager, ExitStack
  2. from pathlib import Path
  3. from typing import Iterator, Union, Optional
  4. import shutil
  5. @contextmanager
  6. def ensure_dir(dirpath: Path) -> Iterator[Path]:
  7. """
  8. Ensure that the given directory (and any parents) exist. When the context
  9. exists, removes any directories that were created.
  10. """
  11. dirpath = dirpath.absolute()
  12. if dirpath.exists():
  13. assert dirpath.is_dir(), f'Directory {dirpath} is a non-directory file'
  14. yield dirpath
  15. return
  16. # Create the directory and clean it up when we are done
  17. with ensure_dir(dirpath.parent):
  18. dirpath.mkdir()
  19. try:
  20. yield dirpath
  21. finally:
  22. shutil.rmtree(dirpath)
  23. @contextmanager
  24. def auto_delete(fpath: Path) -> Iterator[Path]:
  25. try:
  26. yield fpath
  27. finally:
  28. if fpath.exists():
  29. fpath.unlink()
  30. @contextmanager
  31. def set_contents(fpath: Path, content: bytes) -> Iterator[Path]:
  32. prev_content: Optional[bytes] = None
  33. if fpath.exists():
  34. assert fpath.is_file(), 'File {fpath} exists and is not a regular file'
  35. prev_content = fpath.read_bytes()
  36. with ensure_dir(fpath.parent):
  37. fpath.write_bytes(content)
  38. try:
  39. yield fpath
  40. finally:
  41. if prev_content is None:
  42. fpath.unlink()
  43. else:
  44. fpath.write_bytes(prev_content)