String To Dict Problem

Michael Spencer mahs at
Sun Mar 26 20:53:36 CEST 2006

Kamilche wrote:
> Thanks! It's interesting, and nearly what I want, but not quite there.
> When I run my sample code through it, I get a syntax error because it's
> not a valid expression. If I were to put a 'dict(' in front and a ')'
> at the end, THEN it nearly works - but it gives me an
> 'Unsafe_Source_Error: Line 1.  Unsupported source construct:
> compiler.ast.CallFunc' error.
> How do I let one measly function in (dict), without letting them all in?
You could add a Keyword node, and use it something like this:

import compiler

class SafeEval(object):

     def visit(self, node,**kw):
         cls = node.__class__
         meth = getattr(self,'visit'+cls.__name__,self.default)
         return meth(node, **kw)

     def default(self, node, **kw):
         for child in node.getChildNodes():
             return self.visit(child, **kw)

     visitExpression = default

     def visitConst(self, node, **kw):
         return node.value

     def visitDict(self,node,**kw):
         return dict([(self.visit(k),self.visit(v)) for k,v in node.items])

     def visitTuple(self,node, **kw):
         return tuple(self.visit(i) for i in node.nodes)

     def visitList(self,node, **kw):
         return [self.visit(i) for i in node.nodes]

     def visitKeyword(self,node,**kw):
         return, self.visit(node.expr)

def safe_dict(source):
     source = "dict(%s)" % source # funcname is actually ignored
     walker = SafeEval()

     ast = compiler.parse(source,"eval")

     kwargs = {}
     args = ast.node.args
     for arg in args:
         if isinstance(arg, compiler.ast.Keyword):
             keyword, value = walker.visit(arg)
             kwargs[keyword] = value
             raise Exception, "only keywords"
     return dict(**kwargs)

 >>> source=  """gid = 'FPS', type = 'Label', pos = [0, 20], text = 'FPS', text2 
= 'more text without quotes', fmtline = "@VALUE @SIGNAL", signals = 
[('FPS',None), ('FPS2', 'something')]"""
 >>> safe_dict(source)
{'signals': [('FPS', None), ('FPS2', 'something')], 'text2': 'more text without 
quotes', 'gid': 'FPS', 'fmtline': '@VALUE @SIGNAL', 'text': 'FPS', 'type': 
'Label', 'pos': [0, 20]}


More information about the Python-list mailing list