Example #1
0
 def __init__(self, filename):
     self.filename = filename = filename.strip()
     defaults = {
         'here': os.path.dirname(os.path.abspath(filename)),
         '__file__': os.path.abspath(filename)
     }
     self.parser = NicerConfigParser(filename, defaults=defaults)
     self.parser.optionxform = str  # Don't lower-case keys
     with open(filename) as f:
         self.parser.read_file(f)
Example #2
0
 def __init__(self, filename):
     self.filename = filename = filename.strip()
     defaults = {
         'here': os.path.dirname(os.path.abspath(filename)),
         '__file__': os.path.abspath(filename)
     }
     self.parser = NicerConfigParser(filename, defaults=defaults)
     self.parser.optionxform = str  # Don't lower-case keys
     with open(filename) as f:
         self.parser.read_file(f)
Example #3
0
class ConfigLoader(_Loader):

    def __init__(self, filename):
        self.filename = filename = filename.strip()
        defaults = {
            'here': os.path.dirname(os.path.abspath(filename)),
            '__file__': os.path.abspath(filename)
        }
        self.parser = NicerConfigParser(filename, defaults=defaults)
        self.parser.optionxform = str  # Don't lower-case keys
        with open(filename) as f:
            self.parser.read_file(f)

    def update_defaults(self, new_defaults, overwrite=True):
        for key, value in new_defaults.items():
            if not overwrite and key in self.parser._defaults:
                continue
            self.parser._defaults[key] = value

    def get_context(self, object_type, name=None, global_conf=None):
        if self.absolute_name(name):
            return loadcontext(object_type, name,
                               relative_to=os.path.dirname(self.filename),
                               global_conf=global_conf)
        section = self.find_config_section(
            object_type, name=name)
        if global_conf is None:
            global_conf = {}
        else:
            global_conf = global_conf.copy()
        defaults = self.parser.defaults()
        global_conf.update(defaults)
        local_conf = {}
        global_additions = {}
        get_from_globals = {}
        for option in self.parser.options(section):
            if option.startswith('set '):
                name = option[4:].strip()
                global_additions[name] = global_conf[name] = (
                    self.parser.get(section, option))
            elif option.startswith('get '):
                name = option[4:].strip()
                get_from_globals[name] = self.parser.get(section, option)
            else:
                if option in defaults:
                    # @@: It's a global option (?), so skip it
                    continue
                local_conf[option] = self.parser.get(section, option)
        for local_var, glob_var in get_from_globals.items():
            local_conf[local_var] = global_conf[glob_var]
        if object_type in (APP, FILTER) and 'filter-with' in local_conf:
            filter_with = local_conf.pop('filter-with')
        else:
            filter_with = None
        if 'require' in local_conf:
            for spec in local_conf['require'].split():
                pkg_resources.require(spec)
            del local_conf['require']
        if section.startswith('filter-app:'):
            context = self._filter_app_context(
                object_type, section, name=name,
                global_conf=global_conf, local_conf=local_conf,
                global_additions=global_additions)
        elif section.startswith('pipeline:'):
            context = self._pipeline_app_context(
                object_type, section, name=name,
                global_conf=global_conf, local_conf=local_conf,
                global_additions=global_additions)
        elif 'use' in local_conf:
            context = self._context_from_use(
                object_type, local_conf, global_conf, global_additions,
                section)
        else:
            context = self._context_from_explicit(
                object_type, local_conf, global_conf, global_additions,
                section)
        if filter_with is not None:
            filter_with_context = LoaderContext(
                obj=None,
                object_type=FILTER_WITH,
                protocol=None,
                global_conf=global_conf, local_conf=local_conf,
                loader=self)
            filter_with_context.filter_context = self.filter_context(
                name=filter_with, global_conf=global_conf)
            filter_with_context.next_context = context
            return filter_with_context
        return context

    def _context_from_use(self, object_type, local_conf, global_conf,
                          global_additions, section):
        use = local_conf.pop('use')
        context = self.get_context(
            object_type, name=use, global_conf=global_conf)
        context.global_conf.update(global_additions)
        context.local_conf.update(local_conf)
        if '__file__' in global_conf:
            # use sections shouldn't overwrite the original __file__
            context.global_conf['__file__'] = global_conf['__file__']
        # @@: Should loader be overwritten?
        context.loader = self

        if context.protocol is None:
            # Determine protocol from section type
            section_protocol = section.split(':', 1)[0]
            if section_protocol in ('application', 'app'):
                context.protocol = 'paste.app_factory'
            elif section_protocol in ('composit', 'composite'):
                context.protocol = 'paste.composit_factory'
            else:
                # This will work with 'server' and 'filter', otherwise it
                # could fail but there is an error message already for
                # bad protocols
                context.protocol = f'paste.{section_protocol}_factory'

        return context

    def _context_from_explicit(self, object_type, local_conf, global_conf,
                               global_addition, section):
        possible = []
        for protocol_options in object_type.egg_protocols:
            for protocol in protocol_options:
                if protocol in local_conf:
                    possible.append((protocol, local_conf[protocol]))
                    break
        if len(possible) > 1:
            raise LookupError(
                f"Multiple protocols given in section {section!r}: {possible}")
        if not possible:
            raise LookupError(
                f"No loader given in section {section!r}")
        found_protocol, found_expr = possible[0]
        del local_conf[found_protocol]
        value = import_string(found_expr)
        context = LoaderContext(
            value, object_type, found_protocol,
            global_conf, local_conf, self)
        return context

    def _filter_app_context(self, object_type, section, name,
                            global_conf, local_conf, global_additions):
        if 'next' not in local_conf:
            raise LookupError(
                "The [%s] section in %s is missing a 'next' setting"
                % (section, self.filename))
        next_name = local_conf.pop('next')
        context = LoaderContext(None, FILTER_APP, None, global_conf,
                                local_conf, self)
        context.next_context = self.get_context(
            APP, next_name, global_conf)
        if 'use' in local_conf:
            context.filter_context = self._context_from_use(
                FILTER, local_conf, global_conf, global_additions,
                section)
        else:
            context.filter_context = self._context_from_explicit(
                FILTER, local_conf, global_conf, global_additions,
                section)
        return context

    def _pipeline_app_context(self, object_type, section, name,
                              global_conf, local_conf, global_additions):
        if 'pipeline' not in local_conf:
            raise LookupError(
                "The [%s] section in %s is missing a 'pipeline' setting"
                % (section, self.filename))
        pipeline = local_conf.pop('pipeline').split()
        if local_conf:
            raise LookupError(
                "The [%s] pipeline section in %s has extra "
                "(disallowed) settings: %s"
                % (', '.join(local_conf.keys())))
        context = LoaderContext(None, PIPELINE, None, global_conf,
                                local_conf, self)
        context.app_context = self.get_context(
            APP, pipeline[-1], global_conf)
        context.filter_contexts = [
            self.get_context(FILTER, pname, global_conf)
            for pname in pipeline[:-1]]
        return context

    def find_config_section(self, object_type, name=None):
        """
        Return the section name with the given name prefix (following the
        same pattern as ``protocol_desc`` in ``config``.  It must have the
        given name, or for ``'main'`` an empty name is allowed.  The
        prefix must be followed by a ``:``.

        Case is *not* ignored.
        """
        possible = []
        for name_options in object_type.config_prefixes:
            for name_prefix in name_options:
                found = self._find_sections(
                    self.parser.sections(), name_prefix, name)
                if found:
                    possible.extend(found)
                    break
        if not possible:
            raise LookupError(
                "No section %r (prefixed by %s) found in config %s"
                % (name,
                   ' or '.join(map(repr, _flatten(object_type.config_prefixes))),
                   self.filename))
        if len(possible) > 1:
            raise LookupError(
                "Ambiguous section names %r for section %r (prefixed by %s) "
                "found in config %s"
                % (possible, name,
                   ' or '.join(map(repr, _flatten(object_type.config_prefixes))),
                   self.filename))
        return possible[0]

    def _find_sections(self, sections, name_prefix, name):
        found = []
        if name is None:
            if name_prefix in sections:
                found.append(name_prefix)
            name = 'main'
        for section in sections:
            if section.startswith(f"{name_prefix}:"):
                if section[len(name_prefix) + 1:].strip() == name:
                    found.append(section)
        return found
Example #4
0
class ConfigLoader(_Loader):

    def __init__(self, filename):
        self.filename = filename = filename.strip()
        defaults = {
            'here': os.path.dirname(os.path.abspath(filename)),
            '__file__': os.path.abspath(filename)
        }
        self.parser = NicerConfigParser(filename, defaults=defaults)
        self.parser.optionxform = str  # Don't lower-case keys
        with open(filename) as f:
            self.parser.read_file(f)

    def update_defaults(self, new_defaults, overwrite=True):
        for key, value in iteritems(new_defaults):
            if not overwrite and key in self.parser._defaults:
                continue
            self.parser._defaults[key] = value

    def get_context(self, object_type, name=None, global_conf=None):
        if self.absolute_name(name):
            return loadcontext(object_type, name,
                               relative_to=os.path.dirname(self.filename),
                               global_conf=global_conf)
        section = self.find_config_section(
            object_type, name=name)
        if global_conf is None:
            global_conf = {}
        else:
            global_conf = global_conf.copy()
        defaults = self.parser.defaults()
        global_conf.update(defaults)
        local_conf = {}
        global_additions = {}
        get_from_globals = {}
        for option in self.parser.options(section):
            if option.startswith('set '):
                name = option[4:].strip()
                global_additions[name] = global_conf[name] = (
                    self.parser.get(section, option))
            elif option.startswith('get '):
                name = option[4:].strip()
                get_from_globals[name] = self.parser.get(section, option)
            else:
                if option in defaults:
                    # @@: It's a global option (?), so skip it
                    continue
                local_conf[option] = self.parser.get(section, option)
        for local_var, glob_var in get_from_globals.items():
            local_conf[local_var] = global_conf[glob_var]
        if object_type in (APP, FILTER) and 'filter-with' in local_conf:
            filter_with = local_conf.pop('filter-with')
        else:
            filter_with = None
        if 'require' in local_conf:
            for spec in local_conf['require'].split():
                pkg_resources.require(spec)
            del local_conf['require']
        if section.startswith('filter-app:'):
            context = self._filter_app_context(
                object_type, section, name=name,
                global_conf=global_conf, local_conf=local_conf,
                global_additions=global_additions)
        elif section.startswith('pipeline:'):
            context = self._pipeline_app_context(
                object_type, section, name=name,
                global_conf=global_conf, local_conf=local_conf,
                global_additions=global_additions)
        elif 'use' in local_conf:
            context = self._context_from_use(
                object_type, local_conf, global_conf, global_additions,
                section)
        else:
            context = self._context_from_explicit(
                object_type, local_conf, global_conf, global_additions,
                section)
        if filter_with is not None:
            filter_with_context = LoaderContext(
                obj=None,
                object_type=FILTER_WITH,
                protocol=None,
                global_conf=global_conf, local_conf=local_conf,
                loader=self)
            filter_with_context.filter_context = self.filter_context(
                name=filter_with, global_conf=global_conf)
            filter_with_context.next_context = context
            return filter_with_context
        return context

    def _context_from_use(self, object_type, local_conf, global_conf,
                          global_additions, section):
        use = local_conf.pop('use')
        context = self.get_context(
            object_type, name=use, global_conf=global_conf)
        context.global_conf.update(global_additions)
        context.local_conf.update(local_conf)
        if '__file__' in global_conf:
            # use sections shouldn't overwrite the original __file__
            context.global_conf['__file__'] = global_conf['__file__']
        # @@: Should loader be overwritten?
        context.loader = self

        if context.protocol is None:
            # Determine protocol from section type
            section_protocol = section.split(':', 1)[0]
            if section_protocol in ('application', 'app'):
                context.protocol = 'paste.app_factory'
            elif section_protocol in ('composit', 'composite'):
                context.protocol = 'paste.composit_factory'
            else:
                # This will work with 'server' and 'filter', otherwise it
                # could fail but there is an error message already for
                # bad protocols
                context.protocol = 'paste.%s_factory' % section_protocol

        return context

    def _context_from_explicit(self, object_type, local_conf, global_conf,
                               global_addition, section):
        possible = []
        for protocol_options in object_type.egg_protocols:
            for protocol in protocol_options:
                if protocol in local_conf:
                    possible.append((protocol, local_conf[protocol]))
                    break
        if len(possible) > 1:
            raise LookupError(
                "Multiple protocols given in section %r: %s"
                % (section, possible))
        if not possible:
            raise LookupError(
                "No loader given in section %r" % section)
        found_protocol, found_expr = possible[0]
        del local_conf[found_protocol]
        value = import_string(found_expr)
        context = LoaderContext(
            value, object_type, found_protocol,
            global_conf, local_conf, self)
        return context

    def _filter_app_context(self, object_type, section, name,
                            global_conf, local_conf, global_additions):
        if 'next' not in local_conf:
            raise LookupError(
                "The [%s] section in %s is missing a 'next' setting"
                % (section, self.filename))
        next_name = local_conf.pop('next')
        context = LoaderContext(None, FILTER_APP, None, global_conf,
                                local_conf, self)
        context.next_context = self.get_context(
            APP, next_name, global_conf)
        if 'use' in local_conf:
            context.filter_context = self._context_from_use(
                FILTER, local_conf, global_conf, global_additions,
                section)
        else:
            context.filter_context = self._context_from_explicit(
                FILTER, local_conf, global_conf, global_additions,
                section)
        return context

    def _pipeline_app_context(self, object_type, section, name,
                              global_conf, local_conf, global_additions):
        if 'pipeline' not in local_conf:
            raise LookupError(
                "The [%s] section in %s is missing a 'pipeline' setting"
                % (section, self.filename))
        pipeline = local_conf.pop('pipeline').split()
        if local_conf:
            raise LookupError(
                "The [%s] pipeline section in %s has extra "
                "(disallowed) settings: %s"
                % (', '.join(local_conf.keys())))
        context = LoaderContext(None, PIPELINE, None, global_conf,
                                local_conf, self)
        context.app_context = self.get_context(
            APP, pipeline[-1], global_conf)
        context.filter_contexts = [
            self.get_context(FILTER, pname, global_conf)
            for pname in pipeline[:-1]]
        return context

    def find_config_section(self, object_type, name=None):
        """
        Return the section name with the given name prefix (following the
        same pattern as ``protocol_desc`` in ``config``.  It must have the
        given name, or for ``'main'`` an empty name is allowed.  The
        prefix must be followed by a ``:``.

        Case is *not* ignored.
        """
        possible = []
        for name_options in object_type.config_prefixes:
            for name_prefix in name_options:
                found = self._find_sections(
                    self.parser.sections(), name_prefix, name)
                if found:
                    possible.extend(found)
                    break
        if not possible:
            raise LookupError(
                "No section %r (prefixed by %s) found in config %s"
                % (name,
                   ' or '.join(map(repr, _flatten(object_type.config_prefixes))),
                   self.filename))
        if len(possible) > 1:
            raise LookupError(
                "Ambiguous section names %r for section %r (prefixed by %s) "
                "found in config %s"
                % (possible, name,
                   ' or '.join(map(repr, _flatten(object_type.config_prefixes))),
                   self.filename))
        return possible[0]

    def _find_sections(self, sections, name_prefix, name):
        found = []
        if name is None:
            if name_prefix in sections:
                found.append(name_prefix)
            name = 'main'
        for section in sections:
            if section.startswith(name_prefix + ':'):
                if section[len(name_prefix) + 1:].strip() == name:
                    found.append(section)
        return found