473,385 Members | 1,587 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Late binding eval()?

I want to evaluate an expression using eval(), but I only want to supply
the variable values "on demand." For example, let's say that I want to
evaluate 'x+y'. Normally, I would create a dictionary containing 'x'
and 'y' with their corresponding values and pass it in as the globals or
locals. However, in my application, I'm getting an arbitrary expression
from the user. I thought that I could just create a dictionary-like
object and override __getitem__ to look up values in a database as they
were called for, but that didn't work.

Another way of doing this would be to parse the expression and find all
of the top-level variables. This could be a little tricky (i.e. [x for
x in mylist] would only require 'mylist' to be in the dictionary of
globals/locals.

Does anyone have any ideas on how to do this?

--
Kevin Smith
Ke*********@sas.com
Jul 18 '05 #1
3 2423
On Tue, 24 Aug 2004 18:25:54 +0000, Kevin Smith wrote:
However, in my application, I'm getting an arbitrary expression
from the user.


How arbitrary? Using the various parsing packages, it is easy to set up a
math calculator with any features you want, for instance, if you just mean
"arbitrary math".

If you're worried about security, this is really the only safe way to do
it. If you aren't worried about security... then I don't know enough about
what you are doing to have any other suggestions, but I would point out in
the general case even the Python interpeter can't guess in advance what
variables will be used, thanks to the magic of "getattr" and friends.
Jul 18 '05 #2
Kevin Smith wrote:

Does anyone have any ideas on how to do this?


A hack-approach to this migth be to eval in a loop and catch the NameError,
extract the name and bind it like this:
exp = "x * y + z"

z = 10

run = True
while run:
try:
print eval(exp)
run = False
except NameError, e:
name = e.args[0].split("'")[1]
globals()[name] = 10
Of course you can prompt the user for input, or collect the names and try to
get them at once from whereever.

--
Regards,

Diez B. Roggisch
Jul 18 '05 #3
Kevin Smith <Ke*********@sas.com> writes:
I want to evaluate an expression using eval(), but I only want to supply
the variable values "on demand." For example, let's say that I want to
evaluate 'x+y'. Normally, I would create a dictionary containing 'x'
and 'y' with their corresponding values and pass it in as the globals or
locals. However, in my application, I'm getting an arbitrary expression
from the user. I thought that I could just create a dictionary-like
object and override __getitem__ to look up values in a database as they
were called for, but that didn't work.

Another way of doing this would be to parse the expression and find all
of the top-level variables. This could be a little tricky (i.e. [x for
x in mylist] would only require 'mylist' to be in the dictionary of
globals/locals.

Does anyone have any ideas on how to do this?


Here's what I'm doing:

#! /bin/env python

import sys
import os
import tokenize
import keyword
import Numeric

class ReadlineInterface(object):
"""Present an interface that mimics readline for tokenize."""

def __init__(self, source):
"""Construct the instance."""

self.source = source
self.called = 0

def __call__(self):
"""Return the source if and only if we have not been called
before."""

if self.called == 0:
self.called = 1
return self.source
else:
return ""

class Attribute(object):
def __init__(self,
name = None,
value = 0):

self.name = name
self.value = value
return

def coerceToAttribute(value):
"""Returns value if value is an Attribute or an Attribute with
the value set."""

if isinstance(value, Attribute):
result = value
else:
result = Attribute()
result.value = value
return result

coerceToAttribute = staticmethod(coerceToAttribute)

def __add__(self, other):
"""Overloading of binary addition operator (self + other);
returns a new BaseAttribute."""

o = Attribute.coerceToAttribute(other)
result = Attribute()
result.name = self.name
result.value = self.value + o.value
return result

def __sub__(self, other):
"""Overloading of binary subtraction operator (self - other);
returns a new Attribute."""

o = Attribute.coerceToAttribute(other)
result = Attribute()
result.name = self.name
result.value = self.value - o.value
return result

class Equation(object):
def __new__(cls, *p, **k):
"""Construct a new class and correctly set up the dispatching
of properties in subclasses."""

self = object.__new__(cls, *p, **k)

# Correctly set up the dispatching of properties in subclasses.

cls.equation = property(cls.getEquation,
doc = "The equation.")

cls.created = property(cls.getCreated,
doc = "The created variables.")

cls.keywords = property(cls.getKeywords,
doc = "The keywords variable.")

cls.verbose = property(cls.getVerbose,
cls.setVerbose,
doc = "The attribute verbose. When set, the class prints more information.")
return self

def __init__(self,
equation):

"""Construct the instance."""

self.__equation = equation
self.__verbose = False

self.__created = []
self.__keywords = keyword.kwlist + ['dir',
'len',
'int',
'float',
'repr',
'abs',
'long',
'complex',
'divmod',
'max',
'min',
] + dir(Numeric)
return

def createAttribute(self,
name):
"""Build an attribute and save it's name."""
#
# Return a zeroed but otherwise useless attribute
#

result = Attribute(name = name,
value = 0)

self.__created.append(name)
return result

def localSymbols(self):
"""Return the local symbols used by the equation."""

l = locals()

#
# Add some symbols that will persist
#

if not l.has_key("keywords"):
l["keywords"] = self.keywords

return l

def createSymbols(self):
"""Determine by parsing the equation what attributes need to
be created."""

interface = ReadlineInterface(self.equation)

l = self.localSymbols()
g = globals()
k = self.keywords

try:
tokens = tokenize.generate_tokens(interface)
except tokenize.TokenError, msg:
raise TokenError(msg)

lastType = None
lastToken = None
for (tokenType, token, start, end, line) in tokens:
if self.verbose:
print 'Equation.createSymbols: type = %s, token = %s, start = %s, end = %s, line = "%s"' % \
(tokenType, token, start, end, line)

# if we are a name and the last thing that we saw was not an operator named "."
if (tokenType == tokenize.NAME) and not (lastType == tokenize.OP and lastToken == "."):
# if we have not been seen before
if (not token in k) and (not token in l) and (not token in g):
l[token] = self.createAttribute(token)

lastType = tokenType
lastToken = token

return g, l

def getEquation(self):
"""Return the equation."""

return self.__equation

def getCreated(self):
"""Return the list of created attributes."""

return self.__created

def getKeywords(self):
"""Return the list of words that are keywords."""

return self.__keywords

def getVerbose(self):
"""Return the state of verbose."""

return self.__verbose

def setVerbose(self, value):
"""Set the state of verbose."""

self.__verbose = value

return

def main(argv = None):
if argv is None:
argv = sys.argv

userSuppliedEquation = "b.value = 1; c.value = 2;a = b + c"
equ = Equation(userSuppliedEquation)
g, l = equ.createSymbols()
print "Created =", equ.created
code = compile(userSuppliedEquation, '<input>', 'exec')
eval(code, g, l)
print "a =", l['a'].value
print "b =", l['b'].value
print "c =", l['c'].value

return

if __name__ == "__main__":
sys.exit(main() or 0)

--
Jody Winston
Jul 18 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
by: Mike MacSween | last post by:
Had some trouble with Word automation. Sorted it, in the process thought I would try late binding. Some people reccomend it. So this: *********************************************************...
1
by: JD Kronicz | last post by:
Hi .. I have an issue I have been beating my head against the wall on for some time. I am trying to use late binding for MS graph so that my end users don't have to worry about having the right...
14
by: Composer | last post by:
I've read many postings about the problem of Access.References.IsBroken and the consensus seems to be that late binding is the cure-all. I have a very complex Access application that needs...
9
by: Zlatko Matić | last post by:
I was reading about late binding, but I'm not completely sure what is to be done in order to adjust code to late binding... For example, I'm not sure if this is correct: early binding: Dim ws...
5
by: eBob.com | last post by:
In another thread VJ made me aware of Tag. Fantastic! I've been wanting this capability for a long time. But it seems that I cannot use it with Option Strict On. In an event handler I have ......
30
by: lgbjr | last post by:
hi All, I've decided to use Options Strict ON in one of my apps and now I'm trying to fix a late binding issue. I have 5 integer arrays: dim IA1(500), IA2(500), IA3(500), IA4(500), IA5(500) as...
6
by: Tim Roberts | last post by:
I've been doing COM a long time, but I've just come across a behavior with late binding that surprises me. VB and VBS are not my normal milieux, so I'm hoping someone can point me to a document...
2
by: GS | last post by:
I have installed the ms PIA for ofc XP, and followed the article http://support.microsoft.com/kb/247412/ trying to paste into a worksheet However I got late binding not allowed errors .......
3
ADezii
by: ADezii | last post by:
The process of verifying that an Object exists and that a specified Property or Method is valid is called Binding. There are two times when this verification process can take place: during compile...
14
by: Siv | last post by:
hi, I am converting an application that writes to an Excel spreadsheet and the code trips the "option Strict" that I would like on because the parser says "option Strict On disallows late...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.