Example #1
0
    def _handle(self, node: ast.expr) -> Any:
        """
        This is where the evaluation happens.
        Users should use `__getitem__`, i.e. `evaluator[node]`,
        as it provides caching.

        :param node: an AST expression to evaluate
        :return: the value of the node
        """

        with suppress(ValueError):
            return ast.literal_eval(node)

        if isinstance(node, ast.Name):
            try:
                return self.names[node.id]
            except KeyError:
                raise CannotEval

        if isinstance(node, ast.Attribute):
            value = self[node.value]
            attr = node.attr
            return getattr_static(value, attr)

        if isinstance(node, ast.Subscript):
            value = self[node.value]
            index = node.slice
            if is_any(type(value), list, tuple, str, bytes, bytearray):
                if isinstance(index, ast.Index):
                    key = of_type(self[index.value], int, bool)
                    try:
                        return value[key]
                    except IndexError:
                        raise CannotEval
                elif isinstance(index, ast.Slice):
                    return value[slice(*[
                        None if p is None else of_type(self[p], int, bool)
                        for p in [index.lower, index.upper, index.step]
                    ])]
            elif is_any(type(value), dict) and isinstance(index, ast.Index):
                key = self[index.value]
                if (
                        safe_hash_key(key)

                        # Have to ensure that the dict only contains keys that
                        # can safely be compared via __eq__ to the index.
                        # Don't bother for massive dicts to not kill performance
                        and len(value) < 10000
                        and all(map(safe_hash_key, value))
                ):
                    try:
                        return value[key]
                    except KeyError:
                        raise CannotEval

        raise CannotEval
def _resolve_descriptor(d, instance, owner):
    try:
        return type(of_type(d, *safe_descriptor_types)).__get__(
            d, instance, owner)
    except AttributeError as e:
        raise CannotEval from e
Example #3
0
    def _handle_call(self, node):
        if node.keywords:
            raise CannotEval
        func = self[node.func]
        args = [self[arg] for arg in node.args]

        if (is_any(
                func,
                slice,
                int,
                range,
                round,
                complex,
                list,
                tuple,
                abs,
                hex,
                bin,
                oct,
                bool,
                ord,
                float,
                len,
                chr,
        ) or len(args) == 0 and is_any(func, set, dict, str, frozenset, bytes,
                                       bytearray, object) or len(args) >= 2
                and is_any(func, str, divmod, bytes, bytearray, pow)):
            args = [
                of_standard_types(arg, check_dict_values=False, deep=False)
                for arg in args
            ]
            try:
                return func(*args)
            except Exception as e:
                raise CannotEval from e

        if len(args) == 1:
            arg = args[0]
            if is_any(func, id, type):
                try:
                    return func(arg)
                except Exception as e:
                    raise CannotEval from e
            if is_any(func, all, any, sum):
                of_type(arg, tuple, frozenset, list, set, dict, OrderedDict,
                        deque)
                for x in arg:
                    of_standard_types(x, check_dict_values=False, deep=False)
                try:
                    return func(arg)
                except Exception as e:
                    raise CannotEval from e

            if is_any(func, sorted, min, max, hash, set, dict, ascii, str,
                      repr, frozenset):
                of_standard_types(arg, check_dict_values=True, deep=True)
                try:
                    return func(arg)
                except Exception as e:
                    raise CannotEval from e
        raise CannotEval