Instagram / LibCST

A concrete syntax tree parser and serializer library for Python that preserves many aspects of Python's abstract syntax tree
https://libcst.readthedocs.io/
Other
1.53k stars 187 forks source link

[Feature Request] evaluated_value() method on [static] containers #878

Open jakkdl opened 1 year ago

jakkdl commented 1 year ago

Integer.evaluated_value exists, so why not also a Tuple.evaluated_value, Dict.evaluated_value, etc?

Background: I just cobbled together this mess of a function:

def cst_literal_eval(node: cst.BaseExpression) -> Any:
    ast_node = cst.Module([cst.SimpleStatementLine([cst.Expr(node)])]).code
    try:
        return ast.literal_eval(ast_node)
    except Exception:
        return None

In flake8-trio, for seeing if for i in range(...) can be statically determined to run at least once, and would be great to just be able to call .evaluated_value on the node directly. (.code on something other than Module would also be neat, but that might be tricky).

zsol commented 1 year ago

I'm not sure it's a good idea to provide a Tuple.evaluated_value, etc. Mainly because it's impossible to

I'm open to adding a helper function like yours though - maybe somewhere in libcst.helpers, provided that some strong caveats are added in its documentation wrt. safety

jakkdl commented 1 year ago

Sure, I don't think it matters if it's a class method or a helper function. And you're right that it's probably bad to elevate it to the same status as Integer.literal_eval given the risks & differences in functionality.

It should be relatively safe if it just evaluates literal values, but yeah it should have a warning label. This is the docstring for ast.literal_eval:

Evaluate an expression node or a string containing only a Python expression. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None.

Caution: A complex expression can overflow the C stack and cause a crash.