You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(107) |
Dec
(67) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(76) |
Feb
(125) |
Mar
(72) |
Apr
(13) |
May
(18) |
Jun
(12) |
Jul
(129) |
Aug
(47) |
Sep
(1) |
Oct
(36) |
Nov
(128) |
Dec
(124) |
2002 |
Jan
(59) |
Feb
|
Mar
(14) |
Apr
(14) |
May
(72) |
Jun
(9) |
Jul
(3) |
Aug
(5) |
Sep
(18) |
Oct
(65) |
Nov
(28) |
Dec
(12) |
2003 |
Jan
(10) |
Feb
(2) |
Mar
(4) |
Apr
(33) |
May
(21) |
Jun
(9) |
Jul
(29) |
Aug
(34) |
Sep
(4) |
Oct
(8) |
Nov
(15) |
Dec
(4) |
2004 |
Jan
(26) |
Feb
(12) |
Mar
(11) |
Apr
(9) |
May
(7) |
Jun
|
Jul
(5) |
Aug
|
Sep
(3) |
Oct
(7) |
Nov
(1) |
Dec
(10) |
2005 |
Jan
(2) |
Feb
(72) |
Mar
(16) |
Apr
(39) |
May
(48) |
Jun
(97) |
Jul
(57) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(100) |
Dec
(24) |
2006 |
Jan
(15) |
Feb
(34) |
Mar
(33) |
Apr
(31) |
May
(79) |
Jun
(64) |
Jul
(41) |
Aug
(64) |
Sep
(31) |
Oct
(46) |
Nov
(55) |
Dec
(37) |
2007 |
Jan
(32) |
Feb
(61) |
Mar
(11) |
Apr
(58) |
May
(46) |
Jun
(30) |
Jul
(94) |
Aug
(93) |
Sep
(86) |
Oct
(69) |
Nov
(125) |
Dec
(177) |
2008 |
Jan
(169) |
Feb
(97) |
Mar
(74) |
Apr
(113) |
May
(120) |
Jun
(334) |
Jul
(215) |
Aug
(237) |
Sep
(72) |
Oct
(189) |
Nov
(126) |
Dec
(160) |
2009 |
Jan
(180) |
Feb
(45) |
Mar
(98) |
Apr
(140) |
May
(151) |
Jun
(71) |
Jul
(107) |
Aug
(119) |
Sep
(73) |
Oct
(121) |
Nov
(14) |
Dec
(6) |
2010 |
Jan
(13) |
Feb
(9) |
Mar
(10) |
Apr
(64) |
May
(3) |
Jun
(16) |
Jul
(7) |
Aug
(23) |
Sep
(17) |
Oct
(37) |
Nov
(5) |
Dec
(8) |
2011 |
Jan
(10) |
Feb
(11) |
Mar
(77) |
Apr
(11) |
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <zy...@us...> - 2008-08-11 05:52:46
|
Revision: 5146 http://jython.svn.sourceforge.net/jython/?rev=5146&view=rev Author: zyasoft Date: 2008-08-11 05:52:43 +0000 (Mon, 11 Aug 2008) Log Message: ----------- Another corner case for generators: .throw on a just-started generator should immediately raise an exception in the current context. Also fixed buggy tests in test_generators. Modified Paths: -------------- branches/asm/Lib/test/test_generators.py branches/asm/Lib/test/test_genexps.py branches/asm/src/org/python/core/PyGenerator.java Modified: branches/asm/Lib/test/test_generators.py =================================================================== --- branches/asm/Lib/test/test_generators.py 2008-08-11 05:37:15 UTC (rev 5145) +++ branches/asm/Lib/test/test_generators.py 2008-08-11 05:52:43 UTC (rev 5146) @@ -728,14 +728,14 @@ syntax_tests = """ ->>> def f(): +>>> def f(): #doctest: +IGNORE_EXCEPTION_DETAIL, +NORMALIZE_WHITESPACE ... return 22 ... yield 1 Traceback (most recent call last): .. SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 3) ->>> def f(): +>>> def f(): #doctest: +IGNORE_EXCEPTION_DETAIL, +NORMALIZE_WHITESPACE ... yield 1 ... return 22 Traceback (most recent call last): @@ -744,7 +744,7 @@ "return None" is not the same as "return" in a generator: ->>> def f(): +>>> def f(): #doctest: +IGNORE_EXCEPTION_DETAIL, +NORMALIZE_WHITESPACE ... yield 1 ... return None Traceback (most recent call last): @@ -1522,17 +1522,17 @@ Check some syntax errors for yield expressions: ->>> f=lambda: (yield 1),(yield 2) +>>> f=lambda: (yield 1),(yield 2) #doctest: +IGNORE_EXCEPTION_DETAIL, +NORMALIZE_WHITESPACE Traceback (most recent call last): ... SyntaxError: 'yield' outside function (<doctest test.test_generators.__test__.coroutine[21]>, line 1) ->>> def f(): return lambda x=(yield): 1 +>>> def f(): return lambda x=(yield): 1 #doctest: +IGNORE_EXCEPTION_DETAIL, +NORMALIZE_WHITESPACE Traceback (most recent call last): ... SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.coroutine[22]>, line 1) ->>> def f(): x = yield = y +>>> def f(): x = yield = y #doctest: +IGNORE_EXCEPTION_DETAIL, +NORMALIZE_WHITESPACE Traceback (most recent call last): ... SyntaxError: assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[23]>, line 1) @@ -1580,7 +1580,7 @@ ... TypeError: instance exception may not have a separate value ->>> g.throw(ValueError, "foo", 23) # bad args +>>> g.throw(ValueError, "foo", 23) # bad args #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... TypeError: throw() third argument must be a traceback object @@ -1645,8 +1645,9 @@ >>> g.next() >>> g.close() # close normally -And finalization: - +And finalization. But we have to force the timing of GC here, since we are running on Jython: +>>> import gc +>>> from time import sleep >>> def f(): ... try: yield ... finally: @@ -1654,7 +1655,7 @@ >>> g = f() >>> g.next() ->>> del g +>>> del g; gc.collect(); sleep(1); gc.collect() exiting @@ -1679,9 +1680,9 @@ >>> old, sys.stderr = sys.stderr, StringIO.StringIO() >>> g = f() >>> g.next() ->>> del g +>>> del g; gc.collect(); sleep(1); gc.collect() >>> sys.stderr.getvalue().startswith( -... "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in " +... "Exception RuntimeError" ... ) True >>> sys.stderr = old @@ -1787,6 +1788,8 @@ to test. >>> import sys, StringIO +>>> from time import sleep +>>> import gc >>> old = sys.stderr >>> try: ... sys.stderr = StringIO.StringIO() @@ -1795,10 +1798,10 @@ ... raise RuntimeError ... ... l = Leaker() -... del l +... del l; gc.collect(); sleep(1); gc.collect() ... err = sys.stderr.getvalue().strip() ... err.startswith( -... "Exception exceptions.RuntimeError: RuntimeError() in <" +... "Exception RuntimeError in <" ... ) ... err.endswith("> ignored") ... len(err.splitlines()) Modified: branches/asm/Lib/test/test_genexps.py =================================================================== --- branches/asm/Lib/test/test_genexps.py 2008-08-11 05:37:15 UTC (rev 5145) +++ branches/asm/Lib/test/test_genexps.py 2008-08-11 05:52:43 UTC (rev 5146) @@ -133,13 +133,13 @@ >>> list(g) [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] -This doesn't make sense for Jython or other non refcounted implementations -# Verify re-use of tuples (a side benefit of using genexps over listcomps) -# -# >>> tupleids = map(id, ((i,i) for i in xrange(10))) -# >>> int(max(tupleids) - min(tupleids)) -# 0 +This doesn't make sense for Jython or other non refcounted implementations, so +SKIP +Verify re-use of tuples (a side benefit of using genexps over listcomps) + >>> tupleids = map(id, ((i,i) for i in xrange(10))) + >>> int(max(tupleids) - min(tupleids)) #doctest: +SKIP + 0 + Verify that syntax error's are raised for genexps used as lvalues >>> (y for y in (1,2)) = 10 #doctest: +IGNORE_EXCEPTION_DETAIL Modified: branches/asm/src/org/python/core/PyGenerator.java =================================================================== --- branches/asm/src/org/python/core/PyGenerator.java 2008-08-11 05:37:15 UTC (rev 5145) +++ branches/asm/src/org/python/core/PyGenerator.java 2008-08-11 05:52:43 UTC (rev 5146) @@ -46,8 +46,9 @@ } private PyObject raiseException(PyException ex) { - if (gi_frame == null) - return null; + if (gi_frame == null || gi_frame.f_lasti == 0) { + throw ex; + } gi_frame.setGeneratorInput(ex); return next(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2008-08-11 05:37:18
|
Revision: 5145 http://jython.svn.sourceforge.net/jython/?rev=5145&view=rev Author: fwierzbicki Date: 2008-08-11 05:37:15 +0000 (Mon, 11 Aug 2008) Log Message: ----------- Properly handle tuples in subscripts (last test_grammar problem!) Modified Paths: -------------- branches/asm/grammar/Python.g branches/asm/grammar/PythonWalker.g Modified: branches/asm/grammar/Python.g =================================================================== --- branches/asm/grammar/Python.g 2008-08-11 05:35:18 UTC (rev 5144) +++ branches/asm/grammar/Python.g 2008-08-11 05:37:15 UTC (rev 5145) @@ -829,8 +829,9 @@ ; //subscriptlist: subscript (',' subscript)* [','] -subscriptlist : subscript (options {greedy=true;}:COMMA subscript)* (COMMA)? - -> subscript+ +subscriptlist : subscript (options {greedy=true;}:c1=COMMA subscript)* (c2=COMMA)? + -> { $c1 != null || $c2 != null }? ^(Tuple ^(Elts subscript+)) + -> subscript ; //subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] Modified: branches/asm/grammar/PythonWalker.g =================================================================== --- branches/asm/grammar/PythonWalker.g 2008-08-11 05:35:18 UTC (rev 5144) +++ branches/asm/grammar/PythonWalker.g 2008-08-11 05:37:15 UTC (rev 5145) @@ -982,33 +982,37 @@ $marker = $test.marker; } | ^(SubscriptList subscriptlist test[expr_contextType.Load]) { - //XXX: only handling one subscript for now. - sliceType s; + sliceType s = null; List sltypes = $subscriptlist.sltypes; - if (sltypes.size() == 0) { - s = null; - } else if (sltypes.size() == 1){ - s = (sliceType)sltypes.get(0); - } else { + boolean extslice = false; + if ($subscriptlist.isTuple) { sliceType[] st; - //FIXME: here I am using ClassCastException to decide if sltypes is populated with Index - // only. Clearly this is not the best way to do this but it's late. Somebody do - // something better please :) -- (hopefully a note to self) - try { - Iterator iter = sltypes.iterator(); - List etypes = new ArrayList(); - while (iter.hasNext()) { - Index i = (Index)iter.next(); + Iterator iter = sltypes.iterator(); + List etypes = new ArrayList(); + while (iter.hasNext()) { + Object o = iter.next(); + if (o instanceof Index) { + Index i = (Index)o; etypes.add(i.value); + } else { + extslice = true; + break; } + } + if (!extslice) { exprType[] es = (exprType[])etypes.toArray(new exprType[etypes.size()]); exprType t = new Tuple($SubscriptList, es, expr_contextType.Load); s = new Index($SubscriptList, t); - } catch (ClassCastException cc) { - st = (sliceType[])sltypes.toArray(new sliceType[sltypes.size()]); - s = new ExtSlice($SubscriptList, st); } + } else if (sltypes.size() == 1) { + s = (sliceType)sltypes.get(0); + } else if (sltypes.size() != 0) { + extslice = true; } + if (extslice) { + sliceType[] st = (sliceType[])sltypes.toArray(new sliceType[sltypes.size()]); + s = new ExtSlice($SubscriptList, st); + } $etype = new Subscript($test.marker, $test.etype, s, ctype); $marker = $test.marker; } @@ -1082,13 +1086,18 @@ } ; -subscriptlist returns [List sltypes] +subscriptlist returns [List sltypes, boolean isTuple] @init { List subs = new ArrayList(); } - : subscript[subs]+ { + : subscript[subs] { $sltypes = subs; + $isTuple = false; } + | ^(Tuple ^(Elts subscript[subs]+)) { + $sltypes = subs; + $isTuple = true; + } ; subscript [List subs] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <le...@us...> - 2008-08-11 05:35:26
|
Revision: 5144 http://jython.svn.sourceforge.net/jython/?rev=5144&view=rev Author: leosoto Date: 2008-08-11 05:35:18 +0000 (Mon, 11 Aug 2008) Log Message: ----------- Really fix coercion on derived this time Modified Paths: -------------- branches/asm/src/org/python/core/PyArrayDerived.java branches/asm/src/org/python/core/PyBaseExceptionDerived.java branches/asm/src/org/python/core/PyBooleanDerived.java branches/asm/src/org/python/core/PyClassMethodDerived.java branches/asm/src/org/python/core/PyComplexDerived.java branches/asm/src/org/python/core/PyDictionaryDerived.java branches/asm/src/org/python/core/PyEnumerateDerived.java branches/asm/src/org/python/core/PyFileDerived.java branches/asm/src/org/python/core/PyFloatDerived.java branches/asm/src/org/python/core/PyFrozenSetDerived.java branches/asm/src/org/python/core/PyIntegerDerived.java branches/asm/src/org/python/core/PyListDerived.java branches/asm/src/org/python/core/PyLongDerived.java branches/asm/src/org/python/core/PyModuleDerived.java branches/asm/src/org/python/core/PyObject.java branches/asm/src/org/python/core/PyObjectDerived.java branches/asm/src/org/python/core/PyPropertyDerived.java branches/asm/src/org/python/core/PySetDerived.java branches/asm/src/org/python/core/PySliceDerived.java branches/asm/src/org/python/core/PyStringDerived.java branches/asm/src/org/python/core/PySuperDerived.java branches/asm/src/org/python/core/PyTupleDerived.java branches/asm/src/org/python/core/PyTypeDerived.java branches/asm/src/org/python/core/PyUnicodeDerived.java branches/asm/src/org/python/modules/_csv/PyDialectDerived.java branches/asm/src/org/python/modules/_functools/PyPartialDerived.java branches/asm/src/org/python/modules/_weakref/ReferenceTypeDerived.java branches/asm/src/org/python/modules/collections/PyDefaultDictDerived.java branches/asm/src/org/python/modules/collections/PyDequeDerived.java branches/asm/src/org/python/modules/random/PyRandomDerived.java branches/asm/src/org/python/modules/thread/PyLocalDerived.java branches/asm/src/org/python/modules/zipimport/zipimporterDerived.java branches/asm/src/templates/object.derived Modified: branches/asm/src/org/python/core/PyArrayDerived.java =================================================================== --- branches/asm/src/org/python/core/PyArrayDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyArrayDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyBaseExceptionDerived.java =================================================================== --- branches/asm/src/org/python/core/PyBaseExceptionDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyBaseExceptionDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1092,10 +1092,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyBooleanDerived.java =================================================================== --- branches/asm/src/org/python/core/PyBooleanDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyBooleanDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyClassMethodDerived.java =================================================================== --- branches/asm/src/org/python/core/PyClassMethodDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyClassMethodDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyComplexDerived.java =================================================================== --- branches/asm/src/org/python/core/PyComplexDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyComplexDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyDictionaryDerived.java =================================================================== --- branches/asm/src/org/python/core/PyDictionaryDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyDictionaryDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyEnumerateDerived.java =================================================================== --- branches/asm/src/org/python/core/PyEnumerateDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyEnumerateDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyFileDerived.java =================================================================== --- branches/asm/src/org/python/core/PyFileDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyFileDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyFloatDerived.java =================================================================== --- branches/asm/src/org/python/core/PyFloatDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyFloatDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyFrozenSetDerived.java =================================================================== --- branches/asm/src/org/python/core/PyFrozenSetDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyFrozenSetDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyIntegerDerived.java =================================================================== --- branches/asm/src/org/python/core/PyIntegerDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyIntegerDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyListDerived.java =================================================================== --- branches/asm/src/org/python/core/PyListDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyListDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyLongDerived.java =================================================================== --- branches/asm/src/org/python/core/PyLongDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyLongDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyModuleDerived.java =================================================================== --- branches/asm/src/org/python/core/PyModuleDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyModuleDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1092,10 +1092,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyObject.java =================================================================== --- branches/asm/src/org/python/core/PyObject.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyObject.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -936,9 +936,10 @@ * Implements numeric coercion * * @param o the other object involved in the coercion - * @return null if no coercion is possible; - * a single PyObject to use to replace o if this is unchanged; - * or a PyObject[2] consisting of replacements for this and o. + * @return null if coercion is not implemented + * Py.None if coercion was not possible + * a single PyObject to use to replace o if this is unchanged; + * or a PyObject[2] consisting of replacements for this and o. **/ public Object __coerce_ex__(PyObject o) { return null; Modified: branches/asm/src/org/python/core/PyObjectDerived.java =================================================================== --- branches/asm/src/org/python/core/PyObjectDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyObjectDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyPropertyDerived.java =================================================================== --- branches/asm/src/org/python/core/PyPropertyDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyPropertyDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PySetDerived.java =================================================================== --- branches/asm/src/org/python/core/PySetDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PySetDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PySliceDerived.java =================================================================== --- branches/asm/src/org/python/core/PySliceDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PySliceDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyStringDerived.java =================================================================== --- branches/asm/src/org/python/core/PyStringDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyStringDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PySuperDerived.java =================================================================== --- branches/asm/src/org/python/core/PySuperDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PySuperDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyTupleDerived.java =================================================================== --- branches/asm/src/org/python/core/PyTupleDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyTupleDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyTypeDerived.java =================================================================== --- branches/asm/src/org/python/core/PyTypeDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyTypeDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1092,10 +1092,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/core/PyUnicodeDerived.java =================================================================== --- branches/asm/src/org/python/core/PyUnicodeDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/core/PyUnicodeDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1116,10 +1116,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/modules/_csv/PyDialectDerived.java =================================================================== --- branches/asm/src/org/python/modules/_csv/PyDialectDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/modules/_csv/PyDialectDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1094,10 +1094,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/modules/_functools/PyPartialDerived.java =================================================================== --- branches/asm/src/org/python/modules/_functools/PyPartialDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/modules/_functools/PyPartialDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1094,10 +1094,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/modules/_weakref/ReferenceTypeDerived.java =================================================================== --- branches/asm/src/org/python/modules/_weakref/ReferenceTypeDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/modules/_weakref/ReferenceTypeDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1118,10 +1118,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/modules/collections/PyDefaultDictDerived.java =================================================================== --- branches/asm/src/org/python/modules/collections/PyDefaultDictDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/modules/collections/PyDefaultDictDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1118,10 +1118,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/modules/collections/PyDequeDerived.java =================================================================== --- branches/asm/src/org/python/modules/collections/PyDequeDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/modules/collections/PyDequeDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1118,10 +1118,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/modules/random/PyRandomDerived.java =================================================================== --- branches/asm/src/org/python/modules/random/PyRandomDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/modules/random/PyRandomDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1118,10 +1118,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/modules/thread/PyLocalDerived.java =================================================================== --- branches/asm/src/org/python/modules/thread/PyLocalDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/modules/thread/PyLocalDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1094,10 +1094,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/org/python/modules/zipimport/zipimporterDerived.java =================================================================== --- branches/asm/src/org/python/modules/zipimport/zipimporterDerived.java 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/org/python/modules/zipimport/zipimporterDerived.java 2008-08-11 05:35:18 UTC (rev 5144) @@ -1094,10 +1094,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res==null||res==Py.None) - return res; + if (res==Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return((PyTuple)res).getArray(); } return super.__coerce_ex__(o); Modified: branches/asm/src/templates/object.derived =================================================================== --- branches/asm/src/templates/object.derived 2008-08-11 04:09:35 UTC (rev 5143) +++ branches/asm/src/templates/object.derived 2008-08-11 05:35:18 UTC (rev 5144) @@ -450,10 +450,10 @@ PyObject impl=self_type.lookup("__coerce__"); if (impl!=null) { PyObject res=impl.__get__(this,self_type).__call__(o); - if (res == null || res == Py.None) - return res; + if (res == Py.NotImplemented) + return Py.None; if (!(res instanceof PyTuple)) - throw Py.TypeError("coercion should return None or 2-tuple"); + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); return ((PyTuple)res).getArray(); } return super.__coerce_ex__(o); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2008-08-11 04:09:38
|
Revision: 5143 http://jython.svn.sourceforge.net/jython/?rev=5143&view=rev Author: zyasoft Date: 2008-08-11 04:09:35 +0000 (Mon, 11 Aug 2008) Log Message: ----------- From http://svn.python.org/projects/python/branches/release25-maint/Lib/test/test_generators.py@65635 Added Paths: ----------- branches/asm/Lib/test/test_generators.py Added: branches/asm/Lib/test/test_generators.py =================================================================== --- branches/asm/Lib/test/test_generators.py (rev 0) +++ branches/asm/Lib/test/test_generators.py 2008-08-11 04:09:35 UTC (rev 5143) @@ -0,0 +1,1839 @@ +tutorial_tests = """ +Let's try a simple generator: + + >>> def f(): + ... yield 1 + ... yield 2 + + >>> for i in f(): + ... print i + 1 + 2 + >>> g = f() + >>> g.next() + 1 + >>> g.next() + 2 + +"Falling off the end" stops the generator: + + >>> g.next() + Traceback (most recent call last): + File "<stdin>", line 1, in ? + File "<stdin>", line 2, in g + StopIteration + +"return" also stops the generator: + + >>> def f(): + ... yield 1 + ... return + ... yield 2 # never reached + ... + >>> g = f() + >>> g.next() + 1 + >>> g.next() + Traceback (most recent call last): + File "<stdin>", line 1, in ? + File "<stdin>", line 3, in f + StopIteration + >>> g.next() # once stopped, can't be resumed + Traceback (most recent call last): + File "<stdin>", line 1, in ? + StopIteration + +"raise StopIteration" stops the generator too: + + >>> def f(): + ... yield 1 + ... raise StopIteration + ... yield 2 # never reached + ... + >>> g = f() + >>> g.next() + 1 + >>> g.next() + Traceback (most recent call last): + File "<stdin>", line 1, in ? + StopIteration + >>> g.next() + Traceback (most recent call last): + File "<stdin>", line 1, in ? + StopIteration + +However, they are not exactly equivalent: + + >>> def g1(): + ... try: + ... return + ... except: + ... yield 1 + ... + >>> list(g1()) + [] + + >>> def g2(): + ... try: + ... raise StopIteration + ... except: + ... yield 42 + >>> print list(g2()) + [42] + +This may be surprising at first: + + >>> def g3(): + ... try: + ... return + ... finally: + ... yield 1 + ... + >>> list(g3()) + [1] + +Let's create an alternate range() function implemented as a generator: + + >>> def yrange(n): + ... for i in range(n): + ... yield i + ... + >>> list(yrange(5)) + [0, 1, 2, 3, 4] + +Generators always return to the most recent caller: + + >>> def creator(): + ... r = yrange(5) + ... print "creator", r.next() + ... return r + ... + >>> def caller(): + ... r = creator() + ... for i in r: + ... print "caller", i + ... + >>> caller() + creator 0 + caller 1 + caller 2 + caller 3 + caller 4 + +Generators can call other generators: + + >>> def zrange(n): + ... for i in yrange(n): + ... yield i + ... + >>> list(zrange(5)) + [0, 1, 2, 3, 4] + +""" + +# The examples from PEP 255. + +pep_tests = """ + +Specification: Yield + + Restriction: A generator cannot be resumed while it is actively + running: + + >>> def g(): + ... i = me.next() + ... yield i + >>> me = g() + >>> me.next() + Traceback (most recent call last): + ... + File "<string>", line 2, in g + ValueError: generator already executing + +Specification: Return + + Note that return isn't always equivalent to raising StopIteration: the + difference lies in how enclosing try/except constructs are treated. + For example, + + >>> def f1(): + ... try: + ... return + ... except: + ... yield 1 + >>> print list(f1()) + [] + + because, as in any function, return simply exits, but + + >>> def f2(): + ... try: + ... raise StopIteration + ... except: + ... yield 42 + >>> print list(f2()) + [42] + + because StopIteration is captured by a bare "except", as is any + exception. + +Specification: Generators and Exception Propagation + + >>> def f(): + ... return 1//0 + >>> def g(): + ... yield f() # the zero division exception propagates + ... yield 42 # and we'll never get here + >>> k = g() + >>> k.next() + Traceback (most recent call last): + File "<stdin>", line 1, in ? + File "<stdin>", line 2, in g + File "<stdin>", line 2, in f + ZeroDivisionError: integer division or modulo by zero + >>> k.next() # and the generator cannot be resumed + Traceback (most recent call last): + File "<stdin>", line 1, in ? + StopIteration + >>> + +Specification: Try/Except/Finally + + >>> def f(): + ... try: + ... yield 1 + ... try: + ... yield 2 + ... 1//0 + ... yield 3 # never get here + ... except ZeroDivisionError: + ... yield 4 + ... yield 5 + ... raise + ... except: + ... yield 6 + ... yield 7 # the "raise" above stops this + ... except: + ... yield 8 + ... yield 9 + ... try: + ... x = 12 + ... finally: + ... yield 10 + ... yield 11 + >>> print list(f()) + [1, 2, 4, 5, 8, 9, 10, 11] + >>> + +Guido's binary tree example. + + >>> # A binary tree class. + >>> class Tree: + ... + ... def __init__(self, label, left=None, right=None): + ... self.label = label + ... self.left = left + ... self.right = right + ... + ... def __repr__(self, level=0, indent=" "): + ... s = level*indent + repr(self.label) + ... if self.left: + ... s = s + "\\n" + self.left.__repr__(level+1, indent) + ... if self.right: + ... s = s + "\\n" + self.right.__repr__(level+1, indent) + ... return s + ... + ... def __iter__(self): + ... return inorder(self) + + >>> # Create a Tree from a list. + >>> def tree(list): + ... n = len(list) + ... if n == 0: + ... return [] + ... i = n // 2 + ... return Tree(list[i], tree(list[:i]), tree(list[i+1:])) + + >>> # Show it off: create a tree. + >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + + >>> # A recursive generator that generates Tree labels in in-order. + >>> def inorder(t): + ... if t: + ... for x in inorder(t.left): + ... yield x + ... yield t.label + ... for x in inorder(t.right): + ... yield x + + >>> # Show it off: create a tree. + >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + >>> # Print the nodes of the tree in in-order. + >>> for x in t: + ... print x, + A B C D E F G H I J K L M N O P Q R S T U V W X Y Z + + >>> # A non-recursive generator. + >>> def inorder(node): + ... stack = [] + ... while node: + ... while node.left: + ... stack.append(node) + ... node = node.left + ... yield node.label + ... while not node.right: + ... try: + ... node = stack.pop() + ... except IndexError: + ... return + ... yield node.label + ... node = node.right + + >>> # Exercise the non-recursive generator. + >>> for x in t: + ... print x, + A B C D E F G H I J K L M N O P Q R S T U V W X Y Z + +""" + +# Examples from Iterator-List and Python-Dev and c.l.py. + +email_tests = """ + +The difference between yielding None and returning it. + +>>> def g(): +... for i in range(3): +... yield None +... yield None +... return +>>> list(g()) +[None, None, None, None] + +Ensure that explicitly raising StopIteration acts like any other exception +in try/except, not like a return. + +>>> def g(): +... yield 1 +... try: +... raise StopIteration +... except: +... yield 2 +... yield 3 +>>> list(g()) +[1, 2, 3] + +Next one was posted to c.l.py. + +>>> def gcomb(x, k): +... "Generate all combinations of k elements from list x." +... +... if k > len(x): +... return +... if k == 0: +... yield [] +... else: +... first, rest = x[0], x[1:] +... # A combination does or doesn't contain first. +... # If it does, the remainder is a k-1 comb of rest. +... for c in gcomb(rest, k-1): +... c.insert(0, first) +... yield c +... # If it doesn't contain first, it's a k comb of rest. +... for c in gcomb(rest, k): +... yield c + +>>> seq = range(1, 5) +>>> for k in range(len(seq) + 2): +... print "%d-combs of %s:" % (k, seq) +... for c in gcomb(seq, k): +... print " ", c +0-combs of [1, 2, 3, 4]: + [] +1-combs of [1, 2, 3, 4]: + [1] + [2] + [3] + [4] +2-combs of [1, 2, 3, 4]: + [1, 2] + [1, 3] + [1, 4] + [2, 3] + [2, 4] + [3, 4] +3-combs of [1, 2, 3, 4]: + [1, 2, 3] + [1, 2, 4] + [1, 3, 4] + [2, 3, 4] +4-combs of [1, 2, 3, 4]: + [1, 2, 3, 4] +5-combs of [1, 2, 3, 4]: + +From the Iterators list, about the types of these things. + +>>> def g(): +... yield 1 +... +>>> type(g) +<type 'function'> +>>> i = g() +>>> type(i) +<type 'generator'> +>>> [s for s in dir(i) if not s.startswith('_')] +['close', 'gi_frame', 'gi_running', 'next', 'send', 'throw'] +>>> print i.next.__doc__ +x.next() -> the next value, or raise StopIteration +>>> iter(i) is i +True +>>> import types +>>> isinstance(i, types.GeneratorType) +True + +And more, added later. + +>>> i.gi_running +0 +>>> type(i.gi_frame) +<type 'frame'> +>>> i.gi_running = 42 +Traceback (most recent call last): + ... +TypeError: readonly attribute +>>> def g(): +... yield me.gi_running +>>> me = g() +>>> me.gi_running +0 +>>> me.next() +1 +>>> me.gi_running +0 + +A clever union-find implementation from c.l.py, due to David Eppstein. +Sent: Friday, June 29, 2001 12:16 PM +To: pyt...@py... +Subject: Re: PEP 255: Simple Generators + +>>> class disjointSet: +... def __init__(self, name): +... self.name = name +... self.parent = None +... self.generator = self.generate() +... +... def generate(self): +... while not self.parent: +... yield self +... for x in self.parent.generator: +... yield x +... +... def find(self): +... return self.generator.next() +... +... def union(self, parent): +... if self.parent: +... raise ValueError("Sorry, I'm not a root!") +... self.parent = parent +... +... def __str__(self): +... return self.name + +>>> names = "ABCDEFGHIJKLM" +>>> sets = [disjointSet(name) for name in names] +>>> roots = sets[:] + +>>> import random +>>> gen = random.WichmannHill(42) +>>> while 1: +... for s in sets: +... print "%s->%s" % (s, s.find()), +... print +... if len(roots) > 1: +... s1 = gen.choice(roots) +... roots.remove(s1) +... s2 = gen.choice(roots) +... s1.union(s2) +... print "merged", s1, "into", s2 +... else: +... break +A->A B->B C->C D->D E->E F->F G->G H->H I->I J->J K->K L->L M->M +merged D into G +A->A B->B C->C D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M +merged C into F +A->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M +merged L into A +A->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->A M->M +merged H into E +A->A B->B C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M +merged B into E +A->A B->E C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M +merged J into G +A->A B->E C->F D->G E->E F->F G->G H->E I->I J->G K->K L->A M->M +merged E into G +A->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->M +merged M into G +A->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->G +merged I into K +A->A B->G C->F D->G E->G F->F G->G H->G I->K J->G K->K L->A M->G +merged K into A +A->A B->G C->F D->G E->G F->F G->G H->G I->A J->G K->A L->A M->G +merged F into A +A->A B->G C->A D->G E->G F->A G->G H->G I->A J->G K->A L->A M->G +merged A into G +A->G B->G C->G D->G E->G F->G G->G H->G I->G J->G K->G L->G M->G + +""" +# Emacs turd ' + +# Fun tests (for sufficiently warped notions of "fun"). + +fun_tests = """ + +Build up to a recursive Sieve of Eratosthenes generator. + +>>> def firstn(g, n): +... return [g.next() for i in range(n)] + +>>> def intsfrom(i): +... while 1: +... yield i +... i += 1 + +>>> firstn(intsfrom(5), 7) +[5, 6, 7, 8, 9, 10, 11] + +>>> def exclude_multiples(n, ints): +... for i in ints: +... if i % n: +... yield i + +>>> firstn(exclude_multiples(3, intsfrom(1)), 6) +[1, 2, 4, 5, 7, 8] + +>>> def sieve(ints): +... prime = ints.next() +... yield prime +... not_divisible_by_prime = exclude_multiples(prime, ints) +... for p in sieve(not_divisible_by_prime): +... yield p + +>>> primes = sieve(intsfrom(2)) +>>> firstn(primes, 20) +[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71] + + +Another famous problem: generate all integers of the form + 2**i * 3**j * 5**k +in increasing order, where i,j,k >= 0. Trickier than it may look at first! +Try writing it without generators, and correctly, and without generating +3 internal results for each result output. + +>>> def times(n, g): +... for i in g: +... yield n * i +>>> firstn(times(10, intsfrom(1)), 10) +[10, 20, 30, 40, 50, 60, 70, 80, 90, 100] + +>>> def merge(g, h): +... ng = g.next() +... nh = h.next() +... while 1: +... if ng < nh: +... yield ng +... ng = g.next() +... elif ng > nh: +... yield nh +... nh = h.next() +... else: +... yield ng +... ng = g.next() +... nh = h.next() + +The following works, but is doing a whale of a lot of redundant work -- +it's not clear how to get the internal uses of m235 to share a single +generator. Note that me_times2 (etc) each need to see every element in the +result sequence. So this is an example where lazy lists are more natural +(you can look at the head of a lazy list any number of times). + +>>> def m235(): +... yield 1 +... me_times2 = times(2, m235()) +... me_times3 = times(3, m235()) +... me_times5 = times(5, m235()) +... for i in merge(merge(me_times2, +... me_times3), +... me_times5): +... yield i + +Don't print "too many" of these -- the implementation above is extremely +inefficient: each call of m235() leads to 3 recursive calls, and in +turn each of those 3 more, and so on, and so on, until we've descended +enough levels to satisfy the print stmts. Very odd: when I printed 5 +lines of results below, this managed to screw up Win98's malloc in "the +usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting +address space, and it *looked* like a very slow leak. + +>>> result = m235() +>>> for i in range(3): +... print firstn(result, 15) +[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24] +[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80] +[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192] + +Heh. Here's one way to get a shared list, complete with an excruciating +namespace renaming trick. The *pretty* part is that the times() and merge() +functions can be reused as-is, because they only assume their stream +arguments are iterable -- a LazyList is the same as a generator to times(). + +>>> class LazyList: +... def __init__(self, g): +... self.sofar = [] +... self.fetch = g.next +... +... def __getitem__(self, i): +... sofar, fetch = self.sofar, self.fetch +... while i >= len(sofar): +... sofar.append(fetch()) +... return sofar[i] + +>>> def m235(): +... yield 1 +... # Gack: m235 below actually refers to a LazyList. +... me_times2 = times(2, m235) +... me_times3 = times(3, m235) +... me_times5 = times(5, m235) +... for i in merge(merge(me_times2, +... me_times3), +... me_times5): +... yield i + +Print as many of these as you like -- *this* implementation is memory- +efficient. + +>>> m235 = LazyList(m235()) +>>> for i in range(5): +... print [m235[j] for j in range(15*i, 15*(i+1))] +[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24] +[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80] +[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192] +[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384] +[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675] + +Ye olde Fibonacci generator, LazyList style. + +>>> def fibgen(a, b): +... +... def sum(g, h): +... while 1: +... yield g.next() + h.next() +... +... def tail(g): +... g.next() # throw first away +... for x in g: +... yield x +... +... yield a +... yield b +... for s in sum(iter(fib), +... tail(iter(fib))): +... yield s + +>>> fib = LazyList(fibgen(1, 2)) +>>> firstn(iter(fib), 17) +[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584] + + +Running after your tail with itertools.tee (new in version 2.4) + +The algorithms "m235" (Hamming) and Fibonacci presented above are both +examples of a whole family of FP (functional programming) algorithms +where a function produces and returns a list while the production algorithm +suppose the list as already produced by recursively calling itself. +For these algorithms to work, they must: + +- produce at least a first element without presupposing the existence of + the rest of the list +- produce their elements in a lazy manner + +To work efficiently, the beginning of the list must not be recomputed over +and over again. This is ensured in most FP languages as a built-in feature. +In python, we have to explicitly maintain a list of already computed results +and abandon genuine recursivity. + +This is what had been attempted above with the LazyList class. One problem +with that class is that it keeps a list of all of the generated results and +therefore continually grows. This partially defeats the goal of the generator +concept, viz. produce the results only as needed instead of producing them +all and thereby wasting memory. + +Thanks to itertools.tee, it is now clear "how to get the internal uses of +m235 to share a single generator". + +>>> from itertools import tee +>>> def m235(): +... def _m235(): +... yield 1 +... for n in merge(times(2, m2), +... merge(times(3, m3), +... times(5, m5))): +... yield n +... m1 = _m235() +... m2, m3, m5, mRes = tee(m1, 4) +... return mRes + +>>> it = m235() +>>> for i in range(5): +... print firstn(it, 15) +[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24] +[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80] +[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192] +[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384] +[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675] + +The "tee" function does just what we want. It internally keeps a generated +result for as long as it has not been "consumed" from all of the duplicated +iterators, whereupon it is deleted. You can therefore print the hamming +sequence during hours without increasing memory usage, or very little. + +The beauty of it is that recursive running-after-their-tail FP algorithms +are quite straightforwardly expressed with this Python idiom. + +Ye olde Fibonacci generator, tee style. + +>>> def fib(): +... +... def _isum(g, h): +... while 1: +... yield g.next() + h.next() +... +... def _fib(): +... yield 1 +... yield 2 +... fibTail.next() # throw first away +... for res in _isum(fibHead, fibTail): +... yield res +... +... realfib = _fib() +... fibHead, fibTail, fibRes = tee(realfib, 3) +... return fibRes + +>>> firstn(fib(), 17) +[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584] + +""" + +# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0 +# hackery. + +syntax_tests = """ + +>>> def f(): +... return 22 +... yield 1 +Traceback (most recent call last): + .. +SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 3) + +>>> def f(): +... yield 1 +... return 22 +Traceback (most recent call last): + .. +SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[1]>, line 3) + +"return None" is not the same as "return" in a generator: + +>>> def f(): +... yield 1 +... return None +Traceback (most recent call last): + .. +SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3) + +These are fine: + +>>> def f(): +... yield 1 +... return + +>>> def f(): +... try: +... yield 1 +... finally: +... pass + +>>> def f(): +... try: +... try: +... 1//0 +... except ZeroDivisionError: +... yield 666 +... except: +... pass +... finally: +... pass + +>>> def f(): +... try: +... try: +... yield 12 +... 1//0 +... except ZeroDivisionError: +... yield 666 +... except: +... try: +... x = 12 +... finally: +... yield 12 +... except: +... return +>>> list(f()) +[12, 666] + +>>> def f(): +... yield +>>> type(f()) +<type 'generator'> + + +>>> def f(): +... if 0: +... yield +>>> type(f()) +<type 'generator'> + + +>>> def f(): +... if 0: +... yield 1 +>>> type(f()) +<type 'generator'> + +>>> def f(): +... if "": +... yield None +>>> type(f()) +<type 'generator'> + +>>> def f(): +... return +... try: +... if x==4: +... pass +... elif 0: +... try: +... 1//0 +... except SyntaxError: +... pass +... else: +... if 0: +... while 12: +... x += 1 +... yield 2 # don't blink +... f(a, b, c, d, e) +... else: +... pass +... except: +... x = 1 +... return +>>> type(f()) +<type 'generator'> + +>>> def f(): +... if 0: +... def g(): +... yield 1 +... +>>> type(f()) +<type 'NoneType'> + +>>> def f(): +... if 0: +... class C: +... def __init__(self): +... yield 1 +... def f(self): +... yield 2 +>>> type(f()) +<type 'NoneType'> + +>>> def f(): +... if 0: +... return +... if 0: +... yield 2 +>>> type(f()) +<type 'generator'> + + +>>> def f(): +... if 0: +... lambda x: x # shouldn't trigger here +... return # or here +... def f(i): +... return 2*i # or here +... if 0: +... return 3 # but *this* sucks (line 8) +... if 0: +... yield 2 # because it's a generator (line 10) +Traceback (most recent call last): +SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 10) + +This one caused a crash (see SF bug 567538): + +>>> def f(): +... for i in range(3): +... try: +... continue +... finally: +... yield i +... +>>> g = f() +>>> print g.next() +0 +>>> print g.next() +1 +>>> print g.next() +2 +>>> print g.next() +Traceback (most recent call last): +StopIteration +""" + +# conjoin is a simple backtracking generator, named in honor of Icon's +# "conjunction" control structure. Pass a list of no-argument functions +# that return iterable objects. Easiest to explain by example: assume the +# function list [x, y, z] is passed. Then conjoin acts like: +# +# def g(): +# values = [None] * 3 +# for values[0] in x(): +# for values[1] in y(): +# for values[2] in z(): +# yield values +# +# So some 3-lists of values *may* be generated, each time we successfully +# get into the innermost loop. If an iterator fails (is exhausted) before +# then, it "backtracks" to get the next value from the nearest enclosing +# iterator (the one "to the left"), and starts all over again at the next +# slot (pumps a fresh iterator). Of course this is most useful when the +# iterators have side-effects, so that which values *can* be generated at +# each slot depend on the values iterated at previous slots. + +def conjoin(gs): + + values = [None] * len(gs) + + def gen(i, values=values): + if i >= len(gs): + yield values + else: + for values[i] in gs[i](): + for x in gen(i+1): + yield x + + for x in gen(0): + yield x + +# That works fine, but recursing a level and checking i against len(gs) for +# each item produced is inefficient. By doing manual loop unrolling across +# generator boundaries, it's possible to eliminate most of that overhead. +# This isn't worth the bother *in general* for generators, but conjoin() is +# a core building block for some CPU-intensive generator applications. + +def conjoin(gs): + + n = len(gs) + values = [None] * n + + # Do one loop nest at time recursively, until the # of loop nests + # remaining is divisible by 3. + + def gen(i, values=values): + if i >= n: + yield values + + elif (n-i) % 3: + ip1 = i+1 + for values[i] in gs[i](): + for x in gen(ip1): + yield x + + else: + for x in _gen3(i): + yield x + + # Do three loop nests at a time, recursing only if at least three more + # remain. Don't call directly: this is an internal optimization for + # gen's use. + + def _gen3(i, values=values): + assert i < n and (n-i) % 3 == 0 + ip1, ip2, ip3 = i+1, i+2, i+3 + g, g1, g2 = gs[i : ip3] + + if ip3 >= n: + # These are the last three, so we can yield values directly. + for values[i] in g(): + for values[ip1] in g1(): + for values[ip2] in g2(): + yield values + + else: + # At least 6 loop nests remain; peel off 3 and recurse for the + # rest. + for values[i] in g(): + for values[ip1] in g1(): + for values[ip2] in g2(): + for x in _gen3(ip3): + yield x + + for x in gen(0): + yield x + +# And one more approach: For backtracking apps like the Knight's Tour +# solver below, the number of backtracking levels can be enormous (one +# level per square, for the Knight's Tour, so that e.g. a 100x100 board +# needs 10,000 levels). In such cases Python is likely to run out of +# stack space due to recursion. So here's a recursion-free version of +# conjoin too. +# NOTE WELL: This allows large problems to be solved with only trivial +# demands on stack space. Without explicitly resumable generators, this is +# much harder to achieve. OTOH, this is much slower (up to a factor of 2) +# than the fancy unrolled recursive conjoin. + +def flat_conjoin(gs): # rename to conjoin to run tests with this instead + n = len(gs) + values = [None] * n + iters = [None] * n + _StopIteration = StopIteration # make local because caught a *lot* + i = 0 + while 1: + # Descend. + try: + while i < n: + it = iters[i] = gs[i]().next + values[i] = it() + i += 1 + except _StopIteration: + pass + else: + assert i == n + yield values + + # Backtrack until an older iterator can be resumed. + i -= 1 + while i >= 0: + try: + values[i] = iters[i]() + # Success! Start fresh at next level. + i += 1 + break + except _StopIteration: + # Continue backtracking. + i -= 1 + else: + assert i < 0 + break + +# A conjoin-based N-Queens solver. + +class Queens: + def __init__(self, n): + self.n = n + rangen = range(n) + + # Assign a unique int to each column and diagonal. + # columns: n of those, range(n). + # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along + # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0- + # based. + # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along + # each, smallest i+j is 0, largest is 2n-2. + + # For each square, compute a bit vector of the columns and + # diagonals it covers, and for each row compute a function that + # generates the possiblities for the columns in that row. + self.rowgenerators = [] + for i in rangen: + rowuses = [(1L << j) | # column ordinal + (1L << (n + i-j + n-1)) | # NW-SE ordinal + (1L << (n + 2*n-1 + i+j)) # NE-SW ordinal + for j in rangen] + + def rowgen(rowuses=rowuses): + for j in rangen: + uses = rowuses[j] + if uses & self.used == 0: + self.used |= uses + yield j + self.used &= ~uses + + self.rowgenerators.append(rowgen) + + # Generate solutions. + def solve(self): + self.used = 0 + for row2col in conjoin(self.rowgenerators): + yield row2col + + def printsolution(self, row2col): + n = self.n + assert n == len(row2col) + sep = "+" + "-+" * n + print sep + for i in range(n): + squares = [" " for j in range(n)] + squares[row2col[i]] = "Q" + print "|" + "|".join(squares) + "|" + print sep + +# A conjoin-based Knight's Tour solver. This is pretty sophisticated +# (e.g., when used with flat_conjoin above, and passing hard=1 to the +# constructor, a 200x200 Knight's Tour was found quickly -- note that we're +# creating 10s of thousands of generators then!), and is lengthy. + +class Knights: + def __init__(self, m, n, hard=0): + self.m, self.n = m, n + + # solve() will set up succs[i] to be a list of square #i's + # successors. + succs = self.succs = [] + + # Remove i0 from each of its successor's successor lists, i.e. + # successors can't go back to i0 again. Return 0 if we can + # detect this makes a solution impossible, else return 1. + + def remove_from_successors(i0, len=len): + # If we remove all exits from a free square, we're dead: + # even if we move to it next, we can't leave it again. + # If we create a square with one exit, we must visit it next; + # else somebody else will have to visit it, and since there's + # only one adjacent, there won't be a way to leave it again. + # Finelly, if we create more than one free square with a + # single exit, we can only move to one of them next, leaving + # the other one a dead end. + ne0 = ne1 = 0 + for i in succs[i0]: + s = succs[i] + s.remove(i0) + e = len(s) + if e == 0: + ne0 += 1 + elif e == 1: + ne1 += 1 + return ne0 == 0 and ne1 < 2 + + # Put i0 back in each of its successor's successor lists. + + def add_to_successors(i0): + for i in succs[i0]: + succs[i].append(i0) + + # Generate the first move. + def first(): + if m < 1 or n < 1: + return + + # Since we're looking for a cycle, it doesn't matter where we + # start. Starting in a corner makes the 2nd move easy. + corner = self.coords2index(0, 0) + remove_from_successors(corner) + self.lastij = corner + yield corner + add_to_successors(corner) + + # Generate the second moves. + def second(): + corner = self.coords2index(0, 0) + assert self.lastij == corner # i.e., we started in the corner + if m < 3 or n < 3: + return + assert len(succs[corner]) == 2 + assert self.coords2index(1, 2) in succs[corner] + assert self.coords2index(2, 1) in succs[corner] + # Only two choices. Whichever we pick, the other must be the + # square picked on move m*n, as it's the only way to get back + # to (0, 0). Save its index in self.final so that moves before + # the last know it must be kept free. + for i, j in (1, 2), (2, 1): + this = self.coords2index(i, j) + final = self.coords2index(3-i, 3-j) + self.final = final + + remove_from_successors(this) + succs[final].append(corner) + self.lastij = this + yield this + succs[final].remove(corner) + add_to_successors(this) + + # Generate moves 3 thru m*n-1. + def advance(len=len): + # If some successor has only one exit, must take it. + # Else favor successors with fewer exits. + candidates = [] + for i in succs[self.lastij]: + e = len(succs[i]) + assert e > 0, "else remove_from_successors() pruning flawed" + if e == 1: + candidates = [(e, i)] + break + candidates.append((e, i)) + else: + candidates.sort() + + for e, i in candidates: + if i != self.final: + if remove_from_successors(i): + self.lastij = i + yield i + add_to_successors(i) + + # Generate moves 3 thru m*n-1. Alternative version using a + # stronger (but more expensive) heuristic to order successors. + # Since the # of backtracking levels is m*n, a poor move early on + # can take eons to undo. Smallest square board for which this + # matters a lot is 52x52. + def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len): + # If some successor has only one exit, must take it. + # Else favor successors with fewer exits. + # Break ties via max distance from board centerpoint (favor + # corners and edges whenever possible). + candidates = [] + for i in succs[self.lastij]: + e = len(succs[i]) + assert e > 0, "else remove_from_successors() pruning flawed" + if e == 1: + candidates = [(e, 0, i)] + break + i1, j1 = self.index2coords(i) + d = (i1 - vmid)**2 + (j1 - hmid)**2 + candidates.append((e, -d, i)) + else: + candidates.sort() + + for e, d, i in candidates: + if i != self.final: + if remove_from_successors(i): + self.lastij = i + yield i + add_to_successors(i) + + # Generate the last move. + def last(): + assert self.final in succs[self.lastij] + yield self.final + + if m*n < 4: + self.squaregenerators = [first] + else: + self.squaregenerators = [first, second] + \ + [hard and advance_hard or advance] * (m*n - 3) + \ + [last] + + def coords2index(self, i, j): + assert 0 <= i < self.m + assert 0 <= j < self.n + return i * self.n + j + + def index2coords(self, index): + assert 0 <= index < self.m * self.n + return divmod(index, self.n) + + def _init_board(self): + succs = self.succs + del succs[:] + m, n = self.m, self.n + c2i = self.coords2index + + offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2), + (-1, -2), (-2, -1), (-2, 1), (-1, 2)] + rangen = range(n) + for i in range(m): + for j in rangen: + s = [c2i(i+io, j+jo) for io, jo in offsets + if 0 <= i+io < m and + 0 <= j+jo < n] + succs.append(s) + + # Generate solutions. + def solve(self): + self._init_board() + for x in conjoin(self.squaregenerators): + yield x + + def printsolution(self, x): + m, n = self.m, self.n + assert len(x) == m*n + w = len(str(m*n)) + format = "%" + str(w) + "d" + + squares = [[None] * n for i in range(m)] + k = 1 + for i in x: + i1, j1 = self.index2coords(i) + squares[i1][j1] = format % k + k += 1 + + sep = "+" + ("-" * w + "+") * n + print sep + for i in range(m): + row = squares[i] + print "|" + "|".join(row) + "|" + print sep + +conjoin_tests = """ + +Generate the 3-bit binary numbers in order. This illustrates dumbest- +possible use of conjoin, just to generate the full cross-product. + +>>> for c in conjoin([lambda: iter((0, 1))] * 3): +... print c +[0, 0, 0] +[0, 0, 1] +[0, 1, 0] +[0, 1, 1] +[1, 0, 0] +[1, 0, 1] +[1, 1, 0] +[1, 1, 1] + +For efficiency in typical backtracking apps, conjoin() yields the same list +object each time. So if you want to save away a full account of its +generated sequence, you need to copy its results. + +>>> def gencopy(iterator): +... for x in iterator: +... yield x[:] + +>>> for n in range(10): +... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n))) +... print n, len(all), all[0] == [0] * n, all[-1] == [1] * n +0 1 True True +1 2 True True +2 4 True True +3 8 True True +4 16 True True +5 32 True True +6 64 True True +7 128 True True +8 256 True True +9 512 True True + +And run an 8-queens solver. + +>>> q = Queens(8) +>>> LIMIT = 2 +>>> count = 0 +>>> for row2col in q.solve(): +... count += 1 +... if count <= LIMIT: +... print "Solution", count +... q.printsolution(row2col) +Solution 1 ++-+-+-+-+-+-+-+-+ +|Q| | | | | | | | ++-+-+-+-+-+-+-+-+ +| | | | |Q| | | | ++-+-+-+-+-+-+-+-+ +| | | | | | | |Q| ++-+-+-+-+-+-+-+-+ +| | | | | |Q| | | ++-+-+-+-+-+-+-+-+ +| | |Q| | | | | | ++-+-+-+-+-+-+-+-+ +| | | | | | |Q| | ++-+-+-+-+-+-+-+-+ +| |Q| | | | | | | ++-+-+-+-+-+-+-+-+ +| | | |Q| | | | | ++-+-+-+-+-+-+-+-+ +Solution 2 ++-+-+-+-+-+-+-+-+ +|Q| | | | | | | | ++-+-+-+-+-+-+-+-+ +| | | | | |Q| | | ++-+-+-+-+-+-+-+-+ +| | | | | | | |Q| ++-+-+-+-+-+-+-+-+ +| | |Q| | | | | | ++-+-+-+-+-+-+-+-+ +| | | | | | |Q| | ++-+-+-+-+-+-+-+-+ +| | | |Q| | | | | ++-+-+-+-+-+-+-+-+ +| |Q| | | | | | | ++-+-+-+-+-+-+-+-+ +| | | | |Q| | | | ++-+-+-+-+-+-+-+-+ + +>>> print count, "solutions in all." +92 solutions in all. + +And run a Knight's Tour on a 10x10 board. Note that there are about +20,000 solutions even on a 6x6 board, so don't dare run this to exhaustion. + +>>> k = Knights(10, 10) +>>> LIMIT = 2 +>>> count = 0 +>>> for x in k.solve(): +... count += 1 +... if count <= LIMIT: +... print "Solution", count +... k.printsolution(x) +... else: +... break +Solution 1 ++---+---+---+---+---+---+---+---+---+---+ +| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8| ++---+---+---+---+---+---+---+---+---+---+ +| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11| ++---+---+---+---+---+---+---+---+---+---+ +| 59|100| 73| 36| 41| 56| 39| 32| 9| 6| ++---+---+---+---+---+---+---+---+---+---+ +| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31| ++---+---+---+---+---+---+---+---+---+---+ +| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50| ++---+---+---+---+---+---+---+---+---+---+ +| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13| ++---+---+---+---+---+---+---+---+---+---+ +| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44| ++---+---+---+---+---+---+---+---+---+---+ +| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17| ++---+---+---+---+---+---+---+---+---+---+ +| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66| ++---+---+---+---+---+---+---+---+---+---+ +| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15| ++---+---+---+---+---+---+---+---+---+---+ +Solution 2 ++---+---+---+---+---+---+---+---+---+---+ +| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8| ++---+---+---+---+---+---+---+---+---+---+ +| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11| ++---+---+---+---+---+---+---+---+---+---+ +| 59|100| 73| 36| 41| 56| 39| 32| 9| 6| ++---+---+---+---+---+---+---+---+---+---+ +| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31| ++---+---+---+---+---+---+---+---+---+---+ +| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50| ++---+---+---+---+---+---+---+---+---+---+ +| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13| ++---+---+---+---+---+---+---+---+---+---+ +| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44| ++---+---+---+---+---+---+---+---+---+---+ +| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17| ++---+---+---+---+---+---+---+---+---+---+ +| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66| ++---+---+---+---+---+---+---+---+---+---+ +| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15| ++---+---+---+---+---+---+---+---+---+---+ +""" + +weakref_tests = """\ +Generators are weakly referencable: + +>>> import weakref +>>> def gen(): +... yield 'foo!' +... +>>> wr = weakref.ref(gen) +>>> wr() is gen +True +>>> p = weakref.proxy(gen) + +Generator-iterators are weakly referencable as well: + +>>> gi = gen() +>>> wr = weakref.ref(gi) +>>> wr() is gi +True +>>> p = weakref.proxy(gi) +>>> list(p) +['foo!'] + +""" + +coroutine_tests = """\ +Sending a value into a started generator: + +>>> def f(): +... print (yield 1) +... yield 2 +>>> g = f() +>>> g.next() +1 +>>> g.send(42) +42 +2 + +Sending a value into a new generator produces a TypeError: + +>>> f().send("foo") +Traceback (most recent call last): +... +TypeError: can't send non-None value to a just-started generator + + +Yield by itself yields None: + +>>> def f(): yield +>>> list(f()) +[None] + + + +An obscene abuse of a yield expression within a generator expression: + +>>> list((yield 21) for i in range(4)) +[21, None, 21, None, 21, None, 21, None] + +And a more sane, but still weird usage: + +>>> def f(): list(i for i in [(yield 26)]) +>>> type(f()) +<type 'generator'> + + +A yield expression with augmented assignment. + +>>> def coroutine(seq): +... count = 0 +... while count < 200: +... count += yield +... seq.append(count) +>>> seq = [] +>>> c = coroutine(seq) +>>> c.next() +>>> print seq +[] +>>> c.send(10) +>>> print seq +[10] +>>> c.send(10) +>>> print seq +[10, 20] +>>> c.send(10) +>>> print seq +[10, 20, 30] + + +Check some syntax errors for yield expressions: + +>>> f=lambda: (yield 1),(yield 2) +Traceback (most recent call last): + ... +SyntaxError: 'yield' outside function (<doctest test.test_generators.__test__.coroutine[21]>, line 1) + +>>> def f(): return lambda x=(yield): 1 +Traceback (most recent call last): + ... +SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.coroutine[22]>, line 1) + +>>> def f(): x = yield = y +Traceback (most recent call last): + ... +SyntaxError: assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[23]>, line 1) + +>>> def f(): (yield bar) = y +Traceback (most recent call last): + ... +SyntaxError: can't assign to yield expression (<doctest test.test_generators.__test__.coroutine[24]>, line 1) + +>>> def f(): (yield bar) += y +Traceback (most recent call last): + ... +SyntaxError: augmented assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[25]>, line 1) + + +Now check some throw() conditions: + +>>> def f(): +... while True: +... try: +... print (yield) +... except ValueError,v: +... print "caught ValueError (%s)" % (v), +>>> import sys +>>> g = f() +>>> g.next() + +>>> g.throw(ValueError) # type only +caught ValueError () + +>>> g.throw(ValueError("xyz")) # value only +caught ValueError (xyz) + +>>> g.throw(ValueError, ValueError(1)) # value+matching type +caught ValueError (1) + +>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped +caught ValueError (1) + +>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback +caught ValueError (1) + +>>> g.throw(ValueError(1), "foo") # bad args +Traceback (most recent call last): + ... +TypeError: instance exception may not have a separate value + +>>> g.throw(ValueError, "foo", 23) # bad args +Traceback (most recent call last): + ... +TypeError: throw() third argument must be a traceback object + +>>> def throw(g,exc): +... try: +... raise exc +... except: +... g.throw(*sys.exc_info()) +>>> throw(g,ValueError) # do it with traceback included +caught ValueError () + +>>> g.send(1) +1 + +>>> throw(g,TypeError) # terminate the generator +Traceback (most recent call last): + ... +TypeError + +>>> print g.gi_frame +None + +>>> g.send(2) +Traceback (most recent call last): + ... +StopIteration + +>>> g.throw(ValueError,6) # throw on closed generator +Traceback (most recent call last): + ... +ValueError: 6 + +>>> f().throw(ValueError,7) # throw on just-opened generator +Traceback (most recent call last): + ... +ValueError: 7 + +>>> f().throw("abc") # throw on just-opened generator +Traceback (most recent call last): + ... +abc + +Now let's try closing a generator: + +>>> def f(): +... try: yield +... except GeneratorExit: +... print "exiting" + +>>> g = f() +>>> g.next() +>>> g.close() +exiting +>>> g.close() # should be no-op now + +>>> f().close() # close on just-opened generator should be fine + +>>> def f(): yield # an even simpler generator +>>> f().close() # close before opening +>>> g = f() +>>> g.next() +>>> g.close() # close normally + +And finalization: + +>>> def f(): +... try: yield +... finally: +... print "exiting" + +>>> g = f() +>>> g.next() +>>> del g +exiting + + +Now let's try some ill-behaved generators: + +>>> def f(): +... try: yield +... except GeneratorExit: +... yield "foo!" +>>> g = f() +>>> g.next() +>>> g.close() +Traceback (most recent call last): + ... +RuntimeError: generator ignored GeneratorExit +>>> g.close() + + +Our ill-behaved code should be invoked during GC: + +>>> import sys, StringIO +>>> old, sys.stderr = sys.stderr, StringIO.StringIO() +>>> g = f() +>>> g.next() +>>> del g +>>> sys.stderr.getvalue().startswith( +... "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in " +... ) +True +>>> sys.stderr = old + + +And errors thrown during closing should propagate: + +>>> def f(): +... try: yield +... except GeneratorExit: +... raise TypeError("fie!") +>>> g = f() +>>> g.next() +>>> g.close() +Traceback (most recent call last): + ... +TypeError: fie! + + +Ensure that various yield expression constructs make their +enclosing function a generator: + +>>> def f(): x += yield +>>> type(f()) +<type 'generator'> + +>>> def f(): x = yield +>>> type(f()) +<type 'generator'> + +>>> def f(): lambda x=(yield): 1 +>>> type(f()) +<type 'generator'> + +>>> def f(): x=(i for i in (yield) if (yield)) +>>> type(f()) +<type 'generator'> + +>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27 +>>> data = [1,2] +>>> g = f(data) +>>> type(g) +<type 'generator'> +>>> g.send(None) +'a' +>>> data +[1, 2] +>>> g.send(0) +'b' +>>> data +[27, 2] +>>> try: g.send(1) +... except StopIteration: pass +>>> data +[27, 27] + +""" + +refleaks_tests = """ +Prior to adding cycle-GC support to itertools.tee, this code would leak +references. We add it to the standard suite so the routine refleak-tests +would trigger if it starts being uncleanable again. + +>>> import itertools +>>> def leak(): +... class gen: +... def __iter__(self): +... return self +... def next(self): +... return self.item +... g = gen() +... head, tail = itertools.tee(g) +... g.item = head +... return head +>>> it = leak() + +Make sure to also test the involvement of the tee-internal teedataobject, +which stores returned items. + +>>> item = it.next() + + + +This test leaked at one point due to generator finalization/destruction. +It was copied from Lib/test/leakers/test_generator_cycle.py before the file +was removed. + +>>> def leak(): +... def gen(): +... while True: +... yield g +... g = gen() + +>>> leak() + + + +This test isn't really generator related, but rather exception-in-cleanup +related. The coroutine tests (above) just happen to cause an exception in +the generator's __del__ (tp_del) method. We can also test for this +explicitly, without generators. We do have to redirect stderr to avoid +printing warnings and to doublecheck that we actually tested what we wanted +to test. + +>>> import sys, StringIO +>>> old = sys.stderr +>>> try: +... sys.stderr = StringIO.StringIO() +... class Leaker: +... def __del__(self): +... raise RuntimeError +... +... l = Leaker() +... del l +... err = sys.stderr.getvalue().strip() +... err.startswith( +... "Exception exceptions.RuntimeError: RuntimeError() in <" +... ) +... err.endswith("> ignored") +... len(err.splitlines()) +... finally: +... sys.stderr = old +True +True +1 + + + +These refleak tests should perhaps be in a testfile of their own, +test_generators just happened to be the test that drew these out. + +""" + +__test__ = {"tut": tutorial_tests, + "pep": pep_tests, + "email": email_tests, + "fun": fun_tests, + "syntax": syntax_tests, + "conjoin": conjoin_tests, + "weakref": weakref_tests, + "coroutine": coroutine_tests, + "refleaks": refleaks_tests, + } + +# Magic test name that regrtest.py invokes *after* importing this module. +# This worms around a bootstrap problem. +# Note that doctest and regrtest both look in sys.argv for a "-v" argument, +# so this works as expected in both ways of running regrtest. +def test_main(verbose=None): + from test import test_support, test_generators + test_support.run_doctest(test_generators, verbose) + +# This part isn't needed for regrtest, but for running the test directly. +if __name__ == "__main__": + test_main(1) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2008-08-11 03:17:47
|
Revision: 5142 http://jython.svn.sourceforge.net/jython/?rev=5142&view=rev Author: zyasoft Date: 2008-08-11 03:17:44 +0000 (Mon, 11 Aug 2008) Log Message: ----------- Commented out inappropriate doctest in test_genexps that tested for the reuse of memory objects. This obviously doesn't apply to Jython and other nonrefcounted implementations. Fixes test_genexps Modified Paths: -------------- branches/asm/Lib/test/test_genexps.py Modified: branches/asm/Lib/test/test_genexps.py =================================================================== --- branches/asm/Lib/test/test_genexps.py 2008-08-11 02:56:53 UTC (rev 5141) +++ branches/asm/Lib/test/test_genexps.py 2008-08-11 03:17:44 UTC (rev 5142) @@ -133,12 +133,13 @@ >>> list(g) [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] -Verify re-use of tuples (a side benefit of using genexps over listcomps) +This doesn't make sense for Jython or other non refcounted implementations +# Verify re-use of tuples (a side benefit of using genexps over listcomps) +# +# >>> tupleids = map(id, ((i,i) for i in xrange(10))) +# >>> int(max(tupleids) - min(tupleids)) +# 0 - >>> tupleids = map(id, ((i,i) for i in xrange(10))) - >>> int(max(tupleids) - min(tupleids)) - 0 - Verify that syntax error's are raised for genexps used as lvalues >>> (y for y in (1,2)) = 10 #doctest: +IGNORE_EXCEPTION_DETAIL This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2008-08-11 02:56:55
|
Revision: 5141 http://jython.svn.sourceforge.net/jython/?rev=5141&view=rev Author: zyasoft Date: 2008-08-11 02:56:53 +0000 (Mon, 11 Aug 2008) Log Message: ----------- from X import * now raises the appropriate syntax errors (for nested scopes) or warning (otherwise). Modified Paths: -------------- branches/asm/src/org/python/compiler/CodeCompiler.java branches/asm/src/org/python/compiler/ScopeInfo.java Modified: branches/asm/src/org/python/compiler/CodeCompiler.java =================================================================== --- branches/asm/src/org/python/compiler/CodeCompiler.java 2008-08-11 00:32:24 UTC (rev 5140) +++ branches/asm/src/org/python/compiler/CodeCompiler.java 2008-08-11 02:56:53 UTC (rev 5141) @@ -768,6 +768,23 @@ code.ldc(node.module); //Note: parser does not allow node.names.length == 0 if (node.names.length == 1 && node.names[0].name.equals("*")) { + if (my_scope.func_level > 0) { + module.error("import * only allowed at module level", false, node); + + if (my_scope.contains_ns_free_vars) { + module.error("import * is not allowed in function '" + + my_scope.scope_name + + "' because it contains a nested function with free variables", + true, node); + } + } + if (my_scope.func_level > 1) { + module.error("import * is not allowed in function '" + + my_scope.scope_name + + "' because it is a nested function", + true, node); + } + loadFrame(); code.invokestatic("org/python/core/imp", "importAll", "(" + $str + $pyFrame + ")V"); } else { Modified: branches/asm/src/org/python/compiler/ScopeInfo.java =================================================================== --- branches/asm/src/org/python/compiler/ScopeInfo.java 2008-08-11 00:32:24 UTC (rev 5140) +++ branches/asm/src/org/python/compiler/ScopeInfo.java 2008-08-11 02:56:53 UTC (rev 5141) @@ -52,6 +52,7 @@ public boolean unqual_exec; public boolean exec; public boolean from_import_star; + public boolean contains_ns_free_vars; public boolean generator; public int yield_count; public int max_with_count; @@ -179,6 +180,12 @@ names.addElement(purecells.elementAt(i)); } } + + if (some_free && nested) { + up.contains_ns_free_vars = true; + } + // XXX - this doesn't catch all cases - may depend subtly + // on how visiting NOW works with antlr compared to javacc if ((unqual_exec || from_import_star)) { if(some_inner_free) dynastuff_trouble(true, ctxt); else if(func_level > 1 && some_free) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2008-08-11 00:32:27
|
Revision: 5140 http://jython.svn.sourceforge.net/jython/?rev=5140&view=rev Author: fwierzbicki Date: 2008-08-11 00:32:24 +0000 (Mon, 11 Aug 2008) Log Message: ----------- Can't assign to Num and better placement for checkAssign, so lambdef and fplist also get checks for args. Modified Paths: -------------- branches/asm/grammar/PythonWalker.g branches/asm/src/org/python/antlr/GrammarActions.java Modified: branches/asm/grammar/PythonWalker.g =================================================================== --- branches/asm/grammar/PythonWalker.g 2008-08-10 23:14:13 UTC (rev 5139) +++ branches/asm/grammar/PythonWalker.g 2008-08-11 00:32:24 UTC (rev 5140) @@ -171,7 +171,6 @@ defparameter[List params, List defaults] : fpdef[expr_contextType.Param, null] (ASSIGN test[expr_contextType.Load])? { - actions.checkAssign($fpdef.etype); params.add($fpdef.etype); if ($ASSIGN != null) { defaults.add($test.etype); @@ -186,6 +185,7 @@ fpdef [expr_contextType ctype, List nms] returns [exprType etype] : NAME { exprType e = new Name($NAME, $NAME.text, ctype); + actions.checkAssign(e); if (nms == null) { $etype = e; } else { Modified: branches/asm/src/org/python/antlr/GrammarActions.java =================================================================== --- branches/asm/src/org/python/antlr/GrammarActions.java 2008-08-10 23:14:13 UTC (rev 5139) +++ branches/asm/src/org/python/antlr/GrammarActions.java 2008-08-11 00:32:24 UTC (rev 5140) @@ -458,6 +458,8 @@ throw new ParseException("assignment to None", e); } else if (e instanceof GeneratorExp) { throw new ParseException("can't assign to generator expression", e); + } else if (e instanceof Num) { + throw new ParseException("can't assign to number", e); } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2008-08-10 23:14:16
|
Revision: 5139 http://jython.svn.sourceforge.net/jython/?rev=5139&view=rev Author: zyasoft Date: 2008-08-10 23:14:13 +0000 (Sun, 10 Aug 2008) Log Message: ----------- Import test_support from test Modified Paths: -------------- branches/asm/Lib/test/test_exceptions_jy.py branches/asm/Lib/test/test_grammar_jy.py branches/asm/Lib/test/test_importhooks.py branches/asm/Lib/test/test_iter_jy.py branches/asm/Lib/test/test_javashell.py branches/asm/Lib/test/test_jreload.py branches/asm/Lib/test/test_jser2.py branches/asm/Lib/test/test_select.py branches/asm/Lib/test/test_select_new.py branches/asm/Lib/test/test_slots_jy.py branches/asm/Lib/test/test_subclasses.py Modified: branches/asm/Lib/test/test_exceptions_jy.py =================================================================== --- branches/asm/Lib/test/test_exceptions_jy.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_exceptions_jy.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -2,7 +2,7 @@ Made for Jython. """ -import test_support +from test import test_support import unittest class ExceptionsTestCase(unittest.TestCase): Modified: branches/asm/Lib/test/test_grammar_jy.py =================================================================== --- branches/asm/Lib/test/test_grammar_jy.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_grammar_jy.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -1,7 +1,7 @@ """ Extra grammar tests for Jython. """ -import test_support +from test import test_support import unittest class GrammarTest(unittest.TestCase): Modified: branches/asm/Lib/test/test_importhooks.py =================================================================== --- branches/asm/Lib/test/test_importhooks.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_importhooks.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -2,7 +2,7 @@ import imp import os import unittest -import test_support +from test import test_support test_src = """\ Modified: branches/asm/Lib/test/test_iter_jy.py =================================================================== --- branches/asm/Lib/test/test_iter_jy.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_iter_jy.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -2,7 +2,7 @@ Made for Jython. """ -import test_support +from test import test_support import unittest class IterTestCase(unittest.TestCase): Modified: branches/asm/Lib/test/test_javashell.py =================================================================== --- branches/asm/Lib/test/test_javashell.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_javashell.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -1,5 +1,5 @@ import unittest -import test_support +from test import test_support from org.python.core import PyFile import re Modified: branches/asm/Lib/test/test_jreload.py =================================================================== --- branches/asm/Lib/test/test_jreload.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_jreload.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -5,7 +5,7 @@ """ import unittest -import test_support +from test import test_support from jreload import makeLoadSet from java.lang import System, ClassFormatError Modified: branches/asm/Lib/test/test_select.py =================================================================== --- branches/asm/Lib/test/test_select.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_select.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -13,7 +13,7 @@ import os import sys -import test_support +from test import test_support import unittest class SelectWrapper: Modified: branches/asm/Lib/test/test_select_new.py =================================================================== --- branches/asm/Lib/test/test_select_new.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_select_new.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -4,7 +4,7 @@ import errno import time -import test_support +from test import test_support import unittest import socket Modified: branches/asm/Lib/test/test_slots_jy.py =================================================================== --- branches/asm/Lib/test/test_slots_jy.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_slots_jy.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -2,7 +2,7 @@ Made for Jython. """ -import test_support +from test import test_support import unittest # The strict tests fail on PyPy (but work on CPython and Jython). Modified: branches/asm/Lib/test/test_subclasses.py =================================================================== --- branches/asm/Lib/test/test_subclasses.py 2008-08-10 22:57:07 UTC (rev 5138) +++ branches/asm/Lib/test/test_subclasses.py 2008-08-10 23:14:13 UTC (rev 5139) @@ -1,4 +1,5 @@ -import test_support, unittest +from test import test_support +import unittest import pickle #myint and its test taken from pickletester, the other "my" classes and tests This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2008-08-10 22:57:10
|
Revision: 5138 http://jython.svn.sourceforge.net/jython/?rev=5138&view=rev Author: zyasoft Date: 2008-08-10 22:57:07 +0000 (Sun, 10 Aug 2008) Log Message: ----------- Properly closes a generator upon close/throw including throwing StopIteration upon a send to a closed generator. Modified Paths: -------------- branches/asm/src/org/python/core/PyGenerator.java Modified: branches/asm/src/org/python/core/PyGenerator.java =================================================================== --- branches/asm/src/org/python/core/PyGenerator.java 2008-08-10 21:30:15 UTC (rev 5137) +++ branches/asm/src/org/python/core/PyGenerator.java 2008-08-10 22:57:07 UTC (rev 5138) @@ -14,6 +14,7 @@ this.gi_running = false; // Create an exception instance while we have a frame to create it from. // When the GC runs it doesn't have any associated thread state. + // this is necessary for finalize calling close on the generator this.generatorExit = Py.makeException(Py.GeneratorExit); } @@ -34,6 +35,9 @@ } public PyObject send(PyObject value) { + if (gi_frame == null) { + throw Py.StopIteration(""); + } if (gi_frame.f_lasti == 0 && value != Py.None) { throw Py.TypeError("can't send non-None value to a just-started generator"); } @@ -42,6 +46,8 @@ } private PyObject raiseException(PyException ex) { + if (gi_frame == null) + return null; gi_frame.setGeneratorInput(ex); return next(); } @@ -71,14 +77,11 @@ } protected void finalize() throws Throwable { - //if (gi_frame.f_lasti == -1) // Generator already closed. - // return; // this is pure optimization + if (gi_frame == null || gi_frame.f_lasti == -1) + return; try { - close(); // close doesn't work without newcompiler, so ignore the exception + close(); } catch (Throwable e) { - // e.printStackTrace(); - // Py.println(Py.getSystemState().stderr, new PyString("Exception " - // + e + " in " + this + " ignored.")); } finally { super.finalize(); } @@ -87,27 +90,33 @@ public PyObject __iternext__() { if (gi_running) throw Py.ValueError("generator already executing"); - if (gi_frame.f_lasti == -1) + if (gi_frame == null) { return null; + } + + if (gi_frame.f_lasti == -1) { + gi_frame = null; + return null; + } gi_running = true; PyObject result = null; try { result = gi_frame.f_code.call(gi_frame, closure); } catch(PyException e) { - if(!e.type.equals(Py.StopIteration)) { + if (!(e.type == Py.StopIteration || e.type == Py.GeneratorExit)) { + gi_frame = null; throw e; } else { stopException = e; + gi_frame = null; return null; } } finally { gi_running = false; } -// System.out.println("lasti:" + gi_frame.f_lasti); -//if (result == Py.None) -// new Exception().printStackTrace(); - if (result == Py.None && gi_frame.f_lasti == -1) + if (result == Py.None && gi_frame.f_lasti == -1) { return null; + } return result; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-08-10 21:30:20
|
Revision: 5137 http://jython.svn.sourceforge.net/jython/?rev=5137&view=rev Author: pjenvey Date: 2008-08-10 21:30:15 +0000 (Sun, 10 Aug 2008) Log Message: ----------- o __float__ should always return a PyFloat, no need to cast in complex new o prefer PyObject.isCallable to __builtin__'s Modified Paths: -------------- branches/asm/src/org/python/core/PyComplex.java branches/asm/src/org/python/core/PyMethod.java Modified: branches/asm/src/org/python/core/PyComplex.java =================================================================== --- branches/asm/src/org/python/core/PyComplex.java 2008-08-10 21:19:00 UTC (rev 5136) +++ branches/asm/src/org/python/core/PyComplex.java 2008-08-10 21:30:15 UTC (rev 5137) @@ -53,7 +53,7 @@ PyComplex complexReal; PyComplex complexImag; - PyObject toFloat = null; + PyFloat toFloat = null; if (real instanceof PyComplex) { complexReal = (PyComplex)real; } else { @@ -66,11 +66,7 @@ } throw pye; } - if (!(toFloat instanceof PyFloat)) { - throw Py.TypeError(String.format("__float__ returned non-float (type %.200s)", - imag.getType().fastGetName())); - } - complexReal = new PyComplex(((PyFloat)toFloat).getValue()); + complexReal = new PyComplex(toFloat.getValue()); } if (imag == null) { @@ -88,11 +84,7 @@ } throw pye; } - if (!(toFloat instanceof PyFloat)) { - throw Py.TypeError(String.format("__float__ returned non-float (type %.200s)", - imag.getType().fastGetName())); - } - complexImag = new PyComplex(((PyFloat)toFloat).getValue()); + complexImag = new PyComplex(toFloat.getValue()); } complexReal.real -= complexImag.imag; Modified: branches/asm/src/org/python/core/PyMethod.java =================================================================== --- branches/asm/src/org/python/core/PyMethod.java 2008-08-10 21:19:00 UTC (rev 5136) +++ branches/asm/src/org/python/core/PyMethod.java 2008-08-10 21:30:15 UTC (rev 5137) @@ -45,7 +45,7 @@ PyObject self = ap.getPyObject(1); PyObject classObj = ap.getPyObject(2, null); - if (!__builtin__.callable(func)) { + if (!func.isCallable()) { throw Py.TypeError("first argument must be callable"); } if (self == Py.None && classObj == null) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <le...@us...> - 2008-08-10 21:19:04
|
Revision: 5136 http://jython.svn.sourceforge.net/jython/?rev=5136&view=rev Author: leosoto Date: 2008-08-10 21:19:00 +0000 (Sun, 10 Aug 2008) Log Message: ----------- Added test for http://bugs.jython.org/issue1804011 (derived_dict() must be equal to {}) Modified Paths: -------------- branches/asm/Lib/test/test_dict_jy.py Modified: branches/asm/Lib/test/test_dict_jy.py =================================================================== --- branches/asm/Lib/test/test_dict_jy.py 2008-08-10 21:14:36 UTC (rev 5135) +++ branches/asm/Lib/test/test_dict_jy.py 2008-08-10 21:19:00 UTC (rev 5136) @@ -35,6 +35,7 @@ # With derived classes that doesn't override __cmp__, the behaviour # should be the same that with dicts: class derived_dict(dict): pass + self.assertEqual(derived_dict(), {}) self.assertNotEqual(derived_dict(), '') self.assertRaises(TypeError, derived_dict().__cmp__, '') # But, if they *override* __cmp__ and raise TypeError from there, we This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <le...@us...> - 2008-08-10 21:14:40
|
Revision: 5135 http://jython.svn.sourceforge.net/jython/?rev=5135&view=rev Author: leosoto Date: 2008-08-10 21:14:36 +0000 (Sun, 10 Aug 2008) Log Message: ----------- Added cmp test for http://bugs.jython.org/issue1869347 Modified Paths: -------------- branches/asm/Lib/test/test_cmp_jy.py Modified: branches/asm/Lib/test/test_cmp_jy.py =================================================================== --- branches/asm/Lib/test/test_cmp_jy.py 2008-08-10 21:09:42 UTC (rev 5134) +++ branches/asm/Lib/test/test_cmp_jy.py 2008-08-10 21:14:36 UTC (rev 5135) @@ -14,8 +14,15 @@ class B(unicode): pass self.assertEqual(A(), B()) +class LongDerivedCmp(unittest.TestCase): + def testCompareWithString(self): + class Test(long): + pass + self.assertNotEqual(Test(0), 'foo') + self.assertTrue('foo' in [Test(12), 'foo']) + def test_main(): - test_support.run_unittest(UnicodeDerivedCmp) + test_support.run_unittest(UnicodeDerivedCmp, LongDerivedCmp) if __name__ == '__main__': test_main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <le...@us...> - 2008-08-10 21:09:46
|
Revision: 5134 http://jython.svn.sourceforge.net/jython/?rev=5134&view=rev Author: leosoto Date: 2008-08-10 21:09:42 +0000 (Sun, 10 Aug 2008) Log Message: ----------- Added test_cmp_jy, with should have tests to ensure CPython compatibility on cmp(). Currently, it only contains test cases for the problems exposed on http://bugs.jython.org/issue1889394 Added Paths: ----------- branches/asm/Lib/test/test_cmp_jy.py Added: branches/asm/Lib/test/test_cmp_jy.py =================================================================== --- branches/asm/Lib/test/test_cmp_jy.py (rev 0) +++ branches/asm/Lib/test/test_cmp_jy.py 2008-08-10 21:09:42 UTC (rev 5134) @@ -0,0 +1,21 @@ +"Tests for cmp() compatibility with CPython" +import unittest +from test import test_support + +class UnicodeDerivedCmp(unittest.TestCase): + "Test for http://bugs.jython.org/issue1889394" + def testCompareWithString(self): + class Test(unicode): + pass + test = Test('{1:1}') + self.assertNotEqual(test, {1:1}) + def testCompareEmptyDerived(self): + class A(unicode): pass + class B(unicode): pass + self.assertEqual(A(), B()) + +def test_main(): + test_support.run_unittest(UnicodeDerivedCmp) + +if __name__ == '__main__': + test_main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <le...@us...> - 2008-08-10 20:51:16
|
Revision: 5133 http://jython.svn.sourceforge.net/jython/?rev=5133&view=rev Author: leosoto Date: 2008-08-10 20:50:55 +0000 (Sun, 10 Aug 2008) Log Message: ----------- Added coercion to the cmp() algorithm, which is also used for comparison operators in the absence of rich cmp methods (See #1031). In the process, __coerce_ex__ was added to deriveds, and a slight refactor was made on types exposing __coerce__ to avoid using the __coerce_ex__ virtual method on the exposed methods code. Fixes test_coercion. Modified Paths: -------------- branches/asm/src/org/python/core/PyArrayDerived.java branches/asm/src/org/python/core/PyBaseExceptionDerived.java branches/asm/src/org/python/core/PyBooleanDerived.java branches/asm/src/org/python/core/PyClassMethodDerived.java branches/asm/src/org/python/core/PyComplex.java branches/asm/src/org/python/core/PyComplexDerived.java branches/asm/src/org/python/core/PyDictionaryDerived.java branches/asm/src/org/python/core/PyEnumerateDerived.java branches/asm/src/org/python/core/PyFileDerived.java branches/asm/src/org/python/core/PyFloat.java branches/asm/src/org/python/core/PyFloatDerived.java branches/asm/src/org/python/core/PyFrozenSetDerived.java branches/asm/src/org/python/core/PyInteger.java branches/asm/src/org/python/core/PyIntegerDerived.java branches/asm/src/org/python/core/PyListDerived.java branches/asm/src/org/python/core/PyLong.java branches/asm/src/org/python/core/PyLongDerived.java branches/asm/src/org/python/core/PyModuleDerived.java branches/asm/src/org/python/core/PyObject.java branches/asm/src/org/python/core/PyObjectDerived.java branches/asm/src/org/python/core/PyPropertyDerived.java branches/asm/src/org/python/core/PySetDerived.java branches/asm/src/org/python/core/PySliceDerived.java branches/asm/src/org/python/core/PyStringDerived.java branches/asm/src/org/python/core/PySuperDerived.java branches/asm/src/org/python/core/PyTupleDerived.java branches/asm/src/org/python/core/PyTypeDerived.java branches/asm/src/org/python/core/PyUnicodeDerived.java branches/asm/src/org/python/modules/_csv/PyDialectDerived.java branches/asm/src/org/python/modules/_functools/PyPartialDerived.java branches/asm/src/org/python/modules/_weakref/ReferenceTypeDerived.java branches/asm/src/org/python/modules/collections/PyDefaultDictDerived.java branches/asm/src/org/python/modules/collections/PyDequeDerived.java branches/asm/src/org/python/modules/random/PyRandomDerived.java branches/asm/src/org/python/modules/thread/PyLocalDerived.java branches/asm/src/org/python/modules/zipimport/zipimporterDerived.java branches/asm/src/templates/object.derived Modified: branches/asm/src/org/python/core/PyArrayDerived.java =================================================================== --- branches/asm/src/org/python/core/PyArrayDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyArrayDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyBaseExceptionDerived.java =================================================================== --- branches/asm/src/org/python/core/PyBaseExceptionDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyBaseExceptionDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1087,6 +1087,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyBooleanDerived.java =================================================================== --- branches/asm/src/org/python/core/PyBooleanDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyBooleanDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyClassMethodDerived.java =================================================================== --- branches/asm/src/org/python/core/PyClassMethodDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyClassMethodDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyComplex.java =================================================================== --- branches/asm/src/org/python/core/PyComplex.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyComplex.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -266,12 +266,20 @@ return unsupported_comparison(other); } + public Object __coerce_ex__(PyObject other) { + return complex___coerce_ex__(other); + } + @ExposedMethod final PyObject complex___coerce__(PyObject other) { - return __coerce__(other); + return adaptToCoerceTuple(complex___coerce_ex__(other)); } - public Object __coerce_ex__(PyObject other) { + /** + * Coercion logic for complex. Implemented as a final method to avoid + * invocation of virtual methods from the exposed coerce. + */ + final PyObject complex___coerce_ex__(PyObject other) { if (other instanceof PyComplex) return other; if (other instanceof PyFloat) Modified: branches/asm/src/org/python/core/PyComplexDerived.java =================================================================== --- branches/asm/src/org/python/core/PyComplexDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyComplexDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyDictionaryDerived.java =================================================================== --- branches/asm/src/org/python/core/PyDictionaryDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyDictionaryDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyEnumerateDerived.java =================================================================== --- branches/asm/src/org/python/core/PyEnumerateDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyEnumerateDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyFileDerived.java =================================================================== --- branches/asm/src/org/python/core/PyFileDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyFileDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyFloat.java =================================================================== --- branches/asm/src/org/python/core/PyFloat.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyFloat.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -201,6 +201,19 @@ } public Object __coerce_ex__(PyObject other) { + return float___coerce_ex__(other); + } + + @ExposedMethod + final PyObject float___coerce__(PyObject other) { + return adaptToCoerceTuple(float___coerce_ex__(other)); + } + + /** + * Coercion logic for float. Implemented as a final method to avoid + * invocation of virtual methods from the exposed coerce. + */ + final Object float___coerce_ex__(PyObject other) { if (other instanceof PyFloat) return other; else { @@ -211,6 +224,7 @@ else return Py.None; } + } private static final boolean canCoerce(PyObject other) { @@ -504,11 +518,6 @@ } } - @ExposedMethod - final PyObject float___coerce__(PyObject other) { - return __coerce__(other); - } - public PyObject __neg__() { return float___neg__(); } Modified: branches/asm/src/org/python/core/PyFloatDerived.java =================================================================== --- branches/asm/src/org/python/core/PyFloatDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyFloatDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyFrozenSetDerived.java =================================================================== --- branches/asm/src/org/python/core/PyFrozenSetDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyFrozenSetDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyInteger.java =================================================================== --- branches/asm/src/org/python/core/PyInteger.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyInteger.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -164,6 +164,19 @@ } public Object __coerce_ex__(PyObject other) { + return int___coerce_ex__(other); + } + + @ExposedMethod + final PyObject int___coerce__(PyObject other) { + return adaptToCoerceTuple(int___coerce_ex__(other)); + } + + /** + * Coercion logic for int. Implemented as a final method to avoid + * invocation of virtual methods from the exposed coerced. + */ + final Object int___coerce_ex__(PyObject other) { if (other instanceof PyInteger) return other; else @@ -689,14 +702,9 @@ @ExposedMethod(type = MethodType.BINARY) final PyObject int___ror__(PyObject left){ - return int___or__(left); + return int___or__(left); } - @ExposedMethod - final PyObject int___coerce__(PyObject other) { - return __coerce__(other); - } - public PyObject __neg__() { return int___neg__(); } Modified: branches/asm/src/org/python/core/PyIntegerDerived.java =================================================================== --- branches/asm/src/org/python/core/PyIntegerDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyIntegerDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyListDerived.java =================================================================== --- branches/asm/src/org/python/core/PyListDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyListDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyLong.java =================================================================== --- branches/asm/src/org/python/core/PyLong.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyLong.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -256,6 +256,19 @@ } public Object __coerce_ex__(PyObject other) { + return long___coerce_ex__(other); + } + + @ExposedMethod + final PyObject long___coerce__(PyObject other) { + return adaptToCoerceTuple(long___coerce_ex__(other)); + } + + /** + * Coercion logic for long. Implemented as a final method to avoid + * invocation of virtual methods from the exposed coerce. + */ + final Object long___coerce_ex__(PyObject other) { if (other instanceof PyLong) return other; else @@ -710,11 +723,6 @@ return Py.newLong(coerce(left).or(value)); } - @ExposedMethod - final PyObject long___coerce__(PyObject other) { - return __coerce__(other); - } - public PyObject __neg__() { return long___neg__(); } Modified: branches/asm/src/org/python/core/PyLongDerived.java =================================================================== --- branches/asm/src/org/python/core/PyLongDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyLongDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyModuleDerived.java =================================================================== --- branches/asm/src/org/python/core/PyModuleDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyModuleDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1087,6 +1087,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyObject.java =================================================================== --- branches/asm/src/org/python/core/PyObject.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyObject.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -980,10 +980,14 @@ * * This method can not be overridden. * To implement __coerce__ functionality, override __coerce_ex__ instead. + * + * Also, <b>do not</b> call this method from exposed 'coerce' methods. + * Instead, Use adaptToCoerceTuple over the result of the overriden + * __coerce_ex__. * * @param pyo the other object involved in the coercion. * @return a tuple of this object and pyo coerced to the same type - * or Py.None if no coercion is possible. + * or Py.NotImplemented if no coercion is possible. * @see org.python.core.PyObject#__coerce_ex__(org.python.core.PyObject) **/ public final PyObject __coerce__(PyObject pyo) { @@ -991,6 +995,21 @@ if (o == null) { throw Py.AttributeError("__coerce__"); } + return adaptToCoerceTuple(o); + } + + /** + * Adapts the result of __coerce_ex__ to a tuple of two elements, with the + * resulting coerced values, or to Py.NotImplemented, if o is Py.None. + * + * This is safe to be used from subclasses exposing '__coerce__' + * (as opposed to {@link #__coerce__(PyObject)}, which calls the virtual + * method {@link #__coerce_ex__(PyObject)}) + * + * @param o either a PyObject[2] or a PyObject, as given by + * {@link #__coerce_ex__(PyObject)}. + */ + protected final PyObject adaptToCoerceTuple(Object o) { if (o == Py.None) { return Py.NotImplemented; } @@ -1001,8 +1020,6 @@ } } - - /* The basic comparision operations */ /** @@ -1155,29 +1172,40 @@ if (this == other) return 0; - int result; - result = this.__cmp__(other); - if (result != -2) + int result = _try__cmp__(other); + if (result != -2) { return result; - - if (!(this instanceof PyInstance)) { - result = other.__cmp__(this); - if (result != -2) - return -result; } - return this._default_cmp(other); } /* * Like _cmp_unsafe but limited to ==/!= as 0/!=0, - * avoids to invoke Py.id + * thus it avoids to invoke _default_cmp. */ private final int _cmpeq_unsafe(PyObject other) { // Shortcut for equal objects if (this == other) return 0; + int result = _try__cmp__(other); + if (result != -2) { + return result; + } + + return this._is(other).__nonzero__()?0:1; + } + + /** + * Tries a 3-way comparison, using __cmp__. It tries the following + * operations until one of them succeed:<ul> + * <li>this.__cmp__(other) + * <li>other.__cmp__(this) + * <li>this._coerce(other) followed by coerced_this.__cmp__(coerced_other)</ul> + * + * @return -1, 0, -1 or -2, according to the {@link #__cmp__} protocol. + */ + private int _try__cmp__(PyObject other) { int result; result = this.__cmp__(other); if (result != -2) @@ -1188,8 +1216,23 @@ if (result != -2) return -result; } + // Final attempt: coerce both arguments and compare that. We are doing + // this the same point where CPython 2.5 does. (See + // <http://svn.python.org/projects/python/tags/r252/Objects/object.c> at + // the end of try_3way_compare). + // + // This is not exactly was is specified on + // <http://docs.python.org/ref/coercion-rules.html>, where coercion is + // supposed to happen before trying __cmp__. - return this._is(other).__nonzero__()?0:1; + PyObject[] coerced = _coerce(other); + if (coerced != null) { + result = coerced[0].__cmp__(coerced[1]); + if (result != -2) { + return result; + } + } + return -2; } Modified: branches/asm/src/org/python/core/PyObjectDerived.java =================================================================== --- branches/asm/src/org/python/core/PyObjectDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyObjectDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyPropertyDerived.java =================================================================== --- branches/asm/src/org/python/core/PyPropertyDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyPropertyDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PySetDerived.java =================================================================== --- branches/asm/src/org/python/core/PySetDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PySetDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PySliceDerived.java =================================================================== --- branches/asm/src/org/python/core/PySliceDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PySliceDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyStringDerived.java =================================================================== --- branches/asm/src/org/python/core/PyStringDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyStringDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,4 +1111,18 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + } Modified: branches/asm/src/org/python/core/PySuperDerived.java =================================================================== --- branches/asm/src/org/python/core/PySuperDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PySuperDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyTupleDerived.java =================================================================== --- branches/asm/src/org/python/core/PyTupleDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyTupleDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,6 +1111,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyTypeDerived.java =================================================================== --- branches/asm/src/org/python/core/PyTypeDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyTypeDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1087,6 +1087,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/core/PyUnicodeDerived.java =================================================================== --- branches/asm/src/org/python/core/PyUnicodeDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/core/PyUnicodeDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1111,4 +1111,18 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + } Modified: branches/asm/src/org/python/modules/_csv/PyDialectDerived.java =================================================================== --- branches/asm/src/org/python/modules/_csv/PyDialectDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/modules/_csv/PyDialectDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1089,6 +1089,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/modules/_functools/PyPartialDerived.java =================================================================== --- branches/asm/src/org/python/modules/_functools/PyPartialDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/modules/_functools/PyPartialDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1089,6 +1089,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/modules/_weakref/ReferenceTypeDerived.java =================================================================== --- branches/asm/src/org/python/modules/_weakref/ReferenceTypeDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/modules/_weakref/ReferenceTypeDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1113,6 +1113,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/modules/collections/PyDefaultDictDerived.java =================================================================== --- branches/asm/src/org/python/modules/collections/PyDefaultDictDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/modules/collections/PyDefaultDictDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1113,6 +1113,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/modules/collections/PyDequeDerived.java =================================================================== --- branches/asm/src/org/python/modules/collections/PyDequeDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/modules/collections/PyDequeDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1113,6 +1113,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/modules/random/PyRandomDerived.java =================================================================== --- branches/asm/src/org/python/modules/random/PyRandomDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/modules/random/PyRandomDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1113,6 +1113,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/modules/thread/PyLocalDerived.java =================================================================== --- branches/asm/src/org/python/modules/thread/PyLocalDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/modules/thread/PyLocalDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1089,6 +1089,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/org/python/modules/zipimport/zipimporterDerived.java =================================================================== --- branches/asm/src/org/python/modules/zipimport/zipimporterDerived.java 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/org/python/modules/zipimport/zipimporterDerived.java 2008-08-10 20:50:55 UTC (rev 5133) @@ -1089,6 +1089,20 @@ return super.__tojava__(c); } + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==null||res==Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); Modified: branches/asm/src/templates/object.derived =================================================================== --- branches/asm/src/templates/object.derived 2008-08-10 19:52:51 UTC (rev 5132) +++ branches/asm/src/templates/object.derived 2008-08-10 20:50:55 UTC (rev 5133) @@ -444,3 +444,18 @@ return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); return super.__tojava__(c); } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res == null || res == Py.None) + return res; + if (!(res instanceof PyTuple)) + throw Py.TypeError("coercion should return None or 2-tuple"); + return ((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2008-08-10 19:52:55
|
Revision: 5132 http://jython.svn.sourceforge.net/jython/?rev=5132&view=rev Author: zyasoft Date: 2008-08-10 19:52:51 +0000 (Sun, 10 Aug 2008) Log Message: ----------- After a more careful reading of PEP 342: need to emit bytecode for getGeneratorInput and possible raising exception before any yields; and after each yield point. This one-line change fixes test_contextlib Modified Paths: -------------- branches/asm/src/org/python/compiler/CodeCompiler.java Modified: branches/asm/src/org/python/compiler/CodeCompiler.java =================================================================== --- branches/asm/src/org/python/compiler/CodeCompiler.java 2008-08-10 15:31:52 UTC (rev 5131) +++ branches/asm/src/org/python/compiler/CodeCompiler.java 2008-08-10 19:52:51 UTC (rev 5132) @@ -552,15 +552,17 @@ throw new ParseException("'yield' outside function", node); } - loadFrame(); - code.invokevirtual("org/python/core/PyFrame", "getGeneratorInput", "()" + $obj); - code.dup(); - code.instanceof_("org/python/core/PyException"); - Label done = new Label(); - code.ifeq(done); - code.checkcast("java/lang/Throwable"); - code.athrow(); - code.label(done); + if (yield_count == 0) { + loadFrame(); + code.invokevirtual("org/python/core/PyFrame", "getGeneratorInput", "()" + $obj); + code.dup(); + code.instanceof_("org/python/core/PyException"); + Label done = new Label(); + code.ifeq(done); + code.checkcast("java/lang/Throwable"); + code.athrow(); + code.label(done); + } if (node.value != null) { visit(node.value); @@ -577,14 +579,14 @@ restoreLocals(); loadFrame(); - code.invokevirtual("org/python/core/PyFrame", "checkGeneratorInput", "()" + $obj); + code.invokevirtual("org/python/core/PyFrame", "getGeneratorInput", "()" + $obj); code.dup(); code.instanceof_("org/python/core/PyException"); - done = new Label(); - code.ifeq(done); + Label done2 = new Label(); + code.ifeq(done2); code.checkcast("java/lang/Throwable"); code.athrow(); - code.label(done); + code.label(done2); code.checkcast("org/python/core/PyObject"); return null; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2008-08-10 15:31:57
|
Revision: 5131 http://jython.svn.sourceforge.net/jython/?rev=5131&view=rev Author: fwierzbicki Date: 2008-08-10 15:31:52 +0000 (Sun, 10 Aug 2008) Log Message: ----------- Choose a name for the bound parameter to generator expressions that can't collide with a real NAME. Arbitrarily picked _(x) just because it looks a bit like the names of the gen expressions themselves. Modified Paths: -------------- branches/asm/src/org/python/compiler/CodeCompiler.java branches/asm/src/org/python/compiler/ScopesCompiler.java Modified: branches/asm/src/org/python/compiler/CodeCompiler.java =================================================================== --- branches/asm/src/org/python/compiler/CodeCompiler.java 2008-08-10 15:03:21 UTC (rev 5130) +++ branches/asm/src/org/python/compiler/CodeCompiler.java 2008-08-10 15:31:52 UTC (rev 5131) @@ -1964,7 +1964,7 @@ } public Object visitGeneratorExp(GeneratorExp node) throws Exception { - String bound_exp = "x"; + String bound_exp = "_(x)"; String tmp_append ="_(" + node.getLine() + "_" + node.getCharPositionInLine() + ")"; setline(node); Modified: branches/asm/src/org/python/compiler/ScopesCompiler.java =================================================================== --- branches/asm/src/org/python/compiler/ScopesCompiler.java 2008-08-10 15:03:21 UTC (rev 5130) +++ branches/asm/src/org/python/compiler/ScopesCompiler.java 2008-08-10 15:31:52 UTC (rev 5131) @@ -250,7 +250,7 @@ } public Object visitGeneratorExp(GeneratorExp node) throws Exception { - String bound_exp = "x"; + String bound_exp = "_(x)"; String tmp ="_(" + node.getLine() + "_" + node.getCharPositionInLine() + ")"; def(tmp); ArgListCompiler ac = new ArgListCompiler(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2008-08-10 15:03:24
|
Revision: 5130 http://jython.svn.sourceforge.net/jython/?rev=5130&view=rev Author: fwierzbicki Date: 2008-08-10 15:03:21 +0000 (Sun, 10 Aug 2008) Log Message: ----------- Ignoring other SyntaxError details for now -- though I probably want to re-enable these two later. Modified Paths: -------------- branches/asm/Lib/test/test_genexps.py Modified: branches/asm/Lib/test/test_genexps.py =================================================================== --- branches/asm/Lib/test/test_genexps.py 2008-08-09 23:40:43 UTC (rev 5129) +++ branches/asm/Lib/test/test_genexps.py 2008-08-10 15:03:21 UTC (rev 5130) @@ -1,3 +1,10 @@ +#From http://svn.python.org/projects/python/branches/release25-maint/Lib/test_genexps.py@51333 + +#Ignoring details of SyntaxError for now -- justified I think for "invalid +# syntax" since that #message has very little info, where Antlr provides more +# detail. The others really are #differences that should be addressed, but I +# want to concentrate on the other errors for now. + doctests = """ Test simple loop with conditional @@ -134,12 +141,12 @@ Verify that syntax error's are raised for genexps used as lvalues - >>> (y for y in (1,2)) = 10 + >>> (y for y in (1,2)) = 10 #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... SyntaxError: can't assign to generator expression (<doctest test.test_genexps.__test__.doctests[40]>, line 1) - >>> (y for y in (1,2)) += 10 + >>> (y for y in (1,2)) += 10 #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... SyntaxError: augmented assignment to generator expression not possible (<doctest test.test_genexps.__test__.doctests[41]>, line 1) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <nr...@us...> - 2008-08-09 23:40:49
|
Revision: 5129 http://jython.svn.sourceforge.net/jython/?rev=5129&view=rev Author: nriley Date: 2008-08-09 23:40:43 +0000 (Sat, 09 Aug 2008) Log Message: ----------- Don't try tests expecting MemoryError which can pass with large Java heaps. Modified Paths: -------------- branches/asm/Lib/test/test_builtin.py branches/asm/Lib/test/test_format.py Modified: branches/asm/Lib/test/test_builtin.py =================================================================== --- branches/asm/Lib/test/test_builtin.py 2008-08-09 23:02:50 UTC (rev 5128) +++ branches/asm/Lib/test/test_builtin.py 2008-08-09 23:40:43 UTC (rev 5129) @@ -938,7 +938,7 @@ self.assertEqual(list(''), []) self.assertEqual(list('spam'), ['s', 'p', 'a', 'm']) - if sys.maxint == 0x7fffffff: + if sys.maxint == 0x7fffffff and not test.test_support.is_jython: # This test can currently only work on 32-bit machines. # XXX If/when PySequence_Length() returns a ssize_t, it should be # XXX re-enabled. Modified: branches/asm/Lib/test/test_format.py =================================================================== --- branches/asm/Lib/test/test_format.py 2008-08-09 23:02:50 UTC (rev 5128) +++ branches/asm/Lib/test/test_format.py 2008-08-09 23:40:43 UTC (rev 5129) @@ -1,4 +1,4 @@ -from test.test_support import verbose, have_unicode, TestFailed +from test.test_support import verbose, have_unicode, TestFailed, is_jython import sys # test string formatting operator (I am not sure if this is being tested @@ -243,7 +243,7 @@ #test_exc('%o', Foobar(), TypeError, # "expected string or Unicode object, long found") -if sys.maxint == 2**31-1: +if sys.maxint == 2**31-1 and not is_jython: # crashes 2.2.1 and earlier: try: "%*d"%(sys.maxint, -127) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-08-09 23:02:52
|
Revision: 5128 http://jython.svn.sourceforge.net/jython/?rev=5128&view=rev Author: pjenvey Date: 2008-08-09 23:02:50 +0000 (Sat, 09 Aug 2008) Log Message: ----------- oops, Stack won't work because we need to compare via identity. revert r5126 Modified Paths: -------------- branches/asm/src/org/python/core/ThreadState.java Modified: branches/asm/src/org/python/core/ThreadState.java =================================================================== --- branches/asm/src/org/python/core/ThreadState.java 2008-08-09 22:05:00 UTC (rev 5127) +++ branches/asm/src/org/python/core/ThreadState.java 2008-08-09 23:02:50 UTC (rev 5128) @@ -17,7 +17,7 @@ public boolean tracing; - private Stack reprStack = null; + public PyList reprStack = null; // public PyInstance initializingProxy = null; private Stack initializingProxies = null; @@ -69,11 +69,15 @@ public boolean enterRepr(PyObject obj) { if (reprStack == null) { - reprStack = new Stack(); - } else if (reprStack.search(obj) > -1) { - return false; + reprStack = new PyList(new PyObject[] {obj}); + return true; } - reprStack.push(obj); + for (int i = reprStack.size() - 1; i >= 0; i--) { + if (obj == reprStack.pyget(i)) { + return false; + } + } + reprStack.append(obj); return true; } @@ -81,10 +85,11 @@ if (reprStack == null) { return; } - int index; - if ((index = reprStack.search(obj)) > -1) { - int size = reprStack.size(); - reprStack.subList(size - index, size).clear(); + + for (int i = reprStack.size() - 1; i >= 0; i--) { + if (reprStack.pyget(i) == obj) { + reprStack.delRange(i, reprStack.size(), 1); + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-08-09 22:05:05
|
Revision: 5127 http://jython.svn.sourceforge.net/jython/?rev=5127&view=rev Author: pjenvey Date: 2008-08-09 22:05:00 +0000 (Sat, 09 Aug 2008) Log Message: ----------- typo/thinko pointed out by lsoto Modified Paths: -------------- branches/asm/src/org/python/core/PyFloat.java Modified: branches/asm/src/org/python/core/PyFloat.java =================================================================== --- branches/asm/src/org/python/core/PyFloat.java 2008-08-09 22:02:39 UTC (rev 5126) +++ branches/asm/src/org/python/core/PyFloat.java 2008-08-09 22:05:00 UTC (rev 5127) @@ -185,8 +185,9 @@ // with. If NaN, similarly. if (other instanceof PyInteger || other instanceof PyLong) { j = 0.0; + } else { + return -2; } - return -2; } else if (other instanceof PyInteger) { j = ((PyInteger)other).getValue(); } else if (other instanceof PyLong) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-08-09 22:02:43
|
Revision: 5126 http://jython.svn.sourceforge.net/jython/?rev=5126&view=rev Author: pjenvey Date: 2008-08-09 22:02:39 +0000 (Sat, 09 Aug 2008) Log Message: ----------- reprStack isn't exposed anywhere, simplify it as a Stack Modified Paths: -------------- branches/asm/src/org/python/core/ThreadState.java Modified: branches/asm/src/org/python/core/ThreadState.java =================================================================== --- branches/asm/src/org/python/core/ThreadState.java 2008-08-09 21:53:44 UTC (rev 5125) +++ branches/asm/src/org/python/core/ThreadState.java 2008-08-09 22:02:39 UTC (rev 5126) @@ -17,7 +17,7 @@ public boolean tracing; - public PyList reprStack = null; + private Stack reprStack = null; // public PyInstance initializingProxy = null; private Stack initializingProxies = null; @@ -68,30 +68,23 @@ } public boolean enterRepr(PyObject obj) { - // if (reprStack == null) System.err.println("reprStack: null"); - // else System.err.println("reprStack: "+reprStack.__len__()); - if (this.reprStack == null) { - this.reprStack = new PyList(new PyObject[] { obj }); - return true; + if (reprStack == null) { + reprStack = new Stack(); + } else if (reprStack.search(obj) > -1) { + return false; } - for (int i = this.reprStack.size() - 1; i >= 0; i--) { - if (obj == this.reprStack.pyget(i)) { - return false; - } - } - this.reprStack.append(obj); + reprStack.push(obj); return true; } public void exitRepr(PyObject obj) { - if (this.reprStack == null) { + if (reprStack == null) { return; } - - for (int i = this.reprStack.size() - 1; i >= 0; i--) { - if (this.reprStack.pyget(i) == obj) { - this.reprStack.delRange(i, this.reprStack.size(), 1); - } + int index; + if ((index = reprStack.search(obj)) > -1) { + int size = reprStack.size(); + reprStack.subList(size - index, size).clear(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-08-09 21:53:48
|
Revision: 5125 http://jython.svn.sourceforge.net/jython/?rev=5125&view=rev Author: pjenvey Date: 2008-08-09 21:53:44 +0000 (Sat, 09 Aug 2008) Log Message: ----------- fix remove() not fully zeroing out the end of the array, causing a small memory leak. fixes test_deque.test_weakref Modified Paths: -------------- branches/asm/src/org/python/core/AbstractArray.java Modified: branches/asm/src/org/python/core/AbstractArray.java =================================================================== --- branches/asm/src/org/python/core/AbstractArray.java 2008-08-09 17:35:06 UTC (rev 5124) +++ branches/asm/src/org/python/core/AbstractArray.java 2008-08-09 21:53:44 UTC (rev 5125) @@ -377,7 +377,7 @@ } System.arraycopy(base, stop, base, start, this.size - stop); this.size = this.size - nRemove; - clearRangeInternal(this.size, this.size + nRemove - 1); + clearRangeInternal(this.size, this.size + nRemove); setArray(base); return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2008-08-09 17:35:11
|
Revision: 5124 http://jython.svn.sourceforge.net/jython/?rev=5124&view=rev Author: fwierzbicki Date: 2008-08-09 17:35:06 +0000 (Sat, 09 Aug 2008) Log Message: ----------- Call __iter__ on the iter part of gen expressions. Modified Paths: -------------- branches/asm/src/org/python/compiler/CodeCompiler.java Modified: branches/asm/src/org/python/compiler/CodeCompiler.java =================================================================== --- branches/asm/src/org/python/compiler/CodeCompiler.java 2008-08-09 17:07:19 UTC (rev 5123) +++ branches/asm/src/org/python/compiler/CodeCompiler.java 2008-08-09 17:35:06 UTC (rev 5124) @@ -2012,6 +2012,7 @@ visit(new Name(node, tmp_append, expr_contextType.Load)); visit(iter); + 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) })); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2008-08-09 17:07:23
|
Revision: 5123 http://jython.svn.sourceforge.net/jython/?rev=5123&view=rev Author: fwierzbicki Date: 2008-08-09 17:07:19 +0000 (Sat, 09 Aug 2008) Log Message: ----------- Don't allow generator expressions on left side of assignment. Modified Paths: -------------- branches/asm/grammar/PythonWalker.g branches/asm/src/org/python/antlr/GrammarActions.java Modified: branches/asm/grammar/PythonWalker.g =================================================================== --- branches/asm/grammar/PythonWalker.g 2008-08-09 16:27:42 UTC (rev 5122) +++ branches/asm/grammar/PythonWalker.g 2008-08-09 17:07:19 UTC (rev 5123) @@ -328,6 +328,7 @@ $stmts::statements.add(new Expr($test.marker, $test.etype)); } | ^(augassign targ=test[expr_contextType.AugStore] value=test[expr_contextType.Load]) { + actions.checkAssign($targ.etype); AugAssign a = new AugAssign($targ.marker, $targ.etype, $augassign.op, $value.etype); $stmts::statements.add(a); } Modified: branches/asm/src/org/python/antlr/GrammarActions.java =================================================================== --- branches/asm/src/org/python/antlr/GrammarActions.java 2008-08-09 16:27:42 UTC (rev 5122) +++ branches/asm/src/org/python/antlr/GrammarActions.java 2008-08-09 17:07:19 UTC (rev 5123) @@ -456,6 +456,8 @@ void checkAssign(exprType e) { if (e instanceof Name && ((Name)e).id.equals("None")) { throw new ParseException("assignment to None", e); + } else if (e instanceof GeneratorExp) { + throw new ParseException("can't assign to generator expression", e); } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2008-08-09 16:27:46
|
Revision: 5122 http://jython.svn.sourceforge.net/jython/?rev=5122&view=rev Author: fwierzbicki Date: 2008-08-09 16:27:42 +0000 (Sat, 09 Aug 2008) Log Message: ----------- added #doctest: +IGNORE_EXCEPTION_DETAIL for SyntaxErrors that just have "invalid syntax" as the detail, since this is the default message and Antlr actually gives more information. Modified Paths: -------------- branches/asm/Lib/test/test_genexps.py Modified: branches/asm/Lib/test/test_genexps.py =================================================================== --- branches/asm/Lib/test/test_genexps.py 2008-08-09 14:25:25 UTC (rev 5121) +++ branches/asm/Lib/test/test_genexps.py 2008-08-09 16:27:42 UTC (rev 5122) @@ -76,7 +76,7 @@ Verify that parenthesis are required in a statement - >>> def f(n): + >>> def f(n): #doctest: +IGNORE_EXCEPTION_DETAIL ... return i*i for i in xrange(n) Traceback (most recent call last): ... @@ -84,7 +84,7 @@ Verify that parenthesis are required when used as a keyword argument value - >>> dict(a = i for i in xrange(10)) + >>> dict(a = i for i in xrange(10)) #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... SyntaxError: invalid syntax This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |