Construct the event store to write and write from/to.

    The event store is constructed from an optionally given configuration file
    and/or command line arguments. Command line arguments has higher
    presendence over configuration file attributes.

    If a defined event store is missing, `InMemoryEventStore` will be used and
    a warning will be logged to stderr.

    This function is considered public API since external event stores might
    use it to load other (usually, underlying) event stores.

    Arguments:
    config  -- a configuration dictionary. Derived from
                     `configparser.RawConfigParser`.
    section -- the config section to use for event store instantiation.

    returns -- a new event store.

def construct_eventstore(config, section=None):
    """Construct the event store to write and write from/to.

    The event store is constructed from an optionally given configuration file
    and/or command line arguments. Command line arguments has higher
    presendence over configuration file attributes.

    If a defined event store is missing, `InMemoryEventStore` will be used and
    a warning will be logged to stderr.

    This function is considered public API since external event stores might
    use it to load other (usually, underlying) event stores.

    Arguments:
    config  -- a configuration dictionary. Derived from
                     `configparser.RawConfigParser`.
    section -- the config section to use for event store instantiation.

    returns -- a new event store.

    """
    ESTORE_CLASS_ATTRIBUTE = 'class'

    if config is None:
        _logger.warn("Using InMemoryEventStore. Events are not persisted."
                     " See example config file on how to persist them.")
        # XXX: This is to evade circular dependency between config and
        #      eventstores.
        import rewind.server.eventstores as eventstores
        eventstore = eventstores.InMemoryEventStore()
        return eventstore

    if section is None:
        if DEFAULT_SECTION not in config.sections():
            raise ConfigurationError("Missing default section, `general`.")
        try:
            section = config.get(DEFAULT_SECTION, 'storage-backend')
        except configparser.NoOptionError:
            _logger.warn("Using InMemoryEventStore. Events are not persisted."
                         " See example config file on how to persist them.")
            # XXX: This is to evade circular dependency between config and
            #      eventstores.
            import rewind.server.eventstores as eventstores
            eventstore = eventstores.InMemoryEventStore()
            return eventstore

    if section not in config.sections():
        msg = "The section for event store does not exist: {0}"
        raise ConfigurationError(msg.format(section))

    if not config.has_option(section, ESTORE_CLASS_ATTRIBUTE):
        errmsg = 'Configuration option `class` missing for section `{0}`.'
        raise ConfigurationError(errmsg.format(section))

    classpath = config.get(section, ESTORE_CLASS_ATTRIBUTE)
    classpath_pieces = classpath.split('.')
    classname = classpath_pieces[-1]
    modulepath = '.'.join(classpath_pieces[0:-1])

    module = importlib.import_module(modulepath)

    # Instantiating the event store in question using custom arguments
    options = config.options(section)
    if ESTORE_CLASS_ATTRIBUTE in options:
        # Unnecessary argument
        i = options.index(ESTORE_CLASS_ATTRIBUTE)
        del options[i]
    _class = getattr(module, classname)
    customargs = {option: config.get(section, option) for option in options}
    try:
        eventstore = _class.from_config(config, **customargs)
    except ConfigurationError as e:
        msg = "Could not instantiate `{0}`: {1}"
        raise ConfigurationError(msg.format(_class, e.what))

    return eventstore