Beispiel #1
0
def solve_map(expr, vars):
    """Solves the map-form, by recursively calling its RHS with new vars.

    let-forms are binary expressions. The LHS should evaluate to an IAssociative
    that can be used as new vars with which to solve a new query, of which
    the RHS is the root. In most cases, the LHS will be a Var (var).

    Typically, map-forms result from the dotty "dot" (.) operator. For example,
    the query "User.name" will translate to a map-form with the var "User"
    on LHS and a var to "name" on the RHS. With top-level vars being
    something like {"User": {"name": "Bob"}}, the Var on the LHS will
    evaluate to {"name": "Bob"}, which subdict will then be used on the RHS as
    new vars, and that whole form will evaluate to "Bob".
    """
    lhs_values = __solve_for_repeated(expr.lhs, vars)

    def lazy_map():
        try:
            for lhs_value in repeated.getvalues(lhs_values):
                yield solve(expr.rhs,
                            __nest_scope(expr.lhs, vars, lhs_value)).value
        except errors.EfilterNoneError as error:
            error.root = expr
            raise

    return Result(repeated.lazy(lazy_map), ())
Beispiel #2
0
    def _generate_rows(self, args, kwargs):
        # instantiate the plugin with arguments.
        self.plugin_obj = self.plugin_cls(session=self.session,
                                          *args,
                                          **kwargs)
        output_header = getattr(self.plugin_cls, "table_header", None)
        collector = getattr(self.plugin_obj, "collect_as_dicts", None)

        if callable(collector) and output_header is not None:
            # The plugin supports the collect API and declares its output ahead
            # of time. This is the ideal case.
            self.columns = output_header
            return repeated.lazy(
                lambda: self._order_columns(output_header, collector))

        else:
            # TODO: Should we not support these kind of plugins?

            # We don't know enough about the plugin to do the easy thing. We
            # need to create a shim renderer that will cache the plugin output
            # and then use that.
            renderer = identity_renderer.IdentityRenderer(session=self.session)
            with renderer.start():
                self.session.RunPlugin(self.plugin_cls.name,
                                       format=renderer,
                                       *args,
                                       **kwargs)

            # The identity renderer will now contain the plugin output and
            # columns.
            self.columns = renderer.columns
            return repeated.repeated(*list(renderer.rows))
Beispiel #3
0
def solve_map(expr, vars):
    """Solves the map-form, by recursively calling its RHS with new vars.

    let-forms are binary expressions. The LHS should evaluate to an IAssociative
    that can be used as new vars with which to solve a new query, of which
    the RHS is the root. In most cases, the LHS will be a Var (var).

    Typically, map-forms result from the dotty "dot" (.) operator. For example,
    the query "User.name" will translate to a map-form with the var "User"
    on LHS and a var to "name" on the RHS. With top-level vars being
    something like {"User": {"name": "Bob"}}, the Var on the LHS will
    evaluate to {"name": "Bob"}, which subdict will then be used on the RHS as
    new vars, and that whole form will evaluate to "Bob".
    """
    lhs_values = solve(expr.lhs, vars).value

    def lazy_map():
        try:
            for lhs_value in repeated.getvalues(lhs_values):
                yield solve(expr.rhs,
                            __nest_scope(expr.lhs, vars, lhs_value)).value
        except errors.EfilterNoneError as error:
            error.root = expr
            raise

    return Result(repeated.lazy(lazy_map), ())
Beispiel #4
0
    def testMaterialize(self):
        self.__generator_has_run = False

        def _gen():
            if self.__generator_has_run:
                raise ValueError("This should only run once.")

            self.__generator_has_run = True
            yield 1
            yield 2
            yield 3

        lazyseq = repeated.lazy(_gen)
        self.assertValuesEqual(lazyseq, repeated.repeated(1, 2, 3))

        # Accessing this for a second time should blow up.
        with self.assertRaises(ValueError):
            core.Materialize()(lazyseq)

        # So let's reset and do this with a materialized seq.
        self.__generator_has_run = False
        materialized = core.Materialize()(lazyseq)
        self.assertEqual(materialized, repeated.repeated(1, 2, 3))

        # And a second time.
        self.assertEqual(materialized, repeated.repeated(1, 2, 3))
Beispiel #5
0
    def testMaterialize(self):
        self.__generator_has_run = False

        def _gen():
            if self.__generator_has_run:
                raise ValueError("This should only run once.")

            self.__generator_has_run = True
            yield 1
            yield 2
            yield 3

        lazyseq = repeated.lazy(_gen)
        self.assertValuesEqual(lazyseq, repeated.repeated(1, 2, 3))

        # Accessing this for a second time should blow up.
        with self.assertRaises(ValueError):
            core.Materialize()(lazyseq)

        # So let's reset and do this with a materialized seq.
        self.__generator_has_run = False
        materialized = core.Materialize()(lazyseq)
        self.assertEqual(materialized, repeated.repeated(1, 2, 3))

        # And a second time.
        self.assertEqual(materialized, repeated.repeated(1, 2, 3))
Beispiel #6
0
    def apply(self, args, kwargs):
        """Instantiate the plugin with given args and run it.

        This caches the output of the plugin. Subsequently, table_header,
        rows and columns will be populated.

        The CommmandWrapper must not be applied twice with different
        arguments - each instance represents a unique application.

        Arguments:
            args, kwargs: Arguments to the plugin.
        """
        if self._applied_args is not None:
            # Called before. Return what we cached.
            if self._applied_args != (args, kwargs):
                raise ValueError(
                    "%r was previously called with %r but is now being called"
                    " with %r. This should never happen." %
                    (self, self._applied_args, (args, kwargs)))

            return self.rows

        kwargs = kwargs.copy()
        kwargs.pop("vars", None)
        self._applied_args = (args, kwargs)

        # First time - instantiate the plugin with arguments.
        plugin_curry = getattr(self.session.plugins, self.plugin_cls.name)
        self.plugin_obj = plugin_curry(session=self.session, *args, **kwargs)

        output_header = getattr(self.plugin_cls, "table_header", None)
        collector = getattr(self.plugin_obj, "collect_as_dicts", None)

        if callable(collector) and output_header is not None:
            # The plugin supports the collect API and declares its output ahead
            # of time. This is the ideal case.
            self.columns = output_header
            self.rows = repeated.lazy(collector)
        else:
            # We don't know enough about the plugin to do the easy thing. We
            # need to create a shim renderer that will cache the plugin output
            # and then use that.
            renderer = identity_renderer.IdentityRenderer(session=self.session)
            with renderer.start():
                self.session.RunPlugin(self.plugin_cls.name,
                                       format=renderer,
                                       *args,
                                       **kwargs)

            # The identity renderer will now contain the plugin output and
            # columns.
            self.columns = renderer.columns
            self.rows = repeated.repeated(*list(renderer.rows))

        return self.rows
Beispiel #7
0
    def apply(self, args, kwargs):
        """Instantiate the plugin with given args and run it.

        This caches the output of the plugin. Subsequently, table_header,
        rows and columns will be populated.

        The CommmandWrapper must not be applied twice with different
        arguments - each instance represents a unique application.

        Arguments:
            args, kwargs: Arguments to the plugin.
        """
        if self._applied_args is not None:
            # Called before. Return what we cached.
            if self._applied_args != (args, kwargs):
                raise ValueError(
                    "%r was previously called with %r but is now being called"
                    " with %r. This should never happen."
                    % (self, self._applied_args, (args, kwargs)))

            return self.rows

        kwargs = kwargs.copy()
        kwargs.pop("vars", None)
        self._applied_args = (args, kwargs)

        # First time - instantiate the plugin with arguments.
        plugin_curry = getattr(self.session.plugins, self.plugin_cls.name)
        self.plugin_obj = plugin_curry(session=self.session,
                                       *args, **kwargs)

        output_header = getattr(self.plugin_cls, "table_header", None)
        collector = getattr(self.plugin_obj, "collect_as_dicts", None)

        if callable(collector) and output_header is not None:
            # The plugin supports the collect API and declares its output ahead
            # of time. This is the ideal case.
            self.columns = output_header
            self.rows = repeated.lazy(collector)
        else:
            # We don't know enough about the plugin to do the easy thing. We
            # need to create a shim renderer that will cache the plugin output
            # and then use that.
            renderer = identity_renderer.IdentityRenderer(session=self.session)
            with renderer.start():
                self.session.RunPlugin(self.plugin_cls.name, format=renderer,
                                       *args, **kwargs)

            # The identity renderer will now contain the plugin output and
            # columns.
            self.columns = renderer.columns
            self.rows = repeated.repeated(*list(renderer.rows))

        return self.rows
Beispiel #8
0
def solve_filter(expr, vars):
    """Filter values on the LHS by evaluating RHS with each value.

    Returns any LHS values for which RHS evaluates to a true value.
    """
    lhs_values = __solve_for_repeated(expr.lhs, vars)

    def lazy_filter():
        for lhs_value in repeated.getvalues(lhs_values):
            if solve(expr.rhs, __nest_scope(expr.lhs, vars, lhs_value)).value:
                yield lhs_value

    return Result(repeated.lazy(lazy_filter), ())
Beispiel #9
0
def solve_filter(expr, vars):
    """Filter values on the LHS by evaluating RHS with each value.

    Returns any LHS values for which RHS evaluates to a true value.
    """
    lhs_values, _ = __solve_for_repeated(expr.lhs, vars)

    def lazy_filter():
        for lhs_value in repeated.getvalues(lhs_values):
            if solve(expr.rhs, __nest_scope(expr.lhs, vars, lhs_value)).value:
                yield lhs_value

    return Result(repeated.lazy(lazy_filter), ())
Beispiel #10
0
    def __call__(self, count, x):
        def _generator():
            if isinstance(x, tuple):
                values = x
            else:
                values = repeated.getvalues(x)

            for idx, value in enumerate(values):
                if idx < count:
                    continue

                yield value

        return repeated.lazy(_generator)
Beispiel #11
0
    def __call__(self, count, x):
        def _generator():
            if isinstance(x, tuple):
                values = x
            else:
                values = repeated.getvalues(x)

            for idx, value in enumerate(values):
                if idx < count:
                    continue

                yield value

        return repeated.lazy(_generator)
Beispiel #12
0
def solve_filter(expr, vars):
    """Filter values on the LHS by evaluating RHS with each value.

    Returns any LHS values for which RHS evaluates to a true value.
    """
    lhs_values = __within_lhs_as_repeated(expr.lhs, vars)

    def lazy_filter():
        for lhs_value in repeated.getvalues(lhs_values):
            nested_scope = scope.ScopeStack(vars, lhs_value)
            if solve(expr.rhs, nested_scope).value:
                yield lhs_value

    return Result(repeated.lazy(lazy_filter), ())
Beispiel #13
0
    def apply(self, args, kwargs):
        """Instantiate the plugin with given args and run it.

        This caches the output of the plugin. Subsequently, table_header,
        rows and columns will be populated.

        Note that if the args came from efilter itself (e.g. in a
        subquery) then they are always repeated. However if the arg is
        not repeating, we can not just pass it or the plugin might
        explode. We therefore run the plugin multiple times with each
        value of the subquery.

        Arguments:
            args, kwargs: Arguments to the plugin.

        """
        kwargs.pop("vars", None)

        # Materialized kwargs. This is needed because we might expand
        # into multiple plugins below and we might as well keep
        # repeated values between invocations. Note that being lazy
        # here does not buy anything because the args are already
        # expanded in the TypedProfileCommand's arg validation
        # routine.
        kwargs = self._materialize_repeated_kwarg(kwargs)

        # Expand repeating args into non repeating plugins.
        kwargs_groups = [kwargs]

        # Keep expanding until the kwargs_groups are stable.
        while 1:
            expanded_kw_groups = []
            for kwargs in kwargs_groups:
                expanded_kw_groups.extend(self._expand_kwargs(kwargs))

            if len(expanded_kw_groups) == len(kwargs_groups):
                kwargs_groups = expanded_kw_groups
                break

            kwargs_groups = expanded_kw_groups

        row_groups = [self._generate_rows(args, k) for k in kwargs_groups]
        return repeated.lazy(lambda: itertools.chain(*row_groups))
Beispiel #14
0
def solve_filter(expr, vars):
    """Filter values on the LHS by evaluating RHS with each value.

    Returns any LHS values for which RHS evaluates to a true value.
    """
    lhs_values = solve(expr.lhs, vars).value

    def lazy_filter():
        for lhs_value in repeated.getvalues(lhs_values):
            filter_result = solve(expr.rhs, __nest_scope(
                expr.lhs, vars, lhs_value)).value
            # Repeating values are chosen if any of the values returns
            # true.
            if repeated.isrepeating(filter_result):
                if any(filter_result):
                    yield lhs_value

            else:
                # Todo: Implement a bool protocol - for now we use the
                # python bool.  Scalar values must evaluate to true.
                if bool(filter_result):
                    yield lhs_value

    return Result(repeated.lazy(lazy_filter), ())
Beispiel #15
0
 def apply(self, args, kwargs):
     return repeated.lazy(functools.partial(self.cb, *args, **kwargs))
Beispiel #16
0
 def apply(self, args, kwargs):
     return repeated.lazy(functools.partial(self.cb, *args, **kwargs))