(node)
| 83 | node_or_string = node_or_string.body |
| 84 | |
| 85 | def _convert(node): |
| 86 | if isinstance(node, ast.Constant): |
| 87 | return node.value |
| 88 | elif isinstance(node, ast.Tuple): |
| 89 | return tuple(map(_convert, node.elts)) |
| 90 | elif isinstance(node, ast.List): |
| 91 | return list(map(_convert, node.elts)) |
| 92 | elif isinstance(node, ast.Dict): |
| 93 | return { |
| 94 | _convert(k): _convert(v) for k, v in zip(node.keys, node.values) |
| 95 | } |
| 96 | elif isinstance(node, ast.Set): |
| 97 | return set(map(_convert, node.elts)) |
| 98 | elif ( |
| 99 | isinstance(node, ast.Call) |
| 100 | and isinstance(node.func, ast.Name) |
| 101 | and node.func.id == "set" |
| 102 | and node.args == node.keywords == [] |
| 103 | ): |
| 104 | return set() |
| 105 | |
| 106 | # this is a deviation from literal_eval: we evaluate tuple() and list() |
| 107 | elif ( |
| 108 | isinstance(node, ast.Call) |
| 109 | and isinstance(node.func, ast.Name) |
| 110 | and node.func.id == "tuple" |
| 111 | and node.args == node.keywords == [] |
| 112 | ): |
| 113 | return tuple() |
| 114 | elif ( |
| 115 | isinstance(node, ast.Call) |
| 116 | and isinstance(node.func, ast.Name) |
| 117 | and node.func.id == "list" |
| 118 | and node.args == node.keywords == [] |
| 119 | ): |
| 120 | return list() |
| 121 | |
| 122 | # this is a deviation from literal_eval: we allow non-literals |
| 123 | elif isinstance(node, ast.Name): |
| 124 | try: |
| 125 | return namespace[node.id] |
| 126 | except KeyError: |
| 127 | try: |
| 128 | return getattr(builtins, node.id) |
| 129 | except AttributeError: |
| 130 | raise EvaluationError("can't lookup %s" % node.id) |
| 131 | |
| 132 | # unary + and - are allowed on any type |
| 133 | elif isinstance(node, ast.UnaryOp) and isinstance( |
| 134 | node.op, (ast.UAdd, ast.USub) |
| 135 | ): |
| 136 | # ast.literal_eval does ast typechecks here, we use type checks |
| 137 | operand = _convert(node.operand) |
| 138 | if not type(operand) in _numeric_types: |
| 139 | raise ValueError("unary + and - only allowed on builtin nums") |
| 140 | if isinstance(node.op, ast.UAdd): |
| 141 | return +operand |
| 142 | else: |
no test coverage detected