How do you undo x = `a` if A is a list?

Evan Simpson evan at 4-am.com
Fri Feb 11 18:51:51 EST 2000


Aahz Maruch <aahz at netcom.com> wrote in message
news:881t8f$bvb$1 at nntp6.atl.mindspring.net...
> exec, eval(), or execfile().  All three have security problems,
> though...

Here's the safest method I've been able to find to do this sort of "limited
eval", where you want to just evaluate a series of assignment statements
with simple expressions:

from string import strip
import re
class Eval_assigns:
    '''Evaluate a list of assignment statements in a safe context'''
    assignment = re.compile('\s*([A-Z][A-Z0-9_]*)\s*=[^=]', re.I)
    def __init__(self, module_names=(), builtin_names=(), other_dict={}):
        self.safeglobals = sg = {'__builtins__': {}}
        # Leave __builtins__ empty!!

        # provide access to selected modules
        for name in module_names:
            m = __import__(name)
            for f in dir(m):
                if f[:1] != '_':
                    sg[f] = getattr(m, f)

        # provide access to selected builtins
        if type(__builtins__) == type({}):
            bget = __builtins__.get
        else:
            bget = __builtins__.__dict__.get
        for name in builtin_names:
            sg[name] = bget(name)

        # provide other initial variables
        sg.update(other_dict)

    def eval(self, assigns):
        g = self.safeglobals.copy()
        for var, expr in assigns:
            if var:
                g[var] = eval(expr, g)
            else:
                eval(expr, g)
        for k in self.safeglobals.keys():
            del g[k]
        return g

    def eval_file(self, filename=None):
        '''Evaluate assignments from a file or list of files

        If 'filename' is not provided, command line arguments will be used
        (see fileinput module).'''
        from fileinput import input
        if filename is None:
            filename = ()
        else:
            filename = (filename)
        g = self.safeglobals.copy()
        match = self.assignment.match
        for line in apply(input, filename):
            m = match(line)
            if m:
                var = m.group(1)
                expr = strip(line[m.end()-1:])
                g[var] = eval(expr, g)
            else:
                eval(line, g)
        for k in self.safeglobals.keys():
            del g[k]
        return g

if __name__ == '__main__':
    modules = ('math', 'string') # etc
    builtins = ('int', 'str', 'map') # etc
    constants = {'grbl': 6.78} # etc
    results = Eval_assigns(modules, builtins, constants).eval_file()
    print results

Cheers,

Evan @ 4-am





More information about the Python-list mailing list