temp.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. """
  2. The temp module provides a NamedTemporaryFile that can be reopened in the same
  3. process on any platform. Most platforms use the standard Python
  4. tempfile.NamedTemporaryFile class, but Windows users are given a custom class.
  5. This is needed because the Python implementation of NamedTemporaryFile uses the
  6. O_TEMPORARY flag under Windows, which prevents the file from being reopened
  7. if the same flag is not provided [1][2]. Note that this does not address the
  8. more general issue of opening a file for writing and reading in multiple
  9. processes in a manner that works across platforms.
  10. Also note that the custom version of NamedTemporaryFile does not support the
  11. full range of keyword arguments available in Python 2.6+ and 3.0+.
  12. 1: https://mail.python.org/pipermail/python-list/2005-December/336958.html
  13. 2: http://bugs.python.org/issue14243
  14. """
  15. import os
  16. import tempfile
  17. from django.core.files.utils import FileProxyMixin
  18. __all__ = ('NamedTemporaryFile', 'gettempdir',)
  19. if os.name == 'nt':
  20. class TemporaryFile(FileProxyMixin):
  21. """
  22. Temporary file object constructor that supports reopening of the
  23. temporary file in Windows.
  24. Note that __init__() does not support the 'delete' keyword argument in
  25. Python 2.6+, or the 'delete', 'buffering', 'encoding', or 'newline'
  26. keyword arguments in Python 3.0+.
  27. """
  28. def __init__(self, mode='w+b', bufsize=-1, suffix='', prefix='',
  29. dir=None):
  30. fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
  31. self.name = name
  32. self.file = os.fdopen(fd, mode, bufsize)
  33. self.close_called = False
  34. # Because close can be called during shutdown
  35. # we need to cache os.unlink and access it
  36. # as self.unlink only
  37. unlink = os.unlink
  38. def close(self):
  39. if not self.close_called:
  40. self.close_called = True
  41. try:
  42. self.file.close()
  43. except (OSError, IOError):
  44. pass
  45. try:
  46. self.unlink(self.name)
  47. except (OSError):
  48. pass
  49. @property
  50. def closed(self):
  51. """
  52. This attribute needs to be accessible in certain situations,
  53. because this class is supposed to mock the API of the class
  54. tempfile.NamedTemporaryFile in the Python standard library.
  55. """
  56. return self.file.closed
  57. def __del__(self):
  58. self.close()
  59. def __enter__(self):
  60. self.file.__enter__()
  61. return self
  62. def __exit__(self, exc, value, tb):
  63. self.file.__exit__(exc, value, tb)
  64. NamedTemporaryFile = TemporaryFile
  65. else:
  66. NamedTemporaryFile = tempfile.NamedTemporaryFile
  67. gettempdir = tempfile.gettempdir