En Fri, 04 Sep 2009 18:43:28 -0300, Sean Talts <xitr...@gmail.com> escribió:

I'm trying to parse some python with the compiler module, select a
subset of the AST returned, and then evaluate that subset, all in
python 2.4.  It seems like in python 2.6 the compiler.ast.literal_eval
function may be what I'm looking for, but unfortunately for my project
we are restricted to using 2.4.  I was wondering if there was some way
programmers performed this way back when?

Better late than never :)

This is a backport of 2.6 literal_eval using the compiler package as of 2.4; I had to add UnarySub (else -3 would be invalid) and change some attribute names, but basically it's the same code. Untested except as shown.

from compiler import parse
from compiler.ast import *

def literal_eval(node_or_string):
    """
    Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
    and None.
    """
    _safe_names = {'None': None, 'True': True, 'False': False}
    if isinstance(node_or_string, basestring):
        node_or_string = parse(node_or_string, mode='eval')
    if isinstance(node_or_string, Expression):
        node_or_string = node_or_string.node
    def _convert(node):
        if isinstance(node, Const) and isinstance(node.value,
                (basestring, int, float, long, complex)):
             return node.value
        elif isinstance(node, Tuple):
            return tuple(map(_convert, node.nodes))
        elif isinstance(node, List):
            return list(map(_convert, node.nodes))
        elif isinstance(node, Dict):
            return dict((_convert(k), _convert(v)) for k, v
                        in node.items)
        elif isinstance(node, Name):
            if node.name in _safe_names:
                return _safe_names[node.name]
        elif isinstance(node, UnarySub):
            return -_convert(node.expr)
        raise ValueError('malformed string')
    return _convert(node_or_string)

py> print literal_eval("(1, [-2.,'3',4j], {-5:None, u'6':True})")
(1, [-2.0, '3', 4j], {-5: None, u'6': True})

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to