Example #1
0
 def test_eq(self):
     p = (packages.PackageRestriction('one', values.AlwaysTrue), )
     p2 = (packages.PackageRestriction('one', values.AlwaysFalse), )
     v = values.AlwaysTrue
     v2 = values.AlwaysFalse
     self.assertEqual(packages.Conditional('use', v, p),
                      packages.Conditional('use', v, p))
     self.assertNotEqual(packages.Conditional('use', v2, p),
                         packages.Conditional('use', v, p))
     self.assertNotEqual(packages.Conditional('use', v, p),
                         packages.Conditional('use', v, p2))
     self.assertNotEqual(packages.Conditional('use1', v, p),
                         packages.Conditional('use', v, p))
Example #2
0
    def parse(cls,
              dep_str,
              element_class,
              operators=None,
              element_func=None,
              transitive_use_atoms=False,
              allow_src_uri_file_renames=False):
        """
        :param dep_str: string abiding by DepSet syntax
        :param operators: mapping of node -> callable for special operators
            in DepSet syntax
        :param element_func: if None, element_class is used for generating
            elements, else it's used to generate elements.
            Mainly useful for when you need to curry a few args for instance
            generation, since element_class _must_ be a class
        :param element_class: class of generated elements
        """

        if not isinstance(element_class, type):
            # yes, this blocks non new style classes.  touch cookies.
            raise ValueError("element_class must be a new style class")

        if element_func is None:
            element_func = element_class

        if cls.parse_depset is not None and not (allow_src_uri_file_renames):
            restrictions = None
            if operators is None:
                has_conditionals, restrictions = cls.parse_depset(
                    dep_str, element_func, boolean.AndRestriction,
                    boolean.OrRestriction)
            else:
                for x in operators:
                    if x not in ("", "||"):
                        break
                else:
                    has_conditionals, restrictions = cls.parse_depset(
                        dep_str, element_func, operators.get(""),
                        operators.get("||"))

            if restrictions is not None:
                if not has_conditionals and transitive_use_atoms:
                    has_conditionals = cls._has_transitive_use_atoms(
                        restrictions)
                return cls(restrictions, element_class, has_conditionals)

        restrictions = []
        if operators is None:
            operators = {
                "||": boolean.OrRestriction,
                "": boolean.AndRestriction
            }

        raw_conditionals = []
        depsets = [restrictions]

        node_conds = False
        words = iter(dep_str.split())
        # we specifically do it this way since expandable_chain has a bit of nasty
        # overhead to the tune of 33% slower
        if allow_src_uri_file_renames:
            words = expandable_chain(words)
        k = None
        try:
            for k in words:
                if ")" == k:
                    # no elements == error. if closures don't map up,
                    # indexerror would be chucked from trying to pop
                    # the frame so that is addressed.
                    if not depsets[-1] or not raw_conditionals:
                        raise ParseError(dep_str)
                    elif raw_conditionals[-1] in operators:
                        if len(depsets[-1]) == 1:
                            depsets[-2].append(depsets[-1][0])
                        elif raw_conditionals[-1] == '' and (
                                len(raw_conditionals) == 1 or
                            ('' == raw_conditionals[-2])):
                            # if the frame is an and and the parent is an and, collapse it in.
                            depsets[-2].extend(depsets[-1])
                        else:
                            depsets[-2].append(
                                operators[raw_conditionals[-1]](*depsets[-1]))
                    else:
                        node_conds = True
                        c = raw_conditionals[-1]
                        if c[0] == "!":
                            c = values.ContainmentMatch(c[1:-1], negate=True)
                        else:
                            c = values.ContainmentMatch(c[:-1])

                        depsets[-2].append(
                            packages.Conditional("use", c, tuple(depsets[-1])))

                    raw_conditionals.pop()
                    depsets.pop()

                elif "(" == k:
                    k = ''
                    # push another frame on
                    depsets.append([])
                    raw_conditionals.append(k)

                elif k[-1] == '?' or k in operators:
                    # use conditional or custom op.
                    # no tokens left == bad dep_str.
                    k2 = words.next()

                    if k2 != "(":
                        raise ParseError(dep_str, k2)

                    # push another frame on
                    depsets.append([])
                    raw_conditionals.append(k)

                elif "|" in k:
                    raise ParseError(dep_str, k)
                elif allow_src_uri_file_renames:
                    try:
                        k2 = words.next()
                    except StopIteration:
                        depsets[-1].append(element_func(k))
                    else:
                        if k2 != '->':
                            depsets[-1].append(element_func(k))
                            words.appendleft((k2, ))
                        else:
                            k3 = words.next()
                            # file ename.
                            depsets[-1].append(element_func(k, k3))
                else:
                    # node/element.
                    depsets[-1].append(element_func(k))

        except IGNORED_EXCEPTIONS:
            raise
        except IndexError:
            # [][-1] for a frame access, which means it was a parse error.
            raise
        except StopIteration:
            if k is None:
                raise
            raise ParseError(dep_str, k)
        except Exception as e:
            raise_from(ParseError(dep_str, e))

        # check if any closures required
        if len(depsets) != 1:
            raise ParseError(dep_str)

        if transitive_use_atoms and not node_conds:
            # localize to this scope for speed.
            element_class = transitive_use_atom
            # we can't rely on iter(self) here since it doesn't
            # descend through boolean restricts.
            node_conds = cls._has_transitive_use_atoms(restrictions)

        return cls(tuple(restrictions), element_class, node_conds)