docs: def read(*paths, **validators):
      """
      Load the configuration, make each section available in a separate dict.
  
      The configuration location can specified via an environment variable:
         - OQ_CONFIG_FILE
  
      In the absence of this environment variable the following paths will be
      used:
         - sys.prefix + /openquake.cfg when in a virtualenv
         - /etc/openquake/openquake.cfg outside of a virtualenv
  
      If those files are missing, the fallback is the source code:
         - openquake/engine/openquake.cfg
  
      Please note: settings in the site configuration file are overridden
      by settings with the same key names in the OQ_CONFIG_FILE openquake.cfg.
      """
      paths = config.paths + list(paths)
      parser = configparser.ConfigParser()
      found = parser.read(os.path.normpath(os.path.expanduser(p)) for p in paths)
      if not found:
          raise IOError('No configuration file found in %s' % str(paths))
      config.found = found
      config.clear()
      for section in parser.sections():
          config[section] = sec = DotDict(parser.items(section))
          for k, v in sec.items():
              sec[k] = validators.get(k, lambda x: x)(v)