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: <fwi...@us...> - 2009-01-11 22:36:08
|
Revision: 5921 http://jython.svn.sourceforge.net/jython/?rev=5921&view=rev Author: fwierzbicki Date: 2009-01-11 22:36:00 +0000 (Sun, 11 Jan 2009) Log Message: ----------- sham star_expr just to save the spot, causes an ambiguity with arglist so can't implement it just yet. Modified Paths: -------------- branches/jy3k/grammar/Python.g Modified: branches/jy3k/grammar/Python.g =================================================================== --- branches/jy3k/grammar/Python.g 2009-01-11 22:26:38 UTC (rev 5920) +++ branches/jy3k/grammar/Python.g 2009-01-11 22:36:00 UTC (rev 5921) @@ -1043,7 +1043,7 @@ | comparison[ctype] ; -//comparison: expr (comp_op expr)* +//comparison: star_expr (comp_op star_expr)* comparison[expr_contextType ctype] @init { List cmps = new ArrayList(); @@ -1054,8 +1054,8 @@ actions.castExprs($right)); } } - : left=expr[ctype] - ( ( comp_op right+=expr[ctype] {cmps.add($comp_op.op);} + : left=star_expr[ctype] + ( ( comp_op right+=star_expr[ctype] {cmps.add($comp_op.op);} )+ | -> $left @@ -1076,6 +1076,10 @@ | IS NOT {$op = cmpopType.IsNot;} ; +//star_expr: ['*'] expr +star_expr[expr_contextType ect] + : expr[ect] + ; //expr: xor_expr ('|' xor_expr)* expr[expr_contextType ect] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-11 22:26:43
|
Revision: 5920 http://jython.svn.sourceforge.net/jython/?rev=5920&view=rev Author: cgroves Date: 2009-01-11 22:26:38 +0000 (Sun, 11 Jan 2009) Log Message: ----------- test320 - Moved to test_traceback_jy test366,373 - Moved to test_java_integration test391 - Moved to test_java_visibility test395 - Tested by test_java_visibility test396 - Tested by test_java_subclasses Modified Paths: -------------- trunk/jython/Lib/test/test_java_integration.py trunk/jython/Lib/test/test_java_visibility.py trunk/jython/Lib/test/test_traceback_jy.py trunk/jython/src/org/python/compiler/ProxyMaker.java trunk/jython/src/org/python/core/PyLong.java Added Paths: ----------- trunk/jython/Lib/test/except_in_raising_code.py Removed Paths: ------------- trunk/jython/bugtests/classes/test395j1.java trunk/jython/bugtests/classes/test395j2.java trunk/jython/bugtests/classes/test396j.java trunk/jython/bugtests/test320.py trunk/jython/bugtests/test366.py trunk/jython/bugtests/test373.py trunk/jython/bugtests/test391.py trunk/jython/bugtests/test395.py trunk/jython/bugtests/test396.py Added: trunk/jython/Lib/test/except_in_raising_code.py =================================================================== --- trunk/jython/Lib/test/except_in_raising_code.py (rev 0) +++ trunk/jython/Lib/test/except_in_raising_code.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -0,0 +1,8 @@ +def test(): + print noname + +def foo(): + try: + test() + except ValueError: + raise RuntimeError("Accessing a undefined name should raise a NameError") Modified: trunk/jython/Lib/test/test_java_integration.py =================================================================== --- trunk/jython/Lib/test/test_java_integration.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/Lib/test/test_java_integration.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -7,7 +7,7 @@ from test import test_support from java.lang import (ExceptionInInitializerError, String, Runnable, System, Runtime, Math, Byte) -from java.math import BigDecimal +from java.math import BigDecimal, BigInteger from java.io import (FileInputStream, FileNotFoundException, FileOutputStream, FileWriter, OutputStreamWriter, UnsupportedEncodingException) from java.util import ArrayList, Date, HashMap, Hashtable, StringTokenizer, Vector @@ -56,6 +56,11 @@ b = BeanImplementation() self.assertEquals("name", b.getName()) self.assertEquals("name", b.name) + # Tests for #610576 + class SubBean(BeanImplementation): + def __init__(bself): + self.assertEquals("name", bself.getName()) + SubBean() class SysIntegrationTest(unittest.TestCase): @@ -262,7 +267,7 @@ self.assertEquals(len(treePath.path), 3, "Object[] not passed correctly") self.assertEquals(TreePath(treePath.path).path, treePath.path, "Object[] not passed and returned correctly") -class BigDecimalTest(unittest.TestCase): +class BigNumberTest(unittest.TestCase): def test_coerced_bigdecimal(self): from javatests import BigDecimalTest x = BigDecimal("123.4321") @@ -271,6 +276,11 @@ self.assertEqual(type(x), type(y), "BigDecimal coerced") self.assertEqual(x, y, "coerced BigDecimal not equal to directly created version") + def test_biginteger_in_long(self): + '''Checks for #608628, that long can take a BigInteger in its constructor''' + ns = '10000000000' + self.assertEquals(ns, str(long(BigInteger(ns)))) + class JavaStringTest(unittest.TestCase): def test_string_not_iterable(self): x = String('test') @@ -338,7 +348,7 @@ ImportTest, ColorTest, TreePathTest, - BigDecimalTest, + BigNumberTest, JavaStringTest, JavaDelegationTest, SecurityManagerTest) Modified: trunk/jython/Lib/test/test_java_visibility.py =================================================================== --- trunk/jython/Lib/test/test_java_visibility.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/Lib/test/test_java_visibility.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -4,7 +4,7 @@ import sys from test import test_support from java.lang import Byte, Class -from java.util import HashMap, Observable, Observer +from java.util import ArrayList, Collections, HashMap, Observable, Observer from org.python.tests import (Coercions, HiddenSuper, InterfaceCombination, Invisible, Matryoshka, OnlySubclassable, OtherSubVisible, SomePyMethods, SubVisible, Visible, VisibleOverride) from org.python.tests import VisibilityResults as Results @@ -142,6 +142,14 @@ """Bug #452947 - Class of innerclass inst <> innerclass""" self.assertEquals(id(Matryoshka.Outermost), id(Matryoshka.makeOutermost().__class__)) + def test_super_methods_merged(self): + '''Checks that all signatures on a class' methods are found, not just the first for a name + + Bug #628315''' + synchList = Collections.synchronizedList(ArrayList()) + synchList.add("a string") + self.assertEquals("a string", synchList.remove(0)) + class JavaClassTest(unittest.TestCase): def test_class_methods_visible(self): self.assertFalse(HashMap.isInterface(), Modified: trunk/jython/Lib/test/test_traceback_jy.py =================================================================== --- trunk/jython/Lib/test/test_traceback_jy.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/Lib/test/test_traceback_jy.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -50,8 +50,17 @@ # http://bugs.jython.org/issue437809 traceback.extract_stack() + def test_except_around_raising_call(self): + """[ #452526 ] traceback lineno is the except line""" + from test import except_in_raising_code + try: + except_in_raising_code.foo() + except NameError: + tb = sys.exc_info()[2] + self.assertEquals(6, tb.tb_next.tb_lineno) + else: + self.fail("Should've raised a NameError") - try: raise Exception('foo') except Exception: Deleted: trunk/jython/bugtests/classes/test395j1.java =================================================================== --- trunk/jython/bugtests/classes/test395j1.java 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/classes/test395j1.java 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,4 +0,0 @@ -public class test395j1 { - protected test395j1() { - } -} Deleted: trunk/jython/bugtests/classes/test395j2.java =================================================================== --- trunk/jython/bugtests/classes/test395j2.java 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/classes/test395j2.java 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,5 +0,0 @@ -public class test395j2 extends test395j1 { - private test395j2() { - super(); - } -} Deleted: trunk/jython/bugtests/classes/test396j.java =================================================================== --- trunk/jython/bugtests/classes/test396j.java 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/classes/test396j.java 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,8 +0,0 @@ -public abstract class test396j { - public test396j() { - abstractMethod(); - } - - public abstract void abstractMethod(); - -} Deleted: trunk/jython/bugtests/test320.py =================================================================== --- trunk/jython/bugtests/test320.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/test320.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,28 +0,0 @@ -""" -[ #452526 ] traceback lineno is the except line -""" - -import support -import sys, traceback - -def test(): - print noname - -def foo(): - try: - - - test() - - - except ValueError: - print "shouldn't happen." - -try: - foo() -except: - tb = sys.exc_info()[2] - #print tb.tb_lineno - #traceback.print_tb(tb) - assert tb.tb_next.tb_lineno == 15 - Deleted: trunk/jython/bugtests/test366.py =================================================================== --- trunk/jython/bugtests/test366.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/test366.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,17 +0,0 @@ -""" -[ 610576 ] Impl of abstract method not found -""" - -import support - -support.compileJava("test366i.java"); -support.compileJava("test366j.java"); - -import test366i, test366j - -class MyCls(test366j, test366i): - def __init__(self): - self.foo(); - -MyCls() - Deleted: trunk/jython/bugtests/test373.py =================================================================== --- trunk/jython/bugtests/test373.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/test373.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,14 +0,0 @@ -""" -Test for bug [608628] long(java.math.BigInteger) does not work. -""" - -import support - -# local name bugtests/test381.py -ns = '10000000000' -import java -ns2 = str(long(java.math.BigInteger(ns))) -assert ns == ns2, ns2 - - - Deleted: trunk/jython/bugtests/test391.py =================================================================== --- trunk/jython/bugtests/test391.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/test391.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,14 +0,0 @@ -''' -Checks that all methods on a class are found, not just the first interface that has a method of the same name. - -Reported in bug 628315. -''' -import support -import java - -synchList = java.util.Collections.synchronizedList(java.util.ArrayList()) -synchList.add("a string") - -if not synchList.remove(0) == 'a string': - raise support.TestError, "'a string' should've been returned by the call to remove. The object version of remove was probably called instead of the int version" - Deleted: trunk/jython/bugtests/test395.py =================================================================== --- trunk/jython/bugtests/test395.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/test395.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,20 +0,0 @@ -""" -Classes with greater a protected constructor can be subclassed and instantiated -Tests bug #649582 -""" - -import support - -support.compileJava("classes/test395j1.java") -support.compileJava("classes/test395j2.java") - -import test395j2 - -class Subclass(test395j2): - def __init__(self): - test395j2.__init__(self) - -try: - Subclass() -except AttributeError: - raise support.TestWarning('Unable to access protected superclass constructor') Deleted: trunk/jython/bugtests/test396.py =================================================================== --- trunk/jython/bugtests/test396.py 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/bugtests/test396.py 2009-01-11 22:26:38 UTC (rev 5920) @@ -1,19 +0,0 @@ -''' -Checks for bug 663592. Used to be that if an abstract Java class called an -abstract method implemented by a Python subclass in its constructor, an -AttributeError would be thrown. -''' -import support - -support.compileJava("classes/test396j.java") - -import test396j - -class Subclass(test396j): - def __init__(self): - test396j.__init__(self) - - def abstractMethod(self): - pass - -x = Subclass() Modified: trunk/jython/src/org/python/compiler/ProxyMaker.java =================================================================== --- trunk/jython/src/org/python/compiler/ProxyMaker.java 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/src/org/python/compiler/ProxyMaker.java 2009-01-11 22:26:38 UTC (rev 5920) @@ -703,9 +703,7 @@ addMethods(superclass, seenmethods); for (Class<?> iface : interfaces) { if (iface.isAssignableFrom(superclass)) { - Py.writeWarning("compiler", - "discarding redundant interface: "+ - iface.getName()); + Py.writeWarning("compiler", "discarding redundant interface: " + iface.getName()); continue; } classfile.addInterface(mapClass(iface)); Modified: trunk/jython/src/org/python/core/PyLong.java =================================================================== --- trunk/jython/src/org/python/core/PyLong.java 2009-01-11 14:49:43 UTC (rev 5919) +++ trunk/jython/src/org/python/core/PyLong.java 2009-01-11 22:26:38 UTC (rev 5920) @@ -18,7 +18,7 @@ public class PyLong extends PyObject { public static final PyType TYPE = PyType.fromClass(PyLong.class); - + public static final BigInteger minLong = BigInteger.valueOf(Long.MIN_VALUE); public static final BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE); public static final BigInteger maxULong = @@ -35,6 +35,9 @@ ArgParser ap = new ArgParser("long", args, keywords, new String[] {"x", "base"}, 0); PyObject x = ap.getPyObject(0, null); + if (x != null && x.getJavaProxy() instanceof BigInteger) { + return new PyLong((BigInteger)x.getJavaProxy()); + } int base = ap.getInt(1, -909); if (x == null) { @@ -74,7 +77,7 @@ return new PyLongDerived(subtype, ((PyLong)tmp).value); } } - + public PyLong(PyType subType, BigInteger v) { super(subType); value = v; @@ -264,10 +267,10 @@ 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. - */ + * invocation of virtual methods from the exposed coerce. + */ final Object long___coerce_ex__(PyObject other) { if (other instanceof PyLong) return other; @@ -535,7 +538,7 @@ public PyObject __pow__(PyObject right, PyObject modulo) { return long___pow__(right, modulo); } - + @ExposedMethod(type = MethodType.BINARY, defaults = {"null"}, doc = BuiltinDocs.long___pow___doc) final PyObject long___pow__(PyObject right, PyObject modulo) { if (!canCoerce(right)) @@ -744,7 +747,7 @@ public PyObject __abs__() { return long___abs__(); } - + @ExposedMethod(doc = BuiltinDocs.long___abs___doc) final PyObject long___abs__() { return Py.newLong(value.abs()); @@ -830,7 +833,7 @@ public PyString __str__() { return Py.newString(value.toString()); } - + public PyUnicode __unicode__() { return new PyUnicode(value.toString()); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-11 14:49:47
|
Revision: 5919 http://jython.svn.sourceforge.net/jython/?rev=5919&view=rev Author: fwierzbicki Date: 2009-01-11 14:49:43 +0000 (Sun, 11 Jan 2009) Log Message: ----------- refinements to funcdef args. Modified Paths: -------------- branches/jy3k/grammar/Python.g branches/jy3k/src/org/python/antlr/GrammarActions.java Modified: branches/jy3k/grammar/Python.g =================================================================== --- branches/jy3k/grammar/Python.g 2009-01-11 10:35:10 UTC (rev 5918) +++ branches/jy3k/grammar/Python.g 2009-01-11 14:49:43 UTC (rev 5919) @@ -461,7 +461,7 @@ ; //not in CPython's Grammar file -tdefparameter[List defaults] returns [arg atype] +tdefparameter[List defaults, boolean defaultToNone] returns [arg atype] @after { $tdefparameter.tree = $atype; } @@ -470,6 +470,9 @@ $atype = actions.castArg($tfpdef.tree); if ($ASSIGN != null) { defaults.add($test.tree); + } else if (defaultToNone) { + //XXX: is this the right way to add None? + defaults.add(null); } else if (!defaults.isEmpty()) { throw new ParseException("non-default argument follows default argument", $tfpdef.tree); } @@ -484,10 +487,10 @@ List defaults = new ArrayList(); List kw_defaults = new ArrayList(); } - : d+=tdefparameter[defaults] (options {greedy=true;}:COMMA d+=tdefparameter[defaults])* + : d+=tdefparameter[defaults, false] (options {greedy=true;}:COMMA d+=tdefparameter[defaults, false])* (COMMA - (STAR (starargs=tfpdef[expr_contextType.Param])? (COMMA k+=tdefparameter[kw_defaults])* - (COMMA tdefparameter[defaults])* (COMMA DOUBLESTAR kwargs=tfpdef[expr_contextType.Param])? + (STAR (starargs=tfpdef[expr_contextType.Param])? (COMMA k+=tdefparameter[kw_defaults, true])* + (COMMA DOUBLESTAR kwargs=tfpdef[expr_contextType.Param])? | DOUBLESTAR kwargs=tfpdef[expr_contextType.Param] )? )? @@ -501,7 +504,7 @@ defaults, kw_defaults); } - | STAR starargs=tfpdef[expr_contextType.Param] (COMMA DOUBLESTAR kwargs=tfpdef[expr_contextType.Param])? + | STAR (starargs=tfpdef[expr_contextType.Param])? (COMMA DOUBLESTAR kwargs=tfpdef[expr_contextType.Param])? { $args = actions.makeArgumentsType( $typedargslist.start, Modified: branches/jy3k/src/org/python/antlr/GrammarActions.java =================================================================== --- branches/jy3k/src/org/python/antlr/GrammarActions.java 2009-01-11 10:35:10 UTC (rev 5918) +++ branches/jy3k/src/org/python/antlr/GrammarActions.java 2009-01-11 14:49:43 UTC (rev 5919) @@ -136,7 +136,11 @@ result.add((expr)o); } else if (o instanceof PythonParser.test_return) { result.add((expr)((PythonParser.test_return)o).tree); + } else if (o == null) { + //Should we really add null? This is mainly here for kw_defaults + result.add(null); } + //XXX: throw exception if we get here? } } return result; @@ -307,10 +311,10 @@ Token t, List args, arg vararg, - List kwonlyargs, //* + List kwonlyargs, arg kwarg, List defaults, - List kw_defaults //* + List kw_defaults ) { List<arg> p = castArgs(args); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-11 10:35:15
|
Revision: 5918 http://jython.svn.sourceforge.net/jython/?rev=5918&view=rev Author: cgroves Date: 2009-01-11 10:35:10 +0000 (Sun, 11 Jan 2009) Log Message: ----------- In String compilation contexts, we can assume the bytes have already been decoded and just pass them through when parsing instead of using ascii. This gets test_doctest back to passing as it was before and keeps the pep 263 checks. Modified Paths: -------------- trunk/jython/Lib/test/test_doctest.py trunk/jython/src/org/python/core/CompilerFlags.java trunk/jython/src/org/python/core/ParserFacade.java Modified: trunk/jython/Lib/test/test_doctest.py =================================================================== --- trunk/jython/Lib/test/test_doctest.py 2009-01-11 06:24:45 UTC (rev 5917) +++ trunk/jython/Lib/test/test_doctest.py 2009-01-11 10:35:10 UTC (rev 5918) @@ -2265,18 +2265,17 @@ File "...", line 7, in test_doctest4.txt Failed example: u'...' - ... + Expected: + u'f\xf6\xf6' + Got: + u'f\xc3\xb6\xc3\xb6' ********************************************************************** ... ********************************************************************** - ... - ********************************************************************** - ... - ********************************************************************** 1 items had failures: - 4 of 4 in test_doctest4.txt - ***Test Failed*** 4 failures. - (4, 4) + 2 of 4 in test_doctest4.txt + ***Test Failed*** 2 failures. + (2, 4) >>> doctest.master = None # Reset master. >>> doctest.testfile('test_doctest4.txt', encoding='utf-8') Modified: trunk/jython/src/org/python/core/CompilerFlags.java =================================================================== --- trunk/jython/src/org/python/core/CompilerFlags.java 2009-01-11 06:24:45 UTC (rev 5917) +++ trunk/jython/src/org/python/core/CompilerFlags.java 2009-01-11 10:35:10 UTC (rev 5918) @@ -3,54 +3,44 @@ public class CompilerFlags { + private int co_flags; + public boolean nested_scopes = true; public boolean division; public boolean generator_allowed = true; - public boolean with_statement = false; - public boolean absolute_import = false; + public boolean with_statement; + public boolean absolute_import; - public boolean only_ast = false; - public boolean dont_imply_dedent = false; - public boolean source_is_utf8 = false; + public boolean only_ast; + public boolean dont_imply_dedent; + public boolean source_is_utf8; public String encoding; - - public CompilerFlags(){} + public CompilerFlags() {} + public CompilerFlags(int co_flags) { - if ((co_flags & org.python.core.PyTableCode.CO_NESTED) != 0) { - this.nested_scopes = true; - } - if ((co_flags & org.python.core.PyTableCode.CO_FUTUREDIVISION) != 0) { - this.division = true; - } - if ((co_flags & org.python.core.PyTableCode.CO_GENERATOR_ALLOWED) != 0) { - this.generator_allowed = true; - } - if ((co_flags & org.python.core.PyTableCode.CO_FUTURE_ABSOLUTE_IMPORT) != 0) { - this.absolute_import = true; - } - if ((co_flags & org.python.core.PyTableCode.CO_WITH_STATEMENT) != 0) { - this.with_statement = true; - } - if ((co_flags & org.python.core.PyTableCode.PyCF_ONLY_AST) != 0) { - this.only_ast = true; - } - if ((co_flags & org.python.core.PyTableCode.PyCF_DONT_IMPLY_DEDENT) != 0) { - this.dont_imply_dedent = true; - } - if ((co_flags & org.python.core.PyTableCode.PyCF_SOURCE_IS_UTF8) != 0) { - this.source_is_utf8 = true; - } - + this.co_flags = co_flags; + nested_scopes = isEnabled(PyTableCode.CO_NESTED); + division = isEnabled(PyTableCode.CO_FUTUREDIVISION); + generator_allowed = isEnabled(PyTableCode.CO_GENERATOR_ALLOWED); + absolute_import = isEnabled(PyTableCode.CO_FUTURE_ABSOLUTE_IMPORT); + with_statement = isEnabled(PyTableCode.CO_WITH_STATEMENT); + only_ast = isEnabled(PyTableCode.PyCF_ONLY_AST); + dont_imply_dedent = isEnabled(PyTableCode.PyCF_DONT_IMPLY_DEDENT); + source_is_utf8 = isEnabled(PyTableCode.PyCF_SOURCE_IS_UTF8); } + private boolean isEnabled(int codeConstant) { + return (co_flags & codeConstant) != 0; + } + public String toString() { return String.format("CompilerFlags[division=%s nested_scopes=%s generators=%s " + "with_statement=%s absolute_import=%s only_ast=%s " + "dont_imply_dedent=%s source_is_utf8=%s]", division, nested_scopes, - generator_allowed, with_statement, absolute_import, only_ast, + generator_allowed, with_statement, absolute_import, only_ast, dont_imply_dedent, source_is_utf8); } - + } Modified: trunk/jython/src/org/python/core/ParserFacade.java =================================================================== --- trunk/jython/src/org/python/core/ParserFacade.java 2009-01-11 06:24:45 UTC (rev 5917) +++ trunk/jython/src/org/python/core/ParserFacade.java 2009-01-11 10:35:10 UTC (rev 5918) @@ -4,10 +4,13 @@ import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.io.Reader; +import java.io.Writer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; @@ -138,7 +141,7 @@ try { // prepBufReader takes care of encoding detection and universal // newlines: - bufReader = prepBufReader(stream, cflags, filename); + bufReader = prepBufReader(stream, cflags, filename, false); return parse(bufReader, kind, filename, cflags ); } catch (Throwable t) { throw fixParseError(bufReader, t, filename); @@ -223,7 +226,9 @@ private static ExpectedEncodingBufferedReader prepBufReader(InputStream input, CompilerFlags cflags, - String filename) throws IOException { + String filename, + boolean fromString) + throws IOException { input = new BufferedInputStream(input); boolean bom = adjustForBOM(input); String encoding = readEncoding(input); @@ -250,29 +255,45 @@ UniversalIOWrapper textIO = new UniversalIOWrapper(bufferedIO); input = new TextIOInputStream(textIO); - CharsetDecoder dec; + Charset cs; try { // Use ascii for the raw bytes when no encoding was specified - dec = Charset.forName(encoding == null ? "ascii" : encoding).newDecoder(); + if (encoding == null) { + if (fromString) { + cs = Charset.forName("ISO-8859-1"); + } else { + cs = Charset.forName("ascii"); + } + } else { + cs = Charset.forName(encoding); + } } catch (UnsupportedCharsetException exc) { throw new PySyntaxError("Unknown encoding: " + encoding, 1, 0, "", filename); } + CharsetDecoder dec = cs.newDecoder(); dec.onMalformedInput(CodingErrorAction.REPORT); dec.onUnmappableCharacter(CodingErrorAction.REPORT); return new ExpectedEncodingBufferedReader(new InputStreamReader(input, dec), encoding); } - private static ExpectedEncodingBufferedReader prepBufReader(String string, CompilerFlags cflags, - String filename) throws IOException { + private static ExpectedEncodingBufferedReader prepBufReader(String string, + CompilerFlags cflags, + String filename) throws IOException { + byte[] stringBytes; if (cflags.source_is_utf8) { // Passed unicode, re-encode the String to raw bytes // NOTE: This could be more efficient if we duplicate // prepBufReader/adjustForBOM/readEncoding to work on Readers, instead of // encoding - string = new PyUnicode(string).encode("utf-8"); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Writer w = new OutputStreamWriter(out, "utf-8"); + w.write(string); + w.close(); + stringBytes = out.toByteArray(); + } else { + stringBytes = StringUtil.toBytes(string); } - InputStream input = new ByteArrayInputStream(StringUtil.toBytes(string)); - return prepBufReader(input, cflags, filename); + return prepBufReader(new ByteArrayInputStream(stringBytes), cflags, filename, true); } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-11 06:24:51
|
Revision: 5917 http://jython.svn.sourceforge.net/jython/?rev=5917&view=rev Author: cgroves Date: 2009-01-11 06:24:45 +0000 (Sun, 11 Jan 2009) Log Message: ----------- Huh, I guess ECJ can handle inferring these generics, but javac sure can't. Modified Paths: -------------- trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PyType.java trunk/jython/tests/java/javatests/ListTest.java Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2009-01-11 06:04:11 UTC (rev 5916) +++ trunk/jython/src/org/python/core/PyJavaType.java 2009-01-11 06:24:45 UTC (rev 5917) @@ -87,7 +87,8 @@ bases[i] = PyType.fromClass(underlying_class.getInterfaces()[i - 1]); } Set<PyObject> seen = Generic.set(); - List<PyObject> mros = Generic.list(this); + List<PyObject> mros = Generic.list(); + mros.add(this); for (PyObject obj : bases) { for (PyObject mroObj : ((PyType)obj).mro) { if (seen.add(mroObj)) { Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2009-01-11 06:04:11 UTC (rev 5916) +++ trunk/jython/src/org/python/core/PyType.java 2009-01-11 06:24:45 UTC (rev 5917) @@ -722,7 +722,8 @@ to_merge[n] = bases; remain[n] = 0; - List<PyObject> acc = Generic.list(this); + List<PyObject> acc = Generic.list(); + acc.add(this); int empty_cnt = 0; Modified: trunk/jython/tests/java/javatests/ListTest.java =================================================================== --- trunk/jython/tests/java/javatests/ListTest.java 2009-01-11 06:04:11 UTC (rev 5916) +++ trunk/jython/tests/java/javatests/ListTest.java 2009-01-11 06:24:45 UTC (rev 5917) @@ -472,7 +472,8 @@ int prevIndex = li.previousIndex(); TestSupport.assertThat(prevIndex == -1, "ListIterator.previousIndex() on empty List did not return -1"); - List<Object> l = Generic.list(1); + List<Object> l = Generic.list(); + l.add(1); li = newInstance(l).listIterator(); TestSupport.assertThat(!li.hasPrevious(), "ListIterator.hasPrevious() is true with nothing previous"); @@ -493,7 +494,7 @@ TestSupport.fail("expected IllegalStateException"); } catch (IllegalStateException e) {} } - l = Generic.list(0, 1, 2); + l = Generic.list(new Object[]{0, 1, 2}); li = newInstance(l).listIterator(); for (int i = 0, n = l.size(); i < n; i++) { TestSupport.assertThat(li.next().equals(i), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-11 06:04:17
|
Revision: 5916 http://jython.svn.sourceforge.net/jython/?rev=5916&view=rev Author: cgroves Date: 2009-01-11 06:04:11 +0000 (Sun, 11 Jan 2009) Log Message: ----------- Convert to PyObject going into and Object coming out of java.util.Set methods on PySet like PyDictionary does for Map methods and PyList does for List methods. Without this, Java code can add non-PyObjects to the underlying set causing the Python access to it to throw ClassCastExceptions. Modified Paths: -------------- trunk/jython/src/org/python/core/BaseSet.java trunk/jython/src/org/python/core/PyFrozenSet.java trunk/jython/src/org/python/core/PyIterator.java trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PySet.java trunk/jython/src/org/python/core/PyType.java trunk/jython/src/org/python/util/Generic.java trunk/jython/tests/java/javatests/ListTest.java Added Paths: ----------- trunk/jython/Lib/test/test_set_jy.py trunk/jython/tests/java/javatests/PySetInJavaTest.java Removed Paths: ------------- trunk/jython/src/org/python/core/PySetIterator.java Added: trunk/jython/Lib/test/test_set_jy.py =================================================================== --- trunk/jython/Lib/test/test_set_jy.py (rev 0) +++ trunk/jython/Lib/test/test_set_jy.py 2009-01-11 06:04:11 UTC (rev 5916) @@ -0,0 +1,35 @@ +from test import test_support +import unittest + +from java.util import Random +from javatests import PySetInJavaTest + +class SetInJavaTest(unittest.TestCase): + "Tests for derived dict behaviour" + def test_using_PySet_as_Java_Set(self): + PySetInJavaTest.testPySetAsJavaSet() + + def test_accessing_items_added_in_java(self): + s = PySetInJavaTest.createPySetContainingJavaObjects() + for v in s: + self.assert_(v in s) + if isinstance(v, unicode): + self.assertEquals("value", v) + else: + v.nextInt()#Should be a java.util.Random; ensure we can call it + + def test_java_accessing_items_added_in_python(self): + # Test a type that should be coerced into a Java type, a Java instance + # that should be wrapped, and a Python instance that should pass + # through as itself with str, Random and tuple respectively. + s = set(["value", Random(), ("tuple", "of", "stuff")]) + PySetInJavaTest.accessAndRemovePySetItems(s) + self.assertEquals(0, len(s))# Check that the Java removal affected the underlying set + + + +def test_main(): + test_support.run_unittest(SetInJavaTest) + +if __name__ == '__main__': + test_main() Modified: trunk/jython/src/org/python/core/BaseSet.java =================================================================== --- trunk/jython/src/org/python/core/BaseSet.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/src/org/python/core/BaseSet.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -1,41 +1,35 @@ package org.python.core; +import java.lang.reflect.Array; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; import java.util.Set; public abstract class BaseSet extends PyObject implements Set { /** The underlying Set. */ - protected Set _set; + protected Set<PyObject> _set; /** * Create a new Python set instance from the specified Set object. - * - * @param set An Set object. */ - protected BaseSet(Set set) { + protected BaseSet(Set<PyObject> set) { _set = set; } - protected BaseSet(PyType type, Set set) { + protected BaseSet(PyType type, Set<PyObject> set) { super(type); _set = set; } - protected void _update(PyObject data) throws PyIgnoreMethodTag { + protected void _update(PyObject data) { _update(_set, data); } /** * Update the underlying set with the contents of the iterable. - * - * @param data An iterable instance. - * @throws PyIgnoreMethodTag Ignore. */ - protected static Set _update(Set set, PyObject data) throws PyIgnoreMethodTag { + protected static Set<PyObject> _update(Set<PyObject> set, PyObject data) { if (data == null) { return set; } @@ -53,7 +47,7 @@ /** * The union of <code>this</code> with <code>other</code>. <p/> <br/> (I.e. all elements * that are in either set) - * + * * @param other * A <code>BaseSet</code> instance. * @return The union of the two sets as a new set. @@ -115,9 +109,9 @@ final PyObject baseset_difference(PyObject other) { BaseSet bs = (other instanceof BaseSet) ? (BaseSet)other : new PySet(other); - Set set = bs._set; + Set<PyObject> set = bs._set; BaseSet o = BaseSet.makeNewSet(getType()); - for (Object p : _set) { + for (PyObject p : _set) { if (!set.contains(p)) { o._set.add(p); } @@ -153,12 +147,12 @@ final PyObject baseset_symmetric_difference(PyObject other) { BaseSet bs = (other instanceof BaseSet) ? (BaseSet)other : new PySet(other); BaseSet o = BaseSet.makeNewSet(getType()); - for (Object p : _set) { + for (PyObject p : _set) { if (!bs._set.contains(p)) { o._set.add(p); } } - for (Object p : bs._set) { + for (PyObject p : bs._set) { if (!_set.contains(p)) { o._set.add(p); } @@ -206,7 +200,22 @@ } final PyObject baseset___iter__() { - return new PySetIterator(_set); + return new PyIterator() { + private int size = _set.size(); + + private Iterator<PyObject> iterator = _set.iterator(); + + @Override + public PyObject __iternext__() { + if (_set.size() != size) { + throw Py.RuntimeError("set changed size during iteration"); + } + if (iterator.hasNext()) { + return iterator.next(); + } + return null; + } + }; } public boolean __contains__(PyObject other) { @@ -257,7 +266,7 @@ } final PyObject baseset___le__(PyObject other) { - BaseSet bs = _binary_sanity_check(other); + _binary_sanity_check(other); return baseset_issubset(other); } @@ -266,7 +275,7 @@ } final PyObject baseset___ge__(PyObject other) { - BaseSet bs = _binary_sanity_check(other); + _binary_sanity_check(other); return baseset_issuperset(other); } @@ -299,7 +308,7 @@ public PyObject __reduce__() { return baseset___reduce__(); } - + final PyObject baseset___reduce__(){ PyObject args = new PyTuple(new PyList((PyObject)this)); PyObject dict = __findattr__("__dict__"); @@ -309,19 +318,6 @@ return new PyTuple(getType(), args, dict); } - /** - * Return this instance as a Java object. Only coerces to Collection and subinterfaces. - * - * @param c The Class to coerce to. - * @return the underlying HashSet (not a copy) - */ - public Object __tojava__(Class c) { - if (Collection.class.isAssignableFrom(c)) { - return Collections.unmodifiableSet(_set); - } - return super.__tojava__(c); - } - final PyObject baseset_union(PyObject other) { BaseSet result = BaseSet.makeNewSet(getType(), this); result._update(other); @@ -388,8 +384,8 @@ return name + "(...)"; } StringBuilder buf = new StringBuilder(name).append("(["); - for (Iterator i = _set.iterator(); i.hasNext();) { - buf.append(((PyObject)i.next()).__repr__().toString()); + for (Iterator<PyObject> i = _set.iterator(); i.hasNext();) { + buf.append((i.next()).__repr__().toString()); if (i.hasNext()) { buf.append(", "); } @@ -408,20 +404,20 @@ } /** - * Return a PyFrozenSet whose contents are shared with value when - * value is a BaseSet and pye is a TypeError. + * Return a PyFrozenSet whose contents are shared with value when value is a BaseSet and pye is + * a TypeError. * - * WARNING: The PyFrozenSet returned is only intended to be used - * temporarily (and internally); since its contents are shared - * with value, it could be mutated! - * - * This is better than special-casing behavior based on - * isinstance, because a Python subclass can override, say, - * __hash__ and all of a sudden you can't assume that a - * non-PyFrozenSet is unhashable anymore. + * WARNING: The PyFrozenSet returned is only intended to be used temporarily (and internally); + * since its contents are shared with value, it could be mutated! * - * @param pye The exception thrown from a hashable operation. - * @param value The object which was unhashable. + * This is better than special-casing behavior based on isinstance, because a Python subclass + * can override, say, __hash__ and all of a sudden you can't assume that a non-PyFrozenSet is + * unhashable anymore. + * + * @param pye + * The exception thrown from a hashable operation. + * @param value + * The object which was unhashable. * @return A PyFrozenSet if appropriate, otherwise the pye is rethrown */ protected final PyFrozenSet asFrozen(PyException pye, PyObject value) { @@ -442,7 +438,7 @@ protected static BaseSet makeNewSet(PyType type) { return makeNewSet(type, null); } - + /** * Create a new <et of type from iterable. * @@ -477,43 +473,89 @@ return _set.isEmpty(); } - public Object[] toArray() { - return _set.toArray(); - } - public boolean add(Object o) { - return _set.add(o); + return _set.add(Py.java2py(o)); } public boolean contains(Object o) { - return _set.contains(o); + return _set.contains(Py.java2py(o)); } public boolean remove(Object o) { - return _set.remove(o); + return _set.remove(Py.java2py(o)); } public boolean addAll(Collection c) { - return _set.addAll(c); + boolean added = false; + for (Object object : c) { + added |= add(object); + } + return added; } public boolean containsAll(Collection c) { - return _set.containsAll(c); + for (Object object : c) { + if (!_set.contains(Py.java2py(object))) { + return false; + } + } + return true; } public boolean removeAll(Collection c) { - return _set.removeAll(c); + boolean removed = false; + for (Object object : c) { + removed |= _set.remove(Py.java2py(object)); + } + return removed; } public boolean retainAll(Collection c) { - return _set.retainAll(c); + boolean modified = false; + Iterator e = iterator(); + while (e.hasNext()) { + if (!c.contains(e.next())) { + e.remove(); + modified = true; + } + } + return modified; } public Iterator iterator() { - return _set.iterator(); + return new Iterator() { + Iterator<PyObject> real = _set.iterator(); + + public boolean hasNext() { + return real.hasNext(); + } + + public Object next() { + return Py.tojava(real.next(), Object.class); + } + + public void remove() { + real.remove(); + } + }; } + public Object[] toArray() { + return toArray(new Object[size()]); + } + public Object[] toArray(Object a[]) { - return _set.toArray(a); + int size = size(); + if (a.length < size) { + a = (Object[])Array.newInstance(a.getClass().getComponentType(), size); + } + Iterator<PyObject> it = iterator(); + for (int i = 0; i < size; i++) { + a[i] = it.next(); + } + if (a.length > size) { + a[size] = null; + } + return a; } } Modified: trunk/jython/src/org/python/core/PyFrozenSet.java =================================================================== --- trunk/jython/src/org/python/core/PyFrozenSet.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/src/org/python/core/PyFrozenSet.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -11,9 +11,9 @@ @ExposedType(name = "frozenset", base = PyObject.class) public class PyFrozenSet extends BaseSet { - + public static final PyType TYPE = PyType.fromClass(PyFrozenSet.class); - + public PyFrozenSet() { super(new HashSet<PyObject>()); } @@ -204,8 +204,8 @@ } public Iterator iterator() { + final Iterator i = super.iterator(); return new Iterator() { - Iterator i = _set.iterator(); public boolean hasNext() { return i.hasNext(); Modified: trunk/jython/src/org/python/core/PyIterator.java =================================================================== --- trunk/jython/src/org/python/core/PyIterator.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/src/org/python/core/PyIterator.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -2,21 +2,18 @@ package org.python.core; /** - * An abstract helper class usefull when implementing an iterator object. This - * implementation supply a correct __iter__() and a next() method based on the - * __iternext__() implementation. The __iternext__() method must be supplied by - * the subclass. + * An abstract helper class useful when implementing an iterator object. This implementation supply + * a correct __iter__() and a next() method based on the __iternext__() implementation. The + * __iternext__() method must be supplied by the subclass. * - * If the implementation raises a StopIteration exception, it should be stored - * in stopException so the correct exception can be thrown to preserve the line - * numbers in the traceback. + * If the implementation raises a StopIteration exception, it should be stored in stopException so + * the correct exception can be thrown to preserve the line numbers in the traceback. */ public abstract class PyIterator extends PyObject { protected PyException stopException; - public PyIterator() { - } + public PyIterator() {} public PyIterator(PyType subType) { super(subType); Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/src/org/python/core/PyJavaType.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -87,8 +87,7 @@ bases[i] = PyType.fromClass(underlying_class.getInterfaces()[i - 1]); } Set<PyObject> seen = Generic.set(); - List<PyObject> mros = Generic.list(); - mros.add(this); + List<PyObject> mros = Generic.list(this); for (PyObject obj : bases) { for (PyObject mroObj : ((PyType)obj).mro) { if (seen.add(mroObj)) { Modified: trunk/jython/src/org/python/core/PySet.java =================================================================== --- trunk/jython/src/org/python/core/PySet.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/src/org/python/core/PySet.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -13,7 +13,7 @@ public class PySet extends BaseSet { public static final PyType TYPE = PyType.fromClass(PySet.class); - + public PySet() { super(new ConcurrentHashSet<PyObject>()); } @@ -25,7 +25,7 @@ public PySet(PyObject data) { super(_update(new ConcurrentHashSet<PyObject>(), data)); } - + @ExposedNew @ExposedMethod final void set___init__(PyObject[] args, String[] kwds) { @@ -40,7 +40,7 @@ _set.clear(); _update(args[0]); } - + @ExposedMethod(type = MethodType.BINARY) final PyObject set___cmp__(PyObject o) { return new PyInteger(baseset___cmp__(o)); @@ -181,7 +181,7 @@ return set___iand__(other); } - @ExposedMethod(type = MethodType.BINARY) + @ExposedMethod(type = MethodType.BINARY) final PyObject set___iand__(PyObject other) { if (!(other instanceof BaseSet)) { return null; @@ -281,8 +281,7 @@ } BaseSet bs = (other instanceof BaseSet) ? (BaseSet)other : new PySet(other); - for (Iterator iterator = bs._set.iterator(); iterator.hasNext();) { - Object o = iterator.next(); + for (PyObject o : bs._set) { if (_set.contains(o)) { _set.remove(o); } else { Deleted: trunk/jython/src/org/python/core/PySetIterator.java =================================================================== --- trunk/jython/src/org/python/core/PySetIterator.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/src/org/python/core/PySetIterator.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -1,52 +0,0 @@ -package org.python.core; - -import java.util.Iterator; -import java.util.Set; - -public class PySetIterator extends PyObject { - - private Set set; - - private int size; - - private Iterator<PyObject> iterator; - - public PySetIterator(Set set) { - super(); - this.set = set; - size = set.size(); - iterator = set.iterator(); - } - - public PyObject __iter__() { - return this; - } - - /** - * Returns the next item in the iteration or raises a StopIteration. - * - * @return the next item in the iteration - */ - public PyObject next() { - PyObject o = this.__iternext__(); - if (o == null) { - throw Py.StopIteration(""); - } - return o; - } - - /** - * Returns the next item in the iteration. - * - * @return the next item in the iteration or null to signal the end of the iteration - */ - public PyObject __iternext__() { - if (set.size() != size) { - throw Py.RuntimeError("set changed size during iteration"); - } - if (iterator.hasNext()) { - return iterator.next(); - } - return null; - } -} Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/src/org/python/core/PyType.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -722,8 +722,7 @@ to_merge[n] = bases; remain[n] = 0; - List<PyObject> acc = Generic.list(); - acc.add(this); + List<PyObject> acc = Generic.list(this); int empty_cnt = 0; Modified: trunk/jython/src/org/python/util/Generic.java =================================================================== --- trunk/jython/src/org/python/util/Generic.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/src/org/python/util/Generic.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -15,11 +15,22 @@ */ public class Generic { /** - * Makes a List with its generic type inferred from whatever its being assigned to. + * Makes a List with its generic type inferred from whatever it's being assigned to. */ public static <T> List<T> list() { return new ArrayList<T>(); } + /** + * Makes a List with its generic type inferred from whatever it's being assigned to filled with + * the items in <code>contents</code>. + */ + public static <T, U extends T> List<T> list(U...contents) { + List<T> l = new ArrayList<T>(contents.length); + for (T t : contents) { + l.add(t); + } + return l; + } /** * Makes a Map using generic types inferred from whatever this is being assigned to. Modified: trunk/jython/tests/java/javatests/ListTest.java =================================================================== --- trunk/jython/tests/java/javatests/ListTest.java 2009-01-11 03:21:25 UTC (rev 5915) +++ trunk/jython/tests/java/javatests/ListTest.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -472,8 +472,7 @@ int prevIndex = li.previousIndex(); TestSupport.assertThat(prevIndex == -1, "ListIterator.previousIndex() on empty List did not return -1"); - List<Object> l = Generic.list(); - l.add(1); + List<Object> l = Generic.list(1); li = newInstance(l).listIterator(); TestSupport.assertThat(!li.hasPrevious(), "ListIterator.hasPrevious() is true with nothing previous"); @@ -494,10 +493,7 @@ TestSupport.fail("expected IllegalStateException"); } catch (IllegalStateException e) {} } - l = Generic.list(); - l.add(0); - l.add(1); - l.add(2); + l = Generic.list(0, 1, 2); li = newInstance(l).listIterator(); for (int i = 0, n = l.size(); i < n; i++) { TestSupport.assertThat(li.next().equals(i), Added: trunk/jython/tests/java/javatests/PySetInJavaTest.java =================================================================== --- trunk/jython/tests/java/javatests/PySetInJavaTest.java (rev 0) +++ trunk/jython/tests/java/javatests/PySetInJavaTest.java 2009-01-11 06:04:11 UTC (rev 5916) @@ -0,0 +1,92 @@ +package javatests; + +import java.util.Iterator; +import java.util.Random; +import java.util.Set; + +import org.python.core.PySet; +import org.python.core.PyTuple; +import org.python.util.Generic; + +public class PySetInJavaTest { + + public static Set<Object> createPySetContainingJavaObjects() { + PySet s = new PySet(); + s.add("value"); + s.add(new Random()); + return s; + } + + public static void testPySetAsJavaSet() { + PySet s = new PySet(); + String v = "value"; + check(s.add(v));// Add a String as it should be wrapped in PyString + check(!s.add(v)); + String[] asArray = (String[])s.toArray(new String[0]);// The array type should be the same + // and it should be resized properly + check(asArray.length == 1); + check(asArray[0] == v); + Object[] naiveArray = s.toArray(); + check(naiveArray.length == 1); + check(naiveArray[0] == v); + // Add a Random as it should be wrapped in a generic PyObject; go through addAll to give it + // a little exercise + Random rand = new Random(); + check(s.addAll(Generic.list(rand))); + check(!s.addAll(Generic.list(rand, v))); + naiveArray = s.toArray(); + check(naiveArray.length == 2); + for (Object object : naiveArray) { + if (object instanceof String) { + check(object == v); + } else { + check(object == rand, "Should be 'value' or rand, not " + object); + } + } + check(!s.remove(new Random()), "The Random in the set shouldn't match a new Random"); + check(s.remove(rand)); + check(s.removeAll(Generic.list(rand, v)), + "The set should contain v and indicate it removed it"); + check(s.isEmpty()); + check(s.addAll(Generic.list(rand, v))); + check(2 == s.size(), "There should be 2 items, not " + s.size()); + check(s.containsAll(Generic.list(rand, v))); + check(!s.containsAll(Generic.list(rand, v, "other"))); + check(s.retainAll(Generic.list(rand))); + check(!s.retainAll(Generic.list(rand))); + check(s.addAll(Generic.list(rand, v))); + check(2 == s.size(), "There should be 2 items, not " + s.size()); + check(!s.addAll(Generic.list(rand, v))); + check(2 == s.size(), "There should be 2 items, not " + s.size()); + } + + public static void accessAndRemovePySetItems(Set<Object> items) { + check(items instanceof PySet, "The set shouldn't be __tojava'd into " + items.getClass()); + check(items.size() == 3, "Should be 3 items, not " + items.size()); + check(items.contains("value"), "The set from Python should contain 'value'"); + check(!items.contains(new Random()), "The set contains a particular Random"); + Iterator<Object> it = items.iterator(); + while (it.hasNext()) { + Object object = it.next(); + check(items.contains(object), "The set should contain all items from its iterator"); + if (object instanceof String) { + check(object.equals("value"), "The string should be 'value', not '" + object + "'"); + } else { + check(object instanceof Random || object instanceof PyTuple, + "The objects in the set should be a String, a Random or a PyTuple, not a " + + object.getClass()); + } + it.remove(); // Tests that removing on the iterator works + } + } + + private static void check(boolean testVal) { + check(testVal, ""); + } + + private static void check(boolean testVal, String failMsg) { + if (!testVal) { + throw new RuntimeException(failMsg); + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-11 03:21:30
|
Revision: 5915 http://jython.svn.sourceforge.net/jython/?rev=5915&view=rev Author: cgroves Date: 2009-01-11 03:21:25 +0000 (Sun, 11 Jan 2009) Log Message: ----------- Cleanup Modified Paths: -------------- trunk/jython/src/org/python/core/PyDictionary.java trunk/jython/src/org/python/core/PyObjectList.java trunk/jython/src/org/python/core/PySequenceList.java trunk/jython/tests/java/javatests/ListTest.java trunk/jython/tests/java/javatests/TestSupport.java Modified: trunk/jython/src/org/python/core/PyDictionary.java =================================================================== --- trunk/jython/src/org/python/core/PyDictionary.java 2009-01-11 01:12:16 UTC (rev 5914) +++ trunk/jython/src/org/python/core/PyDictionary.java 2009-01-11 03:21:25 UTC (rev 5915) @@ -12,7 +12,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import org.python.core.PyMapSet.PySetIter; import org.python.expose.ExposedClassMethod; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; @@ -27,7 +26,7 @@ public class PyDictionary extends PyObject implements ConcurrentMap { public static final PyType TYPE = PyType.fromClass(PyDictionary.class); - + protected final ConcurrentMap<PyObject, PyObject> table; /** @@ -39,7 +38,6 @@ /** * For derived types - * @param subtype */ public PyDictionary(PyType subtype) { super(subtype); @@ -47,31 +45,27 @@ } /** - * Create an new dictionary which is based on the hashtable. - * @param t the hashtable used. The supplied hashtable is used as - * is and must only contain PyObject key:value pairs. + * Create a new dictionary which is based on given map. */ public PyDictionary(Map<PyObject, PyObject> t) { table = new ConcurrentHashMap<PyObject, PyObject>(t); } - /** - * Create an new dictionary which is based on the map and for derived types. - * @param subtype - * @param t the hashtable used. The supplied hashtable is used as - * is and must only contain PyObject key:value pairs. + /** + * Create a new derived dictionary which is based on the given map. */ public PyDictionary(PyType subtype, Map<PyObject, PyObject> t) { super(subtype); table = new ConcurrentHashMap<PyObject, PyObject>(t); } - + /** * Create a new dictionary with the element as content. - * @param elements The initial elements that is inserted in the - * dictionary. Even numbered elements are keys, - * odd numbered elements are values. + * + * @param elements + * The initial elements that is inserted in the dictionary. Even numbered elements + * are keys, odd numbered elements are values. */ public PyDictionary(PyObject elements[]) { this(); @@ -85,7 +79,7 @@ protected final void dict___init__(PyObject[] args, String[] keywords) { updateCommon(args, keywords, "dict"); } - + public static PyObject fromkeys(PyObject keys) { return fromkeys(keys, Py.None); } @@ -210,10 +204,10 @@ } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.dict___eq___doc) - final PyObject dict___eq__(PyObject ob_other) { + final PyObject dict___eq__(PyObject ob_other) { PyType thisType = getType(); PyType otherType = ob_other.getType(); - if (otherType != thisType && !thisType.isSubType(otherType) + if (otherType != thisType && !thisType.isSubType(otherType) && !otherType.isSubType(thisType)) { return null; } @@ -291,7 +285,7 @@ final int dict___cmp__(PyObject ob_other) { PyType thisType = getType(); PyType otherType = ob_other.getType(); - if (otherType != thisType && !thisType.isSubType(otherType) + if (otherType != thisType && !thisType.isSubType(otherType) && !otherType.isSubType(thisType)) { return -2; } @@ -435,7 +429,7 @@ } for (int i = 0; i < keywords.length; i++) { dict___setitem__(Py.newString(keywords[i]), args[nargs + i]); - } + } } /** @@ -539,7 +533,7 @@ } } - + /** * Return a value based on key * from the dictionary. @@ -578,18 +572,17 @@ @ExposedMethod(doc = BuiltinDocs.dict_popitem_doc) final PyObject dict_popitem() { - Iterator it = table.entrySet().iterator(); + Iterator<Entry<PyObject, PyObject>> it = table.entrySet().iterator(); if (!it.hasNext()) throw Py.KeyError("popitem(): dictionary is empty"); - Entry entry = (Entry)it.next(); - PyTuple tuple = new PyTuple( - (PyObject)entry.getKey(), (PyObject)entry.getValue()); + Entry<PyObject, PyObject> entry = it.next(); + PyTuple tuple = new PyTuple(entry.getKey(), entry.getValue()); it.remove(); return tuple; } /** - * Return a copy of the dictionarys list of (key, value) tuple + * Return a copy of the dictionary's list of (key, value) tuple * pairs. */ public PyList items() { @@ -606,7 +599,7 @@ } /** - * Return a copy of the dictionarys list of keys. + * Return a copy of the dictionary's list of keys. */ public PyList keys() { return dict_keys(); @@ -623,7 +616,7 @@ } /** - * Return an interator over (key, value) pairs. + * Returns an iterator over (key, value) pairs. */ public PyObject iteritems() { return dict_iteritems(); @@ -635,7 +628,7 @@ } /** - * Return an interator over (key, value) pairs. + * Returns an iterator over the dictionary's keys. */ public PyObject iterkeys() { return dict_iterkeys(); @@ -647,7 +640,7 @@ } /** - * Return an interator over (key, value) pairs. + * Returns an iterator over the dictionary's values. */ public PyObject itervalues() { return dict_itervalues(); @@ -703,7 +696,7 @@ iterator = items.iterator(); size = items.size(); } - + public PyObject __iternext__() { if (table.size() != size) { throw Py.RuntimeError("dictionary changed size during iteration"); @@ -716,13 +709,12 @@ } } - /* The following methods implement the java.util.Map interface - which allows PyDictionary to be passed to java methods that take - java.util.Map as a parameter. Basically, the Map methods are a - wrapper around the PyDictionary's Map container stored in member - variable 'table'. These methods simply convert java Object to - PyObjects on insertion, and PyObject to Objects on retrieval. */ - + /* + * The following methods implement the java.util.Map interface which allows PyDictionary to be + * passed to java methods that take java.util.Map as a parameter. Basically, the Map methods are + * a wrapper around the PyDictionary's Map container stored in member variable 'table'. These + * methods convert java Object to PyObjects on insertion, and PyObject to Objects on retrieval. + */ /** @see java.util.Map#entrySet() */ public Set entrySet() { return new PyMapEntrySet(table.entrySet()); @@ -733,17 +725,15 @@ return new PyMapKeyValSet(table.keySet()); } - /** Return a copy of the dictionarys list of values. */ + /** @see java.util.Map#values() */ public Collection values() { return new PyMapKeyValSet(table.values()); } - /** @see java.util.Map#putAll(Map map) */ public void putAll(Map map) { - Iterator i = map.entrySet().iterator(); - while (i.hasNext()) { - Entry entry = (Entry)i.next(); + for (Object o : map.entrySet()) { + Entry entry = (Entry)o; table.put(Py.java2py(entry.getKey()), Py.java2py(entry.getValue())); } } @@ -772,19 +762,19 @@ public boolean containsKey(Object key) { return table.containsKey(Py.java2py(key)); } - - /** @see java.util.Map#isEmpty(Object key) */ + + /** @see java.util.Map#isEmpty() */ public boolean isEmpty() { return table.isEmpty(); } - - /** @see java.util.Map#size(Object key) */ + + /** @see java.util.Map#size() */ public int size() { return table.size(); } /** Convert return values to java objects */ - static final Object tojava(Object val) { + final static Object tojava(Object val) { return val == null ? null : ((PyObject)val).__tojava__(Object.class); } @@ -805,19 +795,20 @@ } } + /** Basic implementation of Entry that just holds onto a key and value and returns them. */ -class SimpleEntry<K, V> implements Entry<K, V> { - - public SimpleEntry(K key, V value){ +class SimpleEntry implements Entry { + + public SimpleEntry(Object key, Object value){ this.key = key; this.value = value; } - - public K getKey() { + + public Object getKey() { return key; } - public V getValue() { + public Object getValue() { return value; } @@ -841,31 +832,29 @@ return key + "=" + value; } - public V setValue(V val) { + public Object setValue(Object val) { throw new UnsupportedOperationException("Not supported by this view"); } - protected K key; + protected Object key; - protected V value; + protected Object value; } /** - * Wrapper for a Entry object returned from the java.util.Set - * object which in turn is returned by the entrySet method of - * java.util.Map. This is needed to correctly convert from PyObjects - * to java Objects. Note that we take care in the equals and hashCode - * methods to make sure these methods are consistent with Entry - * objects that contain java Objects for a value so that on the java - * side they can be reliable compared. + * Wrapper for a Entry object returned from the java.util.Set object which in turn is returned by + * the entrySet method of java.util.Map. This is needed to correctly convert from PyObjects to java + * Objects. Note that we take care in the equals and hashCode methods to make sure these methods are + * consistent with Entry objects that contain java Objects for a value so that on the java side they + * can be reliable compared. */ class PyToJavaMapEntry extends SimpleEntry { - /** Create a copy of the Entry with Py.None coverted to null */ + /** Create a copy of the Entry with Py.None converted to null */ PyToJavaMapEntry(Entry entry) { super(entry.getKey(), entry.getValue()); } - + public boolean equals(Object o) { if (o == null || !(o instanceof Entry)) return false; Entry me = new JavaToPyMapEntry((Entry)o); @@ -877,7 +866,7 @@ public Object getKey() { return PyDictionary.tojava(key); } - + public Object getValue() { return PyDictionary.tojava(value); } @@ -892,24 +881,22 @@ } /** - * MapEntry Object for java MapEntry objects passed to the java.util.Set - * interface which is returned by the entrySet method of PyDictionary. - * Essentially like PyTojavaMapEntry, but going the other way converting java - * Objects to PyObjects. + * MapEntry Object for java MapEntry objects passed to the java.util.Set interface which is returned + * by the entrySet method of PyDictionary. Essentially like PyTojavaMapEntry, but going the other + * way converting java Objects to PyObjects. */ class JavaToPyMapEntry extends SimpleEntry { - + public JavaToPyMapEntry(Entry entry) { super(Py.java2py(entry.getKey()), Py.java2py(entry.getValue())); } } /** - * Wrapper collection class for the keySet and values methods of - * java.util.Map + * Wrapper collection class for the keySet and values methods of java.util.Map */ class PyMapKeyValSet extends PyMapSet { - + PyMapKeyValSet(Collection coll) { super(coll); } @@ -917,21 +904,18 @@ Object toJava(Object o) { return PyDictionary.tojava(o); } - + Object toPython(Object o) { return Py.java2py(o); } } /** - * Set wrapper for the java.util.EntrySet method. Entry - * objects are wrapped further in JavaToPyMapEntry and - * PyToJavaMapEntry. Note - The set interface is reliable for - * standard objects like strings and integers, but may be inconstant - * for other types of objects since the equals method may return false - * for Entry object that hold more elaborate PyObject types. - * However, We insure that this iterface works when the Entry - * object originates from a Set object retrieved from a PyDictionary. + * Set wrapper for the entrySet method. Entry objects are wrapped further in JavaToPyMapEntry and + * PyToJavaMapEntry. Note - The set interface is reliable for standard objects like strings and + * integers, but may be inconsistent for other types of objects since the equals method may return + * false for Entry object that hold more elaborate PyObject types. However, we insure that this + * interface works when the Entry object originates from a Set object retrieved from a PyDictionary. */ class PyMapEntrySet extends PyMapSet { @@ -939,13 +923,13 @@ super(coll); } - // We know that PyMapEntrySet will only contains Entrys, so - // if the object being passed in is null or not a Entry, then - // return null which will match nothing for remove and contains methods. + // We know that PyMapEntrySet will only contains entries, so if the object being passed in is + // null or not an Entry, then return null which will match nothing for remove and contains + // methods. Object toPython(Object o) { if(o == null || !(o instanceof Entry)) return null; - if(o instanceof PyToJavaMapEntry) { + if (o instanceof PyToJavaMapEntry) { // Use the original entry from PyDictionary return ((PyToJavaMapEntry)o).getEntry(); } else { @@ -959,15 +943,12 @@ } /** - * PyMapSet serves as a wrapper around Set Objects returned by the - * java.util.Map interface of PyDictionary. entrySet, values and - * keySet methods return this type for the java.util.Map - * implementation. This class is necessary as a wrapper to convert - * PyObjects to java Objects for methods that return values, and - * convert Objects to PyObjects for methods that take values. The - * translation is necessary to provide java access to jython - * dictionary objects. This wrapper also provides the expected backing - * functionality such that changes to the wrapper set or reflected in + * PyMapSet serves as a wrapper around Set Objects returned by the java.util.Map interface of + * PyDictionary. entrySet, values and keySet methods return this type for the java.util.Map + * implementation. This class is necessary as a wrapper to convert PyObjects to java Objects for + * methods that return values, and convert Objects to PyObjects for methods that take values. The + * translation is necessary to provide java access to jython dictionary objects. This wrapper also + * provides the expected backing functionality such that changes to the wrapper set or reflected in * PyDictionary. */ abstract class PyMapSet extends AbstractSet { @@ -983,15 +964,15 @@ public int size() { return coll.size(); } - + public boolean contains(Object o) { return coll.contains(toPython(o)); } - + public boolean remove(Object o) { return coll.remove(toPython(o)); } - + public void clear() { coll.clear(); } @@ -1013,15 +994,15 @@ public Object next() { return toJava(itr.next()); } - + public void remove() { itr.remove(); } } - + public Iterator iterator() { return new PySetIter(coll.iterator()); } - + private final Collection coll; } Modified: trunk/jython/src/org/python/core/PyObjectList.java =================================================================== --- trunk/jython/src/org/python/core/PyObjectList.java 2009-01-11 01:12:16 UTC (rev 5914) +++ trunk/jython/src/org/python/core/PyObjectList.java 2009-01-11 03:21:25 UTC (rev 5915) @@ -4,7 +4,6 @@ import java.io.Serializable; import java.util.AbstractList; import java.util.Collection; -import java.util.Iterator; import java.util.RandomAccess; /** @@ -20,17 +19,15 @@ * @author Clark Updike */ public class PyObjectList - extends AbstractList implements RandomAccess, Cloneable, Serializable { + extends AbstractList<Object> implements RandomAccess, Cloneable, Serializable { - /* Design note: - * This class let's PySequenceList implement java.util.List by delegating - * to an instance of this. The major distinction is that the backing array - * is PyObject[], not Object[] (as you'd get by delegating to ArrayList). - * There are 2 major benefits: 1) A lot of casting can be avoided - * internally (although use of PySequenceList descendants as java - * collections does involve some casting); 2) PySequenceList descendants - * can still do bulk array operations, allowing better performance and - * reuse of much of the pre-collections bulk operation implementation. + /* + * Design note: This class lets PySequenceList implement java.util.List by delegating to it. The + * major distinction is that the backing array is PyObject[], not Object[] (as you'd get by + * delegating to ArrayList). There are 2 major benefits: 1) A lot of casting can be avoided + * internally (although use of PySequenceList descendants as java collections does involve some + * casting); 2) PySequenceList descendants can still do bulk array operations, allowing better + * performance and reuse of much of the pre-collections bulk operation implementation. */ @@ -49,7 +46,7 @@ array.baseArray = pyObjArr; } - public PyObjectList(Collection c) { + public PyObjectList(Collection<PyObject> c) { array = new PyObjectArray(); array.appendArray(c.toArray()); } @@ -62,8 +59,7 @@ * For internal jython usage, use {@link #pyadd(int, PyObject)}. */ public void add(int index, Object element) { - array.add(index, Py.java2py(element)); - modCount += array.getModCountIncr(); + pyadd(index, Py.java2py(element)); } public void pyadd(int index, PyObject element) { @@ -75,8 +71,7 @@ * For internal jython usage, use {@link #pyadd(PyObject)}. */ public boolean add(Object o) { - array.add(Py.java2py(o)); - modCount += array.getModCountIncr(); + pyadd(Py.java2py(o)); return true; } @@ -90,7 +85,7 @@ try { PyObjectList tol = (PyObjectList) super.clone(); tol.array = (PyObjectArray) array.clone(); - modCount = 0; + tol.modCount = 0; return tol; } catch (CloneNotSupportedException eCNSE) { throw new InternalError("Unexpected CloneNotSupportedException.\n" @@ -113,8 +108,7 @@ * Use <code>pyget(int)</code> for internal jython usage. */ public Object get(int index) { - PyObject obj = array.get(index); - return obj.__tojava__(Object.class); + return array.get(index).__tojava__(Object.class); } PyObject pyget(int index) { @@ -137,7 +131,7 @@ * Use <code>pyset(int, PyObject)</code> for internal jython usage. */ public Object set(int index, Object element) { - return array.set(index, Py.java2py(element) ).__tojava__(Object.class); + return pyset(index, Py.java2py(element)).__tojava__(Object.class); } PyObject pyset(int index, PyObject element) { @@ -148,11 +142,11 @@ return array.getSize(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends Object> c) { return addAll(size(), c); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends Object> c) { if (c instanceof PySequenceList) { PySequenceList cList = (PySequenceList)c; PyObject[] cArray = cList.getArray(); @@ -160,21 +154,20 @@ array.makeInsertSpace(index, cOrigSize); array.replaceSubArray(index, index + cOrigSize, cArray, 0, cOrigSize); } else { - // need to use add to convert anything pulled from a collection - // into a PyObject - for (Iterator i = c.iterator(); i.hasNext(); ) { - add(i.next()); + // need to use add to convert anything pulled from a collection into a PyObject + for (Object element : c) { + add(element); } } return c.size() > 0; } - /** - * Get the backing array. The array should generally not be modified. - * To get a copy of the array, see {@link #toArray()} which returns a copy. - * - * @return backing array object - */ + /** + * Get the backing array. The array should generally not be modified. To get a copy of the + * array, see {@link #toArray()} which returns a copy. + * + * @return backing array object + */ protected PyObject[] getArray() { return (PyObject[])array.getArray(); } Modified: trunk/jython/src/org/python/core/PySequenceList.java =================================================================== --- trunk/jython/src/org/python/core/PySequenceList.java 2009-01-11 01:12:16 UTC (rev 5914) +++ trunk/jython/src/org/python/core/PySequenceList.java 2009-01-11 03:21:25 UTC (rev 5915) @@ -30,7 +30,7 @@ list = new PyObjectList(elements); } - public PySequenceList(PyType type, Collection c) { + public PySequenceList(PyType type, Collection<PyObject> c) { super(type); list = new PyObjectList(c); } Modified: trunk/jython/tests/java/javatests/ListTest.java =================================================================== --- trunk/jython/tests/java/javatests/ListTest.java 2009-01-11 01:12:16 UTC (rev 5914) +++ trunk/jython/tests/java/javatests/ListTest.java 2009-01-11 03:21:25 UTC (rev 5915) @@ -1,151 +1,140 @@ -//Copyright (c) Corporation for National Research Initiatives +// Copyright (c) Corporation for National Research Initiatives package javatests; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; +import org.python.util.Generic; + /** * @author updikca1 */ public abstract class ListTest { - + public static ListTest getArrayListTest(final boolean makeReadOnly) { return new ListTest() { - public List newInstance(Collection c) { - List l = null; - if(c == null) { - l = new ArrayList(); + + public List<Object> newInstance(Collection<Object> c) { + List<Object> l = null; + if (c == null) { + l = Generic.list(); } else { - l = new ArrayList(c); + l = new ArrayList<Object>(c); } - return (makeReadOnly) - ? Collections.unmodifiableList(l) - : l; + return (makeReadOnly) ? Collections.unmodifiableList(l) : l; } + public boolean isReadOnly() { return makeReadOnly; - } + } }; } - - public static void verifyImutability(List l) { - + + public static void verifyImutability(List<Object> l) { String message = "Expected UnsupportedOperationException."; - try { - l.add(0, new Integer(0)); - TestSupport.assertThat(false, message); + l.add(0, 0); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} - try { - l.add(new Integer(0)); - TestSupport.assertThat(false, message); + l.add(0); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} - try { - l.addAll(null); - TestSupport.assertThat(false, message); + l.addAll(null); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} - try { - l.addAll(0, null); - TestSupport.assertThat(false, message); + l.addAll(0, null); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} - try { - l.clear(); - TestSupport.assertThat(false, message); + l.clear(); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} - try { - l.remove(0); - TestSupport.assertThat(false, message); + l.remove(0); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} - try { l.remove(new Object()); - TestSupport.assertThat(false, message); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} - try { - l.removeAll(null); - TestSupport.assertThat(false, message); + l.removeAll(null); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} - try { l.retainAll(null); - TestSupport.assertThat(false, message); + TestSupport.fail(message); } catch (UnsupportedOperationException e) {} try { - l.set(0,new Integer(0)); - TestSupport.assertThat(false, message); - } catch (UnsupportedOperationException e) {} + l.set(0, 0); + TestSupport.fail(message); + } catch (UnsupportedOperationException e) {} } - - private final List nullList; - - protected List defaultList() { - List l = new ArrayList(); + + private final List<Object> nullList; + + protected List<Object> defaultList() { + List<Object> l = Generic.list(); for (int i = 0; i < 4; i++) { - l.add(new Integer(i)); + l.add(i); } return newInstance(l); } - + /** * Implementations must supply an empty list if the collection is null. - * @param c Initial collection or null for empty. + * + * @param c + * Initial collection or null for empty. * @return the List instance */ - public List newInstance(Collection c) { + public List<Object> newInstance(Collection<Object> c) { throw new UnsupportedOperationException("This method must be overridden"); } - + /** * @return true if the list is read-only (like PyTuple) */ public boolean isReadOnly() { throw new UnsupportedOperationException("This method must be overridden"); } - + { nullList = newInstance(Arrays.asList(new Object[] {null})); } - + public void testAll() { - test_get(); test_equals(); test_size(); test_contains(); test_containsAll(); - try { defaultList().hashCode(); test_hashCode(); } catch (Exception e) { // skip unhashable types } - test_subList(); test_lastIndexOf(); test_listIterator(); test_toArray(); test_toArray_typed(); - - if(!isReadOnly()) { + if (!isReadOnly()) { test_add(); test_add_index(); test_set(); test_clear(); test_addAll(); - test_addAll_index(); + test_addAll_index(); test_remove(); test_remove_index(); test_removeAll(); @@ -154,481 +143,404 @@ verifyImutability(newInstance(null)); } } - + /** Tests get(int index) */ public void test_get() { - TestSupport.assertThat(defaultList().get(0).equals(new Integer(0)), - "get() did not return expected value of Integer(0)"); + List<Object> l = defaultList(); + TestSupport.assertThat(l.get(0).equals(0), + "get() did not return expected value of Integer(0)"); try { - defaultList().get(-1); - TestSupport.assertThat(false, - "get(<negative index>) did not throw IndexOutOfBoundsException"); + l.get(-1); + TestSupport.fail("get(<negative index>) did not throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} - try { - defaultList().get(-1); - TestSupport.assertThat(false, - "get(<index too big>) did not throw IndexOutOfBoundsException"); + l.get(l.size()); + TestSupport.fail("get(<index too big>) did not throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} } - + /** Tests set(int index, Object element) */ public void test_set() { - try { newInstance(null).set(-1, "spam"); - TestSupport.assertThat(false, - "get(<negative index>) did not throw IndexOutOfBoundsException"); + TestSupport.fail("get(<negative index>) did not throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} - try { newInstance(null).set(0, "spam"); - TestSupport.assertThat(false, - "set(<index too big>) did not throw IndexOutOfBoundsException"); + TestSupport.fail("set(<index too big>) did not throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} - - List a = defaultList(); - a.set(a.size() - 1 , "spam"); - TestSupport.assertThat(a.get(a.size() - 1).equals("spam"), - "set() object was not retrieved via get()"); + List<Object> a = defaultList(); + a.set(a.size() - 1, "spam"); + TestSupport.assertThat(a.get(a.size() - 1).equals("spam"), + "set() object was not retrieved via get()"); } - - /** Tests add(Object o) */ - public void test_add() { - List a = newInstance(null); + + /** Tests add(Object o) */ + public void test_add() { + List<Object> a = newInstance(null); for (int i = 0; i < 4; i++) { - a.add(new Integer(i)); + a.add(i); } TestSupport.assertEquals(a, defaultList(), "add(Object o) failed"); } - + /** Tests isEmpty() */ public void test_isEmpty() { - List a = newInstance(null); - TestSupport.assertThat(a.isEmpty(), - "isEmpty() is false on an emtpy List"); + List<Object> a = newInstance(null); + TestSupport.assertThat(a.isEmpty(), "isEmpty() is false on an emtpy List"); a.addAll(defaultList()); - TestSupport.assertThat(!a.isEmpty(), - "isEmpty() is true on a non-empty List)" ); + TestSupport.assertThat(!a.isEmpty(), "isEmpty() is true on a non-empty List)"); a.clear(); - TestSupport.assertThat(a.isEmpty(), - "isEmpty() is false on an emtpy List"); + TestSupport.assertThat(a.isEmpty(), "isEmpty() is false on an emtpy List"); } - + /** Tests size() */ - public void test_size() { - List b = newInstance(null); + public void test_size() { + List<Object> b = newInstance(null); TestSupport.assertThat(b.size() == 0, "empty list size was not 0"); - TestSupport.assertThat(defaultList().size() == 4, - "default list did not have a size of 4"); + TestSupport.assertThat(defaultList().size() == 4, "default list did not have a size of 4"); } - - /** Tests add(int index, Object element) */ + + /** Tests add(int index, Object element) */ public void test_add_index() { - List a = newInstance(null); - List b = defaultList(); + List<Object> a = newInstance(null); + List<Object> b = defaultList(); for (int i = 0; i < b.size(); i++) { a.add(i, b.get(i)); } - try { - a.add(a.size() + 1, new Integer(a.size() + 1)); - TestSupport.assertThat(false, "expected IndexOutOfBoundsException"); + a.add(a.size() + 1, new Integer(a.size() + 1)); + TestSupport.fail("expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} - try { - a.add(-1, new Integer(-1)); - TestSupport.assertThat(false, "expected IndexOutOfBoundsException"); - } catch (IndexOutOfBoundsException e) {} + a.add(-1, new Integer(-1)); + TestSupport.fail("expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) {} } - - /** Tests equals(Object o)*/ + + /** Tests equals(Object o) */ public void test_equals() { - TestSupport.assertEquals(defaultList(), defaultList(), - "Identical lists weren't equal()"); - TestSupport.assertNotEquals(newInstance(null), defaultList(), - "Different lists were equal()"); - TestSupport.assertNotEquals(newInstance(null), new Object(), - "List was equal to a non-List type"); + TestSupport.assertEquals(defaultList(), defaultList(), "Identical lists weren't equal()"); + TestSupport.assertNotEquals(newInstance(null), + defaultList(), + "Different lists were equal()"); + TestSupport.assertNotEquals(newInstance(null), + new Object(), + "List was equal to a non-List type"); } - + /** Tests addAll(Collection c) */ public void test_addAll() { - List a = defaultList(); - List b = defaultList(); - - TestSupport.assertThat(a.addAll(b) == true, - "Mutating addAll(Collection) returned false"); - TestSupport.assertThat(a.addAll(newInstance(null)) == false, - "Idempotent addAll(Collection) returned true"); - TestSupport.assertThat(b.addAll(b) == true, - "Mutating addAll(Collection) returned false"); - TestSupport.assertEquals(a, b, - "Expected equal objects from addAll(collection)"); - TestSupport.assertThat(a.size() == 8, - "Expected List to have size 8 after addAll(Collection)"); + List<Object> a = defaultList(); + List<Object> b = defaultList(); + TestSupport.assertThat(a.addAll(b) == true, "Mutating addAll(Collection) returned false"); + TestSupport.assertThat(a.addAll(newInstance(null)) == false, + "Idempotent addAll(Collection) returned true"); + TestSupport.assertThat(b.addAll(b) == true, "Mutating addAll(Collection) returned false"); + TestSupport.assertEquals(a, b, "Expected equal objects from addAll(collection)"); + TestSupport.assertThat(a.size() == 8, + "Expected List to have size 8 after addAll(Collection)"); } - - /** Tests indexOf(Object o) */ + + /** Tests indexOf(Object o) */ public void indexOf() { - TestSupport.assertThat(defaultList().indexOf(new Integer(3)) == 3, - "indexOf(3) did not return 3"); - TestSupport.assertThat(defaultList().indexOf(new Integer(42)) == -1, - "indexOf() non-existing entry did not return -1"); - TestSupport.assertThat(defaultList().indexOf(null) == -1, - "indexOf() non-existing null did not return -1"); - + TestSupport.assertThat(defaultList().indexOf(3) == 3, "indexOf(3) did not return 3"); + TestSupport.assertThat(defaultList().indexOf(42) == -1, + "indexOf() non-existing entry did not return -1"); + TestSupport.assertThat(defaultList().indexOf(null) == -1, + "indexOf() non-existing null did not return -1"); } - - /** Tests contains(Object o) */ - public void test_contains() { - TestSupport.assertThat(defaultList().contains(new Integer(42)) == false, - "contains() returned true for non-existing entry"); - TestSupport.assertThat(defaultList().contains(new Integer(0)) == true, - "contains() returned false for existing entry"); - TestSupport.assertThat(nullList.contains(null) == true, - "contains() returned false for existing null entry"); - TestSupport.assertThat(defaultList().contains(null) == false, - "contains() returned true for non-existing null entry"); + + /** Tests contains(Object o) */ + public void test_contains() { + TestSupport.assertThat(defaultList().contains(42) == false, + "contains() returned true for non-existing entry"); + TestSupport.assertThat(defaultList().contains(0) == true, + "contains() returned false for existing entry"); + TestSupport.assertThat(nullList.contains(null) == true, + "contains() returned false for existing null entry"); + TestSupport.assertThat(defaultList().contains(null) == false, + "contains() returned true for non-existing null entry"); } - + /** Tests remove(Object o) */ public void test_remove() { - List a = defaultList(); + List<Object> a = defaultList(); a.add(null); - TestSupport.assertThat(a.remove(null) == true, - "remove() existing null entry returned false"); - TestSupport.assertThat(a.remove(null) == false, - "remove() non-existing null entry returned false"); + TestSupport.assertThat(a.remove(null) == true, + "remove() existing null entry returned false"); + TestSupport.assertThat(a.remove(null) == false, + "remove() non-existing null entry returned false"); a.add("spam"); - TestSupport.assertThat(a.remove("spam") == true, - "remove() existing entry returned false"); - TestSupport.assertThat(a.remove("spam") == false, - "remove() non-existing entry returned true"); + TestSupport.assertThat(a.remove("spam") == true, "remove() existing entry returned false"); + TestSupport.assertThat(a.remove("spam") == false, + "remove() non-existing entry returned true"); } - - + /** Tests remove(int index) */ - public void test_remove_index() { - - List a = defaultList(); + public void test_remove_index() { + List<Object> a = defaultList(); for (int i = 0, n = a.size(); i < n; i++) { a.remove(0); } - TestSupport.assertThat(a.size() == 0, - "remove()-d all entries but size() not 0"); - + TestSupport.assertThat(a.size() == 0, "remove()-d all entries but size() not 0"); try { a.remove(0); - TestSupport.assertThat(false, - "removing a non-existing index did not throw exception"); - } catch(IndexOutOfBoundsException e) {} + TestSupport.fail("removing a non-existing index did not throw exception"); + } catch (IndexOutOfBoundsException e) {} } - + /** Tests lastIndexOf(Object o) */ public void test_lastIndexOf() { - // avoid calling any mutable methods - List l = new ArrayList(defaultList()); - l.add(new Integer(0)); - + // avoid calling any mutable methods + List<Object> l = new ArrayList<Object>(defaultList()); + l.add(0); // now get the immutable version - List a = newInstance(l); - - TestSupport.assertThat(a.lastIndexOf(new Integer(0)) == 4, - "lastIndexOf() did not return 4"); - TestSupport.assertThat(a.lastIndexOf(new Integer(42)) == -1, - "lastIndexOf() non-existing value did not return -1"); + List<Object> a = newInstance(l); + TestSupport.assertThat(a.lastIndexOf(0) == 4, "lastIndexOf() did not return 4"); + TestSupport.assertThat(a.lastIndexOf(42) == -1, + "lastIndexOf() non-existing value did not return -1"); } - - /** Tests removeAll(Collection c) */ + + /** Tests removeAll(Collection c) */ public void test_removeAll() { - List a = defaultList(); - TestSupport.assertThat(a.removeAll(a) == true, - "mutating removeAll() did not return true"); - TestSupport.assertThat(a.removeAll(a) == false, - "idempotent removeAll did not return false"); - TestSupport.assertThat(a.removeAll(nullList) == false, - "idempotent removeAll did not return false"); - - List yanl = newInstance(null); + List<Object> a = defaultList(); + TestSupport.assertThat(a.removeAll(a) == true, "mutating removeAll() did not return true"); + TestSupport.assertThat(a.removeAll(a) == false, "idempotent removeAll did not return false"); + TestSupport.assertThat(a.removeAll(nullList) == false, + "idempotent removeAll did not return false"); + List<Object> yanl = newInstance(null); yanl.addAll(nullList); - TestSupport.assertThat(yanl.removeAll(nullList) == true, - "mutating removeAll() did not return true"); - TestSupport.assertThat(yanl.size() == 0, - "empty list had non-zero size"); + TestSupport.assertThat(yanl.removeAll(nullList) == true, + "mutating removeAll() did not return true"); + TestSupport.assertThat(yanl.size() == 0, "empty list had non-zero size"); TestSupport.assertThat(yanl.removeAll(newInstance(null)) == false, - "idempotent removeAll did not return false"); - + "idempotent removeAll did not return false"); } - - /** Tests addAll(int index, Collection c) */ + + /** Tests addAll(int index, Collection c) */ public void test_addAll_index() { - List a = defaultList(); - List b = newInstance(null); - TestSupport.assertThat(b.addAll(0,a) == true, - "mutating addAll(index, Collection) did not return true"); - TestSupport.assertEquals(a, b, - "addAll(index, Collection) instances failed equals test"); - TestSupport.assertThat(a.addAll(0, newInstance(null)) == false, - "idempotent addAll(index, Collection) did not return false"); - TestSupport.assertThat(b.addAll(0,b) == true, - "mutating addAll(index, Collection) did not return true"); - + List<Object> a = defaultList(); + List<Object> b = newInstance(null); + TestSupport.assertThat(b.addAll(0, a) == true, + "mutating addAll(index, Collection) did not return true"); + TestSupport.assertEquals(a, b, "addAll(index, Collection) instances failed equals test"); + TestSupport.assertThat(a.addAll(0, newInstance(null)) == false, + "idempotent addAll(index, Collection) did not return false"); + TestSupport.assertThat(b.addAll(0, b) == true, + "mutating addAll(index, Collection) did not return true"); // Since PyObjectList has some specific handling when it detects // addAll on a PySequenceList, make sure the general case works. b = newInstance(null); - b.addAll(new ArrayList(defaultList())); - TestSupport.assertEquals(defaultList(), b, - "addAll(index, <ArrayList>) failed equals test"); + b.addAll(new ArrayList<Object>(defaultList())); + TestSupport.assertEquals(defaultList(), b, "addAll(index, <ArrayList>) failed equals test"); } - - /** Tests hashCode() */ + /** Tests hashCode() */ public void test_hashCode() { - List a = defaultList(); - TestSupport.assertThat(a.hashCode() == defaultList().hashCode(), - "Instances with same internal state have different hashcode"); - TestSupport.assertThat(a.hashCode() != newInstance(null).hashCode(), - "Instances with different internal state have the same hashcode"); - + List<Object> a = defaultList(); + TestSupport.assertThat(a.hashCode() == defaultList().hashCode(), + "Instances with same internal state have different hashcode"); + TestSupport.assertThat(a.hashCode() != newInstance(null).hashCode(), + "Instances with different internal state have the same hashcode"); if (isReadOnly() == false) { - List b = newInstance(null); + List<Object> b = newInstance(null); b.addAll(a); b.remove(0); - TestSupport.assertThat(a.hashCode()!= b.hashCode(), - "Instances with different internal state have the same hashcode"); + TestSupport.assertThat(a.hashCode() != b.hashCode(), + "Instances with different internal state have the same hashcode"); } - } - - /** Tests clear() */ + + /** Tests clear() */ public void test_clear() { - List a = defaultList(); + List<Object> a = defaultList(); a.clear(); - TestSupport.assertThat(a.size() == 0, - "clear()-ed list did not have size of 0"); + TestSupport.assertThat(a.size() == 0, "clear()-ed list did not have size of 0"); } - - /** Tests subList(int fromIndex, int toIndex) */ + + /** Tests subList(int fromIndex, int toIndex) */ public void test_subList() { - List a = defaultList(); - TestSupport.assertThat((a.subList(0, a.size()) != a), - "subList() returned the same instance"); - TestSupport.assertEquals(a.subList(0, a.size()), a, - "Complete subList() did not equal original List"); - TestSupport.assertThat(a.subList(0,0).size() == 0, - "empty subList had non-zero size"); - + List<Object> a = defaultList(); + TestSupport.assertThat((a.subList(0, a.size()) != a), + "subList() returned the same instance"); + TestSupport.assertEquals(a.subList(0, a.size()), + a, + "Complete subList() did not equal original List"); + TestSupport.assertThat(a.subList(0, 0).size() == 0, "empty subList had non-zero size"); try { - a.subList(-1,1); - TestSupport.assertThat(false, "Expected IndexOutOfBoundsException"); + a.subList(-1, 1); + TestSupport.fail("Expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} - try { - a.subList(1,0); - TestSupport.assertThat(false, "Expected IllegalArgumentException"); + a.subList(1, 0); + TestSupport.fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) {} - try { - a.subList(0,a.size() + 1); - TestSupport.assertThat(false, "Expected IndexOutOfBoundsException"); + a.subList(0, a.size() + 1); + TestSupport.fail("Expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} - if (!isReadOnly()) { - a.subList(0, a.size()).clear(); - TestSupport.assertThat(a.size() == 0, - "clear()-ed sublist did not have zero size"); - List c = newInstance(null); + TestSupport.assertThat(a.size() == 0, "clear()-ed sublist did not have zero size"); + List<Object> c = newInstance(null); c.addAll(defaultList()); - List d = c.subList(1,3); - TestSupport.assertThat(d.size() == 2, - "Expected subList to have size of 2"); - TestSupport.assertThat(c.set(1,"canned").equals(new Integer(1)), - "subList.set() did not return Integer(1) from index 1" + - " of defaultList"); + List<Object> d = c.subList(1, 3); + TestSupport.assertThat(d.size() == 2, "Expected subList to have size of 2"); + TestSupport.assertThat(c.set(1, "canned").equals(1), + "subList.set() did not return Integer(1) from index 1" + + " of defaultList"); TestSupport.assertThat(d.get(0).equals("canned"), - "subList does not update with changes to parent"); - d.set(0,"spam"); - TestSupport.assertThat(c.get(1).equals("spam"), - "parent does not update with changes to subList child"); + "subList does not update with changes to parent"); + d.set(0, "spam"); + TestSupport.assertThat(c.get(1).equals("spam"), + "parent does not update with changes to subList child"); } else { - List b = a.subList(0, a.size()); + List<Object> b = a.subList(0, a.size()); verifyImutability(b); } - } - + /** Tests retainAll(Collection c) */ - public void test_retainAll() { - List a = defaultList(); + public void test_retainAll() { + List<Object> a = defaultList(); a.retainAll(defaultList()); - TestSupport.assertEquals(a, defaultList(), - "retainAll(<equal List>) does not equal original list"); + TestSupport.assertEquals(a, + defaultList(), + "retainAll(<equal List>) does not equal original list"); a = defaultList(); a.retainAll(newInstance(null)); - TestSupport.assertThat(a.size() == 0, - "retainAll(<empty List>))does not have size of zero"); - + TestSupport.assertThat(a.size() == 0, "retainAll(<empty List>))does not have size of zero"); a = defaultList(); a.remove(0); a.remove(0); - a.add(new Integer(4)); - a.add(new Integer(5)); - List b = newInstance(null); - b.add(new Integer(2)); - b.add(new Integer(3)); + a.add(4); + a.add(5); + List<Object> b = newInstance(null); + b.add(2); + b.add(3); a.retainAll(b); - TestSupport.assertEquals(a, b, - "retainAll() on overlap of indices [2,3] did not return that List"); + TestSupport.assertEquals(a, + b, + "retainAll() on overlap of indices [2,3] did not return that List"); } - + /** Tests containsAll(Collection c) */ public void test_containsAll() { TestSupport.assertThat(defaultList().containsAll(defaultList()), - "containsAll(<identical List> was false"); - TestSupport.assertThat(defaultList().containsAll(newInstance(null)), - "containsAll(<empty List>) was false"); + "containsAll(<identical List> was false"); + TestSupport.assertThat(defaultList().containsAll(newInstance(null)), + "containsAll(<empty List>) was false"); TestSupport.assertThat(newInstance(null).containsAll(defaultList()) == false, - "containsAll(<disjoint List>) returned true"); - TestSupport.assertThat(defaultList().containsAll(defaultList().subList(1,3)), - "containsAll(<subList>) was false"); + "containsAll(<disjoint List>) returned true"); + TestSupport.assertThat(defaultList().containsAll(defaultList().subList(1, 3)), + "containsAll(<subList>) was false"); } - + /** Tests iterator() */ public void test_iterator() { - - TestSupport.assertThat(newInstance(null).iterator().hasNext() == false, - "Iterator for empty list thinks it hasNext()"); + TestSupport.assertThat(newInstance(null).iterator().hasNext() == false, + "Iterator for empty list thinks it hasNext()"); try { newInstance(null).iterator().next(); - TestSupport.assertThat(false, "expected NoSuchElementException"); + TestSupport.fail("expected NoSuchElementException"); } catch (NoSuchElementException e) {} - - List a = defaultList(); + List<Object> a = defaultList(); int i = 0; - for (Iterator iter = a.iterator(); iter.hasNext(); ) { - TestSupport.assertThat(iter.next() == a.get(i++), - "Iterator next() failed identity test"); + for (Object element : a) { + TestSupport.assertThat(element == a.get(i++), "Iterator next() failed identity test"); } - TestSupport.assertThat(i == a.size(), - "Iterator did not iterator over entire list"); + TestSupport.assertThat(i == a.size(), "Iterator did not iterator over entire list"); } - + public void test_listIterator() { - - ListIterator li = newInstance(null).listIterator(); - TestSupport.assertThat(li.hasNext() == false, - "ListIterator.hasNext() is true for empty List"); - - TestSupport.assertThat(li.hasPrevious() == false, - "ListIterator.hasPrevious() is true for empty List"); - + ListIterator<Object> li = newInstance(null).listIterator(); + TestSupport.assertThat(!li.hasNext(), "ListIterator.hasNext() is true for empty List"); + TestSupport.assertThat(!li.hasPrevious(), + "ListIterator.hasPrevious() is true for empty List"); try { li.next(); - TestSupport.assertThat(false, "expected NoSuchElementException"); + TestSupport.fail("expected NoSuchElementException"); } catch (NoSuchElementException e) {} - try { li.previous(); - TestSupport.assertThat(false, "expected NoSuchElementException"); + TestSupport.fail("expected NoSuchElementException"); } catch (NoSuchElementException e) {} - int nextIndex = li.nextIndex(); - TestSupport.assertThat(nextIndex == 0, - "ListIterator.nextIndex() on empty List did not return 0"); - + TestSupport.assertThat(nextIndex == 0, + "ListIterator.nextIndex() on empty List did not return 0"); int prevIndex = li.previousIndex(); TestSupport.assertThat(prevIndex == -1, - "ListIterator.previousIndex() on empty List did not return -1"); - - List l = new ArrayList(); - l.add(new Integer(1)); + "ListIterator.previousIndex() on empty List did not return -1"); + List<Object> l = Generic.list(); + l.add(1); li = newInstance(l).listIterator(); - TestSupport.assertThat(li.hasPrevious() == false, - "ListIterator.hasPrevious() is true with nothing previous"); - - TestSupport.assertThat(li.hasNext() == true, - "ListIterator.hasNext() is false with next present"); - TestSupport.assertThat(li.next().equals(new Integer(1)), - "ListIterator.next() did not return expected Integer(1)"); - + TestSupport.assertThat(!li.hasPrevious(), + "ListIterator.hasPrevious() is true with nothing previous"); + TestSupport.assertThat(li.hasNext(), "ListIterator.hasNext() is false with next present"); + TestSupport.assertThat(li.next().equals(1), + "ListIterator.next() did not return expected Integer(1)"); if (!isReadOnly()) { - li.remove(); - TestSupport.assertThat(li.hasNext() == false, - "ListIterator.hasNext() is true for empty List"); - - TestSupport.assertThat(li.hasPrevious() == false, - "ListIterator.hasPrevious() is true for empty List"); - try { - li.set(new Integer(42)); - TestSupport.assertThat(false, "expected IllegalStateException"); - } catch (IllegalStateException e) {} - - try { - li.remove(); - TestSupport.assertThat(false, "expected IllegalStateException"); - } catch (IllegalStateException e) {} + li.remove(); + TestSupport.assertThat(!li.hasNext(), "ListIterator.hasNext() is true for empty List"); + TestSupport.assertThat(!li.hasPrevious(), + "ListIterator.hasPrevious() is true for empty List"); + try { + li.set(42); + TestSupport.fail("expected IllegalStateException"); + } catch (IllegalStateException e) {} + try { + li.remove(); + TestSupport.fail("expected IllegalStateException"); + } catch (IllegalStateException e) {} } - - l = new ArrayList(); - l.add(new Integer(0)); - l.add(new Integer(1)); - l.add(new Integer(2)); - + l = Generic.list(); + l.add(0); + l.add(1); + l.add(2); li = newInstance(l).listIterator(); - for (int i = 0, n = l.size(); i < n; i++) { - TestSupport.assertThat(li.next().equals(new Integer(i)), - "ListIterator.previous did not return expected value"); + TestSupport.assertThat(li.next().equals(i), + "ListIterator.previous did not return expected value"); } - while (!isReadOnly() && li.hasNext()) { li.next(); - li.set(new Integer(42)); - TestSupport.assertThat(li.previous().equals(new Integer(42)), - "ListIterator.previous() did not return the value that was set()"); + li.set(42); + TestSupport.assertThat(li.previous().equals(42), + "ListIterator.previous() did not return the value that was set()"); li.remove(); } - - if(isReadOnly()) { + if (isReadOnly()) { li = newInstance(null).listIterator(); } - li = defaultList().listIterator(2); - TestSupport.assertThat(li.next().equals(new Integer(2)), - "List.listIteraor(index) did not return expected value"); - TestSupport.assertThat(li.next().equals(new Integer(3)), - "List.listIteraor(index) did not return expected value"); - TestSupport.assertThat(li.hasNext() == false, - "listIterator.hasNext() at end of list returned true"); - + TestSupport.assertThat(li.next().equals(2), + "List.listIteraor(index) did not return expected value"); + ... [truncated message content] |
From: <cg...@us...> - 2009-01-11 01:12:23
|
Revision: 5914 http://jython.svn.sourceforge.net/jython/?rev=5914&view=rev Author: cgroves Date: 2009-01-11 01:12:16 +0000 (Sun, 11 Jan 2009) Log Message: ----------- Creating the empty.py file after the bytecode just meant that it had a more recent modtime and would be preferred for importing, so it wasn't testing anything. Modified Paths: -------------- trunk/jython/Lib/test/test_import_jy.py Modified: trunk/jython/Lib/test/test_import_jy.py =================================================================== --- trunk/jython/Lib/test/test_import_jy.py 2009-01-11 01:03:33 UTC (rev 5913) +++ trunk/jython/Lib/test/test_import_jy.py 2009-01-11 01:12:16 UTC (rev 5914) @@ -89,13 +89,11 @@ # Again ensure we didn't recompile self.assertEquals(bytecode, read(init_compiled), 'bytecode was recompiled') + def test_corrupt_bytecode(self): f = open("empty$py.class", "w") f.close() self.assertRaises(ImportError, __import__, "empty") - f = open("empty.py", "w") - f.close() - self.assertRaises(ImportError, __import__, "empty") class OverrideBuiltinsImportTestCase(unittest.TestCase): def test_override(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-11 01:03:38
|
Revision: 5913 http://jython.svn.sourceforge.net/jython/?rev=5913&view=rev Author: cgroves Date: 2009-01-11 01:03:33 +0000 (Sun, 11 Jan 2009) Log Message: ----------- Compile Syspath.java for 1.5 instead of 1.6 Modified Paths: -------------- trunk/jython/Lib/test/syspath_import.jar Modified: trunk/jython/Lib/test/syspath_import.jar =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cg...@us...> - 2009-01-11 00:54:06
|
Revision: 5912 http://jython.svn.sourceforge.net/jython/?rev=5912&view=rev Author: cgroves Date: 2009-01-11 00:53:55 +0000 (Sun, 11 Jan 2009) Log Message: ----------- * Add xerces' version number to its file name for future explorers. * Add a skip-brand property to build.xml that allows version branding to be skipped, which keeps jython-dev.jar from being built even if no other files change and shaves a couple seconds off a dev build. Modified Paths: -------------- trunk/jython/build.xml trunk/jython/src/org/python/util/NameUnionAntType.java Added Paths: ----------- trunk/jython/extlibs/xercesImpl-2.9.1.jar Removed Paths: ------------- trunk/jython/extlibs/xercesImpl.jar Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-01-10 20:50:36 UTC (rev 5911) +++ trunk/jython/build.xml 2009-01-11 00:53:55 UTC (rev 5912) @@ -362,7 +362,9 @@ <exec executable="svnversion" failifexecutionfails="false" outputproperty="build.svn.revision"/> </target> - <target name="brand-version" depends="version-init, svnversion"> + <!-- skip-brand can be set in ant.properties or as a system property to keep from updating the + version.properties file and making the jar on every developer build. --> + <target name="brand-version" depends="version-init, svnversion" unless="skip-brand"> <condition property="build.svn.revision" value=""> <not> <isset property="build.svn.revision"/> @@ -520,7 +522,7 @@ <rule pattern="org.jruby.ext.posix.**" result="org.python.posix.@1"/> <zipfileset src="extlibs/constantine-0.4.jar"/> <rule pattern="com.kenai.constantine.**" result="org.python.constantine.@1"/> - <zipfileset src="extlibs/xercesImpl.jar"/> + <zipfileset src="extlibs/xercesImpl-2.9.1.jar"/> <rule pattern="org.apache.**" result="org.python.apache.@1"/> <manifest> <attribute name="Main-Class" value="org.python.util.jython" /> Copied: trunk/jython/extlibs/xercesImpl-2.9.1.jar (from rev 5907, trunk/jython/extlibs/xercesImpl.jar) =================================================================== (Binary files differ) Property changes on: trunk/jython/extlibs/xercesImpl-2.9.1.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: svn:mergeinfo + /branches/newstyle-java-types/extlibs/xercesImpl.jar:5564-5663,5666-5729 Deleted: trunk/jython/extlibs/xercesImpl.jar =================================================================== (Binary files differ) Modified: trunk/jython/src/org/python/util/NameUnionAntType.java =================================================================== --- trunk/jython/src/org/python/util/NameUnionAntType.java 2009-01-10 20:50:36 UTC (rev 5911) +++ trunk/jython/src/org/python/util/NameUnionAntType.java 2009-01-11 00:53:55 UTC (rev 5912) @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-10 20:50:40
|
Revision: 5911 http://jython.svn.sourceforge.net/jython/?rev=5911&view=rev Author: fwierzbicki Date: 2009-01-10 20:50:36 +0000 (Sat, 10 Jan 2009) Log Message: ----------- ClassDef now takes arglist for bases. Modified Paths: -------------- branches/jy3k/grammar/Python.g branches/jy3k/src/org/python/antlr/GrammarActions.java Modified: branches/jy3k/grammar/Python.g =================================================================== --- branches/jy3k/grammar/Python.g 2009-01-10 13:45:43 UTC (rev 5910) +++ branches/jy3k/grammar/Python.g 2009-01-10 20:50:36 UTC (rev 5911) @@ -1505,17 +1505,18 @@ @after { $classdef.tree = stype; } - : decorators? CLASS NAME (LPAREN testlist[expr_contextType.Load]? RPAREN)? COLON suite[false] + : decorators? CLASS NAME (LPAREN arglist? RPAREN)? COLON suite[false] { Token t = $CLASS; if ($decorators.start != null) { t = $decorators.start; } - stype = new ClassDef(t, actions.cantBeNone($NAME), - actions.makeBases(actions.castExpr($testlist.tree)), - new ArrayList<keyword>(), - null, - null, + stype = new ClassDef(t, + actions.cantBeNone($NAME), + actions.castExprs($arglist.args), + actions.makeKeywords($arglist.keywords), + $arglist.starargs, + $arglist.kwargs, actions.castStmts($suite.stypes), actions.castExprs($decorators.etypes)); } @@ -1531,12 +1532,11 @@ List gens = new ArrayList(); List arguments2 = new ArrayList(); - List kws2 = new ArrayList(); List gens2 = new ArrayList(); } : argument[arguments, kws, gens, true] (COMMA argument[arguments, kws, gens, false])* (COMMA - ( STAR s=test[expr_contextType.Load] (COMMA argument[arguments2, kws2, gens2, false])* (COMMA DOUBLESTAR k=test[expr_contextType.Load])? + ( STAR s=test[expr_contextType.Load] (COMMA argument[arguments2, kws, gens2, false])* (COMMA DOUBLESTAR k=test[expr_contextType.Load])? | DOUBLESTAR k=test[expr_contextType.Load] )? )? Modified: branches/jy3k/src/org/python/antlr/GrammarActions.java =================================================================== --- branches/jy3k/src/org/python/antlr/GrammarActions.java 2009-01-10 13:45:43 UTC (rev 5910) +++ branches/jy3k/src/org/python/antlr/GrammarActions.java 2009-01-10 20:50:36 UTC (rev 5911) @@ -100,17 +100,6 @@ return atypes; } - List<expr> makeBases(expr etype) { - List<expr> result = new ArrayList<expr>(); - if (etype != null) { - if (etype instanceof Tuple) { - return ((Tuple)etype).getInternalElts(); - } - result.add(etype); - } - return result; - } - List<String> makeNames(List names) { List<String> s = new ArrayList<String>(); for(int i=0;i<names.size();i++) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-10 13:45:54
|
Revision: 5910 http://jython.svn.sourceforge.net/jython/?rev=5910&view=rev Author: fwierzbicki Date: 2009-01-10 13:45:43 +0000 (Sat, 10 Jan 2009) Log Message: ----------- Change version numbers Modified Paths: -------------- branches/jy3k/build.xml Modified: branches/jy3k/build.xml =================================================================== --- branches/jy3k/build.xml 2009-01-10 13:35:53 UTC (rev 5909) +++ branches/jy3k/build.xml 2009-01-10 13:45:43 UTC (rev 5910) @@ -187,12 +187,12 @@ <property name="PY_RELEASE_LEVEL_SNAPSHOT" value="170"/> <!-- 0xAA --> <!-- The current version info --> - <property name="jython.version" value="2.5b0+"/> - <property name="jython.version.noplus" value="2.5b0"/> - <property name="jython.major_version" value="2"/> - <property name="jython.minor_version" value="5"/> + <property name="jython.version" value="3.1a0+"/> + <property name="jython.version.noplus" value="3.1a0"/> + <property name="jython.major_version" value="3"/> + <property name="jython.minor_version" value="1"/> <property name="jython.micro_version" value="0"/> - <property name="jython.release_level" value="${PY_RELEASE_LEVEL_BETA}"/> + <property name="jython.release_level" value="${PY_RELEASE_LEVEL_ALPHA}"/> <property name="jython.release_serial" value="0"/> <condition property="do.snapshot.build"> @@ -388,7 +388,7 @@ <target name="brand-readme-version" depends="checkout" if="do.snapshot.build"> <!-- change README.txt version string, if so defined: used for snapshot builds. XXX: a bit broken for now--> - <replace file="${jython.base.dir}/README.txt" token='2.5a3+' + <replace file="${jython.base.dir}/README.txt" token='3.1a0+' value='2.5a${svn.revision}' /> <replace file="${jython.base.dir}/README.txt"> <replacetoken>=======================</replacetoken> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-10 13:36:00
|
Revision: 5909 http://jython.svn.sourceforge.net/jython/?rev=5909&view=rev Author: fwierzbicki Date: 2009-01-10 13:35:53 +0000 (Sat, 10 Jan 2009) Log Message: ----------- from http://svn.python.org/projects/python/branches/py3k/Lib/io.py@68478 Modified Paths: -------------- branches/jy3k/Lib/io.py Modified: branches/jy3k/Lib/io.py =================================================================== --- branches/jy3k/Lib/io.py 2009-01-10 12:39:15 UTC (rev 5908) +++ branches/jy3k/Lib/io.py 2009-01-10 13:35:53 UTC (rev 5909) @@ -1 +1,2140 @@ -import cStringIO as StringIO +"""The io module provides the Python interfaces to stream handling. The +builtin open function is defined in this module. + +At the top of the I/O hierarchy is the abstract base class IOBase. It +defines the basic interface to a stream. Note, however, that there is no +seperation between reading and writing to streams; implementations are +allowed to throw an IOError if they do not support a given operation. + +Extending IOBase is RawIOBase which deals simply with the reading and +writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide +an interface to OS files. + +BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its +subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer +streams that are readable, writable, and both respectively. +BufferedRandom provides a buffered interface to random access +streams. BytesIO is a simple stream of in-memory bytes. + +Another IOBase subclass, TextIOBase, deals with the encoding and decoding +of streams into text. TextIOWrapper, which extends it, is a buffered text +interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO +is a in-memory stream for text. + +Argument names are not part of the specification, and only the arguments +of open() are intended to be used as keyword arguments. + +data: + +DEFAULT_BUFFER_SIZE + + An int containing the default buffer size used by the module's buffered + I/O classes. open() uses the file's blksize (as obtained by os.stat) if + possible. +""" +# New I/O library conforming to PEP 3116. + +# This is a prototype; hopefully eventually some of this will be +# reimplemented in C. + +# XXX edge cases when switching between reading/writing +# XXX need to support 1 meaning line-buffered +# XXX whenever an argument is None, use the default value +# XXX read/write ops should check readable/writable +# XXX buffered readinto should work with arbitrary buffer objects +# XXX use incremental encoder for text output, at least for UTF-16 and UTF-8-SIG +# XXX check writable, readable and seekable in appropriate places + + +__author__ = ("Guido van Rossum <gu...@py...>, " + "Mike Verdone <mik...@gm...>, " + "Mark Russell <mar...@ze...>") + +__all__ = ["BlockingIOError", "open", "IOBase", "RawIOBase", "FileIO", + "BytesIO", "StringIO", "BufferedIOBase", + "BufferedReader", "BufferedWriter", "BufferedRWPair", + "BufferedRandom", "TextIOBase", "TextIOWrapper"] + +import os +import abc +import codecs +import _fileio +# Import _thread instead of threading to reduce startup cost +try: + from _thread import allocate_lock as Lock +except ImportError: + from _dummy_thread import allocate_lock as Lock + + +# open() uses st_blksize whenever we can +DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes + + +class BlockingIOError(IOError): + + """Exception raised when I/O would block on a non-blocking I/O stream.""" + + def __init__(self, errno, strerror, characters_written=0): + IOError.__init__(self, errno, strerror) + self.characters_written = characters_written + + +def open(file, mode="r", buffering=None, encoding=None, errors=None, + newline=None, closefd=True): + + r"""Open file and return a stream. Raise IOError upon failure. + + file is either a text or byte string giving the name (and the path + if the file isn't in the current working directory) of the file to + be opened or an integer file descriptor of the file to be + wrapped. (If a file descriptor is given, it is closed when the + returned I/O object is closed, unless closefd is set to False.) + + mode is an optional string that specifies the mode in which the file + is opened. It defaults to 'r' which means open for reading in text + mode. Other common values are 'w' for writing (truncating the file if + it already exists), and 'a' for appending (which on some Unix systems, + means that all writes append to the end of the file regardless of the + current seek position). In text mode, if encoding is not specified the + encoding used is platform dependent. (For reading and writing raw + bytes use binary mode and leave encoding unspecified.) The available + modes are: + + ========= =============================================================== + Character Meaning + --------- --------------------------------------------------------------- + 'r' open for reading (default) + 'w' open for writing, truncating the file first + 'a' open for writing, appending to the end of the file if it exists + 'b' binary mode + 't' text mode (default) + '+' open a disk file for updating (reading and writing) + 'U' universal newline mode (for backwards compatibility; unneeded + for new code) + ========= =============================================================== + + The default mode is 'rt' (open for reading text). For binary random + access, the mode 'w+b' opens and truncates the file to 0 bytes, while + 'r+b' opens the file without truncation. + + Python distinguishes between files opened in binary and text modes, + even when the underlying operating system doesn't. Files opened in + binary mode (appending 'b' to the mode argument) return contents as + bytes objects without any decoding. In text mode (the default, or when + 't' is appended to the mode argument), the contents of the file are + returned as strings, the bytes having been first decoded using a + platform-dependent encoding or using the specified encoding if given. + + buffering is an optional integer used to set the buffering policy. By + default full buffering is on. Pass 0 to switch buffering off (only + allowed in binary mode), 1 to set line buffering, and an integer > 1 + for full buffering. + + encoding is the name of the encoding used to decode or encode the + file. This should only be used in text mode. The default encoding is + platform dependent, but any encoding supported by Python can be + passed. See the codecs module for the list of supported encodings. + + errors is an optional string that specifies how encoding errors are to + be handled---this argument should not be used in binary mode. Pass + 'strict' to raise a ValueError exception if there is an encoding error + (the default of None has the same effect), or pass 'ignore' to ignore + errors. (Note that ignoring encoding errors can lead to data loss.) + See the documentation for codecs.register for a list of the permitted + encoding error strings. + + newline controls how universal newlines works (it only applies to text + mode). It can be None, '', '\n', '\r', and '\r\n'. It works as + follows: + + * On input, if newline is None, universal newlines mode is + enabled. Lines in the input can end in '\n', '\r', or '\r\n', and + these are translated into '\n' before being returned to the + caller. If it is '', universal newline mode is enabled, but line + endings are returned to the caller untranslated. If it has any of + the other legal values, input lines are only terminated by the given + string, and the line ending is returned to the caller untranslated. + + * On output, if newline is None, any '\n' characters written are + translated to the system default line separator, os.linesep. If + newline is '', no translation takes place. If newline is any of the + other legal values, any '\n' characters written are translated to + the given string. + + If closefd is False, the underlying file descriptor will be kept open + when the file is closed. This does not work when a file name is given + and must be True in that case. + + open() returns a file object whose type depends on the mode, and + through which the standard file operations such as reading and writing + are performed. When open() is used to open a file in a text mode ('w', + 'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open + a file in a binary mode, the returned class varies: in read binary + mode, it returns a BufferedReader; in write binary and append binary + modes, it returns a BufferedWriter, and in read/write mode, it returns + a BufferedRandom. + + It is also possible to use a string or bytearray as a file for both + reading and writing. For strings StringIO can be used like a file + opened in a text mode, and for bytes a BytesIO can be used like a file + opened in a binary mode. + """ + if not isinstance(file, (str, bytes, int)): + raise TypeError("invalid file: %r" % file) + if not isinstance(mode, str): + raise TypeError("invalid mode: %r" % mode) + if buffering is not None and not isinstance(buffering, int): + raise TypeError("invalid buffering: %r" % buffering) + if encoding is not None and not isinstance(encoding, str): + raise TypeError("invalid encoding: %r" % encoding) + if errors is not None and not isinstance(errors, str): + raise TypeError("invalid errors: %r" % errors) + modes = set(mode) + if modes - set("arwb+tU") or len(mode) > len(modes): + raise ValueError("invalid mode: %r" % mode) + reading = "r" in modes + writing = "w" in modes + appending = "a" in modes + updating = "+" in modes + text = "t" in modes + binary = "b" in modes + if "U" in modes: + if writing or appending: + raise ValueError("can't use U and writing mode at once") + reading = True + if text and binary: + raise ValueError("can't have text and binary mode at once") + if reading + writing + appending > 1: + raise ValueError("can't have read/write/append mode at once") + if not (reading or writing or appending): + raise ValueError("must have exactly one of read/write/append mode") + if binary and encoding is not None: + raise ValueError("binary mode doesn't take an encoding argument") + if binary and errors is not None: + raise ValueError("binary mode doesn't take an errors argument") + if binary and newline is not None: + raise ValueError("binary mode doesn't take a newline argument") + raw = FileIO(file, + (reading and "r" or "") + + (writing and "w" or "") + + (appending and "a" or "") + + (updating and "+" or ""), + closefd) + if buffering is None: + buffering = -1 + line_buffering = False + if buffering == 1 or buffering < 0 and raw.isatty(): + buffering = -1 + line_buffering = True + if buffering < 0: + buffering = DEFAULT_BUFFER_SIZE + try: + bs = os.fstat(raw.fileno()).st_blksize + except (os.error, AttributeError): + pass + else: + if bs > 1: + buffering = bs + if buffering < 0: + raise ValueError("invalid buffering size") + if buffering == 0: + if binary: + return raw + raise ValueError("can't have unbuffered text I/O") + if updating: + buffer = BufferedRandom(raw, buffering) + elif writing or appending: + buffer = BufferedWriter(raw, buffering) + elif reading: + buffer = BufferedReader(raw, buffering) + else: + raise ValueError("unknown mode: %r" % mode) + if binary: + return buffer + text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering) + text.mode = mode + return text + +class _DocDescriptor: + """Helper for builtins.open.__doc__ + """ + def __get__(self, obj, typ): + return ( + "open(file, mode='r', buffering=None, encoding=None, " + "errors=None, newline=None, closefd=True)\n\n" + + open.__doc__) + +class OpenWrapper: + """Wrapper for builtins.open + + Trick so that open won't become a bound method when stored + as a class variable (as dbm.dumb does). + + See initstdio() in Python/pythonrun.c. + """ + __doc__ = _DocDescriptor() + + def __new__(cls, *args, **kwargs): + return open(*args, **kwargs) + + +class UnsupportedOperation(ValueError, IOError): + pass + + +class IOBase(metaclass=abc.ABCMeta): + + """The abstract base class for all I/O classes, acting on streams of + bytes. There is no public constructor. + + This class provides dummy implementations for many methods that + derived classes can override selectively; the default implementations + represent a file that cannot be read, written or seeked. + + Even though IOBase does not declare read, readinto, or write because + their signatures will vary, implementations and clients should + consider those methods part of the interface. Also, implementations + may raise a IOError when operations they do not support are called. + + The basic type used for binary data read from or written to a file is + bytes. bytearrays are accepted too, and in some cases (such as + readinto) needed. Text I/O classes work with str data. + + Note that calling any method (even inquiries) on a closed stream is + undefined. Implementations may raise IOError in this case. + + IOBase (and its subclasses) support the iterator protocol, meaning + that an IOBase object can be iterated over yielding the lines in a + stream. + + IOBase also supports the :keyword:`with` statement. In this example, + fp is closed after the suite of the with statment is complete: + + with open('spam.txt', 'r') as fp: + fp.write('Spam and eggs!') + """ + + ### Internal ### + + def _unsupported(self, name: str) -> IOError: + """Internal: raise an exception for unsupported operations.""" + raise UnsupportedOperation("%s.%s() not supported" % + (self.__class__.__name__, name)) + + ### Positioning ### + + def seek(self, pos: int, whence: int = 0) -> int: + """Change stream position. + + Change the stream position to byte offset offset. offset is + interpreted relative to the position indicated by whence. Values + for whence are: + + * 0 -- start of stream (the default); offset should be zero or positive + * 1 -- current stream position; offset may be negative + * 2 -- end of stream; offset is usually negative + + Return the new absolute position. + """ + self._unsupported("seek") + + def tell(self) -> int: + """Return current stream position.""" + self._checkClosed() + return self.seek(0, 1) + + def truncate(self, pos: int = None) -> int: + """Truncate file to size bytes. + + Size defaults to the current IO position as reported by tell(). Return + the new size. + """ + self._unsupported("truncate") + + ### Flush and close ### + + def flush(self) -> None: + """Flush write buffers, if applicable. + + This is not implemented for read-only and non-blocking streams. + """ + # XXX Should this return the number of bytes written??? + if self.__closed: + raise ValueError("I/O operation on closed file.") + + __closed = False + + def close(self) -> None: + """Flush and close the IO object. + + This method has no effect if the file is already closed. + """ + if not self.__closed: + try: + self.flush() + except IOError: + pass # If flush() fails, just give up + self.__closed = True + + def __del__(self) -> None: + """Destructor. Calls close().""" + # The try/except block is in case this is called at program + # exit time, when it's possible that globals have already been + # deleted, and then the close() call might fail. Since + # there's nothing we can do about such failures and they annoy + # the end users, we suppress the traceback. + try: + self.close() + except: + pass + + ### Inquiries ### + + def seekable(self) -> bool: + """Return whether object supports random access. + + If False, seek(), tell() and truncate() will raise IOError. + This method may need to do a test seek(). + """ + return False + + def _checkSeekable(self, msg=None): + """Internal: raise an IOError if file is not seekable + """ + if not self.seekable(): + raise IOError("File or stream is not seekable." + if msg is None else msg) + + + def readable(self) -> bool: + """Return whether object was opened for reading. + + If False, read() will raise IOError. + """ + return False + + def _checkReadable(self, msg=None): + """Internal: raise an IOError if file is not readable + """ + if not self.readable(): + raise IOError("File or stream is not readable." + if msg is None else msg) + + def writable(self) -> bool: + """Return whether object was opened for writing. + + If False, write() and truncate() will raise IOError. + """ + return False + + def _checkWritable(self, msg=None): + """Internal: raise an IOError if file is not writable + """ + if not self.writable(): + raise IOError("File or stream is not writable." + if msg is None else msg) + + @property + def closed(self): + """closed: bool. True iff the file has been closed. + + For backwards compatibility, this is a property, not a predicate. + """ + return self.__closed + + def _checkClosed(self, msg=None): + """Internal: raise an ValueError if file is closed + """ + if self.closed: + raise ValueError("I/O operation on closed file." + if msg is None else msg) + + ### Context manager ### + + def __enter__(self) -> "IOBase": # That's a forward reference + """Context management protocol. Returns self.""" + self._checkClosed() + return self + + def __exit__(self, *args) -> None: + """Context management protocol. Calls close()""" + self.close() + + ### Lower-level APIs ### + + # XXX Should these be present even if unimplemented? + + def fileno(self) -> int: + """Returns underlying file descriptor if one exists. + + An IOError is raised if the IO object does not use a file descriptor. + """ + self._unsupported("fileno") + + def isatty(self) -> bool: + """Return whether this is an 'interactive' stream. + + Return False if it can't be determined. + """ + self._checkClosed() + return False + + ### Readline[s] and writelines ### + + def readline(self, limit: int = -1) -> bytes: + r"""Read and return a line from the stream. + + If limit is specified, at most limit bytes will be read. + + The line terminator is always b'\n' for binary files; for text + files, the newlines argument to open can be used to select the line + terminator(s) recognized. + """ + # For backwards compatibility, a (slowish) readline(). + self._checkClosed() + if hasattr(self, "peek"): + def nreadahead(): + readahead = self.peek(1) + if not readahead: + return 1 + n = (readahead.find(b"\n") + 1) or len(readahead) + if limit >= 0: + n = min(n, limit) + return n + else: + def nreadahead(): + return 1 + if limit is None: + limit = -1 + res = bytearray() + while limit < 0 or len(res) < limit: + b = self.read(nreadahead()) + if not b: + break + res += b + if res.endswith(b"\n"): + break + return bytes(res) + + def __iter__(self): + self._checkClosed() + return self + + def __next__(self): + line = self.readline() + if not line: + raise StopIteration + return line + + def readlines(self, hint=None): + """Return a list of lines from the stream. + + hint can be specified to control the number of lines read: no more + lines will be read if the total size (in bytes/characters) of all + lines so far exceeds hint. + """ + self._checkClosed() + if hint is None or hint <= 0: + return list(self) + n = 0 + lines = [] + for line in self: + lines.append(line) + n += len(line) + if n >= hint: + break + return lines + + def writelines(self, lines): + self._checkClosed() + for line in lines: + self.write(line) + + +class RawIOBase(IOBase): + + """Base class for raw binary I/O.""" + + # The read() method is implemented by calling readinto(); derived + # classes that want to support read() only need to implement + # readinto() as a primitive operation. In general, readinto() can be + # more efficient than read(). + + # (It would be tempting to also provide an implementation of + # readinto() in terms of read(), in case the latter is a more suitable + # primitive operation, but that would lead to nasty recursion in case + # a subclass doesn't implement either.) + + def read(self, n: int = -1) -> bytes: + """Read and return up to n bytes. + + Returns an empty bytes object on EOF, or None if the object is + set not to block and has no data to read. + """ + self._checkClosed() + if n is None: + n = -1 + if n < 0: + return self.readall() + b = bytearray(n.__index__()) + n = self.readinto(b) + del b[n:] + return bytes(b) + + def readall(self): + """Read until EOF, using multiple read() call.""" + self._checkClosed() + res = bytearray() + while True: + data = self.read(DEFAULT_BUFFER_SIZE) + if not data: + break + res += data + return bytes(res) + + def readinto(self, b: bytearray) -> int: + """Read up to len(b) bytes into b. + + Returns number of bytes read (0 for EOF), or None if the object + is set not to block as has no data to read. + """ + self._unsupported("readinto") + + def write(self, b: bytes) -> int: + """Write the given buffer to the IO stream. + + Returns the number of bytes written, which may be less than len(b). + """ + self._unsupported("write") + + +class FileIO(_fileio._FileIO, RawIOBase): + + """Raw I/O implementation for OS files.""" + + # This multiply inherits from _FileIO and RawIOBase to make + # isinstance(io.FileIO(), io.RawIOBase) return True without requiring + # that _fileio._FileIO inherits from io.RawIOBase (which would be hard + # to do since _fileio.c is written in C). + + def __init__(self, name, mode="r", closefd=True): + _fileio._FileIO.__init__(self, name, mode, closefd) + self._name = name + + def close(self): + _fileio._FileIO.close(self) + RawIOBase.close(self) + + @property + def name(self): + return self._name + + +class BufferedIOBase(IOBase): + + """Base class for buffered IO objects. + + The main difference with RawIOBase is that the read() method + supports omitting the size argument, and does not have a default + implementation that defers to readinto(). + + In addition, read(), readinto() and write() may raise + BlockingIOError if the underlying raw stream is in non-blocking + mode and not ready; unlike their raw counterparts, they will never + return None. + + A typical implementation should not inherit from a RawIOBase + implementation, but wrap one. + """ + + def read(self, n: int = None) -> bytes: + """Read and return up to n bytes. + + If the argument is omitted, None, or negative, reads and + returns all data until EOF. + + If the argument is positive, and the underlying raw stream is + not 'interactive', multiple raw reads may be issued to satisfy + the byte count (unless EOF is reached first). But for + interactive raw streams (XXX and for pipes?), at most one raw + read will be issued, and a short result does not imply that + EOF is imminent. + + Returns an empty bytes array on EOF. + + Raises BlockingIOError if the underlying raw stream has no + data at the moment. + """ + self._unsupported("read") + + def readinto(self, b: bytearray) -> int: + """Read up to len(b) bytes into b. + + Like read(), this may issue multiple reads to the underlying raw + stream, unless the latter is 'interactive'. + + Returns the number of bytes read (0 for EOF). + + Raises BlockingIOError if the underlying raw stream has no + data at the moment. + """ + # XXX This ought to work with anything that supports the buffer API + self._checkClosed() + data = self.read(len(b)) + n = len(data) + try: + b[:n] = data + except TypeError as err: + import array + if not isinstance(b, array.array): + raise err + b[:n] = array.array('b', data) + return n + + def write(self, b: bytes) -> int: + """Write the given buffer to the IO stream. + + Return the number of bytes written, which is never less than + len(b). + + Raises BlockingIOError if the buffer is full and the + underlying raw stream cannot accept more data at the moment. + """ + self._unsupported("write") + + +class _BufferedIOMixin(BufferedIOBase): + + """A mixin implementation of BufferedIOBase with an underlying raw stream. + + This passes most requests on to the underlying raw stream. It + does *not* provide implementations of read(), readinto() or + write(). + """ + + def __init__(self, raw): + self.raw = raw + + ### Positioning ### + + def seek(self, pos, whence=0): + return self.raw.seek(pos, whence) + + def tell(self): + return self.raw.tell() + + def truncate(self, pos=None): + # Flush the stream. We're mixing buffered I/O with lower-level I/O, + # and a flush may be necessary to synch both views of the current + # file state. + self.flush() + + if pos is None: + pos = self.tell() + # XXX: Should seek() be used, instead of passing the position + # XXX directly to truncate? + return self.raw.truncate(pos) + + ### Flush and close ### + + def flush(self): + self.raw.flush() + + def close(self): + if not self.closed: + try: + self.flush() + except IOError: + pass # If flush() fails, just give up + self.raw.close() + + ### Inquiries ### + + def seekable(self): + return self.raw.seekable() + + def readable(self): + return self.raw.readable() + + def writable(self): + return self.raw.writable() + + @property + def closed(self): + return self.raw.closed + + @property + def name(self): + return self.raw.name + + @property + def mode(self): + return self.raw.mode + + ### Lower-level APIs ### + + def fileno(self): + return self.raw.fileno() + + def isatty(self): + return self.raw.isatty() + + +class _BytesIO(BufferedIOBase): + + """Buffered I/O implementation using an in-memory bytes buffer.""" + + def __init__(self, initial_bytes=None): + buf = bytearray() + if initial_bytes is not None: + buf += initial_bytes + self._buffer = buf + self._pos = 0 + + def getvalue(self): + """Return the bytes value (contents) of the buffer + """ + self._checkClosed() + return bytes(self._buffer) + + def read(self, n=None): + self._checkClosed() + if n is None: + n = -1 + if n < 0: + n = len(self._buffer) + if len(self._buffer) <= self._pos: + return b"" + newpos = min(len(self._buffer), self._pos + n) + b = self._buffer[self._pos : newpos] + self._pos = newpos + return bytes(b) + + def read1(self, n): + """This is the same as read. + """ + return self.read(n) + + def write(self, b): + self._checkClosed() + if isinstance(b, str): + raise TypeError("can't write str to binary stream") + n = len(b) + if n == 0: + return 0 + pos = self._pos + if pos > len(self._buffer): + # Inserts null bytes between the current end of the file + # and the new write position. + padding = b'\x00' * (pos - len(self._buffer)) + self._buffer += padding + self._buffer[pos:pos + n] = b + self._pos += n + return n + + def seek(self, pos, whence=0): + self._checkClosed() + try: + pos = pos.__index__() + except AttributeError as err: + raise TypeError("an integer is required") from err + if whence == 0: + if pos < 0: + raise ValueError("negative seek position %r" % (pos,)) + self._pos = pos + elif whence == 1: + self._pos = max(0, self._pos + pos) + elif whence == 2: + self._pos = max(0, len(self._buffer) + pos) + else: + raise ValueError("invalid whence value") + return self._pos + + def tell(self): + self._checkClosed() + return self._pos + + def truncate(self, pos=None): + self._checkClosed() + if pos is None: + pos = self._pos + elif pos < 0: + raise ValueError("negative truncate position %r" % (pos,)) + del self._buffer[pos:] + return self.seek(pos) + + def readable(self): + return True + + def writable(self): + return True + + def seekable(self): + return True + +# Use the faster implementation of BytesIO if available +try: + import _bytesio + + class BytesIO(_bytesio._BytesIO, BufferedIOBase): + __doc__ = _bytesio._BytesIO.__doc__ + +except ImportError: + BytesIO = _BytesIO + + +class BufferedReader(_BufferedIOMixin): + + """BufferedReader(raw[, buffer_size]) + + A buffer for a readable, sequential BaseRawIO object. + + The constructor creates a BufferedReader for the given readable raw + stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE + is used. + """ + + def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): + """Create a new buffered reader using the given readable raw IO object. + """ + raw._checkReadable() + _BufferedIOMixin.__init__(self, raw) + self.buffer_size = buffer_size + self._reset_read_buf() + self._read_lock = Lock() + + def _reset_read_buf(self): + self._read_buf = b"" + self._read_pos = 0 + + def read(self, n=None): + """Read n bytes. + + Returns exactly n bytes of data unless the underlying raw IO + stream reaches EOF or if the call would block in non-blocking + mode. If n is negative, read until EOF or until read() would + block. + """ + self._checkClosed() + with self._read_lock: + return self._read_unlocked(n) + + def _read_unlocked(self, n=None): + nodata_val = b"" + empty_values = (b"", None) + buf = self._read_buf + pos = self._read_pos + + # Special case for when the number of bytes to read is unspecified. + if n is None or n == -1: + self._reset_read_buf() + chunks = [buf[pos:]] # Strip the consumed bytes. + current_size = 0 + while True: + # Read until EOF or until read() would block. + chunk = self.raw.read() + if chunk in empty_values: + nodata_val = chunk + break + current_size += len(chunk) + chunks.append(chunk) + return b"".join(chunks) or nodata_val + + # The number of bytes to read is specified, return at most n bytes. + avail = len(buf) - pos # Length of the available buffered data. + if n <= avail: + # Fast path: the data to read is fully buffered. + self._read_pos += n + return buf[pos:pos+n] + # Slow path: read from the stream until enough bytes are read, + # or until an EOF occurs or until read() would block. + chunks = [buf[pos:]] + wanted = max(self.buffer_size, n) + while avail < n: + chunk = self.raw.read(wanted) + if chunk in empty_values: + nodata_val = chunk + break + avail += len(chunk) + chunks.append(chunk) + # n is more then avail only when an EOF occurred or when + # read() would have blocked. + n = min(n, avail) + out = b"".join(chunks) + self._read_buf = out[n:] # Save the extra data in the buffer. + self._read_pos = 0 + return out[:n] if out else nodata_val + + def peek(self, n=0): + """Returns buffered bytes without advancing the position. + + The argument indicates a desired minimal number of bytes; we + do at most one raw read to satisfy it. We never return more + than self.buffer_size. + """ + self._checkClosed() + with self._read_lock: + return self._peek_unlocked(n) + + def _peek_unlocked(self, n=0): + want = min(n, self.buffer_size) + have = len(self._read_buf) - self._read_pos + if have < want: + to_read = self.buffer_size - have + current = self.raw.read(to_read) + if current: + self._read_buf = self._read_buf[self._read_pos:] + current + self._read_pos = 0 + return self._read_buf[self._read_pos:] + + def read1(self, n): + """Reads up to n bytes, with at most one read() system call.""" + # Returns up to n bytes. If at least one byte is buffered, we + # only return buffered bytes. Otherwise, we do one raw read. + self._checkClosed() + if n <= 0: + return b"" + with self._read_lock: + self._peek_unlocked(1) + return self._read_unlocked( + min(n, len(self._read_buf) - self._read_pos)) + + def tell(self): + self._checkClosed() + return self.raw.tell() - len(self._read_buf) + self._read_pos + + def seek(self, pos, whence=0): + self._checkClosed() + with self._read_lock: + if whence == 1: + pos -= len(self._read_buf) - self._read_pos + pos = self.raw.seek(pos, whence) + self._reset_read_buf() + return pos + + +class BufferedWriter(_BufferedIOMixin): + + """A buffer for a writeable sequential RawIO object. + + The constructor creates a BufferedWriter for the given writeable raw + stream. If the buffer_size is not given, it defaults to + DEAFULT_BUFFER_SIZE. If max_buffer_size is omitted, it defaults to + twice the buffer size. + """ + + def __init__(self, raw, + buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + raw._checkWritable() + _BufferedIOMixin.__init__(self, raw) + self.buffer_size = buffer_size + self.max_buffer_size = (2*buffer_size + if max_buffer_size is None + else max_buffer_size) + self._write_buf = bytearray() + self._write_lock = Lock() + + def write(self, b): + self._checkClosed() + if isinstance(b, str): + raise TypeError("can't write str to binary stream") + with self._write_lock: + # XXX we can implement some more tricks to try and avoid + # partial writes + if len(self._write_buf) > self.buffer_size: + # We're full, so let's pre-flush the buffer + try: + self._flush_unlocked() + except BlockingIOError as e: + # We can't accept anything else. + # XXX Why not just let the exception pass through? + raise BlockingIOError(e.errno, e.strerror, 0) + before = len(self._write_buf) + self._write_buf.extend(b) + written = len(self._write_buf) - before + if len(self._write_buf) > self.buffer_size: + try: + self._flush_unlocked() + except BlockingIOError as e: + if len(self._write_buf) > self.max_buffer_size: + # We've hit max_buffer_size. We have to accept a + # partial write and cut back our buffer. + overage = len(self._write_buf) - self.max_buffer_size + self._write_buf = self._write_buf[:self.max_buffer_size] + raise BlockingIOError(e.errno, e.strerror, overage) + return written + + def truncate(self, pos=None): + self._checkClosed() + with self._write_lock: + self._flush_unlocked() + if pos is None: + pos = self.raw.tell() + return self.raw.truncate(pos) + + def flush(self): + self._checkClosed() + with self._write_lock: + self._flush_unlocked() + + def _flush_unlocked(self): + written = 0 + try: + while self._write_buf: + n = self.raw.write(self._write_buf) + del self._write_buf[:n] + written += n + except BlockingIOError as e: + n = e.characters_written + del self._write_buf[:n] + written += n + raise BlockingIOError(e.errno, e.strerror, written) + + def tell(self): + self._checkClosed() + return self.raw.tell() + len(self._write_buf) + + def seek(self, pos, whence=0): + self._checkClosed() + with self._write_lock: + self._flush_unlocked() + return self.raw.seek(pos, whence) + + +class BufferedRWPair(BufferedIOBase): + + """A buffered reader and writer object together. + + A buffered reader object and buffered writer object put together to + form a sequential IO object that can read and write. This is typically + used with a socket or two-way pipe. + + reader and writer are RawIOBase objects that are readable and + writeable respectively. If the buffer_size is omitted it defaults to + DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered writer) + defaults to twice the buffer size. + """ + + # XXX The usefulness of this (compared to having two separate IO + # objects) is questionable. + + def __init__(self, reader, writer, + buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + """Constructor. + + The arguments are two RawIO instances. + """ + reader._checkReadable() + writer._checkWritable() + self.reader = BufferedReader(reader, buffer_size) + self.writer = BufferedWriter(writer, buffer_size, max_buffer_size) + + def read(self, n=None): + if n is None: + n = -1 + return self.reader.read(n) + + def readinto(self, b): + return self.reader.readinto(b) + + def write(self, b): + return self.writer.write(b) + + def peek(self, n=0): + return self.reader.peek(n) + + def read1(self, n): + return self.reader.read1(n) + + def readable(self): + return self.reader.readable() + + def writable(self): + return self.writer.writable() + + def flush(self): + return self.writer.flush() + + def close(self): + self.writer.close() + self.reader.close() + + def isatty(self): + return self.reader.isatty() or self.writer.isatty() + + @property + def closed(self): + return self.writer.closed + + +class BufferedRandom(BufferedWriter, BufferedReader): + + """A buffered interface to random access streams. + + The constructor creates a reader and writer for a seekable stream, + raw, given in the first argument. If the buffer_size is omitted it + defaults to DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered + writer) defaults to twice the buffer size. + """ + + def __init__(self, raw, + buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + raw._checkSeekable() + BufferedReader.__init__(self, raw, buffer_size) + BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) + + def seek(self, pos, whence=0): + self.flush() + # First do the raw seek, then empty the read buffer, so that + # if the raw seek fails, we don't lose buffered data forever. + pos = self.raw.seek(pos, whence) + with self._read_lock: + self._reset_read_buf() + return pos + + def tell(self): + self._checkClosed() + if self._write_buf: + return self.raw.tell() + len(self._write_buf) + else: + return BufferedReader.tell(self) + + def truncate(self, pos=None): + if pos is None: + pos = self.tell() + # Use seek to flush the read buffer. + self.seek(pos) + return BufferedWriter.truncate(self) + + def read(self, n=None): + if n is None: + n = -1 + self.flush() + return BufferedReader.read(self, n) + + def readinto(self, b): + self.flush() + return BufferedReader.readinto(self, b) + + def peek(self, n=0): + self.flush() + return BufferedReader.peek(self, n) + + def read1(self, n): + self.flush() + return BufferedReader.read1(self, n) + + def write(self, b): + self._checkClosed() + if self._read_buf: + # Undo readahead + with self._read_lock: + self.raw.seek(self._read_pos - len(self._read_buf), 1) + self._reset_read_buf() + return BufferedWriter.write(self, b) + + +class TextIOBase(IOBase): + + """Base class for text I/O. + + This class provides a character and line based interface to stream + I/O. There is no readinto method because Python's character strings + are immutable. There is no public constructor. + """ + + def read(self, n: int = -1) -> str: + """Read at most n characters from stream. + + Read from underlying buffer until we have n characters or we hit EOF. + If n is negative or omitted, read until EOF. + """ + self._unsupported("read") + + def write(self, s: str) -> int: + """Write string s to stream.""" + self._unsupported("write") + + def truncate(self, pos: int = None) -> int: + """Truncate size to pos.""" + self._unsupported("truncate") + + def readline(self) -> str: + """Read until newline or EOF. + + Returns an empty string if EOF is hit immediately. + """ + self._unsupported("readline") + + @property + def encoding(self): + """Subclasses should override.""" + return None + + @property + def newlines(self): + """Line endings translated so far. + + Only line endings translated during reading are considered. + + Subclasses should override. + """ + return None + + +class IncrementalNewlineDecoder(codecs.IncrementalDecoder): + r"""Codec used when reading a file in universal newlines mode. It wraps + another incremental decoder, translating \r\n and \r into \n. It also + records the types of newlines encountered. When used with + translate=False, it ensures that the newline sequence is returned in + one piece. + """ + def __init__(self, decoder, translate, errors='strict'): + codecs.IncrementalDecoder.__init__(self, errors=errors) + self.translate = translate + self.decoder = decoder + self.seennl = 0 + self.pendingcr = False + + def decode(self, input, final=False): + # decode input (with the eventual \r from a previous pass) + output = self.decoder.decode(input, final=final) + if self.pendingcr and (output or final): + output = "\r" + output + self.pendingcr = False + + # retain last \r even when not translating data: + # then readline() is sure to get \r\n in one pass + if output.endswith("\r") and not final: + output = output[:-1] + self.pendingcr = True + + # Record which newlines are read + crlf = output.count('\r\n') + cr = output.count('\r') - crlf + lf = output.count('\n') - crlf + self.seennl |= (lf and self._LF) | (cr and self._CR) \ + | (crlf and self._CRLF) + + if self.translate: + if crlf: + output = output.replace("\r\n", "\n") + if cr: + output = output.replace("\r", "\n") + + return output + + def getstate(self): + buf, flag = self.decoder.getstate() + flag <<= 1 + if self.pendingcr: + flag |= 1 + return buf, flag + + def setstate(self, state): + buf, flag = state + self.pendingcr = bool(flag & 1) + self.decoder.setstate((buf, flag >> 1)) + + def reset(self): + self.seennl = 0 + self.pendingcr = False + self.decoder.reset() + + _LF = 1 + _CR = 2 + _CRLF = 4 + + @property + def newlines(self): + return (None, + "\n", + "\r", + ("\r", "\n"), + "\r\n", + ("\n", "\r\n"), + ("\r", "\r\n"), + ("\r", "\n", "\r\n") + )[self.seennl] + + +class TextIOWrapper(TextIOBase): + + r"""Character and line based layer over a BufferedIOBase object, buffer. + + encoding gives the name of the encoding that the stream will be + decoded or encoded with. It defaults to locale.getpreferredencoding. + + errors determines the strictness of encoding and decoding (see the + codecs.register) and defaults to "strict". + + newline can be None, '', '\n', '\r', or '\r\n'. It controls the + handling of line endings. If it is None, universal newlines is + enabled. With this enabled, on input, the lines endings '\n', '\r', + or '\r\n' are translated to '\n' before being returned to the + caller. Conversely, on output, '\n' is translated to the system + default line seperator, os.linesep. If newline is any other of its + legal values, that newline becomes the newline when the file is read + and it is returned untranslated. On output, '\n' is converted to the + newline. + + If line_buffering is True, a call to flush is implied when a call to + write contains a newline character. + """ + + _CHUNK_SIZE = 2048 + + def __init__(self, buffer, encoding=None, errors=None, newline=None, + line_buffering=False): + if newline not in (None, "", "\n", "\r", "\r\n"): + raise ValueError("illegal newline value: %r" % (newline,)) + if encoding is None: + try: + encoding = os.device_encoding(buffer.fileno()) + except (AttributeError, UnsupportedOperation): + pass + if encoding is None: + try: + import locale + except ImportError: + # Importing locale may fail if Python is being built + encoding = "ascii" + else: + encoding = locale.getpreferredencoding() + + if not isinstance(encoding, str): + raise ValueError("invalid encoding: %r" % encoding) + + if errors is None: + errors = "strict" + else: + if not isinstance(errors, str): + raise ValueError("invalid errors: %r" % errors) + + self.buffer = buffer + self._line_buffering = line_buffering + self._encoding = encoding + self._errors = errors + self._readuniversal = not newline + self._readtranslate = newline is None + self._readnl = newline + self._writetranslate = newline != '' + self._writenl = newline or os.linesep + self._encoder = None + self._decoder = None + self._decoded_chars = '' # buffer for text returned from decoder + self._decoded_chars_used = 0 # offset into _decoded_chars for read() + self._snapshot = None # info for reconstructing decoder state + self._seekable = self._telling = self.buffer.seekable() + + # self._snapshot is either None, or a tuple (dec_flags, next_input) + # where dec_flags is the second (integer) item of the decoder state + # and next_input is the chunk of input bytes that comes next after the + # snapshot point. We use this to reconstruct decoder states in tell(). + + # Naming convention: + # - "bytes_..." for integer variables that count input bytes + # - "chars_..." for integer variables that count decoded characters + + @property + def encoding(self): + return self._encoding + + @property + def errors(self): + return self._errors + + @property + def line_buffering(self): + return self._line_buffering + + def seekable(self): + return self._seekable + + def readable(self): + return self.buffer.readable() + + def writable(self): + return self.buffer.writable() + + def flush(self): + self.buffer.flush() + self._telling = self._seekable + + def close(self): + try: + self.flush() + except: + pass # If flush() fails, just give up + self.buffer.close() + + @property + def closed(self): + return self.buffer.closed + + @property + def name(self): + return self.buffer.name + + def fileno(self): + return self.buffer.fileno() + + def isatty(self): + return self.buffer.isatty() + + def write(self, s: str): + self._checkClosed() + if not isinstance(s, str): + raise TypeError("can't write %s to text stream" % + s.__class__.__name__) + length = len(s) + haslf = (self._writetranslate or self._line_buffering) and "\n" in s + if haslf and self._writetranslate and self._writenl != "\n": + s = s.replace("\n", self._writenl) + encoder = self._encoder or self._get_encoder() + # XXX What if we were just reading? + b = encoder.encode(s) + self.buffer.write(b) + if self._line_buffering and (haslf or "\r" in s): + self.flush() + self._snapshot = None + if self._decoder: + self._decoder.reset() + return length + + def _get_encoder(self): + make_encoder = codecs.getincrementalencoder(self._encoding) + self._encoder = make_encoder(self._errors) + return self._encoder + + def _get_decoder(self): + make_decoder = codecs.getincrementaldecoder(self._encoding) + decoder = make_decoder(self._errors) + if self._readuniversal: + decoder = IncrementalNewlineDecoder(decoder, self._readtranslate) + self._decoder = decoder + return decoder + + # The following three methods implement an ADT for _decoded_chars. + # Text returned from the decoder is buffered here until the client + # requests it by calling our read() or readline() method. + def _set_decoded_chars(self, chars): + """Set the _decoded_chars buffer.""" + self._decoded_chars = chars + self._decoded_chars_used = 0 + + def _get_decoded_chars(self, n=None): + """Advance into the _decoded_chars buffer.""" + offset = self._decoded_chars_used + if n is None: + chars = self._decoded_chars[offset:] + else: + chars = self._decoded_chars[offset:offset + n] + self._decoded_chars_used += len(chars) + return chars + + def _rewind_decoded_chars(self, n): + """Rewind the _decoded_chars buffer.""" + if self._decoded_chars_used < n: + raise AssertionError("rewind decoded_chars out of bounds") + self._decoded_chars_used -= n + + def _read_chunk(self): + """ + Read and decode the next chunk of data from the BufferedReader. + """ + + # The return value is True unless EOF was reached. The decoded + # string is placed in self._decoded_chars (replacing its previous + # value). The entire input chunk is sent to the decoder, though + # some of it may remain buffered in the decoder, yet to be + # converted. + + if self._decoder is None: + raise ValueError("no decoder") + + if self._telling: + # To prepare for tell(), we need to snapshot a point in the + # file where the decoder's input buffer is empty. + + dec_buffer, dec_flags = self._decoder.getstate() + # Given this, we know there was a valid snapshot point + # len(dec_buffer) bytes ago with decoder state (b'', dec_flags). + + # Read a chunk, decode it, and put the result in self._decoded_chars. + input_chunk = self.buffer.read1(self._CHUNK_SIZE) + eof = not input_chunk + self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) + + if self._telling: + # At the snapshot point, len(dec_buffer) bytes before the read, + # the next input to be decoded is dec_buffer + input_chunk. + self._snapshot = (dec_flags, dec_buffer + input_chunk) + + return not eof + + def _pack_cookie(self, position, dec_flags=0, + bytes_to_feed=0, need_eof=0, chars_to_skip=0): + # The meaning of a tell() cookie is: seek to position, set the + # decoder flags to dec_flags, read bytes_to_feed bytes, feed them + # into the decoder with need_eof as the EOF flag, then skip + # chars_to_skip characters of the decoded result. For most simple + # decoders, tell() will often just give a byte offset in the file. + return (position | (dec_flags<<64) | (bytes_to_feed<<128) | + (chars_to_skip<<192) | bool(need_eof)<<256) + + def _unpack_cookie(self, bigint): + rest, position = divmod(bigint, 1<<64) + rest, dec_flags = divmod(rest, 1<<64) + rest, bytes_to_feed = divmod(rest, 1<<64) + need_eof, chars_to_skip = divmod(rest, 1<<64) + return position, dec_flags, bytes_to_feed, need_eof, chars_to_skip + + def tell(self): + self._checkClosed() + if not self._seekable: + raise IOError("underlying stream is not seekable") + if not self._telling: + raise IOError("telling position disabled by next() call") + self.flush() + position = self.buffer.tell() + decoder = self._decoder + if decoder is None or self._snapshot is None: + if self._decoded_chars: + # This should never happen. + raise AssertionError("pending decoded text") + return position + + # Skip backward to the snapshot point (see _read_chunk). + dec_flags, next_input = self._snapshot + position -= len(next_input) + + # How many decoded characters have been used up since the snapshot? + chars_to_skip = self._decoded_chars_used + if chars_to_skip == 0: + # We haven't moved from the snapshot point. + return self._pack_cookie(position, dec_flags) + + # Starting from the snapshot position, we will walk the decoder + # forward until it gives us enough decoded characters. + saved_state = decoder.getstate() + try: + # Note our initial start point. + decoder.setstate((b'', dec_flags)) + start_pos = position + start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0 + need_eof = 0 + + # Feed the decoder one byte at a time. As we go, note the + # nearest "safe start point" before the current location + # (a point where the decoder has nothing buffered, so seek() + # can safely start from there and advance to this location). + next_byte = bytearray(1) + for next_byte[0] in next_input: + bytes_fed += 1 + chars_decoded += len(decoder.decode(next_byte)) + dec_buffer, dec_flags = decoder.getstate() + if not dec_buffer and chars_decoded <= chars_to_skip: + # Decoder buffer is empty, so this is a safe start point. + start_pos += bytes_fed + chars_to_skip -= chars_decoded + start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0 + if chars_decoded >= chars_to_skip: + break + else: + # We didn't get enough decoded data; signal EOF to get more. + chars_decoded += len(decoder.decode(b'', final=True)) + need_eof = 1 + if chars_decoded < chars_to_skip: + raise IOError("can't reconstruct logical file position") + + # The returned cookie corresponds to the last safe start point. + return self._pack_cookie( + start_pos, start_flags, bytes_fed, need_eof, chars_to_skip) + finally: + decoder.setstate(saved_state) + + def truncate(self, pos=None): + self.flush() + if pos is None: + pos = self.tell() + self.seek(pos) + return self.buffer.truncate() + + def seek(self, cookie, whence=0): + self._checkClosed() + if not self._seekable: + raise IOError("underlying stream is not seekable") + if whence == 1: # seek relative to current position + if cookie != 0: + raise IOError("can't do nonzero cur-relative seeks") + # Seeking to the current position should attempt to + # sync the underlying buffer with the current position. + whence = 0 + cookie = self.tell() + if whence == 2: # seek relative to end of file + if cookie != 0: + raise IOError("can't do nonzero end-relative seeks") + self.flush() + position = self.buffer.seek(0, 2) + self._set_decoded_chars('') + self._snapshot = None + if self._decoder: + self._decoder.reset() + return position + if whence != 0: + raise ValueError("invalid whence (%r, should be 0, 1 or 2)" % + (whence,)) + if cookie < 0: + raise ValueError("negative seek position %r" % (cookie,)) + self.flush() + + # The strategy of seek() is to go back to the safe start point + # and replay the effect of read(chars_to_skip) from there. + start_pos, dec_fla... [truncated message content] |
From: <ped...@us...> - 2009-01-10 12:39:27
|
Revision: 5908 http://jython.svn.sourceforge.net/jython/?rev=5908&view=rev Author: pedronis Date: 2009-01-10 12:39:15 +0000 (Sat, 10 Jan 2009) Log Message: ----------- yet another try at binop rule, with more exhaustive tests (verified against cpython) that now pass see also PyPy issue 412 Modified Paths: -------------- trunk/jython/Lib/test/test_descr_jy.py trunk/jython/src/org/python/core/PyObject.java trunk/jython/src/org/python/core/PyType.java Modified: trunk/jython/Lib/test/test_descr_jy.py =================================================================== --- trunk/jython/Lib/test/test_descr_jy.py 2009-01-10 03:53:36 UTC (rev 5907) +++ trunk/jython/Lib/test/test_descr_jy.py 2009-01-10 12:39:15 UTC (rev 5908) @@ -368,13 +368,148 @@ except AttributeError, e: self.assertEquals("Custom message", str(e)) +# try to test more exhaustively binop overriding combination cases +class Base(object): + def __init__(self, name): + self.name = name + +def lookup_where(obj, name): + mro = type(obj).__mro__ + for t in mro: + if name in t.__dict__: + return t.__dict__[name], t + return None, None + +def refop(x, y, opname, ropname): + # this has been validated by running the tests on top of cpython + # so for the space of possibilities that the tests touch it is known + # to behave like cpython as long as the latter doesn't change its own + # algorithm + t1 = type(x) + t2 = type(y) + op, where1 = lookup_where(x, opname) + rop, where2 = lookup_where(y, ropname) + if op is None and rop is not None: + return rop(y, x) + if rop and where1 is not where2: + if (issubclass(t2, t1) and not issubclass(where1, where2) + and not issubclass(t1, where2) + ): + return rop(y, x) + if op is None: + return "TypeError" + return op(x,y) + +def do_test(X, Y, name, impl): + x = X('x') + y = Y('y') + opname = '__%s__' % name + ropname = '__r%s__' % name + + count = [0] + fail = [] + + def check(z1, z2): + ref = refop(z1, z2, opname, ropname) + try: + v = impl(z1, z2) + except TypeError: + v = "TypeError" + if v != ref: + fail.append(count[0]) + + def override_in_hier(n=6): + if n == 0: + count[0] += 1 + check(x, y) + check(y, x) + return + + f = lambda self, other: (n, self.name, other.name) + if n%2 == 0: + name = opname + else: + name = ropname + + for C in Y.__mro__: + if name in C.__dict__: + continue + if C is not object: + setattr(C, name, f) + override_in_hier(n-1) + if C is not object: + delattr(C, name) + + override_in_hier() + #print count[0] + return fail + +class BinopCombinationsTestCase(unittest.TestCase): + + def test_binop_combinations_mul(self): + class X(Base): + pass + class Y(X): + pass + + fail = do_test(X, Y, 'mul', lambda x,y: x*y) + #print len(fail) + self.assert_(not fail) + + def test_binop_combinations_sub(self): + class X(Base): + pass + class Y(X): + pass + + fail = do_test(X, Y, 'sub', lambda x,y: x-y) + #print len(fail) + self.assert_(not fail) + + def test_binop_combinations_pow(self): + class X(Base): + pass + class Y(X): + pass + + fail = do_test(X, Y, 'pow', lambda x,y: x**y) + #print len(fail) + self.assert_(not fail) + + def test_binop_combinations_more_exhaustive(self): + class X(Base): + pass + + class B1(object): + pass + + class B2(object): + pass + + class X1(B1, X, B2): + pass + + class C1(object): + pass + + class C2(object): + pass + + class Y(C1, X1, C2): + pass + + fail = do_test(X, Y, 'sub', lambda x,y: x-y) + #print len(fail) + self.assert_(not fail) + def test_main(): test_support.run_unittest(TestDescrTestCase, SubclassDescrTestCase, InPlaceTestCase, DescrExceptionsTestCase, - GetAttrTestCase) + GetAttrTestCase, + BinopCombinationsTestCase) if __name__ == '__main__': test_main() Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2009-01-10 03:53:36 UTC (rev 5907) +++ trunk/jython/src/org/python/core/PyObject.java 2009-01-10 12:39:15 UTC (rev 5908) @@ -1888,14 +1888,16 @@ * test_descr.subclass_right_op. */ PyObject o1 = this; - int[] where = new int[1]; - int where1, where2; - PyObject impl1 = t1.lookup_where_index(left, where); + PyObject[] where = new PyObject[1]; + PyObject where1 = null, where2 = null; + PyObject impl1 = t1.lookup_where(left, where); where1 = where[0]; - PyObject impl2 = t2.lookup_where_index(right, where); + PyObject impl2 = t2.lookup_where(right, where); where2 = where[0]; - if (impl2 != null && where1 < where2 && (t2.isSubType(t1) || - isStrUnicodeSpecialCase(t1, t2, op))) { + if (impl2 != null && impl1 != null && where1 != where2 && + (t2.isSubType(t1) && !Py.isSubClass(where1, where2) + && !Py.isSubClass(t1, where2) || + isStrUnicodeSpecialCase(t1, t2, op))) { PyObject tmp = o1; o1 = o2; o2 = tmp; Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2009-01-10 03:53:36 UTC (rev 5907) +++ trunk/jython/src/org/python/core/PyType.java 2009-01-10 12:39:15 UTC (rev 5908) @@ -915,34 +915,6 @@ return null; } - /** - * Like lookup but also provides (in where[0]) the index of the type in the reversed - * mro -- that is, how many subtypes away from the base object the type is. - * - * @param name attribute name (must be interned) - * @param where an int[] with a length of at least 1 - * @return found PyObject or null - */ - public PyObject lookup_where_index(String name, int[] where) { - PyObject[] mro = this.mro; - if (mro == null) { - return null; - } - int i = mro.length; - for (PyObject t : mro) { - i--; - PyObject dict = t.fastGetDict(); - if (dict != null) { - PyObject obj = dict.__finditem__(name); - if (obj != null) { - where[0] = i; - return obj; - } - } - } - return null; - } - public PyObject super_lookup(PyType ref, String name) { PyObject[] mro = this.mro; if (mro == null) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-10 03:53:42
|
Revision: 5907 http://jython.svn.sourceforge.net/jython/?rev=5907&view=rev Author: fwierzbicki Date: 2009-01-10 03:53:36 +0000 (Sat, 10 Jan 2009) Log Message: ----------- Improved parsing of expanded 3.0 argument lists. Modified Paths: -------------- branches/jy3k/grammar/Python.g branches/jy3k/src/org/python/antlr/GrammarActions.java Modified: branches/jy3k/grammar/Python.g =================================================================== --- branches/jy3k/grammar/Python.g 2009-01-10 00:49:02 UTC (rev 5906) +++ branches/jy3k/grammar/Python.g 2009-01-10 03:53:36 UTC (rev 5907) @@ -482,23 +482,46 @@ typedargslist returns [arguments args] @init { List defaults = new ArrayList(); + List kw_defaults = new ArrayList(); } : d+=tdefparameter[defaults] (options {greedy=true;}:COMMA d+=tdefparameter[defaults])* (COMMA - (STAR (starargs=tfpdef[expr_contextType.Param])? (COMMA tdefparameter[defaults])* (COMMA DOUBLESTAR kwargs=tfpdef[expr_contextType.Param])? + (STAR (starargs=tfpdef[expr_contextType.Param])? (COMMA k+=tdefparameter[kw_defaults])* + (COMMA tdefparameter[defaults])* (COMMA DOUBLESTAR kwargs=tfpdef[expr_contextType.Param])? | DOUBLESTAR kwargs=tfpdef[expr_contextType.Param] )? )? { - $args = actions.makeArgumentsType($typedargslist.start, $d, $starargs.tree, $kwargs.tree, defaults); + $args = actions.makeArgumentsType( + $typedargslist.start, + $d, + actions.castArg($starargs.tree), + $k, + actions.castArg($kwargs.tree), + defaults, + kw_defaults); } | STAR starargs=tfpdef[expr_contextType.Param] (COMMA DOUBLESTAR kwargs=tfpdef[expr_contextType.Param])? { - $args = actions.makeArgumentsType($typedargslist.start, $d, $starargs.tree, $kwargs.tree, defaults); + $args = actions.makeArgumentsType( + $typedargslist.start, + $d, + actions.castArg($starargs.tree), + $k, + actions.castArg($kwargs.tree), + defaults, + kw_defaults); } | DOUBLESTAR kwargs=tfpdef[expr_contextType.Param] { - $args = actions.makeArgumentsType($typedargslist.start, $d, null, $kwargs.tree, defaults); + $args = actions.makeArgumentsType( + $typedargslist.start, + $d, + null, + $k, + actions.castArg($kwargs.tree), + defaults, + kw_defaults); } ; @@ -530,23 +553,47 @@ varargslist returns [arguments args] @init { List defaults = new ArrayList(); + List kw_defaults = new ArrayList(); } : d+=vdefparameter[defaults] (options {greedy=true;}:COMMA d+=vdefparameter[defaults])* (COMMA - (STAR (starargs=vfpdef[expr_contextType.Param])? (COMMA DOUBLESTAR kwargs=vfpdef[expr_contextType.Param])? + (STAR (starargs=vfpdef[expr_contextType.Param])? (COMMA k+=vdefparameter[kw_defaults])* + (COMMA DOUBLESTAR kwargs=vfpdef[expr_contextType.Param])? | DOUBLESTAR kwargs=vfpdef[expr_contextType.Param] )? )? { - $args = actions.makeArgumentsType($varargslist.start, $d, $starargs.tree, $kwargs.tree, defaults); + $args = actions.makeArgumentsType( + $varargslist.start, + $d, + actions.castArg($starargs.tree), + $k, + actions.castArg($kwargs.tree), + defaults, + kw_defaults); } | STAR starargs=vfpdef[expr_contextType.Param] (COMMA DOUBLESTAR kwargs=vfpdef[expr_contextType.Param])? { - $args = actions.makeArgumentsType($varargslist.start, $d, $starargs.tree, $kwargs.tree, defaults); + $args = actions.makeArgumentsType( + $varargslist.start, + $d, + actions.castArg($starargs.tree), + $k, + actions.castArg($kwargs.tree), + defaults, + kw_defaults); + } | DOUBLESTAR kwargs=vfpdef[expr_contextType.Param] { - $args = actions.makeArgumentsType($varargslist.start, $d, null, $kwargs.tree, defaults); + $args = actions.makeArgumentsType( + $varargslist.start, + $d, + null, + $k, + actions.castArg($kwargs.tree), + defaults, + kw_defaults); } ; @@ -1482,10 +1529,14 @@ List arguments = new ArrayList(); List kws = new ArrayList(); List gens = new ArrayList(); + + List arguments2 = new ArrayList(); + List kws2 = new ArrayList(); + List gens2 = new ArrayList(); } : argument[arguments, kws, gens, true] (COMMA argument[arguments, kws, gens, false])* (COMMA - ( STAR s=test[expr_contextType.Load] (COMMA DOUBLESTAR k=test[expr_contextType.Load])? + ( STAR s=test[expr_contextType.Load] (COMMA argument[arguments2, kws2, gens2, false])* (COMMA DOUBLESTAR k=test[expr_contextType.Load])? | DOUBLESTAR k=test[expr_contextType.Load] )? )? Modified: branches/jy3k/src/org/python/antlr/GrammarActions.java =================================================================== --- branches/jy3k/src/org/python/antlr/GrammarActions.java 2009-01-10 00:49:02 UTC (rev 5906) +++ branches/jy3k/src/org/python/antlr/GrammarActions.java 2009-01-10 03:53:36 UTC (rev 5907) @@ -170,7 +170,6 @@ if (o instanceof PythonTree) { return errorHandler.errorArg((PythonTree)o); } - errorHandler.error("Bad Arg node", null); return null; } @@ -315,24 +314,39 @@ } } - arguments makeArgumentsType(Token t, List params, PythonTree snameToken, - PythonTree knameToken, List defaults) { + arguments makeArgumentsType( + Token t, + List args, + arg vararg, + List kwonlyargs, //* + arg kwarg, + List defaults, + List kw_defaults //* + ) { - List<arg> p = castArgs(params); + List<arg> p = castArgs(args); List<expr> d = castExprs(defaults); + List<arg> kw = castArgs(kwonlyargs); + List<expr> kw_d = castExprs(kw_defaults); String s; String k; - if (snameToken == null) { + expr sAnnotation; + expr kAnnotation; + if (vararg == null) { s = null; + sAnnotation = null; } else { - s = cantBeNone(snameToken); + s = cantBeNone(vararg); + sAnnotation = vararg.getInternalAnnotation(); } - if (knameToken == null) { + if (kwarg == null) { k = null; + kAnnotation = null; } else { - k = cantBeNone(knameToken); + k = cantBeNone(kwarg); + kAnnotation = kwarg.getInternalAnnotation(); } - return new arguments(t, p, s, null, new ArrayList<arg>(), k, null, d, new ArrayList<expr>()); + return new arguments(t, p, s, sAnnotation, kw, k, kAnnotation, d, kw_d); } List<expr> extractArgs(List args) { @@ -550,6 +564,13 @@ return new UnaryOp(t, unaryopType.USub, o); } + String cantBeNone(arg a) { + if (a == null || a.getInternalArg().equals("None")) { + errorHandler.error("can't be None", a); + } + return a.getInternalArg(); + } + String cantBeNone(Token t) { if (t == null || t.getText().equals("None")) { errorHandler.error("can't be None", new PythonTree(t)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-01-10 00:49:08
|
Revision: 5906 http://jython.svn.sourceforge.net/jython/?rev=5906&view=rev Author: pjenvey Date: 2009-01-10 00:49:02 +0000 (Sat, 10 Jan 2009) Log Message: ----------- fix broken import Modified Paths: -------------- trunk/jython/Lib/os.py Modified: trunk/jython/Lib/os.py =================================================================== --- trunk/jython/Lib/os.py 2009-01-09 20:53:52 UTC (rev 5905) +++ trunk/jython/Lib/os.py 2009-01-10 00:49:02 UTC (rev 5906) @@ -569,7 +569,7 @@ if _time_t is None: from java.lang import Integer, Long try: - from org.python.posix import Platform + from org.python.posix.util import Platform except ImportError: from org.jruby.ext.posix.util import Platform _time_t = Integer if Platform.IS_32_BIT else Long This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-09 20:53:59
|
Revision: 5905 http://jython.svn.sourceforge.net/jython/?rev=5905&view=rev Author: fwierzbicki Date: 2009-01-09 20:53:52 +0000 (Fri, 09 Jan 2009) Log Message: ----------- Update README Modified Paths: -------------- trunk/jython/README.txt Modified: trunk/jython/README.txt =================================================================== --- trunk/jython/README.txt 2009-01-09 20:43:55 UTC (rev 5904) +++ trunk/jython/README.txt 2009-01-09 20:53:52 UTC (rev 5905) @@ -1,7 +1,7 @@ -Welcome to Jython 2.5b0 +Welcome to Jython 2.5b1 ======================= -This is the first beta of the 2.5 version of Jython. It +This is the second beta of the 2.5 version of Jython. It contains most of the new features for the 2.5 release. The release was compiled on Mac OS X with JDK 5 and requires JDK 5 to run. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-09 20:44:01
|
Revision: 5904 http://jython.svn.sourceforge.net/jython/?rev=5904&view=rev Author: fwierzbicki Date: 2009-01-09 20:43:55 +0000 (Fri, 09 Jan 2009) Log Message: ----------- locked CPython to revision 68460. Revision Links: -------------- http://jython.svn.sourceforge.net/jython/?rev=68460&view=rev Property Changed: ---------------- trunk/jython/ Property changes on: trunk/jython ___________________________________________________________________ Modified: svn:externals - CPythonLib http://svn.python.org/projects/python/branches/release25-maint/Lib/ + CPythonLib -r68460 http://svn.python.org/projects/python/branches/release25-maint/Lib/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-09 20:40:16
|
Revision: 5903 http://jython.svn.sourceforge.net/jython/?rev=5903&view=rev Author: fwierzbicki Date: 2009-01-09 20:40:11 +0000 (Fri, 09 Jan 2009) Log Message: ----------- Change release numbers in build. Modified Paths: -------------- trunk/jython/build.xml Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-01-09 18:01:13 UTC (rev 5902) +++ trunk/jython/build.xml 2009-01-09 20:40:11 UTC (rev 5903) @@ -187,8 +187,8 @@ <property name="PY_RELEASE_LEVEL_SNAPSHOT" value="170"/> <!-- 0xAA --> <!-- The current version info --> - <property name="jython.version" value="2.5b0+"/> - <property name="jython.version.noplus" value="2.5b0"/> + <property name="jython.version" value="2.5b1+"/> + <property name="jython.version.noplus" value="2.5b1"/> <property name="jython.major_version" value="2"/> <property name="jython.minor_version" value="5"/> <property name="jython.micro_version" value="0"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2009-01-09 18:01:27
|
Revision: 5902 http://jython.svn.sourceforge.net/jython/?rev=5902&view=rev Author: otmarhumbel Date: 2009-01-09 18:01:13 +0000 (Fri, 09 Jan 2009) Log Message: ----------- let the progress indicator have some air to breathe Modified Paths: -------------- trunk/installer/src/java/org/python/util/install/JarInstaller.java Modified: trunk/installer/src/java/org/python/util/install/JarInstaller.java =================================================================== --- trunk/installer/src/java/org/python/util/install/JarInstaller.java 2009-01-09 17:31:07 UTC (rev 5901) +++ trunk/installer/src/java/org/python/util/install/JarInstaller.java 2009-01-09 18:01:13 UTC (rev 5902) @@ -178,22 +178,22 @@ } private int approximateNumberOfEntries(InstallationType installationType) { - int numberOfEntries = 100; // core (minimum) + int numberOfEntries = 150; // core (minimum) if (installationType.installLibraryModules()) { if (installationType.isStandalone()) { - numberOfEntries += 480; + numberOfEntries += 540; } else { - numberOfEntries += 1260; + numberOfEntries += 1300; } } if (installationType.installDemosAndExamples()) { - numberOfEntries += 50; + numberOfEntries += 60; } if (installationType.installDocumentation()) { - numberOfEntries += 185; + numberOfEntries += 250; } if (installationType.installSources()) { - numberOfEntries += 585; + numberOfEntries += 800; } return numberOfEntries; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2009-01-09 17:31:13
|
Revision: 5901 http://jython.svn.sourceforge.net/jython/?rev=5901&view=rev Author: otmarhumbel Date: 2009-01-09 17:31:07 +0000 (Fri, 09 Jan 2009) Log Message: ----------- reduce the size of the installer .jar by excluding external libraries we do not want to distribute Modified Paths: -------------- trunk/jython/build.xml Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-01-09 15:16:08 UTC (rev 5900) +++ trunk/jython/build.xml 2009-01-09 17:31:07 UTC (rev 5901) @@ -720,6 +720,15 @@ <fileset dir="${dist.dir}"> <exclude name="${jython.dev.jar}"/> <exclude name="callbacker_test.jar"/> + <exclude name="extlibs/svnant-jars/**" /> + <exclude name="extlibs/antlr*.jar" /> + <exclude name="extlibs/asm*.jar" /> + <exclude name="extlibs/constantine*.jar" /> + <exclude name="extlibs/jarjar*.jar" /> + <exclude name="extlibs/junit*.jar" /> + <exclude name="extlibs/servlet-api*.jar" /> + <exclude name="extlibs/stringtemplate*.jar" /> + <exclude name="extlibs/xerces*.jar" /> </fileset> <manifest> <attribute name="Main-Class" value="org.python.util.install.Installation" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-09 15:16:25
|
Revision: 5900 http://jython.svn.sourceforge.net/jython/?rev=5900&view=rev Author: fwierzbicki Date: 2009-01-09 15:16:08 +0000 (Fri, 09 Jan 2009) Log Message: ----------- Fix for wrong error line number when file ends with open paren. Modified Paths: -------------- trunk/jython/Lib/test/test_eof_jy.py trunk/jython/src/org/python/antlr/PythonTokenSource.java Added Paths: ----------- trunk/jython/Lib/test/eof_fodder7.py Added: trunk/jython/Lib/test/eof_fodder7.py =================================================================== --- trunk/jython/Lib/test/eof_fodder7.py (rev 0) +++ trunk/jython/Lib/test/eof_fodder7.py 2009-01-09 15:16:08 UTC (rev 5900) @@ -0,0 +1,5 @@ +def hi(): + pass + +def bye(): + hi( Modified: trunk/jython/Lib/test/test_eof_jy.py =================================================================== --- trunk/jython/Lib/test/test_eof_jy.py 2009-01-09 04:50:22 UTC (rev 5899) +++ trunk/jython/Lib/test/test_eof_jy.py 2009-01-09 15:16:08 UTC (rev 5900) @@ -45,6 +45,12 @@ except ImportError, cause: self.fail(cause) + def test_trailing_paren(self): + try: + import eof_fodder7 + except SyntaxError, cause: + self.assertEquals(cause.lineno, 5) + #============================================================================== def test_main(verbose=None): Modified: trunk/jython/src/org/python/antlr/PythonTokenSource.java =================================================================== --- trunk/jython/src/org/python/antlr/PythonTokenSource.java 2009-01-09 04:50:22 UTC (rev 5899) +++ trunk/jython/src/org/python/antlr/PythonTokenSource.java 2009-01-09 15:16:08 UTC (rev 5900) @@ -146,6 +146,7 @@ } private void generateNewline(Token t) { + //System.out.println("generating newline from token: " + t); CommonToken newline = new CommonToken(PythonLexer.NEWLINE, "\n"); newline.setLine(t.getLine()); newline.setCharPositionInLine(t.getCharPositionInLine()); @@ -153,9 +154,12 @@ } private void handleEOF(CommonToken eof, CommonToken prev) { + //System.out.println("processing eof with token: " + prev); if (prev != null) { eof.setStartIndex(prev.getStopIndex()); eof.setStopIndex(prev.getStopIndex()); + eof.setLine(prev.getLine()); + eof.setCharPositionInLine(prev.getCharPositionInLine()); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-09 04:50:29
|
Revision: 5899 http://jython.svn.sourceforge.net/jython/?rev=5899&view=rev Author: fwierzbicki Date: 2009-01-09 04:50:22 +0000 (Fri, 09 Jan 2009) Log Message: ----------- Merged revisions 5889-5893 via svnmerge from https://jython.svn.sourceforge.net/svnroot/jython/trunk/jython ........ r5889 | pjenvey | 2009-01-08 16:23:29 -0500 (Thu, 08 Jan 2009) | 5 lines jython-elementtree from: http://jython-elementtree.googlecode.com/svn/trunk@69 provides a partial emulation of pyexpat via xerces 2.9.1 and extra tests in test_xml_etree_jy from Sebastien Boisgerault ........ r5890 | pjenvey | 2009-01-08 16:26:19 -0500 (Thu, 08 Jan 2009) | 2 lines xerces 2.9.1 for elementtree ........ r5891 | pjenvey | 2009-01-08 16:49:36 -0500 (Thu, 08 Jan 2009) | 2 lines jarjar xerces into jython-complete and check for the mangled name ........ r5892 | pjenvey | 2009-01-08 17:05:28 -0500 (Thu, 08 Jan 2009) | 2 lines unused import, coding standards ........ r5893 | otmarhumbel | 2009-01-08 17:54:04 -0500 (Thu, 08 Jan 2009) | 10 lines rename the jython*.jar files: jython.jar is now called jython-dev.jar jython-complete.jar is now called jython.jar the one we distribute is jython.jar, containing the necessary external libraries, mangled jython-dev.jar is intended for local developer usage, containing no external libraries, referencing the real external package names ........ Modified Paths: -------------- branches/jy3k/CPythonLib.includes branches/jy3k/Lib/test/regrtest.py branches/jy3k/Lib/test/test_xml_etree.py branches/jy3k/Lib/test/test_xml_etree_c.py branches/jy3k/bugtests/README.txt branches/jy3k/bugtests/test386.py branches/jy3k/bugtests/test394.py branches/jy3k/bugtests/test394jar/MANIFEST.MF branches/jy3k/build.xml branches/jy3k/src/org/python/core/PySystemState.java branches/jy3k/src/org/python/util/JythoncAntTask.java branches/jy3k/src/shell/jython branches/jy3k/src/shell/jython.bat Added Paths: ----------- branches/jy3k/Lib/pyexpat.py branches/jy3k/Lib/test/test_xml_etree_jy.py branches/jy3k/Lib/xml/parsers/ branches/jy3k/Lib/xml/parsers/__init__.py branches/jy3k/Lib/xml/parsers/expat.py branches/jy3k/extlibs/xercesImpl.jar Removed Paths: ------------- branches/jy3k/Lib/xml/parsers/__init__.py branches/jy3k/Lib/xml/parsers/expat.py Property Changed: ---------------- branches/jy3k/ Property changes on: branches/jy3k ___________________________________________________________________ Modified: svnmerge-integrated - /trunk/jython:1-5885 + /trunk/jython:1-5898 Modified: branches/jy3k/CPythonLib.includes =================================================================== --- branches/jy3k/CPythonLib.includes 2009-01-09 04:32:35 UTC (rev 5898) +++ branches/jy3k/CPythonLib.includes 2009-01-09 04:50:22 UTC (rev 5899) @@ -8,6 +8,7 @@ encodings/** logging/* test/** +xml/etree/** # Lib files, in alphabetical order: __future__.py Copied: branches/jy3k/Lib/pyexpat.py (from rev 5893, trunk/jython/Lib/pyexpat.py) =================================================================== --- branches/jy3k/Lib/pyexpat.py (rev 0) +++ branches/jy3k/Lib/pyexpat.py 2009-01-09 04:50:22 UTC (rev 5899) @@ -0,0 +1 @@ +from xml.parsers.expat import * Modified: branches/jy3k/Lib/test/regrtest.py =================================================================== --- branches/jy3k/Lib/test/regrtest.py 2009-01-09 04:32:35 UTC (rev 5898) +++ branches/jy3k/Lib/test/regrtest.py 2009-01-09 04:50:22 UTC (rev 5899) @@ -1449,7 +1449,6 @@ test_wave test_winreg test_winsound - test_xml_etree_c test_zipfile64 """ } @@ -1487,7 +1486,6 @@ test_ucn test_unicode test_unicodedata - test_xml_etree test_zipimport """, } Modified: branches/jy3k/Lib/test/test_xml_etree.py =================================================================== --- branches/jy3k/Lib/test/test_xml_etree.py 2009-01-09 04:32:35 UTC (rev 5898) +++ branches/jy3k/Lib/test/test_xml_etree.py 2009-01-09 04:50:22 UTC (rev 5899) @@ -209,7 +209,7 @@ >>> check_encoding(ET, "iso-8859-1") >>> check_encoding(ET, "iso-8859-15") >>> check_encoding(ET, "cp437") - >>> check_encoding(ET, "mac-roman") + >>> #check_encoding(ET, "mac-roman") """ ET.XML("<?xml version='1.0' encoding='%s'?><xml />" % encoding) Modified: branches/jy3k/Lib/test/test_xml_etree_c.py =================================================================== --- branches/jy3k/Lib/test/test_xml_etree_c.py 2009-01-09 04:32:35 UTC (rev 5898) +++ branches/jy3k/Lib/test/test_xml_etree_c.py 2009-01-09 04:50:22 UTC (rev 5899) @@ -198,7 +198,7 @@ >>> check_encoding("iso-8859-1") >>> check_encoding("iso-8859-15") >>> check_encoding("cp437") - >>> check_encoding("mac-roman") + >>> #check_encoding("mac-roman") """ ET.XML( "<?xml version='1.0' encoding='%s'?><xml />" % encoding Copied: branches/jy3k/Lib/test/test_xml_etree_jy.py (from rev 5893, trunk/jython/Lib/test/test_xml_etree_jy.py) =================================================================== --- branches/jy3k/Lib/test/test_xml_etree_jy.py (rev 0) +++ branches/jy3k/Lib/test/test_xml_etree_jy.py 2009-01-09 04:50:22 UTC (rev 5899) @@ -0,0 +1,754 @@ +# encoding: utf-8 + +import sys +JYTHON = sys.platform.startswith("java") + +import doctest + +import xml.parsers.expat as expat +from xml.etree.ElementTree import * + +def jython(function): + if JYTHON: + return function + else: + return None + +class sortdict(dict): + def __repr__(self): + items = self.items() + items.sort() + pairs = ["%r: %r" % pair for pair in items] + return "{%s}" % ", ".join(pairs) + __str__ = __repr__ + + +class Outputter: + def StartElementHandler(self, name, attrs): + print 'Start element:\n ', repr(name), sortdict(attrs) + + def EndElementHandler(self, name): + print 'End element:\n ', repr(name) + + def CharacterDataHandler(self, data): + data = data.strip() + if data: + print 'Character data:' + print ' ', repr(data) + + def ProcessingInstructionHandler(self, target, data): + print 'PI:\n ', repr(target), repr(data) + + def StartNamespaceDeclHandler(self, prefix, uri): + print 'NS decl:\n ', repr(prefix), repr(uri) + + def EndNamespaceDeclHandler(self, prefix): + print 'End of NS decl:\n ', repr(prefix) + + def StartCdataSectionHandler(self): + print 'Start of CDATA section' + + def EndCdataSectionHandler(self): + print 'End of CDATA section' + + def CommentHandler(self, text): + print 'Comment:\n ', repr(text) + + def NotationDeclHandler(self, *args): + name, base, sysid, pubid = args + print 'Notation declared:', args + + def UnparsedEntityDeclHandler(self, *args): + entityName, base, systemId, publicId, notationName = args + print 'Unparsed entity decl:\n ', args + + def NotStandaloneHandler(self, userData): + print 'Not standalone' + return 1 + + def ExternalEntityRefHandler(self, *args): + context, base, sysId, pubId = args + print 'External entity ref:', args[1:] + return 1 + + def DefaultHandler(self, userData): + pass + + def DefaultHandlerExpand(self, userData): + pass + +_= """ + >>> data = '''\ + ... <?xml version="1.0" encoding="iso-8859-1" standalone="no"?> + ... <?xml-stylesheet href="stylesheet.css"?> + ... <!-- comment data --> + ... <!DOCTYPE quotations SYSTEM "quotations.dtd" [ + ... <!ELEMENT root ANY> + ... <!NOTATION notation SYSTEM "notation.jpeg"> + ... <!ENTITY acirc "â"> + ... <!ENTITY external_entity SYSTEM "entity.file"> + ... <!ENTITY unparsed_entity SYSTEM "entity.file" NDATA notation> + ... %unparsed_entity; + ... ]> + ... + ... <root attr1="value1" attr2="value2ὀ"> + ... <myns:subelement xmlns:myns="http://www.python.org/namespace"> + ... Contents of subelements + ... </myns:subelement> + ... <sub2><![CDATA[contents of CDATA section]]></sub2> + ... &external_entity; + ... </root> + ... ''' + """ + +def test_utf8(): + """ + Source: test_pyexpat.py + Changes: replaced tabs with spaces in Outputter to ease doctest integration + + >>> out = Outputter() + >>> parser = expat.ParserCreate(namespace_separator='!') + >>> HANDLER_NAMES = [ + ... 'StartElementHandler', 'EndElementHandler', + ... 'CharacterDataHandler', + ... 'ProcessingInstructionHandler', + ... 'UnparsedEntityDeclHandler', 'NotationDeclHandler', + ... 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler', + ... 'CommentHandler', 'StartCdataSectionHandler', + ... 'EndCdataSectionHandler', + ... 'DefaultHandler', 'DefaultHandlerExpand', + ... #'NotStandaloneHandler', + ... 'ExternalEntityRefHandler' + ... ] + >>> for name in HANDLER_NAMES: + ... setattr(parser, name, getattr(out, name)) + + >>> data = '''\\ + ... <?xml version="1.0" encoding="iso-8859-1" standalone="no"?> + ... <?xml-stylesheet href="stylesheet.css"?> + ... <!-- comment data --> + ... <!DOCTYPE quotations SYSTEM "quotations.dtd" [ + ... <!ELEMENT root ANY> + ... <!NOTATION notation SYSTEM "notation.jpeg"> + ... <!ENTITY acirc "â"> + ... <!ENTITY external_entity SYSTEM "entity.file"> + ... <!ENTITY unparsed_entity SYSTEM "entity.file" NDATA notation> + ... %unparsed_entity; + ... ]> + ... + ... <root attr1="value1" attr2="value2ὀ"> + ... <myns:subelement xmlns:myns="http://www.python.org/namespace"> + ... Contents of subelements + ... </myns:subelement> + ... <sub2><![CDATA[contents of CDATA section]]></sub2> + ... &external_entity; + ... </root> + ... ''' + + #Produce UTF-8 output + #>>> parser.returns_unicode = 0 + #>>> try: + #... parser.Parse(data, 1) + #... except expat.error: + #... print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode) + #... print '** Line', parser.ErrorLineNumber + #... print '** Column', parser.ErrorColumnNumber + #... print '** Byte', parser.ErrorByteIndex + #PI: + #'xml-stylesheet' 'href="stylesheet.css"' + #Comment: + #' comment data ' + #Notation declared: ('notation', None, 'notation.jpeg', None) + #Unparsed entity decl: + #('unparsed_entity', None, 'entity.file', None, 'notation') + #Start element: + #'root' {'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80'} + #NS decl: + #'myns' 'http://www.python.org/namespace' + #Start element: + #'http://www.python.org/namespace!subelement' {} + #Character data: + #'Contents of subelements' + #End element: + #'http://www.python.org/namespace!subelement' + #End of NS decl: + #'myns' + #Start element: + #'sub2' {} + #Start of CDATA section + #Character data: + #'contents of CDATA section' + #End of CDATA section + #End element: + #'sub2' + #External entity ref: (None, 'entity.file', None) + #End element: + #'root' + #1 + + >>> parser = expat.ParserCreate(namespace_separator='!') + >>> parser.returns_unicode = 1 + >>> for name in HANDLER_NAMES: + ... setattr(parser, name, getattr(out, name)) + >>> try: + ... parser.Parse(data, 1) + ... except expat.error: + ... print '** Line', parser.ErrorLineNumber + ... print '** Column', parser.ErrorColumnNumber + ... print '** Byte', parser.ErrorByteIndex #doctest: +REPORT_UDIFF + PI: + u'xml-stylesheet' u'href="stylesheet.css"' + Comment: + u' comment data ' + Notation declared: (u'notation', None, u'notation.jpeg', None) + Unparsed entity decl: + (u'unparsed_entity', None, u'entity.file', None, u'notation') + Start element: + u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'} + NS decl: + u'myns' u'http://www.python.org/namespace' + Start element: + u'http://www.python.org/namespace!subelement' {} + Character data: + u'Contents of subelements' + End element: + u'http://www.python.org/namespace!subelement' + End of NS decl: + u'myns' + Start element: + u'sub2' {} + Start of CDATA section + Character data: + u'contents of CDATA section' + End of CDATA section + End element: + u'sub2' + External entity ref: (None, u'entity.file', None) + End element: + u'root' + 1 + """ + + +def test_import_as_pyexpat(): + """ + >>> import pyexpat as expat + >>> expat #doctest: +ELLIPSIS + <module 'pyexpat' from ...> + """ + + +def test_errors_submodule(): + """ + >>> import xml.parsers.expat as expat + >>> expat.errors + <module 'pyexpat.errors' (built-in)> + >>> dir(expat.errors) #doctest: +ELLIPSIS + ['XML_ERROR_ABORTED', ..., 'XML_ERROR_XML_DECL', '__doc__', '__name__'] + >>> expat.errors.XML_ERROR_ABORTED + 'parsing aborted' + >>> expat.errors.XML_ERROR_XML_DECL + 'XML declaration not well-formed' + """ + +def test_model_submodule(): + """ + >>> import xml.parsers.expat as expat + >>> expat.model + <module 'pyexpat.model' (built-in)> + >>> print sortdict(expat.model.__dict__) + {'XML_CQUANT_NONE': 0, 'XML_CQUANT_OPT': 1, 'XML_CQUANT_PLUS': 3, 'XML_CQUANT_REP': 2, 'XML_CTYPE_ANY': 2, 'XML_CTYPE_CHOICE': 5, 'XML_CTYPE_EMPTY': 1, 'XML_CTYPE_MIXED': 3, 'XML_CTYPE_NAME': 4, 'XML_CTYPE_SEQ': 6, '__doc__': 'Constants used to interpret content model information.', '__name__': 'pyexpat.model'} + """ + +def test_parse_only_xml_data(): + """ + Source: test_pyexpat.py, see also: http://python.org/sf/1296433 + Changes: + - replaced 'iso8859' encoding with 'ISO-8859-1', + - added isfinal=True keyword argument to Parse call (as in this port, + the data is not processed until it is fully available). + With these changes, the test still crashes CPython 2.5. + + >>> import xml.parsers.expat as expat + >>> # xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025) + + This one doesn't crash: + >>> xml = "<?xml version='1.0'?><s>%s</s>" % ('a' * 10000) + + >>> def handler(text): + ... raise Exception + >>> parser = expat.ParserCreate() + >>> parser.CharacterDataHandler = handler + >>> try: + ... parser.Parse(xml, True) + ... except: + ... pass + """ + + +def test_namespace_separator(): + """ + Source: test_pyexpat.py + + Tests that make sure we get errors when the namespace_separator value + is illegal, and that we don't for good values: + + >>> from xml.parsers.expat import ParserCreate + + >>> p = ParserCreate() + >>> p = ParserCreate(namespace_separator=None) + >>> p = ParserCreate(namespace_separator=' ') + >>> p = ParserCreate(namespace_separator=42) #doctest: +ELLIPSIS + Traceback (most recent call last): + ... + TypeError: ... + >>> p = ParserCreate(namespace_separator='too long') #doctest: +ELLIPSIS + Traceback (most recent call last): + ... + ValueError: ... + + ParserCreate() needs to accept a namespace_separator of zero length + to satisfy the requirements of RDF applications that are required + to simply glue together the namespace URI and the localname. Though + considered a wart of the RDF specifications, it needs to be supported. + + See XML-SIG mailing list thread starting with + http://mail.python.org/pipermail/xml-sig/2001-April/005202.html + + >>> p = ParserCreate(namespace_separator='') # too short +""" + + +def test_interning_machinery(): + """ + Source: test_pyexpat.py + + >>> from xml.parsers.expat import ParserCreate + + >>> p = ParserCreate() + >>> L = [] + >>> def collector(name, *args): + ... L.append(name) + >>> p.StartElementHandler = collector + >>> p.EndElementHandler = collector + >>> p.Parse("<e> <e/> <e></e> </e>", 1) + 1 + >>> tag = L[0] + >>> len(L) + 6 + >>> all(tag is entry for entry in L) + True + """ + + +def test_exception_from_callback(): + """ + Source: test_pyexpat.py + + >>> from xml.parsers.expat import ParserCreate + + >>> def StartElementHandler(name, attrs): + ... raise RuntimeError(name) + + >>> parser = ParserCreate() + >>> parser.StartElementHandler = StartElementHandler + >>> try: + ... parser.Parse("<a><b><c/></b></a>", 1) + ... except RuntimeError, e: + ... pass + >>> e.args[0] == "a" + True + """ + + +def test_with_and_without_namespace(): + """ + >>> from xml.parsers.expat import ParserCreate + + >>> xml = '''<root + ... xmlns="http://www.python.org" + ... xmlns:python="http://www.python.org" + ... python:a="1" b="2"> + ... <python:sub1/> + ... <sub2 xmlns=""/> + ... </root>''' + >>> def handler(name, attributes): + ... attributes = sorted(attributes.items()) + ... print name + ... for attr in attributes: + ... print " %s = %r" % attr + + >>> parser = ParserCreate() + >>> parser.StartElementHandler = handler + >>> _ = parser.Parse(xml, True) + root + b = u'2' + python:a = u'1' + xmlns = u'http://www.python.org' + xmlns:python = u'http://www.python.org' + python:sub1 + sub2 + xmlns = u'' + + >>> parser = ParserCreate(namespace_separator="|") + >>> parser.StartElementHandler = handler + >>> _ = parser.Parse(xml, True) + http://www.python.org|root + b = u'2' + http://www.python.org|a = u'1' + http://www.python.org|sub1 + sub2 + """ + +def test_unicode_bug(): + """ + Regression introduced by revision 28 + + >>> doc = XML("<doc>舰</doc>") + >>> doc.text + u'\u8230' + """ + +def test_DTD(): + """ + >>> xml = '''<!DOCTYPE doc [ + ... <!ELEMENT doc (any|empty|text|mixed|opt|many|plus)> + ... <!ELEMENT any ANY> + ... <!ELEMENT empty EMPTY> + ... <!ELEMENT text (#PCDATA)> + ... <!ELEMENT sequence (_sequence)> + ... <!ELEMENT _sequence (any,any)> + ... <!ELEMENT mixed (#PCDATA|any)*> + ... <!ELEMENT opt (empty)?> + ... <!ELEMENT many (empty)*> + ... <!ELEMENT plus (empty)+> + ... ]> + ... <doc><text>content</text></doc> + ... ''' + >>> parser = expat.ParserCreate() + >>> def handler(header, *args): + ... def _handler(*args): + ... print header + ":", args + ... return _handler + >>> parser.ElementDeclHandler = handler("ELEMENT") + >>> parser.AttlistDeclHandler = handler("ATTRIBUTE") + >>> parser.EntityDeclHandler = handler("ENTITY") + >>> parser.NotationDeclHandler = handler("NOTATION") + >>> parser.UnparsedEntityDeclHandler = handler("UNPARSED") + >>> parser.Parse(xml, True) + ELEMENT: (u'doc', (5, 0, None, ((4, 0, u'any', ()), (4, 0, u'empty', ()), (4, 0, u'text', ()), (4, 0, u'mixed', ()), (4, 0, u'opt', ()), (4, 0, u'many', ()), (4, 0, u'plus', ())))) + ELEMENT: (u'any', (2, 0, None, ())) + ELEMENT: (u'empty', (1, 0, None, ())) + ELEMENT: (u'text', (3, 0, None, ())) + ELEMENT: (u'sequence', (6, 0, None, ((4, 0, u'_sequence', ()),))) + ELEMENT: (u'_sequence', (6, 0, None, ((4, 0, u'any', ()), (4, 0, u'any', ())))) + ELEMENT: (u'mixed', (3, 2, None, ((4, 0, u'any', ()),))) + ELEMENT: (u'opt', (6, 1, None, ((4, 0, u'empty', ()),))) + ELEMENT: (u'many', (6, 2, None, ((4, 0, u'empty', ()),))) + ELEMENT: (u'plus', (6, 3, None, ((4, 0, u'empty', ()),))) + 1 + """ + +def test_entity(): + """ + + TODO: need a fallback for entity-resolver so that empty source is returned. + + >>> xml = ''' <!DOCTYPE doc SYSTEM "external.dtd" [ + ... <!ENTITY ext-entity SYSTEM "external-entity"> + ... ]> + ... <doc>&ext-entity;&in-ext-dtd-entity;</doc>''' + >>> parser = expat.ParserCreate() + >>> parser.Parse(xml, True) + 1 + + EXPAT OH MY ! When applicable (internal entities), the CharacterDataHandler + callback will override DefaultHandlerExpand, but it WON'T override + DefaultHandler. On the other hand, the DefaultHandlerExpand callback WILL + override DefaultHandler ... More tests todo here ... + + >>> xml = '''<!DOCTYPE doc SYSTEM "external.dtd" [ + ... <!ENTITY ext-entity SYSTEM "external-entity"> + ... <!ENTITY int-entity "internal"> + ... ]> + ... <doc>&int-entity;&ext-entity;&in-ext-dtd-entity;</doc>''' + >>> parser = expat.ParserCreate() + >>> def handler(header): + ... def _handler(*args): + ... print header + ":", args + ... return 1 + ... return _handler + >>> parser.CharacterDataHandler = handler("text") + >>> parser.DefaultHandler = handler("default") + >>> parser.Parse(xml, True) #doctest: +ELLIPSIS + default: ... + default: (u'&int-entity;',) + default: (u'&ext-entity;',) + default: (u'&in-ext-dtd-entity;',) + ... + 1 + + EXPAT OH MY ! When applicable (internal entities), the CharacterDataHandler + callback will override DefaultHandlerExpand, but it WON'T override + DefaultHandler. On the other hand, the DefaultHandlerExpand callback WILL + override DefaultHandler ... More tests todo here ... + """ + +def test_resolve_entity_handlers(): + """ + >>> xml = '''<!DOCTYPE doc [ + ... <!ENTITY entity SYSTEM "entity"> + ... ]> + ... <doc>&entity;</doc>''' + >>> def handler(header): + ... def _handler(*args): + ... print header + ":", args + ... return 1 + ... return _handler + + >>> parser = expat.ParserCreate() + >>> parser.ExternalEntityRefHandler = handler("ExternalEntityRefHandler") + >>> parser.Parse(xml, True) + ExternalEntityRefHandler: (u'entity', None, u'entity', None) + 1 + """ + +def handler(name, header="XML>", returns=None): + def _handler(*args): + if len(args) == 1: + args = "(%r)" % args[0] + else: + args = str(args) + print header, name + "%s" % args + return returns + return _handler + +def parse(xml, *handlers): + parser = expat.ParserCreate() + for name in handlers: + if name == "ExternalEntityRefHandler": + returns = 1 + else: + returns = None + setattr(parser, name, handler(name, returns=returns)) + parser.Parse(xml, True) + +def test_internal_entities(): + """ + >>> xml = '''<!DOCTYPE doc [ + ... <!ENTITY entity "entity-content"> + ... ]> + ... <doc>&entity;</doc>''' + + >>> parse(xml) + + >>> parse(xml, "CharacterDataHandler") + XML> CharacterDataHandler(u'entity-content') + + >>> parse(xml, "DefaultHandler") #doctest: +ELLIPSIS + XML> ...DefaultHandler(u'&entity;')... + + >>> parse(xml, "DefaultHandlerExpand") #doctest: +ELLIPSIS + XML> ...DefaultHandlerExpand(u'entity-content')... + + # Uhu ? + >>> parse(xml, "CharacterDataHandler", + ... "DefaultHandler") #doctest: +ELLIPSIS + XML> ...DefaultHandler(u'&entity;')... + + >>> parse(xml, "CharacterDataHandler", + ... "DefaultHandlerExpand") #doctest: +ELLIPSIS + XML> ...CharacterDataHandler(u'entity-content')... + + >>> parse(xml, "DefaultHandler", + ... "DefaultHandlerExpand") #doctest: +ELLIPSIS + XML> ...DefaultHandlerExpand(u'entity-content')... + + >>> parse(xml, "CharacterDataHandler", + ... "DefaultHandler", + ... "DefaultHandlerExpand") #doctest: +ELLIPSIS + XML> ...CharacterDataHandler(u'entity-content')... + """ + +def test_external_entities(): + """ + >>> xml = '''<!DOCTYPE doc [ + ... <!ENTITY entity PUBLIC "http://entity-web" "entity-file"> + ... ]> + ... <doc>&entity;</doc>''' + + >>> parse(xml) + + >>> parse(xml, "ExternalEntityRefHandler") + XML> ExternalEntityRefHandler(u'entity', None, u'entity-file', u'http://entity-web') + + >>> parse(xml, "DefaultHandler") #doctest: +ELLIPSIS + XML> ...DefaultHandler(u'&entity;')... + + >>> parse(xml, "DefaultHandlerExpand") #doctest: +ELLIPSIS + XML> ...DefaultHandlerExpand(u'&entity;')... + + >>> parse(xml, "ExternalEntityRefHandler", + ... "DefaultHandler") #doctest: +ELLIPSIS + XML> ...ExternalEntityRefHandler(u'entity', None, u'entity-file', u'http://entity-web')... + + >>> parse(xml, "ExternalEntityRefHandler", + ... "DefaultHandlerExpand") #doctest: +ELLIPSIS + XML> ...ExternalEntityRefHandler(u'entity', None, u'entity-file', u'http://entity-web')... + + >>> parse(xml, "DefaultHandler", + ... "DefaultHandlerExpand") #doctest: +ELLIPSIS + XML> ...DefaultHandlerExpand(u'&entity;')... + + >>> parse(xml, "ExternalEntityRefHandler", + ... "DefaultHandler", + ... "DefaultHandlerExpand") #doctest: +ELLIPSIS + XML> ...ExternalEntityRefHandler(u'entity', None, u'entity-file', u'http://entity-web')... + """ + +def test_undefined_entities(): + """ + >>> xml = "<doc>&entity;</doc>" + >>> parse(xml) + Traceback (most recent call last): + ... + ExpatError: undefined entity: line 1, column 5 + """ + +def locate(parser, name): + def _handler(*args): + print name, parser.CurrentLineNumber, parser.CurrentColumnNumber + return _handler + +def test_current_location(): + """ + >>> xml = '''<doc>text<tag/>text<tag></tag> + ... <tag></tag> + ... text<tag/> + ... </doc>''' + >>> parser = expat.ParserCreate() + >>> parser.CharacterDataHandler = locate(parser, "TEXT:") + >>> parser.StartElementHandler = locate(parser, "START:") + >>> parser.EndElementHandler = locate(parser, "END:") + >>> _ = parser.Parse(xml, True) #doctest: +ELLIPSIS + START: 1 0 + TEXT: 1 5... + START: 1 9 + END: 1 15 + TEXT: 1 15... + START: 1 19 + END: 1 24 + TEXT: 1 30... + START: 2 0 + END: 2 5 + TEXT: 2 11... + START: 3 4 + END: 3 10 + TEXT: 3 10... + END: 4 0 + + >>> xml = '''<doc> + ... start tag after some text<tag/> + ... <elt></elt><tag/> + ... <elt/><tag/> + ... </doc>''' + >>> parser = expat.ParserCreate() + >>> parser.CharacterDataHandler = locate(parser, "TEXT:") + >>> parser.StartElementHandler = locate(parser, "START:") + >>> parser.EndElementHandler = locate(parser, "END:") + >>> _ = parser.Parse(xml, True) #doctest: +ELLIPSIS + START: 1 0 + TEXT: 1 5... + START: 2 25 + END: 2 31 + TEXT: 2 31... + START: 3 0 + END: 3 5 + START: 3 11 + END: 3 17 + TEXT: 3 17... + START: 4 0 + END: 4 6 + START: 4 6 + END: 4 12 + TEXT: 4 12... + END: 5 0 + """ + + +def test_error_location(): + """ + Source: selftest.py, ElementTree 1.3a3 + Changes: removed dependencies in ElementTree, added one extra test + + >>> def error(xml): + ... p = expat.ParserCreate() + ... try: + ... p.Parse(xml, True) + ... except expat.ExpatError, e: + ... return e.lineno, e.offset + + >>> error("foo") + (1, 0) + >>> error("<tag>&foo;</tag>") + (1, 5) + >>> error("foobar<") + (1, 6) + >>> error("<doc>text<doc") + (1, 9) + """ + +@jython +def test_resolveEntity(): + """ + # TODO: test that 'skipEntity' works. + + >>> # Jython + >>> from org.python.core.util import StringUtil + >>> from jarray import array + + >>> # Java Standard Edition + >>> from org.xml.sax import * + >>> from org.xml.sax.ext import * + >>> from org.xml.sax.helpers import * + >>> from java.io import ByteArrayInputStream + + >>> xml = '''<!DOCTYPE doc + ... [<!ENTITY entity SYSTEM "entity-file"> + ... ]> + ... <doc>&entity;</doc> + ... ''' + + >>> def empty_source(): + ... _source = InputSource() + ... byte_stream = ByteArrayInputStream(array([], "b")) + ... _source.setByteStream(byte_stream) + ... return _source + + >>> class Handler(EntityResolver2): + ... def getExternalSubset(self, name, baseURI): + ... return None + ... def resolveEntity(self, name, publicId, baseURI, systemId): + ... print "Entity name:", name + ... return empty_source() + + >>> def main(): + ... sax_parser = "org.apache.xerces.parsers.SAXParser" + ... reader = XMLReaderFactory.createXMLReader(sax_parser) + ... entity_resolver2 = "http://xml.org/sax/features/use-entity-resolver2" + ... enabled = reader.getFeature(entity_resolver2) + ... print "Entity-Resolver2 enabled:", enabled + ... handler = Handler() + ... reader.setEntityResolver(handler) + ... bytes = StringUtil.toBytes(xml) + ... byte_stream = ByteArrayInputStream(bytes) + ... source = InputSource(byte_stream) + ... reader.parse(source) + + >>> main() + Entity-Resolver2 enabled: True + Entity name: entity + """ + +if __name__ == "__main__": + doctest.testmod() Deleted: branches/jy3k/Lib/xml/parsers/expat.py =================================================================== --- trunk/jython/Lib/xml/parsers/expat.py 2009-01-08 22:54:04 UTC (rev 5893) +++ branches/jy3k/Lib/xml/parsers/expat.py 2009-01-09 04:50:22 UTC (rev 5899) @@ -1,617 +0,0 @@ -# coding: utf-8 - -#------------------------------------------------------------------------------ -# Copyright (c) 2008 Sébastien Boisgérault -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# ----------------------------------------------------------------------------- - -__all__ = ["ExpatError", "ParserCreate", "XMLParserType", "error", "errors"] - -# Jython check -import sys -if not sys.platform.startswith('java'): - raise ImportError("this version of expat requires the jython interpreter") - -# Standard Python Library -import re -import types - -# Jython -from org.python.core import Py -from org.python.core.util import StringUtil -from jarray import array - -# Java Standard Edition -from java.io import ByteArrayInputStream -from java.lang import String, StringBuilder -from org.xml.sax import InputSource -from org.xml.sax import SAXNotRecognizedException, SAXParseException -from org.xml.sax.helpers import XMLReaderFactory -from org.xml.sax.ext import DefaultHandler2 - -# Xerces -try: - # Name mangled by jarjar? - import org.python.apache.xerces.parsers.SAXParser - _xerces_parser = "org.python.apache.xerces.parsers.SAXParser" -except ImportError: - _xerces_parser = "org.apache.xerces.parsers.SAXParser" - - -def ParserCreate(encoding=None, namespace_separator=None): - return XMLParser(encoding, namespace_separator) - - -class XMLParser(object): - - def __init__(self, encoding, namespace_separator): - self.encoding = encoding - self.CurrentLineNumber = 1 - self.CurrentColumnNumber = 0 - self._NextLineNumber = 1 - self._NextColumnNumber = 0 - self.ErrorLineNumber = -1 - self.ErrorColumnNumber = -1 - self.ErrorCode = None - - if namespace_separator is None: - self.namespace_separator = namespace_separator - elif isinstance(namespace_separator, basestring): - self.namespace_separator = str(namespace_separator) - if len(self.namespace_separator) > 1: - error = ("namespace_separator must be at most one character, " - "omitted, or None") - raise ValueError(error) - else: - error = ("ParserCreate() argument 2 must be string or None, " - "not %s" % type(namespace_separator).__name__) - raise TypeError(error) - - self._reader = XMLReaderFactory.createXMLReader(_xerces_parser) - - if self.namespace_separator is None: - try: - feature = "http://xml.org/sax/features/namespaces" - self._reader.setFeature(feature, False) - except SAXNotRecognizedException: - error = ("namespace support cannot be disabled; " - "set namespace_separator to a string of length 1.") - raise ValueError(error) - - self._base = None - self._buffer_text = True - self._returns_unicode = True - - self._data = StringBuilder() - - self._handler = XMLEventHandler(self) - self._reader.setContentHandler(self._handler) - self._reader.setErrorHandler(self._handler) - self._reader.setDTDHandler(self._handler) - self._reader.setEntityResolver(self._handler) - - sax_properties = ("lexical-handler", "declaration-handler") - for name in sax_properties: - try: - name = "http://xml.org/sax/properties/" + name - self._reader.setProperty(name, self._handler) - except SAXNotRecognizedException: - error = "can't set property %r" % name - raise NotImplementedError(error) - - apache_features = (("nonvalidating/load-external-dtd", False),) - for name, value in apache_features: - try: - name = "http://apache.org/xml/features/" + name - self._reader.setFeature(name, value) - except SAXNotRecognizedException: - error = "can't set feature %r" % name - raise NotImplementedError(error) - - # experimental - #f = "http://xml.org/sax/features/external-general-entities" - f = "http://xml.org/sax/features/external-parameter-entities" - #self._reader.setFeature(f, False) - - # check - f = "http://xml.org/sax/features/use-entity-resolver2" - assert self._reader.getFeature(f) - - def GetBase(self): - return self._base - - def SetBase(self, base): - self._base = base - - def _error(self, value=None): - raise AttributeError("'XMLParser' has no such attribute") - - def _get_buffer_text(self): - return self._buffer_text - - def _set_buffer_text(self, value): - self._buffer_text = bool(value) - - def _get_returns_unicode(self): - return bool(self._returns_unicode) - - def _set_returns_unicode(self, value): - self._returns_unicode = value - - # 'ordered' and 'specified' attributes are not supported - ordered_attributes = property(_error, _error) - specified_attributes = property(_error, _error) - # any setting is allowed, but it won't make a difference - buffer_text = property(_get_buffer_text, _set_buffer_text) - # non-significant read-only values - buffer_used = property(lambda self: None) - buffer_size = property(lambda self: None) - # 'returns_unicode' attribute is properly supported - returns_unicode = property(_get_returns_unicode, _set_returns_unicode) - - def _expat_error(self, sax_error): - sax_message = sax_error.getMessage() - pattern = 'The entity ".*" was referenced, but not declared\.' - if re.match(pattern, sax_message): - expat_message = "undefined entity: line %s, column %s" % \ - (self.ErrorLineNumber, self.ErrorColumnNumber) - else: - expat_message = sax_message - error = ExpatError(expat_message) - error.lineno = self.ErrorLineNumber - error.offset = self.ErrorColumnNumber - error.code = self.ErrorCode - return error - - def Parse(self, data, isfinal=False): - # The 'data' argument should be an encoded text: a str instance that - # represents an array of bytes. If instead it is a unicode string, - # only the us-ascii range is considered safe enough to be silently - # converted. - if isinstance(data, unicode): - data = data.encode(sys.getdefaultencoding()) - - self._data.append(data) - - if isfinal: - bytes = StringUtil.toBytes(self._data.toString()) - byte_stream = ByteArrayInputStream(bytes) - source = InputSource(byte_stream) - if self.encoding is not None: - source.setEncoding(self.encoding) - try: - self._reader.parse(source) - except SAXParseException, sax_error: - # Experiments tend to show that the '_Next*' parser locations - # match more closely expat behavior than the 'Current*' or sax - # error locations. - self.ErrorLineNumber = self._NextLineNumber - self.ErrorColumnNumber = self._NextColumnNumber - self.ErrorCode = None - raise self._expat_error(sax_error) - return 1 - - def ParseFile(self, file): - # TODO: pseudo-buffering if a read without argument is not supported. - # document parse / parsefile usage. - return self.Parse(file.read(), isfinal=True) - - -XMLParserType = XMLParser - - -def _encode(arg, encoding): - if isinstance(arg, unicode): - return arg.encode(encoding) - else: - if isinstance(arg, dict): - iterator = arg.iteritems() - else: - iterator = iter(arg) - return type(arg)(_encode(_arg, encoding) for _arg in iterator) - - -def expat(callback=None, guard="True", force=False, returns="None"): - global _register - try: - _ = _register - except NameError: - _register = {} - - def _expat(method): - name = method.__name__ - context = id(sys._getframe(1)) - key = name, context - append = _register.setdefault(key, []).append - append((method, callback, guard, force, returns)) - - def new_method(*args): - self = args[0] - parser = self.parser - self._update_location(event=name) # bug if multiple method def - for (method, callback, guard, force, returns) in _register[key]: - _callback = callback and eval(guard) and \ - getattr(parser, callback, None) - if _callback or force: - results = method(*args) - if _callback: - if not isinstance(results, tuple): - results = (results,) - if not parser.returns_unicode: - results = _encode(results, "utf-8") - _callback(*results) - return_ = eval(returns) - if callable(return_): - return return_(*args[1:]) - else: - return return_ - break - new_method.__name__ = name - #new_method.__doc__ = method.__doc__ # what to do with multiple docs ? - return new_method - return _expat - - -class XMLEventHandler(DefaultHandler2): - - def __init__(self, parser): - self.parser = parser - self._tags = {} - self.dtd = False - self._entity = {} - self._previous_event = None - - # --- Helpers ------------------------------------------------------------- - - def _intern(self, tag): - return self._tags.setdefault(tag, tag) - - def _qualify(self, local_name, qname, namespace=None): - namespace_separator = self.parser.namespace_separator - if namespace_separator is None: - return qname - if not namespace: - return local_name - else: - return namespace + namespace_separator + local_name - - def _char_slice_to_unicode(self, characters, start, length): - """Convert a char[] slice to a PyUnicode instance""" - text = Py.newUnicode(String(characters[start:start + length])) - return text - - def _expat_content_model(self, name, model_): - # TODO : implement a model parser - return (name, model_) # does not fit expat conventions - - def _update_location(self, event=None): - parser = self.parser - locator = self._locator - - # ugly hack that takes care of a xerces-specific (?) locator issue: - # locate start and end elements at the '<' instead of the first tag - # type character. - if event == "startElement" and self._previous_event == "characters": - parser._NextColumnNumber = max(parser._NextColumnNumber - 1, 0) - if event == "endElement" and self._previous_event == "characters": - parser._NextColumnNumber = max(parser._NextColumnNumber - 2, 0) - # TODO: use the same trick to report accurate error locations ? - - parser.CurrentLineNumber = parser._NextLineNumber - parser.CurrentColumnNumber = parser._NextColumnNumber - parser._NextLineNumber = locator.getLineNumber() - parser._NextColumnNumber = locator.getColumnNumber() - 1 - - self._previous_event = event - - # --- ContentHandler Interface -------------------------------------------- - - @expat("ProcessingInstructionHandler") - def processingInstruction(self, target, data): - return target, data - - @expat("StartElementHandler") - def startElement(self, namespace, local_name, qname, attributes): - tag = self._qualify(local_name, qname, namespace) - attribs = {} - length = attributes.getLength() - for index in range(length): - local_name = attributes.getLocalName(index) - qname = attributes.getQName(index) - namespace = attributes.getURI(index) - name = self._qualify(local_name, qname, namespace) - value = attributes.getValue(index) - attribs[name] = value - return self._intern(tag), attribs - - @expat("EndElementHandler") - def endElement(self, namespace, local_name, qname): - return self._intern(self._qualify(local_name, qname, namespace)) - - @expat("CharacterDataHandler") - def characters(self, characters, start, length): - return self._char_slice_to_unicode(characters, start, length) - - @expat("DefaultHandlerExpand") - def characters(self, characters, start, length): - return self._char_slice_to_unicode(characters, start, length) - - @expat("DefaultHandler") - def characters(self, characters, start, length): - # TODO: make a helper function here - if self._entity["location"] == (self.parser.CurrentLineNumber, - self.parser.CurrentColumnNumber): - return "&%s;" % self._entity["name"] - else: - return self._char_slice_to_unicode(characters, start, length) - - @expat("StartNamespaceDeclHandler") - def startPrefixMapping(self, prefix, uri): - return prefix, uri - - @expat("EndNamespaceDeclHandler") - def endPrefixMapping(self, prefix): - return prefix - - def _empty_source(self, *args): - name, publicId, baseURI, systemId = args - source = InputSource() - byte_stream = ByteArrayInputStream(array([], "b")) - source.setByteStream(byte_stream) - source.setPublicId(publicId) - source.setSystemId(systemId) - return source - - @expat("ExternalEntityRefHandler", guard="not self.dtd", - returns="self._empty_source") - def resolveEntity(self, name, publicId, baseURI, systemId): - context = name # wrong. see expat headers documentation. - base = self.parser.GetBase() - return context, base, systemId, publicId - - @expat("DefaultHandlerExpand", guard="not self.dtd", - returns="self._empty_source") - def resolveEntity(self, name, publicId, baseURI, systemId): - return "&%s;" % name - - @expat("DefaultHandler", guard="not self.dtd", - returns="self._empty_source") - def resolveEntity(self, name, publicId, baseURI, systemId): - return "&%s;" % name - - @expat(force=True, returns="self._empty_source") - def resolveEntity(self, name, publicId, baseURI, systemId): - pass - - def setDocumentLocator(self, locator): - self._locator = locator - - def skippedEntity(self, name): - error = ExpatError() - error.lineno = self.ErrorLineNumber = self.parser._NextLineNumber - error.offset = self.ErrorColumnNumber = self.parser._NextColumnNumber - error.code = self.ErrorCode = None - message = "undefined entity &%s;: line %s, column %s" - message = message % (name, error.lineno, error.offset) - error.__init__(message) - raise error - - # --- LexicalHandler Interface -------------------------------------------- - - @expat("CommentHandler") - def comment(self, characters, start, length): - return self._char_slice_to_unicode(characters, start, length) - - @expat("StartCdataSectionHandler") - def startCDATA(self): - return () - - @expat("EndCdataSectionHandler") - def endCDATA(self): - return () - - @expat("StartDoctypeDeclHandler", force=True) - def startDTD(self, name, publicId, systemId): - self.dtd = True - has_internal_subset = 0 # don't know this ... - return name, systemId, publicId, has_internal_subset - - @expat("EndDoctypeDeclHandler", force=True) - def endDTD(self): - self.dtd = False - - def startEntity(self, name): - self._entity = {} - self._entity["location"] = (self.parser._NextLineNumber, - self.parser._NextColumnNumber) - self._entity["name"] = name - - def endEntity(self, name): - pass - - # --- DTDHandler Interface ------------------------------------------------ - - @expat("NotationDeclHandler") - def notationDecl(self, name, publicId, systemId): - base = self.parser.GetBase() - return name, base, systemId, publicId - - @expat("UnparsedEntityDeclHandler") # deprecated - def unparsedEntityDecl(self, name, publicId, systemId, notationName): - base = self.parser.GetBase() - return name, base, systemId, publicId, notationName - - # --- DeclHandler Interface ----------------------------------------------- - - @expat("AttlistDeclHandler") - def attributeDecl(self, eName, aName, type, mode, value): - # TODO: adapt mode, required, etc. - required = False - return eName, aName, type, value, required - - @expat("ElementDeclHandler") - def elementDecl(self, name, model): - return self._expat_content_model(name, model) - - @expat("EntityDeclHandler") - def externalEntityDecl(self, name, publicId, systemId): - base = self.parser.GetBase() - value = None - is_parameter_entity = None - notation_name = None - return (name, is_parameter_entity, value, base, systemId, publicId, - notation_name) - - @expat("EntityDeclHandler") - def internalEntityDecl(self, name, value): - base = self.parser.GetBase() - is_parameter_entity = None - notation_name = None - systemId, publicId = None, None - return (name, is_parameter_entity, value, base, systemId, publicId, - notation_name) - - -def _init_model(): - global model - model = types.ModuleType("pyexpat.model") - model.__doc__ = "Constants used to interpret content model information." - quantifiers = "NONE, OPT, REP, PLUS" - for i, quantifier in enumerate(quantifiers.split(", ")): - setattr(model, "XML_CQUANT_" + quantifier, i) - types_ = "EMPTY, ANY, MIXED, NAME, CHOICE, SEQ" - for i, type_ in enumerate(types_.split(", ")): - setattr(model, "XML_CTYPE_" + type_, i+1) - -_init_model() -del _init_model - - -class ExpatError(Exception): - pass - - -error = ExpatError - - -def _init_error_strings(): - global ErrorString - error_strings = ( - None, - "out of memory", - "syntax error", - "no element found", - "not well-formed (invalid token)", - "unclosed token", - "partial character", - "mismatched tag", - "duplicate attribute", - "junk after document element", - "illegal parameter entity reference", - "undefined entity", - "recursive entity reference", - "asynchronous entity", - "reference to invalid character number", - "reference to binary entity", - "reference to external entity in attribute", - "XML or text declaration not at start of entity", - "unknown encoding", - "encoding specified in XML declaration is incorrect", - "unclosed CDATA section", - "error in processing external entity reference", - "document is not standalone", - "unexpected parser state - please send a bug report", - "entity declared in parameter entity", - "requested feature requires XML_DTD support in Expat", - "cannot change setting once parsing has begun", - "unbound prefix", - "must not undeclare prefix", - "incomplete markup in parameter entity", - "XML declaration not well-formed", - "text declaration not well-formed", - "illegal character(s) in public id", - "parser suspended", - "parser not suspended", - "parsing aborted", - "parsing finished", - "cannot suspend in external parameter entity") - def ErrorString(code): - try: - return error_strings[code] - except IndexError: - return None - -_init_error_strings() -del _init_error_strings - - -def _init_errors(): - global errors - - errors = types.ModuleType("pyexpat.errors") - errors.__doc__ = "Constants used to describe error conditions." - - error_names = """ - XML_ERROR_NONE - XML_ERROR_NONE, - XML_ERROR_NO_MEMORY, - XML_ERROR_SYNTAX, - XML_ERROR_NO_ELEMENTS, - XML_ERROR_INVALID_TOKEN, - XML_ERROR_UNCLOSED_TOKEN, - XML_ERROR_PARTIAL_CHAR, - XML_ERROR_TAG_MISMATCH, - XML_ERROR_DUPLICATE_ATTRIBUTE, - XML_ERROR_JUNK_AFTER_DOC_ELEMENT, - XML_ERROR_PARAM_ENTITY_REF, - XML_ERROR_UNDEFINED_ENTITY, - XML_ERROR_RECURSIVE_ENTITY_REF, - XML_ERROR_ASYNC_ENTITY, - XML_ERROR_BAD_CHAR_REF, - XML_ERROR_BINARY_ENTITY_REF, - XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, - XML_ERROR_MISPLACED_XML_PI, - XML_ERROR_UNKNOWN_ENCODING, - XML_ERROR_INCORRECT_ENCODING, - XML_ERROR_UNCLOSED_CDATA_SECTION, - XML_ERROR_EXTERNAL_ENTITY_HANDLING, - XML_ERROR_NOT_STANDALONE, - XML_ERROR_UNEXPECTED_STATE, - XML_ERROR_ENTITY_DECLARED_IN_PE, - XML_ERROR_FEATURE_REQUIRES_XML_DTD, - XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, - XML_ERROR_UNBOUND_PREFIX, - XML_ERROR_UNDECLARING_PREFIX, - XML_ERROR_INCOMPLETE_PE, - XML_ERROR_XML_DECL, - XML_ERROR_TEXT_DECL, - XML_ERROR_PUBLICID, - XML_ERROR_SUSPENDED, - XML_ERROR_NOT_SUSPENDED, - XML_ERROR_ABORTED, - XML_ERROR_FINISHED, - XML_ERROR_SUSPEND_PE - """ - error_names = [name.strip() for name in error_names.split(',')] - for i, name in enumerate(error_names[1:]): - setattr(errors, name, ErrorString(i+1)) - -_init_errors() -del _init_errors Copied: branches/jy3k/Lib/xml/parsers/expat.py (from rev 5893, trunk/jython/Lib/xml/parsers/expat.py) =================================================================== --- branches/jy3k/Lib/xml/parsers/expat.py (rev 0) +++ branches/jy3k/Lib/xml/parsers/expat.py 2009-01-09 04:50:22 UTC (rev 5899) @@ -0,0 +1,617 @@ +# coding: utf-8 + +#------------------------------------------------------------------------------ +# Copyright (c) 2008 Sébastien Boisgérault +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# ----------------------------------------------------------------------------- + +__all__ = ["ExpatError", "ParserCreate", "XMLParserType", "error", "errors"] + +# Jython check +import sys +if not sys.platform.startswith('java'): + raise ImportError("this version of expat requires the jython interpreter") + +# Standard Python Library +import re +import types + +# Jython +from org.python.core import Py +from org.python.core.util import StringUtil +from jarray import array + +# Java Standard Edition +from java.io import ByteArrayInputStream +from java.lang import String, StringBuilder +from org.xml.sax import InputSource +from org.xml.sax import SAXNotRecognizedException, SAXParseException +from org.xml.sax.helpers import XMLReaderFactory +from org.xml.sax.ext import DefaultHandler2 + +# Xerces +try: + # Name mangled by jarjar? + import org.python.apache.xerces.parsers.SAXParser + _xerces_parser = "org.python.apache.xerces.parsers.SAXParser" +except ImportError: + _xerces_parser = "org.apache.xerces.parsers.SAXParser" + + +def ParserCreate(encoding=None, namespace_separator=None): + return XMLParser(encoding, namespace_separator) + + +class XMLParser(object): + + def __init__(self, encoding, namespace_separator): + self.encoding = encoding + self.CurrentLineNumber = 1 + self.CurrentColumnNumber = 0 + self._NextLineNumber = 1 + self._NextColumnNumber = 0 + self.ErrorLineNumber = -1 + self.ErrorColumnNumber = -1 + self.ErrorCode = None + + if namespace_separator is None: + self.namespace_separator = namespace_separator + elif isinstance(namespace_separator, basestring): + self.namespace_separator = str(namespace_separator) + if len(self.namespace_separator) > 1: + error = ("namespace_separator must be at most one character, " + "omitted, or None") + raise ValueError(error) + else: + error = ("ParserCreate() argument 2 must be string or None, " + "not %s" % type(namespace_separator).__name__) + raise TypeError(error) + + self._reader = XMLReaderFactory.createXMLReader(_xerces_parser) + + if self.namespace_separator is None: + try: + feature = "http://xml.org/sax/features/namespaces" + self._reader.setFeature(feature, False) + except SAXNotRecognizedException: + error = ("namespace support cannot be disabled; " + "set namespace_separator to a string of length 1.") + raise ValueError(error) + + self._base = None + self._buffer_text = True + self._returns_unicode = True + + self._data = StringBuilder() + + self._handler = XMLEventHandler(self) + self._reader.setContentHandler(self._handler) + self._reader.setErrorHandler(self._handler) + self._reader.setDTDHandler(self._handler) + self._reader.setEntityResolver(self._handler) + + sax_properties = ("lexical-handler", "declaration-handler") + for name in sax_properties: + try: + name = "http://xml.org/sax/properties/" + name + self._reader.setProperty(name, self._handler) + except SAXNotRecognizedException: + error = "can't set property %r" % name + raise NotImplementedError(error) + + apache_features = (("nonvalidating/load-external-dtd", False),) + for name, value in apache_features: + try: + name = "http://apache.org/xml/features/" + name + self._reader.setFeature(name, value) + except SAXNotRecognizedException: + error = "can't set feature %r" % name + raise NotImplementedError(error) + + # experimental + #f = "http://xml.org/sax/features/external-general-entities" + f = "http://xml.org/sax/features/external-parameter-entities" + #self._reader.setFeature(f, False) + + # check + f = "http://xml.org/sax/features/use-entity-resolver2" + assert self._reader.getFeature(f) + + def GetBase(self): + return self._base + + def SetBase(self, base): + self._base = base + + def _error(self, value=None): + raise AttributeError("'XMLParser' has no such attribute") + + def _get_buffer_text(self): + return self._buffer_text + + def _set_buffer_text(self, value): + self._buffer_text = bool(value) + + def _get_returns_unicode(self): + return bool(self._returns_unicode) + + def _set_returns_unicode(self, value): + self._returns_unicode = value + + # 'ordered' and 'specified' attributes are not supported + ordered_attributes = property(_error, _error) + specified_attributes = property(_error, _error) + # any setting is allowed, but it won't make a difference + buffer_text = property(_get_buffer_text, _set_buffer_text) + # non-significant read-only values + buffer_used = property(lambda self: None) + buffer_size = property(lambda self: None) + # 'returns_unicode' attribute is properly supported + returns_unicode = property(_get_returns_unicode, _set_returns_unicode) + + def _expat_error(self, sax_error): + sax_message = sax_error.getMessage() + pattern = 'The entity ".*" was referenced, but not declared\.' + if re.match(pattern, sax_message): + expat_message = "undefined entity: line %s, column %s" % \ + (self.ErrorLineNumber, self.ErrorColumnNumber) + else: + expat_message = sax_message + error = ExpatError(expat_message) + error.lineno = self.ErrorLineNumber + error.offset = self.ErrorColumnNumber + error.code = self.ErrorCode + return error + + def Parse(self, data, isfinal=False): + # The 'data' argument should be an encoded text: a str instance that + # represents an a... [truncated message content] |
From: <fwi...@us...> - 2009-01-09 04:32:45
|
Revision: 5898 http://jython.svn.sourceforge.net/jython/?rev=5898&view=rev Author: fwierzbicki Date: 2009-01-09 04:32:35 +0000 (Fri, 09 Jan 2009) Log Message: ----------- list_for, list_if, list_iter no longer needed. Modified Paths: -------------- branches/jy3k/grammar/Python.g Modified: branches/jy3k/grammar/Python.g =================================================================== --- branches/jy3k/grammar/Python.g 2009-01-09 04:24:28 UTC (rev 5897) +++ branches/jy3k/grammar/Python.g 2009-01-09 04:32:35 UTC (rev 5898) @@ -1249,7 +1249,7 @@ -> ^(BYTES<Bytes>[actions.extractStringToken($B), actions.extractBytes($B, encoding)]) ; -//listmaker: test ( list_for | (',' test)* [','] ) +//listmaker: test ( comp_for | (',' test)* [','] ) listmaker[Token lbrack] @init { expr etype = null; @@ -1259,7 +1259,7 @@ $listmaker.tree = etype; } : t+=test[$expr::ctype] - (list_for[gens] + (comp_for[gens] { Collections.reverse(gens); List<comprehension> c = gens; @@ -1538,32 +1538,6 @@ ) ; -//list_iter: list_for | list_if -list_iter [List gens, List ifs] - : list_for[gens] - | list_if[gens, ifs] - ; - -//list_for: 'for' exprlist 'in' testlist_safe [list_iter] -list_for [List gens] -@init { - List ifs = new ArrayList(); -} - : FOR exprlist[expr_contextType.Store] IN testlist[expr_contextType.Load] (list_iter[gens, ifs])? - { - Collections.reverse(ifs); - gens.add(new comprehension($FOR, $exprlist.etype, actions.castExpr($testlist.tree), ifs)); - } - ; - -//list_if: 'if' test [list_iter] -list_if[List gens, List ifs] - : IF test[expr_contextType.Load] (list_iter[gens, ifs])? - { - ifs.add(actions.castExpr($test.tree)); - } - ; - //comp_iter: comp_for | comp_if comp_iter [List gens, List ifs] : comp_for[gens] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-01-09 04:24:31
|
Revision: 5897 http://jython.svn.sourceforge.net/jython/?rev=5897&view=rev Author: fwierzbicki Date: 2009-01-09 04:24:28 +0000 (Fri, 09 Jan 2009) Log Message: ----------- dict comprehensions Modified Paths: -------------- branches/jy3k/grammar/Python.g Modified: branches/jy3k/grammar/Python.g =================================================================== --- branches/jy3k/grammar/Python.g 2009-01-09 04:15:14 UTC (rev 5896) +++ branches/jy3k/grammar/Python.g 2009-01-09 04:24:28 UTC (rev 5897) @@ -104,6 +104,7 @@ import org.python.antlr.ast.Continue; import org.python.antlr.ast.Delete; import org.python.antlr.ast.Dict; +import org.python.antlr.ast.DictComp; import org.python.antlr.ast.Ellipsis; import org.python.antlr.ast.ErrorMod; import org.python.antlr.ast.ExceptHandler; @@ -1422,11 +1423,19 @@ } : (test[null] COLON) => k+=test[expr_contextType.Load] COLON v+=test[expr_contextType.Load] - (options {k=2;}:COMMA k+=test[expr_contextType.Load] COLON v+=test[expr_contextType.Load])* - (COMMA)? - { - etype = new Dict($lcurly, actions.castExprs($k), actions.castExprs($v)); - } + (comp_for[gens] + { + Collections.reverse(gens); + List<comprehension> c = gens; + etype = new DictComp($dictorsetmaker.start, actions.castExpr($k.get(0)), + actions.castExpr($v.get(0)),c); + } + | (options {k=2;}:COMMA k+=test[expr_contextType.Load] COLON v+=test[expr_contextType.Load])* + (COMMA)? + { + etype = new Dict($lcurly, actions.castExprs($k), actions.castExprs($v)); + } + ) | t+=test[$expr::ctype] (comp_for[gens] { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |