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: <pj...@us...> - 2009-05-04 06:34:59
|
Revision: 6292 http://jython.svn.sourceforge.net/jython/?rev=6292&view=rev Author: pjenvey Date: 2009-05-04 06:34:46 +0000 (Mon, 04 May 2009) Log Message: ----------- we can safely shortcut _cmp on identity match Modified Paths: -------------- trunk/jython/src/org/python/core/PyObject.java Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2009-05-04 06:07:19 UTC (rev 6291) +++ trunk/jython/src/org/python/core/PyObject.java 2009-05-04 06:34:46 UTC (rev 6292) @@ -1252,6 +1252,10 @@ * @return -1 if this < 0; 0 if this == o; +1 if this > o **/ public final int _cmp(PyObject o) { + if (this == o) { + return 0; + } + PyObject token = null; ThreadState ts = Py.getThreadState(); try { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-04 06:07:20
|
Revision: 6291 http://jython.svn.sourceforge.net/jython/?rev=6291&view=rev Author: pjenvey Date: 2009-05-04 06:07:19 +0000 (Mon, 04 May 2009) Log Message: ----------- o sequence cmp and generic __contains__ should compare identity for equality -- so change them to use equals (analogous to CPython's PyObject_RichCompareBool) instead of plain _eq (analogous to its PyObject_RichCompare) o fix list/tuple equals on their subclasses Modified Paths: -------------- trunk/jython/src/org/python/core/PyList.java trunk/jython/src/org/python/core/PyObject.java trunk/jython/src/org/python/core/PySequence.java trunk/jython/src/org/python/core/PyTuple.java trunk/jython/src/org/python/modules/_collections/PyDeque.java Added Paths: ----------- trunk/jython/Lib/test/test_seq_jy.py Added: trunk/jython/Lib/test/test_seq_jy.py =================================================================== --- trunk/jython/Lib/test/test_seq_jy.py (rev 0) +++ trunk/jython/Lib/test/test_seq_jy.py 2009-05-04 06:07:19 UTC (rev 6291) @@ -0,0 +1,60 @@ +"""Additional seq_tests + +Made for Jython. +""" +import unittest +from collections import deque +from test import test_support + +class SeqTestCase(unittest.TestCase): + + types2test = list, tuple, deque + + def test_seq_item_equality(self): + eq_called = [] + class Foo(object): + def __eq__(self, other): + eq_called.append(other) + return False + for type2test in self.types2test: + foo = Foo() + seq1 = type2test([foo]) + self.assertEqual(seq1, seq1) + self.assertEqual(cmp(seq1, seq1), 0) + seq2 = type2test([foo]) + self.assertEqual(seq1, seq2) + self.assertEqual(cmp(seq1, seq2), 0) + self.assertTrue(foo in seq1) + self.assertFalse(eq_called) + + def test_seq_subclass_equality(self): + # Various combinations of PyObject._eq, overriden Object.equals, + # and cmp implementations + for type2test in self.types2test: + class Foo(type2test): + def __eq__(self, other): + return False + l = type2test(['bar', 'baz']) + foo = Foo(l) + self.assertNotEqual(l, foo) + self.assertEqual(cmp(l, foo), 1) + self.assertEqual(cmp(foo, foo), 0) + + seqs1 = type2test([l, foo]) + seqs2 = type2test([l, foo]) + self.assertEqual(seqs1, seqs1) + self.assertEqual(seqs1, seqs2) + self.assertEqual(cmp(seqs1, seqs2), 0) + self.assertTrue(foo in seqs1) + if hasattr(seqs1, 'count'): + self.assertTrue(seqs1.count(foo), 1) + if hasattr(seqs1, 'index'): + self.assertEqual(seqs1.index(foo), 1) + + +def test_main(): + test_support.run_unittest(SeqTestCase) + + +if __name__ == "__main__": + test_main() Modified: trunk/jython/src/org/python/core/PyList.java =================================================================== --- trunk/jython/src/org/python/core/PyList.java 2009-05-03 21:39:08 UTC (rev 6290) +++ trunk/jython/src/org/python/core/PyList.java 2009-05-04 06:07:19 UTC (rev 6291) @@ -946,13 +946,16 @@ } @Override - public synchronized boolean equals(Object o) { - if (o instanceof PyList) { - return (((PyList) o).list.equals(list)); - } else if (o instanceof List && !(o instanceof PyTuple)) { - List oList = (List) o; - return oList.equals(list); + public synchronized boolean equals(Object other) { + if (this == other) { + return true; } + if (other instanceof PyList) { + return _eq((PyList)other).__nonzero__(); + } else if (other instanceof List && !(other instanceof PyTuple)) { + List otherList = (List)other; + return list.equals(otherList); + } return false; } Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2009-05-03 21:39:08 UTC (rev 6290) +++ trunk/jython/src/org/python/core/PyObject.java 2009-05-04 06:07:19 UTC (rev 6291) @@ -1676,7 +1676,7 @@ final boolean object___contains__(PyObject o) { for (PyObject item : asIterable()) { - if (o._eq(item).__nonzero__()) { + if (o.equals(item)) { return true; } } Modified: trunk/jython/src/org/python/core/PySequence.java =================================================================== --- trunk/jython/src/org/python/core/PySequence.java 2009-05-03 21:39:08 UTC (rev 6290) +++ trunk/jython/src/org/python/core/PySequence.java 2009-05-04 06:07:19 UTC (rev 6291) @@ -219,7 +219,7 @@ ol2 = o2.__len__(); } for (int i = 0; i < ol1 && i < ol2; i++) { - if (!o1.__getitem__(i)._eq(o2.__getitem__(i)).__nonzero__()) { + if (!o1.__getitem__(i).equals(o2.__getitem__(i))) { return i; } } Modified: trunk/jython/src/org/python/core/PyTuple.java =================================================================== --- trunk/jython/src/org/python/core/PyTuple.java 2009-05-03 21:39:08 UTC (rev 6290) +++ trunk/jython/src/org/python/core/PyTuple.java 2009-05-04 06:07:19 UTC (rev 6291) @@ -470,12 +470,15 @@ } @Override - public boolean equals(Object o) { - if (o instanceof PyTuple) { - return Arrays.equals(array, ((PyTuple) o).array); - } else if (o instanceof List && !(o instanceof PyList)) { - return o.equals(this); + public boolean equals(Object other) { + if (this == other) { + return true; } + if (other instanceof PyTuple) { + return _eq((PyTuple)other).__nonzero__(); + } else if (other instanceof List && !(other instanceof PyList)) { + return other.equals(this); + } return false; } Modified: trunk/jython/src/org/python/modules/_collections/PyDeque.java =================================================================== --- trunk/jython/src/org/python/modules/_collections/PyDeque.java 2009-05-03 21:39:08 UTC (rev 6290) +++ trunk/jython/src/org/python/modules/_collections/PyDeque.java 2009-05-04 06:07:19 UTC (rev 6291) @@ -443,7 +443,7 @@ ol2 = o2.__len__(); } for (int i = 0 ; i < ol1 && i < ol2; i++) { - if (!o1.__getitem__(i)._eq(o2.__getitem__(i)).__nonzero__()) { + if (!o1.__getitem__(i).equals(o2.__getitem__(i))) { return i; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-03 21:39:17
|
Revision: 6290 http://jython.svn.sourceforge.net/jython/?rev=6290&view=rev Author: pjenvey Date: 2009-05-03 21:39:08 +0000 (Sun, 03 May 2009) Log Message: ----------- make runnable on CPython, cleanup Modified Paths: -------------- trunk/jython/Lib/test/test_list_jy.py Modified: trunk/jython/Lib/test/test_list_jy.py =================================================================== --- trunk/jython/Lib/test/test_list_jy.py 2009-05-03 20:56:51 UTC (rev 6289) +++ trunk/jython/Lib/test/test_list_jy.py 2009-05-03 21:39:08 UTC (rev 6290) @@ -1,5 +1,8 @@ import unittest -import test.test_support +from test import test_support +if test_support.is_jython: + from java.util import ArrayList + from java.lang import String class ListTestCase(unittest.TestCase): @@ -21,21 +24,21 @@ self.assert_(bar2 > bar1) self.assert_(bar2 >= bar1) - #From http://bugs.jython.org/issue600790 def test_setget_override(self): - from java.util import ArrayList - from java.lang import String + if not test_support.is_jython: + return - class GoofyListMapThing (ArrayList): + # http://bugs.jython.org/issue600790 + class GoofyListMapThing(ArrayList): def __init__(self): self.silly = "Nothing" - + def __setitem__(self, key, element): self.silly = "spam" - + def __getitem__(self, key): self.silly = "eggs" - + glmt = GoofyListMapThing() glmt['my-key'] = String('el1') self.assertEquals(glmt.silly, "spam") @@ -44,9 +47,9 @@ def test_tuple_equality(self): self.assertEqual([(1,), [1]].count([1]), 1) # http://bugs.jython.org/issue1317 - + def test_main(): - test.test_support.run_unittest(ListTestCase) + test_support.run_unittest(ListTestCase) if __name__ == "__main__": This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-03 20:56:57
|
Revision: 6289 http://jython.svn.sourceforge.net/jython/?rev=6289&view=rev Author: pjenvey Date: 2009-05-03 20:56:51 +0000 (Sun, 03 May 2009) Log Message: ----------- refactor Modified Paths: -------------- trunk/jython/src/org/python/core/PySequence.java Modified: trunk/jython/src/org/python/core/PySequence.java =================================================================== --- trunk/jython/src/org/python/core/PySequence.java 2009-05-03 07:37:09 UTC (rev 6288) +++ trunk/jython/src/org/python/core/PySequence.java 2009-05-03 20:56:51 UTC (rev 6289) @@ -97,7 +97,7 @@ } final PyObject seq___eq__(PyObject o) { - if (getType() != o.getType() && !getType().isSubType(o.getType())) { + if (!isSubType(o)) { return null; } int tl = __len__(); @@ -115,7 +115,7 @@ } final PyObject seq___ne__(PyObject o) { - if (getType() != o.getType() && !getType().isSubType(o.getType())) { + if (!isSubType(o)) { return null; } int tl = __len__(); @@ -133,7 +133,7 @@ } final PyObject seq___lt__(PyObject o) { - if (getType() != o.getType() && !getType().isSubType(o.getType())) { + if (!isSubType(o)) { return null; } int i = cmp(this, -1, o, -1); @@ -149,7 +149,7 @@ } final PyObject seq___le__(PyObject o) { - if (getType() != o.getType() && !getType().isSubType(o.getType())) { + if (!isSubType(o)) { return null; } int i = cmp(this, -1, o, -1); @@ -165,7 +165,7 @@ } final PyObject seq___gt__(PyObject o) { - if (getType() != o.getType() && !getType().isSubType(o.getType())) { + if (!isSubType(o)) { return null; } int i = cmp(this, -1, o, -1); @@ -181,7 +181,7 @@ } final PyObject seq___ge__(PyObject o) { - if (getType() != o.getType() && !getType().isSubType(o.getType())) { + if (!isSubType(o)) { return null; } int i = cmp(this, -1, o, -1); @@ -192,6 +192,18 @@ } /** + * isSubType tailored for PySequence binops. + * + * @param other PyObject + * @return true if subclass of other + */ + protected boolean isSubType(PyObject other) { + PyType type = getType(); + PyType otherType = other.getType(); + return type == otherType || type.isSubType(otherType); + } + + /** * Compare the specified object/length pairs. * * @return value >= 0 is the index where the sequences differs. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-03 07:37:22
|
Revision: 6288 http://jython.svn.sourceforge.net/jython/?rev=6288&view=rev Author: pjenvey Date: 2009-05-03 07:37:09 +0000 (Sun, 03 May 2009) Log Message: ----------- cleanup/coding standards Modified Paths: -------------- trunk/jython/src/org/python/core/PyBaseString.java trunk/jython/src/org/python/core/PySequence.java trunk/jython/src/org/python/core/PySequenceList.java trunk/jython/src/org/python/core/PyXRange.java trunk/jython/src/org/python/core/io/FileIO.java trunk/jython/src/org/python/core/io/StreamIO.java Modified: trunk/jython/src/org/python/core/PyBaseString.java =================================================================== --- trunk/jython/src/org/python/core/PyBaseString.java 2009-05-03 06:09:20 UTC (rev 6287) +++ trunk/jython/src/org/python/core/PyBaseString.java 2009-05-03 07:37:09 UTC (rev 6288) @@ -10,10 +10,6 @@ public static final PyType TYPE = PyType.fromClass(PyBaseString.class); - public PyBaseString() { - super(); - } - protected PyBaseString(PyType type) { super(type); } Modified: trunk/jython/src/org/python/core/PySequence.java =================================================================== --- trunk/jython/src/org/python/core/PySequence.java 2009-05-03 06:09:20 UTC (rev 6287) +++ trunk/jython/src/org/python/core/PySequence.java 2009-05-03 07:37:09 UTC (rev 6288) @@ -2,8 +2,8 @@ package org.python.core; /** - * The abstract superclass of PyObjects that implements a Sequence. Minimize the work in creating - * such objects. + * The abstract superclass of PyObjects that implements a Sequence. Minimize the work in + * creating such objects. * * Method names are designed to make it possible for subclasses of PySequence to implement * java.util.List. @@ -14,50 +14,41 @@ */ public abstract class PySequence extends PyObject { - public PySequence() {} - protected PySequence(PyType type) { super(type); } // These methods must be defined for any sequence /** - * @param index - * index of element to return. + * @param index index of element to return. * @return the element at the given position in the list. */ - abstract protected PyObject pyget(int index); + protected abstract PyObject pyget(int index); /** * Returns a range of elements from the sequence. * - * @param start - * the position of the first element. - * @param stop - * one more than the position of the last element. - * @param step - * the step size. + * @param start the position of the first element. + * @param stop one more than the position of the last element. + * @param step the step size. * @return a sequence corresponding the the given range of elements. */ - abstract protected PyObject getslice(int start, int stop, int step); + protected abstract PyObject getslice(int start, int stop, int step); /** * Repeats the given sequence. * - * @param count - * the number of times to repeat the sequence. + * @param count the number of times to repeat the sequence. * @return this sequence repeated count times. */ - abstract protected PyObject repeat(int count); + protected abstract PyObject repeat(int count); // These methods only apply to mutable sequences /** * Sets the given element of the sequence. * - * @param index - * index of the element to set. - * @param value - * the value to set this element to. + * @param index index of the element to set. + * @param value the value to set this element to. */ protected void pyset(int index, PyObject value) { throw Py.TypeError("can't assign to immutable object"); @@ -71,7 +62,7 @@ getType().fastGetName())); } - protected void del(int i) throws PyException { + protected void del(int i) { throw Py.TypeError(String.format("'%s' object does not support item deletion", getType().fastGetName())); } @@ -82,6 +73,7 @@ } + @Override public boolean __nonzero__() { return seq___nonzero__(); } @@ -90,6 +82,7 @@ return __len__() != 0; } + @Override public PyObject __iter__() { return seq___iter__(); } @@ -98,166 +91,182 @@ return new PySequenceIter(this); } + @Override public PyObject __eq__(PyObject o) { return seq___eq__(o); } final PyObject seq___eq__(PyObject o) { - if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { + if (getType() != o.getType() && !getType().isSubType(o.getType())) { return null; } int tl = __len__(); int ol = o.__len__(); - if(tl != ol) { + if (tl != ol) { return Py.False; } int i = cmp(this, tl, o, ol); - return (i < 0) ? Py.True : Py.False; + return i < 0 ? Py.True : Py.False; } + @Override public PyObject __ne__(PyObject o) { return seq___ne__(o); } final PyObject seq___ne__(PyObject o) { - if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { + if (getType() != o.getType() && !getType().isSubType(o.getType())) { return null; } int tl = __len__(); int ol = o.__len__(); - if(tl != ol) { + if (tl != ol) { return Py.True; } int i = cmp(this, tl, o, ol); - return (i < 0) ? Py.False : Py.True; + return i < 0 ? Py.False : Py.True; } + @Override public PyObject __lt__(PyObject o) { return seq___lt__(o); } final PyObject seq___lt__(PyObject o) { - if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { + if (getType() != o.getType() && !getType().isSubType(o.getType())) { return null; } int i = cmp(this, -1, o, -1); - if(i < 0) { - return (i == -1) ? Py.True : Py.False; + if (i < 0) { + return i == -1 ? Py.True : Py.False; } return __finditem__(i)._lt(o.__finditem__(i)); } + @Override public PyObject __le__(PyObject o) { return seq___le__(o); } final PyObject seq___le__(PyObject o) { - if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { + if (getType() != o.getType() && !getType().isSubType(o.getType())) { return null; } int i = cmp(this, -1, o, -1); - if(i < 0) { - return (i == -1 || i == -2) ? Py.True : Py.False; + if (i < 0) { + return i == -1 || i == -2 ? Py.True : Py.False; } return __finditem__(i)._le(o.__finditem__(i)); } + @Override public PyObject __gt__(PyObject o) { return seq___gt__(o); } final PyObject seq___gt__(PyObject o) { - if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { + if (getType() != o.getType() && !getType().isSubType(o.getType())) { return null; } int i = cmp(this, -1, o, -1); - if(i < 0) - return (i == -3) ? Py.True : Py.False; + if (i < 0) { + return i == -3 ? Py.True : Py.False; + } return __finditem__(i)._gt(o.__finditem__(i)); } + @Override public PyObject __ge__(PyObject o) { return seq___ge__(o); } final PyObject seq___ge__(PyObject o) { - if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { + if (getType() != o.getType() && !getType().isSubType(o.getType())) { return null; } int i = cmp(this, -1, o, -1); - if(i < 0) { - return (i == -3 || i == -2) ? Py.True : Py.False; + if (i < 0) { + return i == -3 || i == -2 ? Py.True : Py.False; } return __finditem__(i)._ge(o.__finditem__(i)); } - // Return value >= 0 is the index where the sequences differs. - // -1: reached the end of o1 without a difference - // -2: reached the end of both seqeunces without a difference - // -3: reached the end of o2 without a difference + /** + * Compare the specified object/length pairs. + * + * @return value >= 0 is the index where the sequences differs. + * -1: reached the end of o1 without a difference + * -2: reached the end of both seqeunces without a difference + * -3: reached the end of o2 without a difference + */ protected static int cmp(PyObject o1, int ol1, PyObject o2, int ol2) { - if(ol1 < 0) { + if (ol1 < 0) { ol1 = o1.__len__(); } - if(ol2 < 0) { + if (ol2 < 0) { ol2 = o2.__len__(); } - for(int i = 0; i < ol1 && i < ol2; i++) { - if(!o1.__getitem__(i)._eq(o2.__getitem__(i)).__nonzero__()) { + for (int i = 0; i < ol1 && i < ol2; i++) { + if (!o1.__getitem__(i)._eq(o2.__getitem__(i)).__nonzero__()) { return i; } } - if(ol1 == ol2) { + if (ol1 == ol2) { return -2; } - return (ol1 < ol2) ? -1 : -3; + return ol1 < ol2 ? -1 : -3; } - // Return a copy of a sequence where the __len__() method is - // telling the truth. + /** + * Return a copy of a sequence where the __len__() method is telling the truth. + */ protected static PySequence fastSequence(PyObject seq, String msg) { if (seq instanceof PySequence) { return (PySequence)seq; } PyList list = new PyList(); PyObject iter = Py.iter(seq, msg); - for(PyObject item = null; (item = iter.__iternext__()) != null;) { + for (PyObject item = null; (item = iter.__iternext__()) != null;) { list.append(item); } return list; } - // make step a long in case adding the start, stop and step together overflows an int + /** + * Make step a long in case adding the start, stop and step together overflows an int. + */ protected static final int sliceLength(int start, int stop, long step) { int ret; - if(step > 0) { + if (step > 0) { ret = (int)((stop - start + step - 1) / step); } else { ret = (int)((stop - start + step + 1) / step); } - if(ret < 0) { + if (ret < 0) { return 0; } return ret; } /** - * Adjusts <code>index</code> such that it's >= 0 and <= __len__. If <code>index</code> starts - * off negative, it's treated as an index from the end of the sequence going back to the start. + * Adjusts <code>index</code> such that it's >= 0 and <= __len__. If + * <code>index</code> starts off negative, it's treated as an index from the end of + * the sequence going back to the start. */ protected int boundToSequence(int index) { int length = __len__(); - if(index < 0) { + if (index < 0) { index += length; - if(index < 0) { + if (index < 0) { index = 0; } - } else if(index > length) { + } else if (index > length) { index = length; } return index; } + @Override public PyObject __finditem__(int index) { return seq___finditem__(index); } @@ -266,6 +275,7 @@ return delegator.checkIdxAndFindItem(index); } + @Override public PyObject __finditem__(PyObject index) { return seq___finditem__(index); } @@ -274,6 +284,7 @@ return delegator.checkIdxAndFindItem(index); } + @Override public PyObject __getitem__(PyObject index) { return seq___getitem__(index); } @@ -282,14 +293,17 @@ return delegator.checkIdxAndGetItem(index); } + @Override public boolean isMappingType() throws PyIgnoreMethodTag { return false; } + @Override public boolean isNumberType() throws PyIgnoreMethodTag { return false; } + @Override public PyObject __getslice__(PyObject start, PyObject stop, PyObject step) { return seq___getslice__(start, stop, step); } @@ -298,17 +312,12 @@ return delegator.getSlice(new PySlice(start, stop, step)); } - public void __setslice__(PyObject start, - PyObject stop, - PyObject step, - PyObject value) { + @Override + public void __setslice__(PyObject start, PyObject stop, PyObject step, PyObject value) { seq___setslice__(start, stop, step, value); } - final void seq___setslice__(PyObject start, - PyObject stop, - PyObject step, - PyObject value) { + final void seq___setslice__(PyObject start, PyObject stop, PyObject step, PyObject value) { if (value == null) { value = step; step = null; @@ -316,6 +325,7 @@ delegator.checkIdxAndSetSlice(new PySlice(start, stop, step), value); } + @Override public void __delslice__(PyObject start, PyObject stop, PyObject step) { seq___delslice__(start, stop, step); } @@ -324,10 +334,12 @@ delegator.checkIdxAndDelItem(new PySlice(start, stop, step)); } + @Override public void __setitem__(int index, PyObject value) { delegator.checkIdxAndSetItem(index, value); } + @Override public void __setitem__(PyObject index, PyObject value) { seq___setitem__(index, value); } @@ -336,6 +348,7 @@ delegator.checkIdxAndSetItem(index, value); } + @Override public void __delitem__(PyObject index) { seq___delitem__(index); } @@ -344,18 +357,19 @@ delegator.checkIdxAndDelItem(index); } - public synchronized Object __tojava__(Class c) throws PyIgnoreMethodTag { - if(c.isArray()) { - Class component = c.getComponentType(); + @Override + public synchronized Object __tojava__(Class<?> c) throws PyIgnoreMethodTag { + if (c.isArray()) { + Class<?> component = c.getComponentType(); try { int n = __len__(); PyArray array = new PyArray(component, n); - for(int i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { PyObject o = pyget(i); array.set(i, o); } return array.getArray(); - } catch(Throwable t) { + } catch (Throwable t) { // ok } } @@ -367,8 +381,9 @@ * * {0} is the op name. {1} is the left operand type. {2} is the right operand type. */ + @Override protected String unsupportedopMessage(String op, PyObject o2) { - if(op.equals("*")) { + if (op.equals("*")) { return "can''t multiply sequence by non-int of type ''{2}''"; } return null; @@ -379,8 +394,9 @@ * * {0} is the op name. {1} is the left operand type. {2} is the right operand type. */ + @Override protected String runsupportedopMessage(String op, PyObject o2) { - if(op.equals("*")) { + if (op.equals("*")) { return "can''t multiply sequence by non-int of type ''{1}''"; } return null; Modified: trunk/jython/src/org/python/core/PySequenceList.java =================================================================== --- trunk/jython/src/org/python/core/PySequenceList.java 2009-05-03 06:09:20 UTC (rev 6287) +++ trunk/jython/src/org/python/core/PySequenceList.java 2009-05-03 07:37:09 UTC (rev 6288) @@ -7,9 +7,6 @@ public abstract class PySequenceList extends PySequence { - public PySequenceList() { - } - protected PySequenceList(PyType type) { super(type); } Modified: trunk/jython/src/org/python/core/PyXRange.java =================================================================== --- trunk/jython/src/org/python/core/PyXRange.java 2009-05-03 06:09:20 UTC (rev 6287) +++ trunk/jython/src/org/python/core/PyXRange.java 2009-05-03 07:37:09 UTC (rev 6288) @@ -28,6 +28,8 @@ } public PyXRange(int ilow, int ihigh, int istep) { + super(TYPE); + if (istep == 0) { throw Py.ValueError("xrange() arg 3 must not be zero"); } Modified: trunk/jython/src/org/python/core/io/FileIO.java =================================================================== --- trunk/jython/src/org/python/core/io/FileIO.java 2009-05-03 06:09:20 UTC (rev 6287) +++ trunk/jython/src/org/python/core/io/FileIO.java 2009-05-03 07:37:09 UTC (rev 6288) @@ -13,7 +13,6 @@ import java.nio.channels.FileChannel; import com.kenai.constantine.platform.Errno; -import org.python.core.imp; import org.python.core.Py; import org.python.core.util.FileUtil; import org.python.core.util.RelativeFile; @@ -168,8 +167,9 @@ // open("/dev/null", "w") works fine. Because we have // to simulate the "w" mode in Java, we suppress the // exception. - if (ioe.getMessage().equals("Invalid argument")) + if (ioe.getMessage().equals("Invalid argument")) { return; + } throw Py.IOError(ioe); } } Modified: trunk/jython/src/org/python/core/io/StreamIO.java =================================================================== --- trunk/jython/src/org/python/core/io/StreamIO.java 2009-05-03 06:09:20 UTC (rev 6287) +++ trunk/jython/src/org/python/core/io/StreamIO.java 2009-05-03 07:37:09 UTC (rev 6288) @@ -173,8 +173,9 @@ } catch (Exception e) { // XXX: masking other exceptions } finally { - if (inField != null && inField.isAccessible()) + if (inField != null && inField.isAccessible()) { inField.setAccessible(false); + } } } return null; @@ -197,8 +198,9 @@ } catch (Exception e) { // XXX: masking other exceptions } finally { - if (outField != null && outField.isAccessible()) + if (outField != null && outField.isAccessible()) { outField.setAccessible(false); + } } } return null; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-03 06:09:33
|
Revision: 6287 http://jython.svn.sourceforge.net/jython/?rev=6287&view=rev Author: pjenvey Date: 2009-05-03 06:09:20 +0000 (Sun, 03 May 2009) Log Message: ----------- match CPython's object.c::try_rich_compare: don't bother swapping the binop if the first op returned NotImplemented (null). _eq and friends already do this Modified Paths: -------------- trunk/jython/Lib/test/test_cmp_jy.py trunk/jython/src/org/python/core/PyObject.java Modified: trunk/jython/Lib/test/test_cmp_jy.py =================================================================== --- trunk/jython/Lib/test/test_cmp_jy.py 2009-05-02 07:55:28 UTC (rev 6286) +++ trunk/jython/Lib/test/test_cmp_jy.py 2009-05-03 06:09:20 UTC (rev 6287) @@ -56,6 +56,13 @@ # object.c:default_3way_compare, and gets 1 here. we don't care self.assert_(cmp(100, baz) in (-1, 1)) + def test_cmp_stops_short(self): + class Foo(object): + __eq__ = lambda self, other: False + class Bar(object): + __eq__ = lambda self, other: True + self.assertEqual(cmp(Foo(), Bar()), 1) + def test_main(): test_support.run_unittest( UnicodeDerivedCmp, Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2009-05-02 07:55:28 UTC (rev 6286) +++ trunk/jython/src/org/python/core/PyObject.java 2009-05-03 06:09:20 UTC (rev 6287) @@ -1260,27 +1260,30 @@ return 0; } - PyObject r; - r = __eq__(o); - if (r != null && r.__nonzero__()) + PyObject result; + result = __eq__(o); + if (result == null) { + result = o.__eq__(this); + } + if (result != null && result.__nonzero__()) { return 0; - r = o.__eq__(this); - if (r != null && r.__nonzero__()) - return 0; + } - r = __lt__(o); - if (r != null && r.__nonzero__()) + result = __lt__(o); + if (result == null) { + result = o.__gt__(this); + } + if (result != null && result.__nonzero__()) { return -1; - r = o.__gt__(this); - if (r != null && r.__nonzero__()) - return -1; + } - r = __gt__(o); - if (r != null && r.__nonzero__()) + result = __gt__(o); + if (result == null) { + result = o.__lt__(this); + } + if (result != null && result.__nonzero__()) { return 1; - r = o.__lt__(this); - if (r != null && r.__nonzero__()) - return 1; + } return _cmp_unsafe(o); } finally { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2009-05-02 07:55:29
|
Revision: 6286 http://jython.svn.sourceforge.net/jython/?rev=6286&view=rev Author: otmarhumbel Date: 2009-05-02 07:55:28 +0000 (Sat, 02 May 2009) Log Message: ----------- java tests need a populated /dist folder Modified Paths: -------------- trunk/jython/build.xml Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-05-02 06:13:13 UTC (rev 6285) +++ trunk/jython/build.xml 2009-05-02 07:55:28 UTC (rev 6286) @@ -809,7 +809,7 @@ <!-- Clean any old test output --> <delete dir="${junit.reports}"/> </target> - <target name="javatest" depends="compile,expose"> + <target name="javatest" depends="developer-build"> <mkdir dir="${junit.reports}"/> <junit fork="true" printsummary="true"> <formatter type="xml"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-05-02 06:13:20
|
Revision: 6285 http://jython.svn.sourceforge.net/jython/?rev=6285&view=rev Author: zyasoft Date: 2009-05-02 06:13:13 +0000 (Sat, 02 May 2009) Log Message: ----------- Some initial code, just to get it going. Added Paths: ----------- branches/jsr223/src/org/python/jsr223/ branches/jsr223/src/org/python/jsr223/PyScriptEngine.java branches/jsr223/src/org/python/jsr223/PyScriptEngineFactory.java Added: branches/jsr223/src/org/python/jsr223/PyScriptEngine.java =================================================================== --- branches/jsr223/src/org/python/jsr223/PyScriptEngine.java (rev 0) +++ branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-05-02 06:13:13 UTC (rev 6285) @@ -0,0 +1,110 @@ +package org.python.jsr223; + +import java.io.Reader; +import javax.script.AbstractScriptEngine; +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.Invocable; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptException; +import org.python.core.Py; +import org.python.core.PyException; +import org.python.core.PyObject; +import org.python.util.PythonInterpreter; + +public class PyScriptEngine extends AbstractScriptEngine implements Compilable, Invocable { + + private final PythonInterpreter interp; + private final ScriptEngineFactory factory; + + PyScriptEngine(ScriptEngineFactory factory) { + this.factory = factory; + interp = new PythonInterpreter(); + } + + public Object eval(String script, ScriptContext context) throws ScriptException { + throw new UnsupportedOperationException("Not supported yet."); + } + + // it would be nice if we supported a Reader interface in Py.compileFlags, instead of having + // to create a string here + public Object eval(Reader reader, ScriptContext context) throws ScriptException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Bindings createBindings() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ScriptEngineFactory getFactory() { + return factory; + } + + // i assume this should simply return a PyModule object or something + public CompiledScript compile(String script) throws ScriptException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public CompiledScript compile(Reader script) throws ScriptException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException { + try { + if (thiz instanceof PyObject) { + return ((PyObject) thiz).invoke(name, java2py(args)).__tojava__(Object.class); + } + throw new NoSuchMethodException(name); + } catch (PyException pye) { + if (Py.matchException(pye, Py.AttributeError)) { + throw new NoSuchMethodException(name); + } + throw new ScriptException(pye); + } + } + + public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException { + try { + return interp.get(name).__call__(java2py(args)).__tojava__(Object.class); + } catch (PyException pye) { + if (Py.matchException(pye, Py.AttributeError)) { + throw new NoSuchMethodException(name); + } + throw new ScriptException(pye); + } + } + + public <T> T getInterface(Class<T> clasz) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public <T> T getInterface(Object thiz, Class<T> clasz) { + throw new UnsupportedOperationException("Not supported yet."); + } + + private static PyObject[] java2py(Object[] args) { + PyObject wrapped[] = new PyObject[args.length]; + for (int i = 0; i < args.length; i++) { + wrapped[i] = Py.java2py(args[i]); + } + return wrapped; + } + + // wraps a PyCode object + private static class PyCompiledScript extends CompiledScript { + + @Override + public Object eval(ScriptContext arg0) throws ScriptException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public ScriptEngine getEngine() { + throw new UnsupportedOperationException("Not supported yet."); + } + + } +} Added: branches/jsr223/src/org/python/jsr223/PyScriptEngineFactory.java =================================================================== --- branches/jsr223/src/org/python/jsr223/PyScriptEngineFactory.java (rev 0) +++ branches/jsr223/src/org/python/jsr223/PyScriptEngineFactory.java 2009-05-02 06:13:13 UTC (rev 6285) @@ -0,0 +1,95 @@ +package org.python.jsr223; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import org.python.Version; +import org.python.core.Py; + +public class PyScriptEngineFactory implements ScriptEngineFactory { + + public String getEngineName() { + return "jython"; + } + + public String getEngineVersion() { + return String.format("%s.%s.%s", Version.PY_MAJOR_VERSION, Version.PY_MINOR_VERSION, Version.PY_MICRO_VERSION); + } + + public List<String> getExtensions() { + return Collections.unmodifiableList(Arrays.asList("py")); + } + + public String getLanguageName() { + return "python"; + } + + public String getLanguageVersion() { + return "2.5.0"; + } + + public Object getParameter(String key) { + if (key.equals(ScriptEngine.ENGINE)) { + return getEngineName(); + } else if (key.equals(ScriptEngine.ENGINE_VERSION)) { + return getEngineVersion(); + } else if (key.equals(ScriptEngine.NAME)) { + return getEngineName(); + } else if (key.equals(ScriptEngine.LANGUAGE)) { + return getLanguageName(); + } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) { + return getLanguageVersion(); + } else if (key.equals("THREADING")) { + return "MULTITHREADED"; + } else { + return null; + } + + } + + public String getMethodCallSyntax(String obj, String m, String... args) { + StringBuilder buffer = new StringBuilder(); + buffer.append(String.format("%s.%s(", obj, m)); + int i = args.length; + for (String arg : args) { + buffer.append(arg); + if (i-- > 0) { + buffer.append(", "); + } + } + buffer.append(")"); + return buffer.toString(); + } + + // presumably a unicode string + public String getOutputStatement(String toDisplay) { + StringBuilder buffer = new StringBuilder(toDisplay.length() + 8); + buffer.append("print "); + buffer.append(Py.newUnicode(toDisplay).__repr__()); + return buffer.toString(); + } + + public String getProgram(String... statements) { + StringBuilder buffer = new StringBuilder(); + for (String statement : statements) { + buffer.append(statement); + buffer.append("\n"); + } + return buffer.toString(); + } + + public ScriptEngine getScriptEngine() { + return new PyScriptEngine(this); + } + + public List<String> getMimeTypes() { + return Collections.EMPTY_LIST; + } + + public List<String> getNames() { + return Collections.unmodifiableList(Arrays.asList("python", "jython")); + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-05-01 03:08:16
|
Revision: 6284 http://jython.svn.sourceforge.net/jython/?rev=6284&view=rev Author: zyasoft Date: 2009-05-01 03:08:07 +0000 (Fri, 01 May 2009) Log Message: ----------- Creating branch for JSR223 dev Added Paths: ----------- branches/jsr223/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2009-05-01 00:33:23
|
Revision: 6283 http://jython.svn.sourceforge.net/jython/?rev=6283&view=rev Author: otmarhumbel Date: 2009-05-01 00:33:13 +0000 (Fri, 01 May 2009) Log Message: ----------- added missing tests for registry/property handling Added Paths: ----------- trunk/jython/tests/java/org/python/core/ trunk/jython/tests/java/org/python/core/PySystemState_registry_Test.java Added: trunk/jython/tests/java/org/python/core/PySystemState_registry_Test.java =================================================================== --- trunk/jython/tests/java/org/python/core/PySystemState_registry_Test.java (rev 0) +++ trunk/jython/tests/java/org/python/core/PySystemState_registry_Test.java 2009-05-01 00:33:13 UTC (rev 6283) @@ -0,0 +1,412 @@ +package org.python.core; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URL; +import java.util.Properties; + +import junit.framework.TestCase; + +/** + * Tests for property handling (pre, post and registry files) + */ +public class PySystemState_registry_Test extends TestCase { + + /** The name of the installed registry file */ + private static final String REGISTRY = "registry"; + + /** The name of the user registry file */ + private static final String USER_REGISTRY = ".jython"; + + /** name of the dist (root) dir */ + private static final String DIST = "dist"; + + /** property name */ + private final static String FIRST_PROP = "first.test.property"; + + /** property name */ + private final static String SECOND_PROP = "second.test.property"; + + /** property name */ + private final static String USER_HOME = "user.home"; + + /** property name */ + private static final String PYTHON_HOME = "python.home"; + + /** property value */ + private final static String ANY = "any"; + + /** property value */ + private final static String PRE = "pre"; + + /** property value */ + private final static String POST = "post"; + + /** property value */ + private final static String INSTALLED = "installed"; + + /** property value */ + private final static String USER = "user"; + + private String _originalUserHome; + + private File _root; + + private String _originalRegistryContent; + + private Properties _originalRegistry; + + private File _tmpDir; + + @Override + protected void setUp() throws Exception { + findRoot(); + storeOriginals(); + uninitialize(); + } + + @Override + protected void tearDown() throws Exception { + restoreOriginals(); + cleanup(); + } + + /** + * make sure post properties override pre properties + * + * @throws Exception + */ + public void testInitialize_PrePostProperties() throws Exception { + Properties preProps = createPreProperties(); + preProps.setProperty(FIRST_PROP, PRE); + preProps.setProperty(SECOND_PROP, PRE); + Properties postProps = createPostProperties(); + postProps.setProperty(SECOND_PROP, POST); + PySystemState.initialize(preProps, postProps); + Properties registry = PySystemState.registry; + String first = registry.getProperty(FIRST_PROP, ANY); + String second = registry.getProperty(SECOND_PROP, ANY); + assertEquals(PRE, first); + assertEquals(POST, second); + } + + /** + * make sure a property from the user registry overrides the same property from the installed + * registry + * + * @throws Exception + */ + public void testInitialize_Registry_User() throws Exception { + // prepare both registry files + String installedContent = FIRST_PROP.concat("=").concat(INSTALLED); + appendToInstalledRegistry(installedContent); + String userContent = FIRST_PROP.concat("=").concat(USER); + addUserRegistry(userContent); + // test with empty pre an post properties + Properties preProps = createPreProperties(); + Properties postProps = createPostProperties(); + PySystemState.initialize(preProps, postProps); + Properties registry = PySystemState.registry; + String first = registry.getProperty(FIRST_PROP, ANY); + assertEquals(USER, first); + } + + /** + * make sure a pre property overrides any registry properties with the same name + * + * @throws Exception + */ + public void testInitialize_Pre_Registries() throws Exception { + // prepare both registry files + String contentToAppend = FIRST_PROP.concat("=").concat(INSTALLED); + appendToInstalledRegistry(contentToAppend); + String userContent = FIRST_PROP.concat("=").concat(USER); + addUserRegistry(userContent); + // set same property on pre properties + Properties preProps = createPreProperties(); + preProps.setProperty(FIRST_PROP, PRE); + Properties postProps = createPostProperties(); + PySystemState.initialize(preProps, postProps); + Properties registry = PySystemState.registry; + String first = registry.getProperty(FIRST_PROP, ANY); + assertEquals(PRE, first); + } + + /** + * make sure a post property overrides any registry properties with the same name, and the pre + * property as well + * + * @throws Exception + */ + public void testInitialize_Post_Registries() throws Exception { + // prepare both registry files + String contentToAppend = FIRST_PROP.concat("=").concat(INSTALLED); + appendToInstalledRegistry(contentToAppend); + String userContent = FIRST_PROP.concat("=").concat(USER); + addUserRegistry(userContent); + // set same property on pre properties + Properties preProps = createPreProperties(); + preProps.setProperty(FIRST_PROP, PRE); + // set same property on post properties + Properties postProps = createPostProperties(); + postProps.setProperty(FIRST_PROP, POST); + PySystemState.initialize(preProps, postProps); + Properties registry = PySystemState.registry; + String first = registry.getProperty(FIRST_PROP, ANY); + assertEquals(POST, first); + } + + /** + * determine the installation root (the /dist directory) + */ + private void findRoot() { + Class<? extends PySystemState_registry_Test> thisClass = getClass(); + String classFileName = "/".concat(thisClass.getName().replace('.', '/')).concat(".class"); + URL url = thisClass.getResource(classFileName); + assertNotNull(url); + String path = url.getPath(); + assertTrue(path.endsWith(classFileName)); + String classesDirName = path.substring(0, path.length() - classFileName.length()); + File classesDir = new File(classesDirName); + assertTrue(classesDir.exists()); + assertTrue(classesDir.isDirectory()); + _root = new File(classesDir.getParentFile().getParentFile(), DIST); + assertTrue(_root.exists()); + assertTrue(_root.isDirectory()); + } + + /** + * force a new initialization + * <p> + * set private static field PySystemState.initialized to false <br> + * clear {@link PySystemState#registry} + * + * @throws Exception + */ + private void uninitialize() throws Exception { + Field field = PySystemState.class.getDeclaredField("initialized"); + field.setAccessible(true); + field.set(null, false); + PySystemState.registry = null; + } + + /** + * keep track of original values, to be able to restore them in tearDown() + * + * @throws Exception + */ + private void storeOriginals() throws Exception { + _originalRegistry = PySystemState.registry; + _originalUserHome = System.getProperty(USER_HOME); + File installedRegistry = new File(getRoot(), REGISTRY); + assertTrue(installedRegistry.exists()); + _originalRegistryContent = readAll(installedRegistry); + } + + /** + * restore the original values + * + * @throws Exception + */ + private void restoreOriginals() throws Exception { + PySystemState.registry = _originalRegistry; + String originalUserHome = getOriginalUserHome(); + if (originalUserHome != null) { + System.setProperty(USER_HOME, originalUserHome); + } + writeInstalledRegistry(getOriginalRegistryContent()); + } + + /** + * overwrite the registry file in the installation root + * + * @param content + * @throws IOException + */ + private void writeInstalledRegistry(String content) throws IOException { + if (content != null && content.length() > 0) { + File installedRegistry = new File(getRoot(), REGISTRY); + assertTrue(installedRegistry.exists()); + write(installedRegistry, content); + } + } + + /** + * append to the registry file in the installation root + * + * @param contentToAppend + * @throws IOException + */ + private void appendToInstalledRegistry(String contentToAppend) throws IOException { + if (contentToAppend != null && contentToAppend.length() > 0) { + String content = getOriginalRegistryContent().concat(contentToAppend); + writeInstalledRegistry(content); + } + } + + /** + * override user.home and add a user registry there + * + * @param content + * @throws Exception + */ + private void addUserRegistry(String content) throws Exception { + File tmpDir = createTempDir(); + System.setProperty(USER_HOME, tmpDir.getCanonicalPath()); + File userRegistry = new File(tmpDir, USER_REGISTRY); + write(userRegistry, content); + assertTrue(userRegistry.exists()); + assertTrue(userRegistry.isFile()); + } + + /** + * @return pre properties, based by System.properties + */ + private Properties createPreProperties() { + return new Properties(System.getProperties()); + } + + /** + * @return post properties, containing python home + * @throws Exception + */ + private Properties createPostProperties() throws Exception { + Properties postProps = new Properties(); + postProps.setProperty(PYTHON_HOME, getRoot().getCanonicalPath()); + return postProps; + } + + /** + * create a temp directory, which is removed in cleanup() + * <p> + * should only be called once per test method + * + * @return the temp directory + * @throws Exception + */ + private File createTempDir() throws Exception { + String name = getClass().getSimpleName(); + File tmpFile = File.createTempFile(name, ""); + assertTrue(tmpFile.exists()); + assertTrue(tmpFile.isFile()); + File parent = tmpFile.getParentFile(); + assertTrue(parent.exists()); + assertTrue(parent.isDirectory()); + assertTrue(tmpFile.delete()); + File tmpDir = new File(parent, name); + assertTrue(tmpDir.mkdir()); + assertTrue(tmpDir.exists()); + assertTrue(tmpDir.isDirectory()); + _tmpDir = tmpDir; + return tmpDir; + } + + /** + * delete created files + */ + private void cleanup() { + File tmpDir = getTmpDir(); + if (tmpDir != null && tmpDir.exists()) { + assertTrue(rmdir(tmpDir)); + } + _tmpDir = null; + } + + /** + * read the contents of a file into a String + * + * @param file + * The file has to exist + * @return The contents of the file as String + * @throws IOException + */ + private String readAll(File file) throws IOException { + FileReader fileReader = new FileReader(file); + try { + StringBuffer sb = new StringBuffer(); + char[] b = new char[8192]; + int n; + while ((n = fileReader.read(b)) > 0) { + sb.append(b, 0, n); + } + return sb.toString(); + } finally { + fileReader.close(); + } + } + + /** + * Write contents to a file. + * <p> + * An existing file would be overwritten. + * + * @param file + * @param content + * + * @throws IOException + */ + private void write(File file, String content) throws IOException { + FileWriter writer = new FileWriter(file); + writer.write(content); + writer.flush(); + writer.close(); + } + + /** + * completely remove a directory + * + * @param dir + * @return <code>true</code> if successful, <code>false</code> otherwise. + */ + private boolean rmdir(File dir) { + boolean success = true; + if (dir.exists()) { + File[] files = dir.listFiles(); + for (int i = 0; i < files.length; i++) { + File file = files[i]; + if (file.isFile()) { + success = carryOnResult(file.delete(), success); + } else { + if (file.isDirectory()) { + success = carryOnResult(rmdir(file), success); + } + } + } + success = carryOnResult(dir.delete(), success); + } + return success; + } + + /** + * @param newResult + * @param existingResult + * @return <code>false</code> if newResult or existingResult are false, <code>true</code> + * otherwise. + */ + private boolean carryOnResult(boolean newResult, boolean existingResult) { + if (existingResult) { + return newResult; + } else { + return existingResult; + } + } + + private File getRoot() { + return _root; + } + + private File getTmpDir() { + return _tmpDir; + } + + private String getOriginalUserHome() { + return _originalUserHome; + } + + private String getOriginalRegistryContent() { + return _originalRegistryContent; + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-04-30 07:01:46
|
Revision: 6282 http://jython.svn.sourceforge.net/jython/?rev=6282&view=rev Author: zyasoft Date: 2009-04-30 07:01:40 +0000 (Thu, 30 Apr 2009) Log Message: ----------- Removed obsolete references to PyComparator Modified Paths: -------------- trunk/jython/src/org/python/core/PyList.java Modified: trunk/jython/src/org/python/core/PyList.java =================================================================== --- trunk/jython/src/org/python/core/PyList.java 2009-04-30 06:33:26 UTC (rev 6281) +++ trunk/jython/src/org/python/core/PyList.java 2009-04-30 07:01:40 UTC (rev 6282) @@ -810,7 +810,7 @@ } if (o instanceof PyObjectComparator) { - return cmp.equals(((PyComparator) o).cmp); + return cmp.equals(((PyObjectComparator) o).cmp); } return false; } @@ -855,8 +855,8 @@ return true; } - if (o instanceof PyObjectComparator) { - return cmp.equals(((PyComparator) o).cmp); + if (o instanceof KVComparator) { + return cmp.equals(((KVComparator) o).cmp); } return false; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-04-30 06:33:28
|
Revision: 6281 http://jython.svn.sourceforge.net/jython/?rev=6281&view=rev Author: zyasoft Date: 2009-04-30 06:33:26 +0000 (Thu, 30 Apr 2009) Log Message: ----------- Removed vestigal MergeState, our apparently buggy implementation of timsort. We will get timsort back with JDK7 java.util.Collections#sort. Removed Paths: ------------- trunk/jython/src/org/python/core/MergeState.java Deleted: trunk/jython/src/org/python/core/MergeState.java =================================================================== --- trunk/jython/src/org/python/core/MergeState.java 2009-04-30 06:25:36 UTC (rev 6280) +++ trunk/jython/src/org/python/core/MergeState.java 2009-04-30 06:33:26 UTC (rev 6281) @@ -1,846 +0,0 @@ -// Copyright 2002 Finn Bock - -package org.python.core; - -/** - * The MergeState class is a java implementation of the sort created - * Tim Peters and added to CPython2.3. - * - * The algorithm is described in details in the file - * python/dist/src/Objects/listsort.txt in the CPython development CVS. - */ -class MergeState { - /** - * The maximum number of entries in a MergeState's pending-runs stack. - * This is enough to sort arrays of size up to about - * 32 * phi ** MAX_MERGE_PENDING - * where phi ~= 1.618. 85 is ridiculously large enough, good for an - * array with 2**64 elements. - */ - static final int MAX_MERGE_PENDING = 85; - - /** - * If a run wins MIN_GALLOP times in a row, we switch to galloping mode, - * and stay there until both runs win less often than MIN_GALLOP - * consecutive times. See listsort.txt for more info. - */ - static final int MIN_GALLOP = 8; - - /** - * Initial temp array size - */ - static final int MERGESTATE_TEMP_SIZE = 256; - - private KVPair[] a = new KVPair[MERGESTATE_TEMP_SIZE]; - - private int[] base = new int[MAX_MERGE_PENDING]; - private int[] len = new int[MAX_MERGE_PENDING]; - - private PyObject compare; - private PyObject key; - private boolean reverse; - private int size; - private int n; - private PyList gOriginalList; - private KVPair[] kvdata; - - MergeState(PyList list, PyObject compare, PyObject key, boolean reverse) { - if(compare != Py.None) { - this.compare = compare; - } - if(key != Py.None) { - this.key = key; - } - this.reverse = reverse; - this.n = 0; - this.size = list.size(); - // not exactly desirable, but works for the moment - this.kvdata = new KVPair[size]; - - //resetting the list to find if any update is done after sorting - this.gOriginalList = list; - this.gOriginalList.gListAllocatedStatus = -1; - } - - private class KVPair { - public PyObject key; - public PyObject value; - - public KVPair(PyObject key, PyObject value) { - this.key = key; - this.value = value; - } - } - - public void sort() { - PyObject origData[] = gOriginalList.getArray(); - PyObject[] data = new PyObject[size]; - //list data is copied to new array and is temporarily made empty, so that - //mutations performed by comparison or key functions can't affect - //the slice of memory we're sorting. - System.arraycopy(origData, 0, data, 0, size); - //list.clear(); - - //If keyfunction is given, object of type KVPair with key resulting from - //key(data[pos]) and value from data[pos] is created. Otherwise the key - //of KVPair object will take the value of data[pos] and the corresponding - //value will be null. Thus, we will do sorting on the keys of KVPair object - //array effectively without disturbing the incoming list object. - if (this.key != null) { - for (int i = 0; i < size; i++) { - this.kvdata[i] = new KVPair(key.__call__(data[i]), data[i]); - } - } else { - for (int i = 0; i < size; i++) { - this.kvdata[i] = new KVPair(data[i], null); - } - } - //make data null, we dont need this reference afterwards - data = null; - - //Reverse sort stability achieved by initially reversing the list, - //applying a stable forward sort, then reversing the final result. - if (reverse && size > 1) { - reverse_slice(0, size); - } - - int nremaining = this.size; - if (nremaining < 2) { - return; - } - - int lo = 0; - int hi = nremaining; - int minrun = merge_compute_minrun(nremaining); - - boolean[] descending = new boolean[1]; - do { - /* Identify next run. */ - int localN = count_run(lo, hi, descending); - if (descending[0]) - reverse_slice(lo, lo + localN); - /* If short, extend to min(minrun, nremaining). */ - if (localN < minrun) { - int force = nremaining < minrun ? nremaining : minrun; - binarysort(lo, lo + force, lo + localN); - localN = force; - } - /* Push run onto pending-runs stack, and maybe merge. */ - //ms.assert_(ms.n < ms.MAX_MERGE_PENDING); - this.base[this.n] = lo; - this.len[this.n] = localN; - ++this.n; - merge_collapse(); - /* Advance to find next run */ - lo += localN; - nremaining -= localN; - } while (nremaining != 0); - //assert_(lo == hi); - - merge_force_collapse(); - //assert_(ms.n == 1); - //assert_(ms.base[0] == 0); - //assert_(ms.len[0] == size); - - //The user mucked up with the list during the sort, - //and so, the value error is thrown - if (gOriginalList.gListAllocatedStatus >= 0) { - throw Py.ValueError("list modified during sort"); - } - - if (reverse && size > 1) { - reverse_slice(0, size); - } - - //Now copy the sorted values from KVPairs if key function is given, - //otherwise the keys from KVPairs. - if (this.key != null) { - for (int i = 0; i < size; i++) { - origData[i] = this.kvdata[i].value; - } - } else { - for (int i = 0; i < size; i++) { - origData[i] = this.kvdata[i].key; - } - } - } - - public void getmem(int need) { - if (need <= this.a.length) - return; - this.a = new KVPair[need]; - } - - int count_run(int lo, int hi, boolean[] descending) { - //assert_(lo < hi); - descending[0] = false; - ++lo; - if (lo == hi) - return 1; - int localN = 2; - if (iflt(this.kvdata[lo].key, this.kvdata[lo-1].key)) { - descending[0] = true; - for (lo = lo + 1; lo < hi; ++lo, ++localN) { - if (! iflt(this.kvdata[lo].key, this.kvdata[lo-1].key)) - break; - } - } else { - for (lo = lo + 1; lo < hi; ++lo, ++localN) { - if (iflt(this.kvdata[lo].key, this.kvdata[lo-1].key)) - break; - } - } - return localN; - } - - - void merge_lo(int pa, int na, int pb, int nb) { - //debug("merge_lo pa:" + pa + " na:" + na + " pb:" + pb + " nb:" + nb); - //dump_data("padata", pa, na); - //dump_data("pbdata", pb, nb); - - //assert_(na > 0 && nb > 0 && pa + na == pb); - getmem(na); - System.arraycopy(this.kvdata, pa, this.a, 0, na); - int dest = pa; - pa = 0; - - this.kvdata[dest++] = this.kvdata[pb++]; - --nb; - if (nb == 0) { - // Succeed; (falls through to Fail) - if (na != 0) - System.arraycopy(this.a, pa, this.kvdata, dest, na); - return; - } - if (na == 1) { - // CopyB; - System.arraycopy(this.kvdata, pb, this.kvdata, dest, nb); - this.kvdata[dest + nb] = this.a[pa]; - return; - } - - try { - for (;;) { - int acount = 0; /* # of time A won in a row */ - int bcount = 0; /* # of time B won in a row */ - - /* Do the straightforward thing until (if ever) one run - * appears to win consistently. - */ - for (;;) { - boolean k = iflt(this.kvdata[pb].key, this.a[pa].key); - if (k) { - this.kvdata[dest++] = this.kvdata[pb++]; - ++bcount; - acount = 0; - --nb; - if (nb == 0) - return; - if (bcount >= MIN_GALLOP) - break; - } else { - this.kvdata[dest++] = this.a[pa++]; - ++acount; - bcount = 0; - --na; - if (na == 1) { - // CopyB; - System.arraycopy(this.kvdata, pb, this.kvdata, dest, nb); - this.kvdata[dest + nb] = this.a[pa]; - na = 0; - return; - } - if (acount >= MIN_GALLOP) - break; - } - } - - /* One run is winning so consistently that galloping may - * be a huge win. So try that, and continue galloping until - * (if ever) neither run appears to be winning consistently - * anymore. - */ - do { - int k = gallop_right(this.kvdata[pb].key, this.a, pa, na, 0); - acount = k; - if (k != 0) { - System.arraycopy(this.a, pa, this.kvdata, dest, k); - dest += k; - pa += k; - na -= k; - if (na == 1) { - // CopyB - System.arraycopy(this.kvdata, pb, this.kvdata, dest, nb); - this.kvdata[dest + nb] = this.a[pa]; - na = 0; - return; - } - /* na==0 is impossible now if the comparison - * function is consistent, but we can't assume - * that it is. - */ - if (na == 0) - return; - } - - this.kvdata[dest++] = this.kvdata[pb++]; - --nb; - if (nb == 0) - return; - - k = gallop_left(this.a[pa].key, this.kvdata, pb, nb, 0); - bcount = k; - if (k != 0) { - System.arraycopy(this.kvdata, pb, this.kvdata, dest, k); - dest += k; - pb += k; - nb -= k; - if (nb == 0) - return; - } - this.kvdata[dest++] = this.a[pa++]; - --na; - if (na == 1) { - // CopyB; - System.arraycopy(this.kvdata, pb, this.kvdata, dest, nb); - this.kvdata[dest + nb] = this.a[pa]; - na = 0; - return; - } - } while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP); - } - } finally { - if (na != 0) - System.arraycopy(this.a, pa, this.kvdata, dest, na); - - //dump_data("result", origpa, cnt); - } - } - - - - void merge_hi(int pa, int na, int pb, int nb) { - //debug("merge_hi pa:" + pa + " na:" + na + " pb:" + pb + " nb:" + nb); - //dump_data("padata", pa, na); - //dump_data("pbdata", pb, nb); - - //assert_(na > 0 && nb > 0 && pa + na == pb); - getmem(nb); - int dest = pb + nb - 1; - int basea = pa; - System.arraycopy(this.kvdata, pb, this.a, 0, nb); - - pb = nb - 1; - pa += na - 1; - - this.kvdata[dest--] = this.kvdata[pa--]; - --na; - if (na == 0) { - // Succeed; (falls through to Fail) - if (nb != 0) - System.arraycopy(this.a, 0, this.kvdata, dest-(nb-1), nb); - return; - } - if (nb == 1) { - // CopyA; - dest -= na; - pa -= na; - System.arraycopy(this.kvdata, pa+1, this.kvdata, dest+1, na); - this.kvdata[dest] = this.a[pb]; - nb = 0; - return; - } - - try { - for (;;) { - int acount = 0; /* # of time A won in a row */ - int bcount = 0; /* # of time B won in a row */ - - /* Do the straightforward thing until (if ever) one run - * appears to win consistently. - */ - for (;;) { - boolean k = iflt(this.a[pb].key, this.kvdata[pa].key); - if (k) { - this.kvdata[dest--] = this.kvdata[pa--]; - ++acount; - bcount = 0; - --na; - if (na == 0) - return; - if (acount >= MIN_GALLOP) - break; - } else { - this.kvdata[dest--] = this.a[pb--]; - ++bcount; - acount = 0; - --nb; - if (nb == 1) { - // CopyA - dest -= na; - pa -= na; - System.arraycopy(this.kvdata, pa+1, this.kvdata, dest+1, na); - this.kvdata[dest] = this.a[pb]; - nb = 0; - return; - } - if (bcount >= MIN_GALLOP) - break; - } - } - - /* One run is winning so consistently that galloping may - * be a huge win. So try that, and continue galloping until - * (if ever) neither run appears to be winning consistently - * anymore. - */ - do { - int k = gallop_right(this.a[pb].key, this.kvdata, basea, na, na-1); - acount = k = na - k; - if (k != 0) { - dest -= k; - pa -= k; - System.arraycopy(this.kvdata, pa+1, this.kvdata, dest+1, k); - na -= k; - if (na == 0) - return; - } - - this.kvdata[dest--] = this.a[pb--]; - --nb; - if (nb == 1) { - // CopyA - dest -= na; - pa -= na; - System.arraycopy(this.kvdata, pa+1, this.kvdata, dest+1, na); - this.kvdata[dest] = this.a[pb]; - nb = 0; - return; - } - - k = gallop_left(this.kvdata[pa].key, this.a, 0, nb, nb-1); - bcount = k = nb - k; - if (k != 0) { - dest -= k; - pb -= k; - System.arraycopy(this.a, pb+1, this.kvdata, dest+1, k); - nb -= k; - if (nb == 1) { - // CopyA - dest -= na; - pa -= na; - System.arraycopy(this.kvdata, pa+1, this.kvdata, dest+1, na); - this.kvdata[dest] = this.a[pb]; - nb = 0; - return; - } - /* nb==0 is impossible now if the comparison - * function is consistent, but we can't assume - * that it is. - */ - if (nb == 0) - return; - } - this.kvdata[dest--] = this.kvdata[pa--]; - --na; - if (na == 0) - return; - } while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP); - } - } finally { - if (nb != 0) - System.arraycopy(this.a, 0, this.kvdata, dest-(nb-1), nb); - - //dump_data("result", origpa, cnt); - } - } - - - - /* - Locate the proper position of key in a sorted vector; if the vector contains - an element equal to key, return the position immediately to the left of - the leftmost equal element. [gallop_right() does the same except returns - the position to the right of the rightmost equal element (if any).] - - "a" is a sorted vector with n elements, starting at a[0]. n must be > 0. - - "hint" is an index at which to begin the search, 0 <= hint < n. The closer - hint is to the final result, the faster this runs. - - The return value is the int k in 0..n such that - - a[k-1] < key <= a[k] - - pretending that *(a-1) is minus infinity and a[n] is plus infinity. IOW, - key belongs at index k; or, IOW, the first k elements of a should precede - key, and the last n-k should follow key. - - Returns -1 on error. See listsort.txt for info on the method. - */ - - private int gallop_left(PyObject key, KVPair[] localData, int localA, int localN, - int hint) - { - //assert_(n > 0 && hint >= 0 && hint < n); - localA += hint; - int ofs = 1; - int lastofs = 0; - - if (iflt(localData[localA].key, key)) { - /* a[hint] < key -- gallop right, until - * a[hint + lastofs] < key <= a[hint + ofs] - */ - int maxofs = localN - hint; // data[a + n - 1] is highest - while (ofs < maxofs) { - if (iflt(localData[localA + ofs].key, key)) { - lastofs = ofs; - ofs = (ofs << 1) + 1; - if (ofs <= 0) // int overflow - ofs = maxofs; - } else { - // key < data[a + hint + ofs] - break; - } - } - if (ofs > maxofs) - ofs = maxofs; - // Translate back to offsets relative to a. - lastofs += hint; - ofs += hint; - } else { - /* key <= a[hint] -- gallop left, until - * a[hint - ofs] < key <= a[hint - lastofs] - */ - int maxofs = hint + 1; // data[a] is lowest - while (ofs < maxofs) { - if (iflt(localData[localA - ofs].key, key)) - break; - // key <= data[a + hint - ofs] - lastofs = ofs; - ofs = (ofs << 1) + 1; - if (ofs <= 0) // int overflow - ofs = maxofs; - } - if (ofs > maxofs) - ofs = maxofs; - // Translate back to offsets relative to a. - int k = lastofs; - lastofs = hint - ofs; - ofs = hint - k; - } - localA -= hint; - //assert_(-1 <= lastofs && lastofs < ofs && ofs <= n); - /* Now a[lastofs] < key <= a[ofs], so key belongs somewhere to the - * right of lastofs but no farther right than ofs. Do a binary - * search, with invariant a[lastofs-1] < key <= a[ofs]. - */ - ++lastofs; - while (lastofs < ofs) { - int m = lastofs + ((ofs - lastofs) >> 1); - if (iflt(localData[localA + m].key, key)) - lastofs = m+1; // data[a + m] < key - else - ofs = m; // key <= data[a + m] - } - //assert_(lastofs == ofs); // so data[a + ofs -1] < key <= data[a+ofs] - return ofs; - } - - - /* - * Exactly like gallop_left(), except that if key already exists in a[0:n], - * finds the position immediately to the right of the rightmost equal value. - * - * The return value is the int k in 0..n such that - * a[k-1] <= key < a[k] - * or -1 if error. - * - * The code duplication is massive, but this is enough different given that - * we're sticking to "<" comparisons that it's much harder to follow if - * written as one routine with yet another "left or right?" flag. - */ - - private int gallop_right(PyObject key, KVPair[] aData, int localA, int localN, - int hint) - { - //assert_(n > 0 && hint >= 0 && hint < n); - localA += hint; - int lastofs = 0; - int ofs = 1; - - if (iflt(key, aData[localA].key)) { - /* key < a[hint] -- gallop left, until - * a[hint - ofs] <= key < a[hint - lastofs] - */ - int maxofs = hint + 1; /* data[a] is lowest */ - while (ofs < maxofs) { - if (iflt(key, aData[localA - ofs].key)) { - lastofs = ofs; - ofs = (ofs << 1) + 1; - if (ofs <= 0) // int overflow - ofs = maxofs; - } else { - /* a[hint - ofs] <= key */ - break; - } - } - if (ofs > maxofs) - ofs = maxofs; - /* Translate back to positive offsets relative to &a[0]. */ - int k = lastofs; - lastofs = hint - ofs; - ofs = hint - k; - } else { - /* a[hint] <= key -- gallop right, until - * a[hint + lastofs] <= key < a[hint + ofs] - */ - int maxofs = localN - hint; /* data[a + n - 1] is highest */ - while (ofs < maxofs) { - if (iflt(key, aData[localA + ofs].key)) - break; - /* a[hint + ofs] <= key */ - lastofs = ofs; - ofs = (ofs << 1) + 1; - if (ofs <= 0) /* int overflow */ - ofs = maxofs; - } - if (ofs > maxofs) - ofs = maxofs; - /* Translate back to offsets relative to &a[0]. */ - lastofs += hint; - ofs += hint; - } - localA -= hint; - - //assert_(-1 <= lastofs && lastofs < ofs && ofs <= n); - - /* Now a[lastofs] <= key < a[ofs], so key belongs somewhere to the - * right of lastofs but no farther right than ofs. Do a binary - * search, with invariant a[lastofs-1] <= key < a[ofs]. - */ - ++lastofs; - while (lastofs < ofs) { - int m = lastofs + ((ofs - lastofs) >> 1); - if (iflt(key, aData[localA + m].key)) - ofs = m; // key < data[a + m] - else - lastofs = m+1; // data[a + m] <= key - } - //assert_(lastofs == ofs); // so data[a + ofs -1] <= key < data[a+ofs] - return ofs; - } - - - void merge_at(int i) { - //assert_(n >= 2); - //assert_(i >= 0); - //assert_(i == n - 2 || i == n - 3); - - int pa = this.base[i]; - int pb = this.base[i+1]; - int na = this.len[i]; - int nb = this.len[i+1]; - - //assert_(na > 0 && nb > 0); - //assert_(pa + na == pb); - - // Record the length of the combined runs; if i is the 3rd-last - // run now, also slide over the last run (which isn't involved - // in this merge). The current run i+1 goes away in any case. - if (i == this.n - 3) { - this.len[i+1] = this.len[i+2]; - this.base[i+1] = this.base[i+2]; - } - this.len[i] = na + nb; - --this.n; - - // Where does b start in a? Elements in a before that can be - // ignored (already in place). - int k = gallop_right(this.kvdata[pb].key, this.kvdata, pa, na, 0); - pa += k; - na -= k; - if (na == 0) - return; - - // Where does a end in b? Elements in b after that can be - // ignored (already in place). - nb = gallop_left(this.kvdata[pa + na - 1].key, this.kvdata, pb, nb, nb-1); - if (nb == 0) - return; - - // Merge what remains of the runs, using a temp array with - // min(na, nb) elements. - if (na <= nb) - merge_lo(pa, na, pb, nb); - else - merge_hi(pa, na, pb, nb); - } - - - /* Examine the stack of runs waiting to be merged, merging adjacent runs - * until the stack invariants are re-established: - * - * 1. len[-3] > len[-2] + len[-1] - * 2. len[-2] > len[-1] - * - * See listsort.txt for more info. - */ - void merge_collapse() { - while (this.n > 1) { - int localN = this.n - 2; - if (localN > 0 && this.len[localN-1] <= this.len[localN] + this.len[localN+1]) { - if (this.len[localN-1] < this.len[localN+1]) - --localN; - merge_at(localN); - } else if (this.len[localN] <= this.len[localN+1]) { - merge_at(localN); - } else { - break; - } - } - } - - - /* Regardless of invariants, merge all runs on the stack until only one - * remains. This is used at the end of the mergesort. - * - * Returns 0 on success, -1 on error. - */ - void merge_force_collapse() { - while (this.n > 1) { - int localN = this.n - 2; - if (localN > 0 && this.len[localN-1] < this.len[localN+1]) - --localN; - merge_at(localN); - } - } - - - /* Compute a good value for the minimum run length; natural runs shorter - * than this are boosted artificially via binary insertion. - * - * If n < 64, return n (it's too small to bother with fancy stuff). - * Else if n is an exact power of 2, return 32. - * Else return an int k, 32 <= k <= 64, such that n/k is close to, but - * strictly less than, an exact power of 2. - * - * See listsort.txt for more info. - */ - int merge_compute_minrun(int localN) { - int r = 0; // becomes 1 if any 1 bits are shifted off - - //assert_(n >= 0); - while (localN >= 64) { - r |= localN & 1; - localN >>= 1; - } - return localN + r; - } - - - void assert_(boolean expr) { - if (!expr) - throw new RuntimeException("assert"); - } - - - private boolean iflt(PyObject x, PyObject y) { - //assert_(x != null); - //assert_(y != null); - - if (this.compare == null) { - /* NOTE: we rely on the fact here that the sorting algorithm - only ever checks whether k<0, i.e., whether x<y. So we - invoke the rich comparison function with _lt ('<'), and - return -1 when it returns true and 0 when it returns - false. */ - return x._lt(y).__nonzero__(); - } - - PyObject ret = this.compare.__call__(x, y); - - if (ret instanceof PyInteger) { - int v = ((PyInteger)ret).getValue(); - return v < 0; - } - throw Py.TypeError("comparision function must return int"); - } - - - void reverse_slice(int lo, int hi) { - --hi; - while (lo < hi) { - KVPair t = this.kvdata[lo]; - this.kvdata[lo] = this.kvdata[hi]; - this.kvdata[hi] = t; - ++lo; - --hi; - } - } - - - - /* - * binarysort is the best method for sorting small arrays: it does - * few compares, but can do data movement quadratic in the number of - * elements. - * [lo, hi) is a contiguous slice of a list, and is sorted via - * binary insertion. This sort is stable. - * On entry, must have lo <= start <= hi, and that [lo, start) is already - * sorted (pass start == lo if you don't know!). - * If islt() complains return -1, else 0. - * Even in case of error, the output slice will be some permutation of - * the input (nothing is lost or duplicated). - */ - void binarysort(int lo, int hi, int start) { - //debug("binarysort: lo:" + lo + " hi:" + hi + " start:" + start); - int p; - - //assert_(lo <= start && start <= hi); - /* assert [lo, start) is sorted */ - if (lo == start) - ++start; - for (; start < hi; ++start) { - /* set l to where *start belongs */ - int l = lo; - int r = start; - KVPair pivot = this.kvdata[r]; - // Invariants: - // pivot >= all in [lo, l). - // pivot < all in [r, start). - // The second is vacuously true at the start. - //assert_(l < r); - do { - p = l + ((r - l) >> 1); - if (iflt(pivot.key, this.kvdata[p].key)) - r = p; - else - l = p+1; - } while (l < r); - //assert_(l == r); - // The invariants still hold, so pivot >= all in [lo, l) and - // pivot < all in [l, start), so pivot belongs at l. Note - // that if there are elements equal to pivot, l points to the - // first slot after them -- that's why this sort is stable. - // Slide over to make room. - for (p = start; p > l; --p) - this.kvdata[p] = this.kvdata[p - 1]; - this.kvdata[l] = pivot; - } - //dump_data("binsort", lo, hi - lo); - } - -/* //debugging methods. - private void dump_data(String txt, int lo, int n) { - System.out.print(txt + ":"); - for (int i = 0; i < n; i++) - System.out.print(data[lo + i] + " "); - System.out.println(); - } - private void debug(String str) { - //System.out.println(str); - } -*/ -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-04-30 06:25:42
|
Revision: 6280 http://jython.svn.sourceforge.net/jython/?rev=6280&view=rev Author: zyasoft Date: 2009-04-30 06:25:36 +0000 (Thu, 30 Apr 2009) Log Message: ----------- Fixed PyList#sort so that reversed sorts are stable and keyed sorts are keyed only once. Modified Paths: -------------- trunk/jython/src/org/python/core/PyList.java Removed Paths: ------------- trunk/jython/src/org/python/core/PyComparator.java Deleted: trunk/jython/src/org/python/core/PyComparator.java =================================================================== --- trunk/jython/src/org/python/core/PyComparator.java 2009-04-30 05:00:01 UTC (rev 6279) +++ trunk/jython/src/org/python/core/PyComparator.java 2009-04-30 06:25:36 UTC (rev 6280) @@ -1,53 +0,0 @@ -package org.python.core; - -import java.util.Comparator; - -public class PyComparator implements Comparator<PyObject> { - - protected PyList list; - protected PyObject cmp; - protected PyObject key; - protected boolean reverse = false; - - PyComparator(PyList list, PyObject cmp, PyObject key, boolean reverse) { - this.list = list; - this.cmp = cmp; - this.key = key; - this.reverse = reverse; - } - - // First cut at an implementation. FIXME: In CPython key is supposed to - // make things fast, accessing each element once. For this first cut I am - // cheating and calling the key function on every pass to get something - // that works right away. - public int compare(PyObject o1, PyObject o2) { - int result; - if (key != null && key != Py.None) { - o1 = key.__call__(o1); - o2 = key.__call__(o2); - } - if (cmp != null && cmp != Py.None) { - result = cmp.__call__(o1, o2).asInt(); - } else { - result = o1._cmp(o2); - } - if (reverse) { - return -result; - } - if (this.list.gListAllocatedStatus >= 0) { - throw Py.ValueError("list modified during sort"); - } - return result; - } - - public boolean equals(Object o) { - if(o == this) { - return true; - } - - if (o instanceof PyComparator) { - return key.equals(((PyComparator)o).key) && cmp.equals(((PyComparator)o).cmp); - } - return false; - } -} Modified: trunk/jython/src/org/python/core/PyList.java =================================================================== --- trunk/jython/src/org/python/core/PyList.java 2009-04-30 05:00:01 UTC (rev 6279) +++ trunk/jython/src/org/python/core/PyList.java 2009-04-30 06:25:36 UTC (rev 6280) @@ -11,6 +11,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; @@ -710,21 +711,183 @@ sort(cmp, key, reverse); } - public void sort(PyObject compare) { - sort(compare, Py.None, Py.False); + public void sort(PyObject cmp, PyObject key, PyObject reverse) { + boolean bReverse = reverse.__nonzero__(); + if (key == Py.None || key == null) { + if (cmp == Py.None || cmp == null) { + sort(bReverse); + } else { + sort(cmp, bReverse); + } + } else { + sort(cmp, key, bReverse); + } } + // a bunch of optimized paths for sort to avoid unnecessary work, such as DSU or checking compare functions for null + public void sort() { - sort(Py.None, Py.None, Py.False); + sort(false); } - public synchronized void sort(PyObject cmp, PyObject key, PyObject reverse) { + private synchronized void sort(boolean reverse) { gListAllocatedStatus = -1; - PyComparator c = new PyComparator(this, cmp, key, reverse.__nonzero__()); + if (reverse) { + Collections.reverse(list); // maintain stability of sort by reversing first + } + Collections.sort(list, new PyObjectDefaultComparator(this)); + if (reverse) { + Collections.reverse(list); // maintain stability of sort by reversing first + } + gListAllocatedStatus = __len__(); + } + + private static class PyObjectDefaultComparator implements Comparator<PyObject> { + + private final PyList list; + + PyObjectDefaultComparator(PyList list) { + this.list = list; + } + + public int compare(PyObject o1, PyObject o2) { + int result = o1._cmp(o2); + if (this.list.gListAllocatedStatus >= 0) { + throw Py.ValueError("list modified during sort"); + } + return result; + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof PyObjectDefaultComparator) { + return true; + } + return false; + } + } + + public void sort(PyObject compare) { + sort(compare, false); + } + + private synchronized void sort(PyObject compare, boolean reverse) { + gListAllocatedStatus = -1; + if (reverse) { + Collections.reverse(list); // maintain stability of sort by reversing first + } + PyObjectComparator c = new PyObjectComparator(this, compare); Collections.sort(list, c); + if (reverse) { + Collections.reverse(list); + } gListAllocatedStatus = __len__(); } + private static class PyObjectComparator implements Comparator<PyObject> { + + private final PyList list; + private final PyObject cmp; + + PyObjectComparator(PyList list, PyObject cmp) { + this.list = list; + this.cmp = cmp; + } + + public int compare(PyObject o1, PyObject o2) { + int result = cmp.__call__(o1, o2).asInt(); + if (this.list.gListAllocatedStatus >= 0) { + throw Py.ValueError("list modified during sort"); + } + return result; + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + + if (o instanceof PyObjectComparator) { + return cmp.equals(((PyComparator) o).cmp); + } + return false; + } + } + + private static class KV { + + private final PyObject key; + private final PyObject value; + + KV(PyObject key, PyObject value) { + this.key = key; + this.value = value; + } + } + + private static class KVComparator implements Comparator<KV> { + + private final PyList list; + private final PyObject cmp; + + KVComparator(PyList list, PyObject cmp) { + this.list = list; + this.cmp = cmp; + } + + public int compare(KV o1, KV o2) { + int result; + if (cmp != null && cmp != Py.None) { + result = cmp.__call__(o1.key, o2.key).asInt(); + } else { + result = o1.key._cmp(o2.key); + } + if (this.list.gListAllocatedStatus >= 0) { + throw Py.ValueError("list modified during sort"); + } + return result; + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + + if (o instanceof PyObjectComparator) { + return cmp.equals(((PyComparator) o).cmp); + } + return false; + } + } + + private synchronized void sort(PyObject cmp, PyObject key, boolean reverse) { + gListAllocatedStatus = -1; + + int size = list.size(); + final ArrayList<KV> decorated = new ArrayList<KV>(size); + for (PyObject value : list) { + decorated.add(new KV(key.__call__(value), value)); + } + list.clear(); + KVComparator c = new KVComparator(this, cmp); + if (reverse) { + Collections.reverse(decorated); // maintain stability of sort by reversing first + } + Collections.sort(decorated, c); + if (reverse) { + Collections.reverse(decorated); + } + if (list instanceof ArrayList) { + ((ArrayList) list).ensureCapacity(size); + } + for (KV kv : decorated) { + list.add(kv.value); + } + gListAllocatedStatus = __len__(); + } + public int hashCode() { return list___hash__(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-04-30 05:00:03
|
Revision: 6279 http://jython.svn.sourceforge.net/jython/?rev=6279&view=rev Author: zyasoft Date: 2009-04-30 05:00:01 +0000 (Thu, 30 Apr 2009) Log Message: ----------- Synchronized methods in PyList, and removed synchronization in PySequence (not necessary for immutable types like xrange, string, tuple). Modified Paths: -------------- trunk/jython/src/org/python/core/PyList.java trunk/jython/src/org/python/core/PySequence.java Modified: trunk/jython/src/org/python/core/PyList.java =================================================================== --- trunk/jython/src/org/python/core/PyList.java 2009-04-29 08:36:15 UTC (rev 6278) +++ trunk/jython/src/org/python/core/PyList.java 2009-04-30 05:00:01 UTC (rev 6279) @@ -21,6 +21,7 @@ public static final PyType TYPE = PyType.fromClass(PyList.class); protected final List<PyObject> list; + public volatile int gListAllocatedStatus = -1; public PyList() { this(TYPE); @@ -113,7 +114,7 @@ } @ExposedMethod(doc = BuiltinDocs.list___len___doc) - final int list___len__() { + final synchronized int list___len__() { return size(); } @@ -150,7 +151,7 @@ } } - protected void setsliceList(int start, int stop, int step, List value) { + final private void setsliceList(int start, int stop, int step, List value) { int n = sliceLength(start, stop, step); if (list instanceof ArrayList) { ((ArrayList) list).ensureCapacity(start + n); @@ -161,7 +162,7 @@ } } - protected void setsliceIterator(int start, int stop, int step, Iterator<PyObject> iter) { + final private void setsliceIterator(int start, int stop, int step, Iterator<PyObject> iter) { if (step == 1) { List<PyObject> insertion = new ArrayList<PyObject>(); if (iter != null) { @@ -184,7 +185,7 @@ } } - protected void setslicePyList(int start, int stop, int step, PyList other) { + final private void setslicePyList(int start, int stop, int step, PyList other) { if (step == 1) { list.subList(start, stop).clear(); list.addAll(start, other.list); @@ -203,7 +204,7 @@ } @Override - protected PyObject repeat(int count) { + protected synchronized PyObject repeat(int count) { if (count < 0) { count = 0; } @@ -221,32 +222,32 @@ } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___ne___doc) - final PyObject list___ne__(PyObject o) { + final synchronized PyObject list___ne__(PyObject o) { return seq___ne__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___eq___doc) - final PyObject list___eq__(PyObject o) { + final synchronized PyObject list___eq__(PyObject o) { return seq___eq__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___lt___doc) - final PyObject list___lt__(PyObject o) { + final synchronized PyObject list___lt__(PyObject o) { return seq___lt__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___le___doc) - final PyObject list___le__(PyObject o) { + final synchronized PyObject list___le__(PyObject o) { return seq___le__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___gt___doc) - final PyObject list___gt__(PyObject o) { + final synchronized PyObject list___gt__(PyObject o) { return seq___gt__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___ge___doc) - final PyObject list___ge__(PyObject o) { + final synchronized PyObject list___ge__(PyObject o) { return seq___ge__(o); } @@ -256,7 +257,7 @@ } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___imul___doc) - final PyObject list___imul__(PyObject o) { + final synchronized PyObject list___imul__(PyObject o) { if (!o.isIndex()) { return null; } @@ -294,7 +295,7 @@ } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___mul___doc) - final PyObject list___mul__(PyObject o) { + final synchronized PyObject list___mul__(PyObject o) { if (!o.isIndex()) { return null; } @@ -307,7 +308,7 @@ } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___rmul___doc) - final PyObject list___rmul__(PyObject o) { + final synchronized PyObject list___rmul__(PyObject o) { if (!o.isIndex()) { return null; } @@ -320,7 +321,7 @@ } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___add___doc) - final PyObject list___add__(PyObject o) { + final synchronized PyObject list___add__(PyObject o) { PyList sum = null; if (o instanceof PySequenceList && !(o instanceof PyTuple)) { if (o instanceof PyList) { @@ -352,7 +353,7 @@ //XXX: needs __doc__ @ExposedMethod(type = MethodType.BINARY) - final PyObject list___radd__(PyObject o) { + final synchronized PyObject list___radd__(PyObject o) { // Support adding java.util.List, but prevent adding PyTuple. // 'o' should never be a PyNewList since __add__ is defined. PyList sum = null; @@ -369,22 +370,22 @@ } @ExposedMethod(doc = BuiltinDocs.list___contains___doc) - final boolean list___contains__(PyObject o) { + final synchronized boolean list___contains__(PyObject o) { return object___contains__(o); } @ExposedMethod(doc = BuiltinDocs.list___delitem___doc) - final void list___delitem__(PyObject index) { + final synchronized void list___delitem__(PyObject index) { seq___delitem__(index); } @ExposedMethod(doc = BuiltinDocs.list___setitem___doc) - final void list___setitem__(PyObject o, PyObject def) { + final synchronized void list___setitem__(PyObject o, PyObject def) { seq___setitem__(o, def); } @ExposedMethod(doc = BuiltinDocs.list___getitem___doc) - final PyObject list___getitem__(PyObject o) { + final synchronized PyObject list___getitem__(PyObject o) { PyObject ret = seq___finditem__(o); if (ret == null) { throw Py.IndexError("index out of range: " + o); @@ -398,22 +399,22 @@ } @ExposedMethod(doc = BuiltinDocs.list___iter___doc) - public PyObject list___iter__() { + public synchronized PyObject list___iter__() { return new PyFastSequenceIter(this); } @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___getslice___doc) - final PyObject list___getslice__(PyObject start, PyObject stop, PyObject step) { + final synchronized PyObject list___getslice__(PyObject start, PyObject stop, PyObject step) { return seq___getslice__(start, stop, step); } @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___setslice___doc) - final void list___setslice__(PyObject start, PyObject stop, PyObject step, PyObject value) { + final synchronized void list___setslice__(PyObject start, PyObject stop, PyObject step, PyObject value) { seq___setslice__(start, stop, step, value); } @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___delslice___doc) - final void list___delslice__(PyObject start, PyObject stop, PyObject step) { + final synchronized void list___delslice__(PyObject start, PyObject stop, PyObject step) { seq___delslice__(start, stop, step); } @@ -431,7 +432,7 @@ //XXX: needs __doc__ @ExposedMethod(names = "__repr__") - final String list_toString() { + final synchronized String list_toString() { ThreadState ts = Py.getThreadState(); if (!ts.enterRepr(this)) { return "[...]"; @@ -462,7 +463,7 @@ } @ExposedMethod(doc = BuiltinDocs.list_append_doc) - final void list_append(PyObject o) { + final synchronized void list_append(PyObject o) { pyadd(o); gListAllocatedStatus = __len__(); } @@ -478,7 +479,7 @@ } @ExposedMethod(doc = BuiltinDocs.list_count_doc) - final int list_count(PyObject o) { + final synchronized int list_count(PyObject o) { int count = 0; for (PyObject item : list) { if (item.equals(o)) { @@ -507,21 +508,21 @@ } @ExposedMethod(defaults = {"null", "null"}, doc = BuiltinDocs.list_index_doc) - final int list_index(PyObject o, PyObject start, PyObject stop) { + final synchronized int list_index(PyObject o, PyObject start, PyObject stop) { int startInt = start == null ? 0 : PySlice.calculateSliceIndex(start); int stopInt = stop == null ? size() : PySlice.calculateSliceIndex(stop); return list_index(o, startInt, stopInt); } - final int list_index(PyObject o, int start, int stop) { + final synchronized int list_index(PyObject o, int start, int stop) { return _index(o, "list.index(x): x not in list", start, stop); } - final int list_index(PyObject o, int start) { + final synchronized int list_index(PyObject o, int start) { return _index(o, "list.index(x): x not in list", start, size()); } - final int list_index(PyObject o) { + final synchronized int list_index(PyObject o) { return _index(o, "list.index(x): x not in list", 0, size()); } @@ -559,7 +560,7 @@ } @ExposedMethod(doc = BuiltinDocs.list_insert_doc) - final void list_insert(int index, PyObject o) { + final synchronized void list_insert(int index, PyObject o) { if (index < 0) { index = Math.max(0, size() + index); } @@ -583,7 +584,7 @@ } @ExposedMethod(doc = BuiltinDocs.list_remove_doc) - final void list_remove(PyObject o) { + final synchronized void list_remove(PyObject o) { del(_index(o, "list.remove(x): x not in list", 0, size())); gListAllocatedStatus = __len__(); } @@ -598,7 +599,7 @@ } @ExposedMethod(doc = BuiltinDocs.list_reverse_doc) - final void list_reverse() { + final synchronized void list_reverse() { Collections.reverse(list); gListAllocatedStatus = __len__(); } @@ -621,7 +622,7 @@ } @ExposedMethod(defaults = "-1", doc = BuiltinDocs.list_pop_doc) - final PyObject list_pop(int n) { + final synchronized PyObject list_pop(int n) { int length = size(); if (length == 0) { throw Py.IndexError("pop from empty list"); @@ -648,7 +649,7 @@ } @ExposedMethod(doc = BuiltinDocs.list_extend_doc) - final void list_extend(PyObject o) { + final synchronized void list_extend(PyObject o) { if (o instanceof PyList) { list.addAll(((PyList) o).list); } else { @@ -665,7 +666,7 @@ } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___iadd___doc) - final PyObject list___iadd__(PyObject o) { + final synchronized PyObject list___iadd__(PyObject o) { PyType oType = o.getType(); if (oType == TYPE || oType == PyTuple.TYPE || this == o) { extend(fastSequence(o, "argument must be iterable")); @@ -701,7 +702,7 @@ * operators. */ @ExposedMethod(doc = BuiltinDocs.list_sort_doc) - final void list_sort(PyObject[] args, String[] kwds) { + final synchronized void list_sort(PyObject[] args, String[] kwds) { ArgParser ap = new ArgParser("list", args, kwds, new String[]{"cmp", "key", "reverse"}, 0); PyObject cmp = ap.getPyObject(0, Py.None); PyObject key = ap.getPyObject(1, Py.None); @@ -729,7 +730,7 @@ } @ExposedMethod(doc = BuiltinDocs.list___hash___doc) - final int list___hash__() { + final synchronized int list___hash__() { throw Py.TypeError(String.format("unhashable type: '%.200s'", getType().fastGetName())); } @@ -750,7 +751,7 @@ } @Override - public boolean addAll(int index, Collection c) { + public synchronized boolean addAll(int index, Collection c) { PyList elements = new PyList(c); return list.addAll(index, elements.list); } @@ -761,17 +762,17 @@ } @Override - public void clear() { + public synchronized void clear() { list.clear(); } @Override - public boolean contains(Object o) { + public synchronized boolean contains(Object o) { return list.contains(Py.java2py(o)); } @Override - public boolean containsAll(Collection c) { + public synchronized boolean containsAll(Collection c) { if (c instanceof PyList) { return list.containsAll(((PyList) c).list); } else if (c instanceof PyTuple) { @@ -782,7 +783,7 @@ } @Override - public boolean equals(Object o) { + public synchronized boolean equals(Object o) { if (o instanceof PyList) { return (((PyList) o).list.equals(list)); } else if (o instanceof List && !(o instanceof PyTuple)) { @@ -793,24 +794,23 @@ } @Override - public Object get(int index) { + public synchronized Object get(int index) { return list.get(index).__tojava__(Object.class); } - /** @deprecated */ @Override - public PyObject[] getArray() { - PyObject a[] = null; // = new PyObject[list.size()]; + public synchronized PyObject[] getArray() { + PyObject a[] = null; return list.toArray(a); } @Override - public int indexOf(Object o) { + public synchronized int indexOf(Object o) { return list.indexOf(o); } @Override - public boolean isEmpty() { + public synchronized boolean isEmpty() { return list.isEmpty(); } @@ -836,7 +836,7 @@ } @Override - public int lastIndexOf(Object o) { + public synchronized int lastIndexOf(Object o) { return list.lastIndexOf(Py.java2py(o)); } @@ -890,37 +890,37 @@ } @Override - public void pyadd(int index, PyObject element) { + public synchronized void pyadd(int index, PyObject element) { list.add(index, element); } @Override - public boolean pyadd(PyObject o) { + public synchronized boolean pyadd(PyObject o) { list.add(o); return true; } @Override - public PyObject pyget(int index) { + public synchronized PyObject pyget(int index) { return list.get(index); } - public void pyset(int index, PyObject element) { + public synchronized void pyset(int index, PyObject element) { list.set(index, element); } @Override - public Object remove(int index) { + public synchronized Object remove(int index) { return list.remove(index); } @Override - public void remove(int start, int stop) { + public synchronized void remove(int start, int stop) { list.subList(start, stop).clear(); } @Override - public boolean removeAll(Collection c) { + public synchronized boolean removeAll(Collection c) { if (c instanceof PySequenceList) { return list.removeAll(c); } else { @@ -929,7 +929,7 @@ } @Override - public boolean retainAll(Collection c) { + public synchronized boolean retainAll(Collection c) { if (c instanceof PySequenceList) { return list.retainAll(c); } else { @@ -938,22 +938,22 @@ } @Override - public Object set(int index, Object element) { + public synchronized Object set(int index, Object element) { return list.set(index, Py.java2py(element)).__tojava__(Object.class); } @Override - public int size() { + public synchronized int size() { return list.size(); } @Override - public List subList(int fromIndex, int toIndex) { + public synchronized List subList(int fromIndex, int toIndex) { return fromList(list.subList(fromIndex, toIndex)); } @Override - public Object[] toArray() { + public synchronized Object[] toArray() { Object copy[] = list.toArray(); for (int i = 0; i < copy.length; i++) { copy[i] = ((PyObject) copy[i]).__tojava__(Object.class); @@ -962,7 +962,7 @@ } @Override - public Object[] toArray(Object[] a) { + public synchronized Object[] toArray(Object[] a) { Object copy[] = list.toArray(); if (a.length < copy.length) { a = copy; @@ -994,7 +994,7 @@ } @Override - public boolean remove(Object o) { + public synchronized boolean remove(Object o) { return list.remove(Py.java2py(o)); } } Modified: trunk/jython/src/org/python/core/PySequence.java =================================================================== --- trunk/jython/src/org/python/core/PySequence.java 2009-04-29 08:36:15 UTC (rev 6278) +++ trunk/jython/src/org/python/core/PySequence.java 2009-04-30 05:00:01 UTC (rev 6279) @@ -15,7 +15,6 @@ public abstract class PySequence extends PyObject { public PySequence() {} - public int gListAllocatedStatus = -1; protected PySequence(PyType type) { super(type); @@ -99,11 +98,11 @@ return new PySequenceIter(this); } - public synchronized PyObject __eq__(PyObject o) { + public PyObject __eq__(PyObject o) { return seq___eq__(o); } - final synchronized PyObject seq___eq__(PyObject o) { + final PyObject seq___eq__(PyObject o) { if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { return null; } @@ -116,11 +115,11 @@ return (i < 0) ? Py.True : Py.False; } - public synchronized PyObject __ne__(PyObject o) { + public PyObject __ne__(PyObject o) { return seq___ne__(o); } - final synchronized PyObject seq___ne__(PyObject o) { + final PyObject seq___ne__(PyObject o) { if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { return null; } @@ -133,11 +132,11 @@ return (i < 0) ? Py.False : Py.True; } - public synchronized PyObject __lt__(PyObject o) { + public PyObject __lt__(PyObject o) { return seq___lt__(o); } - final synchronized PyObject seq___lt__(PyObject o) { + final PyObject seq___lt__(PyObject o) { if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { return null; } @@ -148,11 +147,11 @@ return __finditem__(i)._lt(o.__finditem__(i)); } - public synchronized PyObject __le__(PyObject o) { + public PyObject __le__(PyObject o) { return seq___le__(o); } - final synchronized PyObject seq___le__(PyObject o) { + final PyObject seq___le__(PyObject o) { if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { return null; } @@ -163,11 +162,11 @@ return __finditem__(i)._le(o.__finditem__(i)); } - public synchronized PyObject __gt__(PyObject o) { + public PyObject __gt__(PyObject o) { return seq___gt__(o); } - final synchronized PyObject seq___gt__(PyObject o) { + final PyObject seq___gt__(PyObject o) { if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { return null; } @@ -177,11 +176,11 @@ return __finditem__(i)._gt(o.__finditem__(i)); } - public synchronized PyObject __ge__(PyObject o) { + public PyObject __ge__(PyObject o) { return seq___ge__(o); } - final synchronized PyObject seq___ge__(PyObject o) { + final PyObject seq___ge__(PyObject o) { if(!(getType() == o.getType()) && !(getType().isSubType(o.getType()))) { return null; } @@ -263,7 +262,7 @@ return seq___finditem__(index); } - final synchronized PyObject seq___finditem__(int index) { + final PyObject seq___finditem__(int index) { return delegator.checkIdxAndFindItem(index); } @@ -291,22 +290,22 @@ return false; } - public synchronized PyObject __getslice__(PyObject start, PyObject stop, PyObject step) { + public PyObject __getslice__(PyObject start, PyObject stop, PyObject step) { return seq___getslice__(start, stop, step); } - final synchronized PyObject seq___getslice__(PyObject start, PyObject stop, PyObject step) { + final PyObject seq___getslice__(PyObject start, PyObject stop, PyObject step) { return delegator.getSlice(new PySlice(start, stop, step)); } - public synchronized void __setslice__(PyObject start, + public void __setslice__(PyObject start, PyObject stop, PyObject step, PyObject value) { seq___setslice__(start, stop, step, value); } - final synchronized void seq___setslice__(PyObject start, + final void seq___setslice__(PyObject start, PyObject stop, PyObject step, PyObject value) { @@ -317,15 +316,15 @@ delegator.checkIdxAndSetSlice(new PySlice(start, stop, step), value); } - public synchronized void __delslice__(PyObject start, PyObject stop, PyObject step) { + public void __delslice__(PyObject start, PyObject stop, PyObject step) { seq___delslice__(start, stop, step); } - final synchronized void seq___delslice__(PyObject start, PyObject stop, PyObject step) { + final void seq___delslice__(PyObject start, PyObject stop, PyObject step) { delegator.checkIdxAndDelItem(new PySlice(start, stop, step)); } - public synchronized void __setitem__(int index, PyObject value) { + public void __setitem__(int index, PyObject value) { delegator.checkIdxAndSetItem(index, value); } @@ -337,11 +336,11 @@ delegator.checkIdxAndSetItem(index, value); } - public synchronized void __delitem__(PyObject index) { + public void __delitem__(PyObject index) { seq___delitem__(index); } - final synchronized void seq___delitem__(PyObject index) { + final void seq___delitem__(PyObject index) { delegator.checkIdxAndDelItem(index); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2009-04-29 08:36:17
|
Revision: 6278 http://jython.svn.sourceforge.net/jython/?rev=6278&view=rev Author: otmarhumbel Date: 2009-04-29 08:36:15 +0000 (Wed, 29 Apr 2009) Log Message: ----------- increase jython version numbers to 2.5 beta 4 Modified Paths: -------------- trunk/jython/build.xml Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-04-29 05:48:23 UTC (rev 6277) +++ trunk/jython/build.xml 2009-04-29 08:36:15 UTC (rev 6278) @@ -185,13 +185,13 @@ <property name="PY_RELEASE_LEVEL_SNAPSHOT" value="170"/> <!-- 0xAA --> <!-- The current version info --> - <property name="jython.version" value="2.5b3+"/> - <property name="jython.version.noplus" value="2.5b3"/> + <property name="jython.version" value="2.5b4+"/> + <property name="jython.version.noplus" value="2.5b4"/> <property name="jython.major_version" value="2"/> <property name="jython.minor_version" value="5"/> <property name="jython.micro_version" value="0"/> <property name="jython.release_level" value="${PY_RELEASE_LEVEL_BETA}"/> - <property name="jython.release_serial" value="3"/> + <property name="jython.release_serial" value="4"/> <condition property="do.snapshot.build"> <isset property="snapshot.revision" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2009-04-29 05:48:29
|
Revision: 6277 http://jython.svn.sourceforge.net/jython/?rev=6277&view=rev Author: otmarhumbel Date: 2009-04-29 05:48:23 +0000 (Wed, 29 Apr 2009) Log Message: ----------- revert to user registry having precedence over installed registry; should fix #1331 Modified Paths: -------------- trunk/jython/src/org/python/core/PySystemState.java Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2009-04-29 04:39:13 UTC (rev 6276) +++ trunk/jython/src/org/python/core/PySystemState.java 2009-04-29 05:48:23 UTC (rev 6277) @@ -585,9 +585,10 @@ prefix = exec_prefix = "."; } try { - addRegistryFile(new File(prefix, "registry")); + // user registry has precedence over installed registry File homeFile = new File(registry.getProperty("user.home"), ".jython"); addRegistryFile(homeFile); + addRegistryFile(new File(prefix, "registry")); } catch (Exception exc) { } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fi...@us...> - 2009-04-29 04:39:16
|
Revision: 6276 http://jython.svn.sourceforge.net/jython/?rev=6276&view=rev Author: fijal Date: 2009-04-29 04:39:13 +0000 (Wed, 29 Apr 2009) Log Message: ----------- Copy ctypes over. Hopefully this is short-lived. The reason why I do this is that I had to modify 3 lines in __init__.py because jython's struct module does not support 'P' as pointer or 'O' as PyObject. Added Paths: ----------- branches/ctypes-via-rawffi/Lib/ctypes/ branches/ctypes-via-rawffi/Lib/ctypes/__init__.py branches/ctypes-via-rawffi/Lib/ctypes/_endian.py branches/ctypes-via-rawffi/Lib/ctypes/macholib/ branches/ctypes-via-rawffi/Lib/ctypes/macholib/README.ctypes branches/ctypes-via-rawffi/Lib/ctypes/macholib/__init__.py branches/ctypes-via-rawffi/Lib/ctypes/macholib/dyld.py branches/ctypes-via-rawffi/Lib/ctypes/macholib/dylib.py branches/ctypes-via-rawffi/Lib/ctypes/macholib/fetch_macholib branches/ctypes-via-rawffi/Lib/ctypes/macholib/framework.py branches/ctypes-via-rawffi/Lib/ctypes/test/ branches/ctypes-via-rawffi/Lib/ctypes/test/__init__.py branches/ctypes-via-rawffi/Lib/ctypes/test/runtests.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_anon.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_array_in_pointer.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_arrays.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_as_parameter.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_bitfields.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_buffers.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_byteswap.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_callbacks.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_cast.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_cfuncs.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_checkretval.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_delattr.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_errcheck.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_find.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_funcptr.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_functions.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_incomplete.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_init.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_integers.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_internals.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_keeprefs.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_libc.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_loading.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_macholib.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_memfunctions.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_numbers.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_objects.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_parameters.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_pointers.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_prototypes.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_python_api.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_random_things.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_refcounts.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_repr.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_returnfuncptrs.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_simplesubclasses.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_sizes.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_slicing.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_stringptr.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_strings.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_struct_fields.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_structures.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_unaligned_structures.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_unicode.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_values.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_varsize_struct.py branches/ctypes-via-rawffi/Lib/ctypes/test/test_win32.py branches/ctypes-via-rawffi/Lib/ctypes/util.py branches/ctypes-via-rawffi/Lib/ctypes/wintypes.py Added: branches/ctypes-via-rawffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/__init__.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/__init__.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,537 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +"""create and manipulate C data types in Python""" + +import os as _os, sys as _sys + +__version__ = "1.0.3" + +from _ctypes import Union, Structure, Array +from _ctypes import _Pointer +from _ctypes import CFuncPtr as _CFuncPtr +from _ctypes import __version__ as _ctypes_version +from _ctypes import RTLD_LOCAL, RTLD_GLOBAL +from _ctypes import ArgumentError + +from struct import calcsize as _calcsize + +if __version__ != _ctypes_version: + raise Exception, ("Version number mismatch", __version__, _ctypes_version) + +if _os.name in ("nt", "ce"): + from _ctypes import FormatError + +DEFAULT_MODE = RTLD_LOCAL +if _os.name == "posix" and _sys.platform == "darwin": + import gestalt + + # gestalt.gestalt("sysv") returns the version number of the + # currently active system file as BCD. + # On OS X 10.4.6 -> 0x1046 + # On OS X 10.2.8 -> 0x1028 + # See also http://www.rgaros.nl/gestalt/ + # + # On OS X 10.3, we use RTLD_GLOBAL as default mode + # because RTLD_LOCAL does not work at least on some + # libraries. + + if gestalt.gestalt("sysv") < 0x1040: + DEFAULT_MODE = RTLD_GLOBAL + +from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \ + FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI + +""" +WINOLEAPI -> HRESULT +WINOLEAPI_(type) + +STDMETHODCALLTYPE + +STDMETHOD(name) +STDMETHOD_(type, name) + +STDAPICALLTYPE +""" + +def create_string_buffer(init, size=None): + """create_string_buffer(aString) -> character array + create_string_buffer(anInteger) -> character array + create_string_buffer(aString, anInteger) -> character array + """ + if isinstance(init, (str, unicode)): + if size is None: + size = len(init)+1 + buftype = c_char * size + buf = buftype() + buf.value = init + return buf + elif isinstance(init, (int, long)): + buftype = c_char * init + buf = buftype() + return buf + raise TypeError, init + +def c_buffer(init, size=None): +## "deprecated, use create_string_buffer instead" +## import warnings +## warnings.warn("c_buffer is deprecated, use create_string_buffer instead", +## DeprecationWarning, stacklevel=2) + return create_string_buffer(init, size) + +_c_functype_cache = {} +def CFUNCTYPE(restype, *argtypes): + """CFUNCTYPE(restype, *argtypes) -> function prototype. + + restype: the result type + argtypes: a sequence specifying the argument types + + The function prototype can be called in different ways to create a + callable object: + + prototype(integer address) -> foreign function + prototype(callable) -> create and return a C callable function from callable + prototype(integer index, method name[, paramflags]) -> foreign function calling a COM method + prototype((ordinal number, dll object)[, paramflags]) -> foreign function exported by ordinal + prototype((function name, dll object)[, paramflags]) -> foreign function exported by name + """ + try: + return _c_functype_cache[(restype, argtypes)] + except KeyError: + class CFunctionType(_CFuncPtr): + _argtypes_ = argtypes + _restype_ = restype + _flags_ = _FUNCFLAG_CDECL + _c_functype_cache[(restype, argtypes)] = CFunctionType + return CFunctionType + +if _os.name in ("nt", "ce"): + from _ctypes import LoadLibrary as _dlopen + from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL + if _os.name == "ce": + # 'ce' doesn't have the stdcall calling convention + _FUNCFLAG_STDCALL = _FUNCFLAG_CDECL + + _win_functype_cache = {} + def WINFUNCTYPE(restype, *argtypes): + # docstring set later (very similar to CFUNCTYPE.__doc__) + try: + return _win_functype_cache[(restype, argtypes)] + except KeyError: + class WinFunctionType(_CFuncPtr): + _argtypes_ = argtypes + _restype_ = restype + _flags_ = _FUNCFLAG_STDCALL + _win_functype_cache[(restype, argtypes)] = WinFunctionType + return WinFunctionType + if WINFUNCTYPE.__doc__: + WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE") + +else: + from _ctypes import dlopen as _dlopen + +from _ctypes import sizeof, byref, addressof, alignment, resize +from _ctypes import _SimpleCData + +def _check_size(typ, typecode=None): + # Check if sizeof(ctypes_type) against struct.calcsize. This + # should protect somewhat against a misconfigured libffi. + from struct import calcsize + if typecode is None: + # Most _type_ codes are the same as used in struct + typecode = typ._type_ + actual, required = sizeof(typ), calcsize(typecode) + if actual != required: + raise SystemError("sizeof(%s) wrong: %d instead of %d" % \ + (typ, actual, required)) + +class py_object(_SimpleCData): + _type_ = "O" + def __repr__(self): + try: + return super(py_object, self).__repr__() + except ValueError: + return "%s(<NULL>)" % type(self).__name__ +#_check_size(py_object, "P") + +class c_short(_SimpleCData): + _type_ = "h" +_check_size(c_short) + +class c_ushort(_SimpleCData): + _type_ = "H" +_check_size(c_ushort) + +class c_long(_SimpleCData): + _type_ = "l" +_check_size(c_long) + +class c_ulong(_SimpleCData): + _type_ = "L" +_check_size(c_ulong) + +if _calcsize("i") == _calcsize("l"): + # if int and long have the same size, make c_int an alias for c_long + c_int = c_long + c_uint = c_ulong +else: + class c_int(_SimpleCData): + _type_ = "i" + _check_size(c_int) + + class c_uint(_SimpleCData): + _type_ = "I" + _check_size(c_uint) + +class c_float(_SimpleCData): + _type_ = "f" +_check_size(c_float) + +class c_double(_SimpleCData): + _type_ = "d" +_check_size(c_double) + +if _calcsize("l") == _calcsize("q"): + # if long and long long have the same size, make c_longlong an alias for c_long + c_longlong = c_long + c_ulonglong = c_ulong +else: + class c_longlong(_SimpleCData): + _type_ = "q" + _check_size(c_longlong) + + class c_ulonglong(_SimpleCData): + _type_ = "Q" + ## def from_param(cls, val): + ## return ('d', float(val), val) + ## from_param = classmethod(from_param) + _check_size(c_ulonglong) + +class c_ubyte(_SimpleCData): + _type_ = "B" +c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte +# backward compatibility: +##c_uchar = c_ubyte +_check_size(c_ubyte) + +class c_byte(_SimpleCData): + _type_ = "b" +c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte +_check_size(c_byte) + +class c_char(_SimpleCData): + _type_ = "c" +c_char.__ctype_le__ = c_char.__ctype_be__ = c_char +_check_size(c_char) + +class c_char_p(_SimpleCData): + _type_ = "z" + if _os.name == "nt": + def __repr__(self): + if not windll.kernel32.IsBadStringPtrA(self, -1): + return "%s(%r)" % (self.__class__.__name__, self.value) + return "%s(%s)" % (self.__class__.__name__, cast(self, c_void_p).value) + else: + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, cast(self, c_void_p).value) +#_check_size(c_char_p, "P") + +class c_void_p(_SimpleCData): + _type_ = "P" +c_voidp = c_void_p # backwards compatibility (to a bug) +#_check_size(c_void_p) + +# This cache maps types to pointers to them. +_pointer_type_cache = {} + +def POINTER(cls): + try: + return _pointer_type_cache[cls] + except KeyError: + pass + if type(cls) is str: + klass = type(_Pointer)("LP_%s" % cls, + (_Pointer,), + {}) + _pointer_type_cache[id(klass)] = klass + return klass + else: + name = "LP_%s" % cls.__name__ + klass = type(_Pointer)(name, + (_Pointer,), + {'_type_': cls}) + _pointer_type_cache[cls] = klass + return klass + +try: + from _ctypes import set_conversion_mode +except ImportError: + pass +else: + if _os.name in ("nt", "ce"): + set_conversion_mode("mbcs", "ignore") + else: + set_conversion_mode("ascii", "strict") + + class c_wchar_p(_SimpleCData): + _type_ = "Z" + + class c_wchar(_SimpleCData): + _type_ = "u" + + POINTER(c_wchar).from_param = c_wchar_p.from_param #_SimpleCData.c_wchar_p_from_param + + def create_unicode_buffer(init, size=None): + """create_unicode_buffer(aString) -> character array + create_unicode_buffer(anInteger) -> character array + create_unicode_buffer(aString, anInteger) -> character array + """ + if isinstance(init, (str, unicode)): + if size is None: + size = len(init)+1 + buftype = c_wchar * size + buf = buftype() + buf.value = init + return buf + elif isinstance(init, (int, long)): + buftype = c_wchar * init + buf = buftype() + return buf + raise TypeError, init + +POINTER(c_char).from_param = c_char_p.from_param #_SimpleCData.c_char_p_from_param + +# XXX Deprecated +def SetPointerType(pointer, cls): + if _pointer_type_cache.get(cls, None) is not None: + raise RuntimeError, \ + "This type already exists in the cache" + if not _pointer_type_cache.has_key(id(pointer)): + raise RuntimeError, \ + "What's this???" + pointer.set_type(cls) + _pointer_type_cache[cls] = pointer + del _pointer_type_cache[id(pointer)] + + +def pointer(inst): + return POINTER(type(inst))(inst) + +# XXX Deprecated +def ARRAY(typ, len): + return typ * len + +################################################################ + + +class CDLL(object): + """An instance of this class represents a loaded dll/shared + library, exporting functions using the standard C calling + convention (named 'cdecl' on Windows). + + The exported functions can be accessed as attributes, or by + indexing with the function name. Examples: + + <obj>.qsort -> callable object + <obj>['qsort'] -> callable object + + Calling the functions releases the Python GIL during the call and + reaquires it afterwards. + """ + class _FuncPtr(_CFuncPtr): + _flags_ = _FUNCFLAG_CDECL + _restype_ = c_int # default, can be overridden in instances + + def __init__(self, name, mode=DEFAULT_MODE, handle=None): + self._name = name + if handle is None: + self._handle = _dlopen(self._name, mode) + else: + self._handle = handle + + def __repr__(self): + return "<%s '%s', handle %x at %x>" % \ + (self.__class__.__name__, self._name, + (self._handle & (_sys.maxint*2 + 1)), + id(self) & (_sys.maxint*2 + 1)) + + def __getattr__(self, name): + if name.startswith('__') and name.endswith('__'): + raise AttributeError, name + func = self.__getitem__(name) + setattr(self, name, func) + return func + + def __getitem__(self, name_or_ordinal): + func = self._FuncPtr((name_or_ordinal, self)) + if not isinstance(name_or_ordinal, (int, long)): + func.__name__ = name_or_ordinal + return func + +class PyDLL(CDLL): + """This class represents the Python library itself. It allows to + access Python API functions. The GIL is not released, and + Python exceptions are handled correctly. + """ + class _FuncPtr(_CFuncPtr): + _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI + _restype_ = c_int # default, can be overridden in instances + +if _os.name in ("nt", "ce"): + + class WinDLL(CDLL): + """This class represents a dll exporting functions using the + Windows stdcall calling convention. + """ + class _FuncPtr(_CFuncPtr): + _flags_ = _FUNCFLAG_STDCALL + _restype_ = c_int # default, can be overridden in instances + + # XXX Hm, what about HRESULT as normal parameter? + # Mustn't it derive from c_long then? + from _ctypes import _check_HRESULT, _SimpleCData + class HRESULT(_SimpleCData): + _type_ = "l" + # _check_retval_ is called with the function's result when it + # is used as restype. It checks for the FAILED bit, and + # raises a WindowsError if it is set. + # + # The _check_retval_ method is implemented in C, so that the + # method definition itself is not included in the traceback + # when it raises an error - that is what we want (and Python + # doesn't have a way to raise an exception in the caller's + # frame). + _check_retval_ = _check_HRESULT + + class OleDLL(CDLL): + """This class represents a dll exporting functions using the + Windows stdcall calling convention, and returning HRESULT. + HRESULT error values are automatically raised as WindowsError + exceptions. + """ + class _FuncPtr(_CFuncPtr): + _flags_ = _FUNCFLAG_STDCALL + _restype_ = HRESULT + +class LibraryLoader(object): + def __init__(self, dlltype): + self._dlltype = dlltype + + def __getattr__(self, name): + if name[0] == '_': + raise AttributeError(name) + dll = self._dlltype(name) + setattr(self, name, dll) + return dll + + def __getitem__(self, name): + return getattr(self, name) + + def LoadLibrary(self, name): + return self._dlltype(name) + +cdll = LibraryLoader(CDLL) +pydll = LibraryLoader(PyDLL) + +if _os.name in ("nt", "ce"): + pythonapi = PyDLL("python dll", None, _sys.dllhandle) +elif _sys.platform == "cygwin": + pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2]) +else: + pythonapi = PyDLL(None) + + +if _os.name in ("nt", "ce"): + windll = LibraryLoader(WinDLL) + oledll = LibraryLoader(OleDLL) + + if _os.name == "nt": + GetLastError = windll.kernel32.GetLastError + else: + GetLastError = windll.coredll.GetLastError + + def WinError(code=None, descr=None): + if code is None: + code = GetLastError() + if descr is None: + descr = FormatError(code).strip() + return WindowsError(code, descr) + +_pointer_type_cache[None] = c_void_p + +if sizeof(c_uint) == sizeof(c_void_p): + c_size_t = c_uint +elif sizeof(c_ulong) == sizeof(c_void_p): + c_size_t = c_ulong + +# functions + +from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr + +## void *memmove(void *, const void *, size_t); +memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr) + +## void *memset(void *, int, size_t) +memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr) + +def PYFUNCTYPE(restype, *argtypes): + class CFunctionType(_CFuncPtr): + _argtypes_ = argtypes + _restype_ = restype + _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI + return CFunctionType + +_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr) +def cast(obj, typ): + return _cast(obj, obj, typ) + +_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) +def string_at(ptr, size=-1): + """string_at(addr[, size]) -> string + + Return the string at addr.""" + return _string_at(ptr, size) + +try: + from _ctypes import _wstring_at_addr +except ImportError: + pass +else: + _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) + def wstring_at(ptr, size=-1): + """wstring_at(addr[, size]) -> string + + Return the string at addr.""" + return _wstring_at(ptr, size) + + +if _os.name in ("nt", "ce"): # COM stuff + def DllGetClassObject(rclsid, riid, ppv): + try: + ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*']) + except ImportError: + return -2147221231 # CLASS_E_CLASSNOTAVAILABLE + else: + return ccom.DllGetClassObject(rclsid, riid, ppv) + + def DllCanUnloadNow(): + try: + ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*']) + except ImportError: + return 0 # S_OK + return ccom.DllCanUnloadNow() + +from ctypes._endian import BigEndianStructure, LittleEndianStructure + +# Fill in specifically-sized types +c_int8 = c_byte +c_uint8 = c_ubyte +for kind in [c_short, c_int, c_long, c_longlong]: + if sizeof(kind) == 2: c_int16 = kind + elif sizeof(kind) == 4: c_int32 = kind + elif sizeof(kind) == 8: c_int64 = kind +for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]: + if sizeof(kind) == 2: c_uint16 = kind + elif sizeof(kind) == 4: c_uint32 = kind + elif sizeof(kind) == 8: c_uint64 = kind +del(kind) Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/__init__.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/_endian.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/_endian.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/_endian.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,60 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +import sys +from ctypes import * + +_array_type = type(c_int * 3) + +def _other_endian(typ): + """Return the type with the 'other' byte order. Simple types like + c_int and so on already have __ctype_be__ and __ctype_le__ + attributes which contain the types, for more complicated types + only arrays are supported. + """ + try: + return getattr(typ, _OTHER_ENDIAN) + except AttributeError: + if type(typ) == _array_type: + return _other_endian(typ._type_) * typ._length_ + raise TypeError("This type does not support other endian: %s" % typ) + +class _swapped_meta(type(Structure)): + def __setattr__(self, attrname, value): + if attrname == "_fields_": + fields = [] + for desc in value: + name = desc[0] + typ = desc[1] + rest = desc[2:] + fields.append((name, _other_endian(typ)) + rest) + value = fields + super(_swapped_meta, self).__setattr__(attrname, value) + +################################################################ + +# Note: The Structure metaclass checks for the *presence* (not the +# value!) of a _swapped_bytes_ attribute to determine the bit order in +# structures containing bit fields. + +if sys.byteorder == "little": + _OTHER_ENDIAN = "__ctype_be__" + + LittleEndianStructure = Structure + + class BigEndianStructure(Structure): + """Structure with big endian byte order""" + __metaclass__ = _swapped_meta + _swappedbytes_ = None + +elif sys.byteorder == "big": + _OTHER_ENDIAN = "__ctype_le__" + + BigEndianStructure = Structure + class LittleEndianStructure(Structure): + """Structure with little endian byte order""" + __metaclass__ = _swapped_meta + _swappedbytes_ = None + +else: + raise RuntimeError("Invalid byteorder") Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/_endian.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/macholib/README.ctypes =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/macholib/README.ctypes (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/macholib/README.ctypes 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,7 @@ +Files in this directory from from Bob Ippolito's py2app. + +License: Any components of the py2app suite may be distributed under +the MIT or PSF open source licenses. + +This is version 1.0, SVN revision 789, from 2006/01/25. +The main repository is http://svn.red-bean.com/bob/macholib/trunk/macholib/ \ No newline at end of file Added: branches/ctypes-via-rawffi/Lib/ctypes/macholib/__init__.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/macholib/__init__.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/macholib/__init__.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,12 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +""" +Enough Mach-O to make your head spin. + +See the relevant header files in /usr/include/mach-o + +And also Apple's documentation. +""" + +__version__ = '1.0' Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/macholib/__init__.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/macholib/dyld.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/macholib/dyld.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/macholib/dyld.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,169 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +""" +dyld emulation +""" + +import os +from framework import framework_info +from dylib import dylib_info +from itertools import * + +__all__ = [ + 'dyld_find', 'framework_find', + 'framework_info', 'dylib_info', +] + +# These are the defaults as per man dyld(1) +# +DEFAULT_FRAMEWORK_FALLBACK = [ + os.path.expanduser("~/Library/Frameworks"), + "/Library/Frameworks", + "/Network/Library/Frameworks", + "/System/Library/Frameworks", +] + +DEFAULT_LIBRARY_FALLBACK = [ + os.path.expanduser("~/lib"), + "/usr/local/lib", + "/lib", + "/usr/lib", +] + +def ensure_utf8(s): + """Not all of PyObjC and Python understand unicode paths very well yet""" + if isinstance(s, unicode): + return s.encode('utf8') + return s + +def dyld_env(env, var): + if env is None: + env = os.environ + rval = env.get(var) + if rval is None: + return [] + return rval.split(':') + +def dyld_image_suffix(env=None): + if env is None: + env = os.environ + return env.get('DYLD_IMAGE_SUFFIX') + +def dyld_framework_path(env=None): + return dyld_env(env, 'DYLD_FRAMEWORK_PATH') + +def dyld_library_path(env=None): + return dyld_env(env, 'DYLD_LIBRARY_PATH') + +def dyld_fallback_framework_path(env=None): + return dyld_env(env, 'DYLD_FALLBACK_FRAMEWORK_PATH') + +def dyld_fallback_library_path(env=None): + return dyld_env(env, 'DYLD_FALLBACK_LIBRARY_PATH') + +def dyld_image_suffix_search(iterator, env=None): + """For a potential path iterator, add DYLD_IMAGE_SUFFIX semantics""" + suffix = dyld_image_suffix(env) + if suffix is None: + return iterator + def _inject(iterator=iterator, suffix=suffix): + for path in iterator: + if path.endswith('.dylib'): + yield path[:-len('.dylib')] + suffix + '.dylib' + else: + yield path + suffix + yield path + return _inject() + +def dyld_override_search(name, env=None): + # If DYLD_FRAMEWORK_PATH is set and this dylib_name is a + # framework name, use the first file that exists in the framework + # path if any. If there is none go on to search the DYLD_LIBRARY_PATH + # if any. + + framework = framework_info(name) + + if framework is not None: + for path in dyld_framework_path(env): + yield os.path.join(path, framework['name']) + + # If DYLD_LIBRARY_PATH is set then use the first file that exists + # in the path. If none use the original name. + for path in dyld_library_path(env): + yield os.path.join(path, os.path.basename(name)) + +def dyld_executable_path_search(name, executable_path=None): + # If we haven't done any searching and found a library and the + # dylib_name starts with "@executable_path/" then construct the + # library name. + if name.startswith('@executable_path/') and executable_path is not None: + yield os.path.join(executable_path, name[len('@executable_path/'):]) + +def dyld_default_search(name, env=None): + yield name + + framework = framework_info(name) + + if framework is not None: + fallback_framework_path = dyld_fallback_framework_path(env) + for path in fallback_framework_path: + yield os.path.join(path, framework['name']) + + fallback_library_path = dyld_fallback_library_path(env) + for path in fallback_library_path: + yield os.path.join(path, os.path.basename(name)) + + if framework is not None and not fallback_framework_path: + for path in DEFAULT_FRAMEWORK_FALLBACK: + yield os.path.join(path, framework['name']) + + if not fallback_library_path: + for path in DEFAULT_LIBRARY_FALLBACK: + yield os.path.join(path, os.path.basename(name)) + +def dyld_find(name, executable_path=None, env=None): + """ + Find a library or framework using dyld semantics + """ + name = ensure_utf8(name) + executable_path = ensure_utf8(executable_path) + for path in dyld_image_suffix_search(chain( + dyld_override_search(name, env), + dyld_executable_path_search(name, executable_path), + dyld_default_search(name, env), + ), env): + if os.path.isfile(path): + return path + raise ValueError, "dylib %s could not be found" % (name,) + +def framework_find(fn, executable_path=None, env=None): + """ + Find a framework using dyld semantics in a very loose manner. + + Will take input such as: + Python + Python.framework + Python.framework/Versions/Current + """ + try: + return dyld_find(fn, executable_path=executable_path, env=env) + except ValueError, e: + pass + fmwk_index = fn.rfind('.framework') + if fmwk_index == -1: + fmwk_index = len(fn) + fn += '.framework' + fn = os.path.join(fn, os.path.basename(fn[:fmwk_index])) + try: + return dyld_find(fn, executable_path=executable_path, env=env) + except ValueError: + raise e + +def test_dyld_find(): + env = {} + assert dyld_find('libSystem.dylib') == '/usr/lib/libSystem.dylib' + assert dyld_find('System.framework/System') == '/System/Library/Frameworks/System.framework/System' + +if __name__ == '__main__': + test_dyld_find() Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/macholib/dyld.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/macholib/dylib.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/macholib/dylib.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/macholib/dylib.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,66 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +""" +Generic dylib path manipulation +""" + +import re + +__all__ = ['dylib_info'] + +DYLIB_RE = re.compile(r"""(?x) +(?P<location>^.*)(?:^|/) +(?P<name> + (?P<shortname>\w+?) + (?:\.(?P<version>[^._]+))? + (?:_(?P<suffix>[^._]+))? + \.dylib$ +) +""") + +def dylib_info(filename): + """ + A dylib name can take one of the following four forms: + Location/Name.SomeVersion_Suffix.dylib + Location/Name.SomeVersion.dylib + Location/Name_Suffix.dylib + Location/Name.dylib + + returns None if not found or a mapping equivalent to: + dict( + location='Location', + name='Name.SomeVersion_Suffix.dylib', + shortname='Name', + version='SomeVersion', + suffix='Suffix', + ) + + Note that SomeVersion and Suffix are optional and may be None + if not present. + """ + is_dylib = DYLIB_RE.match(filename) + if not is_dylib: + return None + return is_dylib.groupdict() + + +def test_dylib_info(): + def d(location=None, name=None, shortname=None, version=None, suffix=None): + return dict( + location=location, + name=name, + shortname=shortname, + version=version, + suffix=suffix + ) + assert dylib_info('completely/invalid') is None + assert dylib_info('completely/invalide_debug') is None + assert dylib_info('P/Foo.dylib') == d('P', 'Foo.dylib', 'Foo') + assert dylib_info('P/Foo_debug.dylib') == d('P', 'Foo_debug.dylib', 'Foo', suffix='debug') + assert dylib_info('P/Foo.A.dylib') == d('P', 'Foo.A.dylib', 'Foo', 'A') + assert dylib_info('P/Foo_debug.A.dylib') == d('P', 'Foo_debug.A.dylib', 'Foo_debug', 'A') + assert dylib_info('P/Foo.A_debug.dylib') == d('P', 'Foo.A_debug.dylib', 'Foo', 'A', 'debug') + +if __name__ == '__main__': + test_dylib_info() Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/macholib/dylib.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/macholib/fetch_macholib =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/macholib/fetch_macholib (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/macholib/fetch_macholib 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,2 @@ +#!/bin/sh +svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ . Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/macholib/fetch_macholib ___________________________________________________________________ Added: svn:executable + * Added: branches/ctypes-via-rawffi/Lib/ctypes/macholib/framework.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/macholib/framework.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/macholib/framework.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,68 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +""" +Generic framework path manipulation +""" + +import re + +__all__ = ['framework_info'] + +STRICT_FRAMEWORK_RE = re.compile(r"""(?x) +(?P<location>^.*)(?:^|/) +(?P<name> + (?P<shortname>\w+).framework/ + (?:Versions/(?P<version>[^/]+)/)? + (?P=shortname) + (?:_(?P<suffix>[^_]+))? +)$ +""") + +def framework_info(filename): + """ + A framework name can take one of the following four forms: + Location/Name.framework/Versions/SomeVersion/Name_Suffix + Location/Name.framework/Versions/SomeVersion/Name + Location/Name.framework/Name_Suffix + Location/Name.framework/Name + + returns None if not found, or a mapping equivalent to: + dict( + location='Location', + name='Name.framework/Versions/SomeVersion/Name_Suffix', + shortname='Name', + version='SomeVersion', + suffix='Suffix', + ) + + Note that SomeVersion and Suffix are optional and may be None + if not present + """ + is_framework = STRICT_FRAMEWORK_RE.match(filename) + if not is_framework: + return None + return is_framework.groupdict() + +def test_framework_info(): + def d(location=None, name=None, shortname=None, version=None, suffix=None): + return dict( + location=location, + name=name, + shortname=shortname, + version=version, + suffix=suffix + ) + assert framework_info('completely/invalid') is None + assert framework_info('completely/invalid/_debug') is None + assert framework_info('P/F.framework') is None + assert framework_info('P/F.framework/_debug') is None + assert framework_info('P/F.framework/F') == d('P', 'F.framework/F', 'F') + assert framework_info('P/F.framework/F_debug') == d('P', 'F.framework/F_debug', 'F', suffix='debug') + assert framework_info('P/F.framework/Versions') is None + assert framework_info('P/F.framework/Versions/A') is None + assert framework_info('P/F.framework/Versions/A/F') == d('P', 'F.framework/Versions/A/F', 'F', 'A') + assert framework_info('P/F.framework/Versions/A/F_debug') == d('P', 'F.framework/Versions/A/F_debug', 'F', 'A', 'debug') + +if __name__ == '__main__': + test_framework_info() Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/macholib/framework.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/test/__init__.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/test/__init__.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/test/__init__.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,202 @@ +import glob, os, sys, unittest, getopt, time + +use_resources = [] + +class ResourceDenied(Exception): + """Test skipped because it requested a disallowed resource. + + This is raised when a test calls requires() for a resource that + has not be enabled. Resources are defined by test modules. + """ + +def is_resource_enabled(resource): + """Test whether a resource is enabled. + + If the caller's module is __main__ then automatically return True.""" + if sys._getframe().f_back.f_globals.get("__name__") == "__main__": + return True + result = use_resources is not None and \ + (resource in use_resources or "*" in use_resources) + if not result: + _unavail[resource] = None + return result + +_unavail = {} +def requires(resource, msg=None): + """Raise ResourceDenied if the specified resource is not available. + + If the caller's module is __main__ then automatically return True.""" + # see if the caller's module is __main__ - if so, treat as if + # the resource was set + if sys._getframe().f_back.f_globals.get("__name__") == "__main__": + return + if not is_resource_enabled(resource): + if msg is None: + msg = "Use of the `%s' resource not enabled" % resource + raise ResourceDenied(msg) + +def find_package_modules(package, mask): + import fnmatch + if hasattr(package, "__loader__"): + path = package.__name__.replace(".", os.path.sep) + mask = os.path.join(path, mask) + for fnm in package.__loader__._files.iterkeys(): + if fnmatch.fnmatchcase(fnm, mask): + yield os.path.splitext(fnm)[0].replace(os.path.sep, ".") + else: + path = package.__path__[0] + for fnm in os.listdir(path): + if fnmatch.fnmatchcase(fnm, mask): + yield "%s.%s" % (package.__name__, os.path.splitext(fnm)[0]) + +def get_tests(package, mask, verbosity): + """Return a list of skipped test modules, and a list of test cases.""" + tests = [] + skipped = [] + for modname in find_package_modules(package, mask): + try: + mod = __import__(modname, globals(), locals(), ['*']) + except ResourceDenied, detail: + skipped.append(modname) + if verbosity > 1: + print >> sys.stderr, "Skipped %s: %s" % (modname, detail) + continue + except Exception, detail: + print >> sys.stderr, "Warning: could not import %s: %s" % (modname, detail) + continue + for name in dir(mod): + if name.startswith("_"): + continue + o = getattr(mod, name) + if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase): + tests.append(o) + return skipped, tests + +def usage(): + print __doc__ + return 1 + +def test_with_refcounts(runner, verbosity, testcase): + """Run testcase several times, tracking reference counts.""" + import gc + import ctypes + ptc = ctypes._pointer_type_cache.copy() + cfc = ctypes._c_functype_cache.copy() + wfc = ctypes._win_functype_cache.copy() + + # when searching for refcount leaks, we have to manually reset any + # caches that ctypes has. + def cleanup(): + ctypes._pointer_type_cache = ptc.copy() + ctypes._c_functype_cache = cfc.copy() + ctypes._win_functype_cache = wfc.copy() + gc.collect() + + test = unittest.makeSuite(testcase) + for i in range(5): + rc = sys.gettotalrefcount() + runner.run(test) + cleanup() + COUNT = 5 + refcounts = [None] * COUNT + for i in range(COUNT): + rc = sys.gettotalrefcount() + runner.run(test) + cleanup() + refcounts[i] = sys.gettotalrefcount() - rc + if filter(None, refcounts): + print "%s leaks:\n\t" % testcase, refcounts + elif verbosity: + print "%s: ok." % testcase + +class TestRunner(unittest.TextTestRunner): + def run(self, test, skipped): + "Run the given test case or test suite." + # Same as unittest.TextTestRunner.run, except that it reports + # skipped tests. + result = self._makeResult() + startTime = time.time() + test(result) + stopTime = time.time() + timeTaken = stopTime - startTime + result.printErrors() + self.stream.writeln(result.separator2) + run = result.testsRun + if _unavail: #skipped: + requested = _unavail.keys() + requested.sort() + self.stream.writeln("Ran %d test%s in %.3fs (%s module%s skipped)" % + (run, run != 1 and "s" or "", timeTaken, + len(skipped), + len(skipped) != 1 and "s" or "")) + self.stream.writeln("Unavailable resources: %s" % ", ".join(requested)) + else: + self.stream.writeln("Ran %d test%s in %.3fs" % + (run, run != 1 and "s" or "", timeTaken)) + self.stream.writeln() + if not result.wasSuccessful(): + self.stream.write("FAILED (") + failed, errored = map(len, (result.failures, result.errors)) + if failed: + self.stream.write("failures=%d" % failed) + if errored: + if failed: self.stream.write(", ") + self.stream.write("errors=%d" % errored) + self.stream.writeln(")") + else: + self.stream.writeln("OK") + return result + + +def main(*packages): + try: + opts, args = getopt.getopt(sys.argv[1:], "rqvu:") + except getopt.error: + return usage() + + verbosity = 1 + search_leaks = False + for flag, value in opts: + if flag == "-q": + verbosity -= 1 + elif flag == "-v": + verbosity += 1 + elif flag == "-r": + try: + sys.gettotalrefcount + except AttributeError: + print >> sys.stderr, "-r flag requires Python debug build" + return -1 + search_leaks = True + elif flag == "-u": + use_resources.extend(value.split(",")) + + mask = "test_*.py" + if args: + mask = args[0] + + for package in packages: + run_tests(package, mask, verbosity, search_leaks) + + +def run_tests(package, mask, verbosity, search_leaks): + skipped, testcases = get_tests(package, mask, verbosity) + runner = TestRunner(verbosity=verbosity) + + suites = [unittest.makeSuite(o) for o in testcases] + suite = unittest.TestSuite(suites) + result = runner.run(suite, skipped) + + if search_leaks: + # hunt for refcount leaks + runner = BasicTestRunner() + for t in testcases: + test_with_refcounts(runner, verbosity, t) + + return bool(result.errors) + +class BasicTestRunner: + def run(self, test): + result = unittest.TestResult() + test(result) + return result Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/test/__init__.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/test/runtests.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/test/runtests.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/test/runtests.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,17 @@ +"""Usage: runtests.py [-q] [-r] [-v] [-u resources] [mask] + +Run all tests found in this directory, and print a summary of the results. +Command line flags: + -q quiet mode: don't prnt anything while the tests are running + -r run tests repeatedly, look for refcount leaks + -u<resources> + Add resources to the lits of allowed resources. '*' allows all + resources. + -v verbose mode: print the test currently executed + mask mask to select filenames containing testcases, wildcards allowed +""" +import sys +import ctypes.test + +if __name__ == "__main__": + sys.exit(ctypes.test.main(ctypes.test)) Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/test/runtests.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/test/test_anon.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/test/test_anon.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/test/test_anon.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,60 @@ +import unittest +from ctypes import * + +class AnonTest(unittest.TestCase): + + def test_anon(self): + class ANON(Union): + _fields_ = [("a", c_int), + ("b", c_int)] + + class Y(Structure): + _fields_ = [("x", c_int), + ("_", ANON), + ("y", c_int)] + _anonymous_ = ["_"] + + self.failUnlessEqual(Y.a.offset, sizeof(c_int)) + self.failUnlessEqual(Y.b.offset, sizeof(c_int)) + + self.failUnlessEqual(ANON.a.offset, 0) + self.failUnlessEqual(ANON.b.offset, 0) + + def test_anon_nonseq(self): + # TypeError: _anonymous_ must be a sequence + self.failUnlessRaises(TypeError, + lambda: type(Structure)("Name", + (Structure,), + {"_fields_": [], "_anonymous_": 42})) + + def test_anon_nonmember(self): + # AttributeError: type object 'Name' has no attribute 'x' + self.failUnlessRaises(AttributeError, + lambda: type(Structure)("Name", + (Structure,), + {"_fields_": [], + "_anonymous_": ["x"]})) + + def test_nested(self): + class ANON_S(Structure): + _fields_ = [("a", c_int)] + + class ANON_U(Union): + _fields_ = [("_", ANON_S), + ("b", c_int)] + _anonymous_ = ["_"] + + class Y(Structure): + _fields_ = [("x", c_int), + ("_", ANON_U), + ("y", c_int)] + _anonymous_ = ["_"] + + self.failUnlessEqual(Y.x.offset, 0) + self.failUnlessEqual(Y.a.offset, sizeof(c_int)) + self.failUnlessEqual(Y.b.offset, sizeof(c_int)) + self.failUnlessEqual(Y._.offset, sizeof(c_int)) + self.failUnlessEqual(Y.y.offset, sizeof(c_int) * 2) + +if __name__ == "__main__": + unittest.main() Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/test/test_anon.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/test/test_array_in_pointer.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/test/test_array_in_pointer.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/test/test_array_in_pointer.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,64 @@ +import unittest +from ctypes import * +from binascii import hexlify +import re + +def dump(obj): + # helper function to dump memory contents in hex, with a hyphen + # between the bytes. + h = hexlify(buffer(obj)) + return re.sub(r"(..)", r"\1-", h)[:-1] + + +class Value(Structure): + _fields_ = [("val", c_byte)] + +class Container(Structure): + _fields_ = [("pvalues", POINTER(Value))] + +class Test(unittest.TestCase): + def test(self): + # create an array of 4 values + val_array = (Value * 4)() + + # create a container, which holds a pointer to the pvalues array. + c = Container() + c.pvalues = val_array + + # memory contains 4 NUL bytes now, that's correct + self.failUnlessEqual("00-00-00-00", dump(val_array)) + + # set the values of the array through the pointer: + for i in range(4): + c.pvalues[i].val = i + 1 + + values = [c.pvalues[i].val for i in range(4)] + + # These are the expected results: here s the bug! + self.failUnlessEqual( + (values, dump(val_array)), + ([1, 2, 3, 4], "01-02-03-04") + ) + + def test_2(self): + + val_array = (Value * 4)() + + # memory contains 4 NUL bytes now, that's correct + self.failUnlessEqual("00-00-00-00", dump(val_array)) + + ptr = cast(val_array, POINTER(Value)) + # set the values of the array through the pointer: + for i in range(4): + ptr[i].val = i + 1 + + values = [ptr[i].val for i in range(4)] + + # These are the expected results: here s the bug! + self.failUnlessEqual( + (values, dump(val_array)), + ([1, 2, 3, 4], "01-02-03-04") + ) + +if __name__ == "__main__": + unittest.main() Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/test/test_array_in_pointer.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/test/test_arrays.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/test/test_arrays.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/test/test_arrays.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,112 @@ +import unittest +from ctypes import * + +formats = "bBhHiIlLqQfd" + +formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \ + c_long, c_ulonglong, c_float, c_double + +class ArrayTestCase(unittest.TestCase): + def test_simple(self): + # create classes holding simple numeric types, and check + # various properties. + + init = range(15, 25) + + for fmt in formats: + alen = len(init) + int_array = ARRAY(fmt, alen) + + ia = int_array(*init) + # length of instance ok? + self.failUnlessEqual(len(ia), alen) + + # slot values ok? + values = [ia[i] for i in range(len(init))] + self.failUnlessEqual(values, init) + + # change the items + from operator import setitem + new_values = range(42, 42+alen) + [setitem(ia, n, new_values[n]) for n in range(alen)] + values = [ia[i] for i in range(len(init))] + self.failUnlessEqual(values, new_values) + + # are the items initialized to 0? + ia = int_array() + values = [ia[i] for i in range(len(init))] + self.failUnlessEqual(values, [0] * len(init)) + + # Too many in itializers should be caught + self.assertRaises(IndexError, int_array, *range(alen*2)) + + CharArray = ARRAY(c_char, 3) + + ca = CharArray("a", "b", "c") + + # Should this work? It doesn't: + # CharArray("abc") + self.assertRaises(TypeError, CharArray, "abc") + + self.failUnlessEqual(ca[0], "a") + self.failUnlessEqual(ca[1], "b") + self.failUnlessEqual(ca[2], "c") + self.failUnlessEqual(ca[-3], "a") + self.failUnlessEqual(ca[-2], "b") + self.failUnlessEqual(ca[-1], "c") + + self.failUnlessEqual(len(ca), 3) + + # slicing is now supported, but not extended slicing (3-argument)! + from operator import getslice, delitem + self.assertRaises(TypeError, getslice, ca, 0, 1, -1) + + # cannot delete items + self.assertRaises(TypeError, delitem, ca, 0) + + def test_numeric_arrays(self): + + alen = 5 + + numarray = ARRAY(c_int, alen) + + na = numarray() + values = [na[i] for i in range(alen)] + self.failUnlessEqual(values, [0] * alen) + + na = numarray(*[c_int()] * alen) + values = [na[i] for i in range(alen)] + self.failUnlessEqual(values, [0]*alen) + + na = numarray(1, 2, 3, 4, 5) + values = [i for i in na] + self.failUnlessEqual(values, [1, 2, 3, 4, 5]) + + na = numarray(*map(c_int, (1, 2, 3, 4, 5))) + values = [i for i in na] + self.failUnlessEqual(values, [1, 2, 3, 4, 5]) + + def test_classcache(self): + self.failUnless(not ARRAY(c_int, 3) is ARRAY(c_int, 4)) + self.failUnless(ARRAY(c_int, 3) is ARRAY(c_int, 3)) + + def test_from_address(self): + # Failed with 0.9.8, reported by JUrner + p = create_string_buffer("foo") + sz = (c_char * 3).from_address(addressof(p)) + self.failUnlessEqual(sz[:], "foo") + self.failUnlessEqual(sz.value, "foo") + + try: + create_unicode_buffer + except NameError: + pass + else: + def test_from_addressW(self): + p = create_unicode_buffer("foo") + sz = (c_wchar * 3).from_address(addressof(p)) + self.failUnlessEqual(sz[:], "foo") + self.failUnlessEqual(sz.value, "foo") + +if __name__ == '__main__': + unittest.main() Property changes on: branches/ctypes-via-rawffi/Lib/ctypes/test/test_arrays.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/ctypes/test/test_as_parameter.py =================================================================== --- branches/ctypes-via-rawffi/Lib/ctypes/test/test_as_parameter.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/ctypes/test/test_as_parameter.py 2009-04-29 04:39:13 UTC (rev 6276) @@ -0,0 +1,215 @@ +import unittest +from ctypes import * +import _ctypes_test + +dll = CDLL(_ctypes_test.__file__) + +try: + CALLBACK_FUNCTYPE = WINFUNCTYPE +except NameError: + # fake to enable this test on Linux + CALLBACK_FUNCTYPE = CFUNCTYPE + +class POINT(Structure): + _fields_ = [("x", c_int), ("y", c_int)] + +class BasicWrapTestCase(unittest.TestCase): + def wrap(self, param): + return param + + def test_wchar_parm(self): + try: + c_wchar + except NameError: + return + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] + result = f(self.wrap(1), self.wrap(u"x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0)) + self.failUnlessEqual(result, 139) + self.failUnless(type(result), int) + + def test_pointers(self): + f = dll._testfunc_p_p + f.restype = POINTER(c_int) + f.argtypes = [POINTER(c_int)] + + # This only works if the value c_int(42) passed to the + # function is still alive while the pointer (the result) is + # used. + + v = c_int(42) + + self.failUnlessEqual(pointer(v).contents.value, 42) + result = f(self.wrap(pointer(v))) + self.failUnlessEqual(type(result), POINTER(c_int)) + self.failUnlessEqual(result.contents.value, 42) + + # This on works... + result = f(self.wrap(pointer(v))) + self.failUnlessEqual(result.contents.value, v.value) + + p = pointer(c_int(99)) + result = f(self.wrap(p)) + self.failUnlessEqual(result.contents.value, 99) + + def test_shorts(self): + f = dll._testfunc_callback_i_if + + args = [] + expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, + 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1] + + def callback(v): + args.append(v) + return v + + CallBack = CFUNCTYPE(c_int, c_int) + + cb = CallBack(callback) + f(self.wrap(2**18), self.wrap(cb)) + self.failUnlessEqual(args, expected) + + ################################################################ + + def test_callbacks(self): + f = dll._testfunc_callback_i_if + f.restype = c_int + + MyCallback = CFUNCTYPE(c_int, c_int) + + def callback(value): + #print "called back with", value + return value + + cb = MyCallback(callback) + + result = f(self.wrap(-10), self.wrap(cb)) + self.failUnlessEqual(result, -18) + + # test with prototype + f.argtypes = [c_int, MyCallback] + cb = MyCallback(callback) + + result = f(self.wrap(-10), self.wrap(cb)) + self.failUnlessEqual(result, -18) + + result = f(self.wrap(-10), self.wrap(cb)) + self.failUnlessEqual(result, -18) + + AnotherCallback = CALLBACK_FUNCTYPE(c_int, c_int, c_int, c_int, c_int) + + # check that the prototype works: we call f with wrong + # argument types + cb = AnotherCallback(callback) + self.assertRaises(ArgumentError, f, self.wrap(-10), self.wrap(cb)) + + def test_callbacks_2(self): + # Can also use simple datatypes as argument type specifiers + # for the callback function. + # In this case the call receives an instance of that type + f = dll._testfunc_callback_i_if + f.restype = c_int + + MyCallback = CFUNCTYPE(c_int, c_int) + + f.argtypes = [c_int, MyCallback] + + def callback(value): + #print "called back with", value + self.failUnlessEqual(type(value), int) + return value + + cb = MyCallback(callback) + result = f(self.wrap(-10), self.wrap(cb)) + self.failUnlessEqual(result, -18) + + def test_longlong_callbacks(self): + + f = dll._testfunc_callback_q_qf + f.restype = c_longlong + + MyCallback = CFUNCTYPE(c_longlong, c_longlong) ... [truncated message content] |
From: <fi...@us...> - 2009-04-29 04:36:07
|
Revision: 6275 http://jython.svn.sourceforge.net/jython/?rev=6275&view=rev Author: fijal Date: 2009-04-29 04:36:03 +0000 (Wed, 29 Apr 2009) Log Message: ----------- ignore java security for now. Modified Paths: -------------- branches/ctypes-via-rawffi/registry Modified: branches/ctypes-via-rawffi/registry =================================================================== --- branches/ctypes-via-rawffi/registry 2009-04-29 04:35:18 UTC (rev 6274) +++ branches/ctypes-via-rawffi/registry 2009-04-29 04:36:03 UTC (rev 6275) @@ -42,7 +42,7 @@ # Setting this to false will allow Jython to provide access to # non-public fields, methods, and constructors of Java objects. -python.security.respectJavaAccessibility = true +python.security.respectJavaAccessibility = false # Setting this to true will force Jython will use the first module # found on sys.path where java File.isFile() returns true. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fi...@us...> - 2009-04-29 04:35:26
|
Revision: 6274 http://jython.svn.sourceforge.net/jython/?rev=6274&view=rev Author: fijal Date: 2009-04-29 04:35:18 +0000 (Wed, 29 Apr 2009) Log Message: ----------- Progress on _rawffi. Supports more types (short, int, char), sizes are hardcoded so far. Rudimentary support for other things, enough to import slightly modified ctypes Modified Paths: -------------- branches/ctypes-via-rawffi/Lib/_rawffi.py branches/ctypes-via-rawffi/Lib/test/test__rawffi.py Modified: branches/ctypes-via-rawffi/Lib/_rawffi.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_rawffi.py 2009-04-29 04:34:08 UTC (rev 6273) +++ branches/ctypes-via-rawffi/Lib/_rawffi.py 2009-04-29 04:35:18 UTC (rev 6274) @@ -1,57 +1,204 @@ import com.sun.jna as jna +from java.lang import Short, Character +import sys def get_libc(): return CDLL("c") -typecode_map = {'h': 2, 'H': 2} +FUNCFLAG_STDCALL = 0 +FUNCFLAG_CDECL = 1 # for WINAPI calls +FUNCFLAG_PYTHONAPI = 4 +# XXX hardcoded +typecode_map = {'h': 2, 'H': 2, + 'c': 1, 'p': 4, + 's': 4, 'P': 4, + 'i': 4, 'O': 4, + 'l': 4, 'L': 4, + 'f': 4, 'd': 8, + 'q': 8, 'Q': 8, + 'b': 1, 'B': 1, + 'z': 4, 'Z': 4, + 'u': 2} + +# set up of machine internals +_bits = 0 +_itest = 1 +_Ltest = 1L +while _itest == _Ltest and type(_itest) is int: + _itest *= 2 + _Ltest *= 2 + _bits += 1 + +LONG_BIT = _bits+1 +LONG_MASK = _Ltest*2-1 +LONG_TEST = _Ltest + +def intmask(n): + if isinstance(n, int): + return int(n) # possibly bool->int + n = long(n) + n &= LONG_MASK + if n >= LONG_TEST: + n -= 2*LONG_TEST + return int(n) + class Array(object): def __init__(self, typecode): self.typecode = typecode self.itemsize = typecode_map[typecode] - def __call__(self, size, autofree=False): + def allocate(self, size, autofree=False): if not autofree: - raise Exception + return ArrayInstanceNoAutoFree(self, size) return ArrayInstance(self, size) -class ArrayInstance(object): + def __call__(self, size, items=None, autofree=False): + res = self.allocate(size, autofree) + if items is not None: + for i, item in enumerate(items): + res[i] = item + return res + + def size_alignment(self, lgt): + return sizeof(self.typecode) * lgt, alignment(self.typecode) + +class ArrayInstanceNoAutoFree(object): def __init__(self, shape, size): self.shape = shape - self.alloc = jna.Memory(shape.itemsize * size) + self.alloc = jna.Pointer(jna.Memory.malloc(size * shape.itemsize)) def __setitem__(self, index, value): - self.alloc.setShort(index, value) + if self.shape.itemsize == 1: + self.alloc.setByte(index, ord(value)) + elif self.shape.itemsize == 2: + self.alloc.setShort(index, value) + elif self.shape.itemsize == 4: + self.alloc.setInt(index, value) + else: + xxx def __getitem__(self, index): - return self.alloc.getShort(index) + if self.shape.itemsize == 1: + return chr(self.alloc.getByte(index)) + elif self.shape.itemsize == 2: + return self.alloc.getShort(index) + elif self.shape.itemsize == 4: + return self.alloc.getInt(index) + else: + xxx + def free(self): + jna.Memory.free(self.alloc.peer) + + def byptr(self): + a = Array('p')(1) + a[0] = intmask(self.alloc.peer) + return a + + def getbuffer(self): + return self.alloc.peer + + def setbuffer(self, i): + self.alloc.peer = i + + buffer = property(getbuffer, setbuffer) + +class ArrayInstance(ArrayInstanceNoAutoFree): + def __del__(self): + self.free() + class FuncPtr(object): - def __init__(self, fn, name, argtypes, restype): - self.fn = fn - self.name = name + def __init__(self, fn, argtypes, restype, flags=0): + if isinstance(fn, (int, long)): + self.fn = jna.Function(jna.Pointer(fn), FUNCFLAG_STDCALL) + else: + self.fn = fn self.argtypes = argtypes self.restype = restype def __call__(self, *args): - container = Array('H')(1, autofree=True) - container[0] = self.fn.invokeInt([i[0] for i in args]) + container = Array(self.restype)(1, autofree=True) + _args = [self._convert(t, i[0]) for t, i in zip(self.argtypes, args)] + res = self.fn.invokeInt(_args) + if self.restype == 'c': + container[0] = chr(res) + else: + container[0] = res + return container + + def byptr(self): + a = Array('p')(1) + a[0] = intmask(self.fn.peer) + return a + def _convert(self, t, v): + if t == 'c': + return Character(v) + elif t == 'h': + return Short(v) + return v + +# XXX dummy obj +class CallbackPtr(object): + def __init__(self, tp, callable, args, result): + pass + + def byptr(self): + a = Array('p')(1) + a[0] = 0 + return a + class CDLL(object): def __init__(self, libname): self.lib = jna.NativeLibrary.getInstance(libname) self.cache = dict() - def ptr(self, name, argtypes, restype): + def ptr(self, name, argtypes, restype, flags=0): key = (name, tuple(argtypes), restype) try: return self.cache[key] except KeyError: fn = self.lib.getFunction(name) - fnp = FuncPtr(fn, name, argtypes, restype) + fnp = FuncPtr(fn, argtypes, restype, flags) self.cache[key] = fnp return fnp + def getaddressindll(self, symbol): + return self.lib.getFunction(symbol).peer +def sizeof(s): + return typecode_map[s] +def alignment(s): + return 1 + +def charp2string(s_p): + if s_p == 0: + return None + a = jna.Memory() + a.size = sys.maxint + a.peer = s_p + i = 0 + l = [] + while True: + c = chr(a.getByte(i)) + if c == '\x00': + return ''.join(l) + l.append(c) + i += 1 + +def charp2rawstring(s_p, size=-1): + if size == -1: + return charp2string(s_p) + else: + a = jna.Memory() + a.size = sys.maxint + a.peer = s_p + l = [] + for i in range(size): + c = chr(a.getByte(i)) + l.append(c) + i += 1 + return ''.join(l) Modified: branches/ctypes-via-rawffi/Lib/test/test__rawffi.py =================================================================== --- branches/ctypes-via-rawffi/Lib/test/test__rawffi.py 2009-04-29 04:34:08 UTC (rev 6273) +++ branches/ctypes-via-rawffi/Lib/test/test__rawffi.py 2009-04-29 04:35:18 UTC (rev 6274) @@ -3,11 +3,11 @@ # xxx - forces a skip in the case we haven't built ctypes_test module in ant (which is not yet a task as of now) -try: - import _rawffi - _rawffi.CDLL("ctypes_test") -except: - raise ImportError +#try: +import _rawffi +_rawffi.CDLL("ctypes_test") +#except: +# raise ImportError class RawFFITestCase(unittest.TestCase): @@ -47,6 +47,61 @@ #arg1.free() #arg2.free() + def test_short_addition_no_autofree(self): + import _rawffi + lib = _rawffi.CDLL(self.lib_name) + short_add = lib.ptr('add_shorts', ['h', 'h'], 'H') + A = _rawffi.Array('h') + arg1 = A(1) + arg2 = A(1) + arg1[0] = 1 + arg2[0] = 2 + res = short_add(arg1, arg2) + assert res[0] == 3 + arg1.free() + arg2.free() + + def test_getchar(self): + import _rawffi + lib = _rawffi.CDLL(self.lib_name) + get_char = lib.ptr('get_char', ['P', 'H'], 'c') + A = _rawffi.Array('c') + B = _rawffi.Array('H') + dupa = A(5, 'dupa') + dupaptr = dupa.byptr() + for i in range(4): + intptr = B(1) + intptr[0] = i + res = get_char(dupaptr, intptr) + assert res[0] == 'dupa'[i] + intptr.free() + dupaptr.free() + dupa.free() + + def test_returning_str(self): + import _rawffi + lib = _rawffi.CDLL(self.lib_name) + char_check = lib.ptr('char_check', ['c', 'c'], 's') + A = _rawffi.Array('c') + arg1 = A(1) + arg2 = A(1) + arg1[0] = 'y' + arg2[0] = 'x' + res = char_check(arg1, arg2) + assert _rawffi.charp2string(res[0]) == 'xxxxxx' + assert _rawffi.charp2rawstring(res[0]) == 'xxxxxx' + assert _rawffi.charp2rawstring(res[0], 3) == 'xxx' + a = A(6, 'xx\x00\x00xx') + assert _rawffi.charp2string(a.buffer) == 'xx' + assert _rawffi.charp2rawstring(a.buffer, 4) == 'xx\x00\x00' + arg1[0] = 'x' + arg2[0] = 'y' + res = char_check(arg1, arg2) + assert res[0] == 0 + assert _rawffi.charp2string(res[0]) is None + arg1.free() + arg2.free() + def test_main(): tests = [RawFFITestCase, ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fi...@us...> - 2009-04-29 04:34:13
|
Revision: 6273 http://jython.svn.sourceforge.net/jython/?rev=6273&view=rev Author: fijal Date: 2009-04-29 04:34:08 +0000 (Wed, 29 Apr 2009) Log Message: ----------- a document about ctypes keepalives. Found out by trial-error-read source code -repeat cycle. Added Paths: ----------- branches/ctypes-via-rawffi/Lib/_ctypes/keepalive.txt Added: branches/ctypes-via-rawffi/Lib/_ctypes/keepalive.txt =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/keepalive.txt (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/keepalive.txt 2009-04-29 04:34:08 UTC (rev 6273) @@ -0,0 +1,34 @@ + +Few rules about ctypes keepalives: + +* Ownership: the memory is freed when owner of this memory is deleted. + Owner is the one who allocated the memory. So if we have: + + a = c_int(3) + b = c_int.from_address(a._buffer.buffer) # pypy notion of address access + + only a frees memory. + +* _objects: each ctypes object has (eventually) _objects dictionary in which + it simply keeps objects to be kept alive. + +* there are (some) rules about when to put stuff in it's objects when + accessing the fields etc. need to list them here. + + * each object has _objects dictionary. In this dict stuff is stored per + key, which should be a tuple of indices of storages. + +places storing stuff in _objects: + +* array item assignement, if we share the storage + +* pointer item assignement, if we share the storage + +* getitem on CDLL stores function pointer + +* CFuncPtr.__new__ (assuming that it's a ctypes callable), stores itself + (XXX???) + +* set contents on pointer + +* set value on primitive or __init__ on primitive Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/keepalive.txt ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fi...@us...> - 2009-04-29 04:33:28
|
Revision: 6272 http://jython.svn.sourceforge.net/jython/?rev=6272&view=rev Author: fijal Date: 2009-04-29 04:33:26 +0000 (Wed, 29 Apr 2009) Log Message: ----------- svn:ignore properties (*.class and *.pyc) Property Changed: ---------------- branches/ctypes-via-rawffi/Lib/_ctypes/ Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes ___________________________________________________________________ Added: svn:ignore + *.class *.pyc This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fi...@us...> - 2009-04-29 04:32:31
|
Revision: 6271 http://jython.svn.sourceforge.net/jython/?rev=6271&view=rev Author: fijal Date: 2009-04-29 04:32:23 +0000 (Wed, 29 Apr 2009) Log Message: ----------- Import _ctypes from PyPy. A verbatim copy instead of svn:external, no good reason for that I suppose Added Paths: ----------- branches/ctypes-via-rawffi/Lib/_ctypes/ branches/ctypes-via-rawffi/Lib/_ctypes/__init__.py branches/ctypes-via-rawffi/Lib/_ctypes/array.py branches/ctypes-via-rawffi/Lib/_ctypes/basics.py branches/ctypes-via-rawffi/Lib/_ctypes/builtin.py branches/ctypes-via-rawffi/Lib/_ctypes/dll.py branches/ctypes-via-rawffi/Lib/_ctypes/dummy.py branches/ctypes-via-rawffi/Lib/_ctypes/function.py branches/ctypes-via-rawffi/Lib/_ctypes/pointer.py branches/ctypes-via-rawffi/Lib/_ctypes/primitive.py branches/ctypes-via-rawffi/Lib/_ctypes/structure.py branches/ctypes-via-rawffi/Lib/_ctypes/union.py Added: branches/ctypes-via-rawffi/Lib/_ctypes/__init__.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/__init__.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/__init__.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,26 @@ +from _ctypes.dummy import resize +from _ctypes.basics import _CData, sizeof, alignment, byref, addressof,\ + ArgumentError, COMError +from _ctypes.primitive import _SimpleCData +from _ctypes.pointer import _Pointer, _cast_addr +from _ctypes.function import CFuncPtr +from _ctypes.dll import dlopen +from _ctypes.structure import Structure +from _ctypes.array import Array +from _ctypes.builtin import _memmove_addr, _string_at_addr, _memset_addr,\ + set_conversion_mode, _wstring_at_addr +from _ctypes.union import Union + +import os as _os + +if _os.name in ("nt", "ce"): + from _rawffi import FormatError + from _rawffi import check_HRESULT as _check_HRESULT + CopyComPointer = None # XXX + +from _rawffi import FUNCFLAG_STDCALL, FUNCFLAG_CDECL, FUNCFLAG_PYTHONAPI + +__version__ = '1.0.3' +#XXX platform dependant? +RTLD_LOCAL = 0 +RTLD_GLOBAL = 256 Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/__init__.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/array.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/array.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/array.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,209 @@ + +import _rawffi + +from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof +from _ctypes.basics import keepalive_key, store_reference, ensure_objects +from _ctypes.basics import CArgObject +from _ctypes.builtin import _string_at_addr, _wstring_at_addr + +def _create_unicode(buffer, maxlength): + res = [] + for i in range(maxlength): + if buffer[i] == '\x00': + break + res.append(buffer[i]) + return u''.join(res) + +class ArrayMeta(_CDataMeta): + def __new__(self, name, cls, typedict): + res = type.__new__(self, name, cls, typedict) + if '_type_' in typedict: + ffiarray = _rawffi.Array(typedict['_type_']._ffishape) + res._ffiarray = ffiarray + subletter = getattr(typedict['_type_'], '_type_', None) + if subletter == 'c': + def getvalue(self): + return _rawffi.charp2string(self._buffer.buffer, + self._length_) + def setvalue(self, val): + # we don't want to have buffers here + if len(val) > self._length_: + raise ValueError("%r too long" % (val,)) + for i in range(len(val)): + self[i] = val[i] + if len(val) < self._length_: + self[len(val)] = '\x00' + res.value = property(getvalue, setvalue) + + def getraw(self): + return "".join([self[i] for i in range(self._length_)]) + + def setraw(self, buffer): + for i in range(len(buffer)): + self[i] = buffer[i] + res.raw = property(getraw, setraw) + elif subletter == 'u': + def getvalue(self): + # rawffi support anyone? + return _create_unicode(self._buffer, self._length_) + + def setvalue(self, val): + # we don't want to have buffers here + if len(val) > self._length_: + raise ValueError("%r too long" % (val,)) + for i in range(len(val)): + self[i] = val[i] + if len(val) < self._length_: + self[len(val)] = '\x00' + res.value = property(getvalue, setvalue) + + if '_length_' in typedict: + res._ffishape = (ffiarray, typedict['_length_']) + res._fficompositesize = res._sizeofinstances() + else: + res._ffiarray = None + return res + + from_address = cdata_from_address + + def _sizeofinstances(self): + size, alignment = self._ffiarray.size_alignment(self._length_) + return size + + def _alignmentofinstances(self): + return self._type_._alignmentofinstances() + + def _CData_output(self, resarray, base=None, index=-1): + # this seems to be a string if we're array of char, surprise! + from ctypes import c_char, c_wchar, c_char_p, c_wchar_p + if self._type_ is c_char: + return _rawffi.charp2string(resarray.buffer, self._length_) + if self._type_ is c_wchar: + xxx + res = self.__new__(self) + ffiarray = self._ffiarray.fromaddress(resarray.buffer, self._length_) + res._buffer = ffiarray + res._base = base + res._index = index + return res + + def _CData_retval(self, resbuffer): + raise NotImplementedError + + def _CData_value(self, value): + # array accepts very strange parameters as part of structure + # or function argument... + from ctypes import c_char, c_wchar + if issubclass(self._type_, (c_char, c_wchar)): + if isinstance(value, basestring): + if len(value) > self._length_: + raise ValueError("Invalid length") + value = self(*value) + else: + if isinstance(value, tuple): + if len(value) > self._length_: + raise RuntimeError("Invalid length") + value = self(*value) + return _CDataMeta._CData_value(self, value) + +def array_get_slice_params(self, index): + if index.step is not None: + raise TypeError("3 arg slices not supported (for no reason)") + start = index.start or 0 + stop = index.stop or self._length_ + return start, stop + +def array_slice_setitem(self, index, value): + start, stop = self._get_slice_params(index) + if stop - start != len(value): + raise ValueError("Can only assign slices of the same length") + for i in range(start, stop): + self[i] = value[i - start] + +def array_slice_getitem(self, index): + start, stop = self._get_slice_params(index) + l = [self[i] for i in range(start, stop)] + letter = getattr(self._type_, '_type_', None) + if letter == 'c': + return "".join(l) + if letter == 'u': + return u"".join(l) + return l + +class Array(_CData): + __metaclass__ = ArrayMeta + _ffiargshape = 'P' + + def __init__(self, *args): + self._buffer = self._ffiarray(self._length_, autofree=True) + for i, arg in enumerate(args): + self[i] = arg + + def _fix_index(self, index): + if index < 0: + index += self._length_ + if 0 <= index < self._length_: + return index + else: + raise IndexError + + _get_slice_params = array_get_slice_params + _slice_getitem = array_slice_getitem + _slice_setitem = array_slice_setitem + + def _subarray(self, index): + """Return a _rawffi array of length 1 whose address is the same as + the index'th item of self.""" + address = self._buffer.itemaddress(index) + return self._ffiarray.fromaddress(address, 1) + + def __setitem__(self, index, value): + if isinstance(index, slice): + self._slice_setitem(index, value) + return + index = self._fix_index(index) + if ensure_objects(value) is not None: + store_reference(self, index, value._objects) + arg = self._type_._CData_value(value) + if self._type_._fficompositesize is None: + self._buffer[index] = arg + # something more sophisticated, cannot set field directly + else: + from ctypes import memmove + dest = self._buffer.itemaddress(index) + memmove(dest, arg, self._type_._fficompositesize) + + def __getitem__(self, index): + if isinstance(index, slice): + return self._slice_getitem(index) + index = self._fix_index(index) + return self._type_._CData_output(self._subarray(index), self, index) + + def __len__(self): + return self._length_ + + def _get_buffer_for_param(self): + return CArgObject(self._buffer.byptr()) + + def _get_buffer_value(self): + return self._buffer.buffer + +ARRAY_CACHE = {} + +def create_array_type(base, length): + if not isinstance(length, (int, long)): + raise TypeError("Can't multiply a ctypes type by a non-integer") + if length < 0: + raise ValueError("Array length must be >= 0") + key = (base, length) + try: + return ARRAY_CACHE[key] + except KeyError: + name = "%s_Array_%d" % (base.__name__, length) + tpdict = dict( + _length_ = length, + _type_ = base + ) + cls = ArrayMeta(name, (Array,), tpdict) + ARRAY_CACHE[key] = cls + return cls Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/array.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/basics.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/basics.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/basics.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,166 @@ + +import _rawffi +import sys + +keepalive_key = str # XXX fix this when provided with test + +def ensure_objects(where): + try: + ensure = where._ensure_objects + except AttributeError: + return None + return ensure() + +def store_reference(where, base_key, target): + if '_index' not in where.__dict__: + # shortcut + where._ensure_objects()[str(base_key)] = target + return + key = [base_key] + while '_index' in where.__dict__: + key.append(where.__dict__['_index']) + where = where.__dict__['_base'] + real_key = ":".join([str(i) for i in key]) + where._ensure_objects()[real_key] = target + +class ArgumentError(Exception): + pass + +class COMError(Exception): + "Raised when a COM method call failed." + def __init__(self, hresult, text, details): + self.args = (hresult, text, details) + self.hresult = hresult + self.text = text + self.details = details + +class _CDataMeta(type): + def from_param(self, value): + if isinstance(value, self): + return value + try: + as_parameter = value._as_parameter_ + except AttributeError: + raise TypeError("expected %s instance instead of %s" % ( + self.__name__, type(value).__name__)) + else: + return self.from_param(as_parameter) + + def _CData_input(self, value): + """Used when data enters into ctypes from user code. 'value' is + some user-specified Python object, which is converted into a _rawffi + array of length 1 containing the same value according to the + type 'self'. + """ + cobj = self.from_param(value) + return cobj, cobj._get_buffer_for_param() + + def _CData_value(self, value): + cobj = self.from_param(value) + # we don't care here if this stuff will live afterwards, as we're + # interested only in value anyway + return cobj._get_buffer_value() + + def _CData_output(self, resbuffer, base=None, index=-1): + #assert isinstance(resbuffer, _rawffi.ArrayInstance) + """Used when data exits ctypes and goes into user code. + 'resbuffer' is a _rawffi array of length 1 containing the value, + and this returns a general Python object that corresponds. + """ + res = self.__new__(self) + res.__dict__['_buffer'] = resbuffer + res.__dict__['_base'] = base + res.__dict__['_index'] = index + return res + + def _CData_retval(self, resbuffer): + return self._CData_output(resbuffer) + + def __mul__(self, other): + from _ctypes.array import create_array_type + return create_array_type(self, other) + + __rmul__ = __mul__ + + def _is_pointer_like(self): + return False + + def in_dll(self, dll, name): + return self.from_address(dll._handle.getaddressindll(name)) + +class CArgObject(object): + """ simple wrapper around buffer, just for the case of freeing + it afterwards + """ + def __init__(self, buffer): + self._buffer = buffer + + def __del__(self): + self._buffer.free() + self._buffer = None + +class _CData(object): + """ The most basic object for all ctypes types + """ + __metaclass__ = _CDataMeta + _objects = None + + def __init__(self, *args, **kwds): + raise TypeError("%s has no type" % (type(self),)) + + def _ensure_objects(self): + if '_objects' not in self.__dict__: + if '_index' in self.__dict__: + return None + self.__dict__['_objects'] = {} + return self._objects + + def __ctypes_from_outparam__(self): + return self + + def _get_buffer_for_param(self): + return self + + def _get_buffer_value(self): + return self._buffer[0] + + def __buffer__(self): + return buffer(self._buffer) + + def _get_b_base(self): + return self._objects + _b_base_ = property(_get_b_base) + _b_needsfree_ = False + +def sizeof(tp): + if not isinstance(tp, _CDataMeta): + if isinstance(tp, _CData): + tp = type(tp) + else: + raise TypeError("ctypes type or instance expected, got %r" % ( + type(tp).__name__,)) + return tp._sizeofinstances() + +def alignment(tp): + if not isinstance(tp, _CDataMeta): + if isinstance(tp, _CData): + tp = type(tp) + else: + raise TypeError("ctypes type or instance expected, got %r" % ( + type(tp).__name__,)) + return tp._alignmentofinstances() + +def byref(cdata): + from ctypes import pointer + return pointer(cdata) + +def cdata_from_address(self, address): + # fix the address, in case it's unsigned + address = address & (sys.maxint * 2 + 1) + instance = self.__new__(self) + lgt = getattr(self, '_length_', 1) + instance._buffer = self._ffiarray.fromaddress(address, lgt) + return instance + +def addressof(tp): + return tp._buffer.buffer Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/basics.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/builtin.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/builtin.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/builtin.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,35 @@ + +import _rawffi, sys + +class ConvMode: + encoding = 'ascii' + errors = 'strict' + +_memmove_addr = _rawffi.get_libc().getaddressindll('memmove') +_memset_addr = _rawffi.get_libc().getaddressindll('memset') + +def _string_at_addr(addr, lgt): + # address here can be almost anything + import ctypes + arg = ctypes.c_char_p._CData_value(addr) + return _rawffi.charp2rawstring(arg, lgt) + +def set_conversion_mode(encoding, errors): + old_cm = ConvMode.encoding, ConvMode.errors + ConvMode.errors = errors + ConvMode.encoding = encoding + return old_cm + +def _wstring_at_addr(addr, lgt): + import ctypes + arg = ctypes.c_wchar_p._CData_value(addr) + # XXX purely applevel + if lgt == -1: + lgt = sys.maxint + a = _rawffi.Array('u').fromaddress(arg, lgt) + res = [] + for i in xrange(lgt): + if lgt == sys.maxint and a[i] == '\x00': + break + res.append(a[i]) + return u''.join(res) Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/builtin.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/dll.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/dll.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/dll.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,7 @@ +import _rawffi + +def dlopen(name, mode): + # XXX mode is ignored + if name is None: + return None # XXX this should return *all* loaded libs, dlopen(NULL) + return _rawffi.CDLL(name) Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/dll.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/dummy.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/dummy.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/dummy.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,5 @@ +def dummyfunc(*args, **kwargs): + raise NotImplementedError("non-implemented ctypes function") + +resize = dummyfunc + Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/dummy.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/function.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/function.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/function.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,368 @@ + +from _ctypes.basics import _CData, _CDataMeta, ArgumentError, keepalive_key +import _rawffi +import sys +import traceback + +# XXX this file needs huge refactoring I fear + +PARAMFLAG_FIN = 0x1 +PARAMFLAG_FOUT = 0x2 +PARAMFLAG_FLCID = 0x4 +def get_com_error(errcode, riid, pIunk): + "Win32 specific: build a COM Error exception" + # XXX need C support code + from _ctypes import COMError + return COMError(errcode, None, None) + +class CFuncPtrType(_CDataMeta): + # XXX write down here defaults and such things + + def _sizeofinstances(self): + return _rawffi.sizeof('P') + + def _alignmentofinstances(self): + return _rawffi.alignment('P') + + def _is_pointer_like(self): + return True + +class CFuncPtr(_CData): + __metaclass__ = CFuncPtrType + + _argtypes_ = None + _restype_ = None + _flags_ = 0 + _ffiargshape = 'P' + _ffishape = 'P' + _fficompositesize = None + _needs_free = False + callable = None + _ptr = None + _buffer = None + # win32 COM properties + _paramflags = None + _com_index = None + _com_iid = None + + def _getargtypes(self): + return self._argtypes_ + def _setargtypes(self, argtypes): + self._ptr = None + self._argtypes_ = argtypes + argtypes = property(_getargtypes, _setargtypes) + + def _getrestype(self): + return self._restype_ + def _setrestype(self, restype): + self._ptr = None + from ctypes import c_char_p + if restype is int: + from ctypes import c_int + restype = c_int + if not isinstance(restype, _CDataMeta) and not restype is None and \ + not callable(restype): + raise TypeError("Expected ctypes type, got %s" % (restype,)) + self._restype_ = restype + def _delrestype(self): + self._ptr = None + del self._restype_ + restype = property(_getrestype, _setrestype, _delrestype) + + def _ffishapes(self, args, restype): + argtypes = [arg._ffiargshape for arg in args] + if restype is not None: + restype = restype._ffiargshape + else: + restype = 'O' # void + return argtypes, restype + + def __init__(self, *args): + self.name = None + self._objects = {keepalive_key(0):self} + self._needs_free = True + argument = None + if len(args) == 1: + argument = args[0] + + if isinstance(argument, (int, long)): + # direct construction from raw address + ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) + self._ptr = _rawffi.FuncPtr(argument, ffiargs, ffires, + self._flags_) + self._buffer = self._ptr.byptr() + elif callable(argument): + # A callback into python + self.callable = argument + ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) + self._ptr = _rawffi.CallbackPtr(self._wrap_callable(argument, + self.argtypes), + ffiargs, ffires, self._flags_) + self._buffer = self._ptr.byptr() + elif isinstance(argument, tuple) and len(argument) == 2: + # function exported from a shared library + import ctypes + self.name, self.dll = argument + if isinstance(self.dll, str): + self.dll = ctypes.CDLL(self.dll) + # we need to check dll anyway + ptr = self._getfuncptr([], ctypes.c_int) + self._buffer = ptr.byptr() + + elif (sys.platform == 'win32' and + len(args) >= 2 and isinstance(args[0], (int, long))): + # A COM function call, by index + ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) + self._com_index = args[0] + 0x1000 + self.name = args[1] + if len(args) > 2: + self._paramflags = args[2] + # XXX ignored iid = args[3] + + elif len(args) == 0: + # Empty function object. + # this is needed for casts + self._buffer = _rawffi.Array('P')(1) + return + else: + raise TypeError("Unknown constructor %s" % (args,)) + + def _wrap_callable(self, to_call, argtypes): + def f(*args): + if argtypes: + args = [argtype._CData_retval(argtype.from_address(arg)._buffer) + for argtype, arg in zip(argtypes, args)] + return to_call(*args) + return f + + def __call__(self, *args): + if self.callable is not None: + try: + res = self.callable(*args) + except: + exc_info = sys.exc_info() + traceback.print_tb(exc_info[2], file=sys.stderr) + print >>sys.stderr, "%s: %s" % (exc_info[0].__name__, exc_info[1]) + return 0 + if self._restype_ is not None: + return res + return + argtypes = self._argtypes_ + + if self._com_index: + from ctypes import cast, c_void_p, POINTER + thisarg = cast(args[0], POINTER(POINTER(c_void_p))).contents + argtypes = [c_void_p] + list(argtypes) + args = list(args) + args[0] = args[0].value + else: + thisarg = None + + if argtypes is None: + argtypes = self._guess_argtypes(args) + argtypes, argsandobjs = self._wrap_args(argtypes, args) + + restype = self._restype_ + funcptr = self._getfuncptr(argtypes, restype, thisarg) + resbuffer = funcptr(*[arg._buffer for _, arg in argsandobjs]) + return self._build_result(restype, resbuffer, argtypes, argsandobjs) + + def _getfuncptr(self, argtypes, restype, thisarg=None): + if self._ptr is not None: + return self._ptr + if restype is None or not isinstance(restype, _CDataMeta): + import ctypes + restype = ctypes.c_int + argshapes = [arg._ffiargshape for arg in argtypes] + resshape = restype._ffiargshape + if self._buffer is not None: + ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape, + self._flags_) + if argtypes is self._argtypes_: + self._ptr = ptr + return ptr + + if self._com_index: + # extract the address from the object's virtual table + if not thisarg: + raise ValueError("COM method call without VTable") + ptr = thisarg[self._com_index - 0x1000] + return _rawffi.FuncPtr(ptr, argshapes, resshape, self._flags_) + + cdll = self.dll._handle + try: + return cdll.ptr(self.name, argshapes, resshape, self._flags_) + except AttributeError: + if self._flags_ & _rawffi.FUNCFLAG_CDECL: + raise + + # For stdcall, try mangled names: + # funcname -> _funcname@<n> + # where n is 0, 4, 8, 12, ..., 128 + for i in range(33): + mangled_name = "_%s@%d" % (self.name, i*4) + try: + return cdll.ptr(mangled_name, argshapes, resshape, + self._flags_) + except AttributeError: + pass + raise + + @staticmethod + def _guess_argtypes(args): + from _ctypes import _CData + from ctypes import c_char_p, c_wchar_p, c_void_p, c_int + from ctypes import Array, Structure + res = [] + for arg in args: + if hasattr(arg, '_as_parameter_'): + arg = arg._as_parameter_ + if isinstance(arg, str): + res.append(c_char_p) + elif isinstance(arg, unicode): + res.append(c_wchar_p) + elif isinstance(arg, _CData): + res.append(type(arg)) + elif arg is None: + res.append(c_void_p) + #elif arg == 0: + # res.append(c_void_p) + elif isinstance(arg, (int, long)): + res.append(c_int) + else: + raise TypeError("Don't know how to handle %s" % (arg,)) + return res + + def _wrap_args(self, argtypes, args): + wrapped_args = [] + consumed = 0 + for i, argtype in enumerate(argtypes): + defaultvalue = None + if i > 0 and self._paramflags is not None: + paramflag = self._paramflags[i-1] + if len(paramflag) == 2: + idlflag, name = paramflag + elif len(paramflag) == 3: + idlflag, name, defaultvalue = paramflag + else: + idlflag = 0 + idlflag &= (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID) + + if idlflag in (0, PARAMFLAG_FIN): + pass + elif idlflag == PARAMFLAG_FOUT: + import ctypes + val = argtype._type_() + wrapped = (val, ctypes.byref(val)) + wrapped_args.append(wrapped) + continue + elif idlflag == PARAMFLAG_FIN | PARAMFLAG_FLCID: + # Always taken from defaultvalue if given, + # else the integer 0. + val = defaultvalue + if val is None: + val = 0 + wrapped = argtype._CData_input(val) + wrapped_args.append(wrapped) + continue + else: + raise NotImplementedError( + "paramflags = %s" % (self._paramflags[i-1],)) + + if consumed < len(args): + arg = args[consumed] + elif defaultvalue is not None: + arg = defaultvalue + else: + raise TypeError("Not enough arguments") + + try: + wrapped = argtype._CData_input(arg) + except (UnicodeError, TypeError), e: + raise ArgumentError(str(e)) + wrapped_args.append(wrapped) + consumed += 1 + + if len(wrapped_args) < len(args): + extra = args[len(wrapped_args):] + extra_types = self._guess_argtypes(extra) + for arg, argtype in zip(extra, extra_types): + try: + wrapped = argtype._CData_input(arg) + except (UnicodeError, TypeError), e: + raise ArgumentError(str(e)) + wrapped_args.append(wrapped) + argtypes = list(argtypes) + extra_types + return argtypes, wrapped_args + + def _build_result(self, restype, resbuffer, argtypes, argsandobjs): + """Build the function result: + If there is no OUT parameter, return the actual function result + If there is one OUT parameter, return it + If there are many OUT parameters, return a tuple""" + + retval = None + + if self._com_index: + if resbuffer[0] & 0x80000000: + raise get_com_error(resbuffer[0], + self._com_iid, argsandobjs[0][0]) + else: + retval = int(resbuffer[0]) + elif restype is not None: + checker = getattr(self.restype, '_check_retval_', None) + if checker: + val = restype(resbuffer[0]) + # the original ctypes seems to make the distinction between + # classes defining a new type, and their subclasses + if '_type_' in restype.__dict__: + val = val.value + retval = checker(val) + elif not isinstance(restype, _CDataMeta): + retval = restype(resbuffer[0]) + else: + retval = restype._CData_retval(resbuffer) + + results = [] + if self._paramflags: + for argtype, (obj, _), paramflag in zip(argtypes[1:], argsandobjs[1:], + self._paramflags): + if len(paramflag) == 2: + idlflag, name = paramflag + elif len(paramflag) == 3: + idlflag, name, defaultvalue = paramflag + else: + idlflag = 0 + idlflag &= (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID) + + if idlflag in (0, PARAMFLAG_FIN): + pass + elif idlflag == PARAMFLAG_FOUT: + val = obj.__ctypes_from_outparam__() + results.append(val) + elif idlflag == PARAMFLAG_FIN | PARAMFLAG_FLCID: + pass + else: + raise NotImplementedError( + "paramflags = %s" % (paramflag,)) + + if results: + if len(results) == 1: + return results[0] + else: + return tuple(results) + + # No output parameter, return the actual function result. + return retval + + def __del__(self): + if self._needs_free: + # XXX we need to find a bad guy here + if self._buffer is None: + return + self._buffer.free() + self._buffer = None + if isinstance(self._ptr, _rawffi.CallbackPtr): + self._ptr.free() + self._ptr = None + self._needs_free = False Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/function.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/pointer.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/pointer.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/pointer.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,130 @@ + +import _rawffi +from _ctypes.basics import _CData, _CDataMeta, cdata_from_address +from _ctypes.basics import sizeof, byref, keepalive_key +from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\ + array_slice_setitem + +DEFAULT_VALUE = object() + +class PointerType(_CDataMeta): + def __new__(self, name, cls, typedict): + d = dict( + size = _rawffi.sizeof('P'), + align = _rawffi.alignment('P'), + length = 1, + _ffiargshape = 'P', + _ffishape = 'P', + _fficompositesize = None + ) + # XXX check if typedict['_type_'] is any sane + # XXX remember about paramfunc + obj = type.__new__(self, name, cls, typedict) + for k, v in d.iteritems(): + setattr(obj, k, v) + if '_type_' in typedict: + self.set_type(obj, typedict['_type_']) + else: + def __init__(self, value=None): + raise TypeError("%s has no type" % obj) + obj.__init__ = __init__ + return obj + + def from_param(self, value): + if value is None: + return self(None) + # If we expect POINTER(<type>), but receive a <type> instance, accept + # it by calling byref(<type>). + if isinstance(value, self._type_): + return byref(value) + # Array instances are also pointers when the item types are the same. + if isinstance(value, (_Pointer, Array)): + if issubclass(type(value)._type_, self._type_): + return value + return _CDataMeta.from_param(self, value) + + def _sizeofinstances(self): + return _rawffi.sizeof('P') + + def _alignmentofinstances(self): + return _rawffi.alignment('P') + + def _is_pointer_like(self): + return True + + def set_type(self, TP): + ffiarray = _rawffi.Array('P') + def __init__(self, value=None): + self._buffer = ffiarray(1, autofree=True) + if value is not None: + self.contents = value + self._ffiarray = ffiarray + self.__init__ = __init__ + self._type_ = TP + + from_address = cdata_from_address + +class _Pointer(_CData): + __metaclass__ = PointerType + + def getcontents(self): + addr = self._buffer[0] + if addr == 0: + raise ValueError("NULL pointer access") + return self._type_.from_address(addr) + + def setcontents(self, value): + if not isinstance(value, self._type_): + raise TypeError("expected %s instead of %s" % ( + self._type_.__name__, type(value).__name__)) + self._objects = {keepalive_key(1):value} + if value._ensure_objects() is not None: + self._objects[keepalive_key(0)] = value._objects + value = value._buffer + self._buffer[0] = value + + _get_slice_params = array_get_slice_params + _slice_getitem = array_slice_getitem + + def _subarray(self, index=0): + """Return a _rawffi array of length 1 whose address is the same as + the index'th item to which self is pointing.""" + address = self._buffer[0] + address += index * sizeof(self._type_) + return self._type_.from_address(address)._buffer + + def __getitem__(self, index): + if isinstance(index, slice): + return self._slice_getitem(index) + return self._type_._CData_output(self._subarray(index), self, index) + + def __setitem__(self, index, value): + self._subarray(index)[0] = self._type_._CData_value(value) + + def __nonzero__(self): + return self._buffer[0] != 0 + + contents = property(getcontents, setcontents) + +def _cast_addr(obj, _, tp): + if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()): + raise TypeError("cast() argument 2 must be a pointer type, not %s" + % (tp,)) + if isinstance(obj, Array): + ptr = tp.__new__(tp) + ptr._buffer = tp._ffiarray(1, autofree=True) + ptr._buffer[0] = obj._buffer + return ptr + if isinstance(obj, (int, long)): + result = tp() + result._buffer[0] = obj + return result + if obj is None: + result = tp() + return result + if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()): + raise TypeError("cast() argument 1 must be a pointer, not %s" + % (type(obj),)) + result = tp() + result._buffer[0] = obj._buffer[0] + return result Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/pointer.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/primitive.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/primitive.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/primitive.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,314 @@ +import _rawffi +import weakref +import sys + +SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" + +from _ctypes.basics import _CData, _CDataMeta, cdata_from_address,\ + CArgObject +from _ctypes.builtin import ConvMode +from _ctypes.array import Array +from _ctypes.pointer import _Pointer + +class NULL(object): + pass +NULL = NULL() + +TP_TO_DEFAULT = { + 'c': 0, + 'u': 0, + 'b': 0, + 'B': 0, + 'h': 0, + 'H': 0, + 'i': 0, + 'I': 0, + 'l': 0, + 'L': 0, + 'q': 0, + 'Q': 0, + 'f': 0.0, + 'd': 0.0, + 'P': None, + # not part of struct + 'O': NULL, + 'z': None, + 'Z': None, +} + +if sys.platform == 'win32': + TP_TO_DEFAULT['X'] = NULL + TP_TO_DEFAULT['v'] = 0 + +DEFAULT_VALUE = object() + +class GlobalPyobjContainer(object): + def __init__(self): + self.objs = [] + + def add(self, obj): + num = len(self.objs) + self.objs.append(weakref.ref(obj)) + return num + + def get(self, num): + return self.objs[num]() + +pyobj_container = GlobalPyobjContainer() + +def generic_xxx_p_from_param(cls, value): + from _ctypes import Array, _Pointer + if value is None: + return cls(None) + if isinstance(value, basestring): + return cls(value) + if isinstance(value, _SimpleCData) and \ + type(value)._type_ in 'zZP': + return value + return None # eventually raise + +def from_param_char_p(cls, value): + "used by c_char_p and c_wchar_p subclasses" + res = generic_xxx_p_from_param(cls, value) + if res is not None: + return res + if isinstance(value, (Array, _Pointer)): + from ctypes import c_char, c_byte, c_wchar + if type(value)._type_ in [c_char, c_byte, c_wchar]: + return value + +def from_param_void_p(cls, value): + "used by c_void_p subclasses" + res = generic_xxx_p_from_param(cls, value) + if res is not None: + return res + if isinstance(value, Array): + return value + if isinstance(value, _Pointer): + return cls.from_address(value._buffer.buffer) + +FROM_PARAM_BY_TYPE = { + 'z': from_param_char_p, + 'Z': from_param_char_p, + 'P': from_param_void_p, + } + +class SimpleType(_CDataMeta): + def __new__(self, name, bases, dct): + try: + tp = dct['_type_'] + except KeyError: + for base in bases: + if hasattr(base, '_type_'): + tp = base._type_ + break + else: + raise AttributeError("cannot find _type_ attribute") + if (not isinstance(tp, str) or + not len(tp) == 1 or + tp not in SIMPLE_TYPE_CHARS): + raise ValueError('%s is not a type character' % (tp)) + default = TP_TO_DEFAULT[tp] + ffiarray = _rawffi.Array(tp) + result = type.__new__(self, name, bases, dct) + result._ffiargshape = tp + result._ffishape = tp + result._fficompositesize = None + result._ffiarray = ffiarray + if tp == 'z': + # c_char_p + from _ctypes import Array, _Pointer + + def _getvalue(self): + addr = self._buffer[0] + if addr == 0: + return None + else: + return _rawffi.charp2string(addr) + + def _setvalue(self, value): + if isinstance(value, basestring): + if isinstance(value, unicode): + value = value.encode(ConvMode.encoding, + ConvMode.errors) + #self._objects = value + array = _rawffi.Array('c')(len(value)+1, value) + value = array.buffer + self._objects = {'0': CArgObject(array)} + elif value is None: + value = 0 + self._buffer[0] = value + result.value = property(_getvalue, _setvalue) + elif tp == 'Z': + # c_wchar_p + from _ctypes import Array, _Pointer, _wstring_at_addr + def _getvalue(self): + addr = self._buffer[0] + if addr == 0: + return None + else: + return _wstring_at_addr(addr, -1) + + def _setvalue(self, value): + if isinstance(value, basestring): + if isinstance(value, str): + value = value.decode(ConvMode.encoding, + ConvMode.errors) + #self._objects = value + array = _rawffi.Array('u')(len(value)+1, value) + value = array.buffer + self._objects = {'0': CArgObject(array)} + elif value is None: + value = 0 + self._buffer[0] = value + result.value = property(_getvalue, _setvalue) + + elif tp == 'P': + # c_void_p + + def _getvalue(self): + addr = self._buffer[0] + if addr == 0: + return None + return addr + + def _setvalue(self, value): + if isinstance(value, str): + array = _rawffi.Array('c')(len(value)+1, value) + value = array.buffer + self._objects = {'0': CArgObject(array)} + elif value is None: + value = 0 + self._buffer[0] = value + result.value = property(_getvalue, _setvalue) + + elif tp == 'u': + def _setvalue(self, val): + if isinstance(val, str): + val = val.decode(ConvMode.encoding, ConvMode.errors) + # possible if we use 'ignore' + if val: + self._buffer[0] = val + def _getvalue(self): + return self._buffer[0] + result.value = property(_getvalue, _setvalue) + + elif tp == 'c': + def _setvalue(self, val): + if isinstance(val, unicode): + val = val.encode(ConvMode.encoding, ConvMode.errors) + if val: + self._buffer[0] = val + def _getvalue(self): + return self._buffer[0] + result.value = property(_getvalue, _setvalue) + + elif tp == 'O': + def _setvalue(self, val): + num = pyobj_container.add(val) + self._buffer[0] = num + def _getvalue(self): + return pyobj_container.get(self._buffer[0]) + result.value = property(_getvalue, _setvalue) + + elif tp == 'X': + from ctypes import windll + SysAllocStringLen = windll.oleaut32.SysAllocStringLen + SysStringLen = windll.oleaut32.SysStringLen + SysFreeString = windll.oleaut32.SysFreeString + from _ctypes import _wstring_at_addr + def _getvalue(self): + addr = self._buffer[0] + if addr == 0: + return None + else: + size = SysStringLen(addr) + return _wstring_at_addr(addr, size) + + def _setvalue(self, value): + if isinstance(value, basestring): + if isinstance(value, str): + value = value.decode(ConvMode.encoding, + ConvMode.errors) + array = _rawffi.Array('u')(len(value)+1, value) + value = SysAllocStringLen(array.buffer, len(value)) + elif value is None: + value = 0 + if self._buffer[0]: + SysFreeString(self._buffer[0]) + self._buffer[0] = value + result.value = property(_getvalue, _setvalue) + + elif tp == 'v': # VARIANT_BOOL type + def _getvalue(self): + return bool(self._buffer[0]) + def _setvalue(self, value): + if value: + self._buffer[0] = -1 # VARIANT_TRUE + else: + self._buffer[0] = 0 # VARIANT_FALSE + result.value = property(_getvalue, _setvalue) + + return result + + from_address = cdata_from_address + + def from_param(self, value): + from_param_f = FROM_PARAM_BY_TYPE.get(self._type_) + if from_param_f: + res = from_param_f(self, value) + if res is not None: + return res + + if isinstance(value, self): + return value + try: + return self(value) + except (TypeError, ValueError): + return super(SimpleType, self).from_param(value) + + def _CData_output(self, resbuffer, base=None, index=-1): + output = super(SimpleType, self)._CData_output(resbuffer, base, index) + return output.value + + def _sizeofinstances(self): + return _rawffi.sizeof(self._type_) + + def _alignmentofinstances(self): + return _rawffi.alignment(self._type_) + + def _is_pointer_like(self): + return self._type_ in "sPzUZXO" + +class _SimpleCData(_CData): + __metaclass__ = SimpleType + _type_ = 'i' + + def __init__(self, value=DEFAULT_VALUE): + self._buffer = self._ffiarray(1, autofree=True) + if value is not DEFAULT_VALUE: + self.value = value + + def _ensure_objects(self): + return None + + def _getvalue(self): + return self._buffer[0] + + def _setvalue(self, value): + self._buffer[0] = value + value = property(_getvalue, _setvalue) + del _getvalue, _setvalue + + def __ctypes_from_outparam__(self): + meta = type(type(self)) + if issubclass(meta, SimpleType) and meta != SimpleType: + return self + + return self.value + + def __repr__(self): + return "%s(%r)" % (type(self).__name__, self.value) + + def __nonzero__(self): + return self._buffer[0] not in (0, '\x00') Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/primitive.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/structure.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/structure.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/structure.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,211 @@ + +import _rawffi +from _ctypes.basics import _CData, _CDataMeta, keepalive_key,\ + store_reference, ensure_objects, CArgObject +import inspect + +def round_up(size, alignment): + return (size + alignment - 1) & -alignment + +def size_alignment_pos(fields): + import ctypes + size = 0 + alignment = 1 + pos = [] + for fieldname, ctype in fields: + fieldsize = ctypes.sizeof(ctype) + fieldalignment = ctypes.alignment(ctype) + size = round_up(size, fieldalignment) + alignment = max(alignment, fieldalignment) + pos.append(size) + size += fieldsize + size = round_up(size, alignment) + return size, alignment, pos + +def names_and_fields(_fields_, superclass, zero_offset=False, anon=None): + if isinstance(_fields_, tuple): + _fields_ = list(_fields_) + for _, tp in _fields_: + if not isinstance(tp, _CDataMeta): + raise TypeError("Expected CData subclass, got %s" % (tp,)) + import ctypes + all_fields = _fields_[:] + for cls in inspect.getmro(superclass): + all_fields += getattr(cls, '_fields_', []) + names = [name for name, ctype in all_fields] + rawfields = [(name, ctype._ffishape) + for name, ctype in all_fields] + if not zero_offset: + _, _, pos = size_alignment_pos(all_fields) + else: + pos = [0] * len(all_fields) + fields = {} + for i, (name, ctype) in enumerate(all_fields): + fields[name] = Field(name, pos[i], ctypes.sizeof(ctype), ctype, i) + if anon: + resnames = [] + for i, (name, value) in enumerate(all_fields): + if name in anon: + for subname in value._names: + resnames.append(subname) + relpos = pos[i] + value._fieldtypes[subname].offset + subvalue = value._fieldtypes[subname].ctype + fields[subname] = Field(subname, relpos, + ctypes.sizeof(subvalue), subvalue, + i) + # XXX we never set rawfields here, let's wait for a test + else: + resnames.append(name) + names = resnames + return names, rawfields, fields + +class Field(object): + def __init__(self, name, offset, size, ctype, num): + for k in ('name', 'offset', 'size', 'ctype', 'num'): + self.__dict__[k] = locals()[k] + + def __setattr__(self, name, value): + raise AttributeError(name) + + def __repr__(self): + return "<Field '%s' offset=%d size=%d>" % (self.name, self.offset, + self.size) + +# ________________________________________________________________ + +def _set_shape(tp, rawfields): + tp._ffistruct = _rawffi.Structure(rawfields) + tp._ffiargshape = tp._ffishape = (tp._ffistruct, 1) + tp._fficompositesize = tp._ffistruct.size + +def struct_getattr(self, name): + if hasattr(self, '_fieldtypes') and name in self._fieldtypes: + return self._fieldtypes[name] + return _CDataMeta.__getattribute__(self, name) + +def struct_setattr(self, name, value): + if name == '_fields_': + if self.__dict__.get('_fields_', None) is not None: + raise AttributeError("_fields_ is final") + if self in [v for k, v in value]: + raise AttributeError("Structure or union cannot contain itself") + self._names, rawfields, self._fieldtypes = names_and_fields( + value, self.__bases__[0], False, + self.__dict__.get('_anonymous_', None)) + _CDataMeta.__setattr__(self, '_fields_', value) + _set_shape(self, rawfields) + return + _CDataMeta.__setattr__(self, name, value) + +class StructureMeta(_CDataMeta): + def __new__(self, name, cls, typedict): + res = type.__new__(self, name, cls, typedict) + if '_fields_' in typedict: + if not hasattr(typedict.get('_anonymous_', []), '__iter__'): + raise TypeError("Anonymous field must be iterable") + for item in typedict.get('_anonymous_', []): + if item not in dict(typedict['_fields_']): + raise AttributeError("Anonymous field not found") + res._names, rawfields, res._fieldtypes = names_and_fields( + typedict['_fields_'], cls[0], False, + typedict.get('_anonymous_', None)) + _set_shape(res, rawfields) + + return res + + __getattr__ = struct_getattr + __setattr__ = struct_setattr + + def from_address(self, address): + instance = self.__new__(self) + instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address) + return instance + + def _sizeofinstances(self): + if not hasattr(self, '_ffistruct'): + return 0 + return self._ffistruct.size + + def _alignmentofinstances(self): + return self._ffistruct.alignment + + def _CData_value(self, value): + if isinstance(value, tuple): + value = self(*value) + return _CDataMeta._CData_value(self, value) + + def _CData_output(self, resarray, base=None, index=-1): + res = self.__new__(self) + ffistruct = self._ffistruct.fromaddress(resarray.buffer) + res.__dict__['_buffer'] = ffistruct + res.__dict__['_base'] = base + res.__dict__['_index'] = index + return res + + def _CData_retval(self, resbuffer): + res = self.__new__(self) + res.__dict__['_buffer'] = resbuffer + res.__dict__['_base'] = None + res.__dict__['_index'] = -1 + return res + +class Structure(_CData): + __metaclass__ = StructureMeta + + def __new__(cls, *args, **kwds): + if not hasattr(cls, '_ffistruct'): + raise TypeError("Cannot instantiate structure, has no _fields_") + self = super(_CData, cls).__new__(cls, *args, **kwds) + self.__dict__['_buffer'] = self._ffistruct(autofree=True) + return self + + def __init__(self, *args, **kwds): + if len(args) > len(self._names): + raise TypeError("too many arguments") + for name, arg in zip(self._names, args): + if name in kwds: + raise TypeError("duplicate value for argument %r" % ( + name,)) + self.__setattr__(name, arg) + for name, arg in kwds.items(): + self.__setattr__(name, arg) + + def _subarray(self, fieldtype, name): + """Return a _rawffi array of length 1 whose address is the same as + the address of the field 'name' of self.""" + address = self._buffer.fieldaddress(name) + A = _rawffi.Array(fieldtype._ffishape) + return A.fromaddress(address, 1) + + def __setattr__(self, name, value): + try: + fieldtype = self._fieldtypes[name].ctype + except KeyError: + return _CData.__setattr__(self, name, value) + if ensure_objects(value) is not None: + key = keepalive_key(getattr(self.__class__, name).num) + store_reference(self, key, value._objects) + arg = fieldtype._CData_value(value) + if fieldtype._fficompositesize is not None: + from ctypes import memmove + dest = self._buffer.fieldaddress(name) + memmove(dest, arg, fieldtype._fficompositesize) + else: + self._buffer.__setattr__(name, arg) + + def __getattribute__(self, name): + if name == '_fieldtypes': + return _CData.__getattribute__(self, '_fieldtypes') + try: + fieldtype = self._fieldtypes[name].ctype + except KeyError: + return _CData.__getattribute__(self, name) + offset = self.__class__._fieldtypes[name].num + suba = self._subarray(fieldtype, name) + return fieldtype._CData_output(suba, self, offset) + + def _get_buffer_for_param(self): + return self + + def _get_buffer_value(self): + return self._buffer.buffer Property changes on: branches/ctypes-via-rawffi/Lib/_ctypes/structure.py ___________________________________________________________________ Added: svn:eol-style + native Added: branches/ctypes-via-rawffi/Lib/_ctypes/union.py =================================================================== --- branches/ctypes-via-rawffi/Lib/_ctypes/union.py (rev 0) +++ branches/ctypes-via-rawffi/Lib/_ctypes/union.py 2009-04-29 04:32:23 UTC (rev 6271) @@ -0,0 +1,115 @@ + + +import _rawffi +from _ctypes.basics import _CData, _CDataMeta, store_reference, keepalive_key +from _ctypes.basics import ensure_objects +from _ctypes.structure import round_up, names_and_fields, struct_getattr,\ + struct_setattr + + +def _set_shape(tp): + size = tp._sizeofinstances() + alignment = tp._alignmentofinstances() + tp._ffiopaque = _rawffi.Structure((size, alignment)) # opaque + tp._ffiargshape = tp._ffishape = (tp._ffiopaque, 1) + tp._fficompositesize = tp._ffiopaque.size + # we need to create an array of size one for each + # of our elements + tp._ffiarrays = {} + for name, field in tp._fieldtypes.iteritems(): + tp._ffiarrays[name] = _rawffi.Array(field.ctype._ffishape) + +class UnionMeta(_CDataMeta): + def __new__(self, name, cls, typedict): + res = type.__new__(self, name, cls, typedict) + if '_fields_' in typedict: + res._names, rawfields, res._fieldtypes = names_and_fields( + typedict['_fields_'], cls[0], True, + typedict.get('_anonymous_', None)) + _set_shape(res) + + def __init__(self): # don't allow arguments by now + if not hasattr(self, '_ffiarrays'): + raise TypeError("Cannot instantiate union, has no type") + # malloc size + size = self.__class__._sizeofinstances() + self.__dict__['_objects'] = {} + self.__dict__['_buffer'] = self._ffiopaque(autofree=True) + res.__init__ = __init__ + return res + + def _sizeofinstances(self): + if not hasattr(self, '_size_'): + self._size_ = max([field.size for field in + self._fieldtypes.values()] + [0]) + return self._size_ + + def _alignmentofinstances(self): + from ctypes import alignment + if not hasattr(self, '_alignment_'): + self._alignment_ = max([alignment(field.ctype) for field in + self._fieldtypes.values()] + [1]) + return self._alignment_ + + __getattr__ = struct_getattr + + def __setattr__(self, name, value): + if name == '_fields_': + if self.__dict__.get('_fields_', None): + raise AttributeError("_fields_ is final") + if self in [v for k, v in value]: + raise AttributeError("Union cannot contain itself") + self._names, rawfields, self._fieldtypes = names_and_fields( + value, self.__bases__[0], True, + self.__dict__.get('_anonymous_', None)) + _CDataMeta.__setattr__(self, '_fields_', value) + _set_shape(self) + _CDataMeta.__setattr__(self, name, value) + + def _CData_output(self, resarray, base=None, index=-1):... [truncated message content] |
From: <fi...@us...> - 2009-04-29 02:40:49
|
Revision: 6270 http://jython.svn.sourceforge.net/jython/?rev=6270&view=rev Author: fijal Date: 2009-04-29 02:40:41 +0000 (Wed, 29 Apr 2009) Log Message: ----------- Create a branch for experimenting with _rawffi implementation, that together with _ctypes stolen from pypy gives ctypes Added Paths: ----------- branches/ctypes-via-rawffi/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-04-29 01:24:37
|
Revision: 6269 http://jython.svn.sourceforge.net/jython/?rev=6269&view=rev Author: pjenvey Date: 2009-04-29 01:24:23 +0000 (Wed, 29 Apr 2009) Log Message: ----------- fix int __mul__ assuming sequences wouldnt't overload __rmul__ fixes #1332 Modified Paths: -------------- trunk/jython/Lib/test/test_descr_jy.py trunk/jython/src/org/python/core/PyInteger.java Modified: trunk/jython/Lib/test/test_descr_jy.py =================================================================== --- trunk/jython/Lib/test/test_descr_jy.py 2009-04-28 17:35:27 UTC (rev 6268) +++ trunk/jython/Lib/test/test_descr_jy.py 2009-04-29 01:24:23 UTC (rev 6269) @@ -232,7 +232,16 @@ return 3 self.assertEqual(Foo() + Bar(), 3) + def test_int_mul(self): + # http://bugs.jython.org/issue1332 + class Foo(tuple): + def __rmul__(self, other): + return 'foo' + foo = Foo() + self.assertEqual(3.0 * foo, 'foo') + self.assertEqual(4 * foo, 'foo') + class InPlaceTestCase(unittest.TestCase): def test_iadd(self): Modified: trunk/jython/src/org/python/core/PyInteger.java =================================================================== --- trunk/jython/src/org/python/core/PyInteger.java 2009-04-28 17:35:27 UTC (rev 6268) +++ trunk/jython/src/org/python/core/PyInteger.java 2009-04-29 01:24:23 UTC (rev 6269) @@ -257,9 +257,6 @@ @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___mul___doc) final PyObject int___mul__(PyObject right) { - if (right instanceof PySequence) - return ((PySequence) right).repeat(getValue()); - if (!canCoerce(right)) return null; int rightv = coerce(right); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-04-28 17:35:28
|
Revision: 6268 http://jython.svn.sourceforge.net/jython/?rev=6268&view=rev Author: fwierzbicki Date: 2009-04-28 17:35:27 +0000 (Tue, 28 Apr 2009) Log Message: ----------- tag b4. Added Paths: ----------- tags/Release_2_5beta4/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |