PyXR

c:\python24\lib \ tempfile.py



0001 """Temporary files.
0002 
0003 This module provides generic, low- and high-level interfaces for
0004 creating temporary files and directories.  The interfaces listed
0005 as "safe" just below can be used without fear of race conditions.
0006 Those listed as "unsafe" cannot, and are provided for backward
0007 compatibility only.
0008 
0009 This module also provides some data items to the user:
0010 
0011   TMP_MAX  - maximum number of names that will be tried before
0012              giving up.
0013   template - the default prefix for all temporary names.
0014              You may change this to control the default prefix.
0015   tempdir  - If this is set to a string before the first use of
0016              any routine from this module, it will be considered as
0017              another candidate location to store temporary files.
0018 """
0019 
0020 __all__ = [
0021     "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
0022     "mkstemp", "mkdtemp",                  # low level safe interfaces
0023     "mktemp",                              # deprecated unsafe interface
0024     "TMP_MAX", "gettempprefix",            # constants
0025     "tempdir", "gettempdir"
0026    ]
0027 
0028 
0029 # Imports.
0030 
0031 import os as _os
0032 import errno as _errno
0033 from random import Random as _Random
0034 
0035 if _os.name == 'mac':
0036     import Carbon.Folder as _Folder
0037     import Carbon.Folders as _Folders
0038 
0039 try:
0040     import fcntl as _fcntl
0041 except ImportError:
0042     def _set_cloexec(fd):
0043         pass
0044 else:
0045     def _set_cloexec(fd):
0046         try:
0047             flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
0048         except IOError:
0049             pass
0050         else:
0051             # flags read successfully, modify
0052             flags |= _fcntl.FD_CLOEXEC
0053             _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
0054 
0055 
0056 try:
0057     import thread as _thread
0058 except ImportError:
0059     import dummy_thread as _thread
0060 _allocate_lock = _thread.allocate_lock
0061 
0062 _text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
0063 if hasattr(_os, 'O_NOINHERIT'):
0064     _text_openflags |= _os.O_NOINHERIT
0065 if hasattr(_os, 'O_NOFOLLOW'):
0066     _text_openflags |= _os.O_NOFOLLOW
0067 
0068 _bin_openflags = _text_openflags
0069 if hasattr(_os, 'O_BINARY'):
0070     _bin_openflags |= _os.O_BINARY
0071 
0072 if hasattr(_os, 'TMP_MAX'):
0073     TMP_MAX = _os.TMP_MAX
0074 else:
0075     TMP_MAX = 10000
0076 
0077 template = "tmp"
0078 
0079 tempdir = None
0080 
0081 # Internal routines.
0082 
0083 _once_lock = _allocate_lock()
0084 
0085 if hasattr(_os, "lstat"):
0086     _stat = _os.lstat
0087 elif hasattr(_os, "stat"):
0088     _stat = _os.stat
0089 else:
0090     # Fallback.  All we need is something that raises os.error if the
0091     # file doesn't exist.
0092     def _stat(fn):
0093         try:
0094             f = open(fn)
0095         except IOError:
0096             raise _os.error
0097         f.close()
0098 
0099 def _exists(fn):
0100     try:
0101         _stat(fn)
0102     except _os.error:
0103         return False
0104     else:
0105         return True
0106 
0107 class _RandomNameSequence:
0108     """An instance of _RandomNameSequence generates an endless
0109     sequence of unpredictable strings which can safely be incorporated
0110     into file names.  Each string is six characters long.  Multiple
0111     threads can safely use the same instance at the same time.
0112 
0113     _RandomNameSequence is an iterator."""
0114 
0115     characters = ("abcdefghijklmnopqrstuvwxyz" +
0116                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
0117                   "0123456789-_")
0118 
0119     def __init__(self):
0120         self.mutex = _allocate_lock()
0121         self.rng = _Random()
0122         self.normcase = _os.path.normcase
0123 
0124     def __iter__(self):
0125         return self
0126 
0127     def next(self):
0128         m = self.mutex
0129         c = self.characters
0130         choose = self.rng.choice
0131 
0132         m.acquire()
0133         try:
0134             letters = [choose(c) for dummy in "123456"]
0135         finally:
0136             m.release()
0137 
0138         return self.normcase(''.join(letters))
0139 
0140 def _candidate_tempdir_list():
0141     """Generate a list of candidate temporary directories which
0142     _get_default_tempdir will try."""
0143 
0144     dirlist = []
0145 
0146     # First, try the environment.
0147     for envname in 'TMPDIR', 'TEMP', 'TMP':
0148         dirname = _os.getenv(envname)
0149         if dirname: dirlist.append(dirname)
0150 
0151     # Failing that, try OS-specific locations.
0152     if _os.name == 'mac':
0153         try:
0154             fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
0155                                               _Folders.kTemporaryFolderType, 1)
0156             dirname = fsr.as_pathname()
0157             dirlist.append(dirname)
0158         except _Folder.error:
0159             pass
0160     elif _os.name == 'riscos':
0161         dirname = _os.getenv('Wimp$ScrapDir')
0162         if dirname: dirlist.append(dirname)
0163     elif _os.name == 'nt':
0164         dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
0165     else:
0166         dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
0167 
0168     # As a last resort, the current directory.
0169     try:
0170         dirlist.append(_os.getcwd())
0171     except (AttributeError, _os.error):
0172         dirlist.append(_os.curdir)
0173 
0174     return dirlist
0175 
0176 def _get_default_tempdir():
0177     """Calculate the default directory to use for temporary files.
0178     This routine should be called exactly once.
0179 
0180     We determine whether or not a candidate temp dir is usable by
0181     trying to create and write to a file in that directory.  If this
0182     is successful, the test file is deleted.  To prevent denial of
0183     service, the name of the test file must be randomized."""
0184 
0185     namer = _RandomNameSequence()
0186     dirlist = _candidate_tempdir_list()
0187     flags = _text_openflags
0188 
0189     for dir in dirlist:
0190         if dir != _os.curdir:
0191             dir = _os.path.normcase(_os.path.abspath(dir))
0192         # Try only a few names per directory.
0193         for seq in xrange(100):
0194             name = namer.next()
0195             filename = _os.path.join(dir, name)
0196             try:
0197                 fd = _os.open(filename, flags, 0600)
0198                 fp = _os.fdopen(fd, 'w')
0199                 fp.write('blat')
0200                 fp.close()
0201                 _os.unlink(filename)
0202                 del fp, fd
0203                 return dir
0204             except (OSError, IOError), e:
0205                 if e[0] != _errno.EEXIST:
0206                     break # no point trying more names in this directory
0207                 pass
0208     raise IOError, (_errno.ENOENT,
0209                     ("No usable temporary directory found in %s" % dirlist))
0210 
0211 _name_sequence = None
0212 
0213 def _get_candidate_names():
0214     """Common setup sequence for all user-callable interfaces."""
0215 
0216     global _name_sequence
0217     if _name_sequence is None:
0218         _once_lock.acquire()
0219         try:
0220             if _name_sequence is None:
0221                 _name_sequence = _RandomNameSequence()
0222         finally:
0223             _once_lock.release()
0224     return _name_sequence
0225 
0226 
0227 def _mkstemp_inner(dir, pre, suf, flags):
0228     """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
0229 
0230     names = _get_candidate_names()
0231 
0232     for seq in xrange(TMP_MAX):
0233         name = names.next()
0234         file = _os.path.join(dir, pre + name + suf)
0235         try:
0236             fd = _os.open(file, flags, 0600)
0237             _set_cloexec(fd)
0238             return (fd, _os.path.abspath(file))
0239         except OSError, e:
0240             if e.errno == _errno.EEXIST:
0241                 continue # try again
0242             raise
0243 
0244     raise IOError, (_errno.EEXIST, "No usable temporary file name found")
0245 
0246 
0247 # User visible interfaces.
0248 
0249 def gettempprefix():
0250     """Accessor for tempdir.template."""
0251     return template
0252 
0253 tempdir = None
0254 
0255 def gettempdir():
0256     """Accessor for tempdir.tempdir."""
0257     global tempdir
0258     if tempdir is None:
0259         _once_lock.acquire()
0260         try:
0261             if tempdir is None:
0262                 tempdir = _get_default_tempdir()
0263         finally:
0264             _once_lock.release()
0265     return tempdir
0266 
0267 def mkstemp(suffix="", prefix=template, dir=None, text=False):
0268     """mkstemp([suffix, [prefix, [dir, [text]]]])
0269     User-callable function to create and return a unique temporary
0270     file.  The return value is a pair (fd, name) where fd is the
0271     file descriptor returned by os.open, and name is the filename.
0272 
0273     If 'suffix' is specified, the file name will end with that suffix,
0274     otherwise there will be no suffix.
0275 
0276     If 'prefix' is specified, the file name will begin with that prefix,
0277     otherwise a default prefix is used.
0278 
0279     If 'dir' is specified, the file will be created in that directory,
0280     otherwise a default directory is used.
0281 
0282     If 'text' is specified and true, the file is opened in text
0283     mode.  Else (the default) the file is opened in binary mode.  On
0284     some operating systems, this makes no difference.
0285 
0286     The file is readable and writable only by the creating user ID.
0287     If the operating system uses permission bits to indicate whether a
0288     file is executable, the file is executable by no one. The file
0289     descriptor is not inherited by children of this process.
0290 
0291     Caller is responsible for deleting the file when done with it.
0292     """
0293 
0294     if dir is None:
0295         dir = gettempdir()
0296 
0297     if text:
0298         flags = _text_openflags
0299     else:
0300         flags = _bin_openflags
0301 
0302     return _mkstemp_inner(dir, prefix, suffix, flags)
0303 
0304 
0305 def mkdtemp(suffix="", prefix=template, dir=None):
0306     """mkdtemp([suffix, [prefix, [dir]]])
0307     User-callable function to create and return a unique temporary
0308     directory.  The return value is the pathname of the directory.
0309 
0310     Arguments are as for mkstemp, except that the 'text' argument is
0311     not accepted.
0312 
0313     The directory is readable, writable, and searchable only by the
0314     creating user.
0315 
0316     Caller is responsible for deleting the directory when done with it.
0317     """
0318 
0319     if dir is None:
0320         dir = gettempdir()
0321 
0322     names = _get_candidate_names()
0323 
0324     for seq in xrange(TMP_MAX):
0325         name = names.next()
0326         file = _os.path.join(dir, prefix + name + suffix)
0327         try:
0328             _os.mkdir(file, 0700)
0329             return file
0330         except OSError, e:
0331             if e.errno == _errno.EEXIST:
0332                 continue # try again
0333             raise
0334 
0335     raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
0336 
0337 def mktemp(suffix="", prefix=template, dir=None):
0338     """mktemp([suffix, [prefix, [dir]]])
0339     User-callable function to return a unique temporary file name.  The
0340     file is not created.
0341 
0342     Arguments are as for mkstemp, except that the 'text' argument is
0343     not accepted.
0344 
0345     This function is unsafe and should not be used.  The file name
0346     refers to a file that did not exist at some point, but by the time
0347     you get around to creating it, someone else may have beaten you to
0348     the punch.
0349     """
0350 
0351 ##    from warnings import warn as _warn
0352 ##    _warn("mktemp is a potential security risk to your program",
0353 ##          RuntimeWarning, stacklevel=2)
0354 
0355     if dir is None:
0356         dir = gettempdir()
0357 
0358     names = _get_candidate_names()
0359     for seq in xrange(TMP_MAX):
0360         name = names.next()
0361         file = _os.path.join(dir, prefix + name + suffix)
0362         if not _exists(file):
0363             return file
0364 
0365     raise IOError, (_errno.EEXIST, "No usable temporary filename found")
0366 
0367 class _TemporaryFileWrapper:
0368     """Temporary file wrapper
0369 
0370     This class provides a wrapper around files opened for
0371     temporary use.  In particular, it seeks to automatically
0372     remove the file when it is no longer needed.
0373     """
0374 
0375     def __init__(self, file, name):
0376         self.file = file
0377         self.name = name
0378         self.close_called = False
0379 
0380     def __getattr__(self, name):
0381         file = self.__dict__['file']
0382         a = getattr(file, name)
0383         if type(a) != type(0):
0384             setattr(self, name, a)
0385         return a
0386 
0387     # NT provides delete-on-close as a primitive, so we don't need
0388     # the wrapper to do anything special.  We still use it so that
0389     # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
0390     if _os.name != 'nt':
0391 
0392         # Cache the unlinker so we don't get spurious errors at
0393         # shutdown when the module-level "os" is None'd out.  Note
0394         # that this must be referenced as self.unlink, because the
0395         # name TemporaryFileWrapper may also get None'd out before
0396         # __del__ is called.
0397         unlink = _os.unlink
0398 
0399         def close(self):
0400             if not self.close_called:
0401                 self.close_called = True
0402                 self.file.close()
0403                 self.unlink(self.name)
0404 
0405         def __del__(self):
0406             self.close()
0407 
0408 def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
0409                        prefix=template, dir=None):
0410     """Create and return a temporary file.
0411     Arguments:
0412     'prefix', 'suffix', 'dir' -- as for mkstemp.
0413     'mode' -- the mode argument to os.fdopen (default "w+b").
0414     'bufsize' -- the buffer size argument to os.fdopen (default -1).
0415     The file is created as mkstemp() would do it.
0416 
0417     Returns a file object; the name of the file is accessible as
0418     file.name.  The file will be automatically deleted when it is
0419     closed.
0420     """
0421 
0422     if dir is None:
0423         dir = gettempdir()
0424 
0425     if 'b' in mode:
0426         flags = _bin_openflags
0427     else:
0428         flags = _text_openflags
0429 
0430     # Setting O_TEMPORARY in the flags causes the OS to delete
0431     # the file when it is closed.  This is only supported by Windows.
0432     if _os.name == 'nt':
0433         flags |= _os.O_TEMPORARY
0434 
0435     (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
0436     file = _os.fdopen(fd, mode, bufsize)
0437     return _TemporaryFileWrapper(file, name)
0438 
0439 if _os.name != 'posix' or _os.sys.platform == 'cygwin':
0440     # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
0441     # while it is open.
0442     TemporaryFile = NamedTemporaryFile
0443 
0444 else:
0445     def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
0446                       prefix=template, dir=None):
0447         """Create and return a temporary file.
0448         Arguments:
0449         'prefix', 'suffix', 'directory' -- as for mkstemp.
0450         'mode' -- the mode argument to os.fdopen (default "w+b").
0451         'bufsize' -- the buffer size argument to os.fdopen (default -1).
0452         The file is created as mkstemp() would do it.
0453 
0454         Returns a file object.  The file has no name, and will cease to
0455         exist when it is closed.
0456         """
0457 
0458         if dir is None:
0459             dir = gettempdir()
0460 
0461         if 'b' in mode:
0462             flags = _bin_openflags
0463         else:
0464             flags = _text_openflags
0465 
0466         (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
0467         try:
0468             _os.unlink(name)
0469             return _os.fdopen(fd, mode, bufsize)
0470         except:
0471             _os.close(fd)
0472             raise
0473 

Generated by PyXR 0.9.4
SourceForge.net Logo