470,810 Members | 856 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,810 developers. It's quick & easy.

String To Dict Problem

Hi everyone. I'm trying to convert a string that looks like this:

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

to a dict that looks like this:

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

I've got a home-rolled routine that was 'good enough', until I added
the list of tuples in there. Now it's failing. I have a hack to
'special case' it, but you know that will come up to bite me in the
future.

Does anyone have a thought on how I can turn what are basically
function keyword arguments in string form, to a dict, without using
exec or eval?

--Kamilche

Mar 26 '06 #1
9 1348
Kamilche wrote:
Hi everyone. I'm trying to convert a string that looks like this:

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

to a dict that looks like this:

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

I've got a home-rolled routine that was 'good enough', until I added
the list of tuples in there. Now it's failing. I have a hack to
'special case' it, but you know that will come up to bite me in the
future.

Does anyone have a thought on how I can turn what are basically
function keyword arguments in string form, to a dict, without using
exec or eval?

--Kamilche


http://aspn.activestate.com/ASPN/Coo.../Recipe/364469

HTH

Michael

Mar 26 '06 #2
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?

Mar 26 '06 #3
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 node.name, 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
else:
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]}


Michael

Mar 26 '06 #4
Ah, finally, that's exactly what I need! Thanks bunches. I was
attempting to modify your first code to fit my needs, but mine was much
longer, and not yet working, a sure clue that yours is a better
solution. :-D

Mar 26 '06 #5
> def default(self, node, **kw):
for child in node.getChildNodes():
return self.visit(child, **kw)

visitExpression = default


I'm not sure I grok this part. It leads to unexpected results:
safe_dict("""gid = 'FPS', type = 'Label', pos = [0, 20], text = 'FPS', text2 = 'more text without quotes', fmtline = "@VALUE @SIGNAL", signals =
[('FPS',None), ('FPS2', 'something')], danger = 2+2""")
{'text2': 'more text without quotes', 'danger': 2, 'fmtline': '@VALUE
@SIGNAL', 'text': 'FPS', 'pos': [0, 20], 'signals': [('FPS', None),
('FPS2', 'something')], 'gid': 'FPS', 'type': 'Label'} safe_dict("""gid = 'FPS', type = 'Label', pos = [0, 20], text = 'FPS', text2

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

Mar 29 '06 #6
Michael Spencer wrote:
http://aspn.activestate.com/ASPN/Coo.../Recipe/364469


Very nice work. It will be very useful. Thanks.

Only a small problem when I try to evaluate this:

safe_eval('True')

I get:

Traceback (most recent call last):
File "safe_eval.py", line 63, in ?
safe_eval('True')
File "safe_eval.py", line 59, in safe_eval
return walker.visit(ast)
File "safe_eval.py", line 19, in visit
return meth(node, **kw)
File "safe_eval.py", line 23, in default
return self.visit(child, **kw)
File "safe_eval.py", line 19, in visit
return meth(node, **kw)
File "safe_eval.py", line 47, in visitName
node.name, node)
__main__.Unsafe_Source_Error: Line 1. Strings must be quoted: True

This is just to let you know. I can live with that. I just replace True
for 1.

Regards, Clodoaldo Pinto

Apr 22 '06 #7
Clodoaldo Pinto wrote:
Michael Spencer wrote:
http://aspn.activestate.com/ASPN/Coo.../Recipe/364469


Very nice work. It will be very useful. Thanks.

Only a small problem when I try to evaluate this:

safe_eval('True')

I get:

Traceback (most recent call last):
File "safe_eval.py", line 63, in ?
safe_eval('True')
File "safe_eval.py", line 59, in safe_eval
return walker.visit(ast)
File "safe_eval.py", line 19, in visit
return meth(node, **kw)
File "safe_eval.py", line 23, in default
return self.visit(child, **kw)
File "safe_eval.py", line 19, in visit
return meth(node, **kw)
File "safe_eval.py", line 47, in visitName
node.name, node)
__main__.Unsafe_Source_Error: Line 1. Strings must be quoted: True

This is just to let you know. I can live with that. I just replace True
for 1.

Regards, Clodoaldo Pinto

Alternatively, you could edit visitName to allow 'True' and any other
identifiers you specify e.g. (untested):

allowed = {"True": True, "False": False}
def visitName(self,node, **kw):
try:
return self.allowed[node.name]
except KeyError:
raise Unsafe_Source_Error("Strings must be quoted",
node.name, node)

Cheers
Michael

Apr 22 '06 #8
Em Sex, 2006-04-21 √*s 18:40 -0700, Clodoaldo Pinto escreveu:
Only a small problem when I try to evaluate this:

safe_eval('True')


Change

def visitName(self,node, **kw):
raise Unsafe_Source_Error("Strings must be quoted",
node.name, node)

To
otherNames = {
'True': True,
'False': False,
'None': None
}

def visitName(self, node, **kw):
name = node.name
try:
return self.__class__.otherNames[name]
except KeyError:
raise Unsafe_Source_Error("Strings must be quoted",
name, node)
--
Felipe.

Apr 22 '06 #9
Michael Spencer wrote:
Alternatively, you could edit visitName to allow 'True' and any other
identifiers you specify e.g. (untested):

allowed = {"True": True, "False": False}
def visitName(self,node, **kw):
try:
return self.allowed[node.name]
except KeyError:
raise Unsafe_Source_Error("Strings must be quoted",
node.name, node)


Thank you both Michael and Felipe. The solutions work great!

Regards, Clodoaldo

Apr 22 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

12 posts views Thread by Kamilche | last post: by
7 posts views Thread by Kamilche | last post: by
20 posts views Thread by Pierre Fortin | last post: by
21 posts views Thread by Chris S. | last post: by
16 posts views Thread by flyaflya | last post: by
15 posts views Thread by George Sakkis | last post: by
5 posts views Thread by linnorm | last post: by
20 posts views Thread by sophia | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.