24 Utilities for safe file IO 
   26 from contextlib 
import contextmanager
 
   40     """Make a directory in a manner avoiding race conditions""" 
   41     if directory != 
"" and not os.path.exists(directory):
 
   43             os.makedirs(directory)
 
   46             if e.errno != errno.EEXIST:
 
   51     """Set a file mode according to the user's umask""" 
   53     umask = os.umask(0o077)
 
   57     os.chmod(filename, (~umask & 0o666))
 
   66     """Context manager to get a file that can be written only once and all other writes will succeed only if 
   67     they match the initial write. 
   69     The context manager provides a temporary file object. After the user is done, the temporary file becomes 
   70     the permanent file if the file at name does not already exist. If the file at name does exist the 
   71     temporary file is compared to the file at name. If they are the same then this is good and the temp file 
   72     is silently thrown away. If they are not the same then a runtime error is raised. 
   74     outDir, outName = os.path.split(name)
 
   76     temp = tempfile.NamedTemporaryFile(mode=
"w", dir=outDir, prefix=outName, delete=
False)
 
   84             os.symlink(temp.name, name)
 
   87             os.rename(temp.name, name)
 
   92             if e.errno != errno.EEXIST:
 
   94             filesMatch = filecmp.cmp(temp.name, name, shallow=
False)
 
  107     """Context manager to create a file in a manner avoiding race conditions 
  109     The context manager provides a temporary file object. After the user is done, 
  110     we move that file into the desired place and close the fd to avoid resource 
  113     outDir, outName = os.path.split(name)
 
  116     with tempfile.NamedTemporaryFile(mode=
"w", dir=outDir, prefix=outName, delete=
False) 
as temp:
 
  123                 os.rename(temp.name, name)
 
  129     """Context manager for creating a file in a manner avoiding race conditions 
  131     The context manager provides a temporary filename with no open file descriptors 
  132     (as this can cause trouble on some systems). After the user is done, we move the 
  133     file into the desired place. 
  135     outDir, outName = os.path.split(name)
 
  137     temp = tempfile.NamedTemporaryFile(mode=
"w", dir=outDir, prefix=outName, delete=
False)
 
  143         os.rename(tempName, name)
 
  149     """Context manager for reading a file that may be locked with an exclusive lock via 
  150     SafeLockedFileForWrite. This will first acquire a shared lock before returning the file. When the file is 
  151     closed the shared lock will be unlocked. 
  156         The file name to be opened, may include path. 
  161         The file to be read from. 
  163     log = Log.getLogger(
"daf.persistence.butler")
 
  165         with open(name, 
'r') 
as f:
 
  166             log.debug(
"Acquiring shared lock on {}".
format(name))
 
  167             fcntl.flock(f, fcntl.LOCK_SH)
 
  168             log.debug(
"Acquired shared lock on {}".
format(name))
 
  171         log.debug(
"Releasing shared lock on {}".
format(name))
 
  175     """File-like object that is used to create a file if needed, lock it with an exclusive lock, and contain 
  176     file descriptors to readable and writable versions of the file. 
  178     This will only open a file descriptor in 'write' mode if a write operation is performed. If no write 
  179     operation is performed, the existing file (if there is one) will not be overwritten. 
  181     Contains __enter__ and __exit__ functions so this can be used by a context manager. 
  184         self.
log = Log.getLogger(
"daf.persistence.butler")