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
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