Package x2go :: Module inifiles

[frames] | no frames]

# Source Code for Module x2go.inifiles

      1  # -*- coding: utf-8 -*-
      2
      3  # Copyright (C) 2010-2013 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
      4  #
      5  # Python X2Go is free software; you can redistribute it and/or modify
      6  # it under the terms of the GNU Affero 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  # Python X2Go 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 Affero General Public License for more details.
     14  #
     15  # You should have received a copy of the GNU Affero General Public License
     16  # along with this program; if not, write to the
     17  # Free Software Foundation, Inc.,
     18  # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
     19  #
     20  # This code was initially written by:
     21  #       2010 Dick Kniep <dick.kniep@lindix.nl>
     22  #
     23  # Other contributors:
     24  #       none so far
     25
     26  """\
     27  X2GoProcessIniFile - helper class for parsing .ini files
     28
     29  """
     30  __NAME__ = 'x2goinifiles-pylib'
     31
     32  # modules
     33  import os
     34  import ConfigParser
     35  import types
     36  import cStringIO
     37  import copy
     38
     39  # Python X2Go modules
     40  from defaults import LOCAL_HOME as _current_home
     41  import log
     42  import utils
     43
     44 -class X2GoIniFile(object):
     45      """
     46      Base class for processing the different ini files used by X2Go
     47      clients. Primarily used to standardize the content of the different
     48      X2Go client ini file (settings, printing, sessions, xconfig).
     49
     50      If entries are omitted in an ini file, they are filled with
     51      default values (as hard coded in Python X2Go), so the resulting objects
     52      always contain the same fields.
     53
     54      """
     55      defaultValues = {
     56          'none': {
     57              'none': 'empty',
     58              },
     59          }
     60      write_user_config = False
     61      user_config_file = None
     62
     63 -    def __init__(self, config_files, defaults=None, logger=None, loglevel=log.loglevel_DEFAULT):
     64          """\
     65          @param config_files: a list of configuration file names (e.g. a global filename and a user's home
     66              directory filename)
     67          @type config_files: C{list}
     68          @param defaults: a cascaded Python dicitionary structure with ini file defaults (to override
     69              Python X2Go's hard coded defaults in L{defaults}
     70          @type defaults: C{dict}
     71          @param logger: you can pass an L{X2GoLogger} object to the
     72              L{X2GoIniFile} constructor
     73          @type logger: L{X2GoLogger} instance
     74          @param loglevel: if no L{X2GoLogger} object has been supplied a new one will be
     75              constructed with the given loglevel
     76          @type loglevel: C{int}
     77
     78          """
     79          # make sure a None type gets turned into list type
     80          if not config_files:
     81              config_files = []
     82
     83          if logger is None:
     84              self.logger = log.X2GoLogger(loglevel=loglevel)
     85          else:
     86              self.logger = copy.deepcopy(logger)
     87          self.logger.tag = __NAME__
     88
     89          self.config_files = config_files
     90
     91          if utils._checkIniFileDefaults(defaults):
     92              self.defaultValues = defaults
     93
     94          # we purposefully do not inherit the SafeConfigParser class
     95          # here as we do not want to run into name conflicts between
     96          # X2Go ini file options and method / property names in
     97          # SafeConfigParser... This is a pre-cautious approach...
     98          self.iniConfig = ConfigParser.SafeConfigParser(self.defaultValues)
     99          self.iniConfig.optionxform = str
    100
    101          _create_file = False
    102          for file_name in self.config_files:
    103              if file_name.startswith(_current_home):
    104                  if not os.path.exists(file_name):
    105                      utils.touch_file(file_name)
    106                      _create_file = True
    107                  break
    108
    109          self.load()
    110
    111          if _create_file:
    112              self.write_user_config = True
    113              self.write()
    114
    115 -    def load(self):
    116          """\
    117          R(e-r)ead configuration file(s).
    118
    119          """
    120          self.logger('proposed config files are %s' % self.config_files, loglevel=log.loglevel_INFO, )
    121          _found_config_files = self.iniConfig.read(self.config_files)
    122          self.logger('config files found: %s' % _found_config_files or 'none', loglevel=log.loglevel_INFO, )
    123
    124          for file_name in _found_config_files:
    125              if file_name.startswith(os.path.normpath(_current_home)):
    126                  # we will use the first file found in the user's home dir for writing modifications
    127                  self.user_config_file = file_name
    128                  break
    129
    130          self.config_files = _found_config_files
    131          self._fill_defaults()
    132
    133 -    def __repr__(self):
    134          result = 'X2GoIniFile('
    135          for p in dir(self):
    136              if '__' in p or not p in self.__dict__ or type(p) is types.InstanceType: continue
    137              result += p + '=' + str(self.__dict__[p]) + ','
    138          result = result.strip(',')
    139          return result + ')'
    140
    141 -    def _storeValue(self, section, key, value):
    142          """\
    143          Stores a value for a given section and key.
    144
    145          This methods affects a SafeConfigParser object held in
    146          RAM. No configuration file is affected by this
    147          method. To write the configuration to disk use
    148          the L{write()} method.
    149
    150          @param section: the ini file section
    151          @type section: C{str}
    152          @param key: the ini file key in the given section
    153          @type key: C{str}
    154          @param value: the value for the given section and key
    155          @type value: C{str}, C{list}, C{booAl}, ...
    156
    157          """
    158          if type(value) == type(u''):
    159              value = value.encode(utils.get_encoding())
    160          if type(value) is types.BooleanType:
    161              self.iniConfig.set(section, key, str(int(value)))
    162          elif type(value) in (types.ListType, types.TupleType):
    163              self.iniConfig.set(section, key, ", ".join(value))
    164          else:
    165              self.iniConfig.set(section, key, str(value))
    166
    167 -    def _fill_defaults(self):
    168          """\
    169          Fills a C{SafeConfigParser} object with the default ini file
    170          values as pre-defined in Python X2Go or. This SafeConfigParser
    171          object is held in RAM. No configuration file is affected by this
    172          method.
    173
    174          """
    175          for section, sectionvalue in self.defaultValues.items():
    176              for key, value in sectionvalue.items():
    177                  if self.iniConfig.has_option(section, key): continue
    178                  if not self.iniConfig.has_section(section):
    179                      self.iniConfig.add_section(section)
    180                  self._storeValue(section, key, value)
    181
    182 -    def update_value(self, section, key, value):
    183          """\
    184          Change a value for a given section and key. This method
    185          does not have any effect on configuration files.
    186
    187          @param section: the ini file section
    188          @type section: C{str}
    189          @param key: the ini file key in the given section
    190          @type key: C{str}
    191          @param value: the value for the given section and key
    192          @type value: C{str}, C{list}, C{bool}, ...
    193
    194          """
    195          if not self.iniConfig.has_section(section):
    196              self.iniConfig.add_section(section)
    197          self._storeValue(section, key, value)
    198          self.write_user_config = True
    199
    200 -    def write(self):
    201          """\
    202          Write the ini file modifications (SafeConfigParser object) from RAM to disk.
    203
    204          For writing the first of the C{config_files} specified on instance construction
    205          that is writable will be used.
    206
    207          @return: C{True} if the user config file has been successfully writte, C{False} otherwise.
    208          @rtype: C{bool}
    209
    210          """
    211          if self.user_config_file and self.write_user_config:
    212              try:
    213                  fd = open(self.user_config_file, 'wb')
    214                  self.iniConfig.write(fd)
    215                  fd.close()
    216                  self.write_user_config = False
    217                  return True
    218              except Exception, e:
    219                  print e
    220          return False
    221
    222 -    def get_type(self, section, key):
    223          """\
    224          Retrieve a value type for a given section and key. The returned
    225          value type is based on the default values dictionary.
    226
    227          @param section: the ini file section
    228          @type section: C{str}
    229          @param key: the ini file key in the given section
    230          @type key: C{str}
    231
    232          @return: a Python variable type
    233          @rtype: class
    234
    235          """
    236          return type(self.defaultValues[section][key])
    237
    238 -    def get_value(self, section, key, key_type=None):
    239          """\
    240          Retrieve a value for a given section and key.
    241
    242          @param section: the ini file section
    243          @type section: C{str}
    244          @param key: the ini file key in the given section
    245          @type key: C{str}
    246
    247          @return: the value for the given section and key
    248          @rtype: class
    249
    250          """
    251          if key_type is None:
    252              key_type = self.get_type(section, key)
    253          if self.iniConfig.has_option(section, key):
    254              if key_type is types.BooleanType:
    255                  return self.iniConfig.getboolean(section, key)
    256              elif key_type is types.IntType:
    257                  return self.iniConfig.getint(section, key)
    258              elif key_type is types.ListType:
    259                  _val = self.iniConfig.get(section, key)
    260                  _val = _val.strip()
    261                  if _val.startswith('[') and _val.endswith(']'):
    262                      return eval(_val)
    263                  elif ',' in _val:
    264                      _val = [ v.strip() for v in _val.split(',') ]
    265                  else:
    266                      _val = [ _val ]
    267                  return _val
    268              else:
    269                  _val = self.iniConfig.get(section, key)
    270                  return _val.decode(utils.get_encoding())
    271      get = get_value
    272      __call__ = get_value
    273
    274      @property
    275 -    def printable_config_file(self):
    276          """\
    277          Returns a printable configuration file as a multi-line string.
    278
    279          """
    280          stdout = cStringIO.StringIO()
    281          self.iniConfig.write(stdout)
    282          _ret_val = stdout.getvalue()
    283          stdout.close()
    284          return _ret_val
    285