On Mon, Sep 7, 2020 at 9:47 AM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 7/09/20 6:03 am, Christopher Barker wrote:
Would that require that it be a keyword? I don't think so, couldn't it be "just a name" in most contexts, like "True" was in py2, which did work in ast.literal_eval()?
There could be a special bytecode that looks it up as a name, and if that doesn't work, returns float('inf'). But then you might as well make it a built-in name, which would behave almost exactly the same way, and Guido doesn't want to do that.
For it to work in ast.literal_eval, it has to have a special form in the Abstract Syntax Tree. Play around with it using something like this: ast.dump(ast.parse(some_code, mode='eval').body) and you'll see that the magic constants (eg True) have an AST node of type "Constant", as do literals that represent constants. (Note that by the time you get there, the textual representation is gone. You can't distinguish octal or hex constants once they just become integers.) Name lookups, on the other hand, are quite different. If "inf" were to do a name lookup with a fallback, it'd be much more similar to name lookups than to constants, and it'd definitely need special handling inside literal_eval. And if it's going to get special handling, it'd be way WAY cleaner to just build a function similar to literal_eval that permits exactly the operations you're okay with. For instance, Name lookups (in a Load context) that can be satisfied from a specific dictionary; or all Name lookups but no Attribute referencing; or allow basic arithmetic operations (+-*/) but disallow function calls; or whatever you like. Check out the source code for literal_eval and you'll see that it's fairly simple: it does an AST parse on the text string, then recursively walks the syntax tree using its own evaluator, raising an exception if it finds something it doesn't want to work with. ChrisA