From: <pj...@us...> - 2008-11-27 04:52:48
|
Revision: 5646 http://jython.svn.sourceforge.net/jython/?rev=5646&view=rev Author: pjenvey Date: 2008-11-27 04:52:37 +0000 (Thu, 27 Nov 2008) Log Message: ----------- temporarily store genexps in Java's frame instead of PyFrame. the latter could modify f_locals when cleaning up the temp slot, which causes an obscure bug if the genexp is iterating over that same f_locals (dict changed size during iteration). e.g., in a module's top level: __all__ = tuple(x for x in locals() if x.isupper()) Modified Paths: -------------- trunk/jython/src/org/python/compiler/CodeCompiler.java Added Paths: ----------- trunk/jython/Lib/test/test_genexps_jy.py Added: trunk/jython/Lib/test/test_genexps_jy.py =================================================================== --- trunk/jython/Lib/test/test_genexps_jy.py (rev 0) +++ trunk/jython/Lib/test/test_genexps_jy.py 2008-11-27 04:52:37 UTC (rev 5646) @@ -0,0 +1,23 @@ +"""Misc generator expression tests + +Made for Jython. +""" +import unittest +from test import test_support + +locals_test = list(local for local in locals() if not local.startswith('_')) + +class GeneratorExpressionsTestCase(unittest.TestCase): + + def test_module_level_locals(self): + # NOTE: The locals_test genexp used to cause a 'dictionary + # changed size during iteration' RuntimeError. If we've gotten + # this far we've already passed + self.assert_(sorted(locals_test) == ['test_support', 'unittest']) + + +def test_main(): + test_support.run_unittest(GeneratorExpressionsTestCase) + +if __name__ == '__main__': + test_main() Modified: trunk/jython/src/org/python/compiler/CodeCompiler.java =================================================================== --- trunk/jython/src/org/python/compiler/CodeCompiler.java 2008-11-27 04:01:27 UTC (rev 5645) +++ trunk/jython/src/org/python/compiler/CodeCompiler.java 2008-11-27 04:52:37 UTC (rev 5646) @@ -2155,7 +2155,6 @@ @Override public Object visitGeneratorExp(GeneratorExp node) throws Exception { String bound_exp = "_(x)"; - String tmp_append ="_(" + node.getLine() + "_" + node.getCharPositionInLine() + ")"; setline(node); @@ -2189,7 +2188,7 @@ } } - module.PyCode(new Suite(node, new stmtType[]{n}), tmp_append, true, + module.PyCode(new Suite(node, new stmtType[]{n}), "<genexpr>", true, className, false, false, node.getLine(), scope, cflags).get(code); @@ -2199,17 +2198,15 @@ } else { code.invokespecial( "org/python/core/PyFunction", "<init>", "(" + $pyObj + $pyObjArr + $pyCode + $pyObj + $pyObjArr + ")V"); } + int genExp = storeTop(); - set(new Name(node, tmp_append, expr_contextType.Store)); - visit(iter); - visit(new Name(node, tmp_append, expr_contextType.Load)); + code.aload(genExp); + code.freeLocal(genExp); code.swap(); code.invokevirtual("org/python/core/PyObject", "__iter__", "()Lorg/python/core/PyObject;"); code.invokevirtual("org/python/core/PyObject", "__call__", "(" + $pyObj + ")" + $pyObj); - visit(new Delete(n, new exprType[] { new Name(n, tmp_append, expr_contextType.Del) })); - return null; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |