text: import configparser
  import os
  import ast
  
  
  class Config(object):
      """
          The settings can be changed by setting up a config file. For an example of a config file, see
           config.cfg in the main-directory. 
      """
  
      def __init__(self):
          """
              Sets the default values for the project
          """
          self.version = '1.0'
          self.link = 'dashboard'
          self.database_name = 'sqlite:///flask_monitoringdashboard.db'
          self.test_dir = None
          self.username = 'admin'
          self.password = 'admin'
          self.guest_username = 'guest'
          self.guest_password = ['guest_password']
          self.outlier_detection_constant = 2.5
          self.colors = {}
          self.security_token = 'cc83733cb0af8b884ff6577086b87909'
          self.outliers_enabled = True
  
          # define a custom function to retrieve the session_id or username
          self.get_group_by = None
  
      def init_from(self, file=None, envvar=None):
          """
              The config_file must at least contains the following variables in section 'dashboard':
              APP_VERSION: the version of the app that you use. Updating the version helps in 
                  showing differences in execution times of a function over a period of time.
              CUSTOM_LINK: The dashboard can be visited at localhost:5000/{{CUSTOM_LINK}}.
              DATABASE: Suppose you have multiple projects where you're working on and want to 
                  separate the results. Then you can specify different database_names, such that the 
                  result of each project is stored in its own database.
              
              Since updating the version in the config-file when updating code isn't very useful, it
              is a better idea to provide the location of the git-folder. From the git-folder. The 
              version automatically retrieved by reading the commit-id (hashed value):
              GIT = If you're using git, then it is easier to set the location to the .git-folder, 
                  The location is relative to the config-file.
  
              USERNAME: for logging into the dashboard, a username and password is required. The
                  username can be set using this variable.
              PASSWORD: same as for the username, but this is the password variable.
              GUEST_USERNAME: A guest can only see the results, but cannot configure/download data.
              GUEST_PASSWORD: A guest can only see the results, but cannot configure/download data.
  
              OUTLIER_DETECTION_CONSTANT: When the execution time is more than this constant *
                  average, extra information is logged into the database. A default value for this
                  variable is 2.5, but can be changed in the config-file.
  
              SECURITY_TOKEN: Used for getting the data in /get_json_data/<security_token>
  
              OUTLIERS_ENABLED: Whether you want the Dashboard to collect extra information about outliers.
  
              :param file: a string pointing to the location of the config-file
              :param envvar: a string specifying which environment variable holds the config file location
          """
  
          if envvar:
              file = os.getenv(envvar)
          if not file:
              print("No configuration file specified. Please do so.")
              return
  
          # When collecting unit test performance results, create log file
          log_dir = os.getenv('DASHBOARD_LOG_DIR')
          if log_dir:
              log = open(log_dir + "endpoint_hits.log", "w")
              log.write("\"time\",\"endpoint\"\n")
              log.close()
  
          parser = configparser.RawConfigParser()
          try:
              parser.read(file)
              if parser.has_option('dashboard', 'APP_VERSION'):
                  self.version = parser.get('dashboard', 'APP_VERSION')
              if parser.has_option('dashboard', 'CUSTOM_LINK'):
                  self.link = parser.get('dashboard', 'CUSTOM_LINK')
              if parser.has_option('dashboard', 'DATABASE'):
                  self.database_name = parser.get('dashboard', 'DATABASE')
              if parser.has_option('dashboard', 'TEST_DIR'):
                  self.test_dir = parser.get('dashboard', 'TEST_DIR')
              if parser.has_option('dashboard', 'OUTLIERS_ENABLED'):
                  self.outliers_enabled = parser.get('dashboard', 'OUTLIERS_ENABLED') == "True"
  
              # For manually defining colors of specific endpoints
              if parser.has_option('dashboard', 'COLORS'):
                  self.colors = ast.literal_eval(parser.get('dashboard', 'COLORS'))
  
              # When the option git is selected, it overrides the given version
              if parser.has_option('dashboard', 'GIT'):
                  git = parser.get('dashboard', 'GIT')
                  try:
                      # current hash can be found in the link in HEAD-file in git-folder
                      # The file is specified by: 'ref: <location>'
                      git_file = (open(os.path.join(git, 'HEAD')).read().rsplit(': ', 1)[1]).rstrip()
                      # read the git-version
                      self.version = open(git + '/' + git_file).read()
                      # cut version to at most 6 chars
                      self.version = self.version[:6]
                  except IOError:
                      print("Error reading one of the files to retrieve the current git-version.")
                      raise
  
              # provide username and/or password ..
              # .. for admin
              if parser.has_option('dashboard', 'USERNAME'):
                  self.username = parser.get('dashboard', 'USERNAME')
              if parser.has_option('dashboard', 'PASSWORD'):
                  self.password = parser.get('dashboard', 'PASSWORD')
              # .. for guest (a guest can only see the results, but cannot configure or download any data)
              if parser.has_option('dashboard', 'GUEST_USERNAME'):
                  self.guest_username = parser.get('dashboard', 'GUEST_USERNAME')
              if parser.has_option('dashboard', 'GUEST_PASSWORD'):
                  self.guest_password = ast.literal_eval(parser.get('dashboard', 'GUEST_PASSWORD'))
  
              # when an outlier detection constant has been set up:
              if parser.has_option('dashboard', 'OUTLIER_DETECTION_CONSTANT'):
                  self.outlier_detection_constant = ast.literal_eval(
                      parser.get('dashboard', 'OUTLIER_DETECTION_CONSTANT'))
  
              # when a security token is provided:
              if parser.has_option('dashboard', 'security_token'):
                  self.security_token = parser.get('dashboard', 'SECURITY_TOKEN')
  
          except configparser.Error:
              raise
  