Package x2go :: Module inifiles

[frames] | no frames]

# Source Code for Module x2go.inifiles

      1  # -*- coding: utf-8 -*-
      2
      3  # Copyright (C) 2010-2016 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
     56 -    def __init__(self, config_files, defaults=None, logger=None, loglevel=log.loglevel_DEFAULT):
     57          """\
     58          @param config_files: a list of configuration file names (e.g. a global filename and a user's home
     59              directory filename)
     60          @type config_files: C{list}
     61          @param defaults: a cascaded Python dicitionary structure with ini file defaults (to override
     62              Python X2Go's hard coded defaults in L{defaults}
     63          @type defaults: C{dict}
     64          @param logger: you can pass an L{X2GoLogger} object to the
     65              L{X2GoIniFile} constructor
     66          @type logger: L{X2GoLogger} instance
     67          @param loglevel: if no L{X2GoLogger} object has been supplied a new one will be
     68              constructed with the given loglevel
     69          @type loglevel: C{int}
     70
     71          """
     72          self.user_config_file = None
     73          self._write_user_config = True
     74
     75          # make sure a None type gets turned into list type
     76          if not config_files:
     77              config_files = []
     78
     79          if logger is None:
     80              self.logger = log.X2GoLogger(loglevel=loglevel)
     81          else:
     82              self.logger = copy.deepcopy(logger)
     83          self.logger.tag = __NAME__
     84
     85          self.config_files = config_files
     86
     87          if utils._checkIniFileDefaults(defaults):
     88              self.defaultValues = defaults
     89          else:
     90              self.defaultValues = {}
     91
     92          # we purposefully do not inherit the SafeConfigParser class
     93          # here as we do not want to run into name conflicts between
     94          # X2Go ini file options and method / property names in
     95          # SafeConfigParser... This is a pre-cautious approach...
     96          self.iniConfig = ConfigParser.SafeConfigParser()
     97          self.iniConfig.optionxform = str
     98
     99          _create_file = False
    100          for file_name in self.config_files:
    101              file_name = os.path.normpath(file_name)
    102              if file_name.startswith(_current_home):
    103                  if not os.path.exists(file_name):
    104                      utils.touch_file(file_name)
    105                      _create_file = True
    106                  self.user_config_file = file_name
    107                  break
    108          self.load()
    109
    110          if _create_file:
    111              self._write_user_config = True
    112              self._X2GoIniFile__write()
    113
    114 -    def load(self):
    115          """\
    116          R(e-r)ead configuration file(s).
    117
    118          """
    119          self.logger('proposed config files are %s' % self.config_files, loglevel=log.loglevel_INFO, )
    120          _found_config_files = self.iniConfig.read(self.config_files)
    121          self.logger('config files found: %s' % _found_config_files or 'none', loglevel=log.loglevel_INFO, )
    122
    123          for file_name in _found_config_files:
    124              if file_name.startswith(os.path.normpath(_current_home)):
    125                  # we will use the first file found in the user's home dir for writing modifications
    126                  self.user_config_file = file_name
    127                  break
    128
    129          self.config_files = _found_config_files
    130          self._fill_defaults()
    131
    132 -    def __repr__(self):
    133          result = 'X2GoIniFile('
    134          for p in dir(self):
    135              if '__' in p or not p in self.__dict__ or type(p) is types.InstanceType: continue
    136              result += p + '=' + str(self.__dict__[p]) + ','
    137          result = result.strip(',')
    138          return result + ')'
    139
    140 -    def _storeValue(self, section, key, value):
    141          """\
    142          Stores a value for a given section and key.
    143
    144          This methods affects a SafeConfigParser object held in
    145          RAM. No configuration file is affected by this
    146          method. To write the configuration to disk use
    147          the L{write()} method.
    148
    149          @param section: the ini file section
    150          @type section: C{str}
    151          @param key: the ini file key in the given section
    152          @type key: C{str}
    153          @param value: the value for the given section and key
    154          @type value: C{str}, C{list}, C{booAl}, ...
    155
    156          """
    157          if type(value) == type(u''):
    158              value = value.encode(utils.get_encoding())
    159          if type(value) is types.BooleanType:
    160              self.iniConfig.set(section, key, str(int(value)))
    161          elif type(value) in (types.ListType, types.TupleType):
    162              self.iniConfig.set(section, key, ", ".join(value))
    163          else:
    164              self.iniConfig.set(section, key, str(value))
    165
    166 -    def _fill_defaults(self):
    167          """\
    168          Fills a C{SafeConfigParser} object with the default ini file
    169          values as pre-defined in Python X2Go or. This SafeConfigParser
    170          object is held in RAM. No configuration file is affected by this
    171          method.
    172
    173          """
    174          for section, sectionvalue in self.defaultValues.items():
    175              for key, value in sectionvalue.items():
    176                  if self.iniConfig.has_option(section, key): continue
    177                  if not self.iniConfig.has_section(section):
    178                      self.iniConfig.add_section(section)
    179                  self._storeValue(section, key, value)
    180
    181 -    def update_value(self, section, key, value):
    182          """\
    183          Change a value for a given section and key. This method
    184          does not have any effect on configuration files.
    185
    186          @param section: the ini file section
    187          @type section: C{str}
    188          @param key: the ini file key in the given section
    189          @type key: C{str}
    190          @param value: the value for the given section and key
    191          @type value: C{str}, C{list}, C{bool}, ...
    192
    193          """
    194          if not self.iniConfig.has_section(section):
    195              self.iniConfig.add_section(section)
    196          self._storeValue(section, key, value)
    197          self._write_user_config = True
    198      __update_value = update_value
    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 written, 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      __write = write
    222
    223 -    def get_type(self, section, key):
    224          """\
    225          Retrieve a value type for a given section and key. The returned
    226          value type is based on the default values dictionary.
    227
    228          @param section: the ini file section
    229          @type section: C{str}
    230          @param key: the ini file key in the given section
    231          @type key: C{str}
    232
    233          @return: a Python variable type
    234          @rtype: class
    235
    236          """
    237          return type(self.defaultValues[section][key])
    238
    239 -    def get_value(self, section, key, key_type=None):
    240          """\
    241          Retrieve a value for a given section and key.
    242
    243          @param section: the ini file section
    244          @type section: C{str}
    245          @param key: the ini file key in the given section
    246          @type key: C{str}
    247
    248          @return: the value for the given section and key
    249          @rtype: class
    250
    251          """
    252          if key_type is None:
    253              key_type = self.get_type(section, key)
    254          if self.iniConfig.has_option(section, key):
    255              if key_type is types.BooleanType:
    256                  return self.iniConfig.getboolean(section, key)
    257              elif key_type is types.IntType:
    258                  return self.iniConfig.getint(section, key)
    259              elif key_type is types.ListType:
    260                  _val = self.iniConfig.get(section, key)
    261                  _val = _val.strip()
    262                  if _val.startswith('[') and _val.endswith(']'):
    263                      return eval(_val)
    264                  elif ',' in _val:
    265                      _val = [ v.strip() for v in _val.split(',') ]
    266                  else:
    267                      _val = [ _val ]
    268                  return _val
    269              else:
    270                  _val = self.iniConfig.get(section, key)
    271                  return _val.decode(utils.get_encoding())
    272      get = get_value
    273      __call__ = get_value
    274
    275      @property
    276 -    def printable_config_file(self):
    277          """\
    278          Returns a printable configuration file as a multi-line string.
    279
    280          """
    281          stdout = cStringIO.StringIO()
    282          self.iniConfig.write(stdout)
    283          _ret_val = stdout.getvalue()
    284          stdout.close()
    285          return _ret_val
    286