def _handle_binop(self, node): op_type = type(node.op) op = { ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.FloorDiv: operator.floordiv, ast.Mod: operator.mod, ast.Pow: operator.pow, ast.LShift: operator.lshift, ast.RShift: operator.rshift, ast.BitOr: operator.or_, ast.BitXor: operator.xor, ast.BitAnd: operator.and_, }.get(op_type) if not op: raise CannotEval left = self[node.left] hash_type = is_any(type(left), set, frozenset, dict, OrderedDict) left = of_standard_types(left, check_dict_values=False, deep=hash_type) formatting = type(left) in (str, bytes) and op_type == ast.Mod right = of_standard_types( self[node.right], check_dict_values=formatting, deep=formatting or hash_type, ) try: return op(left, right) except Exception as e: raise CannotEval from e
def _handle_compare(self, node): left = self[node.left] result = True for op, right in zip(node.ops, node.comparators): right = self[right] op_type = type(op) op_func = { ast.Eq: operator.eq, ast.NotEq: operator.ne, ast.Lt: operator.lt, ast.LtE: operator.le, ast.Gt: operator.gt, ast.GtE: operator.ge, ast.Is: operator.is_, ast.IsNot: operator.is_not, ast.In: (lambda a, b: a in b), ast.NotIn: (lambda a, b: a not in b), }[op_type] if op_type not in (ast.Is, ast.IsNot): of_standard_types(left, check_dict_values=False, deep=True) of_standard_types(right, check_dict_values=False, deep=True) try: result = op_func(left, right) except Exception as e: raise CannotEval from e if not result: return result left = right return result
def _handle_boolop(self, node): left = of_standard_types(self[node.values[0]], check_dict_values=False, deep=False) for right in node.values[1:]: # We need short circuiting so that the whole operation can be evaluated # even if the right operand can't if isinstance(node.op, ast.Or): left = left or of_standard_types( self[right], check_dict_values=False, deep=False) else: assert isinstance(node.op, ast.And) left = left and of_standard_types( self[right], check_dict_values=False, deep=False) return left
def _handle_subscript(self, node): value = self[node.value] of_standard_types(value, check_dict_values=False, deep=is_any(type(value), dict, OrderedDict)) index = node.slice if isinstance(index, ast.Slice): index = slice(*[ None if p is None else self[p] for p in [index.lower, index.upper, index.step] ]) elif isinstance(index, ast.ExtSlice): raise CannotEval else: if isinstance(index, ast.Index): index = index.value index = self[index] of_standard_types(index, check_dict_values=False, deep=True) try: return value[index] except Exception: raise CannotEval
def _handle_unary(self, node: ast.UnaryOp): value = of_standard_types(self[node.operand], check_dict_values=False, deep=False) op_type = type(node.op) op = { ast.USub: operator.neg, ast.UAdd: operator.pos, ast.Not: operator.not_, ast.Invert: operator.invert, }[op_type] try: return op(value) except Exception as e: raise CannotEval from e
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