Ejemplo n.º 1
0
    def test_dependency(self):
        """Test Dependency class"""
        versop_str = '>= 1.5'
        tc_versop_str = 'GCC >= 3.0'

        versop = VersionOperator(versop_str)
        tc_versop = ToolchainVersionOperator(tc_versop_str)

        txt = Dependency.SEPARATOR_DEP.join([versop_str])
        dest = {'versop':versop}
        res = Dependency(txt)
        self.assertEqual(dest, res)
        self.assertEqual(str(res), txt)

        txt = Dependency.SEPARATOR_DEP.join([versop_str, tc_versop_str])
        dest = {'versop':versop, 'tc_versop':tc_versop}
        res = Dependency(txt)
        self.assertEqual(dest, res)
        self.assertEqual(str(res), txt)
Ejemplo n.º 2
0
    def parse_sections(self, toparse, current):
        """
        Parse Section instance; convert all supported sections, keys and values to their respective representations

        Returns a dict of (nested) Sections

        :param toparse: a Section (or ConfigObj) instance, basically a dict of (unparsed) sections
        :param current: the current NestedDict 
        """
        # note: configobj already converts comma-separated strings in lists
        #
        # list of supported keywords, all else will fail
        special_keys = self.VERSION_OPERATOR_VALUE_TYPES.keys()

        self.log.debug('Processing current depth %s' % current.depth)

        for key, value in toparse.items():
            if isinstance(value, Section):
                self.log.debug("Enter subsection key %s value %s" % (key, value))

                # only supported types of section keys are:
                # * DEFAULT
                # * SUPPORTED
                # * dependencies
                # * VersionOperator or ToolchainVersionOperator (e.g. [> 2.0], [goolf > 1])
                if key in [self.SECTION_MARKER_DEFAULT, self.SECTION_MARKER_SUPPORTED]:
                    # parse value as a section, recursively
                    new_value = self.parse_sections(value, current.get_nested_dict())
                    self.log.debug('Converted %s section to new value %s' % (key, new_value))
                    current[key] = new_value

                elif key == self.SECTION_MARKER_DEPENDENCIES:
                    new_key = 'dependencies'
                    new_value = []
                    for dep_name, dep_val in value.items():
                        if isinstance(dep_val, Section):
                            raise EasyBuildError("Unsupported nested section '%s' in dependencies section", dep_name)
                        else:
                            # FIXME: parse the dependency specification for version, toolchain, suffix, etc.
                            dep = Dependency(dep_val, name=dep_name)
                            if dep.name() is None or dep.version() is None:
                                raise EasyBuildError("Failed to find name/version in parsed dependency: %s (dict: %s)",
                                                     dep, dict(dep))
                            new_value.append(dep)

                    tmpl = 'Converted dependency section %s to %s, passed it to parent section (or default)'
                    self.log.debug(tmpl % (key, new_value))
                    if isinstance(current, TopNestedDict):
                        current[self.SECTION_MARKER_DEFAULT].update({new_key: new_value})
                    else:
                        current.parent[new_key] = new_value
                else:
                    # try parsing key as toolchain version operator first
                    # try parsing as version operator if it's not a toolchain version operator
                    for marker_type in self.KNOWN_VERSION_MARKER_TYPES:
                        new_key = marker_type(key)
                        if new_key:
                            self.log.debug("'%s' was parsed as a %s section marker" % (key, marker_type.__name__))
                            break
                        else:
                            self.log.debug("Not a %s section marker" % marker_type.__name__)
                    if not new_key:
                        raise EasyBuildError("Unsupported section marker '%s'", key)

                    # parse value as a section, recursively
                    new_value = self.parse_sections(value, current.get_nested_dict())

                    self.log.debug('Converted section key %s value %s in new key %s new value %s' %
                                   (key, value, new_key, new_value))
                    current[new_key] = new_value

            else:
                # simply pass down any non-special key-value items
                if not key in special_keys:
                    self.log.debug('Passing down key %s with value %s' % (key, value))
                    new_value = value

                # parse individual key-value assignments
                elif key in self.VERSION_OPERATOR_VALUE_TYPES:
                    value_type = self.VERSION_OPERATOR_VALUE_TYPES[key]
                    # list of supported toolchains/versions
                    # first one is default
                    if isinstance(value, basestring):
                        # so the split should be unnecessary
                        # (if it's not a list already, it's just one value)
                        # TODO this is annoying. check if we can force this in configobj
                        value = value.split(',')
                    # remove possible surrounding whitespace (some people add space after comma)
                    new_value = [value_type(x.strip()) for x in value]
                    if False in [x.is_valid() for x in new_value]:
                        raise EasyBuildError("Failed to parse '%s' as list of %s", value, value_type.__name__)
                else:
                    raise EasyBuildError('Bug: supported but unknown key %s with non-string value: %s, type %s',
                                         key, value, type(value))

                self.log.debug("Converted value '%s' for key '%s' into new value '%s'" % (value, key, new_value))
                current[key] = new_value

        return current
Ejemplo n.º 3
0
    def parse_sections(self, toparse, current):
        """
        Parse Section instance; convert all supported sections, keys and values to their respective representations

        Returns a dict of (nested) Sections

        @param toparse: a Section (or ConfigObj) instance, basically a dict of (unparsed) sections
        @param current: the current NestedDict 
        """
        # note: configobj already converts comma-separated strings in lists
        #
        # list of supported keywords, all else will fail
        special_keys = self.VERSION_OPERATOR_VALUE_TYPES.keys()

        self.log.debug('Processing current depth %s' % current.depth)

        for key, value in toparse.items():
            if isinstance(value, Section):
                self.log.debug("Enter subsection key %s value %s" %
                               (key, value))

                # only supported types of section keys are:
                # * DEFAULT
                # * SUPPORTED
                # * dependencies
                # * VersionOperator or ToolchainVersionOperator (e.g. [> 2.0], [goolf > 1])
                if key in [
                        self.SECTION_MARKER_DEFAULT,
                        self.SECTION_MARKER_SUPPORTED
                ]:
                    # parse value as a section, recursively
                    new_value = self.parse_sections(value,
                                                    current.get_nested_dict())
                    self.log.debug('Converted %s section to new value %s' %
                                   (key, new_value))
                    current[key] = new_value

                elif key == self.SECTION_MARKER_DEPENDENCIES:
                    new_key = 'dependencies'
                    new_value = []
                    for dep_name, dep_val in value.items():
                        if isinstance(dep_val, Section):
                            raise EasyBuildError(
                                "Unsupported nested section '%s' in dependencies section",
                                dep_name)
                        else:
                            # FIXME: parse the dependency specification for version, toolchain, suffix, etc.
                            dep = Dependency(dep_val, name=dep_name)
                            if dep.name() is None or dep.version() is None:
                                raise EasyBuildError(
                                    "Failed to find name/version in parsed dependency: %s (dict: %s)",
                                    dep, dict(dep))
                            new_value.append(dep)

                    tmpl = 'Converted dependency section %s to %s, passed it to parent section (or default)'
                    self.log.debug(tmpl % (key, new_value))
                    if isinstance(current, TopNestedDict):
                        current[self.SECTION_MARKER_DEFAULT].update(
                            {new_key: new_value})
                    else:
                        current.parent[new_key] = new_value
                else:
                    # try parsing key as toolchain version operator first
                    # try parsing as version operator if it's not a toolchain version operator
                    for marker_type in self.KNOWN_VERSION_MARKER_TYPES:
                        new_key = marker_type(key)
                        if new_key:
                            self.log.debug(
                                "'%s' was parsed as a %s section marker" %
                                (key, marker_type.__name__))
                            break
                        else:
                            self.log.debug("Not a %s section marker" %
                                           marker_type.__name__)
                    if not new_key:
                        raise EasyBuildError("Unsupported section marker '%s'",
                                             key)

                    # parse value as a section, recursively
                    new_value = self.parse_sections(value,
                                                    current.get_nested_dict())

                    self.log.debug(
                        'Converted section key %s value %s in new key %s new value %s'
                        % (key, value, new_key, new_value))
                    current[new_key] = new_value

            else:
                # simply pass down any non-special key-value items
                if not key in special_keys:
                    self.log.debug('Passing down key %s with value %s' %
                                   (key, value))
                    new_value = value

                # parse individual key-value assignments
                elif key in self.VERSION_OPERATOR_VALUE_TYPES:
                    value_type = self.VERSION_OPERATOR_VALUE_TYPES[key]
                    # list of supported toolchains/versions
                    # first one is default
                    if isinstance(value, basestring):
                        # so the split should be unnecessary
                        # (if it's not a list already, it's just one value)
                        # TODO this is annoying. check if we can force this in configobj
                        value = value.split(',')
                    # remove possible surrounding whitespace (some people add space after comma)
                    new_value = [value_type(x.strip()) for x in value]
                    if False in [x.is_valid() for x in new_value]:
                        raise EasyBuildError(
                            "Failed to parse '%s' as list of %s", value,
                            value_type.__name__)
                else:
                    raise EasyBuildError(
                        'Bug: supported but unknown key %s with non-string value: %s, type %s',
                        key, value, type(value))

                self.log.debug(
                    "Converted value '%s' for key '%s' into new value '%s'" %
                    (value, key, new_value))
                current[key] = new_value

        return current