text: #!/usr/bin/env python3
  # -*- coding: utf-8 -*-
  
  """
  Configuration module for slack-backup
  """
  import json
  import os
  import configparser
  
  
  class Config(object):
      """Configuration keeper"""
  
      ints = ['verbose', 'quiet']
      bools = ['url_file_to_attachment']
  
      sections = {'common': ['channels', 'database', 'quiet', 'verbose'],
                  'fetch': ['user', 'password', 'team', 'token',
                            'url_file_to_attachment', 'raw_dir'],
                  'generate': ['output', 'format', 'theme']}
  
      def __init__(self):
          """
          Init. Read config, if exists, and update passed argument parser
          object.
          """
  
          self.cp = configparser.ConfigParser()
          self._options = {'channels': [],
                           'database': None,
                           'quiet': 0,
                           'verbose': 0,
                           'user': None,
                           'password': None,
                           'team': None,
                           'token': None,
                           'output': None,
                           'format': None,
                           'theme': None,
                           'url_file_to_attachment': False,
                           'raw_dir': None}
          # This message supposed to be displayed in INFO level. During the time
          # of running the code where it should be displayed there is no
          # complete information about logging level. Displaying message is
          # dependent on the a) config file, b) argument from commandline. Let's
          # resolve if user want to have that information or not after merging
          # those two sources. If user do not want to see any message in INFO
          # level, we shouldn't do so.
          self.msg = ''
  
      def update(self, args):
          self.load_config(args)
          self.parse_loaded_options()
          self.update_args(args)
          return self.msg
  
      def load_config(self, args):
  
          path = ''
          if hasattr(args, 'config') and args.config:
              path = args.config
  
          locations = [path,
                       './slack-backup.ini',
                       os.path.expandvars('$XDG_CONFIG_HOME/slack-backup.ini'),
                       os.path.expandvars('$HOME/.config/slack-backup.ini')]
  
          for location in locations:
              if os.path.exists(location):
                  self.cp.read(location)
                  self.msg = 'Found configuration file: %s' % location
                  break
          else:
              self.msg = 'No configuration file found'
  
      def parse_loaded_options(self):
  
          for section in self.cp.sections():
              if section not in self.sections:
                  continue
  
              for option in self.sections[section]:
                  if option in self.ints:
                      val = self.cp.getint(section, option, fallback=0)
                  elif option in self.bools:
                      val = self.cp.getboolean(section, option, fallback=False)
                  elif option == 'channels':
                      val = self.cp.get(section, option, fallback='[]')
                      val = json.loads(val)
                  else:
                      val = self.cp.get(section, option, fallback=None)
  
                  self._options[option] = val
  
      def update_args(self, args):
          if 'parser' not in args:
              # it doesn't make sense to update args, since no action was
              # choosen
              return
  
          # special case, re-set information for verbose/quiet options
          if 'verbose' in args and args.verbose is not None:
              self._options['verbose'] = args.verbose
              if self._options['quiet'] is not None:
                  self._options['quiet'] = 0
          if 'quiet' in args and args.quiet is not None:
              self._options['quiet'] = args.quiet
              if self._options['verbose'] is not None:
                  self._options['verbose'] = 0
  
          for sec_id in (args.parser, 'common'):
              for option in self.sections[sec_id]:
                  if option in args:
                      if getattr(args, option) is not None:
                          continue
  
                  setattr(args, option, self._options[option])
  