tempdir.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. """This module contains classes - NamedFileInTemporaryDirectory, TemporaryWorkingDirectory.
  2. These classes add extra features such as creating a named file in temporary directory and
  3. creating a context manager for the working directory which is also temporary.
  4. """
  5. import os as _os
  6. from io import BufferedWriter
  7. from pathlib import Path
  8. from tempfile import TemporaryDirectory
  9. from types import TracebackType
  10. from typing import Optional, Type
  11. class NamedFileInTemporaryDirectory:
  12. def __init__(self, filename: str, mode: str, bufsize: int=-1, add_to_syspath: bool=False, **kwds):
  13. """
  14. Open a file named `filename` in a temporary directory.
  15. This context manager is preferred over `NamedTemporaryFile` in
  16. stdlib `tempfile` when one needs to reopen the file.
  17. Arguments `mode` and `bufsize` are passed to `open`.
  18. Rest of the arguments are passed to `TemporaryDirectory`.
  19. """
  20. self._tmpdir = TemporaryDirectory(**kwds)
  21. path = Path(self._tmpdir.name) / filename
  22. encoding = None if "b" in mode else "utf-8"
  23. self.file = open(path, mode, bufsize, encoding=encoding)
  24. def cleanup(self):
  25. self.file.close()
  26. self._tmpdir.cleanup()
  27. __del__ = cleanup
  28. def __enter__(self) -> BufferedWriter:
  29. return self.file
  30. def __exit__(self, type: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType]):
  31. self.cleanup()
  32. class TemporaryWorkingDirectory(TemporaryDirectory):
  33. """
  34. Creates a temporary directory and sets the cwd to that directory.
  35. Automatically reverts to previous cwd upon cleanup.
  36. Usage example:
  37. with TemporaryWorkingDirectory() as tmpdir:
  38. ...
  39. """
  40. def __enter__(self) -> str:
  41. self.old_wd = Path.cwd()
  42. _os.chdir(self.name)
  43. return super(TemporaryWorkingDirectory, self).__enter__()
  44. def __exit__(self, exc: Optional[Type[BaseException]], value: Optional[BaseException], tb: Optional[TracebackType]) -> None:
  45. _os.chdir(self.old_wd)
  46. return super(TemporaryWorkingDirectory, self).__exit__(exc, value, tb)