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.

53 lines
1.4KB

  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)