1 message in org.python.python-bugs-list[ python-Bugs-215126 ] Over restricte...
FromSent OnAttachments
SourceForge.netMar 3, 2004 4:40 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:[ python-Bugs-215126 ] Over restricted type checking on eval() functionActions...
From:SourceForge.net (nore@sourceforge.net)
Date:Mar 3, 2004 4:40:43 am
List:org.python.python-bugs-list

Bugs item #215126, was opened at 2000-09-22 21:36 Message generated for change (Comment added) made by pfremy You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=215126&group_id=5470

Category: Python Interpreter Core Group: Feature Request Status: Open Resolution: Later Priority: 5 Submitted By: Nobody/Anonymous (nobody) Assigned to: Raymond Hettinger (rhettinger) Summary: Over restricted type checking on eval() function

Initial Comment: The built-in function eval() takes a string argument and a dictionary. The
second argument should allow any instance which defines __getitem__ as opposed
to just dictionaries.

The following example creates a type error: eval, argument 2: expected dictionary, instance found

class SpreadSheet: _cells = {} def __setitem__( self, key, formula ): self._cells[key] = formula def __getitem__( self, key ): return eval( self._cells[key], self )

ss = SpreadSheet() ss['a1'] = '5' ss['a2'] = 'a1*5' ss['a2']

----------------------------------------------------------------------

Comment By: Philippe Fremy (pfremy) Date: 2004-03-03 10:40

Message: Logged In: YES user_id=233844

I have exactly the same need as the original poster. The only difference in my case is that I inhreted a dictionnary.

I want to use the eval() function as a simple expression evaluator. I have the follwing dictionnary: d['a']='1' d['b']='2' d['c']='a+b'

I want the following results: d[a] -> 1 d[b] -> 2 d[c] -> 3

To do that, I was planning to use the eval() function and overloading the __getitem__ of the global or local dictionnary:

class MyDict( dict ) : def __getitem__( self, key ): print "__getitem__", key val = dict.__getitem__( self, key ) print "val = '%s'" % val return eval( val , self )

But it does not work: d[a]: __getitem__ a val = '1' -> 1

d[b]: __getitem__ b val = '2' -> 2

d[c]: __getitem__ c val = 'e+1' ERROR Traceback (most recent call last): File "test_parse_jaycos_config.py", line 83, in testMyDict self.assertEquals( d['c'], 2 ) File "parse_config_file.py", line 10, in __getitem__ return eval( val , self ) File "<string>", line 0, in ? TypeError: cannot concatenate 'str' and 'int' objects

d['c'] did fetch the 'a+1' value, which was passed to eval. However, eval() tried to evaluate the expression using the content of the dictionnary instead of using __getitem__. So it fetched the string '1' for 'a' instead of the value 1, so the result is not suitable for the addition.

----------------------------------------------------------------------

Comment By: Michael Chermside (mcherm) Date: 2004-01-12 23:01

Message: Logged In: YES user_id=99874

Hmm... I like this!

Of course, I am wary of adding *yet another* special double- underscore function to satisfy a single special purpose, but this would satisfy all of *my* needs, and without any performance impact for lookups that are FOUND. Lookups that are NOT found would have a slight performance degrade (I know better than to speculate about the size of the effect without measuring it). I'm not really sure what percentage of dict lookups succeed.

At any rate, what are these "other contexts" you mention in which a __keyerror__ would "also be useful"? Because if we can find other places where it is useful, that significantly improves the usefulness.

OTOH, if the tests can be done ONLY for eval (I don't really think that's possible), then I'm certain no one cares about the performance of eval.

----------------------------------------------------------------------

Comment By: Gregory Smith (gregsmith) Date: 2004-01-12 20:38

Message: Logged In: YES user_id=292741

This may be a compromise solution, which could also be useful in other contexts: What if the object passed is derived from dict - presumably that doesn't help because the point is to do low-level calls to the actual dict's lookup functions. Now, suppose we modify the basic dict type, so that before throwing a KeyError, it checks to see if it is really a derived object with a method __keyerror__, and if so, calls that and returns its result (or lets it throw)? Now you can make objects that look like dicts, and act like them at the low level, but can automatically populate themselves when non-existent keys are requested. Of course, __keyerror__('x') does not have to make an 'x' entry in the dict; it could make no change, or add several entries, depending on the desired semantics regarding future lookups. It could be set up so that every lookup fails and is forwarded by __keyerror__ to the __getitem__ of another object, for instance.

The cost of this to the 'normal' dict lookup is that the need to do PyDict_CheckExact() each time a lookup fails.

----------------------------------------------------------------------

Comment By: Michael Chermside (mcherm) Date: 2003-12-16 16:37

Message: Logged In: YES user_id=99874

I'll just add my voice as somebody who would find this to be "darn handy" if it could ever done without noticably impacting the speed of python code that DOESN'T use eval().

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one) Date: 2000-09-23 06:18

Message: Added to PEP 42.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one) Date: 2000-09-22 21:42

Message: Changed Group to Feature Request. Should be added to PEP 42 (I'll do that if
nobody beats me to it).

CPython requires a genuine dict now for speed. I believe JPython allows any
mapping object.

----------------------------------------------------------------------