This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: python3 fails to use custom mapping object as symbols in eval()
Type: Stage: resolved
Components: Versions: Python 3.8
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Robert Haschke, josh.r, terry.reedy
Priority: normal Keywords:

Created on 2020-09-28 19:12 by Robert Haschke, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
buggy.py Robert Haschke, 2020-09-28 19:12 minimal working and failing code example
Messages (5)
msg377616 - (view) Author: Robert Haschke (Robert Haschke) * Date: 2020-09-28 19:12
The attached file implements a custom dict-like class (MyDict) as a minimal example of code I am using in a larger codebase. 
Before you ask, why I reimplemented a dict-like object: The real code base employs a hierarchical dict, referencing recursively to the parent dict, if a key cannot be found in the current dict.

The main code of the file defines two entries/variables for this dict:
symbols = MyDict()
symbols['abc'] = '[1, 2, 3]'
symbols['xyz'] = 'abc + abc'

and eval_text('xyz', symbols) should evaluate to the python expression as you would have evaluated those variables in a python interpreter.
While this works for the first given expression (above), it fails for this one:
symbols['xyz'] = '[abc[i]*abc[i] for i in [0, 1, 2]]'

raising NameError: name 'abc' is not defined.
The same code works perfectly in python 2.7. Hence, I assume this is a bug in python3.
msg377653 - (view) Author: Robert Haschke (Robert Haschke) * Date: 2020-09-29 04:46
Looks like the list generator is considered as a new nested scope, which prohibits access to local variables?
This basic expression, passing local symbols only, fails as well:

eval('[abc[i]*abc[i] for i in [0, 1, 2]]', {}, dict(abc=[1, 2, 3]))

while this one, passing dict as global symbols, works:

eval('[abc[i]*abc[i] for i in [0, 1, 2]]', dict(abc=[1, 2, 3]))

However, passing globals must be a real dict. So I cannot simply pass my custom mapping to globals.
msg377663 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2020-09-29 12:02
Yes, list comprehensions having their own local scope was a change from Py2 to Py3. Python 2 did not do this for list comps initially, and it was left that way during the 2.x timeframe due to back compat constraints, but 2.x did it from the start for generator expressions, as well set and dict comps, and they were all made consistent for Py3.
msg377665 - (view) Author: Robert Haschke (Robert Haschke) * Date: 2020-09-29 12:17
Thanks, Josh, for this clarification. What is the suggested mitigation?
Obviously, I need to pass all symbols from my hierarchical dictionary in a flattend version as a dict to globals. Or do you see another option?
msg377842 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2020-10-02 23:47
Robert, this tracker is for patching CPython, not for debugging user code.  If, as it appears, you are not suggesting the former, please close this.  For the latter, python-list and stackoverflow.com are appropriate forums.
History
Date User Action Args
2022-04-11 14:59:36adminsetgithub: 86044
2020-11-25 05:16:09josh.rsetstatus: open -> closed
resolution: not a bug
stage: resolved
2020-10-02 23:47:13terry.reedysetnosy: + terry.reedy
messages: + msg377842
2020-09-29 12:17:37Robert Haschkesetmessages: + msg377665
2020-09-29 12:02:49josh.rsetnosy: + josh.r
messages: + msg377663
2020-09-29 04:46:11Robert Haschkesetmessages: + msg377653
title: python3 fails to use custom dict-like object as symbols in eval() -> python3 fails to use custom mapping object as symbols in eval()
2020-09-28 19:12:20Robert Haschkecreate