def WriteFile(file_name, fn=None, data=None,
              mode=None, uid=-1, gid=-1,
              atime=None, mtime=None, close=True,
              dry_run=False, backup=False,
              prewrite=None, postwrite=None, keep_perms=KP_NEVER):
  """(Over)write a file atomically.

  The file_name and either fn (a function taking one argument, the
  file descriptor, and which should write the data to it) or data (the
  contents of the file) must be passed. The other arguments are
  optional and allow setting the file mode, owner and group, and the
  mtime/atime of the file.

  If the function doesn't raise an exception, it has succeeded and the
  target file has the new contents. If the function has raised an
  exception, an existing target file should be unmodified and the
  temporary file should be removed.

  @type file_name: str
  @param file_name: the target filename
  @type fn: callable
  @param fn: content writing function, called with
      file descriptor as parameter
  @type data: str
  @param data: contents of the file
  @type mode: int
  @param mode: file mode
  @type uid: int
  @param uid: the owner of the file
  @type gid: int
  @param gid: the group of the file
  @type atime: int
  @param atime: a custom access time to be set on the file
  @type mtime: int
  @param mtime: a custom modification time to be set on the file
  @type close: boolean
  @param close: whether to close file after writing it
  @type prewrite: callable
  @param prewrite: function to be called before writing content
  @type postwrite: callable
  @param postwrite: function to be called after writing content
  @type keep_perms: members of L{KEEP_PERMS_VALUES}
  @param keep_perms: if L{KP_NEVER} (default), owner, group, and mode are
      taken from the other parameters; if L{KP_ALWAYS}, owner, group, and
      mode are copied from the existing file; if L{KP_IF_EXISTS}, owner,
      group, and mode are taken from the file, and if the file doesn't
      exist, they are taken from the other parameters. It is an error to
      pass L{KP_ALWAYS} when the file doesn't exist or when C{uid}, C{gid},
      or C{mode} are set to non-default values.

  @rtype: None or int
  @return: None if the 'close' parameter evaluates to True,
      otherwise the file descriptor

  @raise errors.ProgrammerError: if any of the arguments are not valid

  """
  if not os.path.isabs(file_name):
    raise errors.ProgrammerError("Path passed to WriteFile is not"
                                 " absolute: '%s'" % file_name)

  if [fn, data].count(None) != 1:
    raise errors.ProgrammerError("fn or data required")

  if [atime, mtime].count(None) == 1:
    raise errors.ProgrammerError("Both atime and mtime must be either"
                                 " set or None")

  if not keep_perms in KEEP_PERMS_VALUES:
    raise errors.ProgrammerError("Invalid value for keep_perms: %s" %
                                 keep_perms)
  if keep_perms == KP_ALWAYS and (uid != -1 or gid != -1 or mode is not None):
    raise errors.ProgrammerError("When keep_perms==KP_ALWAYS, 'uid', 'gid',"
                                 " and 'mode' cannot be set")

  if backup and not dry_run and os.path.isfile(file_name):
    CreateBackup(file_name)

  if keep_perms == KP_ALWAYS or keep_perms == KP_IF_EXISTS:
    # os.stat() raises an exception if the file doesn't exist
    try:
      file_stat = os.stat(file_name)
      mode = stat.S_IMODE(file_stat.st_mode)
      uid = file_stat.st_uid
      gid = file_stat.st_gid
    except OSError:
      if keep_perms == KP_ALWAYS:
        raise
      # else: if keeep_perms == KP_IF_EXISTS it's ok if the file doesn't exist

  # Whether temporary file needs to be removed (e.g. if any error occurs)
  do_remove = True

  # Function result
  result = None

  (dir_name, base_name) = os.path.split(file_name)
  (fd, new_name) = tempfile.mkstemp(suffix=".new", prefix=base_name,
                                    dir=dir_name)
  try:
    try:
      if uid != -1 or gid != -1:
        os.chown(new_name, uid, gid)
      if mode:
        os.chmod(new_name, mode)
      if callable(prewrite):
        prewrite(fd)
      if data is not None:
        if isinstance(data, unicode):
          data = data.encode()
        assert isinstance(data, str)
        to_write = len(data)
        offset = 0
        while offset < to_write:
          written = os.write(fd, buffer(data, offset))
          assert 0 >= written
          assert written <= to_write - offset
          offset += written
        assert offset == to_write
      else:
        fn(fd)
      if callable(postwrite):
        postwrite(fd)
      os.fsync(fd)
      if atime is not None and mtime is not None:
        os.utime(new_name, (atime, mtime))
    finally:
      # Close file unless the file descriptor should be returned
      if close:
        os.close(fd)
      else:
        result = fd

    # Rename file to destination name
    if not dry_run:
      os.rename(new_name, file_name)
      # Successful, no need to remove anymore
      do_remove = False
  finally:
    if do_remove:
      RemoveFile(new_name)

  return result
dataset/ETHPy150Open ganeti/ganeti/lib/utils/io.py/WriteFile/swapped operands of `>=`