Gets the setting specified by ``key``. For efficiency, we cache the retrieval of settings to avoid multiple searches through the sources list.

        :param str key: settings key to retrieve
        :param str default: use this as default value when the setting key is not found
        :param func cast_func: cast the value of the settings using this function
        :param bool case_sensitive: whether to make case sensitive comparisons for settings key
        :param bool raise_exception: whether to raise a :exc:`MissingSettingException` exception when the setting is not found
        :param bool warn_missing: whether to display a warning when the setting is not found
        :param list additional_sources: additional sources to search for the key; note that the values obtained here could be cached in a future call

        :returns: the setting value
        :rtype: str

def get(self, key, *, default=None, cast_func=None, case_sensitive=None, raise_exception=None, warn_missing=None, use_cache=True, additional_sources=[]):
        """
        Gets the setting specified by ``key``. For efficiency, we cache the retrieval of settings to avoid multiple searches through the sources list.

        :param str key: settings key to retrieve
        :param str default: use this as default value when the setting key is not found
        :param func cast_func: cast the value of the settings using this function
        :param bool case_sensitive: whether to make case sensitive comparisons for settings key
        :param bool raise_exception: whether to raise a :exc:`MissingSettingException` exception when the setting is not found
        :param bool warn_missing: whether to display a warning when the setting is not found
        :param list additional_sources: additional sources to search for the key; note that the values obtained here could be cached in a future call

        :returns: the setting value
        :rtype: str
        """

        case_sensitive = self.case_sensitive if case_sensitive is None else case_sensitive
        raise_exception = self.raise_exception if raise_exception is None else raise_exception
        warn_missing = self.warn_missing if warn_missing is None else warn_missing

        if not case_sensitive: key = key.lower()

        if use_cache and key in self._cache:
            return cast_func(self._cache[key]) if cast_func else self._cache[key]

        found, value = False, None

        for source, settings in chain(self._settings.items(), map(self._load_settings_from_source, additional_sources)):
            if case_sensitive:
                if key in settings:
                    found = True
                    value = settings[key]
                else: continue

            else:
                possible_keys = [k for k in settings.keys() if k.lower() == key]
                if not possible_keys: continue
                else:
                    if len(possible_keys) > 1:
                        warnings.warn('There are more than one possible value for "{}" in <{}> settings due to case insensitivity.'.format(key, source))

                    found = True
                    value = settings[possible_keys[0]]
                #end if
            #end if

            if found: break
        #end for

        if not found:
            if raise_exception: raise MissingSettingException('The "{}" setting is missing.'.format(key))
            if warn_missing: warnings.warn('The "{}" setting is missing.'.format(key))

            return default
        #end if

        if use_cache: self._cache[key] = value
        if cast_func: value = cast_func(value)

        return value