0

I am trying to do something like this

Evaluating a mathematical expression in a string

Update - Some details about the app

The app 'exposes' some variables to the users. An example of an exposed variable is user_name. The user of the app can then create a new variable called 'user_name_upper' that can be set as user_name.upper(). Another example is exposed variables first_name and last_name and the user can create a new variable called 'full_name = last_name.upper() + ',' + first_name.upper()'. This is entered using a input box UI element. So no hooks into the program. Or think of this as a report like excel where I can create a new column to be a manipulation of some already defined variables.

The users of this app are not programmers. But they can be given a list of examples to find their way around string manipulations

However, my expression will be used for string manupulation. Something like "string3 = string1 + string2". Here I'd like set the value of string3 to the value of string1 appended with string2. Or "string1 = string2.lower()"

I have researched and have come to the conclusion that eval can be used but is very dangerous. From what I understand, ast_literal_eval() will not work with string manipulation methods like lower() as described here Why does this string not work with ast.literal_eval

Any suggestion on how to go about this?

Community
  • 1
  • 1
Shreyas
  • 1,410
  • 3
  • 11
  • 15
  • 2
    Why are you trying to do this? There is probably a better way to organize your problem from the beginning so that this isn't necessary. – Andrew Clark Apr 08 '13 at 16:21
  • This is for a scientific app. Users will have the option of 'creating' their own variables and so this will involve user input that needs to be sanitized. What other way would you recommend? – Shreyas Apr 08 '13 at 16:23
  • Let the users write python scripts using your library – piokuc Apr 08 '13 at 16:26
  • I would recommend learning how to use a lexer/parser. [PLY](http://www.dabeaz.com/ply/) seems to be a popular choice, though I've never used it. I just use my own. – Tyler Crompton Apr 08 '13 at 16:28
  • Some more detail of the app. The app 'exposes' some variables to the users. An example is user_name. The user of the app can then create a new variable called 'user_name_upper' that can be set as user_name.upper(). Another example is variables 'first_name' and 'last_name' are available and user can create a new variable called 'full_name = last_name.upper() + ',' + first_name.upper()'. This is entered using a input box UI element. So no hooks into the program. Hope this helps – Shreyas Apr 08 '13 at 16:30

2 Answers2

1

ast.literal_eval is the wrong function. It only evaluates literals like 2.3 or "hello".

What you want is the built in function compile() or ast.parse(). These functions IMHO (I never used them) can create abstract syntax trees. Look at the second paragraph of:

http://docs.python.org/2/library/ast.html

Off course it's risky to let your users enter arbitrary expressions. However I think you ask this question, because you want want to search the AST for problematic code.

Eike
  • 2,205
  • 17
  • 10
  • Thanks @Eike. This might be a good way of doing it. Based on your answer, I searched more and found this [link]http://pythonic.pocoo.org/2008/3/29/ast-compilation-from-python. Are there any downsides to doing this for string expressions? Can malicious code be injected? I think having the AST helps eliminate that issue, correct? – Shreyas Apr 08 '13 at 18:03
  • Yes, off course can your users enter malicious code, and try to trick you. Making it really safe will probably require some serious thinking. However, preventing your users to crash the program involuntarily, shouldn't be too difficult. Make a set of AST nodes that the program accepts, and refuse to process anything else. – Eike Apr 08 '13 at 18:13
  • If your program is really a publicly accessible web server, you should probably think about an alternative solution. Anyway, your inspiration should be this XKCD cartoon: http://xkcd.com/327/ – Eike Apr 08 '13 at 18:18
  • Thanks @Eike ...marked your answer as the correct one. Loved the xkcd cartoon :) – Shreyas Apr 08 '13 at 21:53
-2

Although I would recommend other methods of using this, if you need to use dynamic variables (when you don't know what they will be called, or how many there will be), I find that dictionaries work well.

Ex:

def createVariable(variables, string1, string2):
    variables[string1] = string2.lower()
Tyler Crompton
  • 12,284
  • 14
  • 65
  • 94
James
  • 2,635
  • 5
  • 23
  • 30
  • Thanks for the response. Not sure if this makes sense. Please revisit my question which I have edited to add more info about the apps/users – Shreyas Apr 08 '13 at 16:34