Package Gnumed :: Package timelinelib :: Package db :: Module utils |
[frames] | no frames]

# Source Code for Module Gnumed.timelinelib.db.utils

     1  # Copyright (C) 2009, 2010, 2011  Rickard Lindberg, Roger Lindberg
     2  #
     3  # This file is part of Timeline.
     4  #
     5  # Timeline is free software: you can redistribute it and/or modify
     6  # it under the terms of the GNU General Public License as published by
     7  # the Free Software Foundation, either version 3 of the License, or
     8  # (at your option) any later version.
     9  #
    10  # Timeline is distributed in the hope that it will be useful,
    11  # but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  # GNU General Public License for more details.
    14  #
    15  # You should have received a copy of the GNU General Public License
    16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>.
    17
    18
    19  import codecs
    20  import os
    21  import os.path
    22
    23  from timelinelib.db.exceptions import TimelineIOError
    24
    25
    26 -class IdCounter(object):
    27
    28 -    def __init__(self, initial_id=0):
    29          self.id = initial_id
    30
    31 -    def get_next(self):
    32          self.id += 1
    33          return self.id
    34
    35
    36 -def safe_write(path, encoding, write_fn):
    37      """
    38      Write to path in such a way that the contents of path is only modified
    39      correctly or not modified at all.
    40
    41      In some extremely rare cases the contents of path might be incorrect, but
    42      in those cases the correct content is always present in another file.
    43      """
    44      def raise_error(specific_msg, cause_exception):
    45          err_general = _("Unable to save timeline data to '%s'. File left unmodified.") % path
    46          err_template = "%s\n\n%%s\n\n%%s" % err_general
    47          raise TimelineIOError(err_template % (specific_msg, cause_exception))
    48      tmp_path = _create_non_exising_path(path, "tmp")
    49      backup_path = _create_non_exising_path(path, "bak")
    50      # Write data to tmp file
    51      try:
    52          if encoding is None:
    53              file = open(tmp_path, "wb")
    54          else:
    55              file = codecs.open(tmp_path, "w", encoding)
    56          try:
    57              try:
    58                  write_fn(file)
    59              except Exception, e:
    60                  raise_error(_("Unable to write timeline data."), e)
    61          finally:
    62              file.close()
    63      except IOError, e:
    64          raise_error(_("Unable to write to temporary file '%s'.") % tmp_path, e)
    65      # Copy original to backup (if original exists)
    66      if os.path.exists(path):
    67          try:
    68              os.rename(path, backup_path)
    69          except Exception, e: # Can this only be a OSError?
    70              raise_error(_("Unable to take backup to '%s'.") % backup_path, e)
    71      # Copy tmp to original
    72      try:
    73          os.rename(tmp_path, path)
    74      except Exception, e: # Can this only be a OSError?
    75          raise_error(_("Unable to rename temporary file '%s' to original.") % tmp_path, e)
    76      # Delete backup (if backup was created)
    77      if os.path.exists(backup_path):
    78          try:
    79              os.remove(backup_path)
    80          except Exception, e: # Can this only be a OSError?
    81              raise_error(_("Unable to delete backup file '%s'.") % backup_path, e)
    82
    83
    84 -def _create_non_exising_path(base, suffix):
    85      i = 1
    86      while True:
    87          new_path = "%s.%s%i" % (base, suffix, i)
    88          if os.path.exists(new_path):
    89              i += 1
    90          else:
    91              return new_path
    92