Package screenlets :: Module backend

[hide private]
[frames] | no frames]

# Source Code for Module screenlets.backend

      1  # This application is released under the GNU General Public License
      2  # v3 (or, at your option, any later version). You can find the full
      3  # text of the license under http://www.gnu.org/licenses/gpl.txt.
      4  # By using, editing and/or distributing this software you agree to
      5  # the terms and conditions of this license.
      6  # Thank you for using free software!
      7  #
      8  # screenlets.backend (c) RYX (aka Rico Pfaus) 2007 <ryx@ryxperience.com>
      9  #
     10  # INFO:
     11  # - The backend offers an abstracted way of saving a Screenlet's data
     12  #
     13  # TODO:
     14  # - add "type"-argument to save_option and read_option to be able to correctly
     15  #   set the values in GconfBackend (instead of storing only strings).
     16  #
     17
     18  import glob
     19  import os
     20  import gobject
     21  import gettext
     22
     23  gettext.textdomain('screenlets')
     24  gettext.bindtextdomain('screenlets', '/usr/share/locale')
     25
     26 -def _(s):
     27          return gettext.gettext(s)
     28
     29
     30  try:
     31          import gconf
     32  except:
     33          print _("GConf python module not found. GConf settings backend is disabled.")
     34
     35
     36 -class ScreenletsBackend:
     37          """The backend performs the loading/saving of the 'key=value'-strings.
     38          Extend this superclass to implement different saving-backends."""
     39
     40 -        def __init__ (self):
     41                  pass
     42
     43 -        def delete_instance (self, id):
     44                  """Delete an instance's configuration by its id."""
     45                  pass
     46
     47 -        def flush (self):
     48                  """Immediately store all values to disk (in case the backend doesn't
     49                  save in realtime anyway."""
     50                  pass
     51
     52 -        def load_option (self, id, name):
     53                  """Load one option for the instance with the given id."""
     54                  pass
     55
     56 -        def load_instance (self, id):
     57                  """Load all options for the instance with the given id."""
     58                  pass
     59
     60 -        def save_option (self, id, name, value):
     61                  """Save one option for the instance with the given id."""
     62                  pass
     63
     64
     65 -class GconfBackend (ScreenletsBackend):
     66          """Backend for storing settings in the GConf registry"""
     67
     68          gconf_dir = '/apps/screenlets/'
     69
     70 -        def __init__ (self):
     71                  ScreenletsBackend.__init__(self)
     72                  print _('GConfBackend: initializing')
     73                  self.client = gconf.client_get_default()
     74
     75 -        def delete_instance (self, id):
     76                  """Delete an instance's configuration by its id."""
     77                  os.system('gconftool-2 --recursive-unset ' + self.key + id)
     78                  return True
     79
     80 -        def flush (self):
     81                  """Immediately store all values to disk (in case the backend doesn't
     82                  save in realtime anyway."""
     83                  pass    #No need, GConf saves in realtime
     84
     85 -        def load_option (self, id, name):
     86                  """Load one option for the instance with the given id."""
     87                  return self.client.get_string(self.gconf_dir + id + '/' + name)
     88
     89 -        def load_instance (self, id):
     90                  """Load all options for the instance with the given id."""
     91                  keys = []
     92                  vals = []
     93                  for i in self.client.all_entries(self.gconf_dir + id):
     94                          keys.append(i.key.split('/')[4])
     95                          vals.append(self.client.get_string(i.key))
     96                  return dict(zip(keys, vals))
     97                  return None
     98
     99 -        def save_option (self, id, name, value):
    100                  """Save one option for the instance with the given id."""
    101                  self.client.set_string(self.gconf_dir + id + '/' + name, value)
    102                  print _('Saved option %s%s/%s = %s') % (self.gconf_dir, id, name, value)
    103
    104
    105 -class CachingBackend (ScreenletsBackend):
    106          """A backend that stores the settings in arrays and saves after a short
    107          interval to avoid overhead when multiple values are set within a short time.
    108          The data gets saved into $HOME/.config/Screenlets/<Screenletname>/, in a
    109          file for each element (named like its id with the extension '.ini')."""
    110
    111          # internals
    112          __instances = {}                # a dict with (id:dict)-entries cntaining the data
    113          __delay_time = 3000             # delay to wait before performing save
    114          __timeout = None                # the id of the timeout-function
    115          __queue = []                    # list with ids of instances that need saving
    116
    117          # attribs
    118          path = ''                               # the path to store the files
    119
    120          # Constructor
    121 -        def __init__ (self, path):
    122                  ScreenletsBackend.__init__(self)
    123                  self.path = path
    124                  self.__load_cache()
    125
    126 -        def delete_instance (self, id):
    127                  """Delete an instance from the list and from the filesystem."""
    128                  if self.__instances.has_key(id):
    129                          del self.__instances[id]
    130                          try:
    131                                  import os
    132                                  os.remove(self.path + id + '.ini')
    133                          except Exception,ex:
    134                                  print ex
    135                                  print _("Temporary file didn't exist - nothing to remove.")
    136                                  return False
    137                  print _("CachingBackend: <#%s> removed!") % id
    138                  return True
    139
    140 -        def flush (self):
    141                  """Immediately save all pending data."""
    142                  self.__save_cache()
    143
    144 -        def save_option (self, id, name, value):
    145                  """Save option for an instance to cache and start saving-timeout
    146                  for that element (value must be of type string)."""
    147                  # create key for option, if not existent yet
    148                  if self.__instances.has_key(id) == False:
    149                          self.__instances[id] = {}
    150                  # set option in array
    151                  self.__instances[id][name] = str(value)
    152                  #print "CachingBackend.save_option: "+name+"="+self.__instances[id][name]
    153                  # if id is not already in queue, add the id to the queue
    154                  if self.__queue.count(id) == 0:
    155                          self.__queue.append(id)
    156                  # reset timeout and start new
    157                  if self.__timeout:
    158                          gobject.source_remove(self.__timeout)
    159                  self.__timeout = gobject.timeout_add(self.__delay_time,
    160                          self.__save_cache)#, id)
    161
    162 -        def load_option (self, id, name):
    163                  """TODO: Load option from the backend (returned as str)."""
    164                  return self.__instances[id][name]
    165
    166 -        def load_instance (self, id):
    167                  """Load all options for the instance with the given id."""
    168                  #print "Load element: "+id
    169                  if self.__instances.has_key(id):
    170                          return self.__instances[id]
    171                  return None
    172
    173 -        def __load_cache (self):
    174                  """Load all cached files from path."""
    175                  # perform saving
    176                  print _("CachingBackend: Loading instances from cache")
    177                  # get dir content of self.path
    178                  dirname = self.path
    179                  dirlst = glob.glob(dirname + '*')
    180                  tdlen = len(dirname)
    181                  lst = []
    182                  for fname in dirlst:
    183                          dname = fname[tdlen:]
    184                          if dname.endswith('.ini'):
    185                                  id = dname[:-4]
    186                                  print _("CachingBackend: Loading <%s>") % id
    187                                  #print "ID: "+id
    188                                  if self.__instances.has_key(id) == False:
    189                                          self.__instances[id] = {}
    190                                  # open file
    191                                  try:
    192                                          f = open(fname, 'r')
    193                                          lines = f.readlines()
    194                                          # read all options for this element from file
    195                                          for line in lines:
    196                                                  #print "LOAD: "+line[:-1]
    197                                                  parts = line[:-1].split('=', 1)
    198                                                  if len(parts) > 1:
    199                                                          self.__instances[id][parts[0]] = parts[1]
    200                                          f.close()
    201                                  except Exception, ex:
    202                                          print _("Error while loading options: %s") % str(ex)
    203
    204 -        def __save_cache (self):
    205                  """Save the cache (for all pending instances in queue) to self.path."""
    206                  # loop through all instances in queue:
    207                  for id in self.__queue:
    208                          # if element with id not exists, remove it and break
    209                          if self.__instances.has_key(id) == False:
    210                                  print _("Queue-element <%s> not found (already removed?)!") % id
    211                                  self.__queue.remove(id)
    212                                  break
    213                          # create list with options
    214                          #print _("CachingBackend: Saving <#%s> :) ...") % id
    215                          lst = []
    216                          for oname in self.__instances[id]:
    217                                  lst.append([oname, self.__instances[id][oname]])
    218                          # and save them (if any)
    219                          if len(lst) > 0:
    220                                  backup = ''
    221                                  try:
    222                                          backup = open(self.path + id + '.ini', 'r')
    223                                          backup.close()
    224                                  except:pass
    225                                  try:
    226                                          # In here something strage appends , sometimes it opens the file , then it cant write to it  so it writes and empty file reseting all settings
    227
    228                                          f = open(self.path + id + '.ini', 'w')
    229                                          for el in lst:
    230                                                  f.write(el[0] + '=' + el[1] + "\n")
    231                                          f.close()
    232                                          print "OK"
    233                                  except:
    234                                          if backup != '' and os.path.exists(self.path + id + '.ini'):
    235                                                  try:
    236                                                          backup_restore = open(self.path + id + '.ini', 'w')
    237                                                          backup_restore.write(backup)
    238                                                          backup_restore.close()
    239                                                  except:pass
    240                                          print _("error while saving config: %s %s") % ( oname , self.path)
    241                  # clear queue
    242                  self.__queue = []
    243                  # NOT continue the timeout-function (!!!!!)
    244                  return False
    245