From jython-checkins at python.org Tue Jul 3 20:21:17 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Tue, 3 Jul 2012 20:21:17 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Refactor_and_2=2E7_update_o?= =?utf-8?q?f_itertools=2E_Thanks_Jezreel_Ng!?= Message-ID: <3WRYYn5MZbzMgx@mail.python.org> http://hg.python.org/jython/rev/b47015465ca0 changeset: 6777:b47015465ca0 user: Jezreel Ng date: Tue Jul 03 10:49:58 2012 -0700 summary: Refactor and 2.7 update of itertools. Thanks Jezreel Ng! files: CoreExposed.includes | 14 +- src/org/python/modules/itertools/PyTeeIterator.java | 146 +- src/org/python/modules/itertools/PyTeeIteratorDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/combinations.java | 96 + src/org/python/modules/itertools/combinationsDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/combinationsWithReplacement.java | 98 + src/org/python/modules/itertools/combinationsWithReplacementDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/compress.java | 2 +- src/org/python/modules/itertools/count.java | 26 +- src/org/python/modules/itertools/dropwhile.java | 66 + src/org/python/modules/itertools/dropwhileDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/groupby.java | 125 + src/org/python/modules/itertools/groupbyDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/islice.java | 141 + src/org/python/modules/itertools/isliceDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/itertools.java | 497 +---- src/org/python/modules/itertools/izip.java | 2 + src/org/python/modules/itertools/izipDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/izipLongest.java | 115 + src/org/python/modules/itertools/izipLongestDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/permutations.java | 117 + src/org/python/modules/itertools/permutationsDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/product.java | 126 + src/org/python/modules/itertools/productDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/repeat.java | 129 + src/org/python/modules/itertools/repeatDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/starmap.java | 88 + src/org/python/modules/itertools/starmapDerived.java | 1125 ++++++++++ src/org/python/modules/itertools/takewhile.java | 66 + src/org/python/modules/itertools/takewhileDerived.java | 1125 ++++++++++ src/templates/array.derived | 2 +- src/templates/array.derived | 2 +- src/templates/array.derived | 2 +- src/templates/array.derived | 2 +- src/templates/array.derived | 2 +- src/templates/array.derived | 2 +- src/templates/array.derived | 2 +- src/templates/array.derived | 2 +- src/templates/mappings | 20 +- src/templates/array.derived | 2 +- src/templates/chain.derived | 2 +- src/templates/chain.derived | 2 +- src/templates/chain.derived | 2 +- src/templates/array.derived | 2 +- 44 files changed, 15960 insertions(+), 565 deletions(-) diff --git a/CoreExposed.includes b/CoreExposed.includes --- a/CoreExposed.includes +++ b/CoreExposed.includes @@ -52,7 +52,6 @@ org/python/core/stringlib/MarkupIterator.class org/python/core/stringlib/FieldNameIterator.class org/python/modules/PyStruct.class -org/python/modules/PyTeeIterator.class org/python/jsr223/PyScriptEngineScope.class org/python/modules/_codecs$EncodingMap.class org/python/modules/_collections/PyDefaultDict.class @@ -65,10 +64,23 @@ org/python/modules/_hashlib$Hash.class org/python/modules/itertools/chain.class org/python/modules/itertools/compress.class +org/python/modules/itertools/combinations.class +org/python/modules/itertools/combinationsWithReplacement.class org/python/modules/itertools/cycle.class org/python/modules/itertools/count.class +org/python/modules/itertools/dropwhile.class +org/python/modules/itertools/groupby.class org/python/modules/itertools/ifilterfalse.class org/python/modules/itertools/ifilter.class +org/python/modules/itertools/islice.class +org/python/modules/itertools/izip.class +org/python/modules/itertools/izipLongest.class +org/python/modules/itertools/permutations.class +org/python/modules/itertools/product.class +org/python/modules/itertools/repeat.class +org/python/modules/itertools/starmap.class +org/python/modules/itertools/takewhile.class +org/python/modules/itertools/PyTeeIterator.class org/python/modules/jffi/ArrayCData.class org/python/modules/jffi/ByReference.class org/python/modules/jffi/CData.class diff --git a/src/org/python/modules/itertools/PyTeeIterator.java b/src/org/python/modules/itertools/PyTeeIterator.java --- a/src/org/python/modules/itertools/PyTeeIterator.java +++ b/src/org/python/modules/itertools/PyTeeIterator.java @@ -16,17 +16,63 @@ @ExposedType(name = "itertools.tee", base = PyObject.class, isBaseType = false) public class PyTeeIterator extends PyIterator { - private final int position; - private int count = 0; - private final PyObject iterator; - private final Map buffer; - private final int[] offsets; + private static class PyTeeData { + private PyObject iterator; + private int total; + private Map buffer; + public PyException stopException; + private Object lock; - PyTeeIterator(PyObject iterator, Map buffer, int[] offsets, int position) { - this.iterator = iterator; - this.buffer = buffer; - this.offsets = offsets; - this.position = position; + public PyTeeData(PyObject iterator) { + this.iterator = iterator; + buffer = Generic.concurrentMap(); + total = 0; + lock = new Object(); + } + + public PyObject getItem(int pos) { + if (pos == total) { + synchronized (lock) { + if (pos == total) { + PyObject obj = nextElement(iterator); + if (obj == null) { + return null; + } + buffer.put(total++, obj); + } + } + } + return buffer.get(pos); + } + + private PyObject nextElement(PyObject pyIter) { + PyObject element = null; + try { + element = pyIter.__iternext__(); + } catch (PyException pyEx) { + if (pyEx.match(Py.StopIteration)) { + stopException = pyEx; + } else { + throw pyEx; + } + } + return element; + } + } + + private int position; + private PyTeeData teeData; + + public PyTeeIterator() { + super(); + } + + public PyTeeIterator(PyType subType) { + super(subType); + } + + public PyTeeIterator(PyTeeData teeData) { + this.teeData = teeData; } @ExposedNew @@ -37,37 +83,41 @@ if (nargs < 1 || nargs > 1) { throw Py.TypeError("tee expected 1 arguments, got " + nargs); } - return makeTees(args[0], 1)[0]; + return fromIterable(args[0]); } - public static PyTeeIterator[] makeTees(PyObject iterable, int n) { + public static PyObject[] makeTees(PyObject iterable, int n) { if (n < 0) { throw Py.ValueError("n must be >= 0"); } - PyObject iterator = iterable.__iter__(); - Map buffer = Generic.concurrentMap(); - int[] offsets = new int[n]; - PyTeeIterator[] tees = new PyTeeIterator[n]; - for (int i = 0; i < n; i++) { - offsets[i] = -1; - tees[i] = new PyTeeIterator(iterator, buffer, offsets, i); + + PyObject[] tees = new PyTeeIterator[n]; + + if (n == 0) { + return tees; + } + + PyObject copyFunc = iterable.__findattr__("__copy__"); + if (copyFunc == null) { + tees[0] = fromIterable(iterable); + copyFunc = tees[0].__getattr__("__copy__"); + } + else { + tees[0] = iterable; + } + for (int i = 1; i < n; i++) { + tees[i] = copyFunc.__call__(); } return tees; } - protected PyObject nextElement(PyObject pyIter) { - PyObject element = null; - try { - element = pyIter.__iternext__();//next(); - } catch (PyException pyEx) { - if (pyEx.match(Py.StopIteration)) { - // store exception - will be used by PyIterator.next() - stopException = pyEx; - } else { - throw pyEx; - } + private static PyTeeIterator fromIterable(PyObject iterable) { + if (iterable instanceof PyTeeIterator) { + return ((PyTeeIterator) iterable).tee___copy__(); } - return element; + PyObject iterator = (PyObject)iterable.__iter__(); + PyTeeData teeData = new PyTeeData(iterator); + return new PyTeeIterator(teeData); } @ExposedMethod @@ -76,31 +126,15 @@ } public PyObject __iternext__() { - final PyObject item; - int max = Integer.MIN_VALUE; - int min = Integer.MAX_VALUE; - for (int j = 0; j < offsets.length; j++) { - if (max < offsets[j]) { - max = offsets[j]; - } - if (min > offsets[j]) { - min = offsets[j]; - } + PyObject obj = teeData.getItem(position++); + if (obj == null) { + stopException = teeData.stopException; } - if (count > max) { - item = nextElement(iterator); - if (item != null) { - buffer.put(count, item); - } - } else if (count < min) { - item = buffer.remove(count); - } else { - item = buffer.get(count); - } - offsets[position] = count; - count++; - return item; + return obj; + } + + @ExposedMethod + public final PyTeeIterator tee___copy__() { + return new PyTeeIterator(teeData); } } - - diff --git a/src/org/python/modules/itertools/PyTeeIteratorDerived.java b/src/org/python/modules/itertools/PyTeeIteratorDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/PyTeeIteratorDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class PyTeeIteratorDerived extends PyTeeIterator implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public PyTeeIteratorDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/combinations.java b/src/org/python/modules/itertools/combinations.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/combinations.java @@ -0,0 +1,96 @@ +package org.python.modules.itertools; + +import org.python.core.ArgParser; +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyTuple; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.combinations", base = PyObject.class) +public class combinations extends PyObject { + + public static final PyType TYPE = PyType.fromClass(combinations.class); + private PyIterator iter; + + @ExposedGet + public static PyString __doc__ = new PyString( + "combinations(iterable, r) --> combinations object\n\n" + + "Return successive r-length combinations of elements in the iterable.\n\n" + + "combinations(range(4), 3) --> (0,1,2), (0,1,3), (0,2,3), (1,2,3)"); + + public combinations() { + super(); + } + + public combinations(PyType subType) { + super(subType); + } + + public combinations(PyObject iterable, int r) { + super(); + combinations___init__(iterable, r); + } + + @ExposedNew + @ExposedMethod + final void combinations___init__(PyObject[] args, String[] kwds) { + if (args.length > 2) { + throw Py.TypeError(String.format( + "combinations_with_replacement() takes at most 2 arguments (%d given)", args.length)); + } + ArgParser ap = new ArgParser("combinations_with_replacement", args, kwds, "iterable", "r"); + PyObject iterable = ap.getPyObject(0); + int r = ap.getInt(1); + if (r < 0) { + throw Py.ValueError("r must be non-negative"); + } + combinations___init__(iterable, r); + } + + private void combinations___init__(PyObject iterable, final int r) { + if (r < 0) throw Py.ValueError("r must be non-negative"); + final PyTuple pool = PyTuple.fromIterable(iterable); + final int n = pool.__len__(); + final int indices[] = new int[r]; + for (int i = 0; i < r; i++) { + indices[i] = i; + } + + iter = new itertools.ItertoolsIterator() { + boolean firstthru = true; + + @Override + public PyObject __iternext__() { + if (r > n) { return null; } + if (firstthru) { + firstthru = false; + return itertools.makeIndexedTuple(pool, indices); + } + int i; + for (i = r-1; i >= 0 && indices[i] == i+n-r ; i--); + if (i < 0) return null; + indices[i]++; + for (int j = i+1; j < r; j++) { + indices[j] = indices[j-1] + 1; + } + return itertools.makeIndexedTuple(pool, indices); + } + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } +} diff --git a/src/org/python/modules/itertools/combinationsDerived.java b/src/org/python/modules/itertools/combinationsDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/combinationsDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class combinationsDerived extends combinations implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public combinationsDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/combinationsWithReplacement.java b/src/org/python/modules/itertools/combinationsWithReplacement.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/combinationsWithReplacement.java @@ -0,0 +1,98 @@ +/* Copyright (c) 2012 Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.ArgParser; +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyTuple; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.combinations_with_replacement", base = PyObject.class) +public class combinationsWithReplacement extends PyObject { + + public static final PyType TYPE = PyType.fromClass(combinationsWithReplacement.class); + private itertools.ItertoolsIterator iter; + + @ExposedGet + public static PyString __doc__ = new PyString( + "combinations_with_replacement(iterable, r) --> combinations_with_replacement object\n\n" + + "Return successive r-length combinations of elements in the iterable\n" + + "allowing individual elements to have successive repeats.\n" + + "combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC"); + + public combinationsWithReplacement() { + super(); + } + + public combinationsWithReplacement(PyType subType) { + super(subType); + } + + public combinationsWithReplacement(PyObject iterable, int r) { + super(); + combinationsWithReplacement___init__(iterable, r); + } + + @ExposedNew + @ExposedMethod + final void combinationsWithReplacement___init__(PyObject[] args, String[] kwds) { + if (args.length > 2) { + throw Py.TypeError("combinations_with_replacement() takes at most 2 arguments (3 given)"); + } + ArgParser ap = new ArgParser("combinations_with_replacement", args, kwds, "iterable", "r"); + PyObject iterable = ap.getPyObject(0); + int r = ap.getInt(1); + if (r < 0) { + throw Py.ValueError("r must be non-negative"); + } + combinationsWithReplacement___init__(iterable, r); + } + + private void combinationsWithReplacement___init__(PyObject iterable, final int r) { + final PyTuple pool = PyTuple.fromIterable(iterable); + final int n = pool.__len__(); + final int indices[] = new int[r]; + for (int i = 0; i < r; i++) { + indices[i] = 0; + } + + iter = new itertools.ItertoolsIterator() { + boolean firstthru = true; + + @Override + public PyObject __iternext__() { + if (firstthru) { + firstthru = false; + if (n == 0 && r > 0) { + return null; + } + return itertools.makeIndexedTuple(pool, indices); + } + int i; + for (i = r - 1 ; i >= 0 && indices[i] == n - 1; i--); + if (i < 0) return null; + indices[i]++; + for (int j = i + 1; j < r; j++) { + indices[j] = indices[j-1]; + } + return itertools.makeIndexedTuple(pool, indices); + } + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } +} diff --git a/src/org/python/modules/itertools/combinationsWithReplacementDerived.java b/src/org/python/modules/itertools/combinationsWithReplacementDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/combinationsWithReplacementDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class combinationsWithReplacementDerived extends combinationsWithReplacement implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public combinationsWithReplacementDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/compress.java b/src/org/python/modules/itertools/compress.java --- a/src/org/python/modules/itertools/compress.java +++ b/src/org/python/modules/itertools/compress.java @@ -18,7 +18,7 @@ private itertools.ItertoolsIterator iter; @ExposedGet - public static PyString __doc__compress = new PyString( + public static PyString __doc__ = new PyString( "compress(data, selectors) --> iterator over selected data\n\n" + "Return data elements corresponding to true selector elements.\n" + "Forms a shorter iterator from selected data elements using the\n" + diff --git a/src/org/python/modules/itertools/count.java b/src/org/python/modules/itertools/count.java --- a/src/org/python/modules/itertools/count.java +++ b/src/org/python/modules/itertools/count.java @@ -22,6 +22,8 @@ public static final PyType TYPE = PyType.fromClass(count.class); private PyIterator iter; + private int counter; + private int stepper; @ExposedGet public static PyString __doc__ = new PyString( @@ -66,7 +68,7 @@ @ExposedNew @ExposedMethod final void count___init__(final PyObject[] args, String[] kwds) { - ArgParser ap = new ArgParser("count", args, kwds, new String[] {"start", "step"}); + ArgParser ap = new ArgParser("count", args, kwds, new String[] {"start", "step"}, 0); int start = ap.getInt(0, 0); int step = ap.getInt(1, 1); @@ -74,20 +76,17 @@ } private void count___init__(final int start, final int step) { + counter = start; + stepper = step; + iter = new PyIterator() { - int counter = start; - int stepper = step; public PyObject __iternext__() { int result = counter; counter += stepper; return new PyInteger(result); } - - public PyString __repr__() { - return (PyString)(Py.newString("count(%d, %d)").__mod__(new PyTuple( - Py.newInteger(counter), Py.newInteger(stepper)))); - } + }; } @@ -101,4 +100,15 @@ return iter.next(); } + @ExposedMethod + public PyString __repr__() { + if (stepper == 1) { + return (PyString)(Py.newString("count(%d)").__mod__(Py.newInteger(counter))); + } + else { + return (PyString)(Py.newString("count(%d, %d)").__mod__(new PyTuple( + Py.newInteger(counter), Py.newInteger(stepper)))); + } + } + } diff --git a/src/org/python/modules/itertools/dropwhile.java b/src/org/python/modules/itertools/dropwhile.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/dropwhile.java @@ -0,0 +1,66 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.ArgParser; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.dropwhile", base = PyObject.class) +public class dropwhile extends PyObject { + + public static final PyType TYPE = PyType.fromClass(dropwhile.class); + private PyIterator iter; + + public dropwhile() { + super(); + } + + public dropwhile(PyType subType) { + super(subType); + } + + public dropwhile(PyObject predicate, PyObject iterable) { + super(); + dropwhile___init__(predicate, iterable); + } + + @ExposedGet + public static PyString __doc__ = new PyString( + "dropwhile(predicate, iterable) --> dropwhile object\n\n" + + "Drop items from the iterable while predicate(item) is true.\n" + + "Afterwards, return every element until the iterable is exhausted."); + + /** + * Create an iterator that drops items from the iterable while predicate(item) + * equals true. After which every remaining item of the iterable is returned. + */ + @ExposedNew + @ExposedMethod + final void dropwhile___init__(PyObject[] args, String[] kwds) { + ArgParser ap = new ArgParser("dropwhile", args, kwds, new String[] {"predicate", "iterable"}, 2); + ap.noKeywords(); + PyObject predicate = ap.getPyObject(0); + PyObject iterable = ap.getPyObject(1); + dropwhile___init__(predicate, iterable); + } + + private void dropwhile___init__(PyObject predicate, PyObject iterable) { + iter = new itertools.WhileIterator(predicate, iterable, true); + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } +} diff --git a/src/org/python/modules/itertools/dropwhileDerived.java b/src/org/python/modules/itertools/dropwhileDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/dropwhileDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class dropwhileDerived extends dropwhile implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public dropwhileDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/groupby.java b/src/org/python/modules/itertools/groupby.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/groupby.java @@ -0,0 +1,125 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.ArgParser; +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyNone; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyTuple; +import org.python.core.PyType; +import org.python.core.PyXRange; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.groupby", base = PyObject.class) +public class groupby extends PyObject { + + public static final PyType TYPE = PyType.fromClass(groupby.class); + private PyIterator iter; + + public groupby() { + super(); + } + + public groupby(PyType subType) { + super(subType); + } + + public groupby(PyObject iterable) { + super(); + groupby___init__(iterable, Py.None); + } + + public groupby(PyObject iterable, PyObject keyfunc) { + super(); + groupby___init__(iterable, keyfunc); + } + + @ExposedGet + public static PyString __doc__ = new PyString( + "groupby(iterable[, keyfunc]) -> create an iterator which returns\n" + + "(key, sub-iterator) grouped by each value of key(value)."); + + /** + * Creates an iterator that returns the items of the iterable for which + * predicate(item) is true. If predicate is null + * (None) return the items that are true. + */ + @ExposedNew + @ExposedMethod + final void groupby___init__(PyObject[] args, String[] kwds) { + ArgParser ap = new ArgParser("groupby", args, kwds, "iterable", "key"); + if(args.length > 2){ + throw Py.TypeError("groupby takes two arguments, iterable and key"); + } + PyObject iterable = ap.getPyObject(0); + PyObject keyfunc = ap.getPyObject(1, Py.None); + + groupby___init__(iterable, keyfunc); + } + + private void groupby___init__(final PyObject iterable, final PyObject keyfunc) { + iter = new itertools.ItertoolsIterator() { + PyObject currentKey; + PyObject currentValue; + PyObject iterator = iterable.__iter__(); + PyObject targetKey = currentKey = currentValue = new PyXRange(0); + + public PyObject __iternext__() { + while (currentKey.equals(targetKey)) { + currentValue = nextElement(iterator); + if (currentValue == null) { + return null; + } + if (keyfunc == Py.None) { + currentKey = currentValue; + } else { + currentKey = keyfunc.__call__(currentValue); + } + } + targetKey = currentKey; + return new PyTuple(currentKey, new GroupByIterator()); + } + + class GroupByIterator extends itertools.ItertoolsIterator { + + private boolean completed = false; + + public PyObject __iternext__() { + final PyObject item = currentValue; + if (completed) { + return null; + } + currentValue = nextElement(iterator); + if (currentValue == null) { + completed = true; + } else { + if (keyfunc == Py.None) { + currentKey = currentValue; + } else { + currentKey = keyfunc.__call__(currentValue); + } + } + if (!currentKey.equals(targetKey)) { + completed = true; + } + return item; + } + } + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } +} diff --git a/src/org/python/modules/itertools/groupbyDerived.java b/src/org/python/modules/itertools/groupbyDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/groupbyDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class groupbyDerived extends groupby implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public groupbyDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/islice.java b/src/org/python/modules/itertools/islice.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/islice.java @@ -0,0 +1,141 @@ +package org.python.modules.itertools; + +import org.python.core.ArgParser; +import org.python.core.Py; +import org.python.core.PyInteger; +import org.python.core.PyNone; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.islice", base = PyObject.class) +public class islice extends PyObject { + + public static final PyType TYPE = PyType.fromClass(islice.class); + private itertools.ItertoolsIterator iter; + + @ExposedGet + public static PyString __doc__ = new PyString( + "islice(iterable, [start,] stop [, step]) --> islice object\n\n" + + "Return an iterator whose next() method returns selected values from an\n" + + "iterable. If start is specified, will skip all preceding elements;\n" + + "otherwise, start defaults to zero. Step defaults to one. If\n" + + "specified as another value, step determines how many values are \n" + + "skipped between successive calls. Works like a slice() on a list\n" + + "but returns an iterator."); + + public islice() { + super(); + } + + public islice(PyType subType) { + super(subType); + } + + /** + * @see #islice___init__(PyObject, PyObject, PyObject, PyObject) startObj defaults to 0 and stepObj to 1 + */ + public islice(PyObject iterable, PyObject stopObj) { + super(); + islice___init__(iterable, new PyInteger(0), stopObj, new PyInteger(1)); + } + + /** + * @see #islice___init__(PyObject, PyObject, PyObject, PyObject) stepObj defaults to 1 + */ + public islice(PyObject iterable, PyObject start, + PyObject stopObj) { + super(); + islice___init__(iterable, start, stopObj, new PyInteger(1)); + } + + @ExposedNew + @ExposedMethod + final void islice___init__(PyObject[] args, String[] kwds) { + ArgParser ap = new ArgParser("islice", args, kwds, new String[] { + "iterable", "start", "stop", "step"}, 2); + + PyObject iterable = ap.getPyObject(0); + if (args.length == 2) { + PyObject stopObj = ap.getPyObject(1); + islice___init__(iterable, new PyInteger(0), stopObj, new PyInteger(1)); + } + else { + PyObject startObj = ap.getPyObject(1); + PyObject stopObj = ap.getPyObject(2); + if (args.length == 3) { + islice___init__(iterable, startObj, stopObj, new PyInteger(1)); + } + else { + PyObject stepObj = ap.getPyObject(3); + islice___init__(iterable, startObj, stopObj, stepObj); + } + } + } + + /** + * Creates an iterator that returns selected values from an iterable. + * + * @param startObj + * the index of where in the iterable to start returning values + * @param stopObj + * the index of where in the iterable to stop returning values + * @param stepObj + * the number of steps to take between each call to next() + */ + private void islice___init__(final PyObject iterable, PyObject startObj, + PyObject stopObj, PyObject stepObj) { + final int start = itertools.py2int(startObj, 0, "Start argument must be a non-negative integer or None"); + final int step = itertools.py2int(stepObj, 1, "Step argument must be a non-negative integer or None"); + final int stopArg = itertools.py2int(stopObj, 0, "Stop argument must be a non-negative integer or None"); + final int stop = stopObj instanceof PyNone ? Integer.MAX_VALUE : stopArg; + + if (start < 0 || step < 0 || stop < 0) { + throw Py.ValueError("Indices for islice() must be non-negative integers"); + } + + if (step == 0) { + throw Py.ValueError("Step must be one or larger for islice()"); + } + + iter = new itertools.ItertoolsIterator() { + int counter = start; + + int lastCount = 0; + + PyObject iter = iterable.__iter__(); + + public PyObject __iternext__() { + PyObject result = null; + + // ensure we never move the underlying iterator past 'stop' + while (lastCount < Math.min(counter + 1, stop)) { + result = nextElement(iter); + lastCount++; + } + + if (lastCount - 1 == counter) { + counter += step; + return result; + } + + return null; + } + + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } +} diff --git a/src/org/python/modules/itertools/isliceDerived.java b/src/org/python/modules/itertools/isliceDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/isliceDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class isliceDerived extends islice implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public isliceDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/itertools.java b/src/org/python/modules/itertools/itertools.java --- a/src/org/python/modules/itertools/itertools.java +++ b/src/org/python/modules/itertools/itertools.java @@ -1,23 +1,14 @@ /* Copyright (c) Jython Developers */ package org.python.modules.itertools; -import java.util.ArrayList; -import java.util.List; - -import org.python.core.__builtin__; -import org.python.core.ArgParser; import org.python.core.ClassDictInit; import org.python.core.Py; import org.python.core.PyException; -import org.python.core.PyInteger; import org.python.core.PyIterator; import org.python.core.PyNone; import org.python.core.PyObject; import org.python.core.PyString; import org.python.core.PyTuple; -import org.python.core.PyXRange; - -import java.util.Arrays; //XXX /** * Functional tools for creating and using iterators. Java implementation of the CPython module @@ -83,65 +74,29 @@ dict.__setitem__("__name__", new PyString("itertools")); dict.__setitem__("__doc__", __doc__); dict.__setitem__("chain", chain.TYPE); + dict.__setitem__("combinations", combinations.TYPE); + dict.__setitem__("combinations_with_replacement", combinationsWithReplacement.TYPE); dict.__setitem__("compress", compress.TYPE); dict.__setitem__("cycle", cycle.TYPE); dict.__setitem__("count", count.TYPE); + dict.__setitem__("dropwhile", dropwhile.TYPE); + dict.__setitem__("groupby", groupby.TYPE); dict.__setitem__("imap", imap.TYPE); dict.__setitem__("ifilter", ifilter.TYPE); dict.__setitem__("ifilterfalse", ifilterfalse.TYPE); + dict.__setitem__("islice", islice.TYPE); dict.__setitem__("izip", izip.TYPE); + dict.__setitem__("izip_longest", izipLongest.TYPE); + dict.__setitem__("permutations", permutations.TYPE); + dict.__setitem__("product", product.TYPE); + dict.__setitem__("repeat", repeat.TYPE); + dict.__setitem__("starmap", starmap.TYPE); + dict.__setitem__("takewhile", takewhile.TYPE); // Hide from Python dict.__setitem__("classDictInit", null); dict.__setitem__("initClassExceptions", null); } - - public static PyString __doc__repeat = new PyString( - "'repeat(element [,times]) -> create an iterator which returns the element\n" - + "for the specified number of times. If not specified, returns the element\nendlessly."); - - /** - * Creates an iterator that returns the same object the number of times given by - * times. - */ - public static PyIterator repeat(final PyObject object, final int times) { - return new PyIterator() { - int counter = times; - - public PyObject __iternext__() { - if (counter > 0) { - counter--; - return object; - } - return null; - } - - public int __len__() { - return times; - } - - public PyString __repr__() { - return (PyString)(Py.newString("repeat(%r, %d)"). - __mod__(new PyTuple(object, Py.newInteger(counter)))); - } - }; - } - - /** - * Creates an iterator that returns the same object over and over again. - */ - public static PyIterator repeat(final PyObject object) { - return new PyIterator() { - public PyObject __iternext__() { - return object; - } - - public PyString __repr__() { - return (PyString)(Py.newString("repeat(%r)"). - __mod__(new PyTuple(object))); - } - }; - } public static PyString __doc__islice = new PyString( "islice(iterable, [start,] stop [, step]) --> islice object\n" @@ -151,7 +106,7 @@ + "skipped between successive calls. Works like a slice() on a list\nbut returns an iterator."); - private static int py2int(PyObject obj, int defaultValue, String msg) { + static int py2int(PyObject obj, int defaultValue, String msg) { if (obj instanceof PyNone) { return defaultValue; } else { @@ -169,71 +124,6 @@ return value; } } - /** - * Creates an iterator that returns selected values from an iterable. - * - * @param startObj - * the index of where in the iterable to start returning values - * @param stopObj - * the index of where in the iterable to stop returning values - * @param stepObj - * the number of steps to take beween each call to next() - */ - public static PyIterator islice(final PyObject iterable, PyObject startObj, - PyObject stopObj, PyObject stepObj) { - final int stop = py2int(stopObj, 0, "Stop argument must be a non-negative integer or None"); - final int start = py2int(startObj, 0, "Start argument must be a non-negative integer or None"); - final int step = py2int(stepObj, 1, "Step argument must be a non-negative integer or None"); - final boolean stopNone = stopObj instanceof PyNone; - - if (start < 0 || step < 0 || stop < 0) { - throw Py.ValueError("Indices for islice() must be non-negative integers"); - } - - if (step == 0) { - throw Py.ValueError("Step must be one or larger for islice()"); - } - - return new ItertoolsIterator() { - int counter = start; - - int lastCount = 0; - - PyObject iter = iterable.__iter__(); - - public PyObject __iternext__() { - PyObject result = null; - - if (counter >= stop && !stopNone) { - return null; - } - - while (lastCount <= counter) { - result = nextElement(iter); - lastCount++; - } - counter += step; - return result; - } - - }; - - } - - /** - * @see #islice(PyObject, PyObject, PyObject, PyObject) startObj defaults to 0 and stepObj to 1 - */ - public static PyIterator islice(PyObject iterable, PyObject stopObj) { - return islice(iterable, new PyInteger(0), stopObj, new PyInteger(1)); - } - - /** - * @see #islice(PyObject, PyObject, PyObject, PyObject) stepObj defaults to 1 - */ - public static PyIterator islice(PyObject iterable, PyObject start, - PyObject stopObj) { - return islice(iterable, start, stopObj, new PyInteger(1)); - } /** * Iterator base class for iterators returned by ifilter and @@ -280,47 +170,6 @@ } } - public static PyString __doc__starmap = new PyString( - "starmap(function, sequence) --> starmap object\n\nReturn an " - + "iterator whose values are returned from the function evaluated\nwith an argument tuple taken from the " - + "given sequence."); - - /** - * Create an iterator whose next() method returns the result - * of calling the function (first argument) with a tuple of arguments - * returned from the iterable (second argument). - * - * @param starargs - * [0] = callable function, [1] = iterable with argument tuples - */ - public static PyIterator starmap(PyObject[] starargs) { - if (starargs.length != 2) { - throw Py.TypeError("starmap requires 2 arguments, got " - + starargs.length); - } - final PyObject callable = starargs[0]; - final PyObject iterator = starargs[1].__iter__(); - - return new ItertoolsIterator() { - - public PyObject __iternext__() { - PyObject args = nextElement(iterator); - PyObject result = null; - - if (args != null) { - if (!args.getClass().isAssignableFrom(PyTuple.class)) { - throw Py.TypeError("iterator must return a tuple"); - } - PyTuple argTuple = (PyTuple) args; - // convert to array of PyObjects in call to function - result = callable.__call__(argTuple.getArray()); - } - return result; - } - - }; - } - /** * Iterator base class used by dropwhile() and takewhile. */ @@ -371,104 +220,6 @@ } } - public static PyString __doc__dropwhile = new PyString( - "dropwhile(predicate, iterable) --> dropwhile object\n\nDrop items " - + "from the iterable while predicate(item) is true.\nAfterwards, return every element until theiterable is exhausted."); - - /** - * Create an iterator that drops items from the iterable while prdicate(item) - * equals true. After which every remaining item of the iterable is returned. - */ - public static PyIterator dropwhile(PyObject predicate, PyObject iterable) { - return new WhileIterator(predicate, iterable, true); - } - - public static PyString __doc__takewhile = new PyString( - "takewhile(predicate, iterable) --> takewhile object\n\nReturn " - + "successive entries from an iterable as long as the \npredicate evaluates to true for each entry."); - - /** - * Create an iterator that returns items from the iterable while predicate(item) - * is true. After which iteration is stopped. - */ - public static PyIterator takewhile(PyObject predicate, PyObject iterable) { - return new WhileIterator(predicate, iterable, false); - } - - private final static class GroupBy extends ItertoolsIterator { - - private final PyObject iterator; - private final PyObject keyFunc; - private PyObject currentKey; - private PyObject currentValue; - private PyObject targetKey; - - private GroupBy(PyObject iterable, PyObject key) { - iterator = iterable.__iter__(); - keyFunc = key; - targetKey = currentKey = currentValue = new PyXRange(0); - } - - public PyObject __iternext__() { - while (currentKey.equals(targetKey)) { - currentValue = nextElement(iterator); - if (currentValue == null) { - return null; - } - if (keyFunc == null) { - currentKey = currentValue; - } else { - currentKey = keyFunc.__call__(currentValue); - } - } - targetKey = currentKey; - return new PyTuple(currentKey, new GroupByIterator()); - } - - private class GroupByIterator extends ItertoolsIterator { - - private boolean completed = false; - - public PyObject __iternext__() { - final PyObject item = currentValue; - if (completed) { - return null; - } - currentValue = nextElement(iterator); - if (currentValue == null) { - completed = true; - } else { - if (keyFunc == null) { - currentKey = currentValue; - } else { - currentKey = keyFunc.__call__(currentValue); - } - } - if (!currentKey.equals(targetKey)) { - completed = true; - } - return item; - } - } - } - - public static PyString __doc__groupby = new PyString( - "groupby(iterable[, keyfunc]) -> create an iterator which returns\n" + - "(key, sub-iterator) grouped by each value of key(value)."); - - /** - * Create an iterator which returns the pair (key, sub-iterator) grouped by key(value). - */ - public static PyIterator groupby(PyObject [] args, String [] kws) { - ArgParser ap = new ArgParser("groupby", args, kws, "iterable", "key"); - if(args.length > 2){ - throw Py.TypeError("groupby takes two arguments, iterable and key"); - } - PyObject iterable = ap.getPyObject(0); - PyObject key = ap.getPyObject(1, null); - return new GroupBy(iterable, key); - } - public static PyString __doc__tee = new PyString( "tee(iterable, n=2) --> tuple of n independent iterators."); @@ -486,235 +237,15 @@ return tee(iterable, 2); } - private static PyTuple makeIndexedTuple(PyTuple pool, int indices[]) { + static PyTuple makeIndexedTuple(PyTuple pool, int indices[]) { return makeIndexedTuple(pool, indices, indices.length); } - private static PyTuple makeIndexedTuple(PyTuple pool, int indices[], int end) { + static PyTuple makeIndexedTuple(PyTuple pool, int indices[], int end) { PyObject items[] = new PyObject[end]; for (int i = 0; i < end; i++) { items[i] = pool.__getitem__(indices[i]); } return new PyTuple(items); } - - public static PyIterator combinations(PyObject iterable, final int r) { - if (r < 0) throw Py.ValueError("r must be non-negative"); - final PyTuple pool = PyTuple.fromIterable(iterable); - final int n = pool.__len__(); - final int indices[] = new int[r]; - for (int i = 0; i < r; i++) { - indices[i] = i; - } - - return new ItertoolsIterator() { - boolean firstthru = true; - - @Override - public PyObject __iternext__() { - if (r > n) { return null; } - if (firstthru) { - firstthru = false; - return makeIndexedTuple(pool, indices); - } - int i; - for (i = r-1; i >= 0 && indices[i] == i+n-r ; i--); - if (i < 0) return null; - indices[i]++; - for (int j = i+1; j < r; j++) { - indices[j] = indices[j-1] + 1; - } - return makeIndexedTuple(pool, indices); - } - - - }; - } - - public static PyIterator combinations_with_replacement(PyObject iterable, final int r) { - final PyTuple pool = PyTuple.fromIterable(iterable); - final int n = pool.__len__(); - final int indices[] = new int[r]; - for (int i = 0; i < r; i++) { - indices[i] = 0; - } - - return new ItertoolsIterator() { - boolean firstthru = true; - - @Override - public PyObject __iternext__() { - if (n == 0 || r == 0) { - return null; - } - if (firstthru) { - firstthru = false; - return makeIndexedTuple(pool, indices); - } - int i; - for (i= r - 1 ; i >= 0 && indices[i] == n - 1; i--); - if (i < 0) return null; - indices[i]++; - for (int j = i + 1; j < r; j++) { - indices[j] = indices[j-1]; - } - return makeIndexedTuple(pool, indices); - } - }; - } - - public static PyIterator izip_longest(PyObject[] args, String[] kws) { - final int num_iterables; - final PyObject fillvalue; - if (kws.length == 1 && kws[0] == "fillvalue") { - fillvalue = args[args.length - 1]; - num_iterables = args.length - 1; - } else { - fillvalue = Py.None; - num_iterables = args.length; - } - - //XXX error checking on args - final PyObject iterators[] = new PyObject[num_iterables]; - final boolean exhausted[] = new boolean[num_iterables]; - for (int i = 0; i < num_iterables; i++) { - iterators[i] = args[i].__iter__(); - exhausted[i] = false; - } - - return new ItertoolsIterator() { - int unexhausted = num_iterables; - - @Override - public PyObject __iternext__() { - PyObject item[] = new PyObject[num_iterables]; - for (int i = 0; i < num_iterables; i++) { - if (exhausted[i]) { - item[i] = fillvalue; - } else { - PyObject elem = iterators[i].__iternext__(); - if (elem == null) { - unexhausted--; - exhausted[i] = true; - item[i] = fillvalue; - } else { - item[i] = elem; - } - } - } - if (unexhausted == 0) { - return null; - } else { - return new PyTuple(item); - } - } - }; - } - - public static PyIterator permutations(PyObject iterable, final int r) { - //XXX keyword args support - if (r < 0) throw Py.ValueError("r must be non-negative"); - final PyTuple pool = PyTuple.fromIterable(iterable); - final int n = pool.__len__(); - final int indices[] = new int[n]; - for (int i = 0; i < n; i++) { - indices[i] = i; - } - final int cycles[] = new int[r]; - for (int i = 0; i < r; i++) { - cycles[i] = n - i; - } - - return new ItertoolsIterator() { - boolean firstthru = true; - - @Override - public PyObject __iternext__() { - if (r > n) return null; - if (firstthru) { - firstthru = false; - return makeIndexedTuple(pool, indices, r); - } - for (int i = r - 1; i >= 0; i--) { - cycles[i] -= 1; - if (cycles[i] == 0) { - // rotate indices at the ith position - int first = indices[i]; - for (int j = i; j < n - 1; j++) { - indices[j] = indices[j + 1]; - } - indices[n - 1] = first; - cycles[i] = n - i; - } else { - int j = cycles[i]; - int index = indices[i]; - indices[i] = indices[n - j]; - indices[n - j] = index; - return makeIndexedTuple(pool, indices, r); - } - } - return null; - } - }; - } - - public static PyIterator product(PyObject [] args, String [] kws) { - final int repeat; - final int num_iterables; - if (kws.length == 1 && kws[0] == "repeat") { - repeat = args[args.length -1].asInt(); - num_iterables = args.length - 1; - } else { - repeat = 1; - num_iterables = args.length; - } - // XXX error checking on args! XXX - final int num_pools = num_iterables * repeat; - final PyTuple pools[] = new PyTuple[num_pools]; - for (int i = 0; i < num_iterables; i++) { - pools[i] = PyTuple.fromIterable(args[i]); - } - // Make repeat - 1 duplicates, in order - for (int r = 1; r < repeat; r++) { - for (int i = 0; i < num_iterables; i++) { - pools[r * num_iterables + i] = pools[i]; - } - } - final int indices[] = new int[num_pools]; - for (int i = 0; i < num_pools; i++) { - indices[i] = 0; - } - - return new ItertoolsIterator() { - boolean firstthru = true; - - @Override - public PyObject __iternext__() { - if (firstthru) { - firstthru = false; - return makeTuple(); - } - for (int i = num_pools - 1; i >= 0; i--) { - indices[i]++; - - if (indices[i] == pools[i].__len__()) { - indices[i] = 0; - } else { - return makeTuple(); - } - } - return null; - } - - private PyTuple makeTuple() { - PyObject items[] = new PyObject[num_pools]; - for (int i = 0; i < num_pools; i++) { - items[i] = pools[i].__getitem__(indices[i]); - } - return new PyTuple(items); - } - - }; - } - } diff --git a/src/org/python/modules/itertools/izip.java b/src/org/python/modules/itertools/izip.java --- a/src/org/python/modules/itertools/izip.java +++ b/src/org/python/modules/itertools/izip.java @@ -51,6 +51,8 @@ * (Code in this method is based on __builtin__.zip()). * */ + @ExposedNew + @ExposedMethod final void izip___init__(PyObject[] args, String[] kwds) { if (kwds.length > 0) { throw Py.TypeError(String.format("izip does not take keyword arguments")); diff --git a/src/org/python/modules/itertools/izipDerived.java b/src/org/python/modules/itertools/izipDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/izipDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class izipDerived extends izip implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public izipDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/izipLongest.java b/src/org/python/modules/itertools/izipLongest.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/izipLongest.java @@ -0,0 +1,115 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyTuple; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.izip_longest", base = PyObject.class) +public class izipLongest extends PyObject { + + public static final PyType TYPE = PyType.fromClass(izipLongest.class); + private PyIterator iter; + + public izipLongest() { + super(); + } + + public izipLongest(PyType subType) { + super(subType); + } + + public izipLongest(PyObject[] iterables, PyObject fillvalue) { + super(); + izipLongest___init__(iterables, fillvalue); + } + + @ExposedGet + public static PyString __doc__ = new PyString( + "izip_longest(iter1 [,iter2 [...]], [fillvalue=None]) --> izip_longest object\n\n" + + "Return an izip_longest object whose .next() method returns a tuple where\n" + + "the i-th element comes from the i-th iterable argument. The .next()\n" + + "method continues until the longest iterable in the argument sequence\n" + + "is exhausted and then it raises StopIteration. When the shorter iterables\n" + + "are exhausted, the fillvalue is substituted in their place. The fillvalue\n" + + "defaults to None or can be specified by a keyword argument."); + + /** + * Create an iterator that returns items from the iterable while predicate(item) + * is true. After which iteration is stopped. + */ + @ExposedNew + @ExposedMethod + final void izipLongest___init__(PyObject[] args, String[] kwds) { + + PyObject[] iterables; + PyObject fillvalue; + + if (kwds.length == 1 && kwds[0] == "fillvalue") { + fillvalue = args[args.length - 1]; + iterables = new PyObject[args.length - 1]; + System.arraycopy(args, 0, iterables, 0, args.length - 1); + } else { + fillvalue = Py.None; + iterables = args; + } + //XXX error checking on args + + izipLongest___init__(iterables, fillvalue); + } + + private void izipLongest___init__(final PyObject[] iterables, final PyObject fillvalue) { + final PyObject iterators[] = new PyObject[iterables.length]; + final boolean exhausted[] = new boolean[iterables.length]; + for (int i = 0; i < iterables.length; i++) { + iterators[i] = iterables[i].__iter__(); + exhausted[i] = false; + } + + iter = new itertools.ItertoolsIterator() { + int unexhausted = iterables.length; + + @Override + public PyObject __iternext__() { + PyObject item[] = new PyObject[iterables.length]; + for (int i = 0; i < iterables.length; i++) { + if (exhausted[i]) { + item[i] = fillvalue; + } else { + PyObject elem = iterators[i].__iternext__(); + if (elem == null) { + unexhausted--; + exhausted[i] = true; + item[i] = fillvalue; + } else { + item[i] = elem; + } + } + } + if (unexhausted == 0) { + return null; + } else { + return new PyTuple(item); + } + } + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } + +} diff --git a/src/org/python/modules/itertools/izipLongestDerived.java b/src/org/python/modules/itertools/izipLongestDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/izipLongestDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class izipLongestDerived extends izipLongest implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public izipLongestDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/permutations.java b/src/org/python/modules/itertools/permutations.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/permutations.java @@ -0,0 +1,117 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.ArgParser; +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyTuple; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.permutations", base = PyObject.class) +public class permutations extends PyObject { + public static final PyType TYPE = PyType.fromClass(permutations.class); + private PyIterator iter; + + @ExposedGet + public static PyString __doc__ = new PyString( + "permutations(iterable[, r]) --> permutations object\n\n" + + "Return successive r-length permutations of elements in the iterable.\n\n" + + "permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)"); + + public permutations() { + super(); + } + + public permutations(PyType subType) { + super(subType); + } + + public permutations(PyObject iterable, int r) { + super(); + permutations___init__(iterable, r); + } + + @ExposedNew + @ExposedMethod + final void permutations___init__(PyObject[] args, String[] kwds) { + if (args.length > 2) { + throw Py.TypeError("permutations() takes at most 2 arguments (3 given)"); + } + ArgParser ap = new ArgParser("permutations", args, kwds, "iterable", "r"); + PyObject iterable = ap.getPyObject(0); + PyObject r = ap.getPyObject(1, Py.None); + + int perm_length; + if (r == Py.None) { + perm_length = iterable.__len__(); + } + else { + perm_length = r.asInt(); + if (perm_length < 0) { + throw Py.ValueError("r must be non-negative"); + } + } + + permutations___init__(iterable, perm_length); + } + + private void permutations___init__(final PyObject iterable, final int r) { + final PyTuple pool = PyTuple.fromIterable(iterable); + final int n = pool.__len__(); + final int indices[] = new int[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + final int cycles[] = new int[r]; + for (int i = 0; i < r; i++) { + cycles[i] = n - i; + } + iter = new itertools.ItertoolsIterator() { + boolean firstthru = true; + + @Override + public PyObject __iternext__() { + if (r > n) return null; + if (firstthru) { + firstthru = false; + return itertools.makeIndexedTuple(pool, indices, r); + } + for (int i = r - 1; i >= 0; i--) { + cycles[i] -= 1; + if (cycles[i] == 0) { + // rotate indices at the ith position + int first = indices[i]; + for (int j = i; j < n - 1; j++) { + indices[j] = indices[j + 1]; + } + indices[n - 1] = first; + cycles[i] = n - i; + } else { + int j = cycles[i]; + int index = indices[i]; + indices[i] = indices[n - j]; + indices[n - j] = index; + return itertools.makeIndexedTuple(pool, indices, r); + } + } + return null; + } + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } +} diff --git a/src/org/python/modules/itertools/permutationsDerived.java b/src/org/python/modules/itertools/permutationsDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/permutationsDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class permutationsDerived extends permutations implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public permutationsDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/product.java b/src/org/python/modules/itertools/product.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/product.java @@ -0,0 +1,126 @@ +/* Copyright (c) 2012 Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyTuple; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.product", base = PyObject.class) +public class product extends PyObject { + + public static final PyType TYPE = PyType.fromClass(product.class); + private PyIterator iter; + + @ExposedGet + public static PyString __doc__ = new PyString( + "product(*iterables) --> product object\n\n" + + "Cartesian product of input iterables. Equivalent to nested for-loops.\n\n" + + "For example, product(A, B) returns the same as: ((x,y) for x in A for y in B).\n" + + "The leftmost iterators are in the outermost for-loop, so the output tuples\n" + + "cycle in a manner similar to an odometer (with the rightmost element changing\n" + + "on every iteration).\n\n" + + "To compute the product of an iterable with itself, specify the number\n" + + "of repetitions with the optional repeat keyword argument. For example,\n" + + "product(A, repeat=4) means the same as product(A, A, A, A).\n\n" + + "product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)\n" + + "product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ..."); + + public product() { + super(); + } + + public product(PyType subType) { + super(subType); + } + + public product(PyTuple[] tuples, int repeat) { + super(); + product___init__(tuples, repeat); + } + + @ExposedNew + @ExposedMethod + final void product___init__(PyObject[] args, String[] kws) { + final int repeat; + final int num_iterables; + if (kws.length == 1 && kws[0] == "repeat") { + repeat = args[args.length -1].asInt(); + if (repeat < 0) { + throw Py.ValueError("repeat argument cannot be negative"); + } + num_iterables = args.length - 1; + } else { + repeat = 1; + num_iterables = args.length; + } + final PyTuple tuples[] = new PyTuple[num_iterables]; + for (int i = 0; i < num_iterables; i++) { + tuples[i] = PyTuple.fromIterable(args[i]); + } + product___init__(tuples, repeat); + } + + private void product___init__(PyTuple[] tuples, int repeat) { + // Make repeat duplicates, in order + final int num_pools = tuples.length * repeat; + final PyTuple pools[] = new PyTuple[num_pools]; + for (int r = 0; r < repeat; r++) { + System.arraycopy(tuples, 0, pools, r * tuples.length, tuples.length); + } + final int indices[] = new int[num_pools]; + + iter = new itertools.ItertoolsIterator() { + boolean firstthru = true; + + @Override + public PyObject __iternext__() { + if (firstthru) { + for (PyTuple pool : pools) { + if (pool.__len__() == 0) { + return null; + } + } + firstthru = false; + return makeTuple(); + } + for (int i = num_pools - 1; i >= 0; i--) { + indices[i]++; + + if (indices[i] == pools[i].__len__()) { + indices[i] = 0; + } else { + return makeTuple(); + } + } + return null; + } + + private PyTuple makeTuple() { + PyObject items[] = new PyObject[num_pools]; + for (int i = 0; i < num_pools; i++) { + items[i] = pools[i].__getitem__(indices[i]); + } + return new PyTuple(items); + } + + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } + +} diff --git a/src/org/python/modules/itertools/productDerived.java b/src/org/python/modules/itertools/productDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/productDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class productDerived extends product implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public productDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/repeat.java b/src/org/python/modules/itertools/repeat.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/repeat.java @@ -0,0 +1,129 @@ +/* Copyright (c) 2012 Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.ArgParser; +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyTuple; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.repeat", base = PyObject.class) +public class repeat extends PyObject { + + public static final PyType TYPE = PyType.fromClass(repeat.class); + private PyIterator iter; + private PyObject object; + private int counter; + + @ExposedGet + public static PyString __doc__ = new PyString( + "'repeat(element [,times]) -> create an iterator which returns the element\n" + + "for the specified number of times. If not specified, returns the element\nendlessly."); + + public repeat() { + super(); + } + + public repeat(PyType subType) { + super(subType); + } + + public repeat(PyObject object) { + super(); + repeat___init__(object); + } + + public repeat(PyObject object, int times) { + super(); + repeat___init__(object, times); + } + + @ExposedNew + @ExposedMethod + final void repeat___init__(final PyObject[] args, String[] kwds) { + ArgParser ap = new ArgParser("repeat", args, kwds, new String[] {"object", "times"}, 1); + + PyObject object = ap.getPyObject(0); + if (args.length == 1) { + repeat___init__(object); + } + else { + int times = ap.getInt(1); + repeat___init__(object, times); + } + } + + /** + * Creates an iterator that returns the same object the number of times given by + * times. + */ + private void repeat___init__(final PyObject object, final int times) { + this.object = object; + if (times < 0) { + counter = 0; + } + else { + counter = times; + } + iter = new PyIterator() { + + public PyObject __iternext__() { + if (counter > 0) { + counter--; + return object; + } + return null; + } + + }; + } + + /** + * Creates an iterator that returns the same object over and over again. + */ + private void repeat___init__(final PyObject object) { + this.object = object; + counter = -1; + iter = new PyIterator() { + public PyObject __iternext__() { + return object; + } + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } + + @ExposedMethod + public int __len__() { + if (counter < 0) { + throw Py.TypeError("object of type 'itertools.repeat' has no len()"); + } + return counter; + } + + @ExposedMethod + public PyString __repr__() { + if (counter >= 0) { + return (PyString)(Py.newString("repeat(%r, %d)"). + __mod__(new PyTuple(object, Py.newInteger(counter)))); + } + else { + return (PyString)(Py.newString("repeat(%r)"). + __mod__(new PyTuple(object))); + } + } +} diff --git a/src/org/python/modules/itertools/repeatDerived.java b/src/org/python/modules/itertools/repeatDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/repeatDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class repeatDerived extends repeat implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public repeatDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/starmap.java b/src/org/python/modules/itertools/starmap.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/starmap.java @@ -0,0 +1,88 @@ +/* Copyright (c) 2012 Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyTuple; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.starmap", base = PyObject.class) +public class starmap extends PyObject { + + public static final PyType TYPE = PyType.fromClass(starmap.class); + private PyIterator iter; + + @ExposedGet + public static PyString __doc__ = new PyString( + "starmap(function, sequence) --> starmap object\n\nReturn an " + + "iterator whose values are returned from the function evaluated\nwith an argument tuple taken from the " + + "given sequence."); + + public starmap() { + super(); + } + + public starmap(PyType subType) { + super(subType); + } + + public starmap(PyObject callable, PyObject iterator) { + super(); + starmap___init__(callable, iterator); + } + + /** + * Create an iterator whose next() method returns the result + * of calling the function (first argument) with a tuple of arguments + * returned from the iterable (second argument). + * + * @param starargs + * [0] = callable function, [1] = iterable with argument tuples + */ + @ExposedNew + @ExposedMethod + final void starmap___init__(PyObject[] starargs, String[] kwds) { + if (starargs.length != 2) { + throw Py.TypeError("starmap requires 2 arguments, got " + + starargs.length); + } + final PyObject callable = starargs[0]; + final PyObject iterator = starargs[1].__iter__(); + + starmap___init__(callable, iterator); + } + + private void starmap___init__(final PyObject callable, final PyObject iterator) { + iter = new itertools.ItertoolsIterator() { + + public PyObject __iternext__() { + PyObject args = nextElement(iterator); + PyObject result = null; + + if (args != null) { + PyTuple argTuple = PyTuple.fromIterable(args); + // convert to array of PyObjects in call to function + result = callable.__call__(argTuple.getArray()); + } + return result; + } + + }; + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } +} diff --git a/src/org/python/modules/itertools/starmapDerived.java b/src/org/python/modules/itertools/starmapDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/starmapDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class starmapDerived extends starmap implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public starmapDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/org/python/modules/itertools/takewhile.java b/src/org/python/modules/itertools/takewhile.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/takewhile.java @@ -0,0 +1,66 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules.itertools; + +import org.python.core.ArgParser; +import org.python.core.PyIterator; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + + at ExposedType(name = "itertools.takewhile", base = PyObject.class) +public class takewhile extends PyObject { + + public static final PyType TYPE = PyType.fromClass(takewhile.class); + private PyIterator iter; + + public takewhile() { + super(); + } + + public takewhile(PyType subType) { + super(subType); + } + + public takewhile(PyObject predicate, PyObject iterable) { + super(); + takewhile___init__(predicate, iterable); + } + + @ExposedGet + public static PyString __doc__ = new PyString( + "takewhile(predicate, iterable) --> takewhile object\n\n" + + "Return successive entries from an iterable as long as the \n" + + "predicate evaluates to true for each entry."); + + /** + * Create an iterator that returns items from the iterable while predicate(item) + * is true. After which iteration is stopped. + */ + @ExposedNew + @ExposedMethod + final void takewhile___init__(PyObject[] args, String[] kwds) { + ArgParser ap = new ArgParser("takewhile", args, kwds, new String[] {"predicate", "iterable"}, 2); + ap.noKeywords(); + PyObject predicate = ap.getPyObject(0); + PyObject iterable = ap.getPyObject(1); + takewhile___init__(predicate, iterable); + } + + private void takewhile___init__(PyObject predicate, PyObject iterable) { + iter = new itertools.WhileIterator(predicate, iterable, false); + } + + @ExposedMethod + public PyObject __iter__() { + return iter; + } + + @ExposedMethod + public PyObject next() { + return iter.next(); + } +} diff --git a/src/org/python/modules/itertools/takewhileDerived.java b/src/org/python/modules/itertools/takewhileDerived.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/itertools/takewhileDerived.java @@ -0,0 +1,1125 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules.itertools; + +import java.io.Serializable; +import org.python.core.*; + +public class takewhileDerived extends takewhile implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + private PyObject dict; + + public PyObject fastGetDict() { + return dict; + } + + public PyObject getDict() { + return dict; + } + + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) { + dict=newDict; + } else { + throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName()); + } + } + + public void delDict() { + // deleting an object's instance dict makes it grow a new one + dict=new PyStringMap(); + } + + public takewhileDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + dict=subtype.instDict(); + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __dir__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__dir__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__dir__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyObject[]where_type=new PyObject[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) { + return-2; + } + int c=res.asInt(); + return c<0?-1:c>0?1:0; + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + PyObject o=impl.__get__(this,self_type).__call__(); + Class c=o.getClass(); + if (c!=PyInteger.class&&c!=PyBoolean.class) { + throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName())); + } + return o.__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (exc.match(Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (exc.match(Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr_ex__(String name) { + return Deriveds.__findattr_ex__(this,name); + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyObject[]args,String[]keywords) { + Deriveds.dispatch__init__(this,args,keywords); + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public Object __coerce_ex__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__coerce__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(o); + if (res==Py.NotImplemented) + return Py.None; + if (!(res instanceof PyTuple)) + throw Py.TypeError("__coerce__ didn't return a 2-tuple"); + return((PyTuple)res).getArray(); + } + return super.__coerce_ex__(o); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} diff --git a/src/templates/array.derived b/src/templates/PyTeeIterator.derived copy from src/templates/array.derived copy to src/templates/PyTeeIterator.derived --- a/src/templates/array.derived +++ b/src/templates/PyTeeIterator.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: PyTeeIterator want_dict: true ctr: incl: object diff --git a/src/templates/array.derived b/src/templates/combinations.derived copy from src/templates/array.derived copy to src/templates/combinations.derived --- a/src/templates/array.derived +++ b/src/templates/combinations.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: combinations want_dict: true ctr: incl: object diff --git a/src/templates/array.derived b/src/templates/combinationsWithReplacement.derived copy from src/templates/array.derived copy to src/templates/combinationsWithReplacement.derived --- a/src/templates/array.derived +++ b/src/templates/combinationsWithReplacement.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: combinationsWithReplacement want_dict: true ctr: incl: object diff --git a/src/templates/array.derived b/src/templates/dropwhile.derived copy from src/templates/array.derived copy to src/templates/dropwhile.derived --- a/src/templates/array.derived +++ b/src/templates/dropwhile.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: dropwhile want_dict: true ctr: incl: object diff --git a/src/templates/array.derived b/src/templates/groupby.derived copy from src/templates/array.derived copy to src/templates/groupby.derived --- a/src/templates/array.derived +++ b/src/templates/groupby.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: groupby want_dict: true ctr: incl: object diff --git a/src/templates/array.derived b/src/templates/islice.derived copy from src/templates/array.derived copy to src/templates/islice.derived --- a/src/templates/array.derived +++ b/src/templates/islice.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: islice want_dict: true ctr: incl: object diff --git a/src/templates/array.derived b/src/templates/izip.derived copy from src/templates/array.derived copy to src/templates/izip.derived --- a/src/templates/array.derived +++ b/src/templates/izip.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: izip want_dict: true ctr: incl: object diff --git a/src/templates/array.derived b/src/templates/izipLongest.derived copy from src/templates/array.derived copy to src/templates/izipLongest.derived --- a/src/templates/array.derived +++ b/src/templates/izipLongest.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: izipLongest want_dict: true ctr: incl: object diff --git a/src/templates/mappings b/src/templates/mappings --- a/src/templates/mappings +++ b/src/templates/mappings @@ -13,10 +13,26 @@ bytearray.derived:org.python.core.PyByteArrayDerived classmethod.derived:org.python.core.PyClassMethodDerived chain.derived:org.python.modules.itertools.chainDerived +combinationsWithReplacement.derived:org.python.modules.itertools.combinationsWithReplacementDerived +combinations.derived:org.python.modules.itertools.combinationsDerived compress.derived:org.python.modules.itertools.compressDerived +count.derived:org.python.modules.itertools.countDerived cycle.derived:org.python.modules.itertools.cycleDerived +dropwhile.derived:org.python.modules.itertools.dropwhileDerived +groupby.derived:org.python.modules.itertools.groupbyDerived +ifilter.derived:org.python.modules.itertools.ifilterDerived +ifilterfalse.derived:org.python.modules.itertools.ifilterfalseDerived +islice.derived:org.python.modules.itertools.isliceDerived +izip.derived:org.python.modules.itertools.izipDerived +izipLongest.derived:org.python.modules.itertools.izipLongestDerived +islice.derived:org.python.modules.itertools.isliceDerived +PyTeeIterator.derived:org.python.modules.itertools.PyTeeIteratorDerived +product.derived:org.python.modules.itertools.productDerived +permutations.derived:org.python.modules.itertools.permutationsDerived +repeat.derived:org.python.modules.itertools.repeatDerived +starmap.derived:org.python.modules.itertools.starmapDerived +takewhile.derived:org.python.modules.itertools.takewhileDerived complex.derived:org.python.core.PyComplexDerived -count.derived:org.python.modules.itertools.countDerived defaultdict.derived:org.python.modules._collections.PyDefaultDictDerived deque.derived:org.python.modules._collections.PyDequeDerived dialect.derived:org.python.modules._csv.PyDialectDerived @@ -25,8 +41,6 @@ file.derived:org.python.core.PyFileDerived float.derived:org.python.core.PyFloatDerived frozenset.derived:org.python.core.PyFrozenSetDerived -ifilter.derived:org.python.modules.itertools.ifilterDerived -ifilterfalse.derived:org.python.modules.itertools.ifilterfalseDerived int.derived:org.python.core.PyIntegerDerived list.derived:org.python.core.PyListDerived long.derived:org.python.core.PyLongDerived diff --git a/src/templates/array.derived b/src/templates/permutations.derived copy from src/templates/array.derived copy to src/templates/permutations.derived --- a/src/templates/array.derived +++ b/src/templates/permutations.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: permutations want_dict: true ctr: incl: object diff --git a/src/templates/chain.derived b/src/templates/product.derived copy from src/templates/chain.derived copy to src/templates/product.derived --- a/src/templates/chain.derived +++ b/src/templates/product.derived @@ -1,4 +1,4 @@ -base_class: chain +base_class: product want_dict: true ctr: incl: object diff --git a/src/templates/chain.derived b/src/templates/repeat.derived copy from src/templates/chain.derived copy to src/templates/repeat.derived --- a/src/templates/chain.derived +++ b/src/templates/repeat.derived @@ -1,4 +1,4 @@ -base_class: chain +base_class: repeat want_dict: true ctr: incl: object diff --git a/src/templates/chain.derived b/src/templates/starmap.derived copy from src/templates/chain.derived copy to src/templates/starmap.derived --- a/src/templates/chain.derived +++ b/src/templates/starmap.derived @@ -1,4 +1,4 @@ -base_class: chain +base_class: starmap want_dict: true ctr: incl: object diff --git a/src/templates/array.derived b/src/templates/takewhile.derived copy from src/templates/array.derived copy to src/templates/takewhile.derived --- a/src/templates/array.derived +++ b/src/templates/takewhile.derived @@ -1,4 +1,4 @@ -base_class: PyArray +base_class: takewhile want_dict: true ctr: incl: object -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Tue Jul 3 20:21:19 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Tue, 3 Jul 2012 20:21:19 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_from=3A?= Message-ID: <3WRYYq5hMxzMh6@mail.python.org> http://hg.python.org/jython/rev/9fb661e6ecb7 changeset: 6778:9fb661e6ecb7 user: Frank Wierzbicki date: Tue Jul 03 10:58:52 2012 -0700 summary: from: http://hg.python.org/cpython/Lib/test/test_itertools.py at 22db03646d9b files: Lib/test/test_itertools.py | 1659 ++++++++++++++++++++++++ 1 files changed, 1659 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_itertools.py @@ -0,0 +1,1659 @@ +import unittest +from test import test_support +from itertools import * +from weakref import proxy +from decimal import Decimal +from fractions import Fraction +import sys +import operator +import random +import copy +import pickle +from functools import reduce +maxsize = test_support.MAX_Py_ssize_t +minsize = -maxsize-1 + +def onearg(x): + 'Test function of one argument' + return 2*x + +def errfunc(*args): + 'Test function that raises an error' + raise ValueError + +def gen3(): + 'Non-restartable source sequence' + for i in (0, 1, 2): + yield i + +def isEven(x): + 'Test predicate' + return x%2==0 + +def isOdd(x): + 'Test predicate' + return x%2==1 + +class StopNow: + 'Class emulating an empty iterable.' + def __iter__(self): + return self + def next(self): + raise StopIteration + +def take(n, seq): + 'Convenience function for partially consuming a long of infinite iterable' + return list(islice(seq, n)) + +def prod(iterable): + return reduce(operator.mul, iterable, 1) + +def fact(n): + 'Factorial' + return prod(range(1, n+1)) + +class TestBasicOps(unittest.TestCase): + def test_chain(self): + + def chain2(*iterables): + 'Pure python version in the docs' + for it in iterables: + for element in it: + yield element + + for c in (chain, chain2): + self.assertEqual(list(c('abc', 'def')), list('abcdef')) + self.assertEqual(list(c('abc')), list('abc')) + self.assertEqual(list(c('')), []) + self.assertEqual(take(4, c('abc', 'def')), list('abcd')) + self.assertRaises(TypeError, list,c(2, 3)) + + def test_chain_from_iterable(self): + self.assertEqual(list(chain.from_iterable(['abc', 'def'])), list('abcdef')) + self.assertEqual(list(chain.from_iterable(['abc'])), list('abc')) + self.assertEqual(list(chain.from_iterable([''])), []) + self.assertEqual(take(4, chain.from_iterable(['abc', 'def'])), list('abcd')) + self.assertRaises(TypeError, list, chain.from_iterable([2, 3])) + + def test_combinations(self): + self.assertRaises(TypeError, combinations, 'abc') # missing r argument + self.assertRaises(TypeError, combinations, 'abc', 2, 1) # too many arguments + self.assertRaises(TypeError, combinations, None) # pool is not iterable + self.assertRaises(ValueError, combinations, 'abc', -2) # r is negative + self.assertEqual(list(combinations('abc', 32)), []) # r > n + self.assertEqual(list(combinations(range(4), 3)), + [(0,1,2), (0,1,3), (0,2,3), (1,2,3)]) + + def combinations1(iterable, r): + 'Pure python version shown in the docs' + pool = tuple(iterable) + n = len(pool) + if r > n: + return + indices = range(r) + yield tuple(pool[i] for i in indices) + while 1: + for i in reversed(range(r)): + if indices[i] != i + n - r: + break + else: + return + indices[i] += 1 + for j in range(i+1, r): + indices[j] = indices[j-1] + 1 + yield tuple(pool[i] for i in indices) + + def combinations2(iterable, r): + 'Pure python version shown in the docs' + pool = tuple(iterable) + n = len(pool) + for indices in permutations(range(n), r): + if sorted(indices) == list(indices): + yield tuple(pool[i] for i in indices) + + def combinations3(iterable, r): + 'Pure python version from cwr()' + pool = tuple(iterable) + n = len(pool) + for indices in combinations_with_replacement(range(n), r): + if len(set(indices)) == r: + yield tuple(pool[i] for i in indices) + + for n in range(7): + values = [5*x-12 for x in range(n)] + for r in range(n+2): + result = list(combinations(values, r)) + self.assertEqual(len(result), 0 if r>n else fact(n) // fact(r) // fact(n-r)) # right number of combs + self.assertEqual(len(result), len(set(result))) # no repeats + self.assertEqual(result, sorted(result)) # lexicographic order + for c in result: + self.assertEqual(len(c), r) # r-length combinations + self.assertEqual(len(set(c)), r) # no duplicate elements + self.assertEqual(list(c), sorted(c)) # keep original ordering + self.assertTrue(all(e in values for e in c)) # elements taken from input iterable + self.assertEqual(list(c), + [e for e in values if e in c]) # comb is a subsequence of the input iterable + self.assertEqual(result, list(combinations1(values, r))) # matches first pure python version + self.assertEqual(result, list(combinations2(values, r))) # matches second pure python version + self.assertEqual(result, list(combinations3(values, r))) # matches second pure python version + + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_combinations_tuple_reuse(self): + self.assertEqual(len(set(map(id, combinations('abcde', 3)))), 1) + self.assertNotEqual(len(set(map(id, list(combinations('abcde', 3))))), 1) + + def test_combinations_with_replacement(self): + cwr = combinations_with_replacement + self.assertRaises(TypeError, cwr, 'abc') # missing r argument + self.assertRaises(TypeError, cwr, 'abc', 2, 1) # too many arguments + self.assertRaises(TypeError, cwr, None) # pool is not iterable + self.assertRaises(ValueError, cwr, 'abc', -2) # r is negative + self.assertEqual(list(cwr('ABC', 2)), + [('A','A'), ('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')]) + + def cwr1(iterable, r): + 'Pure python version shown in the docs' + # number items returned: (n+r-1)! / r! / (n-1)! when n>0 + pool = tuple(iterable) + n = len(pool) + if not n and r: + return + indices = [0] * r + yield tuple(pool[i] for i in indices) + while 1: + for i in reversed(range(r)): + if indices[i] != n - 1: + break + else: + return + indices[i:] = [indices[i] + 1] * (r - i) + yield tuple(pool[i] for i in indices) + + def cwr2(iterable, r): + 'Pure python version shown in the docs' + pool = tuple(iterable) + n = len(pool) + for indices in product(range(n), repeat=r): + if sorted(indices) == list(indices): + yield tuple(pool[i] for i in indices) + + def numcombs(n, r): + if not n: + return 0 if r else 1 + return fact(n+r-1) // fact(r) // fact(n-1) + + for n in range(7): + values = [5*x-12 for x in range(n)] + for r in range(n+2): + result = list(cwr(values, r)) + + self.assertEqual(len(result), numcombs(n, r)) # right number of combs + self.assertEqual(len(result), len(set(result))) # no repeats + self.assertEqual(result, sorted(result)) # lexicographic order + + regular_combs = list(combinations(values, r)) # compare to combs without replacement + if n == 0 or r <= 1: + self.assertEqual(result, regular_combs) # cases that should be identical + else: + self.assertTrue(set(result) >= set(regular_combs)) # rest should be supersets of regular combs + + for c in result: + self.assertEqual(len(c), r) # r-length combinations + noruns = [k for k,v in groupby(c)] # combo without consecutive repeats + self.assertEqual(len(noruns), len(set(noruns))) # no repeats other than consecutive + self.assertEqual(list(c), sorted(c)) # keep original ordering + self.assertTrue(all(e in values for e in c)) # elements taken from input iterable + self.assertEqual(noruns, + [e for e in values if e in c]) # comb is a subsequence of the input iterable + self.assertEqual(result, list(cwr1(values, r))) # matches first pure python version + self.assertEqual(result, list(cwr2(values, r))) # matches second pure python version + + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_combinations_with_replacement_tuple_reuse(self): + cwr = combinations_with_replacement + self.assertEqual(len(set(map(id, cwr('abcde', 3)))), 1) + self.assertNotEqual(len(set(map(id, list(cwr('abcde', 3))))), 1) + + def test_permutations(self): + self.assertRaises(TypeError, permutations) # too few arguments + self.assertRaises(TypeError, permutations, 'abc', 2, 1) # too many arguments + self.assertRaises(TypeError, permutations, None) # pool is not iterable + self.assertRaises(ValueError, permutations, 'abc', -2) # r is negative + self.assertEqual(list(permutations('abc', 32)), []) # r > n + self.assertRaises(TypeError, permutations, 'abc', 's') # r is not an int or None + self.assertEqual(list(permutations(range(3), 2)), + [(0,1), (0,2), (1,0), (1,2), (2,0), (2,1)]) + + def permutations1(iterable, r=None): + 'Pure python version shown in the docs' + pool = tuple(iterable) + n = len(pool) + r = n if r is None else r + if r > n: + return + indices = range(n) + cycles = range(n, n-r, -1) + yield tuple(pool[i] for i in indices[:r]) + while n: + for i in reversed(range(r)): + cycles[i] -= 1 + if cycles[i] == 0: + indices[i:] = indices[i+1:] + indices[i:i+1] + cycles[i] = n - i + else: + j = cycles[i] + indices[i], indices[-j] = indices[-j], indices[i] + yield tuple(pool[i] for i in indices[:r]) + break + else: + return + + def permutations2(iterable, r=None): + 'Pure python version shown in the docs' + pool = tuple(iterable) + n = len(pool) + r = n if r is None else r + for indices in product(range(n), repeat=r): + if len(set(indices)) == r: + yield tuple(pool[i] for i in indices) + + for n in range(7): + values = [5*x-12 for x in range(n)] + for r in range(n+2): + result = list(permutations(values, r)) + self.assertEqual(len(result), 0 if r>n else fact(n) // fact(n-r)) # right number of perms + self.assertEqual(len(result), len(set(result))) # no repeats + self.assertEqual(result, sorted(result)) # lexicographic order + for p in result: + self.assertEqual(len(p), r) # r-length permutations + self.assertEqual(len(set(p)), r) # no duplicate elements + self.assertTrue(all(e in values for e in p)) # elements taken from input iterable + self.assertEqual(result, list(permutations1(values, r))) # matches first pure python version + self.assertEqual(result, list(permutations2(values, r))) # matches second pure python version + if r == n: + self.assertEqual(result, list(permutations(values, None))) # test r as None + self.assertEqual(result, list(permutations(values))) # test default r + + @test_support.impl_detail("tuple resuse is CPython specific") + def test_permutations_tuple_reuse(self): + self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1) + self.assertNotEqual(len(set(map(id, list(permutations('abcde', 3))))), 1) + + def test_combinatorics(self): + # Test relationships between product(), permutations(), + # combinations() and combinations_with_replacement(). + + for n in range(6): + s = 'ABCDEFG'[:n] + for r in range(8): + prod = list(product(s, repeat=r)) + cwr = list(combinations_with_replacement(s, r)) + perm = list(permutations(s, r)) + comb = list(combinations(s, r)) + + # Check size + self.assertEqual(len(prod), n**r) + self.assertEqual(len(cwr), (fact(n+r-1) // fact(r) // fact(n-1)) if n else (not r)) + self.assertEqual(len(perm), 0 if r>n else fact(n) // fact(n-r)) + self.assertEqual(len(comb), 0 if r>n else fact(n) // fact(r) // fact(n-r)) + + # Check lexicographic order without repeated tuples + self.assertEqual(prod, sorted(set(prod))) + self.assertEqual(cwr, sorted(set(cwr))) + self.assertEqual(perm, sorted(set(perm))) + self.assertEqual(comb, sorted(set(comb))) + + # Check interrelationships + self.assertEqual(cwr, [t for t in prod if sorted(t)==list(t)]) # cwr: prods which are sorted + self.assertEqual(perm, [t for t in prod if len(set(t))==r]) # perm: prods with no dups + self.assertEqual(comb, [t for t in perm if sorted(t)==list(t)]) # comb: perms that are sorted + self.assertEqual(comb, [t for t in cwr if len(set(t))==r]) # comb: cwrs without dups + self.assertEqual(comb, filter(set(cwr).__contains__, perm)) # comb: perm that is a cwr + self.assertEqual(comb, filter(set(perm).__contains__, cwr)) # comb: cwr that is a perm + self.assertEqual(comb, sorted(set(cwr) & set(perm))) # comb: both a cwr and a perm + + def test_compress(self): + self.assertEqual(list(compress(data='ABCDEF', selectors=[1,0,1,0,1,1])), list('ACEF')) + self.assertEqual(list(compress('ABCDEF', [1,0,1,0,1,1])), list('ACEF')) + self.assertEqual(list(compress('ABCDEF', [0,0,0,0,0,0])), list('')) + self.assertEqual(list(compress('ABCDEF', [1,1,1,1,1,1])), list('ABCDEF')) + self.assertEqual(list(compress('ABCDEF', [1,0,1])), list('AC')) + self.assertEqual(list(compress('ABC', [0,1,1,1,1,1])), list('BC')) + n = 10000 + data = chain.from_iterable(repeat(range(6), n)) + selectors = chain.from_iterable(repeat((0, 1))) + self.assertEqual(list(compress(data, selectors)), [1,3,5] * n) + self.assertRaises(TypeError, compress, None, range(6)) # 1st arg not iterable + self.assertRaises(TypeError, compress, range(6), None) # 2nd arg not iterable + self.assertRaises(TypeError, compress, range(6)) # too few args + self.assertRaises(TypeError, compress, range(6), None) # too many args + + def test_count(self): + self.assertEqual(zip('abc',count()), [('a', 0), ('b', 1), ('c', 2)]) + self.assertEqual(zip('abc',count(3)), [('a', 3), ('b', 4), ('c', 5)]) + self.assertEqual(take(2, zip('abc',count(3))), [('a', 3), ('b', 4)]) + self.assertEqual(take(2, zip('abc',count(-1))), [('a', -1), ('b', 0)]) + self.assertEqual(take(2, zip('abc',count(-3))), [('a', -3), ('b', -2)]) + self.assertRaises(TypeError, count, 2, 3, 4) + self.assertRaises(TypeError, count, 'a') + self.assertEqual(list(islice(count(maxsize-5), 10)), range(maxsize-5, maxsize+5)) + self.assertEqual(list(islice(count(-maxsize-5), 10)), range(-maxsize-5, -maxsize+5)) + c = count(3) + self.assertEqual(repr(c), 'count(3)') + c.next() + self.assertEqual(repr(c), 'count(4)') + c = count(-9) + self.assertEqual(repr(c), 'count(-9)') + c.next() + self.assertEqual(repr(count(10.25)), 'count(10.25)') + self.assertEqual(c.next(), -8) + for i in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 10, sys.maxint-5, sys.maxint+5): + # Test repr (ignoring the L in longs) + r1 = repr(count(i)).replace('L', '') + r2 = 'count(%r)'.__mod__(i).replace('L', '') + self.assertEqual(r1, r2) + + # check copy, deepcopy, pickle + for value in -3, 3, sys.maxint-5, sys.maxint+5: + c = count(value) + self.assertEqual(next(copy.copy(c)), value) + self.assertEqual(next(copy.deepcopy(c)), value) + self.assertEqual(next(pickle.loads(pickle.dumps(c))), value) + + def test_count_with_stride(self): + self.assertEqual(zip('abc',count(2,3)), [('a', 2), ('b', 5), ('c', 8)]) + self.assertEqual(zip('abc',count(start=2,step=3)), + [('a', 2), ('b', 5), ('c', 8)]) + self.assertEqual(zip('abc',count(step=-1)), + [('a', 0), ('b', -1), ('c', -2)]) + self.assertEqual(zip('abc',count(2,0)), [('a', 2), ('b', 2), ('c', 2)]) + self.assertEqual(zip('abc',count(2,1)), [('a', 2), ('b', 3), ('c', 4)]) + self.assertEqual(take(20, count(maxsize-15, 3)), take(20, range(maxsize-15, maxsize+100, 3))) + self.assertEqual(take(20, count(-maxsize-15, 3)), take(20, range(-maxsize-15,-maxsize+100, 3))) + self.assertEqual(take(3, count(2, 3.25-4j)), [2, 5.25-4j, 8.5-8j]) + self.assertEqual(take(3, count(Decimal('1.1'), Decimal('.1'))), + [Decimal('1.1'), Decimal('1.2'), Decimal('1.3')]) + self.assertEqual(take(3, count(Fraction(2,3), Fraction(1,7))), + [Fraction(2,3), Fraction(17,21), Fraction(20,21)]) + self.assertEqual(repr(take(3, count(10, 2.5))), repr([10, 12.5, 15.0])) + c = count(3, 5) + self.assertEqual(repr(c), 'count(3, 5)') + c.next() + self.assertEqual(repr(c), 'count(8, 5)') + c = count(-9, 0) + self.assertEqual(repr(c), 'count(-9, 0)') + c.next() + self.assertEqual(repr(c), 'count(-9, 0)') + c = count(-9, -3) + self.assertEqual(repr(c), 'count(-9, -3)') + c.next() + self.assertEqual(repr(c), 'count(-12, -3)') + self.assertEqual(repr(c), 'count(-12, -3)') + self.assertEqual(repr(count(10.5, 1.25)), 'count(10.5, 1.25)') + self.assertEqual(repr(count(10.5, 1)), 'count(10.5)') # suppress step=1 when it's an int + self.assertEqual(repr(count(10.5, 1.00)), 'count(10.5, 1.0)') # do show float values lilke 1.0 + for i in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 10, sys.maxint-5, sys.maxint+5): + for j in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 1, 10, sys.maxint-5, sys.maxint+5): + # Test repr (ignoring the L in longs) + r1 = repr(count(i, j)).replace('L', '') + if j == 1: + r2 = ('count(%r)' % i).replace('L', '') + else: + r2 = ('count(%r, %r)' % (i, j)).replace('L', '') + self.assertEqual(r1, r2) + + def test_cycle(self): + self.assertEqual(take(10, cycle('abc')), list('abcabcabca')) + self.assertEqual(list(cycle('')), []) + self.assertRaises(TypeError, cycle) + self.assertRaises(TypeError, cycle, 5) + self.assertEqual(list(islice(cycle(gen3()),10)), [0,1,2,0,1,2,0,1,2,0]) + + def test_groupby(self): + # Check whether it accepts arguments correctly + self.assertEqual([], list(groupby([]))) + self.assertEqual([], list(groupby([], key=id))) + self.assertRaises(TypeError, list, groupby('abc', [])) + self.assertRaises(TypeError, groupby, None) + self.assertRaises(TypeError, groupby, 'abc', lambda x:x, 10) + + # Check normal input + s = [(0, 10, 20), (0, 11,21), (0,12,21), (1,13,21), (1,14,22), + (2,15,22), (3,16,23), (3,17,23)] + dup = [] + for k, g in groupby(s, lambda r:r[0]): + for elem in g: + self.assertEqual(k, elem[0]) + dup.append(elem) + self.assertEqual(s, dup) + + # Check nested case + dup = [] + for k, g in groupby(s, lambda r:r[0]): + for ik, ig in groupby(g, lambda r:r[2]): + for elem in ig: + self.assertEqual(k, elem[0]) + self.assertEqual(ik, elem[2]) + dup.append(elem) + self.assertEqual(s, dup) + + # Check case where inner iterator is not used + keys = [k for k, g in groupby(s, lambda r:r[0])] + expectedkeys = set([r[0] for r in s]) + self.assertEqual(set(keys), expectedkeys) + self.assertEqual(len(keys), len(expectedkeys)) + + # Exercise pipes and filters style + s = 'abracadabra' + # sort s | uniq + r = [k for k, g in groupby(sorted(s))] + self.assertEqual(r, ['a', 'b', 'c', 'd', 'r']) + # sort s | uniq -d + r = [k for k, g in groupby(sorted(s)) if list(islice(g,1,2))] + self.assertEqual(r, ['a', 'b', 'r']) + # sort s | uniq -c + r = [(len(list(g)), k) for k, g in groupby(sorted(s))] + self.assertEqual(r, [(5, 'a'), (2, 'b'), (1, 'c'), (1, 'd'), (2, 'r')]) + # sort s | uniq -c | sort -rn | head -3 + r = sorted([(len(list(g)) , k) for k, g in groupby(sorted(s))], reverse=True)[:3] + self.assertEqual(r, [(5, 'a'), (2, 'r'), (2, 'b')]) + + # iter.next failure + class ExpectedError(Exception): + pass + def delayed_raise(n=0): + for i in range(n): + yield 'yo' + raise ExpectedError + def gulp(iterable, keyp=None, func=list): + return [func(g) for k, g in groupby(iterable, keyp)] + + # iter.next failure on outer object + self.assertRaises(ExpectedError, gulp, delayed_raise(0)) + # iter.next failure on inner object + self.assertRaises(ExpectedError, gulp, delayed_raise(1)) + + # __cmp__ failure + class DummyCmp: + def __cmp__(self, dst): + raise ExpectedError + s = [DummyCmp(), DummyCmp(), None] + + # __cmp__ failure on outer object + self.assertRaises(ExpectedError, gulp, s, func=id) + # __cmp__ failure on inner object + self.assertRaises(ExpectedError, gulp, s) + + # keyfunc failure + def keyfunc(obj): + if keyfunc.skip > 0: + keyfunc.skip -= 1 + return obj + else: + raise ExpectedError + + # keyfunc failure on outer object + keyfunc.skip = 0 + self.assertRaises(ExpectedError, gulp, [None], keyfunc) + keyfunc.skip = 1 + self.assertRaises(ExpectedError, gulp, [None, None], keyfunc) + + def test_ifilter(self): + self.assertEqual(list(ifilter(isEven, range(6))), [0,2,4]) + self.assertEqual(list(ifilter(None, [0,1,0,2,0])), [1,2]) + self.assertEqual(list(ifilter(bool, [0,1,0,2,0])), [1,2]) + self.assertEqual(take(4, ifilter(isEven, count())), [0,2,4,6]) + self.assertRaises(TypeError, ifilter) + self.assertRaises(TypeError, ifilter, lambda x:x) + self.assertRaises(TypeError, ifilter, lambda x:x, range(6), 7) + self.assertRaises(TypeError, ifilter, isEven, 3) + self.assertRaises(TypeError, ifilter(range(6), range(6)).next) + + def test_ifilterfalse(self): + self.assertEqual(list(ifilterfalse(isEven, range(6))), [1,3,5]) + self.assertEqual(list(ifilterfalse(None, [0,1,0,2,0])), [0,0,0]) + self.assertEqual(list(ifilterfalse(bool, [0,1,0,2,0])), [0,0,0]) + self.assertEqual(take(4, ifilterfalse(isEven, count())), [1,3,5,7]) + self.assertRaises(TypeError, ifilterfalse) + self.assertRaises(TypeError, ifilterfalse, lambda x:x) + self.assertRaises(TypeError, ifilterfalse, lambda x:x, range(6), 7) + self.assertRaises(TypeError, ifilterfalse, isEven, 3) + self.assertRaises(TypeError, ifilterfalse(range(6), range(6)).next) + + def test_izip(self): + ans = [(x,y) for x, y in izip('abc',count())] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + self.assertEqual(list(izip('abc', range(6))), zip('abc', range(6))) + self.assertEqual(list(izip('abcdef', range(3))), zip('abcdef', range(3))) + self.assertEqual(take(3,izip('abcdef', count())), zip('abcdef', range(3))) + self.assertEqual(list(izip('abcdef')), zip('abcdef')) + self.assertEqual(list(izip()), zip()) + self.assertRaises(TypeError, izip, 3) + self.assertRaises(TypeError, izip, range(3), 3) + self.assertEqual([tuple(list(pair)) for pair in izip('abc', 'def')], + zip('abc', 'def')) + self.assertEqual([pair for pair in izip('abc', 'def')], + zip('abc', 'def')) + + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_izip_tuple_resuse(self): + ids = map(id, izip('abc', 'def')) + self.assertEqual(min(ids), max(ids)) + ids = map(id, list(izip('abc', 'def'))) + self.assertEqual(len(dict.fromkeys(ids)), len(ids)) + + def test_iziplongest(self): + for args in [ + ['abc', range(6)], + [range(6), 'abc'], + [range(1000), range(2000,2100), range(3000,3050)], + [range(1000), range(0), range(3000,3050), range(1200), range(1500)], + [range(1000), range(0), range(3000,3050), range(1200), range(1500), range(0)], + ]: + # target = map(None, *args) <- this raises a py3k warning + # this is the replacement: + target = [tuple([arg[i] if i < len(arg) else None for arg in args]) + for i in range(max(map(len, args)))] + self.assertEqual(list(izip_longest(*args)), target) + self.assertEqual(list(izip_longest(*args, **{})), target) + target = [tuple((e is None and 'X' or e) for e in t) for t in target] # Replace None fills with 'X' + self.assertEqual(list(izip_longest(*args, **dict(fillvalue='X'))), target) + + self.assertEqual(take(3,izip_longest('abcdef', count())), zip('abcdef', range(3))) # take 3 from infinite input + + self.assertEqual(list(izip_longest()), zip()) + self.assertEqual(list(izip_longest([])), zip([])) + self.assertEqual(list(izip_longest('abcdef')), zip('abcdef')) + + self.assertEqual(list(izip_longest('abc', 'defg', **{})), + zip(list('abc') + [None], 'defg')) # empty keyword dict + self.assertRaises(TypeError, izip_longest, 3) + self.assertRaises(TypeError, izip_longest, range(3), 3) + + for stmt in [ + "izip_longest('abc', fv=1)", + "izip_longest('abc', fillvalue=1, bogus_keyword=None)", + ]: + try: + eval(stmt, globals(), locals()) + except TypeError: + pass + else: + self.fail('Did not raise Type in: ' + stmt) + + self.assertEqual([tuple(list(pair)) for pair in izip_longest('abc', 'def')], + zip('abc', 'def')) + self.assertEqual([pair for pair in izip_longest('abc', 'def')], + zip('abc', 'def')) + + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_izip_longest_tuple_reuse(self): + ids = map(id, izip_longest('abc', 'def')) + self.assertEqual(min(ids), max(ids)) + ids = map(id, list(izip_longest('abc', 'def'))) + self.assertEqual(len(dict.fromkeys(ids)), len(ids)) + + def test_bug_7244(self): + + class Repeater(object): + # this class is similar to itertools.repeat + def __init__(self, o, t, e): + self.o = o + self.t = int(t) + self.e = e + def __iter__(self): # its iterator is itself + return self + def next(self): + if self.t > 0: + self.t -= 1 + return self.o + else: + raise self.e + + # Formerly this code in would fail in debug mode + # with Undetected Error and Stop Iteration + r1 = Repeater(1, 3, StopIteration) + r2 = Repeater(2, 4, StopIteration) + def run(r1, r2): + result = [] + for i, j in izip_longest(r1, r2, fillvalue=0): + with test_support.captured_output('stdout'): + print (i, j) + result.append((i, j)) + return result + self.assertEqual(run(r1, r2), [(1,2), (1,2), (1,2), (0,2)]) + + # Formerly, the RuntimeError would be lost + # and StopIteration would stop as expected + r1 = Repeater(1, 3, RuntimeError) + r2 = Repeater(2, 4, StopIteration) + it = izip_longest(r1, r2, fillvalue=0) + self.assertEqual(next(it), (1, 2)) + self.assertEqual(next(it), (1, 2)) + self.assertEqual(next(it), (1, 2)) + self.assertRaises(RuntimeError, next, it) + + def test_product(self): + for args, result in [ + ([], [()]), # zero iterables + (['ab'], [('a',), ('b',)]), # one iterable + ([range(2), range(3)], [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2)]), # two iterables + ([range(0), range(2), range(3)], []), # first iterable with zero length + ([range(2), range(0), range(3)], []), # middle iterable with zero length + ([range(2), range(3), range(0)], []), # last iterable with zero length + ]: + self.assertEqual(list(product(*args)), result) + for r in range(4): + self.assertEqual(list(product(*(args*r))), + list(product(*args, **dict(repeat=r)))) + self.assertEqual(len(list(product(*[range(7)]*6))), 7**6) + self.assertRaises(TypeError, product, range(6), None) + + def product1(*args, **kwds): + pools = map(tuple, args) * kwds.get('repeat', 1) + n = len(pools) + if n == 0: + yield () + return + if any(len(pool) == 0 for pool in pools): + return + indices = [0] * n + yield tuple(pool[i] for pool, i in zip(pools, indices)) + while 1: + for i in reversed(range(n)): # right to left + if indices[i] == len(pools[i]) - 1: + continue + indices[i] += 1 + for j in range(i+1, n): + indices[j] = 0 + yield tuple(pool[i] for pool, i in zip(pools, indices)) + break + else: + return + + def product2(*args, **kwds): + 'Pure python version used in docs' + pools = map(tuple, args) * kwds.get('repeat', 1) + result = [[]] + for pool in pools: + result = [x+[y] for x in result for y in pool] + for prod in result: + yield tuple(prod) + + argtypes = ['', 'abc', '', xrange(0), xrange(4), dict(a=1, b=2, c=3), + set('abcdefg'), range(11), tuple(range(13))] + for i in range(100): + args = [random.choice(argtypes) for j in range(random.randrange(5))] + expected_len = prod(map(len, args)) + self.assertEqual(len(list(product(*args))), expected_len) + self.assertEqual(list(product(*args)), list(product1(*args))) + self.assertEqual(list(product(*args)), list(product2(*args))) + args = map(iter, args) + self.assertEqual(len(list(product(*args))), expected_len) + + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_product_tuple_reuse(self): + self.assertEqual(len(set(map(id, product('abc', 'def')))), 1) + self.assertNotEqual(len(set(map(id, list(product('abc', 'def'))))), 1) + + def test_repeat(self): + self.assertEqual(list(repeat(object='a', times=3)), ['a', 'a', 'a']) + self.assertEqual(zip(xrange(3),repeat('a')), + [(0, 'a'), (1, 'a'), (2, 'a')]) + self.assertEqual(list(repeat('a', 3)), ['a', 'a', 'a']) + self.assertEqual(take(3, repeat('a')), ['a', 'a', 'a']) + self.assertEqual(list(repeat('a', 0)), []) + self.assertEqual(list(repeat('a', -3)), []) + self.assertRaises(TypeError, repeat) + self.assertRaises(TypeError, repeat, None, 3, 4) + self.assertRaises(TypeError, repeat, None, 'a') + r = repeat(1+0j) + self.assertEqual(repr(r), 'repeat((1+0j))') + r = repeat(1+0j, 5) + self.assertEqual(repr(r), 'repeat((1+0j), 5)') + list(r) + self.assertEqual(repr(r), 'repeat((1+0j), 0)') + + def test_imap(self): + self.assertEqual(list(imap(operator.pow, range(3), range(1,7))), + [0**1, 1**2, 2**3]) + self.assertEqual(list(imap(None, 'abc', range(5))), + [('a',0),('b',1),('c',2)]) + self.assertEqual(list(imap(None, 'abc', count())), + [('a',0),('b',1),('c',2)]) + self.assertEqual(take(2,imap(None, 'abc', count())), + [('a',0),('b',1)]) + self.assertEqual(list(imap(operator.pow, [])), []) + self.assertRaises(TypeError, imap) + self.assertRaises(TypeError, imap, operator.neg) + self.assertRaises(TypeError, imap(10, range(5)).next) + self.assertRaises(ValueError, imap(errfunc, [4], [5]).next) + self.assertRaises(TypeError, imap(onearg, [4], [5]).next) + + def test_starmap(self): + self.assertEqual(list(starmap(operator.pow, zip(range(3), range(1,7)))), + [0**1, 1**2, 2**3]) + self.assertEqual(take(3, starmap(operator.pow, izip(count(), count(1)))), + [0**1, 1**2, 2**3]) + self.assertEqual(list(starmap(operator.pow, [])), []) + self.assertEqual(list(starmap(operator.pow, [iter([4,5])])), [4**5]) + self.assertRaises(TypeError, list, starmap(operator.pow, [None])) + self.assertRaises(TypeError, starmap) + self.assertRaises(TypeError, starmap, operator.pow, [(4,5)], 'extra') + self.assertRaises(TypeError, starmap(10, [(4,5)]).next) + self.assertRaises(ValueError, starmap(errfunc, [(4,5)]).next) + self.assertRaises(TypeError, starmap(onearg, [(4,5)]).next) + + def test_islice(self): + for args in [ # islice(args) should agree with range(args) + (10, 20, 3), + (10, 3, 20), + (10, 20), + (10, 3), + (20,) + ]: + self.assertEqual(list(islice(xrange(100), *args)), range(*args)) + + for args, tgtargs in [ # Stop when seqn is exhausted + ((10, 110, 3), ((10, 100, 3))), + ((10, 110), ((10, 100))), + ((110,), (100,)) + ]: + self.assertEqual(list(islice(xrange(100), *args)), range(*tgtargs)) + + # Test stop=None + self.assertEqual(list(islice(xrange(10), None)), range(10)) + self.assertEqual(list(islice(xrange(10), None, None)), range(10)) + self.assertEqual(list(islice(xrange(10), None, None, None)), range(10)) + self.assertEqual(list(islice(xrange(10), 2, None)), range(2, 10)) + self.assertEqual(list(islice(xrange(10), 1, None, 2)), range(1, 10, 2)) + + # Test number of items consumed SF #1171417 + it = iter(range(10)) + self.assertEqual(list(islice(it, 3)), range(3)) + self.assertEqual(list(it), range(3, 10)) + + # Test invalid arguments + self.assertRaises(TypeError, islice, xrange(10)) + self.assertRaises(TypeError, islice, xrange(10), 1, 2, 3, 4) + self.assertRaises(ValueError, islice, xrange(10), -5, 10, 1) + self.assertRaises(ValueError, islice, xrange(10), 1, -5, -1) + self.assertRaises(ValueError, islice, xrange(10), 1, 10, -1) + self.assertRaises(ValueError, islice, xrange(10), 1, 10, 0) + self.assertRaises(ValueError, islice, xrange(10), 'a') + self.assertRaises(ValueError, islice, xrange(10), 'a', 1) + self.assertRaises(ValueError, islice, xrange(10), 1, 'a') + self.assertRaises(ValueError, islice, xrange(10), 'a', 1, 1) + self.assertRaises(ValueError, islice, xrange(10), 1, 'a', 1) + self.assertEqual(len(list(islice(count(), 1, 10, maxsize))), 1) + + # Issue #10323: Less islice in a predictable state + c = count() + self.assertEqual(list(islice(c, 1, 3, 50)), [1]) + self.assertEqual(next(c), 3) + + def test_takewhile(self): + data = [1, 3, 5, 20, 2, 4, 6, 8] + underten = lambda x: x<10 + self.assertEqual(list(takewhile(underten, data)), [1, 3, 5]) + self.assertEqual(list(takewhile(underten, [])), []) + self.assertRaises(TypeError, takewhile) + self.assertRaises(TypeError, takewhile, operator.pow) + self.assertRaises(TypeError, takewhile, operator.pow, [(4,5)], 'extra') + self.assertRaises(TypeError, takewhile(10, [(4,5)]).next) + self.assertRaises(ValueError, takewhile(errfunc, [(4,5)]).next) + t = takewhile(bool, [1, 1, 1, 0, 0, 0]) + self.assertEqual(list(t), [1, 1, 1]) + self.assertRaises(StopIteration, t.next) + + def test_dropwhile(self): + data = [1, 3, 5, 20, 2, 4, 6, 8] + underten = lambda x: x<10 + self.assertEqual(list(dropwhile(underten, data)), [20, 2, 4, 6, 8]) + self.assertEqual(list(dropwhile(underten, [])), []) + self.assertRaises(TypeError, dropwhile) + self.assertRaises(TypeError, dropwhile, operator.pow) + self.assertRaises(TypeError, dropwhile, operator.pow, [(4,5)], 'extra') + self.assertRaises(TypeError, dropwhile(10, [(4,5)]).next) + self.assertRaises(ValueError, dropwhile(errfunc, [(4,5)]).next) + + def test_tee(self): + n = 200 + def irange(n): + for i in xrange(n): + yield i + + a, b = tee([]) # test empty iterator + self.assertEqual(list(a), []) + self.assertEqual(list(b), []) + + a, b = tee(irange(n)) # test 100% interleaved + self.assertEqual(zip(a,b), zip(range(n),range(n))) + + a, b = tee(irange(n)) # test 0% interleaved + self.assertEqual(list(a), range(n)) + self.assertEqual(list(b), range(n)) + + a, b = tee(irange(n)) # test dealloc of leading iterator + for i in xrange(100): + self.assertEqual(a.next(), i) + del a + self.assertEqual(list(b), range(n)) + + a, b = tee(irange(n)) # test dealloc of trailing iterator + for i in xrange(100): + self.assertEqual(a.next(), i) + del b + self.assertEqual(list(a), range(100, n)) + + for j in xrange(5): # test randomly interleaved + order = [0]*n + [1]*n + random.shuffle(order) + lists = ([], []) + its = tee(irange(n)) + for i in order: + value = its[i].next() + lists[i].append(value) + self.assertEqual(lists[0], range(n)) + self.assertEqual(lists[1], range(n)) + + # test argument format checking + self.assertRaises(TypeError, tee) + self.assertRaises(TypeError, tee, 3) + self.assertRaises(TypeError, tee, [1,2], 'x') + self.assertRaises(TypeError, tee, [1,2], 3, 'x') + + # tee object should be instantiable + a, b = tee('abc') + c = type(a)('def') + self.assertEqual(list(c), list('def')) + + # test long-lagged and multi-way split + a, b, c = tee(xrange(2000), 3) + for i in xrange(100): + self.assertEqual(a.next(), i) + self.assertEqual(list(b), range(2000)) + self.assertEqual([c.next(), c.next()], range(2)) + self.assertEqual(list(a), range(100,2000)) + self.assertEqual(list(c), range(2,2000)) + + # test values of n + self.assertRaises(TypeError, tee, 'abc', 'invalid') + self.assertRaises(ValueError, tee, [], -1) + for n in xrange(5): + result = tee('abc', n) + self.assertEqual(type(result), tuple) + self.assertEqual(len(result), n) + self.assertEqual(map(list, result), [list('abc')]*n) + + # tee pass-through to copyable iterator + a, b = tee('abc') + c, d = tee(a) + self.assertTrue(a is c) + + # test tee_new + t1, t2 = tee('abc') + tnew = type(t1) + self.assertRaises(TypeError, tnew) + self.assertRaises(TypeError, tnew, 10) + t3 = tnew(t1) + self.assertTrue(list(t1) == list(t2) == list(t3) == list('abc')) + + # test that tee objects are weak referencable + a, b = tee(xrange(10)) + p = proxy(a) + self.assertEqual(getattr(p, '__class__'), type(b)) + del a + self.assertRaises(ReferenceError, getattr, p, '__class__') + + def test_StopIteration(self): + self.assertRaises(StopIteration, izip().next) + + for f in (chain, cycle, izip, groupby): + self.assertRaises(StopIteration, f([]).next) + self.assertRaises(StopIteration, f(StopNow()).next) + + self.assertRaises(StopIteration, islice([], None).next) + self.assertRaises(StopIteration, islice(StopNow(), None).next) + + p, q = tee([]) + self.assertRaises(StopIteration, p.next) + self.assertRaises(StopIteration, q.next) + p, q = tee(StopNow()) + self.assertRaises(StopIteration, p.next) + self.assertRaises(StopIteration, q.next) + + self.assertRaises(StopIteration, repeat(None, 0).next) + + for f in (ifilter, ifilterfalse, imap, takewhile, dropwhile, starmap): + self.assertRaises(StopIteration, f(lambda x:x, []).next) + self.assertRaises(StopIteration, f(lambda x:x, StopNow()).next) + +class TestExamples(unittest.TestCase): + + def test_chain(self): + self.assertEqual(''.join(chain('ABC', 'DEF')), 'ABCDEF') + + def test_chain_from_iterable(self): + self.assertEqual(''.join(chain.from_iterable(['ABC', 'DEF'])), 'ABCDEF') + + def test_combinations(self): + self.assertEqual(list(combinations('ABCD', 2)), + [('A','B'), ('A','C'), ('A','D'), ('B','C'), ('B','D'), ('C','D')]) + self.assertEqual(list(combinations(range(4), 3)), + [(0,1,2), (0,1,3), (0,2,3), (1,2,3)]) + + def test_combinations_with_replacement(self): + self.assertEqual(list(combinations_with_replacement('ABC', 2)), + [('A','A'), ('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')]) + + def test_compress(self): + self.assertEqual(list(compress('ABCDEF', [1,0,1,0,1,1])), list('ACEF')) + + def test_count(self): + self.assertEqual(list(islice(count(10), 5)), [10, 11, 12, 13, 14]) + + def test_cycle(self): + self.assertEqual(list(islice(cycle('ABCD'), 12)), list('ABCDABCDABCD')) + + def test_dropwhile(self): + self.assertEqual(list(dropwhile(lambda x: x<5, [1,4,6,4,1])), [6,4,1]) + + def test_groupby(self): + self.assertEqual([k for k, g in groupby('AAAABBBCCDAABBB')], + list('ABCDAB')) + self.assertEqual([(list(g)) for k, g in groupby('AAAABBBCCD')], + [list('AAAA'), list('BBB'), list('CC'), list('D')]) + + def test_ifilter(self): + self.assertEqual(list(ifilter(lambda x: x%2, range(10))), [1,3,5,7,9]) + + def test_ifilterfalse(self): + self.assertEqual(list(ifilterfalse(lambda x: x%2, range(10))), [0,2,4,6,8]) + + def test_imap(self): + self.assertEqual(list(imap(pow, (2,3,10), (5,2,3))), [32, 9, 1000]) + + def test_islice(self): + self.assertEqual(list(islice('ABCDEFG', 2)), list('AB')) + self.assertEqual(list(islice('ABCDEFG', 2, 4)), list('CD')) + self.assertEqual(list(islice('ABCDEFG', 2, None)), list('CDEFG')) + self.assertEqual(list(islice('ABCDEFG', 0, None, 2)), list('ACEG')) + + def test_izip(self): + self.assertEqual(list(izip('ABCD', 'xy')), [('A', 'x'), ('B', 'y')]) + + def test_izip_longest(self): + self.assertEqual(list(izip_longest('ABCD', 'xy', fillvalue='-')), + [('A', 'x'), ('B', 'y'), ('C', '-'), ('D', '-')]) + + def test_permutations(self): + self.assertEqual(list(permutations('ABCD', 2)), + map(tuple, 'AB AC AD BA BC BD CA CB CD DA DB DC'.split())) + self.assertEqual(list(permutations(range(3))), + [(0,1,2), (0,2,1), (1,0,2), (1,2,0), (2,0,1), (2,1,0)]) + + def test_product(self): + self.assertEqual(list(product('ABCD', 'xy')), + map(tuple, 'Ax Ay Bx By Cx Cy Dx Dy'.split())) + self.assertEqual(list(product(range(2), repeat=3)), + [(0,0,0), (0,0,1), (0,1,0), (0,1,1), + (1,0,0), (1,0,1), (1,1,0), (1,1,1)]) + + def test_repeat(self): + self.assertEqual(list(repeat(10, 3)), [10, 10, 10]) + + def test_stapmap(self): + self.assertEqual(list(starmap(pow, [(2,5), (3,2), (10,3)])), + [32, 9, 1000]) + + def test_takewhile(self): + self.assertEqual(list(takewhile(lambda x: x<5, [1,4,6,4,1])), [1,4]) + + +class TestGC(unittest.TestCase): + + def makecycle(self, iterator, container): + container.append(iterator) + iterator.next() + del container, iterator + + def test_chain(self): + a = [] + self.makecycle(chain(a), a) + + def test_chain_from_iterable(self): + a = [] + self.makecycle(chain.from_iterable([a]), a) + + def test_combinations(self): + a = [] + self.makecycle(combinations([1,2,a,3], 3), a) + + def test_combinations_with_replacement(self): + a = [] + self.makecycle(combinations_with_replacement([1,2,a,3], 3), a) + + def test_compress(self): + a = [] + self.makecycle(compress('ABCDEF', [1,0,1,0,1,0]), a) + + def test_count(self): + a = [] + Int = type('Int', (int,), dict(x=a)) + self.makecycle(count(Int(0), Int(1)), a) + + def test_cycle(self): + a = [] + self.makecycle(cycle([a]*2), a) + + def test_dropwhile(self): + a = [] + self.makecycle(dropwhile(bool, [0, a, a]), a) + + def test_groupby(self): + a = [] + self.makecycle(groupby([a]*2, lambda x:x), a) + + def test_issue2246(self): + # Issue 2246 -- the _grouper iterator was not included in GC + n = 10 + keyfunc = lambda x: x + for i, j in groupby(xrange(n), key=keyfunc): + keyfunc.__dict__.setdefault('x',[]).append(j) + + def test_ifilter(self): + a = [] + self.makecycle(ifilter(lambda x:True, [a]*2), a) + + def test_ifilterfalse(self): + a = [] + self.makecycle(ifilterfalse(lambda x:False, a), a) + + def test_izip(self): + a = [] + self.makecycle(izip([a]*2, [a]*3), a) + + def test_izip_longest(self): + a = [] + self.makecycle(izip_longest([a]*2, [a]*3), a) + b = [a, None] + self.makecycle(izip_longest([a]*2, [a]*3, fillvalue=b), a) + + def test_imap(self): + a = [] + self.makecycle(imap(lambda x:x, [a]*2), a) + + def test_islice(self): + a = [] + self.makecycle(islice([a]*2, None), a) + + def test_permutations(self): + a = [] + self.makecycle(permutations([1,2,a,3], 3), a) + + def test_product(self): + a = [] + self.makecycle(product([1,2,a,3], repeat=3), a) + + def test_repeat(self): + a = [] + self.makecycle(repeat(a), a) + + def test_starmap(self): + a = [] + self.makecycle(starmap(lambda *t: t, [(a,a)]*2), a) + + def test_takewhile(self): + a = [] + self.makecycle(takewhile(bool, [1, 0, a, a]), a) + +def R(seqn): + 'Regular generator' + for i in seqn: + yield i + +class G: + 'Sequence using __getitem__' + def __init__(self, seqn): + self.seqn = seqn + def __getitem__(self, i): + return self.seqn[i] + +class I: + 'Sequence using iterator protocol' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class Ig: + 'Sequence using iterator protocol defined with a generator' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + for val in self.seqn: + yield val + +class X: + 'Missing __getitem__ and __iter__' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class N: + 'Iterator missing next()' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + +class E: + 'Test propagation of exceptions' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + 3 // 0 + +class S: + 'Test immediate stop' + def __init__(self, seqn): + pass + def __iter__(self): + return self + def next(self): + raise StopIteration + +def L(seqn): + 'Test multiple tiers of iterators' + return chain(imap(lambda x:x, R(Ig(G(seqn))))) + + +class TestVariousIteratorArgs(unittest.TestCase): + + def test_chain(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + self.assertEqual(list(chain(g(s))), list(g(s))) + self.assertEqual(list(chain(g(s), g(s))), list(g(s))+list(g(s))) + self.assertRaises(TypeError, list, chain(X(s))) + self.assertRaises(TypeError, list, chain(N(s))) + self.assertRaises(ZeroDivisionError, list, chain(E(s))) + + def test_compress(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + n = len(s) + for g in (G, I, Ig, S, L, R): + self.assertEqual(list(compress(g(s), repeat(1))), list(g(s))) + self.assertRaises(TypeError, compress, X(s), repeat(1)) + self.assertRaises(TypeError, list, compress(N(s), repeat(1))) + self.assertRaises(ZeroDivisionError, list, compress(E(s), repeat(1))) + + def test_product(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + self.assertRaises(TypeError, product, X(s)) + self.assertRaises(TypeError, product, N(s)) + self.assertRaises(ZeroDivisionError, product, E(s)) + + def test_cycle(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + tgtlen = len(s) * 3 + expected = list(g(s))*3 + actual = list(islice(cycle(g(s)), tgtlen)) + self.assertEqual(actual, expected) + self.assertRaises(TypeError, cycle, X(s)) + self.assertRaises(TypeError, list, cycle(N(s))) + self.assertRaises(ZeroDivisionError, list, cycle(E(s))) + + def test_groupby(self): + for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + self.assertEqual([k for k, sb in groupby(g(s))], list(g(s))) + self.assertRaises(TypeError, groupby, X(s)) + self.assertRaises(TypeError, list, groupby(N(s))) + self.assertRaises(ZeroDivisionError, list, groupby(E(s))) + + def test_ifilter(self): + for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + self.assertEqual(list(ifilter(isEven, g(s))), filter(isEven, g(s))) + self.assertRaises(TypeError, ifilter, isEven, X(s)) + self.assertRaises(TypeError, list, ifilter(isEven, N(s))) + self.assertRaises(ZeroDivisionError, list, ifilter(isEven, E(s))) + + def test_ifilterfalse(self): + for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + self.assertEqual(list(ifilterfalse(isEven, g(s))), filter(isOdd, g(s))) + self.assertRaises(TypeError, ifilterfalse, isEven, X(s)) + self.assertRaises(TypeError, list, ifilterfalse(isEven, N(s))) + self.assertRaises(ZeroDivisionError, list, ifilterfalse(isEven, E(s))) + + def test_izip(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + self.assertEqual(list(izip(g(s))), zip(g(s))) + self.assertEqual(list(izip(g(s), g(s))), zip(g(s), g(s))) + self.assertRaises(TypeError, izip, X(s)) + self.assertRaises(TypeError, list, izip(N(s))) + self.assertRaises(ZeroDivisionError, list, izip(E(s))) + + def test_iziplongest(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + self.assertEqual(list(izip_longest(g(s))), zip(g(s))) + self.assertEqual(list(izip_longest(g(s), g(s))), zip(g(s), g(s))) + self.assertRaises(TypeError, izip_longest, X(s)) + self.assertRaises(TypeError, list, izip_longest(N(s))) + self.assertRaises(ZeroDivisionError, list, izip_longest(E(s))) + + def test_imap(self): + for s in (range(10), range(0), range(100), (7,11), xrange(20,50,5)): + for g in (G, I, Ig, S, L, R): + self.assertEqual(list(imap(onearg, g(s))), map(onearg, g(s))) + self.assertEqual(list(imap(operator.pow, g(s), g(s))), map(operator.pow, g(s), g(s))) + self.assertRaises(TypeError, imap, onearg, X(s)) + self.assertRaises(TypeError, list, imap(onearg, N(s))) + self.assertRaises(ZeroDivisionError, list, imap(onearg, E(s))) + + def test_islice(self): + for s in ("12345", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + self.assertEqual(list(islice(g(s),1,None,2)), list(g(s))[1::2]) + self.assertRaises(TypeError, islice, X(s), 10) + self.assertRaises(TypeError, list, islice(N(s), 10)) + self.assertRaises(ZeroDivisionError, list, islice(E(s), 10)) + + def test_starmap(self): + for s in (range(10), range(0), range(100), (7,11), xrange(20,50,5)): + for g in (G, I, Ig, S, L, R): + ss = zip(s, s) + self.assertEqual(list(starmap(operator.pow, g(ss))), map(operator.pow, g(s), g(s))) + self.assertRaises(TypeError, starmap, operator.pow, X(ss)) + self.assertRaises(TypeError, list, starmap(operator.pow, N(ss))) + self.assertRaises(ZeroDivisionError, list, starmap(operator.pow, E(ss))) + + def test_takewhile(self): + for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + tgt = [] + for elem in g(s): + if not isEven(elem): break + tgt.append(elem) + self.assertEqual(list(takewhile(isEven, g(s))), tgt) + self.assertRaises(TypeError, takewhile, isEven, X(s)) + self.assertRaises(TypeError, list, takewhile(isEven, N(s))) + self.assertRaises(ZeroDivisionError, list, takewhile(isEven, E(s))) + + def test_dropwhile(self): + for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + tgt = [] + for elem in g(s): + if not tgt and isOdd(elem): continue + tgt.append(elem) + self.assertEqual(list(dropwhile(isOdd, g(s))), tgt) + self.assertRaises(TypeError, dropwhile, isOdd, X(s)) + self.assertRaises(TypeError, list, dropwhile(isOdd, N(s))) + self.assertRaises(ZeroDivisionError, list, dropwhile(isOdd, E(s))) + + def test_tee(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, L, R): + it1, it2 = tee(g(s)) + self.assertEqual(list(it1), list(g(s))) + self.assertEqual(list(it2), list(g(s))) + self.assertRaises(TypeError, tee, X(s)) + self.assertRaises(TypeError, list, tee(N(s))[0]) + self.assertRaises(ZeroDivisionError, list, tee(E(s))[0]) + +class LengthTransparency(unittest.TestCase): + + def test_repeat(self): + from test.test_iterlen import len + self.assertEqual(len(repeat(None, 50)), 50) + self.assertRaises(TypeError, len, repeat(None)) + +class RegressionTests(unittest.TestCase): + + def test_sf_793826(self): + # Fix Armin Rigo's successful efforts to wreak havoc + + def mutatingtuple(tuple1, f, tuple2): + # this builds a tuple t which is a copy of tuple1, + # then calls f(t), then mutates t to be equal to tuple2 + # (needs len(tuple1) == len(tuple2)). + def g(value, first=[1]): + if first: + del first[:] + f(z.next()) + return value + items = list(tuple2) + items[1:1] = list(tuple1) + gen = imap(g, items) + z = izip(*[gen]*len(tuple1)) + z.next() + + def f(t): + global T + T = t + first[:] = list(T) + + first = [] + mutatingtuple((1,2,3), f, (4,5,6)) + second = list(T) + self.assertEqual(first, second) + + + def test_sf_950057(self): + # Make sure that chain() and cycle() catch exceptions immediately + # rather than when shifting between input sources + + def gen1(): + hist.append(0) + yield 1 + hist.append(1) + raise AssertionError + hist.append(2) + + def gen2(x): + hist.append(3) + yield 2 + hist.append(4) + if x: + raise StopIteration + + hist = [] + self.assertRaises(AssertionError, list, chain(gen1(), gen2(False))) + self.assertEqual(hist, [0,1]) + + hist = [] + self.assertRaises(AssertionError, list, chain(gen1(), gen2(True))) + self.assertEqual(hist, [0,1]) + + hist = [] + self.assertRaises(AssertionError, list, cycle(gen1())) + self.assertEqual(hist, [0,1]) + +class SubclassWithKwargsTest(unittest.TestCase): + def test_keywords_in_subclass(self): + # count is not subclassable... + for cls in (repeat, izip, ifilter, ifilterfalse, chain, imap, + starmap, islice, takewhile, dropwhile, cycle, compress): + class Subclass(cls): + def __init__(self, newarg=None, *args): + cls.__init__(self, *args) + try: + Subclass(newarg=1) + except TypeError, err: + # we expect type errors because of wrong argument count + self.assertNotIn("does not take keyword arguments", err.args[0]) + + +libreftest = """ Doctest for examples in the library reference: libitertools.tex + + +>>> amounts = [120.15, 764.05, 823.14] +>>> for checknum, amount in izip(count(1200), amounts): +... print 'Check %d is for $%.2f' % (checknum, amount) +... +Check 1200 is for $120.15 +Check 1201 is for $764.05 +Check 1202 is for $823.14 + +>>> import operator +>>> for cube in imap(operator.pow, xrange(1,4), repeat(3)): +... print cube +... +1 +8 +27 + +>>> reportlines = ['EuroPython', 'Roster', '', 'alex', '', 'laura', '', 'martin', '', 'walter', '', 'samuele'] +>>> for name in islice(reportlines, 3, None, 2): +... print name.title() +... +Alex +Laura +Martin +Walter +Samuele + +>>> from operator import itemgetter +>>> d = dict(a=1, b=2, c=1, d=2, e=1, f=2, g=3) +>>> di = sorted(sorted(d.iteritems()), key=itemgetter(1)) +>>> for k, g in groupby(di, itemgetter(1)): +... print k, map(itemgetter(0), g) +... +1 ['a', 'c', 'e'] +2 ['b', 'd', 'f'] +3 ['g'] + +# Find runs of consecutive numbers using groupby. The key to the solution +# is differencing with a range so that consecutive numbers all appear in +# same group. +>>> data = [ 1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28] +>>> for k, g in groupby(enumerate(data), lambda t:t[0]-t[1]): +... print map(operator.itemgetter(1), g) +... +[1] +[4, 5, 6] +[10] +[15, 16, 17, 18] +[22] +[25, 26, 27, 28] + +>>> def take(n, iterable): +... "Return first n items of the iterable as a list" +... return list(islice(iterable, n)) + +>>> def enumerate(iterable, start=0): +... return izip(count(start), iterable) + +>>> def tabulate(function, start=0): +... "Return function(0), function(1), ..." +... return imap(function, count(start)) + +>>> def nth(iterable, n, default=None): +... "Returns the nth item or a default value" +... return next(islice(iterable, n, None), default) + +>>> def quantify(iterable, pred=bool): +... "Count how many times the predicate is true" +... return sum(imap(pred, iterable)) + +>>> def padnone(iterable): +... "Returns the sequence elements and then returns None indefinitely" +... return chain(iterable, repeat(None)) + +>>> def ncycles(iterable, n): +... "Returns the sequence elements n times" +... return chain(*repeat(iterable, n)) + +>>> def dotproduct(vec1, vec2): +... return sum(imap(operator.mul, vec1, vec2)) + +>>> def flatten(listOfLists): +... return list(chain.from_iterable(listOfLists)) + +>>> def repeatfunc(func, times=None, *args): +... "Repeat calls to func with specified arguments." +... " Example: repeatfunc(random.random)" +... if times is None: +... return starmap(func, repeat(args)) +... else: +... return starmap(func, repeat(args, times)) + +>>> def pairwise(iterable): +... "s -> (s0,s1), (s1,s2), (s2, s3), ..." +... a, b = tee(iterable) +... for elem in b: +... break +... return izip(a, b) + +>>> def grouper(n, iterable, fillvalue=None): +... "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" +... args = [iter(iterable)] * n +... return izip_longest(fillvalue=fillvalue, *args) + +>>> def roundrobin(*iterables): +... "roundrobin('ABC', 'D', 'EF') --> A D E B F C" +... # Recipe credited to George Sakkis +... pending = len(iterables) +... nexts = cycle(iter(it).next for it in iterables) +... while pending: +... try: +... for next in nexts: +... yield next() +... except StopIteration: +... pending -= 1 +... nexts = cycle(islice(nexts, pending)) + +>>> def powerset(iterable): +... "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" +... s = list(iterable) +... return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) + +>>> def unique_everseen(iterable, key=None): +... "List unique elements, preserving order. Remember all elements ever seen." +... # unique_everseen('AAAABBBCCDAABBB') --> A B C D +... # unique_everseen('ABBCcAD', str.lower) --> A B C D +... seen = set() +... seen_add = seen.add +... if key is None: +... for element in iterable: +... if element not in seen: +... seen_add(element) +... yield element +... else: +... for element in iterable: +... k = key(element) +... if k not in seen: +... seen_add(k) +... yield element + +>>> def unique_justseen(iterable, key=None): +... "List unique elements, preserving order. Remember only the element just seen." +... # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B +... # unique_justseen('ABBCcAD', str.lower) --> A B C A D +... return imap(next, imap(itemgetter(1), groupby(iterable, key))) + +This is not part of the examples but it tests to make sure the definitions +perform as purported. + +>>> take(10, count()) +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +>>> list(enumerate('abc')) +[(0, 'a'), (1, 'b'), (2, 'c')] + +>>> list(islice(tabulate(lambda x: 2*x), 4)) +[0, 2, 4, 6] + +>>> nth('abcde', 3) +'d' + +>>> nth('abcde', 9) is None +True + +>>> quantify(xrange(99), lambda x: x%2==0) +50 + +>>> a = [[1, 2, 3], [4, 5, 6]] +>>> flatten(a) +[1, 2, 3, 4, 5, 6] + +>>> list(repeatfunc(pow, 5, 2, 3)) +[8, 8, 8, 8, 8] + +>>> import random +>>> take(5, imap(int, repeatfunc(random.random))) +[0, 0, 0, 0, 0] + +>>> list(pairwise('abcd')) +[('a', 'b'), ('b', 'c'), ('c', 'd')] + +>>> list(pairwise([])) +[] + +>>> list(pairwise('a')) +[] + +>>> list(islice(padnone('abc'), 0, 6)) +['a', 'b', 'c', None, None, None] + +>>> list(ncycles('abc', 3)) +['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'] + +>>> dotproduct([1,2,3], [4,5,6]) +32 + +>>> list(grouper(3, 'abcdefg', 'x')) +[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'x', 'x')] + +>>> list(roundrobin('abc', 'd', 'ef')) +['a', 'd', 'e', 'b', 'f', 'c'] + +>>> list(powerset([1,2,3])) +[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] + +>>> all(len(list(powerset(range(n)))) == 2**n for n in range(18)) +True + +>>> list(powerset('abcde')) == sorted(sorted(set(powerset('abcde'))), key=len) +True + +>>> list(unique_everseen('AAAABBBCCDAABBB')) +['A', 'B', 'C', 'D'] + +>>> list(unique_everseen('ABBCcAD', str.lower)) +['A', 'B', 'C', 'D'] + +>>> list(unique_justseen('AAAABBBCCDAABBB')) +['A', 'B', 'C', 'D', 'A', 'B'] + +>>> list(unique_justseen('ABBCcAD', str.lower)) +['A', 'B', 'C', 'A', 'D'] + +""" + +__test__ = {'libreftest' : libreftest} + +def test_main(verbose=None): + test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC, + RegressionTests, LengthTransparency, + SubclassWithKwargsTest, TestExamples) + test_support.run_unittest(*test_classes) + + # verify reference counting + if verbose and hasattr(sys, "gettotalrefcount"): + import gc + counts = [None] * 5 + for i in xrange(len(counts)): + test_support.run_unittest(*test_classes) + gc.collect() + counts[i] = sys.gettotalrefcount() + print counts + + # doctest the examples in the library reference + test_support.run_doctest(sys.modules[__name__], verbose) + +if __name__ == "__main__": + test_main(verbose=True) -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Tue Jul 3 20:21:21 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Tue, 3 Jul 2012 20:21:21 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Add_skips=2E?= Message-ID: <3WRYYs20PszMh6@mail.python.org> http://hg.python.org/jython/rev/ee80bc790d2a changeset: 6779:ee80bc790d2a user: Frank Wierzbicki date: Tue Jul 03 11:21:05 2012 -0700 summary: Add skips. files: Lib/test/test_itertools.py | 89 ++++++++++++++++--------- 1 files changed, 55 insertions(+), 34 deletions(-) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -336,8 +336,11 @@ self.assertEqual(take(2, zip('abc',count(-3))), [('a', -3), ('b', -2)]) self.assertRaises(TypeError, count, 2, 3, 4) self.assertRaises(TypeError, count, 'a') - self.assertEqual(list(islice(count(maxsize-5), 10)), range(maxsize-5, maxsize+5)) - self.assertEqual(list(islice(count(-maxsize-5), 10)), range(-maxsize-5, -maxsize+5)) + + #FIXME: not working in Jython + #self.assertEqual(list(islice(count(maxsize-5), 10)), range(maxsize-5, maxsize+5)) + #self.assertEqual(list(islice(count(-maxsize-5), 10)), range(-maxsize-5, -maxsize+5)) + c = count(3) self.assertEqual(repr(c), 'count(3)') c.next() @@ -345,20 +348,27 @@ c = count(-9) self.assertEqual(repr(c), 'count(-9)') c.next() - self.assertEqual(repr(count(10.25)), 'count(10.25)') + + #FIXME: not working in Jython + #self.assertEqual(repr(count(10.25)), 'count(10.25)') self.assertEqual(c.next(), -8) - for i in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 10, sys.maxint-5, sys.maxint+5): - # Test repr (ignoring the L in longs) - r1 = repr(count(i)).replace('L', '') - r2 = 'count(%r)'.__mod__(i).replace('L', '') - self.assertEqual(r1, r2) + #FIXME: not working in Jython + if not test_support.is_jython: + for i in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 10, sys.maxint-5, sys.maxint+5): + # Test repr (ignoring the L in longs) + r1 = repr(count(i)).replace('L', '') + r2 = 'count(%r)'.__mod__(i).replace('L', '') + self.assertEqual(r1, r2) + + #FIXME: not working in Jython # check copy, deepcopy, pickle - for value in -3, 3, sys.maxint-5, sys.maxint+5: - c = count(value) - self.assertEqual(next(copy.copy(c)), value) - self.assertEqual(next(copy.deepcopy(c)), value) - self.assertEqual(next(pickle.loads(pickle.dumps(c))), value) + if not test_support.is_jython: + for value in -3, 3, sys.maxint-5, sys.maxint+5: + c = count(value) + self.assertEqual(next(copy.copy(c)), value) + self.assertEqual(next(copy.deepcopy(c)), value) + self.assertEqual(next(pickle.loads(pickle.dumps(c))), value) def test_count_with_stride(self): self.assertEqual(zip('abc',count(2,3)), [('a', 2), ('b', 5), ('c', 8)]) @@ -368,14 +378,17 @@ [('a', 0), ('b', -1), ('c', -2)]) self.assertEqual(zip('abc',count(2,0)), [('a', 2), ('b', 2), ('c', 2)]) self.assertEqual(zip('abc',count(2,1)), [('a', 2), ('b', 3), ('c', 4)]) - self.assertEqual(take(20, count(maxsize-15, 3)), take(20, range(maxsize-15, maxsize+100, 3))) - self.assertEqual(take(20, count(-maxsize-15, 3)), take(20, range(-maxsize-15,-maxsize+100, 3))) - self.assertEqual(take(3, count(2, 3.25-4j)), [2, 5.25-4j, 8.5-8j]) - self.assertEqual(take(3, count(Decimal('1.1'), Decimal('.1'))), - [Decimal('1.1'), Decimal('1.2'), Decimal('1.3')]) - self.assertEqual(take(3, count(Fraction(2,3), Fraction(1,7))), - [Fraction(2,3), Fraction(17,21), Fraction(20,21)]) - self.assertEqual(repr(take(3, count(10, 2.5))), repr([10, 12.5, 15.0])) + + #FIXME: not working in Jython + #self.assertEqual(take(20, count(maxsize-15, 3)), take(20, range(maxsize-15, maxsize+100, 3))) + #self.assertEqual(take(20, count(-maxsize-15, 3)), take(20, range(-maxsize-15,-maxsize+100, 3))) + #self.assertEqual(take(3, count(2, 3.25-4j)), [2, 5.25-4j, 8.5-8j]) + #self.assertEqual(take(3, count(Decimal('1.1'), Decimal('.1'))), + # [Decimal('1.1'), Decimal('1.2'), Decimal('1.3')]) + #self.assertEqual(take(3, count(Fraction(2,3), Fraction(1,7))), + # [Fraction(2,3), Fraction(17,21), Fraction(20,21)]) + #self.assertEqual(repr(take(3, count(10, 2.5))), repr([10, 12.5, 15.0])) + c = count(3, 5) self.assertEqual(repr(c), 'count(3, 5)') c.next() @@ -389,18 +402,23 @@ c.next() self.assertEqual(repr(c), 'count(-12, -3)') self.assertEqual(repr(c), 'count(-12, -3)') - self.assertEqual(repr(count(10.5, 1.25)), 'count(10.5, 1.25)') - self.assertEqual(repr(count(10.5, 1)), 'count(10.5)') # suppress step=1 when it's an int - self.assertEqual(repr(count(10.5, 1.00)), 'count(10.5, 1.0)') # do show float values lilke 1.0 - for i in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 10, sys.maxint-5, sys.maxint+5): - for j in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 1, 10, sys.maxint-5, sys.maxint+5): - # Test repr (ignoring the L in longs) - r1 = repr(count(i, j)).replace('L', '') - if j == 1: - r2 = ('count(%r)' % i).replace('L', '') - else: - r2 = ('count(%r, %r)' % (i, j)).replace('L', '') - self.assertEqual(r1, r2) + + #FIXME: not working in Jython + #self.assertEqual(repr(count(10.5, 1.25)), 'count(10.5, 1.25)') + #self.assertEqual(repr(count(10.5, 1)), 'count(10.5)') # suppress step=1 when it's an int + #self.assertEqual(repr(count(10.5, 1.00)), 'count(10.5, 1.0)') # do show float values lilke 1.0 + + #FIXME: not working in Jython + if not test_support.is_jython: + for i in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 10, sys.maxint-5, sys.maxint+5): + for j in (-sys.maxint-5, -sys.maxint+5 ,-10, -1, 0, 1, 10, sys.maxint-5, sys.maxint+5): + # Test repr (ignoring the L in longs) + r1 = repr(count(i, j)).replace('L', '') + if j == 1: + r2 = ('count(%r)' % i).replace('L', '') + else: + r2 = ('count(%r, %r)' % (i, j)).replace('L', '') + self.assertEqual(r1, r2) def test_cycle(self): self.assertEqual(take(10, cycle('abc')), list('abcabcabca')) @@ -904,7 +922,10 @@ p = proxy(a) self.assertEqual(getattr(p, '__class__'), type(b)) del a - self.assertRaises(ReferenceError, getattr, p, '__class__') + + #FIXME: not working in Jython + if not test_support.is_jython: + self.assertRaises(ReferenceError, getattr, p, '__class__') def test_StopIteration(self): self.assertRaises(StopIteration, izip().next) -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Thu Jul 5 18:48:11 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Thu, 5 Jul 2012 18:48:11 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?b?anl0aG9uICgyLjUpOiAjMTc1NDogRml4IG1v?= =?utf-8?q?djy_does_not_provide_appropriate_wsgi=2Einput_file-like_object?= =?utf-8?q?=2E?= Message-ID: <3WSlPR226YzN7S@mail.python.org> http://hg.python.org/jython/rev/bc783e270abc changeset: 6780:bc783e270abc branch: 2.5 parent: 6711:0ea5676c29a8 user: Frank Wierzbicki date: Thu Jul 05 09:24:49 2012 -0700 summary: #1754: Fix modjy does not provide appropriate wsgi.input file-like object. Thanks for initial patch Philip Jenvey! files: Lib/test/test_io_jy.py | 66 ++++++++++++ NEWS | 4 + src/org/python/core/io/StreamIO.java | 85 +++++++++++++++- 3 files changed, 154 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_io_jy.py b/Lib/test/test_io_jy.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_io_jy.py @@ -0,0 +1,66 @@ +"""Misc io tests. + +Made for Jython. +""" +import unittest + +from org.python.core.util import FileUtil +from org.python.core.io import StreamIO + +from java.io import InputStream +from java.nio import ByteBuffer; + +class InfiniteInputStream(InputStream): + + def read(self, *args): + if len(args) == 0: + return ord('x') + elif len(args) == 1: + return InputStream.read(self, args[0]) + else: + return self.read_buffer(*args) + + def read_buffer(self, buf, off, length): + if length > 0: + buf[off] = ord('x') + return 1 + return 0 + + +class IoTestCase(unittest.TestCase): + """ + Jython was failing to read all available content when an InputStream + returns early. Java's InputStream.read() is allowed to return less than the + requested # of bytes under non-exceptional/EOF conditions, whereas + (for example) wsgi.input requires the file.read() method to block until the + requested # of bytes are available (except for exceptional/EOF conditions). + + See http://bugs.jython.org/issue1754 for more discussion. + """ + def test_infinite_input(self): + iis = InfiniteInputStream() + f = FileUtil.wrap(iis, 'rb') + size = 10000 + self.assertEqual(len(f.read(size)), size) + self.assertEqual(len(f.read(size)), size) + self.assertEqual(len(f.read(size)), size) + + def test_buffer_no_array(self): + """ + Directly tests StreamIO with and without a backing array and an + InputStream that returns early. + """ + size = 10000 + without_array = ByteBuffer.allocateDirect(size) + self.assertFalse(without_array.hasArray()) + with_array = ByteBuffer.allocate(size) + self.assertTrue(with_array.hasArray()) + bbs = [with_array, without_array] + for bb in bbs: + iis = InfiniteInputStream() + io = StreamIO(iis, True) + self.assertEqual(io.readinto(bb), size) + + +if __name__ == '__main__': + unittest.main() diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -3,6 +3,10 @@ Jython 2.7a1 Bugs Fixed +Jython 2.5.3b3 + Bugs Fixed + - [ 1754 ] modjy does not provide appropriate wsgi.input file-like object + Jython 2.5.3b2 Bugs Fixed - [ 1908 ] Patch for 'Unmapped exception: java.net.NoRouteToHostException' diff --git a/src/org/python/core/io/StreamIO.java b/src/org/python/core/io/StreamIO.java --- a/src/org/python/core/io/StreamIO.java +++ b/src/org/python/core/io/StreamIO.java @@ -16,6 +16,8 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; +import java.nio.channels.spi.AbstractInterruptibleChannel; + import org.python.core.Py; import org.python.modules.posix.PosixModule; @@ -95,7 +97,7 @@ * close() (defaults to True) */ public StreamIO(InputStream inputStream, boolean closefd) { - this(Channels.newChannel(inputStream), closefd); + this(newChannel(inputStream), closefd); this.inputStream = inputStream; } @@ -107,6 +109,8 @@ * close() (defaults to True) */ public StreamIO(OutputStream outputStream, boolean closefd) { + //XXX: It turns out we needed to write our own channel for + // InputStreams. Do we need to do the same for OutputStreams? this(Channels.newChannel(outputStream), closefd); this.outputStream = outputStream; } @@ -270,4 +274,83 @@ public Channel getChannel() { return readable() ? readChannel : writeChannel; } + + private static ReadableByteChannel newChannel(InputStream in) { + return new InternalReadableByteChannel(in); + } + + + /* + * AbstractInterruptibleChannel is used for its end() and begin() implementations + * but this Channel is not really interruptible. + */ + private static class InternalReadableByteChannel + extends AbstractInterruptibleChannel + implements ReadableByteChannel { + + private InputStream in; + private boolean open = true; + + InternalReadableByteChannel(InputStream in) { + this.in = in; + } + + public int read(ByteBuffer dst) throws IOException { + final int CHUNK = 8192; + + int len = dst.remaining(); + int totalRead = 0; + int bytesRead = 0; + if (dst.hasArray()) { + while (totalRead < len) { + // array() can throw RuntimeExceptions but really shouldn't when + // hasArray() is true + try { + begin(); + bytesRead = in.read(dst.array(), dst.arrayOffset(), dst.remaining()); + } finally { + end(bytesRead > 0); + } + if (bytesRead < 0) { + break; + } else { + dst.position(dst.position() + bytesRead); + totalRead += bytesRead; + } + } + } else { + byte buf[] = new byte[0]; + while (totalRead < len) { + int bytesToRead = Math.min((len - totalRead), CHUNK); + if (buf.length < bytesToRead) { + buf = new byte[bytesToRead]; + } + try { + begin(); + bytesRead = in.read(buf, 0, bytesToRead); + } finally { + end(bytesRead > 0); + } + if (bytesRead < 0) { + break; + } else { + totalRead += bytesRead; + } + dst.put(buf, 0, bytesRead); + } + } + if ((bytesRead < 0) && (totalRead == 0)) { + return -1; + } + return totalRead; + } + + protected void implCloseChannel() throws IOException { + if (open) { + in.close(); + open = false; + } + } + } + } -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Thu Jul 5 18:48:12 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Thu, 5 Jul 2012 18:48:12 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?b?OiBNZXJnZSAyLjUu?= Message-ID: <3WSlPS6HKtzN7S@mail.python.org> http://hg.python.org/jython/rev/bf3a1d3eae8c changeset: 6781:bf3a1d3eae8c parent: 6779:ee80bc790d2a parent: 6780:bc783e270abc user: Frank Wierzbicki date: Thu Jul 05 09:47:59 2012 -0700 summary: Merge 2.5. files: Lib/test/test_io_jy.py | 66 +++++++ NEWS | 5 + build.xml | 17 ++ src/org/python/core/imp.java | 6 + src/org/python/core/io/StreamIO.java | 85 +++++++++- tests/java/org/python/tests/imp/ImportTests.java | 22 ++ tests/python/testpkg/__init__.py | 10 + tests/python/testpkg/submodule.py | 1 + 8 files changed, 211 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_io_jy.py b/Lib/test/test_io_jy.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_io_jy.py @@ -0,0 +1,66 @@ +"""Misc io tests. + +Made for Jython. +""" +import unittest + +from org.python.core.util import FileUtil +from org.python.core.io import StreamIO + +from java.io import InputStream +from java.nio import ByteBuffer; + +class InfiniteInputStream(InputStream): + + def read(self, *args): + if len(args) == 0: + return ord('x') + elif len(args) == 1: + return InputStream.read(self, args[0]) + else: + return self.read_buffer(*args) + + def read_buffer(self, buf, off, length): + if length > 0: + buf[off] = ord('x') + return 1 + return 0 + + +class IoTestCase(unittest.TestCase): + """ + Jython was failing to read all available content when an InputStream + returns early. Java's InputStream.read() is allowed to return less than the + requested # of bytes under non-exceptional/EOF conditions, whereas + (for example) wsgi.input requires the file.read() method to block until the + requested # of bytes are available (except for exceptional/EOF conditions). + + See http://bugs.jython.org/issue1754 for more discussion. + """ + def test_infinite_input(self): + iis = InfiniteInputStream() + f = FileUtil.wrap(iis, 'rb') + size = 10000 + self.assertEqual(len(f.read(size)), size) + self.assertEqual(len(f.read(size)), size) + self.assertEqual(len(f.read(size)), size) + + def test_buffer_no_array(self): + """ + Directly tests StreamIO with and without a backing array and an + InputStream that returns early. + """ + size = 10000 + without_array = ByteBuffer.allocateDirect(size) + self.assertFalse(without_array.hasArray()) + with_array = ByteBuffer.allocate(size) + self.assertTrue(with_array.hasArray()) + bbs = [with_array, without_array] + for bb in bbs: + iis = InfiniteInputStream() + io = StreamIO(iis, True) + self.assertEqual(io.readinto(bb), size) + + +if __name__ == '__main__': + unittest.main() diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -19,8 +19,13 @@ Bugs Fixed - [ 1880 ] Sha 224 library not present in Jython +Jython 2.5.3b3 + Bugs Fixed + - [ 1754 ] modjy does not provide appropriate wsgi.input file-like object + Jython 2.5.3b2 Bugs Fixed + - [ 1908 ] Patch for 'Unmapped exception: java.net.NoRouteToHostException' - [ 1871 ] Relative import in module gets imported to top level (regression) - [ 1854 ] set().pop() race condition - [ 1730 ] functools.partial incorrectly makes __doc__ property readonly diff --git a/build.xml b/build.xml --- a/build.xml +++ b/build.xml @@ -982,6 +982,23 @@ + + + + + + + + + + + + + + + + + diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java --- a/src/org/python/core/imp.java +++ b/src/org/python/core/imp.java @@ -1032,6 +1032,12 @@ PyObject[] submods = new PyObject[names.length]; for (int i = 0; i < names.length; i++) { PyObject submod = module.__findattr__(names[i]); + //XXX: Temporary fix for http://bugs.jython.org/issue1900 + if (submod == null) { + submod = module.impAttr(names[i]); + } + //end temporary fix. + if (submod == null) { throw Py.ImportError("cannot import name " + names[i]); } diff --git a/src/org/python/core/io/StreamIO.java b/src/org/python/core/io/StreamIO.java --- a/src/org/python/core/io/StreamIO.java +++ b/src/org/python/core/io/StreamIO.java @@ -16,6 +16,8 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; +import java.nio.channels.spi.AbstractInterruptibleChannel; + import org.python.core.Py; import org.python.modules.posix.PosixModule; @@ -95,7 +97,7 @@ * close() (defaults to True) */ public StreamIO(InputStream inputStream, boolean closefd) { - this(Channels.newChannel(inputStream), closefd); + this(newChannel(inputStream), closefd); this.inputStream = inputStream; } @@ -107,6 +109,8 @@ * close() (defaults to True) */ public StreamIO(OutputStream outputStream, boolean closefd) { + //XXX: It turns out we needed to write our own channel for + // InputStreams. Do we need to do the same for OutputStreams? this(Channels.newChannel(outputStream), closefd); this.outputStream = outputStream; } @@ -270,4 +274,83 @@ public Channel getChannel() { return readable() ? readChannel : writeChannel; } + + private static ReadableByteChannel newChannel(InputStream in) { + return new InternalReadableByteChannel(in); + } + + + /* + * AbstractInterruptibleChannel is used for its end() and begin() implementations + * but this Channel is not really interruptible. + */ + private static class InternalReadableByteChannel + extends AbstractInterruptibleChannel + implements ReadableByteChannel { + + private InputStream in; + private boolean open = true; + + InternalReadableByteChannel(InputStream in) { + this.in = in; + } + + public int read(ByteBuffer dst) throws IOException { + final int CHUNK = 8192; + + int len = dst.remaining(); + int totalRead = 0; + int bytesRead = 0; + if (dst.hasArray()) { + while (totalRead < len) { + // array() can throw RuntimeExceptions but really shouldn't when + // hasArray() is true + try { + begin(); + bytesRead = in.read(dst.array(), dst.arrayOffset(), dst.remaining()); + } finally { + end(bytesRead > 0); + } + if (bytesRead < 0) { + break; + } else { + dst.position(dst.position() + bytesRead); + totalRead += bytesRead; + } + } + } else { + byte buf[] = new byte[0]; + while (totalRead < len) { + int bytesToRead = Math.min((len - totalRead), CHUNK); + if (buf.length < bytesToRead) { + buf = new byte[bytesToRead]; + } + try { + begin(); + bytesRead = in.read(buf, 0, bytesToRead); + } finally { + end(bytesRead > 0); + } + if (bytesRead < 0) { + break; + } else { + totalRead += bytesRead; + } + dst.put(buf, 0, bytesRead); + } + } + if ((bytesRead < 0) && (totalRead == 0)) { + return -1; + } + return totalRead; + } + + protected void implCloseChannel() throws IOException { + if (open) { + in.close(); + open = false; + } + } + } + } diff --git a/tests/java/org/python/tests/imp/ImportTests.java b/tests/java/org/python/tests/imp/ImportTests.java new file mode 100644 --- /dev/null +++ b/tests/java/org/python/tests/imp/ImportTests.java @@ -0,0 +1,22 @@ +package org.python.tests.imp; + +import junit.framework.TestCase; + +import org.python.core.Py; +import org.python.core.PyObject; +import org.python.core.PyList; +import org.python.core.PyString; +import org.python.core.PySystemState; +import org.python.core.imp; + +import java.io.File; + +public class ImportTests extends TestCase { + + public void testImportFromJava() { + PySystemState.initialize(); + PyObject submodule = imp.load("testpkg.submodule"); + PyObject module = imp.load("testpkg"); + module.__getattr__("test").__call__(); + } +} diff --git a/tests/python/testpkg/__init__.py b/tests/python/testpkg/__init__.py new file mode 100644 --- /dev/null +++ b/tests/python/testpkg/__init__.py @@ -0,0 +1,10 @@ +import sys + + +def test(): + print dir(sys.modules['testpkg']) + print 'submodule in sys.modules: %s' % ('testpkg.submodule' in sys.modules) + import testpkg + print testpkg.__file__ + print dir(testpkg) + from testpkg import submodule diff --git a/tests/python/testpkg/submodule.py b/tests/python/testpkg/submodule.py new file mode 100644 --- /dev/null +++ b/tests/python/testpkg/submodule.py @@ -0,0 +1,1 @@ +# coding: utf-8 -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Thu Jul 5 19:25:51 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Thu, 5 Jul 2012 19:25:51 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?b?anl0aG9uICgyLjUpOiBBZGRlZCB0YWcgdjIu?= =?utf-8?q?5=2E3b3_for_changeset_bc783e270abc?= Message-ID: <3WSmDv5N4zzNGk@mail.python.org> http://hg.python.org/jython/rev/9d64d6b53fad changeset: 6782:9d64d6b53fad branch: 2.5 parent: 6780:bc783e270abc user: Frank Wierzbicki date: Thu Jul 05 10:24:18 2012 -0700 summary: Added tag v2.5.3b3 for changeset bc783e270abc files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -58,3 +58,4 @@ c72d5c5c968abac480c0841057797abf2d7f0018 v2.5.2 91332231a44804192e47ca25be334bab8ac8ea7c v2.5.2 c5567b7757e7ff086bdb10006ddbd513a727a803 v2.5.3b1 +bc783e270abc80c94aab8fb55aa363de0d2422bb v2.5.3b3 -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Thu Jul 5 19:25:53 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Thu, 5 Jul 2012 19:25:53 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Prepare_for_2?= =?utf-8?b?LjUuM2Iz?= Message-ID: <3WSmDx0GnVzNPD@mail.python.org> http://hg.python.org/jython/rev/b37f16c56f69 changeset: 6783:b37f16c56f69 branch: 2.5 user: Frank Wierzbicki date: Thu Jul 05 10:25:44 2012 -0700 summary: Prepare for 2.5.3b3 files: README.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.txt b/README.txt --- a/README.txt +++ b/README.txt @@ -1,7 +1,7 @@ -Welcome to Jython 2.5.3b1 +Welcome to Jython 2.5.3b3 ======================= -This is the first beta release of the 2.5.3 version of Jython +This is the third beta release of the 2.5.3 version of Jython Please see the NEWS file for detailed release notes. The release was compiled on Ubuntu with JDK 6 and requires JDK 5 to run. -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Thu Jul 5 20:40:21 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Thu, 5 Jul 2012 20:40:21 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Fix_full-build_?= =?utf-8?q?to_use_the_main_hg_repo=2E?= Message-ID: <3WSnts1CxgzNDh@mail.python.org> http://hg.python.org/jython/rev/b4a67621c2b6 changeset: 6784:b4a67621c2b6 branch: 2.5 user: Frank Wierzbicki date: Thu Jul 05 11:40:14 2012 -0700 summary: Fix full-build to use the main hg repo. files: build.xml | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/build.xml b/build.xml --- a/build.xml +++ b/build.xml @@ -385,7 +385,7 @@ - + -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Thu Jul 5 21:20:59 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Thu, 5 Jul 2012 21:20:59 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Backport_Toby_C?= =?utf-8?q?rawley=27s_maven_fixes_to_2=2E5=2E?= Message-ID: <3WSpnl3Zq9zNMx@mail.python.org> http://hg.python.org/jython/rev/3a0502b1eaa5 changeset: 6785:3a0502b1eaa5 branch: 2.5 user: Frank Wierzbicki date: Thu Jul 05 12:09:34 2012 -0700 summary: Backport Toby Crawley's maven fixes to 2.5. files: build.xml | 27 +++- maven/build.xml | 285 +++++++++++++++++++---------------- maven/pom.xml | 54 +++--- 3 files changed, 206 insertions(+), 160 deletions(-) diff --git a/build.xml b/build.xml --- a/build.xml +++ b/build.xml @@ -226,6 +226,7 @@ + @@ -673,6 +674,29 @@ + + + + + + + + + + +
+ + + + + + + +
+
+
+
+ @@ -843,7 +867,7 @@ - + compiling installer from ${install.src.dir} + diff --git a/maven/build.xml b/maven/build.xml --- a/maven/build.xml +++ b/maven/build.xml @@ -8,9 +8,9 @@ to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,141 +18,162 @@ specific language governing permissions and limitations under the License. --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/maven/pom.xml b/maven/pom.xml --- a/maven/pom.xml +++ b/maven/pom.xml @@ -1,30 +1,30 @@ - - 4.0.0 - org.python - jython - jar - Jython - @PROJECT-VERSION@ - http://www.jython.org/ - - Jython is an implementation of the high-level, dynamic, object-oriented - language Python written in 100% Pure Java, and seamlessly integrated with - the Java platform. It thus allows you to run Python on any Java platform. - - - - Jython Software License - http://www.jython.org/Project/license.html - repo - - - - scm:hg:http://hg.python.org/jython - scm:hg:ssh://hg at hg.python.org/jython - http://hg.python.org/jython - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + 4.0.0 + org.python + @ARTIFACT-ID@ + jar + Jython + @PROJECT-VERSION@ + http://www.jython.org/ + + Jython is an implementation of the high-level, dynamic, object-oriented + language Python written in 100% Pure Java, and seamlessly integrated with + the Java platform. It thus allows you to run Python on any Java platform. + + + + Jython Software License + http://www.jython.org/Project/license.html + repo + + + + scm:hg:http://hg.python.org/jython + scm:hg:ssh://hg at hg.python.org/jython + http://hg.python.org/jython + -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Thu Jul 5 21:21:00 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Thu, 5 Jul 2012 21:21:00 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Fix_up_maven_in?= =?utf-8?q?stall_options=2E?= Message-ID: <3WSpnm5jsszNQV@mail.python.org> http://hg.python.org/jython/rev/f4b6a6f04d9c changeset: 6786:f4b6a6f04d9c branch: 2.5 user: Frank Wierzbicki date: Thu Jul 05 12:20:52 2012 -0700 summary: Fix up maven install options. files: maven/build.xml | 2 +- maven/pom.xml | 0 2 files changed, 1 insertions(+), 1 deletions(-) diff --git a/maven/build.xml b/maven/build.xml --- a/maven/build.xml +++ b/maven/build.xml @@ -31,7 +31,7 @@ - + diff --git a/maven/pom.xml b/maven/pom-template.xml rename from maven/pom.xml rename to maven/pom-template.xml -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Sun Jul 8 15:22:55 2012 From: jython-checkins at python.org (jeff.allen) Date: Sun, 8 Jul 2012 15:22:55 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Fix_index_out_of_range_in_s?= =?utf-8?q?lice_deletion_from_sequences=2E?= Message-ID: <3WVVjC5yhWzNHp@mail.python.org> http://hg.python.org/jython/rev/cdf3485e1ba6 changeset: 6787:cdf3485e1ba6 parent: 6781:bf3a1d3eae8c user: Jeff Allen date: Sun Jul 08 14:00:01 2012 +0100 summary: Fix index out of range in slice deletion from sequences. The loop in SequenceIndexDelegate.delSlice generated an invalid index for size approaching MAXINT. Fixes a failure in test_bytes.py and removes a skip from list_tests.py . files: Lib/test/list_tests.py | 8 +- src/org/python/core/SequenceIndexDelegate.java | 37 +++++---- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -529,11 +529,9 @@ a[::2] = tuple(range(5)) self.assertEqual(a, self.type2test([0, 1, 1, 3, 2, 5, 3, 7, 4, 9])) - #FIXME: not working on Jython - if not test_support.is_jython: - # test issue7788 - a = self.type2test(range(10)) - del a[9::1<<333] + # test issue7788 + a = self.type2test(range(10)) + del a[9::1<<333] # XXX: CPython specific, PyList doesn't len() during init def _test_constructor_exception_handling(self): diff --git a/src/org/python/core/SequenceIndexDelegate.java b/src/org/python/core/SequenceIndexDelegate.java --- a/src/org/python/core/SequenceIndexDelegate.java +++ b/src/org/python/core/SequenceIndexDelegate.java @@ -50,8 +50,8 @@ if (idx.isIndex()) { delItem(checkIdx(idx.asIndex(Py.IndexError))); } else if (idx instanceof PySlice) { - int[] indices = ((PySlice)idx).indicesEx(len()); - delSlice(indices[0], indices[1], indices[2]); + PySlice slice = (PySlice) idx; + delSlice(slice.indicesEx(len())); } else { throw Py.TypeError(getTypeName() + " indices must be integers"); } @@ -109,21 +109,28 @@ } } - private void delSlice(int start, int stop, int step) { - if(step == 1) { - if (stop > start) { - delItems(start, stop); + private void delSlice(int[] indices) { + int p = indices[0], step = indices[2], count = indices[3]; + if (step > 1) { + /* + * Key observation: each deletion causes material to the right (not yet visited) to move + * one place left, so the deletion pointer moves by step-1 not by step as might be + * expected. + */ + step = step - 1; + for (; count > 0; --count, p += step) { + delItem(p); } - } else if(step > 1) { - for(int i = start; i < stop; i += step) { - delItem(i); - i--; - stop--; + } else if (step < 1) { + // Deletion pointer moves leftwards, and moving data is to the right + for (; count > 0; --count, p += step) { + delItem(p); } - } else if(step < 0) { - for(int i = start; i >= 0 && i > stop; i += step) { - delItem(i); + } else { // step == 1, since it is never == 0 + // Slice is contiguous: use range delete + if (count > 0) { + delItems(p, p + count); } } } -} \ No newline at end of file +} -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Mon Jul 9 17:34:11 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Mon, 9 Jul 2012 17:34:11 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?q?=3A_Merge_with_2=2E5=2E?= Message-ID: <3WW9ZC6RwTzNvB@mail.python.org> http://hg.python.org/jython/rev/8b94cb17bf20 changeset: 6788:8b94cb17bf20 parent: 6781:bf3a1d3eae8c parent: 6786:f4b6a6f04d9c user: Frank Wierzbicki date: Thu Jul 05 12:24:10 2012 -0700 summary: Merge with 2.5. files: -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Mon Jul 9 17:34:13 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Mon, 9 Jul 2012 17:34:13 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2Ugd2l0aCAyLjUu?= Message-ID: <3WW9ZF2gCYzP0q@mail.python.org> http://hg.python.org/jython/rev/8b61a77d6dd0 changeset: 6789:8b61a77d6dd0 parent: 6787:cdf3485e1ba6 parent: 6788:8b94cb17bf20 user: Frank Wierzbicki date: Mon Jul 09 08:34:02 2012 -0700 summary: Merge with 2.5. files: -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 13 20:08:41 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 13 Jul 2012 20:08:41 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Remove_StreamIO?= =?utf-8?q?_array_speedup_for_now_as_it_breaks_tomcat_and_test=5Fquopri=2E?= Message-ID: <3WYhpd5L1SzP2p@mail.python.org> http://hg.python.org/jython/rev/36e6f6a4f476 changeset: 6790:36e6f6a4f476 branch: 2.5 parent: 6786:f4b6a6f04d9c user: Frank Wierzbicki date: Fri Jul 13 09:23:54 2012 -0700 summary: Remove StreamIO array speedup for now as it breaks tomcat and test_quopri. files: src/org/python/core/io/StreamIO.java | 52 +++++---------- 1 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/org/python/core/io/StreamIO.java b/src/org/python/core/io/StreamIO.java --- a/src/org/python/core/io/StreamIO.java +++ b/src/org/python/core/io/StreamIO.java @@ -301,43 +301,25 @@ int len = dst.remaining(); int totalRead = 0; int bytesRead = 0; - if (dst.hasArray()) { - while (totalRead < len) { - // array() can throw RuntimeExceptions but really shouldn't when - // hasArray() is true - try { - begin(); - bytesRead = in.read(dst.array(), dst.arrayOffset(), dst.remaining()); - } finally { - end(bytesRead > 0); - } - if (bytesRead < 0) { - break; - } else { - dst.position(dst.position() + bytesRead); - totalRead += bytesRead; - } + + byte buf[] = new byte[0]; + while (totalRead < len) { + int bytesToRead = Math.min((len - totalRead), CHUNK); + if (buf.length < bytesToRead) { + buf = new byte[bytesToRead]; } - } else { - byte buf[] = new byte[0]; - while (totalRead < len) { - int bytesToRead = Math.min((len - totalRead), CHUNK); - if (buf.length < bytesToRead) { - buf = new byte[bytesToRead]; - } - try { - begin(); - bytesRead = in.read(buf, 0, bytesToRead); - } finally { - end(bytesRead > 0); - } - if (bytesRead < 0) { - break; - } else { - totalRead += bytesRead; - } - dst.put(buf, 0, bytesRead); + try { + begin(); + bytesRead = in.read(buf, 0, bytesToRead); + } finally { + end(bytesRead > 0); } + if (bytesRead < 0) { + break; + } else { + totalRead += bytesRead; + } + dst.put(buf, 0, bytesRead); } if ((bytesRead < 0) && (totalRead == 0)) { return -1; -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 13 20:08:43 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 13 Jul 2012 20:08:43 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?b?OiBNZXJnZSAyLjUu?= Message-ID: <3WYhpg0rTFzPB0@mail.python.org> http://hg.python.org/jython/rev/b2725f5ff56b changeset: 6791:b2725f5ff56b parent: 6789:8b61a77d6dd0 parent: 6790:36e6f6a4f476 user: Frank Wierzbicki date: Fri Jul 13 09:25:08 2012 -0700 summary: Merge 2.5. files: src/org/python/core/io/StreamIO.java | 52 +++++---------- 1 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/org/python/core/io/StreamIO.java b/src/org/python/core/io/StreamIO.java --- a/src/org/python/core/io/StreamIO.java +++ b/src/org/python/core/io/StreamIO.java @@ -301,43 +301,25 @@ int len = dst.remaining(); int totalRead = 0; int bytesRead = 0; - if (dst.hasArray()) { - while (totalRead < len) { - // array() can throw RuntimeExceptions but really shouldn't when - // hasArray() is true - try { - begin(); - bytesRead = in.read(dst.array(), dst.arrayOffset(), dst.remaining()); - } finally { - end(bytesRead > 0); - } - if (bytesRead < 0) { - break; - } else { - dst.position(dst.position() + bytesRead); - totalRead += bytesRead; - } + + byte buf[] = new byte[0]; + while (totalRead < len) { + int bytesToRead = Math.min((len - totalRead), CHUNK); + if (buf.length < bytesToRead) { + buf = new byte[bytesToRead]; } - } else { - byte buf[] = new byte[0]; - while (totalRead < len) { - int bytesToRead = Math.min((len - totalRead), CHUNK); - if (buf.length < bytesToRead) { - buf = new byte[bytesToRead]; - } - try { - begin(); - bytesRead = in.read(buf, 0, bytesToRead); - } finally { - end(bytesRead > 0); - } - if (bytesRead < 0) { - break; - } else { - totalRead += bytesRead; - } - dst.put(buf, 0, bytesRead); + try { + begin(); + bytesRead = in.read(buf, 0, bytesToRead); + } finally { + end(bytesRead > 0); } + if (bytesRead < 0) { + break; + } else { + totalRead += bytesRead; + } + dst.put(buf, 0, bytesRead); } if ((bytesRead < 0) && (totalRead == 0)) { return -1; -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 13 20:08:44 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 13 Jul 2012 20:08:44 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_=231914_Float_formatting_br?= =?utf-8?q?oken_in_many_non-English_locales_in_Jython_2=2E7?= Message-ID: <3WYhph36lZzP7m@mail.python.org> http://hg.python.org/jython/rev/32bdf218eb0f changeset: 6792:32bdf218eb0f user: Frank Wierzbicki date: Fri Jul 13 11:08:32 2012 -0700 summary: #1914 Float formatting broken in many non-English locales in Jython 2.7 files: NEWS | 1 + src/org/python/core/PyString.java | 2 +- 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ Jython 2.7a3 Bugs Fixed + - [ 1914 ] Float formatting broken in many non-English locales in Jython 2.7 - [ 1909 ] attrgetter does not parse dotted attributes - [ 1924 ] Implement operator.methodcaller - [ 1934 ] Break itertools.compress into a separate class diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java +++ b/src/org/python/core/PyString.java @@ -2954,7 +2954,7 @@ static class DecimalFormatTemplate { static DecimalFormat template; static { - template = new DecimalFormat("#,##0.#####"); + template = new DecimalFormat("#,##0.#####", new DecimalFormatSymbols(java.util.Locale.US)); DecimalFormatSymbols symbols = template.getDecimalFormatSymbols(); symbols.setNaN("nan"); symbols.setInfinity("inf"); -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 13 21:13:50 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 13 Jul 2012 21:13:50 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_=231920=2C_=231921_compiler?= =?utf-8?q?=2Epy_fixes=2E_Thanks_Arfrever!?= Message-ID: <3WYkFp5BpRzP9M@mail.python.org> http://hg.python.org/jython/rev/e0a776d3a03e changeset: 6793:e0a776d3a03e user: Frank Wierzbicki date: Fri Jul 13 11:22:51 2012 -0700 summary: #1920, #1921 compiler.py fixes. Thanks Arfrever! files: Lib/compiler/pycodegen.py | 11 ++++++++--- NEWS | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py @@ -8,10 +8,11 @@ from compiler import ast, parse, walk, syntax from compiler import misc, future, symbols -from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL +from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \ + SC_FREE, SC_CELL from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION, - CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT) + CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT, CO_FUTURE_PRINT_FUNCTION) if not is_jython: from compiler.pyassem import TupleArg else: @@ -226,6 +227,8 @@ self.graph.setFlag(CO_FUTURE_ABSIMPORT) elif feature == "with_statement": self.graph.setFlag(CO_FUTURE_WITH_STATEMENT) + elif feature == "print_function": + self.graph.setFlag(CO_FUTURE_PRINT_FUNCTION) def initClass(self): """This method is called once for each class""" @@ -288,7 +291,9 @@ self.emit(prefix + '_NAME', name) else: self.emit(prefix + '_FAST', name) - elif scope == SC_GLOBAL: + elif scope == SC_GLOBAL_EXPLICT: + self.emit(prefix + '_GLOBAL', name) + elif scope == SC_GLOBAL_IMPLICIT: if not self.optimized: self.emit(prefix + '_NAME', name) else: diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ Jython 2.7a3 Bugs Fixed + - [ 1921 ] compiler module broken in Jython 2.7 + - [ 1920 ] Backport CO_FUTURE_PRINT_FUNCTION to Lib/compiler/pycodegen.py - [ 1914 ] Float formatting broken in many non-English locales in Jython 2.7 - [ 1909 ] attrgetter does not parse dotted attributes - [ 1924 ] Implement operator.methodcaller -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 13 23:40:45 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 13 Jul 2012 23:40:45 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Fixed_more_non-english_form?= =?utf-8?q?atting_trouble_=28similar_to_=231914=29=2E?= Message-ID: <3WYnWK3JyFzPBD@mail.python.org> http://hg.python.org/jython/rev/940d38d23c83 changeset: 6794:940d38d23c83 user: Frank Wierzbicki date: Fri Jul 13 14:40:20 2012 -0700 summary: Fixed more non-english formatting trouble (similar to #1914). files: src/org/python/core/stringlib/Formatter.java | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/org/python/core/stringlib/Formatter.java b/src/org/python/core/stringlib/Formatter.java --- a/src/org/python/core/stringlib/Formatter.java +++ b/src/org/python/core/stringlib/Formatter.java @@ -66,7 +66,7 @@ static class DecimalFormatTemplate { static DecimalFormat template; static { - template = new DecimalFormat("#,##0.#####"); + template = new DecimalFormat("#,##0.#####", new DecimalFormatSymbols(java.util.Locale.US)); DecimalFormatSymbols symbols = template.getDecimalFormatSymbols(); symbols.setNaN("nan"); symbols.setInfinity("inf"); @@ -82,7 +82,7 @@ static class PercentageFormatTemplate { static DecimalFormat template; static { - template = new DecimalFormat("#,##0.#####%"); + template = new DecimalFormat("#,##0.#####%", new DecimalFormatSymbols(java.util.Locale.US)); DecimalFormatSymbols symbols = template.getDecimalFormatSymbols(); symbols.setNaN("nan"); symbols.setInfinity("inf"); -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Mon Jul 16 23:00:53 2012 From: jython-checkins at python.org (alan.kennedy) Date: Mon, 16 Jul 2012 23:00:53 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Tidying_up_the_?= =?utf-8?q?situation_with_getsockname=28=29_and_getpeername=28=29?= Message-ID: <3WbcTx3CJCzPHv@mail.python.org> http://hg.python.org/jython/rev/e40f741bd904 changeset: 6795:e40f741bd904 branch: 2.5 parent: 6790:36e6f6a4f476 user: Alan Kennedy date: Mon Jul 16 21:52:22 2012 +0100 summary: Tidying up the situation with getsockname() and getpeername() files: Lib/socket.py | 100 ++++++++++++----------- Lib/test/test_socket.py | 115 ++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 49 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -298,9 +298,6 @@ timeout = None mode = MODE_BLOCKING - def getpeername(self): - return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getPort() ) - def config(self, mode, timeout): self.mode = mode if self.mode == MODE_BLOCKING: @@ -414,6 +411,12 @@ if how in (SHUT_WR, SHUT_RDWR): self.jsocket.shutdownOutput() + def getsockname(self): + return (self.jsocket.getLocalAddress().getHostAddress(), self.jsocket.getLocalPort()) + + def getpeername(self): + return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getPort() ) + class _server_socket_impl(_nio_impl): options = { @@ -448,6 +451,13 @@ # later cause the user explicit close() call to fail pass + def getsockname(self): + return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getLocalPort()) + + def getpeername(self): + # Not a meaningful operation for server sockets. + raise error(errno.ENOTCONN, "Socket is not connected") + class _datagram_socket_impl(_nio_impl): options = { @@ -557,6 +567,15 @@ else: return self._do_receive_nio(0, num_bytes, flags) + def getsockname(self): + return (self.jsocket.getLocalAddress().getHostAddress(), self.jsocket.getLocalPort()) + + def getpeername(self): + peer_address = self.jsocket.getInetAddress() + if peer_address is None: + raise error(errno.ENOTCONN, "Socket is not connected") + return (peer_address.getHostAddress(), self.jsocket.getPort() ) + has_ipv6 = True # IPV6 FTW! # Name and address functions @@ -1039,6 +1058,27 @@ except java.lang.Exception, jlx: raise _map_exception(jlx) + def getsockname(self): + try: + if self.sock_impl is None: + # If the user has already bound an address, return that + if self.local_addr: + return self.local_addr + # The user has not bound, connected or listened + # This is what cpython raises in this scenario + raise error(errno.EINVAL, "Invalid argument") + return self.sock_impl.getsockname() + except java.lang.Exception, jlx: + raise _map_exception(jlx) + + def getpeername(self): + try: + if self.sock_impl is None: + raise error(errno.ENOTCONN, "Socket is not connected") + return self.sock_impl.getpeername() + except java.lang.Exception, jlx: + raise _map_exception(jlx) + def _config(self): assert self.mode in _permitted_modes if self.sock_impl: @@ -1175,31 +1215,6 @@ sendall = send - def getsockname(self): - try: - if not self.sock_impl: - host, port = self.local_addr or ("", 0) - host = java.net.InetAddress.getByName(host).getHostAddress() - else: - if self.server: - host = self.sock_impl.jsocket.getInetAddress().getHostAddress() - else: - host = self.sock_impl.jsocket.getLocalAddress().getHostAddress() - port = self.sock_impl.jsocket.getLocalPort() - return (host, port) - except java.lang.Exception, jlx: - raise _map_exception(jlx) - - def getpeername(self): - try: - assert self.sock_impl - assert not self.server - host = self.sock_impl.jsocket.getInetAddress().getHostAddress() - port = self.sock_impl.jsocket.getPort() - return (host, port) - except java.lang.Exception, jlx: - raise _map_exception(jlx) - def close(self): try: if self.istream: @@ -1216,14 +1231,19 @@ sock_impl = None connected = False + local_addr = None def __init__(self): _nonblocking_api_mixin.__init__(self) def bind(self, addr): - try: + try: assert not self.sock_impl - self.sock_impl = _datagram_socket_impl(_get_jsockaddr(addr, self.family, self.type, self.proto, AI_PASSIVE), + assert not self.local_addr + # Do the address format check + _get_jsockaddr(addr, self.family, self.type, self.proto, 0) + self.local_addr = addr + self.sock_impl = _datagram_socket_impl(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, AI_PASSIVE), self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ]) self._config() except java.lang.Exception, jlx: @@ -1235,7 +1255,7 @@ if not self.sock_impl: self.sock_impl = _datagram_socket_impl() self._config() - self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0)) + self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0)) self.connected = True except java.lang.Exception, jlx: raise _map_exception(jlx) @@ -1296,24 +1316,6 @@ except java.lang.Exception, jlx: raise _map_exception(jlx) - def getsockname(self): - try: - assert self.sock_impl - host = self.sock_impl.jsocket.getLocalAddress().getHostAddress() - port = self.sock_impl.jsocket.getLocalPort() - return (host, port) - except java.lang.Exception, jlx: - raise _map_exception(jlx) - - def getpeername(self): - try: - assert self.sock - host = self.sock_impl.jsocket.getInetAddress().getHostAddress() - port = self.sock_impl.jsocket.getPort() - return (host, port) - except java.lang.Exception, jlx: - raise _map_exception(jlx) - def __del__(self): self.close() diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -2201,6 +2201,118 @@ else: self.fail("Shutdown on unconnected socket should have raised socket exception") +class TestGetSockAndPeerName: + + def testGetpeernameNoImpl(self): + try: + self.s.getpeername() + except socket.error, se: + if se[0] == errno.ENOTCONN: + return + self.fail("getpeername() on unconnected socket should have raised socket.error") + + def testGetsocknameUnboundNoImpl(self): + try: + self.s.getsockname() + except socket.error, se: + if se[0] == errno.EINVAL: + return + self.fail("getsockname() on unconnected socket should have raised socket.error") + + def testGetsocknameBoundNoImpl(self): + self.s.bind( ("localhost", 0) ) + try: + self.s.getsockname() + except socket.error, se: + self.fail("getsockname() on bound socket should have not raised socket.error") + + def testGetsocknameImplCreated(self): + self._create_impl_socket() + try: + self.s.getsockname() + except socket.error, se: + self.fail("getsockname() on active socket should not have raised socket.error") + + def tearDown(self): + self.s.close() + +class TestGetSockAndPeerNameTCPClient(unittest.TestCase, TestGetSockAndPeerName): + + def setUp(self): + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # This server is not needed for all tests, but create it anyway + # It uses an ephemeral port, so there should be no port clashes or + # problems with reuse. + self.server_peer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server_peer.bind( ("localhost", 0) ) + self.server_peer.listen(5) + + def _create_impl_socket(self): + self.s.connect(self.server_peer.getsockname()) + + def testGetpeernameImplCreated(self): + self._create_impl_socket() + try: + self.s.getpeername() + except socket.error, se: + self.fail("getpeername() on active socket should not have raised socket.error") + self.failUnlessEqual(self.s.getpeername(), self.server_peer.getsockname()) + + def tearDown(self): + self.server_peer.close() + +class TestGetSockAndPeerNameTCPServer(unittest.TestCase, TestGetSockAndPeerName): + + def setUp(self): + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + def _create_impl_socket(self): + self.s.bind(("localhost", 0)) + self.s.listen(5) + + def testGetpeernameImplCreated(self): + self._create_impl_socket() + try: + self.s.getpeername() + except socket.error, se: + if se[0] == errno.ENOTCONN: + return + self.fail("getpeername() on listening socket should have raised socket.error") + +class TestGetSockAndPeerNameUDP(unittest.TestCase, TestGetSockAndPeerName): + + def setUp(self): + self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + def _create_impl_socket(self): + # Binding is enough to cause socket impl creation + self.s.bind(("localhost", 0)) + + def testGetpeernameImplCreatedNotConnected(self): + self._create_impl_socket() + try: + self.s.getpeername() + except socket.error, se: + if se[0] == errno.ENOTCONN: + return + self.fail("getpeername() on unconnected UDP socket should have raised socket.error") + + def testGetpeernameImplCreatedAndConnected(self): + # This test also tests that an UDP socket can be bound and connected at the same time + self._create_impl_socket() + # Need to connect to an UDP port + self._udp_peer = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self._udp_peer.bind( ("localhost", 0) ) + self.s.connect(self._udp_peer.getsockname()) + try: + try: + self.s.getpeername() + except socket.error, se: + self.fail("getpeername() on connected UDP socket should not have raised socket.error") + self.failUnlessEqual(self.s.getpeername(), self._udp_peer.getsockname()) + finally: + self._udp_peer.close() + def test_main(): tests = [ GeneralModuleTests, @@ -2231,6 +2343,9 @@ SmallBufferedFileObjectClassTestCase, UnicodeTest, IDNATest, + TestGetSockAndPeerNameTCPClient, + TestGetSockAndPeerNameTCPServer, + TestGetSockAndPeerNameUDP, ] if hasattr(socket, "socketpair"): tests.append(BasicSocketPairTest) -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Mon Jul 16 23:00:55 2012 From: jython-checkins at python.org (alan.kennedy) Date: Mon, 16 Jul 2012 23:00:55 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?q?=3A_merge_w/2=2E5=3A_Tidying_up_the_situation_with_getsockname?= =?utf-8?q?=28=29_and_getpeername=28=29?= Message-ID: <3WbcTz1c59zPJM@mail.python.org> http://hg.python.org/jython/rev/d3fd05f7230e changeset: 6796:d3fd05f7230e parent: 6794:940d38d23c83 parent: 6795:e40f741bd904 user: Alan Kennedy date: Mon Jul 16 21:59:47 2012 +0100 summary: merge w/2.5: Tidying up the situation with getsockname() and getpeername() files: Lib/socket.py | 100 ++++++++++++----------- Lib/test/test_socket.py | 115 ++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 49 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -303,9 +303,6 @@ timeout = None mode = MODE_BLOCKING - def getpeername(self): - return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getPort() ) - def config(self, mode, timeout): self.mode = mode if self.mode == MODE_BLOCKING: @@ -419,6 +416,12 @@ if how in (SHUT_WR, SHUT_RDWR): self.jsocket.shutdownOutput() + def getsockname(self): + return (self.jsocket.getLocalAddress().getHostAddress(), self.jsocket.getLocalPort()) + + def getpeername(self): + return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getPort() ) + class _server_socket_impl(_nio_impl): options = { @@ -453,6 +456,13 @@ # later cause the user explicit close() call to fail pass + def getsockname(self): + return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getLocalPort()) + + def getpeername(self): + # Not a meaningful operation for server sockets. + raise error(errno.ENOTCONN, "Socket is not connected") + class _datagram_socket_impl(_nio_impl): options = { @@ -562,6 +572,15 @@ else: return self._do_receive_nio(0, num_bytes, flags) + def getsockname(self): + return (self.jsocket.getLocalAddress().getHostAddress(), self.jsocket.getLocalPort()) + + def getpeername(self): + peer_address = self.jsocket.getInetAddress() + if peer_address is None: + raise error(errno.ENOTCONN, "Socket is not connected") + return (peer_address.getHostAddress(), self.jsocket.getPort() ) + has_ipv6 = True # IPV6 FTW! # Name and address functions @@ -1044,6 +1063,27 @@ except java.lang.Exception, jlx: raise _map_exception(jlx) + def getsockname(self): + try: + if self.sock_impl is None: + # If the user has already bound an address, return that + if self.local_addr: + return self.local_addr + # The user has not bound, connected or listened + # This is what cpython raises in this scenario + raise error(errno.EINVAL, "Invalid argument") + return self.sock_impl.getsockname() + except java.lang.Exception, jlx: + raise _map_exception(jlx) + + def getpeername(self): + try: + if self.sock_impl is None: + raise error(errno.ENOTCONN, "Socket is not connected") + return self.sock_impl.getpeername() + except java.lang.Exception, jlx: + raise _map_exception(jlx) + def _config(self): assert self.mode in _permitted_modes if self.sock_impl: @@ -1180,31 +1220,6 @@ sendall = send - def getsockname(self): - try: - if not self.sock_impl: - host, port = self.local_addr or ("", 0) - host = java.net.InetAddress.getByName(host).getHostAddress() - else: - if self.server: - host = self.sock_impl.jsocket.getInetAddress().getHostAddress() - else: - host = self.sock_impl.jsocket.getLocalAddress().getHostAddress() - port = self.sock_impl.jsocket.getLocalPort() - return (host, port) - except java.lang.Exception, jlx: - raise _map_exception(jlx) - - def getpeername(self): - try: - assert self.sock_impl - assert not self.server - host = self.sock_impl.jsocket.getInetAddress().getHostAddress() - port = self.sock_impl.jsocket.getPort() - return (host, port) - except java.lang.Exception, jlx: - raise _map_exception(jlx) - def close(self): try: if self.istream: @@ -1221,14 +1236,19 @@ sock_impl = None connected = False + local_addr = None def __init__(self): _nonblocking_api_mixin.__init__(self) def bind(self, addr): - try: + try: assert not self.sock_impl - self.sock_impl = _datagram_socket_impl(_get_jsockaddr(addr, self.family, self.type, self.proto, AI_PASSIVE), + assert not self.local_addr + # Do the address format check + _get_jsockaddr(addr, self.family, self.type, self.proto, 0) + self.local_addr = addr + self.sock_impl = _datagram_socket_impl(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, AI_PASSIVE), self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ]) self._config() except java.lang.Exception, jlx: @@ -1240,7 +1260,7 @@ if not self.sock_impl: self.sock_impl = _datagram_socket_impl() self._config() - self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0)) + self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0)) self.connected = True except java.lang.Exception, jlx: raise _map_exception(jlx) @@ -1301,24 +1321,6 @@ except java.lang.Exception, jlx: raise _map_exception(jlx) - def getsockname(self): - try: - assert self.sock_impl - host = self.sock_impl.jsocket.getLocalAddress().getHostAddress() - port = self.sock_impl.jsocket.getLocalPort() - return (host, port) - except java.lang.Exception, jlx: - raise _map_exception(jlx) - - def getpeername(self): - try: - assert self.sock - host = self.sock_impl.jsocket.getInetAddress().getHostAddress() - port = self.sock_impl.jsocket.getPort() - return (host, port) - except java.lang.Exception, jlx: - raise _map_exception(jlx) - def __del__(self): self.close() diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -2204,6 +2204,118 @@ else: self.fail("Shutdown on unconnected socket should have raised socket exception") +class TestGetSockAndPeerName: + + def testGetpeernameNoImpl(self): + try: + self.s.getpeername() + except socket.error, se: + if se[0] == errno.ENOTCONN: + return + self.fail("getpeername() on unconnected socket should have raised socket.error") + + def testGetsocknameUnboundNoImpl(self): + try: + self.s.getsockname() + except socket.error, se: + if se[0] == errno.EINVAL: + return + self.fail("getsockname() on unconnected socket should have raised socket.error") + + def testGetsocknameBoundNoImpl(self): + self.s.bind( ("localhost", 0) ) + try: + self.s.getsockname() + except socket.error, se: + self.fail("getsockname() on bound socket should have not raised socket.error") + + def testGetsocknameImplCreated(self): + self._create_impl_socket() + try: + self.s.getsockname() + except socket.error, se: + self.fail("getsockname() on active socket should not have raised socket.error") + + def tearDown(self): + self.s.close() + +class TestGetSockAndPeerNameTCPClient(unittest.TestCase, TestGetSockAndPeerName): + + def setUp(self): + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # This server is not needed for all tests, but create it anyway + # It uses an ephemeral port, so there should be no port clashes or + # problems with reuse. + self.server_peer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server_peer.bind( ("localhost", 0) ) + self.server_peer.listen(5) + + def _create_impl_socket(self): + self.s.connect(self.server_peer.getsockname()) + + def testGetpeernameImplCreated(self): + self._create_impl_socket() + try: + self.s.getpeername() + except socket.error, se: + self.fail("getpeername() on active socket should not have raised socket.error") + self.failUnlessEqual(self.s.getpeername(), self.server_peer.getsockname()) + + def tearDown(self): + self.server_peer.close() + +class TestGetSockAndPeerNameTCPServer(unittest.TestCase, TestGetSockAndPeerName): + + def setUp(self): + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + def _create_impl_socket(self): + self.s.bind(("localhost", 0)) + self.s.listen(5) + + def testGetpeernameImplCreated(self): + self._create_impl_socket() + try: + self.s.getpeername() + except socket.error, se: + if se[0] == errno.ENOTCONN: + return + self.fail("getpeername() on listening socket should have raised socket.error") + +class TestGetSockAndPeerNameUDP(unittest.TestCase, TestGetSockAndPeerName): + + def setUp(self): + self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + def _create_impl_socket(self): + # Binding is enough to cause socket impl creation + self.s.bind(("localhost", 0)) + + def testGetpeernameImplCreatedNotConnected(self): + self._create_impl_socket() + try: + self.s.getpeername() + except socket.error, se: + if se[0] == errno.ENOTCONN: + return + self.fail("getpeername() on unconnected UDP socket should have raised socket.error") + + def testGetpeernameImplCreatedAndConnected(self): + # This test also tests that an UDP socket can be bound and connected at the same time + self._create_impl_socket() + # Need to connect to an UDP port + self._udp_peer = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self._udp_peer.bind( ("localhost", 0) ) + self.s.connect(self._udp_peer.getsockname()) + try: + try: + self.s.getpeername() + except socket.error, se: + self.fail("getpeername() on connected UDP socket should not have raised socket.error") + self.failUnlessEqual(self.s.getpeername(), self._udp_peer.getsockname()) + finally: + self._udp_peer.close() + def test_main(): tests = [ GeneralModuleTests, @@ -2234,6 +2346,9 @@ SmallBufferedFileObjectClassTestCase, UnicodeTest, IDNATest, + TestGetSockAndPeerNameTCPClient, + TestGetSockAndPeerNameTCPServer, + TestGetSockAndPeerNameUDP, ] if hasattr(socket, "socketpair"): tests.append(BasicSocketPairTest) -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Wed Jul 18 10:44:06 2012 From: jython-checkins at python.org (jeff.allen) Date: Wed, 18 Jul 2012 10:44:06 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_PEP_3118_buffer_API_impleme?= =?utf-8?q?nted_for_Jython=2E?= Message-ID: <3WcX2t6zbwzPB3@mail.python.org> http://hg.python.org/jython/rev/e0aa95bac30e changeset: 6797:e0aa95bac30e parent: 6787:cdf3485e1ba6 user: Jeff Allen date: Wed Jul 18 09:29:38 2012 +0100 summary: PEP 3118 buffer API implemented for Jython. This provides an implementation for one-dimensional buffers sufficient for use in the core. There is a thorough JUnit test. Types bytearray and str now have the API and memoryview is improved, although still not complete. Regression test scores: test_str (no errors), test_bytes (8 errors, unchanged), test_memoryview (37 errors, down a bit). files: src/org/python/core/BaseBytes.java | 105 +- src/org/python/core/BufferPointer.java | 49 + src/org/python/core/MemoryViewProtocol.java | 15 +- src/org/python/core/Py.java | 5 + src/org/python/core/PyBUF.java | 238 ++ src/org/python/core/MemoryView.java | 252 ++- src/org/python/core/PyByteArray.java | 100 +- src/org/python/core/PyMemoryView.java | 137 +- src/org/python/core/PyString.java | 47 +- src/org/python/core/buffer/BaseBuffer.java | 367 +++ src/org/python/core/buffer/SimpleBuffer.java | 66 + src/org/python/core/buffer/SimpleReadonlyBuffer.java | 128 + src/org/python/core/buffer/SimpleStringBuffer.java | 149 + tests/java/org/python/core/BaseBytesTest.java | 70 +- tests/java/org/python/core/PyBufferTest.java | 1094 ++++++++++ 15 files changed, 2597 insertions(+), 225 deletions(-) diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -9,6 +9,8 @@ import java.util.List; import java.util.ListIterator; +import org.python.core.buffer.SimpleReadonlyBuffer; + /** * Base class for Jython bytearray (and bytes in due course) that provides most of the Java API, * including Java List behaviour. Attempts to modify the contents through this API will throw a @@ -31,7 +33,7 @@ * * since the default implementations will otherwise throw an exception. */ -public abstract class BaseBytes extends PySequence implements MemoryViewProtocol, List { +public abstract class BaseBytes extends PySequence implements List { /** * Simple constructor of empty zero-length array of defined type. @@ -141,75 +143,6 @@ /* * ============================================================================================ - * Support for memoryview - * ============================================================================================ - * - * This is present in order to facilitate development of PyMemoryView which a full - * implementation of bytearray would depend on, while at the same time a full implementation of - * memoryview depends on bytearray. - */ - /** - * Get hold of a memoryview on the current byte array. - * - * @see MemoryViewProtocol#getMemoryView() - */ - @Override - public MemoryView getMemoryView() { - if (mv == null) { - mv = new MemoryViewImpl(); - } - return mv; - } - - private MemoryView mv; - - /** - * All instances of BaseBytes have one dimension with stride one. - */ - private static final PyTuple STRIDES = new PyTuple(Py.One); - - /** - * Very simple MemoryView for one-dimensional byte array. This lacks any actual access to the - * underlying storage as the interface is not presently defined. - */ - private class MemoryViewImpl implements MemoryView { - - private final PyTuple SHAPE = new PyTuple(new PyInteger(storage.length)); - - @Override - public String get_format() { - return "B"; - } - - @Override - public int get_itemsize() { - return 1; - } - - @Override - public PyTuple get_shape() { - return SHAPE; - } - - @Override - public int get_ndim() { - return 1; - } - - @Override - public PyTuple get_strides() { - return STRIDES; - } - - @Override - public boolean get_readonly() { - return true; - } - - } - - /* - * ============================================================================================ * Support for construction and initialisation * ============================================================================================ * @@ -257,11 +190,11 @@ */ init((BaseBytes)arg); - } else if (arg instanceof MemoryViewProtocol) { + } else if (arg instanceof BufferProtocol) { /* * bytearray copy of object supporting Jython implementation of PEP 3118 */ - init(((MemoryViewProtocol)arg).getMemoryView()); + init((BufferProtocol)arg); } else { /* @@ -387,29 +320,21 @@ /** * Helper for __new__ and __init__ and the Java API constructor from - * objects supporting the Jython implementation of PEP 3118 (memoryview) in subclasses. + * objects supporting the Jython implementation of PEP 3118 (Buffer API) in subclasses. * - * @param value a memoryview object consistent with the slice assignment - * @throws PyException(NotImplementedError) until memoryview is properly supported - * @throws PyException(TypeError) if the memoryview is not byte-oriented + * @param value an object bearing the Buffer API and consistent with the slice assignment */ - protected void init(MemoryView value) throws PyException { - // XXX Support memoryview once means of access to bytes is defined - Py.NotImplementedError("memoryview not yet supported in bytearray"); - String format = value.get_format(); - boolean isBytes = format == null || "B".equals(format); - if (value.get_ndim() != 1 || !isBytes) { - Py.TypeError("memoryview value must be byte-oriented"); - } else { - // Dimensions are given as a PyTuple (although only one) - int len = value.get_shape().pyget(0).asInt(); - // XXX Access to memoryview bytes to go here - } + protected void init(BufferProtocol value) throws PyException { + // Get the buffer view + PyBuffer view = value.getBuffer(PyBUF.SIMPLE); + // Create storage for the bytes and have the view drop them in + newStorage(view.getLen()); + view.copyTo(storage, offset); } /** - * Helper for the Java API constructor from a {@link #View}. View is (perhaps) a stop-gap while - * there is no Jython implementation of PEP 3118 (memoryview). + * Helper for the Java API constructor from a {@link #View}. View is (perhaps) a stop-gap until + * the Jython implementation of PEP 3118 (buffer API) is embedded. * * @param value a byte-oriented view */ diff --git a/src/org/python/core/BufferPointer.java b/src/org/python/core/BufferPointer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/BufferPointer.java @@ -0,0 +1,49 @@ +package org.python.core; + +/** + * A class that references a contiguous slice of a byte[] array for use in the buffer + * API. This class simply bundles together a refernce to an array, a starting offset within that + * array, and specification of the number of bytes that may validly be accessed at that offset. It + * is used by the Jython buffer API roughly where the CPython buffer API uses a C (char *) pointer, + * or such a pointer and a length. + */ +public class BufferPointer { + + /** + * Reference to the array holding the bytes. Usually this is the actual storage exported by a + * Python object. In some contexts the consumer will be entitled to make changes to the contents + * of this array, and in others, not. See {@link PyBuffer#isReadonly()}. + */ + public final byte[] storage; + /** Starting position within the array for the data being pointed to. */ + public final int offset; + /** Number of bytes within the array comprising the data being pointed to. */ + public final int size; + + /** + * Refer to a contiguous slice of the given array. + * + * @param storage array at reference + * @param offset index of the first byte + * @param size number of bytes being referred to + */ + public BufferPointer(byte[] storage, int offset, int size) { + if ((offset | size | (storage.length-(offset + size))) < 0) { + throw Py.BufferError("Indexing error in buffer API"); + } + this.storage = storage; + this.offset = offset; + this.size = size; + } + + /** + * Refer to the whole of a byte array. + * + * @param storage array at reference + */ + public BufferPointer(byte[] storage) { + this.storage = storage; + this.offset = 0; + this.size = storage.length; + } +} \ No newline at end of file diff --git a/src/org/python/core/MemoryViewProtocol.java b/src/org/python/core/BufferProtocol.java rename from src/org/python/core/MemoryViewProtocol.java rename to src/org/python/core/BufferProtocol.java --- a/src/org/python/core/MemoryViewProtocol.java +++ b/src/org/python/core/BufferProtocol.java @@ -1,6 +1,17 @@ package org.python.core; -public interface MemoryViewProtocol { +/** + * Interface marking an object as capable of exposing its internal state as a {@link PyBuffer}. + */ +public interface BufferProtocol { - public MemoryView getMemoryView(); + /** + * Method by which the consumer requests the buffer from the exporter. The consumer + * provides information on its intended method of navigation and the optional + * features the buffer object must provide. + * + * @param flags specification of options and the navigational capabilities of the consumer + * @return exported buffer + */ + PyBuffer getBuffer(int flags); } diff --git a/src/org/python/core/Py.java b/src/org/python/core/Py.java --- a/src/org/python/core/Py.java +++ b/src/org/python/core/Py.java @@ -363,7 +363,12 @@ public static PyException MemoryError(String message) { return new PyException(Py.MemoryError, message); } + public static PyObject BufferError; + public static PyException BufferError(String message) { + return new PyException(Py.BufferError, message); + } + public static PyObject ArithmeticError; public static PyObject LookupError; public static PyObject StandardError; diff --git a/src/org/python/core/PyBUF.java b/src/org/python/core/PyBUF.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/PyBUF.java @@ -0,0 +1,238 @@ +package org.python.core; + +/** + * This interface provides a base for the key interface of the buffer API, {@link PyBuffer}, + * including symbolic constants used by the consumer of a PyBuffer to specify its + * requirements. The Jython buffer API emulates the CPython buffer API closely. + *
    + *
  • There are two reasons for separating parts of PyBuffer into this interface: The + * constants defined in CPython have the names PyBUF_SIMPLE, + * PyBUF_WRITABLE, etc., and the trick of defining ours here means we can write + * {@link PyBUF#SIMPLE}, {@link PyBUF#WRITABLE}, etc. so source code looks similar.
  • + *
  • It is not so easy in Java as it is in C to treat a byte array as storing + * anything other than byte, and we prepare for the possibility of buffers with a + * series of different primitive types by defining here, those methods that would be in common + * between (Byte)Buffer and an assumed future FloatBuffer or + * TypedBuffer<T>. (Compare java.nio.Buffer.)
  • + *
+ * Except for other interfaces, it is unlikely any classes would implement PyBUF + * directly. + */ +public interface PyBUF { + + /** + * Determine whether the consumer is entitled to write to the exported storage. + * + * @return true if writing is not allowed, false if it is. + */ + boolean isReadonly(); + + /** + * The number of dimensions to the buffer. This number is the length of the shape + * array. + * + * @return number of dimensions + */ + int getNdim(); + + /** + * An array reporting the size of the buffer, considered as a multidimensional array, in each + * dimension and (by its length) number of dimensions. The size is the size in "items". An item + * is the amount of buffer content addressed by one index or set of indices. In the simplest + * case an item is a single unit (byte), and there is one dimension. In complex cases, the array + * is multi-dimensional, and the item at each location is multi-unit (multi-byte). The consumer + * must not modify this array. + * + * @return the dimensions of the buffer as an array + */ + int[] getShape(); + + /** + * The number of units (bytes) stored in each indexable item. + * + * @return the number of units (bytes) comprising each item. + */ + int getItemsize(); + + /** + * The total number of units (bytes) stored, which will be the product of the elements of the + * shape, and the item size. + * + * @return the total number of units stored. + */ + int getLen(); + + /** + * A buffer is (usually) coupled to the internal state of an exporting Python object, and that + * object may have to restrict its behaviour while the buffer exists. The consumer must + * therefore say when it has finished. + */ + void release(); + + /** + * The "strides" array gives the distance in the storage array between adjacent items (in each + * dimension). If the rawest parts of the buffer API, the consumer of the buffer is able to + * navigate the exported storage. The "strides" array is part of the support for interpreting + * the buffer as an n-dimensional array of items. In the one-dimensional case, the "strides" + * array is In more dimensions, it provides the coefficients of the "addressing polynomial". + * (More on this in the CPython documentation.) The consumer must not modify this array. + * + * @return the distance in the storage array between adjacent items (in each dimension) + */ + int[] getStrides(); + + /** + * The "suboffsets" array is a further part of the support for interpreting the buffer as an + * n-dimensional array of items, where the array potentially uses indirect addressing (like a + * real Java array of arrays, in fact). This is only applicable when there are more than 1 + * dimension and works in conjunction with the strides array. (More on this in the + * CPython documentation.) When used, suboffsets[k] is an integer index, bit a byte + * offset as in CPython. The consumer must not modify this array. + * + * @return + */ + int[] getSuboffsets(); + + /** + * Enquire whether the array is represented contiguously in the backing storage, according to C + * or Fortran ordering. A one-dimensional contiguous array is both. + * + * @param order 'C', 'F' or 'A', as the storage order is C, Fortran or either. + * @return true iff the array is stored contiguously in the order specified + */ + boolean isContiguous(char order); + + /* Constants taken from CPython object.h in v3.3.0a */ + + /** + * The maximum allowed number of dimensions (NumPy restriction?). + */ + static final int MAX_NDIM = 64; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it expects to write to the buffer contents. getBuffer will raise an exception if + * the exporter's buffer cannot meet this requirement. + */ + static final int WRITABLE = 0x0001; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it assumes a simple one-dimensional organisation of the exported storage with + * item size of one. getBuffer will raise an exception if the consumer sets this flag and the + * exporter's buffer cannot be navigated that simply. + */ + static final int SIMPLE = 0; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it requires {@link PyBuffer#getFormat()} to return the type of the unit (rather + * than return null). + */ + // I don't understand why we need this, or why format MUST be null of this is not set. + static final int FORMAT = 0x0004; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it it is prepared to navigate the buffer as multi-dimensional. + * getBuffer will raise an exception if consumer does not specify the flag but the + * exporter's buffer cannot be navigated without taking into account its multiple dimensions. + */ + static final int ND = 0x0008 | SIMPLE; // Differs from CPython by or'ing in SIMPLE + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it it expects to use the "strides" array. getBuffer will raise an + * exception if consumer does not specify the flag but the exporter's buffer cannot be navigated + * without using the "strides" array. + */ + static final int STRIDES = 0x0010 | ND; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it will assume C-order organisation of the units. getBuffer will raise an + * exception if the exporter's buffer is not C-ordered. C_CONTIGUOUS implies + * STRIDES. + */ + static final int C_CONTIGUOUS = 0x0020 | STRIDES; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it will assume Fortran-order organisation of the units. getBuffer will raise an + * exception if the exporter's buffer is not Fortran-ordered. F_CONTIGUOUS implies + * STRIDES. + */ + static final int F_CONTIGUOUS = 0x0040 | STRIDES; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it + * + * getBuffer will raise an exception if the exporter's buffer is not contiguous. + * ANY_CONTIGUOUS implies STRIDES. + */ + static final int ANY_CONTIGUOUS = 0x0080 | STRIDES; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it understands the "suboffsets" array. getBuffer will raise an + * exception if consumer does not specify the flag but the exporter's buffer cannot be navigated + * without understanding the "suboffsets" array. INDIRECT implies + * STRIDES. + */ + static final int INDIRECT = 0x0100 | STRIDES; + /** + * Equivalent to (ND | WRITABLE) + */ + static final int CONTIG = ND | WRITABLE; + /** + * Equivalent to ND + */ + static final int CONTIG_RO = ND; + /** + * Equivalent to (STRIDES | WRITABLE) + */ + static final int STRIDED = STRIDES | WRITABLE; + /** + * Equivalent to STRIDES + */ + static final int STRIDED_RO = STRIDES; + /** + * Equivalent to (STRIDES | WRITABLE | FORMAT) + */ + static final int RECORDS = STRIDES | WRITABLE | FORMAT; + /** + * Equivalent to (STRIDES | FORMAT) + */ + static final int RECORDS_RO = STRIDES | FORMAT; + /** + * Equivalent to (INDIRECT | WRITABLE | FORMAT) + */ + static final int FULL = INDIRECT | WRITABLE | FORMAT; + /** + * Equivalent to (INDIRECT | FORMAT) + */ + static final int FULL_RO = INDIRECT | FORMAT; + + /* Constants for readability, not standard for CPython */ + + /** + * Field mask, use as in if ((capabilityFlags&ORGANISATION) == STRIDES) .... + */ + static final int ORGANISATION = SIMPLE | ND | STRIDES | INDIRECT; + /** + * Field mask, use as in if ((capabilityFlags&ORGANIZATION) == STRIDES) .... + * + * @see #ORGANISATION + */ + static final int ORGANIZATION = ORGANISATION; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it will assume C-order organisation of the units, irrespective of whether + * the strides array is to be provided. getBuffer will raise an + * exception if the exporter's buffer is not C-ordered. C_CONTIGUOUS = IS_C_CONTIGUOUS | STRIDES. + */ + static final int IS_C_CONTIGUOUS = C_CONTIGUOUS & ~STRIDES; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it will assume Fortran-order organisation of the units, irrespective of whether + * the strides array is to be provided. getBuffer will raise an + * exception if the exporter's buffer is not Fortran-ordered. F_CONTIGUOUS = IS_F_CONTIGUOUS | STRIDES. + */ + static final int IS_F_CONTIGUOUS = F_CONTIGUOUS & ~STRIDES; + /** + * Field mask, use as in if (capabilityFlags&CONTIGUITY== ... ) .... + */ + static final int CONTIGUITY = (C_CONTIGUOUS | F_CONTIGUOUS | ANY_CONTIGUOUS) & ~STRIDES; +} \ No newline at end of file diff --git a/src/org/python/core/MemoryView.java b/src/org/python/core/PyBuffer.java rename from src/org/python/core/MemoryView.java rename to src/org/python/core/PyBuffer.java --- a/src/org/python/core/MemoryView.java +++ b/src/org/python/core/PyBuffer.java @@ -1,12 +1,248 @@ package org.python.core; -public interface MemoryView { - // readonly attributes XXX just the boring stuff so far +/** + * The Jython buffer API for access to a byte array within an exporting object. This interface is + * the counterpart of the CPython Py_buffer struct. Several concrete types implement + * this interface in order to provide tailored support for different storage organisations. + */ +public interface PyBuffer extends PyBUF { - public String get_format(); - public int get_itemsize(); - public PyTuple get_shape(); - public int get_ndim(); - public PyTuple get_strides(); - public boolean get_readonly(); + /* + * The different behaviours required as the actual structure of the buffer changes (from one + * exporter to another, that is) should be dealt with using polymorphism. The implementation of + * those types may then calculate indices etc. without checking e.g for whether the strides + * array must be used, or the array is C or F contiguous, since they know the answer to these + * questions already, and can just get on with the request in their own way. + * + * The issue of consumer requests is different: the strides array will be present if the + * consumer asked for it, yet the methods of the buffer implementation do not have to use it + * (and won't). + */ + + // Informational methods inherited from PyBUF + // + // boolean isReadonly(); + // int getNdim(); + // int[] getShape(); + // int getLen(); + + /** + * Return the byte indexed from a one-dimensional buffer with item size one. This is part of the + * fully-encapsulated API: the exporter takes care of navigating the structure of the buffer. + * Results are undefined where the number of dimensions is not one or if + * itemsize>1. + * + * @param index to retrieve from + * @return the item at index, which is a byte + */ + byte byteAt(int index) throws IndexOutOfBoundsException; + + /** + * Return the unsigned byte value indexed from a one-dimensional buffer with item size one. This + * is part of the fully-encapsulated API: the exporter takes care of navigating the structure of + * the buffer. Results are undefined where the number of dimensions is not one or if + * itemsize>1. + * + * @param index to retrieve from + * @return the item at index, treated as an unsigned byte, =0xff & byteAt(index) + */ + int intAt(int index) throws IndexOutOfBoundsException; + + /** + * Store the given byte at the indexed location in of a one-dimensional buffer with item size + * one. This is part of the fully-encapsulated API: the exporter takes care of navigating the + * structure of the buffer. Results are undefined where the number of dimensions is not one or + * if itemsize>1. + * + * @param value to store + * @param index to location + */ + void storeAt(byte value, int index) throws IndexOutOfBoundsException; + + // Access to n-dimensional array + // + /** + * Return the byte indexed from an N-dimensional buffer with item size one. This is part of the + * fully-encapsulated API: the exporter takes care of navigating the structure of the buffer. + * The indices must be correct in length and value for the array shape. Results are undefined + * where itemsize>1. + * + * @param indices specifying location to retrieve from + * @return the item at location, which is a byte + */ + byte byteAt(int... indices) throws IndexOutOfBoundsException; + + /** + * Return the unsigned byte value indexed from an N-dimensional buffer with item size one. This + * is part of the fully-encapsulated API: the exporter takes care of navigating the structure of + * the buffer. The indices must be correct in length and value for the array shape. Results are + * undefined where itemsize>1. + * + * @param index to retrieve from + * @return the item at location, treated as an unsigned byte, =0xff & byteAt(index) + */ + int intAt(int... indices) throws IndexOutOfBoundsException; + + /** + * Store the given byte at the indexed location in of an N-dimensional buffer with item size + * one. This is part of the fully-encapsulated API: the exporter takes care of navigating the + * structure of the buffer. The indices must be correct in length and value for the array shape. + * Results are undefined where itemsize>1. + * + * @param value to store + * @param indices specifying location to store at + */ + void storeAt(byte value, int... indices) throws IndexOutOfBoundsException; + + // Bulk access in one dimension + // + /** + * Copy the contents of the buffer to the destination byte array. The number of bytes will be + * that returned by {@link #getLen()}, and the order is the natural ordering according to the + * contiguity type. + * + * @param dest destination byte array + * @param destPos index in the destination array of the byte [0] + * @throws IndexOutOfBoundsException if the destination cannot hold it + */ + void copyTo(byte[] dest, int destPos) throws IndexOutOfBoundsException; + + /** + * Copy a simple slice of the buffer to the destination byte array, defined by a starting index + * and length in the source buffer. This may validly be done only for a one-dimensional buffer, + * as the meaning of the starting index is otherwise not defined. + * + * @param srcIndex starting index in the source buffer + * @param dest destination byte array + * @param destPos index in the destination array of the byte [0,...] + * @param length number of bytes to copy + * @throws IndexOutOfBoundsException if access out of bounds in source or destination + */ + void copyTo(int srcIndex, byte[] dest, int destPos, int length) // mimic arraycopy args + throws IndexOutOfBoundsException; + + /** + * Copy bytes from a slice of a (Java) byte array into the buffer. This may validly be done only + * for a one-dimensional buffer, as the meaning of the starting index is otherwise not defined. + * + * @param src source byte array + * @param srcPos location in source of first byte to copy + * @param destIndex starting index in the destination (i.e. this) + * @param length number of bytes to copy in + * @throws IndexOutOfBoundsException if access out of bounds in source or destination + * @throws PyException (BufferError) if read-only buffer + */ + void copyFrom(byte[] src, int srcPos, int destIndex, int length) // mimic arraycopy args + throws IndexOutOfBoundsException, PyException; + + // Bulk access in n-dimensions may be added here if desired semantics can be settled + // + + // Buffer management inherited from PyBUF + // + // void release(); + + // Direct access to actual storage + // + /** + * Return a structure describing the slice of a byte array that holds the data being exported to + * the consumer. For a one-dimensional contiguous buffer, assuming the following client code + * where obj has type BufferProtocol: + * + *
+     *
+     * PyBuffer a = obj.getBuffer();
+     * int itemsize = a.getItemsize();
+     * BufferPointer b = a.getBuf();
+     * 
+ * + * the item with index k is in the array b.storage at index + * [b.offset + k*itemsize] to [b.offset + (k+1)*itemsize - 1] + * inclusive. And if itemsize==1, the item is simply the byte + * b.storage[b.offset + k] + *

+ * If the buffer is multidimensional or non-contiguous, b.storage[b.offset] is + * still the (first byte of) the item at index [0] or [0,...,0]. However, it is necessary to + * navigate b using the shape, strides and sub-offsets provided by the API. + * + * @return structure defining the byte[] slice that is the shared data + */ + BufferPointer getBuf(); + + /** + * Return a structure describing the slice of a byte array that holds a single item from the + * data being exported to the consumer. For a one-dimensional contiguous buffer, assuming the + * following client code where obj has type BufferProtocol: + * + *

+     * int k = ... ;
+     * PyBuffer a = obj.getBuffer();
+     * int itemsize = a.getItemsize();
+     * BufferPointer b = a.getPointer(k);
+     * 
+ * + * the item with index k is in the array b.storage at index + * [b.offset] to [b.offset + itemsize - 1] inclusive. And if + * itemsize==1, the item is simply the byte b.storage[b.offset] + *

+ * Essentially this is a method for computing the offset of a particular index. Although + * b.size==itemsize, the client is free to navigate the underlying buffer + * b.storage without respecting these boundaries. + * + * @param index in the buffer to position the pointer + * @return structure defining the byte[] slice that is the shared data + */ + BufferPointer getPointer(int index); + + /** + * Return a structure describing the slice of a byte array that holds a single item from the + * data being exported to the consumer, in the case that array may be multi-dimensional. For an + * 3-dimensional contiguous buffer, assuming the following client code where obj + * has type BufferProtocol: + * + *

+     * int i, j, k = ... ;
+     * PyBuffer a = obj.getBuffer();
+     * int itemsize = a.getItemsize();
+     * BufferPointer b = a.getPointer(i,j,k);
+     * 
+ * + * the item with index [i,j,k] is in the array b.storage at index + * [b.offset] to [b.offset + itemsize - 1] inclusive. And if + * itemsize==1, the item is simply the byte b.storage[b.offset] + *

+ * Essentially this is a method for computing the offset of a particular index. Although + * b.size==itemsize, the client is free to navigate the underlying buffer + * b.storage without respecting these boundaries. + *

+ * If the buffer is also non-contiguous, b.storage[b.offset] is still the (first + * byte of) the item at index [0,...,0]. However, it is necessary to navigate b + * using the shape, strides and sub-offsets provided by the API. + * + * @param indices multidimensional index at which to position the pointer + * @return structure defining the byte[] slice that is the shared data + */ + BufferPointer getPointer(int... indices); + + // Inherited from PyBUF and belonging here + // + // int[] getStrides(); + // int[] getSuboffsets(); + // boolean isContiguous(char order); + + // Interpretation of bytes as items + /** + * A format string in the language of Python structs describing how the bytes of each item + * should be interpreted (or null if {@link PyBUF#FORMAT} was not part of the consumer's flags). + *

+ * This is provided for compatibility with CPython. Jython only implements "B" so far, and it is + * debatable whether anything fancier than "<n>B" can be supported in Java. + * + * @return the format string + */ + String getFormat(); + + // Inherited from PyBUF and belonging here + // + // int getItemsize(); } diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java --- a/src/org/python/core/PyByteArray.java +++ b/src/org/python/core/PyByteArray.java @@ -2,6 +2,7 @@ import java.util.Arrays; +import org.python.core.buffer.SimpleBuffer; import org.python.expose.ExposedClassMethod; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; @@ -23,7 +24,7 @@ * */ @ExposedType(name = "bytearray", base = PyObject.class, doc = BuiltinDocs.bytearray_doc) -public class PyByteArray extends BaseBytes { +public class PyByteArray extends BaseBytes implements BufferProtocol { public static final PyType TYPE = PyType.fromClass(PyByteArray.class); @@ -85,14 +86,14 @@ } /** - * Create a new array filled exactly by a copy of the contents of the source, which is a - * memoryview. + * Create a new array filled exactly by a copy of the contents of the source, which is an + * object supporting the Jython version of the PEP 3118 buffer API. * * @param value source of the bytes (and size) */ - public PyByteArray(MemoryViewProtocol value) { + public PyByteArray(BufferProtocol value) { super(TYPE); - init(value.getMemoryView()); + init(value); } /** @@ -196,6 +197,55 @@ init(arg); } + /* + * ============================================================================================ + * Support for the Buffer API + * ============================================================================================ + * + * The buffer API allows other classes to access the storage directly. + */ + + /** + * {@inheritDoc} + *

+ * The {@link PyBuffer} returned from this method is a one-dimensional array of single byte + * items, that allows modification of the object state but prohibits resizing the byte array. + * This prohibition is not only on the consumer of the view but extends to any other operations, + * such as any kind or insertion or deletion. + */ + @Override + public synchronized PyBuffer getBuffer(int flags) { + exportCount++; + return new SimpleBuffer(this, new BufferPointer(storage, offset, size), flags) { + + @Override + public void releaseAction() { + // synchronise on the same object as getBuffer() + synchronized (obj) { + exportCount--; + } + } + }; + } + + /** + * Test to see if the byte array may be resized and raise a BufferError if not. + * + * @throws PyException (BufferError) if there are buffer exports preventing a resize + */ + protected void resizeCheck() throws PyException { + // XXX Quite likely this is not called in all the places it should be + if (exportCount!=0) { + throw Py.BufferError("Existing exports of data: object cannot be re-sized"); + } + } + + /** + * Count of PyBuffer exports not yet released, used to prevent untimely resizing. + */ + private int exportCount; + + /* ============================================================================================ * API for org.python.core.PySequence * ============================================================================================ @@ -368,12 +418,12 @@ */ setslice(start, stop, step, (BaseBytes)value); - } else if (value instanceof MemoryViewProtocol) { + } else if (value instanceof BufferProtocol) { /* * Value supports Jython implementation of PEP 3118, and can be can be inserted without * making a copy. */ - setslice(start, stop, step, ((MemoryViewProtocol)value).getMemoryView()); + setslice(start, stop, step, (BufferProtocol)value); } else { /* @@ -449,12 +499,31 @@ * @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 value a memoryview object consistent with the slice assignment + * @param value an object supporting the buffer API consistent with the slice assignment * @throws PyException(SliceSizeError) if the value size is inconsistent with an extended slice */ - private void setslice(int start, int stop, int step, MemoryView value) throws PyException { - // XXX Support memoryview once means of access to bytes is defined - throw Py.NotImplementedError("memoryview not yet supported in bytearray"); + private void setslice(int start, int stop, int step, BufferProtocol value) throws PyException { + PyBuffer view = value.getBuffer(PyBUF.SIMPLE); + + + int len = view.getLen(); + + if (step == 1) { + // Delete this[start:stop] and open a space of the right size + storageReplace(start, stop - start, len); + view.copyTo(storage, start+offset); + + } else { + // This is an extended slice which means we are replacing elements + int n = sliceLength(start, stop, step); + if (n != len) { + throw SliceSizeError("bytes", len, n); + } + + for (int io = start + offset, j = 0; j < n; io += step, j++) { + storage[io] = view.byteAt(j); // Assign this[i] = value[j] + } + } } /** @@ -2089,6 +2158,9 @@ return; } + // This will not be possible if this object has buffer exports + resizeCheck(); + // Compute some handy points of reference final int L = storage.length; final int f = offset; @@ -2351,6 +2423,9 @@ return; // Everything stays where it is. } + // This will not be possible if this object has buffer exports + resizeCheck(); + // Compute some handy points of reference final int L = storage.length; final int f = offset; @@ -2430,6 +2505,9 @@ return; // Everything stays where it is. } + // This will not be possible if this object has buffer exports + resizeCheck(); + // Compute some handy points of reference final int L = storage.length; final int f = offset; diff --git a/src/org/python/core/PyMemoryView.java b/src/org/python/core/PyMemoryView.java --- a/src/org/python/core/PyMemoryView.java +++ b/src/org/python/core/PyMemoryView.java @@ -1,61 +1,140 @@ package org.python.core; import org.python.expose.ExposedGet; -import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; +/** + * Class implementing the Python memoryview type, at present highly incomplete. It + * provides a wrapper around the Jython buffer API, but slice operations and most others are + * missing. + */ @ExposedType(name = "memoryview", base = PyObject.class, isBaseType = false) public class PyMemoryView extends PyObject { + // XXX This should probably extend PySequence to get the slice behaviour + public static final PyType TYPE = PyType.fromClass(PyMemoryView.class); - MemoryView backing; + /** + * The buffer exported by the object. We do not a present implement the buffer sharing strategy + * used by CPython memoryview. + */ + private PyBuffer backing; + /** Cache the result of getting shape here. */ + private PyTuple shape; + /** Cache the result of getting strides here. */ + private PyTuple strides; - public PyMemoryView(MemoryViewProtocol obj) { - backing = obj.getMemoryView(); + /** + * Construct a PyMemoryView from an object that bears the necessary BufferProtocol interface. + * The buffer so obtained will be writable if the underlying object permits it. + * + * @param obj object that will export the buffer + */ + public PyMemoryView(BufferProtocol obj) { + /* + * Ask for the full set of facilities (strides, indirect, etc.) from the object in case they + * are necessary for navigation, but only ask for read access. If the object is writable, + * the PyBuffer will be writable. + */ + backing = obj.getBuffer(PyBUF.FULL_RO); } @ExposedNew - static PyObject memoryview_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, - String[] keywords) { + static PyObject memoryview_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { PyObject obj = args[0]; - if (obj instanceof MemoryViewProtocol) { - return new PyMemoryView((MemoryViewProtocol)obj); + if (obj instanceof BufferProtocol) { + return new PyMemoryView((BufferProtocol)obj); + } else { + throw Py.TypeError("cannot make memory view because object does not have " + + "the buffer interface"); } - else throw Py.TypeError("cannot make memory view because object does not have the buffer interface"); } - @ExposedGet(name = "format") - public String get_format() { - return backing.get_format(); + @ExposedGet(doc = format_doc) + public String format() { + return backing.getFormat(); } - @ExposedGet(name = "itemsize") - public int get_itemsize() { - return backing.get_itemsize(); + @ExposedGet(doc = itemsize_doc) + public int itemsize() { + return backing.getItemsize(); } - @ExposedGet(name = "shape") - public PyTuple get_shape() { - return backing.get_shape(); + @ExposedGet(doc = shape_doc) + public PyTuple shape() { + if (shape == null) { + shape = tupleOf(backing.getShape()); + } + return shape; } - @ExposedGet(name = "ndim") - public int get_ndim() { - return backing.get_ndim(); + @ExposedGet(doc = ndim_doc) + public int ndim() { + return backing.getShape().length; } - @ExposedGet(name = "strides") - public PyTuple get_strides() { - return backing.get_strides(); + @ExposedGet(doc = strides_doc) + public PyTuple strides() { + if (strides == null) { + strides = tupleOf(backing.getStrides()); + } + return strides; } - @ExposedGet(name = "readonly") - public boolean get_readonly() { - return backing.get_readonly(); + @ExposedGet(doc = readonly_doc) + public boolean readonly() { + return backing.isReadonly(); } + /** + * Make an integer array into a PyTuple of PyInteger values. + * + * @param x the array + * @return the PyTuple + */ + private PyTuple tupleOf(int[] x) { + PyInteger[] pyx = new PyInteger[x.length]; + for (int k = 0; k < x.length; k++) { + pyx[k] = new PyInteger(x[k]); + } + return new PyTuple(pyx, false); + } + + /* + * These strings are adapted from the on-line documentation as the attributes do not come with + * any docstrings. + */ + private final static String memoryview_tobytes_doc = "tobytes()\n\n" + + "Return the data in the buffer as a bytestring (an object of class str).\n\n" + + ">>> m = memoryview(\"abc\")\n" + ">>> m.tobytes()\n" + "'abc'"; + + private final static String memoryview_tolist_doc = "tolist()\n\n" + + "Return the data in the buffer as a list of integers.\n\n" + + ">>> memoryview(\"abc\").tolist()\n" + "[97, 98, 99]"; + + private final static String format_doc = "format\n" + + "A string containing the format (in struct module style) for each element in\n" + + "the view. This defaults to 'B', a simple bytestring.\n"; + + private final static String itemsize_doc = "itemsize\n" + + "The size in bytes of each element of the memoryview.\n"; + + private final static String shape_doc = "shape\n" + + "A tuple of integers the length of ndim giving the shape of the memory as an\n" + + "N-dimensional array.\n"; + + private final static String ndim_doc = "ndim\n" + + "An integer indicating how many dimensions of a multi-dimensional array the\n" + + "memory represents.\n"; + + private final static String strides_doc = "strides\n" + + "A tuple of integers the length of ndim giving the size in bytes to access\n" + + "each element for each dimension of the array.\n"; + + private final static String readonly_doc = "readonly\n" + + "A bool indicating whether the memory is read only.\n"; + } - - diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java +++ b/src/org/python/core/PyString.java @@ -1,6 +1,12 @@ /// Copyright (c) Corporation for National Research Initiatives package org.python.core; +import java.math.BigInteger; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; + +import org.python.core.StringFormatter.DecimalFormatTemplate; +import org.python.core.buffer.SimpleStringBuffer; import org.python.core.stringlib.FieldNameIterator; import org.python.core.stringlib.InternalFormatSpec; import org.python.core.stringlib.InternalFormatSpecParser; @@ -12,15 +18,11 @@ import org.python.expose.ExposedType; import org.python.expose.MethodType; -import java.math.BigInteger; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; - /** * A builtin python string. */ @ExposedType(name = "str", doc = BuiltinDocs.str_doc) -public class PyString extends PyBaseString implements MemoryViewProtocol +public class PyString extends PyBaseString implements BufferProtocol { public static final PyType TYPE = PyType.fromClass(PyString.class); protected String string; // cannot make final because of Python intern support @@ -93,28 +95,19 @@ return codePoints; } - public MemoryView getMemoryView() { - return new MemoryView() { - // beginning of support - public String get_format() { - return "B"; - } - public int get_itemsize() { - return 2; - } - public PyTuple get_shape() { - return new PyTuple(Py.newInteger(getString().length())); - } - public int get_ndim() { - return 1; - } - public PyTuple get_strides() { - return new PyTuple(Py.newInteger(1)); - } - public boolean get_readonly() { - return true; - } - }; + /** + * Create a read-only buffer view of the contents of the string, treating it as a sequence of + * unsigned bytes. The caller specifies its requirements and navigational capabilities in the + * flags argument (see the constants in class {@link PyBUF} for an explanation). + * + * @param flags consumer requirements + * @return the requested buffer + */ + public PyBuffer getBuffer(int flags) { + /* + * Return a buffer, but specialised to defer construction of the buf object. + */ + return new SimpleStringBuffer(this, getString(), flags); } public String substring(int start, int end) { diff --git a/src/org/python/core/buffer/BaseBuffer.java b/src/org/python/core/buffer/BaseBuffer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/buffer/BaseBuffer.java @@ -0,0 +1,367 @@ +package org.python.core.buffer; + +import org.python.core.BufferPointer; +import org.python.core.BufferProtocol; +import org.python.core.Py; +import org.python.core.PyBUF; +import org.python.core.PyBuffer; +import org.python.core.PyException; + +/** + * Base implementation of the Buffer API for implementations to extend. The default implementation + * provides some mechanisms for checking the consumer's capabilities against those stated as + * necessary by the exporter. Default implementations of methods are provided for the standard array + * organisations. The implementors of simple buffers will find it more efficient to override methods + * to which performance might be sensitive with a calculation specific to their actual type. + *

+ * The default implementation raises a read-only exception for those methods that store data in the + * buffer, and {@link #isReadonly()} returns true. Writable types must override this + * implementation. Default implementations of other methods are generally oriented towards + * contiguous N-dimensional arrays. + *

+ * At the time of writing, only the SIMPLE organisation (one-dimensional, of item size one) is used + * in the Jython core. + */ +public abstract class BaseBuffer implements PyBuffer { + + /** + * The object from which this buffer export must be released (see {@link PyBuffer#release()}). + * This is normally the original exporter of this buffer and the owner of the underlying + * storage. Exceptions to this occur when some other object is managing release (this is the + * case when a memoryview has provided the buffer), and when disposal can safely be + * left to the Java garbage collector (local temporaries and perhaps exports from immutable + * objects). + */ + protected BufferProtocol obj; + /** + * The dimensions of the array represented by the buffer. The length of the shape + * array is the number of dimensions. The shape array should always be created and + * filled (difference from CPython). + */ + protected int[] shape; + /** + * Step sizes in the underlying buffer essential to correct translation of an index (or indices) + * into an index into the storage. This reference will be null if not needed for + * the storage organisation, and not requested by the consumer in flags. If it is + * either necessary for the buffer navigation, or requested by the consumer in flags, the + * strides array must be correctly filled to at least the length of the + * shape array. + */ + protected int[] strides; + /** + * Reference to a structure that wraps the underlying storage that the exporter is sharing with + * the consumer. + */ + protected BufferPointer buf; + /** + * Bit pattern using the constants defined in {@link PyBUF} that records the actual capabilities + * this buffer offers. See {@link #assignCapabilityFlags(int, int, int, int)}. + */ + protected int capabilityFlags; + + /** + * The result of the operation is to set the {@link #capabilityFlags} according to the + * capabilities this instance should support. This method is normally called in the constructor + * of each particular sub-class of BaseBuffer, passing in a flags + * argument that originated in the consumer's call to {@link BufferProtocol#getBuffer(int)}. + *

+ * The consumer supplies as a set of flags, using constants from {@link PyBUF}, the + * capabilities that it expects from the buffer. These include a statement of which navigational + * arrays it will use ( shape, strides, and suboffsets), + * whether it wants the format string set so it describes the item type or left + * null, and whether it expects the buffer to be writable. The consumer flags are taken by this + * method both as a statement of needs to be met by the buffer, and as a statement of + * capabilities in the consumer to navigate different buffers. + *

+ * In its call to this method, the exporter specifies the capabilities it requires the consumer + * to have (and indicate by asking for them in flags) in order to navigate the + * buffer successfully. For example, if the buffer is a strided array, the consumer must specify + * that it expects the strides array. Otherwise the method concludes the consumer + * is not capable of the navigation required. Capabilities specified in the + * requiredFlags must appear in the consumer's flags request. If any + * don't, a Python BufferError will be raised. If there is no error these flags + * will be set in capabilityFlags as required of the buffer. + *

+ * The exporter specifies some capabilities it allows the consumer to request, such as + * the format string. Depending on the type of exporter, the navigational arrays ( + * shape, strides, and suboffsets) may also be allowed + * rather than required. Capabilities specified in the allowedFlags, if they also + * appear in the consumer's flags, will be set in capabilityFlags. + *

+ * The exporter specifies some capabilities that will be supplied whether requested or not. For + * example (and it might be the only one) this is used only to express that an unstrided, + * one-dimensional array is C_CONTIGUOUS, F_CONTIGUOUS, and + * ANY_CONTIGUOUS, all at once. Capabilities specified in the + * impliedFlags, will be set in capabilityFlags whether in the + * consumer's flags or not. + *

+ * Capabilities specified in the consumer's flags request, if they do not appear in + * the exporter's requiredFlags allowedFlags or + * impliedFlags, will cause a Python BufferError. + *

+ * Note that this method cannot actually set the shape, strides and + * suboffsets properties: the implementation of the specific buffer type must do + * that based on the capabilityFlags. This forms a partial counterpart to CPython + * PyBuffer_FillInfo() but it is not specific to the simple type of buffer, and + * covers the flag processing of all buffer types. This is complex (in CPython) and the Jython + * approach attempts to be compatible yet comprehensible. + */ + protected void assignCapabilityFlags(int flags, int requiredFlags, int allowedFlags, + int impliedFlags) { + + // Ensure what may be requested includes what must be and what comes unasked + allowedFlags = allowedFlags | requiredFlags | impliedFlags; + + // Look for request flags (other than buffer organisation) outside what is allowed + int syndrome = flags & ~(allowedFlags | ORGANISATION); + + if (syndrome != 0) { + // Some flag was set that is neither required nor allowed + if ((syndrome & WRITABLE) != 0) { + throw notWritable(); + } else if ((syndrome & C_CONTIGUOUS) != 0) { + throw bufferIsNot("C-contiguous"); + } else if ((syndrome & F_CONTIGUOUS) != 0) { + throw bufferIsNot("Fortran-contiguous"); + } else if ((syndrome & ANY_CONTIGUOUS) != 0) { + throw bufferIsNot("contiguous"); + } else { + // Catch-all error (never in practice?) + throw bufferIsNot("capable of matching request"); + } + + } else if ((flags & requiredFlags) != requiredFlags) { + // This buffer needs more capability to navigate than the consumer has requested + if ((flags & ND) != ND) { + throw bufferRequires("shape"); + } else if ((flags & STRIDES) != STRIDES) { + throw bufferRequires("strides"); + } else if ((flags & INDIRECT) != INDIRECT) { + throw bufferRequires("suboffsets"); + } else { + // Catch-all error + throw bufferRequires("feature consumer lacks"); + } + + } else { + // These flags control returns from (default) getShape etc.. + capabilityFlags = (flags & allowedFlags) | impliedFlags; + // Note that shape and strides are still to be initialised + } + + /* + * Caller must responds to the requested/required capabilities with shape and strides arrays + * suited to the actual type of buffer. + */ + } + + /** + * Provide an instance of BaseBuffer or a sub-class meeting the consumer's expectations as + * expressed in the flags argument. Compare CPython: + * + *

+     * int PyBuffer_FillInfo(Py_buffer *view, PyObject *exporter,
+     *                       void *buf, Py_ssize_t len,
+     *                       int readonly, int flags)
+     * 
+ * + * @param exporter the exporting object + * @param buf descriptor for the exported buffer itself + */ + protected BaseBuffer(BufferProtocol exporter, BufferPointer buf) { + // Exporting object (is allowed to be null) + this.obj = exporter; + // Exported data (not normally allowed to be null) + this.buf = buf; + } + + @Override + public boolean isReadonly() { + // Default position is read only: mutable buffers must override + return true; + } + + @Override + public int getNdim() { + return shape.length; + } + + @Override + public int[] getShape() { + // Difference from CPython: never null, even when the consumer doesn't request it. + return shape; + } + + @Override + public int getLen() { + // Correct if contiguous. Override if strided or indirect with itemsize*product(shape). + return buf.size; + } + + // Let the sub-class implement: + // @Override public byte byteAt(int index) throws IndexOutOfBoundsException {} + + @Override + public int intAt(int index) throws IndexOutOfBoundsException { + return 0xff & byteAt(index); + } + + @Override + public void storeAt(byte value, int index) throws IndexOutOfBoundsException, PyException { + throw notWritable(); + } + + // Let the sub-class implement: + // @Override public byte byteAt(int... indices) throws IndexOutOfBoundsException {} + + @Override + public int intAt(int... indices) throws IndexOutOfBoundsException { + return 0xff & byteAt(indices); + } + + @Override + public void storeAt(byte value, int... indices) throws IndexOutOfBoundsException, PyException { + throw notWritable(); + } + + @Override + public void copyTo(byte[] dest, int destPos) throws IndexOutOfBoundsException { + // Correct for contiguous arrays (if destination expects same F or C contiguity) + copyTo(0, dest, destPos, getLen()); + } + + // Let the sub-class implement: + // @Override public void copyTo(int srcIndex, byte[] dest, int destPos, int length) + // throws IndexOutOfBoundsException {} + + @Override + public void copyFrom(byte[] src, int srcPos, int destIndex, int length) + throws IndexOutOfBoundsException, PyException { + throw notWritable(); + } + + /** + * {@inheritDoc} + *

+ * The implementation here calls {@link #releaseAction()}, which the implementer of a specific + * buffer type should override with the necessary actions to release the buffer from the + * exporter. It is not an error to call this method more than once (difference from CPython), or + * on a temporary buffer that needs no release action. If not released explicitly, it will be + * called during object finalisation (before garbage collection) of the buffer object. + */ + @Override + public final void release() { + if (obj != null) { + releaseAction(); + } + obj = null; + } + + @Override + public BufferPointer getBuf() { + return buf; + } + + // Let the sub-class implement: + // @Override public BufferPointer getPointer(int index) { return null; } + // @Override public BufferPointer getPointer(int... indices) { return null; } + + @Override + public int[] getStrides() { + return strides; + } + + @Override + public int[] getSuboffsets() { + return null; + } + + @Override + public boolean isContiguous(char order) { + return true; + } + + @Override + public String getFormat() { + // Avoid having to have an actual 'format' member + return ((capabilityFlags & FORMAT) == 0) ? null : "B"; + } + + @Override + public int getItemsize() { + // Avoid having to have an actual 'itemsize' member + return 1; + } + + /** + * Ensure buffer, if not released sooner, is released from the exporter during object + * finalisation (before garbage collection) of the buffer object. + */ + @Override + protected void finalize() throws Throwable { + release(); + super.finalize(); + } + + /** + * This method will be called when the consumer calls {@link #release()} (to be precise, only on + * the first call). The default implementation does nothing. Override this method to add release + * behaviour specific to exporter. A common convention is to do this within the definition of + * {@link BufferProtocol#getBuffer(int)} within the exporting class, where a nested class is + * finally defined. + */ + protected void releaseAction() {} + + /** + * Check the number of indices (but not their values), raising a Python BufferError if this does + * not match the number of dimensions. + * + * @param indices into the buffer (to test) + * @return number of dimensions + * @throws PyException (BufferError) if wrong number of indices + */ + final int checkDimension(int[] indices) throws PyException { + int ndim = shape.length; + if (indices.length != ndim) { + if (indices.length < ndim) { + throw Py.BufferError("too few indices supplied"); + } else { + throw Py.BufferError("too many indices supplied"); + } + } + return ndim; + } + + /** + * Convenience method to create (for the caller to throw) a + * BufferError("underlying buffer is not writable"). + * + * @return the error as a PyException + */ + protected PyException notWritable() { + return bufferIsNot("writable"); + } + + /** + * Convenience method to create (for the caller to throw) a + * BufferError("underlying buffer is not {property}"). + * + * @param property + * @return the error as a PyException + */ + protected PyException bufferIsNot(String property) { + return Py.BufferError("underlying buffer is not " + property); + } + + /** + * Convenience method to create (for the caller to throw) a + * BufferError("underlying buffer requires {feature}"). + * + * @param feature + * @return the error as a PyException + */ + protected PyException bufferRequires(String feature) { + return Py.BufferError("underlying buffer requires " + feature); + } + +} diff --git a/src/org/python/core/buffer/SimpleBuffer.java b/src/org/python/core/buffer/SimpleBuffer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/buffer/SimpleBuffer.java @@ -0,0 +1,66 @@ +package org.python.core.buffer; + +import org.python.core.BufferPointer; +import org.python.core.BufferProtocol; + +/** + * Buffer API over a writable one-dimensional array of one-byte items. + */ +public class SimpleBuffer extends SimpleReadonlyBuffer { + + /** + * SimpleBuffer allows consumer requests that are the same as + * SimpleReadonlyBuffer, with the addition of WRITABLE. + */ + protected static final int ALLOWED_FLAGS = WRITABLE | SimpleReadonlyBuffer.ALLOWED_FLAGS; + + /** + * Provide an instance of SimpleBuffer in a default, semi-constructed state. The + * sub-class constructor takes responsibility for completing construction with a call to + * {@link #assignCapabilityFlags(int, int, int, int)}. + * + * @param exporter the exporting object + * @param buf wrapping the array of bytes storing the implementation of the object + */ + protected SimpleBuffer(BufferProtocol exporter, BufferPointer buf) { + super(exporter, buf); + } + + /** + * Provide an instance of SimpleBuffer meeting the consumer's expectations as expressed in the + * flags argument. + * + * @param exporter the exporting object + * @param buf wrapping the array of bytes storing the implementation of the object + * @param flags consumer requirements + */ + public SimpleBuffer(BufferProtocol exporter, BufferPointer buf, int flags) { + super(exporter, buf); + assignCapabilityFlags(flags, REQUIRED_FLAGS, ALLOWED_FLAGS, IMPLIED_FLAGS); + fillInfo(); + } + + @Override + public boolean isReadonly() { + return false; + } + + @Override + public void storeAt(byte value, int index) { + buf.storage[buf.offset + index] = value; + } + + @Override + public void storeAt(byte value, int... indices) { + if (indices.length != 1) { + checkDimension(indices); + } + storeAt(value, indices[0]); + } + + @Override + public void copyFrom(byte[] src, int srcPos, int destIndex, int length) { + System.arraycopy(src, srcPos, buf.storage, buf.offset + destIndex, length); + } + +} diff --git a/src/org/python/core/buffer/SimpleReadonlyBuffer.java b/src/org/python/core/buffer/SimpleReadonlyBuffer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/buffer/SimpleReadonlyBuffer.java @@ -0,0 +1,128 @@ +package org.python.core.buffer; + +import org.python.core.BufferPointer; +import org.python.core.BufferProtocol; + +/** + * Buffer API over a one-dimensional array of one-byte items providing read-only API. A writable + * simple buffer will extend this implementation. + */ +public class SimpleReadonlyBuffer extends BaseBuffer { + + /** + * Using the PyBUF constants, express capabilities the consumer must request if it is to + * navigate the storage successfully. (None.) + */ + public static final int REQUIRED_FLAGS = 0; + /** + * Using the PyBUF constants, express capabilities the consumer may request so it can navigate + * the storage in its chosen way. The buffer instance has to implement these mechanisms if and + * only if they are requested. (FORMAT | ND | STRIDES | INDIRECT) + */ + public static final int ALLOWED_FLAGS = FORMAT | ND | STRIDES | INDIRECT; + /** + * Using the PyBUF constants, express capabilities the consumer doesn't need to request because + * they will be there anyway. (One-dimensional arrays (including those sliced with step size + * one) are C- and F-contiguous.) + */ + public static final int IMPLIED_FLAGS = CONTIGUITY; + /** + * The strides array for this type is always a single element array with a 1 in it. + */ + protected static final int[] SIMPLE_STRIDES = {1}; + + /** + * Partial counterpart to CPython PyBuffer_FillInfo() specific to the simple type + * of buffer and called from the constructor. The base constructor will already have been + * called, filling {@link #buf} and {@link #obj}. And the method + * {@link #assignCapabilityFlags(int, int, int, int)} has set {@link #capabilityFlags}. + */ + protected void fillInfo() { + /* + * We will already have called: assignCapabilityFlags(flags, requiredFlags, allowedFlags, + * impliedFlags); So capabilityFlags holds the requests for shape, strides, writable, etc.. + */ + // Difference from CPython: never null, even when the consumer doesn't request it + shape = new int[1]; + shape[0] = getLen(); + + // Following CPython: provide strides only when the consumer requests it + if ((capabilityFlags & STRIDES) == STRIDES) { + strides = SIMPLE_STRIDES; + } + + // Even when the consumer requests suboffsets, the exporter is allowed to supply null. + // In theory, the exporter could require that it be requested and still supply null. + } + + /** + * Provide an instance of SimpleReadonlyBuffer in a default, semi-constructed + * state. The sub-class constructor takes responsibility for completing construction including a + * call to {@link #assignCapabilityFlags(int, int, int, int)}. + * + * @param exporter the exporting object + * @param buf wrapping the array of bytes storing the implementation of the object + */ + protected SimpleReadonlyBuffer(BufferProtocol exporter, BufferPointer buf) { + super(exporter, buf); + } + + /** + * Provide an instance of SimpleReadonlyBuffer meeting the consumer's expectations as expressed + * in the flags argument. + * + * @param exporter the exporting object + * @param buf wrapping the array of bytes storing the implementation of the object + * @param flags consumer requirements + */ + public SimpleReadonlyBuffer(BufferProtocol exporter, BufferPointer buf, int flags) { + super(exporter, buf); + assignCapabilityFlags(flags, REQUIRED_FLAGS, ALLOWED_FLAGS, IMPLIED_FLAGS); + fillInfo(); + } + + @Override + public int getNdim() { + return 1; + } + + @Override + public byte byteAt(int index) throws IndexOutOfBoundsException { + // offset is not necessarily zero + return buf.storage[buf.offset + index]; + } + + @Override + public int intAt(int index) throws IndexOutOfBoundsException { + // Implement directly: a bit quicker than the default + return 0xff & buf.storage[buf.offset + index]; + } + + @Override + public byte byteAt(int... indices) throws IndexOutOfBoundsException { + if (indices.length != 1) { + checkDimension(indices); + } + return byteAt(indices[0]); + } + + @Override + public void copyTo(int srcIndex, byte[] dest, int destPos, int length) + throws IndexOutOfBoundsException { + System.arraycopy(buf.storage, buf.offset + srcIndex, dest, destPos, length); + } + + @Override + public BufferPointer getPointer(int index) { + return new BufferPointer(buf.storage, buf.offset + index, 1); + } + + @Override + public BufferPointer getPointer(int... indices) { + if (indices.length != 1) { + checkDimension(indices); + } + return getPointer(indices[0]); + } + +} diff --git a/src/org/python/core/buffer/SimpleStringBuffer.java b/src/org/python/core/buffer/SimpleStringBuffer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/buffer/SimpleStringBuffer.java @@ -0,0 +1,149 @@ +package org.python.core.buffer; + +import org.python.core.BufferPointer; +import org.python.core.BufferProtocol; +import org.python.core.util.StringUtil; + +/** + * Buffer API that appears to be a one-dimensional array of one-byte items providing read-only API, + * but which is actually backed by a Java String. Some of the buffer API absolutely needs access to + * the data as a byte array (those parts that involve a {@link BufferPointer} result), and therefore + * this class must create a byte array from the String for them. However, it defers creation of a + * byte array until that part of the API is actually used. This class overrides those methods in + * SimpleReadonlyBuffer that would access the buf attribute to work out their results + * from the String instead. + */ +public class SimpleStringBuffer extends SimpleReadonlyBuffer { + + /** + * The string backing this PyBuffer. A substitute for {@link #buf} until we can no longer avoid + * creating it. + */ + private String bufString; + + /** + * Partial counterpart to CPython PyBuffer_FillInfo() specific to the simple type + * of buffer and called from the constructor. The base constructor will already have been + * called, filling {@link #bufString} and {@link #obj}. And the method + * {@link #assignCapabilityFlags(int, int, int, int)} has set {@link #capabilityFlags}. + */ + protected void fillInfo(String bufString) { + /* + * We will already have called: assignCapabilityFlags(flags, requiredFlags, allowedFlags, + * impliedFlags); So capabilityFlags holds the requests for shape, strides, writable, etc.. + */ + // Save the backing string + this.bufString = bufString; + + // Difference from CPython: never null, even when the consumer doesn't request it + shape = new int[1]; + shape[0] = bufString.length(); + + // Following CPython: provide strides only when the consumer requests it + if ((capabilityFlags & STRIDES) == STRIDES) { + strides = SIMPLE_STRIDES; + } + + // Even when the consumer requests suboffsets, the exporter is allowed to supply null. + // In theory, the exporter could require that it be requested and still supply null. + } + + /** + * Provide an instance of SimpleReadonlyBuffer meeting the consumer's expectations as expressed + * in the flags argument. + * + * @param exporter the exporting object + * @param bufString storing the implementation of the object + * @param flags consumer requirements + */ + public SimpleStringBuffer(BufferProtocol exporter, String bufString, int flags) { + super(exporter, null); + assignCapabilityFlags(flags, REQUIRED_FLAGS, ALLOWED_FLAGS, IMPLIED_FLAGS); + fillInfo(bufString); + } + + /** + * {@inheritDoc} + *

+ * This method uses {@link String#length()} rather than create an actual byte buffer. + */ + @Override + public int getLen() { + // Avoid creating buf by using String.length + return bufString.length(); + } + + /** + * {@inheritDoc} + *

+ * This method uses {@link String#charAt(int)} rather than create an actual byte buffer. + */ + @Override + public byte byteAt(int index) throws IndexOutOfBoundsException { + // Avoid creating buf by using String.charAt + return (byte)bufString.charAt(index); + } + + /** + * {@inheritDoc} + *

+ * This method uses {@link String#charAt(int)} rather than create an actual byte buffer. + */ + @Override + public int intAt(int index) throws IndexOutOfBoundsException { + // Avoid creating buf by using String.charAt + return bufString.charAt(index); + } + + /** + * {@inheritDoc} + *

+ * This method uses {@link String#charAt(int)} rather than create an actual byte buffer. + */ + @Override + public void copyTo(int srcIndex, byte[] dest, int destPos, int length) + throws IndexOutOfBoundsException { + // Avoid creating buf by using String.charAt + int endIndex = srcIndex + length, p = destPos; + for (int i = srcIndex; i < endIndex; i++) { + dest[p++] = (byte)bufString.charAt(i); + } + } + + /** + * {@inheritDoc} + *

+ * This method creates an actual byte buffer from the String if none yet exists. + */ + @Override + public BufferPointer getBuf() { + if (buf == null) { + // We can't avoid creating buf any longer + buf = new BufferPointer(StringUtil.toBytes(bufString)); + } + return buf; + } + + /** + * {@inheritDoc} + *

+ * This method creates an actual byte buffer from the String if none yet exists. + */ + @Override + public BufferPointer getPointer(int index) { + getBuf(); // Ensure buffer created + return super.getPointer(index); + } + + /** + * {@inheritDoc} + *

+ * This method creates an actual byte buffer from the String if none yet exists. + */ + @Override + public BufferPointer getPointer(int... indices) { + getBuf(); // Ensure buffer created + return super.getPointer(indices); + } + +} diff --git a/tests/java/org/python/core/BaseBytesTest.java b/tests/java/org/python/core/BaseBytesTest.java --- a/tests/java/org/python/core/BaseBytesTest.java +++ b/tests/java/org/python/core/BaseBytesTest.java @@ -4,10 +4,11 @@ import java.util.List; import java.util.Random; +import junit.framework.TestCase; + +import org.python.core.buffer.SimpleBuffer; import org.python.util.PythonInterpreter; -import junit.framework.TestCase; - /** * Unit test of org.python.core.BaseBytes, a class that supplies much of the behaviour of the Jython * bytearray. In fact, it supplies almost all the immutable behaviour, and is abstract. In order to @@ -517,7 +518,7 @@ return new MyBytes(value); } - public BaseBytes getInstance(MemoryViewProtocol value) throws PyException { + public BaseBytes getInstance(BufferProtocol value) throws PyException { return new MyBytes(value); } @@ -599,9 +600,9 @@ * * @param value source of the bytes (and size) */ - public MyBytes(MemoryViewProtocol value) { + public MyBytes(BufferProtocol value) { super(TYPE); - init(value.getMemoryView()); + init((BufferProtocol)value.getBuffer(PyBUF.SIMPLE)); } /** @@ -769,13 +770,12 @@ /** * An object that for test purposes (of construction and slice assignment) contains an array of - * values that it is able to offer for reading through the MemoryView interface. + * values that it is able to offer for reading through the PyBuffer interface. */ - public static class MemoryViewable extends PyObject implements MemoryViewProtocol { + public static class BufferedObject extends PyObject implements BufferProtocol { - public static final PyType TYPE = PyType.fromClass(MemoryViewable.class); + public static final PyType TYPE = PyType.fromClass(BufferedObject.class); - private MemoryView mv; private byte[] store; /** @@ -783,7 +783,7 @@ * * @param value integers to store */ - MemoryViewable(int[] value) { + BufferedObject(int[] value) { super(TYPE); int n = value.length; store = new byte[n]; @@ -793,56 +793,10 @@ } @Override - public MemoryView getMemoryView() { - if (mv == null) { - mv = new MemoryViewImpl(); - } - return mv; + public PyBuffer getBuffer(int flags) { + return new SimpleBuffer(this, new BufferPointer(store), flags); } - /** - * All instances of MemoryViewable have one dimension with stride one. - */ - private static final PyTuple STRIDES = new PyTuple(Py.One); - - /** - * Very simple MemoryView for one-dimensional byte array. - */ - class MemoryViewImpl implements MemoryView { - - private final PyTuple shape = new PyTuple(new PyInteger(store.length)); - - @Override - public String get_format() { - return "B"; - } - - @Override - public int get_itemsize() { - return 1; - } - - @Override - public PyTuple get_shape() { - return shape; - } - - @Override - public int get_ndim() { - return 1; - } - - @Override - public PyTuple get_strides() { - return STRIDES; - } - - @Override - public boolean get_readonly() { - return true; - } - - } } /** diff --git a/tests/java/org/python/core/PyBufferTest.java b/tests/java/org/python/core/PyBufferTest.java new file mode 100644 --- /dev/null +++ b/tests/java/org/python/core/PyBufferTest.java @@ -0,0 +1,1094 @@ +package org.python.core; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import junit.framework.TestCase; + +import org.python.core.buffer.SimpleBuffer; +import org.python.core.buffer.SimpleReadonlyBuffer; +import org.python.core.buffer.SimpleStringBuffer; +import org.python.util.PythonInterpreter; + +/** + * Test the several implementations (and exporters) of the PyBuffer interface provided in the Jython + * core. + *

+ * The approach is to create test material once that has the necessary variety in byte array values, + * then for each test, when the JUnit framework creates an instance of the function-specific test, + * to use this material to create instances of each read-only type and each writable type. Writable + * instance types go onto the lists buffersToRead and buffersToWrite, while read-only instances go + * onto the lists buffersToRead and buffersToFailToWrite. + *

+ * In general, tests of methods that read data apply themselves to all the elements of the + * buffersToRead list, while tests of methods that write data apply themselves to all the elements + * of the buffersToWrite list and check that members of the buffersToFailToWrite list raise an + * exception. + *

+ * The Jython buffer API follows the structures of the CPython buffer API so that it supports in + * principle the use of multi-dimensional, strided add indirect array structures as buffers. + * However, actual buffers in the Jython core, and therefore these tests, limit themselves to one + * dimensional contiguous buffers with a simple organisation. Some tests apply directly to the + * N-dimensional cases, and some need a complete re-think. Sub-classing this test would probably be + * a good way to extend it to a wider range. + */ +public class PyBufferTest extends TestCase { + + /** + * Generated constructor + * + * @param name + */ + public PyBufferTest(String name) { + super(name); + } + + /** Sometimes we need the interpreter to be initialised **/ + PythonInterpreter interp; + + /* + * Values for initialising the exporters. + */ + private static final ByteMaterial byteMaterial = new ByteMaterial(0, 17, 16); + private static final ByteMaterial abcMaterial = new ByteMaterial("abcdef"); + private static final ByteMaterial stringMaterial = new ByteMaterial("Mon c?t? f?cheux"); + private static final ByteMaterial emptyMaterial = new ByteMaterial(new byte[0]); + private static final ByteMaterial longMaterial = new ByteMaterial(0, 5, 1000); + + protected void setUp() throws Exception { + super.setUp(); + + // Exception raising requires the Jython interpreter + interp = new PythonInterpreter(); + + // Tests using local examples + queueWrite(new SimpleExporter(abcMaterial.getBytes()), abcMaterial); + queueReadonly(new SimpleExporter(byteMaterial.getBytes(), true), byteMaterial); + queueReadonly(new StringExporter(stringMaterial.string), stringMaterial); + queueWrite(new SimpleExporter(emptyMaterial.getBytes()), emptyMaterial); + + // Tests with PyByteArray + queueWrite(new PyByteArray(abcMaterial.getBytes()), abcMaterial); + queueWrite(new PyByteArray(longMaterial.getBytes()), longMaterial); + queueWrite(new PyByteArray(), emptyMaterial); + + // Tests with PyString + queueReadonly(new PyString(abcMaterial.string), abcMaterial); + queueReadonly(new PyString(), emptyMaterial); + + // Ensure case is tested where PyByteArray has an internal offset + PyByteArray truncated = new PyByteArray(stringMaterial.getBytes()); + truncated.delRange(0, 4); + ByteMaterial truncatedMaterial = new ByteMaterial(stringMaterial.string.substring(4)); + assert truncated.__alloc__() > truncatedMaterial.length; + queueWrite(truncated, truncatedMaterial); + } + + private void queueWrite(BufferProtocol exporter, ByteMaterial material) { + BufferTestPair pair = new BufferTestPair(exporter, material); + buffersToRead.add(pair); + buffersToWrite.add(pair); + } + + private void queueReadonly(BufferProtocol exporter, ByteMaterial material) { + BufferTestPair pair = new BufferTestPair(exporter, material); + buffersToRead.add(pair); + buffersToFailToWrite.add(pair); + } + + /** Read operations should succeed on all these objects. */ + private List buffersToRead = new LinkedList(); + /** Write operations should succeed on all these objects. */ + private List buffersToWrite = new LinkedList(); + /** Write operations should fail on all these objects. */ + private List buffersToFailToWrite = new LinkedList(); + + /** We should be able to get a buffer for all these flag types. */ + private int[] validFlags = {PyBUF.SIMPLE, PyBUF.ND, PyBUF.STRIDES, PyBUF.INDIRECT}; + + /** To which we can add any of these (in one dimension, anyway) */ + private int[] validTassles = {PyBUF.FORMAT, + PyBUF.C_CONTIGUOUS, + PyBUF.F_CONTIGUOUS, + PyBUF.ANY_CONTIGUOUS}; + + /** + * Test method for {@link org.python.core.PyBuffer#getBuf()}. + */ + public void testGetBuffer() { + + for (BufferTestPair test : buffersToRead) { + System.out.println("getBuffer(): " + test); + for (int flags : validFlags) { + for (int tassle : validTassles) { + PyBuffer view = test.exporter.getBuffer(flags | tassle); + assertNotNull(view); + } + } + } + + for (BufferTestPair test : buffersToWrite) { + System.out.println("getBuffer(WRITABLE): " + test); + for (int flags : validFlags) { + for (int tassle : validTassles) { + PyBuffer view = test.exporter.getBuffer(flags | tassle | PyBUF.WRITABLE); + assertNotNull(view); + } + } + } + + for (BufferTestPair test : buffersToFailToWrite) { + System.out.println("getBuffer(WRITABLE): " + test); + for (int flags : validFlags) { + try { + test.exporter.getBuffer(flags | PyBUF.WRITABLE); + fail("Write access not prevented: " + test); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + } + + /** + * Test method for {@link org.python.core.PyBUF#isReadonly()}. + */ + public void testIsReadonly() { + + for (BufferTestPair test : buffersToWrite) { + System.out.println("isReadonly: " + test); + assertFalse(test.simple.isReadonly()); + } + + for (BufferTestPair test : buffersToFailToWrite) { + System.out.println("isReadonly: " + test); + assertTrue(test.simple.isReadonly()); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getNdim()}. + */ + public void testGetNdim() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getNdim: " + test); + assertEquals("simple ndim", test.shape.length, test.simple.getNdim()); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getShape()}. + */ + public void testGetShape() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getShape: " + test); + int[] shape = test.simple.getShape(); + assertNotNull(shape); + assertIntsEqual("simple shape", test.shape, shape); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getLen()}. + */ + public void testGetLen() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getLen: " + test); + assertEquals(" simple len", test.material.bytes.length, test.simple.getLen()); + assertEquals("strided len", test.material.bytes.length, test.strided.getLen()); + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#byteAt(int)}. + */ + public void testByteAt() { + for (BufferTestPair test : buffersToRead) { + System.out.println("byteAt: " + test); + int n = test.material.length; + byte[] exp = test.material.bytes; + for (int i = 0; i < n; i++) { + assertEquals(exp[i], test.simple.byteAt(i)); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#byteAt(int[])}. + */ + public void testByteAtNdim() { + int[] index = new int[1]; + for (BufferTestPair test : buffersToRead) { + System.out.println("byteAt(array): " + test); + if (test.strided.getShape().length != 1) { + fail("Test not implemented dimensions != 1"); + } + byte[] exp = test.material.bytes; + int n = test.material.length; + // Run through 1D index for simple + for (int i = 0; i < n; i++) { + index[0] = i; + assertEquals(exp[i], test.simple.byteAt(index)); + } + // Check 2D index throws + try { + test.simple.byteAt(0, 0); + fail("Use of 2D index did not raise exception"); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#intAt(int)}. + */ + public void testIntAt() { + for (BufferTestPair test : buffersToRead) { + System.out.println("intAt: " + test); + int n = test.material.length; + int[] exp = test.material.ints; + for (int i = 0; i < n; i++) { + assertEquals(exp[i], test.simple.intAt(i)); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#intAt(int[])}. + */ + public void testIntAtNdim() { + int[] index = new int[1]; + for (BufferTestPair test : buffersToRead) { + System.out.println("intAt(array): " + test); + if (test.strided.getShape().length != 1) { + fail("Test not implemented dimensions != 1"); + } + int[] exp = test.material.ints; + int n = test.material.length; + // Run through 1D index for simple + for (int i = 0; i < n; i++) { + index[0] = i; + assertEquals(exp[i], test.simple.intAt(index)); + } + // Check 2D index throws + try { + test.simple.intAt(0, 0); + fail("Use of 2D index did not raise exception"); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#storeAt(byte, int)}. + */ + public void testStoreAt() { + for (BufferTestPair test : buffersToWrite) { + System.out.println("storeAt: " + test); + int n = test.material.length; + int[] exp = test.material.ints; + // Write modified test material into each location using storeAt() + for (int i = 0; i < n; i++) { + byte v = (byte)(exp[i] ^ 3); // twiddle some bits + test.simple.storeAt(v, i); + } + // Compare each location with modified test data using intAt() + for (int i = 0; i < n; i++) { + assertEquals(exp[i] ^ 3, test.simple.intAt(i)); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#storeAt(byte, int[])}. + */ + public void testStoreAtNdim() { + for (BufferTestPair test : buffersToWrite) { + System.out.println("storeAt: " + test); + int n = test.material.length; + int[] exp = test.material.ints; + // Write modified test material into each location using storeAt() + for (int i = 0; i < n; i++) { + byte v = (byte)(exp[i] ^ 3); // twiddle some bits + test.simple.storeAt(v, i); + } + // Compare each location with modified test data using intAt() + for (int i = 0; i < n; i++) { + assertEquals(exp[i] ^ 3, test.simple.intAt(i)); + } + // Check 2D index throws + try { + test.simple.storeAt((byte)1, 0, 0); + fail("Use of 2D index did not raise exception"); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#copyTo(byte[], int)}. + */ + public void testCopyTo() { + final int OFFSET = 5; + for (BufferTestPair test : buffersToRead) { + System.out.println("copyTo: " + test); + int n = test.material.length; + // Try with zero offset + byte[] actual = new byte[n]; + test.simple.copyTo(actual, 0); + assertBytesEqual("copyTo() incorrect", test.material.bytes, actual, 0); + // Try to middle of array + actual = new byte[n + 2 * OFFSET]; + test.simple.copyTo(actual, OFFSET); + assertBytesEqual("copyTo(offset) incorrect", test.material.bytes, actual, OFFSET); + assertEquals("data before destination", 0, actual[OFFSET - 1]); + assertEquals("data after destination", 0, actual[OFFSET + n]); + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#copyTo(int, byte[], int, int)}. + */ + public void testSliceCopyTo() { + final int OFFSET = 5; + final byte BLANK = 7; + + for (BufferTestPair test : buffersToRead) { + System.out.println("copyTo(from slice): " + test); + PyBuffer view = test.simple; + + int n = test.material.length; + byte[] actual = new byte[n + 2 * OFFSET]; + + // Try destination positions in actual[] of 0 and OFFSET + for (int destPos = 0; destPos <= OFFSET; destPos += OFFSET) { + // Try source positions in 0 and OFFSET + for (int srcIndex = 0; srcIndex <= OFFSET; srcIndex += OFFSET) { + + // A variety of lengths from zero to (n-srcIndex)-ish + for (int length = 0; srcIndex + length <= n; length = 2 * length + 1) { + /* + * System.out.printf(" copy src[%d:%d] (%d) to dst[%d:%d] (%d)\n", + * srcIndex, srcIndex + length, n, destPos, destPos + length, + * actual.length); + */ + Arrays.fill(actual, BLANK); + + // Test the method + view.copyTo(srcIndex, actual, destPos, length); + + // Check changed part of destination + assertBytesEqual("copyTo(slice) incorrect", test.material.bytes, srcIndex, + actual, destPos, length); + if (destPos > 0) { + assertEquals("data before destination", BLANK, actual[destPos - 1]); + } + assertEquals("data after destination", BLANK, actual[destPos + length]); + } + + // And from exactly n-srcIndex down to zero-ish + for (int trim = 0; srcIndex + trim <= n; trim = 2 * trim + 1) { + int length = n - srcIndex - trim; + /* + * System.out.printf(" copy src[%d:%d] (%d) to dst[%d:%d] (%d)\n", + * srcIndex, srcIndex + length, n, destPos, destPos + length, + * actual.length); + */ + Arrays.fill(actual, BLANK); + + // Test the method + view.copyTo(srcIndex, actual, destPos, length); + + // Check changed part of destination + assertBytesEqual("copyTo(slice) incorrect", test.material.bytes, srcIndex, + actual, destPos, length); + if (destPos > 0) { + assertEquals("data before destination", BLANK, actual[destPos - 1]); + } + assertEquals("data after destination", BLANK, actual[destPos + length]); + } + } + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#copyFrom(byte[], int, int, int)}. + */ + public void testCopyFrom() { + final int OFFSET = 5; + final byte BLANK = 7; + + for (BufferTestPair test : buffersToWrite) { + System.out.println("copyFrom(): " + test); + PyBuffer view = test.simple; + + int n = test.material.length; + byte[] actual = new byte[n]; + byte[] expected = new byte[n]; + + // Make some source material for copies (need to test at OFFSET too). + byte[] src = new byte[n + OFFSET]; + for (int i = 0; i < src.length; i++) { + src[i] = (byte)i; + } + + // Try destination positions in test object of 0 and OFFSET + for (int destIndex = 0; destIndex <= OFFSET; destIndex += OFFSET) { + + // Try source positions in 0 and OFFSET + for (int srcPos = 0; srcPos <= OFFSET; srcPos += OFFSET) { + + // A variety of lengths from zero to (n-destIndex)-ish + for (int length = 0; destIndex + length <= n; length = 2 * length + 1) { + + System.out.printf(" copy src[%d:%d] (%d) to dst[%d:%d] (%d)\n", srcPos, + srcPos + length, n, destIndex, destIndex + length, + actual.length); + + // Initialise the object (have to do each time) and expected value + for (int i = 0; i < n; i++) { + expected[i] = BLANK; + view.storeAt(BLANK, i); + } + + // Test the method and extract the result to actual[] + view.copyFrom(src, srcPos, destIndex, length); + view.copyTo(actual, 0); + + // Complete what is should be in expected[] + for (int i = 0; i < length; i++) { + expected[destIndex + i] = src[srcPos + i]; + } + assertBytesEqual("copyFrom() incorrect", expected, actual, 0); + } + + // And from exactly n-destIndex down to zero-ish + for (int trim = 0; destIndex + trim <= n; trim = 2 * trim + 1) { + int length = n - destIndex - trim; + System.out.printf(" copy src[%d:%d] (%d) to dst[%d:%d] (%d)\n", srcPos, + srcPos + length, n, destIndex, destIndex + length, + actual.length); + + // Initialise the object (have to do each time) and expected value + for (int i = 0; i < n; i++) { + expected[i] = BLANK; + view.storeAt(BLANK, i); + } + + // Test the method and extract the result to actual[] + view.copyFrom(src, srcPos, destIndex, length); + view.copyTo(actual, 0); + + // Complete what is should be in expected[] + for (int i = 0; i < length; i++) { + expected[destIndex + i] = src[srcPos + i]; + } + assertBytesEqual("copyFrom() incorrect", expected, actual, 0); + } + } + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#getBuf()}. + */ + public void testGetBuf() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getBuf: " + test); + PyBuffer view = test.exporter.getBuffer(PyBUF.SIMPLE); + ByteMaterial m = test.material; + + BufferPointer bp = view.getBuf(); + assertBytesEqual("getBuf: ", m.bytes, bp); + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#getPointer(int)}. + */ + public void testGetPointer() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getPointer: " + test); + PyBuffer view = test.strided; + int n = test.material.length, itemsize = view.getItemsize(); + byte[] exp = new byte[itemsize], bytes = test.material.bytes; + + for (int i = 0; i < n; i++) { + // Expected result is one item (allow for itemsize) + int p = i * itemsize; + for (int j = 0; j < itemsize; j++) { + exp[j] = bytes[p + j]; + } + + // Get pointer and check contents for correct data + BufferPointer bp = view.getPointer(i); + assertBytesEqual("getPointer value", exp, bp.storage, bp.offset); + assertEquals("getPointer size wrong", itemsize, bp.size); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#getPointer(int[])}. + */ + public void testGetPointerNdim() { + int[] index = new int[1]; + for (BufferTestPair test : buffersToRead) { + System.out.println("getPointer(array): " + test); + PyBuffer view = test.strided; + int n = test.material.length, itemsize = view.getItemsize(); + byte[] exp = new byte[itemsize], bytes = test.material.bytes; + + for (int i = 0; i < n; i++) { + // Expected result is one item (allow for itemsize) + int p = i * itemsize; + for (int j = 0; j < itemsize; j++) { + exp[j] = bytes[p + j]; + } + + // Get pointer and check contents for correct data + index[0] = i; + BufferPointer bp = view.getPointer(index); + assertBytesEqual("getPointer value", exp, bp.storage, bp.offset); + assertEquals("getPointer size wrong", itemsize, bp.size); + } + // Check 2D index throws + try { + view.getPointer(0, 0); + fail("Use of 2D index did not raise exception"); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + /** + * Test method for {@link org.python.core.PyBUF#release()}. + */ + public void testRelease() { + for (BufferTestPair test : buffersToRead) { + System.out.println("release: " + test); + BufferProtocol obj = test.exporter; + // The object should already be exporting test.simple and test.strided + PyBuffer a = test.simple; // 1 + PyBuffer b = test.strided; // 2 + PyBuffer c = obj.getBuffer(PyBUF.SIMPLE | PyBUF.FORMAT); // 3 + checkExporting(obj); + // Multiple releases of the same buffer are just one release + b.release(); // 2 + b.release(); + b.release(); + b.release(); + checkExporting(obj); + // Now see that releasing in some other order works correctly + a.release(); // 1 + checkExporting(obj); + PyBuffer d = obj.getBuffer(PyBUF.STRIDES | PyBUF.FORMAT); // 2 + c.release(); // 1 + checkExporting(obj); + d.release(); // 0 + checkNotExporting(obj); + d.release(); // 0 + checkNotExporting(obj); + } + } + + /** + * Error if exporter is not actually exporting (and is of a type that locks on export). + * + * @param exporter + */ + private void checkExporting(BufferProtocol exporter) { + if (exporter instanceof SimpleExporter) { + assertTrue("exports not being counted", ((SimpleExporter)exporter).exportCount >= 1); + } else if (exporter instanceof PyByteArray) { + // Size-changing access should fail + try { + ((PyByteArray)exporter).bytearray_extend(Py.One); + fail("bytearray_extend with exports should fail"); + } catch (Exception e) { + // Success + } + } + // Other types cannot be checked + } + + /** + * Error if exporter is exporting (and is of a type that locks on export). + * + * @param exporter + */ + private void checkNotExporting(BufferProtocol exporter) { + if (exporter instanceof SimpleExporter) { + assertFalse("exports falsely counted", ((SimpleExporter)exporter).exportCount >= 1); + } else if (exporter instanceof PyByteArray) { + // Size-changing access should fail + try { + ((PyByteArray)exporter).bytearray_extend(Py.One); + } catch (Exception e) { + fail("bytearray unexpectedly locked"); + } + } + // Other types cannot be checked + } + + /** + * Test method for {@link org.python.core.PyBUF#getStrides()}. + */ + public void testGetStrides() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getStrides: " + test); + // When not requested ... + assertNull(test.simple.getStrides()); + // When requested, ought to be as expected + int[] strides = test.strided.getStrides(); + assertNotNull(strides); + assertIntsEqual("strided.strides", test.strides, strides); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getSuboffsets()}. + */ + public void testGetSuboffsets() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getSuboffsets: " + test); + // Null for all test material + assertNull(test.simple.getSuboffsets()); + assertNull(test.strided.getSuboffsets()); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#isContiguous(char)}. + */ + public void testIsContiguous() { + for (BufferTestPair test : buffersToRead) { + System.out.println("isContiguous: " + test); + // True for all test material and orders (since 1-dimensional) + for (char order : validOrders) { + assertTrue(test.simple.isContiguous(order)); + assertTrue(test.strided.isContiguous(order)); + } + } + } + + private static final char[] validOrders = {'C', 'F', 'A'}; + + /** + * Test method for {@link org.python.core.PyBuffer#getFormat()}. + */ + public void testGetFormat() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getFormat: " + test); + // Null for all test material + assertNull(test.simple.getFormat()); + assertNull(test.strided.getFormat()); + // However, we can ask for it explicitly ... + PyBuffer simpleWithFormat = test.exporter.getBuffer(PyBUF.SIMPLE | PyBUF.FORMAT); + PyBuffer stridedWithFormat = test.exporter.getBuffer(PyBUF.STRIDES | PyBUF.FORMAT); + // "B" for all test material where requested in flags + assertEquals("B", simpleWithFormat.getFormat()); + assertEquals("B", stridedWithFormat.getFormat()); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getItemsize()}. + */ + public void testGetItemsize() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getItemsize: " + test); + // Unity for all test material + assertEquals(1, test.simple.getItemsize()); + assertEquals(1, test.strided.getItemsize()); + } + } + + /** + * A class to act as an exporter that uses the SimpleBuffer (or SimpleReadonlyBuffer). This + * permits testing abstracted from the Jython interpreter. + */ + static class SimpleExporter implements BufferProtocol { + + byte[] storage; + int exportCount; + boolean readonly; + + /** + * Construct a simple exporter from the bytes supplied. + * + * @param storage + */ + public SimpleExporter(byte[] storage) { + this.storage = storage; + } + + /** + * Construct a simple exporter from the bytes supplied, optionally read-only. + * + * @param storage + * @param readonly + */ + public SimpleExporter(byte[] storage, boolean readonly) { + this.storage = storage; + this.readonly = readonly; + } + + @Override + public PyBuffer getBuffer(int flags) { + BufferPointer mb = new BufferPointer(storage); + exportCount++; + if (readonly) { + return new SimpleReadonlyBuffer(this, mb, flags) { + + protected void releaseAction() { + --exportCount; + } + }; + } else { + return new SimpleBuffer(this, mb, flags) { + + protected void releaseAction() { + --exportCount; + } + }; + } + } + } + + /** + * A class to act as an exporter that uses the SimpleStringBuffer. This permits testing + * abstracted from the Jython interpreter. + */ + static class StringExporter implements BufferProtocol { + + String storage; + int exportCount; + + /** + * Construct a simple exporter from the String supplied. + * + * @param s + */ + public StringExporter(String s) { + storage = s; + } + + @Override + public PyBuffer getBuffer(int flags) { + return new SimpleStringBuffer(this, storage, flags); + } + } + + /** + * Class to hold test material representing the same sequence of values 0..255 in several + * different ways. + */ + protected static class ByteMaterial { + + final String string; + final byte[] bytes; + final int[] ints; + final int length; + + /** Construct from String. */ + public ByteMaterial(String s) { + string = s; + length = s.length(); + bytes = new byte[length]; + ints = new int[length]; + for (int i = 0; i < length; i++) { + int x = s.charAt(i); + ints[i] = x; + bytes[i] = (byte)x; + } + } + + /** Construct from byte array. */ + public ByteMaterial(byte[] b) { + length = b.length; + StringBuilder buf = new StringBuilder(length); + bytes = new byte[length]; + ints = new int[length]; + for (int i = 0; i < length; i++) { + int x = 0xff & b[i]; + ints[i] = x; + bytes[i] = (byte)x; + buf.appendCodePoint(x); + } + string = buf.toString(); + } + + /** Construct from int array. */ + public ByteMaterial(int[] a) { + length = a.length; + StringBuilder buf = new StringBuilder(length); + bytes = new byte[length]; + ints = new int[length]; + for (int i = 0; i < length; i++) { + int x = a[i]; + ints[i] = x; + bytes[i] = (byte)x; + buf.appendCodePoint(x); + } + string = buf.toString(); + } + + /** Construct from pattern on values (used modulo 256). */ + public ByteMaterial(int start, int inc, int count) { + length = count; + StringBuilder buf = new StringBuilder(length); + bytes = new byte[length]; + ints = new int[length]; + int x = start; + for (int i = 0; i < length; i++) { + ints[i] = x; + bytes[i] = (byte)x; + buf.appendCodePoint(x); + x = (x + inc) & 0xff; + } + string = buf.toString(); + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(100); + buf.append("byte[").append(length).append("]={ "); + for (int i = 0; i < length; i++) { + if (i > 0) { + buf.append(", "); + } + if (i >= 5) { + buf.append(" ..."); + break; + } else { + buf.append(ints[i]); + } + } + buf.append(" }"); + return buf.toString(); + } + + /** + * @return a copy of the bytes array (that the client is allowed to modify) + */ + byte[] getBytes() { + return bytes.clone(); + } + } + + /** + * Customised assert method comparing a buffer pointer to a byte array, usually the one from + * ByteMaterial. + * + * @param message to issue on failure + * @param expected expected byte array + * @param bp result to test + */ + void assertBytesEqual(String message, byte[] expected, BufferPointer bp) { + int size = bp.size; + if (size != expected.length) { + fail(message + " (size)"); + } else { + int len = bp.storage.length; + if (bp.offset < 0 || bp.offset + size > len) { + fail(message + " (offset)"); + } else { + // Should be safe to compare the bytes + int i = bp.offset, j; + for (j = 0; j < size; j++) { + if (bp.storage[i++] != expected[j]) { + break; + } + } + if (j < size) { + fail(message + " (byte at " + j + ")"); + } + } + } + } + + /** + * Customised assert method comparing a buffer pointer to a byte array, usually the one from + * ByteMaterial. + * + * @param expected expected byte array + * @param bp result to test + */ + void assertBytesEqual(byte[] expected, BufferPointer bp) { + assertBytesEqual("", expected, bp); + } + + /** + * Customised assert method comparing a byte arrays: values in the actual value starting at + * actual[actualStart] must match all those in expected[], and there must be enough of them. + * + * @param message to issue on failure + * @param expected expected byte array + * @param actual result to test + * @param actualStart where to start the comparison in actual + */ + void assertBytesEqual(String message, byte[] expected, byte[] actual, int actualStart) { + assertBytesEqual(message, expected, 0, actual, actualStart, expected.length); + } + + /** + * Customised assert method comparing a byte arrays: values starting at actual[actualStart] must + * those starting at actual[actualStart], for a distance of n bytes. + * + * @param message to issue on failure + * @param expected expected byte array + * @param expectedStart where to start the comparison in expected + * @param actual result to test + * @param actualStart where to start the comparison in actual + * @param n number of bytes to test + */ + void assertBytesEqual(String message, byte[] expected, int expectedStart, byte[] actual, + int actualStart, int n) { + if (actualStart < 0 || expectedStart < 0) { + fail(message + " (start<0)"); + } else if (actualStart + n > actual.length || expectedStart + n > expected.length) { + fail(message + " (too short)"); + } else { + // Should be safe to compare the values + int i = actualStart, j, jLimit = expectedStart + n; + for (j = expectedStart; j < jLimit; j++) { + if (actual[i++] != expected[j]) { + break; + } + } + if (j < jLimit) { + System.out.println(" expected:" + + Arrays.toString(Arrays.copyOfRange(expected, expectedStart, expectedStart + + n))); + System.out.println(" actual:" + + Arrays.toString(Arrays.copyOfRange(actual, actualStart, actualStart + n))); + System.out.println(" _actual_:" + Arrays.toString(actual)); + fail(message + " (byte at " + j + ")"); + } + } + } + + /** + * Customised assert method comparing a int arrays: values in the actual value starting at + * actual[offset] must match all those in expected[], and there must be enough of them. + * + * @param message to issue on failure + * @param expected expected array + * @param actual result to test + * @param offset where to start the comparison in actual + */ + void assertIntsEqual(String message, int[] expected, int[] actual, int offset) { + int n = expected.length; + if (offset < 0) { + fail(message + " (offset<0)"); + } else if (offset + n > actual.length) { + fail(message + " (too short)"); + } else { + // Should be safe to compare the values + int i = offset, j; + for (j = 0; j < n; j++) { + if (actual[i++] != expected[j]) { + break; + } + } + if (j < n) { + System.out.println(" expected:" + Arrays.toString(expected)); + System.out.println(" actual:" + Arrays.toString(actual)); + fail(message + " (int at " + j + ")"); + } + } + } + + /** + * Customised assert method comparing a int arrays: int in the actual value must match all those + * in expected[], and there must be the same number of them. + * + * @param message to issue on failure + * @param expected expected array + * @param actual result to test + */ + void assertIntsEqual(String message, int[] expected, int[] actual) { + int n = expected.length; + assertEquals(message, n, actual.length); + // Should be safe to compare the values + int j; + for (j = 0; j < n; j++) { + if (actual[j] != expected[j]) { + break; + } + } + if (j < n) { + System.out.println(" expected:" + Arrays.toString(expected)); + System.out.println(" actual:" + Arrays.toString(actual)); + fail(message + " (int at " + j + ")"); + } + } + + /** + * Element for queueing tests, wraps an exporter object with (a copy of) the material from which + * it was created, and several PyBuffer views. + */ + static class BufferTestPair { + + static final int[] STRIDES_1D = {1}; + + BufferProtocol exporter; + ByteMaterial material; + PyBuffer simple, strided; + int[] shape, strides; + + /** + * A test to do and the material for constructing it (and its results). + * + * @param exporter + * @param material + * @param shape of the array, when testing in N-dimensions + * @param stride of the array, when testing in N-dimensions + */ + public BufferTestPair(BufferProtocol exporter, ByteMaterial material, int[] shape, + int[] strides) { + this.exporter = exporter; + this.material = new ByteMaterial(material.ints); + this.shape = shape; + this.strides = strides; + try { + simple = exporter.getBuffer(PyBUF.SIMPLE); + strided = exporter.getBuffer(PyBUF.STRIDES); + } catch (Exception e) { + // Leave them null if we can't get a PyBuffer: test being set up will fail. + // Silent here, but explicit test of getBuffer will reproduce and log this failure. + } + } + + /** + * A test to do and the material for constructing it (and its results) in one dimension. + * + * @param exporter + * @param material + */ + public BufferTestPair(BufferProtocol exporter, ByteMaterial material) { + this(exporter, material, new int[1], STRIDES_1D); + shape[0] = material.length; + } + + @Override + public String toString() { + return exporter.getClass().getSimpleName() + "( " + material.toString() + " )"; + } + + } +} -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Wed Jul 18 10:44:09 2012 From: jython-checkins at python.org (jeff.allen) Date: Wed, 18 Jul 2012 10:44:09 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_buffer_API?= Message-ID: <3WcX2x2rrnzPB3@mail.python.org> http://hg.python.org/jython/rev/e8553ae3a804 changeset: 6798:e8553ae3a804 parent: 6796:d3fd05f7230e parent: 6797:e0aa95bac30e user: Jeff Allen date: Wed Jul 18 09:34:39 2012 +0100 summary: Merge buffer API files: src/org/python/core/BaseBytes.java | 105 +- src/org/python/core/BufferPointer.java | 49 + src/org/python/core/MemoryViewProtocol.java | 15 +- src/org/python/core/Py.java | 5 + src/org/python/core/PyBUF.java | 238 ++ src/org/python/core/MemoryView.java | 252 ++- src/org/python/core/PyByteArray.java | 100 +- src/org/python/core/PyMemoryView.java | 137 +- src/org/python/core/PyString.java | 47 +- src/org/python/core/buffer/BaseBuffer.java | 367 +++ src/org/python/core/buffer/SimpleBuffer.java | 66 + src/org/python/core/buffer/SimpleReadonlyBuffer.java | 128 + src/org/python/core/buffer/SimpleStringBuffer.java | 149 + tests/java/org/python/core/BaseBytesTest.java | 70 +- tests/java/org/python/core/PyBufferTest.java | 1094 ++++++++++ 15 files changed, 2597 insertions(+), 225 deletions(-) diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -9,6 +9,8 @@ import java.util.List; import java.util.ListIterator; +import org.python.core.buffer.SimpleReadonlyBuffer; + /** * Base class for Jython bytearray (and bytes in due course) that provides most of the Java API, * including Java List behaviour. Attempts to modify the contents through this API will throw a @@ -31,7 +33,7 @@ * * since the default implementations will otherwise throw an exception. */ -public abstract class BaseBytes extends PySequence implements MemoryViewProtocol, List { +public abstract class BaseBytes extends PySequence implements List { /** * Simple constructor of empty zero-length array of defined type. @@ -141,75 +143,6 @@ /* * ============================================================================================ - * Support for memoryview - * ============================================================================================ - * - * This is present in order to facilitate development of PyMemoryView which a full - * implementation of bytearray would depend on, while at the same time a full implementation of - * memoryview depends on bytearray. - */ - /** - * Get hold of a memoryview on the current byte array. - * - * @see MemoryViewProtocol#getMemoryView() - */ - @Override - public MemoryView getMemoryView() { - if (mv == null) { - mv = new MemoryViewImpl(); - } - return mv; - } - - private MemoryView mv; - - /** - * All instances of BaseBytes have one dimension with stride one. - */ - private static final PyTuple STRIDES = new PyTuple(Py.One); - - /** - * Very simple MemoryView for one-dimensional byte array. This lacks any actual access to the - * underlying storage as the interface is not presently defined. - */ - private class MemoryViewImpl implements MemoryView { - - private final PyTuple SHAPE = new PyTuple(new PyInteger(storage.length)); - - @Override - public String get_format() { - return "B"; - } - - @Override - public int get_itemsize() { - return 1; - } - - @Override - public PyTuple get_shape() { - return SHAPE; - } - - @Override - public int get_ndim() { - return 1; - } - - @Override - public PyTuple get_strides() { - return STRIDES; - } - - @Override - public boolean get_readonly() { - return true; - } - - } - - /* - * ============================================================================================ * Support for construction and initialisation * ============================================================================================ * @@ -257,11 +190,11 @@ */ init((BaseBytes)arg); - } else if (arg instanceof MemoryViewProtocol) { + } else if (arg instanceof BufferProtocol) { /* * bytearray copy of object supporting Jython implementation of PEP 3118 */ - init(((MemoryViewProtocol)arg).getMemoryView()); + init((BufferProtocol)arg); } else { /* @@ -387,29 +320,21 @@ /** * Helper for __new__ and __init__ and the Java API constructor from - * objects supporting the Jython implementation of PEP 3118 (memoryview) in subclasses. + * objects supporting the Jython implementation of PEP 3118 (Buffer API) in subclasses. * - * @param value a memoryview object consistent with the slice assignment - * @throws PyException(NotImplementedError) until memoryview is properly supported - * @throws PyException(TypeError) if the memoryview is not byte-oriented + * @param value an object bearing the Buffer API and consistent with the slice assignment */ - protected void init(MemoryView value) throws PyException { - // XXX Support memoryview once means of access to bytes is defined - Py.NotImplementedError("memoryview not yet supported in bytearray"); - String format = value.get_format(); - boolean isBytes = format == null || "B".equals(format); - if (value.get_ndim() != 1 || !isBytes) { - Py.TypeError("memoryview value must be byte-oriented"); - } else { - // Dimensions are given as a PyTuple (although only one) - int len = value.get_shape().pyget(0).asInt(); - // XXX Access to memoryview bytes to go here - } + protected void init(BufferProtocol value) throws PyException { + // Get the buffer view + PyBuffer view = value.getBuffer(PyBUF.SIMPLE); + // Create storage for the bytes and have the view drop them in + newStorage(view.getLen()); + view.copyTo(storage, offset); } /** - * Helper for the Java API constructor from a {@link #View}. View is (perhaps) a stop-gap while - * there is no Jython implementation of PEP 3118 (memoryview). + * Helper for the Java API constructor from a {@link #View}. View is (perhaps) a stop-gap until + * the Jython implementation of PEP 3118 (buffer API) is embedded. * * @param value a byte-oriented view */ diff --git a/src/org/python/core/BufferPointer.java b/src/org/python/core/BufferPointer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/BufferPointer.java @@ -0,0 +1,49 @@ +package org.python.core; + +/** + * A class that references a contiguous slice of a byte[] array for use in the buffer + * API. This class simply bundles together a refernce to an array, a starting offset within that + * array, and specification of the number of bytes that may validly be accessed at that offset. It + * is used by the Jython buffer API roughly where the CPython buffer API uses a C (char *) pointer, + * or such a pointer and a length. + */ +public class BufferPointer { + + /** + * Reference to the array holding the bytes. Usually this is the actual storage exported by a + * Python object. In some contexts the consumer will be entitled to make changes to the contents + * of this array, and in others, not. See {@link PyBuffer#isReadonly()}. + */ + public final byte[] storage; + /** Starting position within the array for the data being pointed to. */ + public final int offset; + /** Number of bytes within the array comprising the data being pointed to. */ + public final int size; + + /** + * Refer to a contiguous slice of the given array. + * + * @param storage array at reference + * @param offset index of the first byte + * @param size number of bytes being referred to + */ + public BufferPointer(byte[] storage, int offset, int size) { + if ((offset | size | (storage.length-(offset + size))) < 0) { + throw Py.BufferError("Indexing error in buffer API"); + } + this.storage = storage; + this.offset = offset; + this.size = size; + } + + /** + * Refer to the whole of a byte array. + * + * @param storage array at reference + */ + public BufferPointer(byte[] storage) { + this.storage = storage; + this.offset = 0; + this.size = storage.length; + } +} \ No newline at end of file diff --git a/src/org/python/core/MemoryViewProtocol.java b/src/org/python/core/BufferProtocol.java rename from src/org/python/core/MemoryViewProtocol.java rename to src/org/python/core/BufferProtocol.java --- a/src/org/python/core/MemoryViewProtocol.java +++ b/src/org/python/core/BufferProtocol.java @@ -1,6 +1,17 @@ package org.python.core; -public interface MemoryViewProtocol { +/** + * Interface marking an object as capable of exposing its internal state as a {@link PyBuffer}. + */ +public interface BufferProtocol { - public MemoryView getMemoryView(); + /** + * Method by which the consumer requests the buffer from the exporter. The consumer + * provides information on its intended method of navigation and the optional + * features the buffer object must provide. + * + * @param flags specification of options and the navigational capabilities of the consumer + * @return exported buffer + */ + PyBuffer getBuffer(int flags); } diff --git a/src/org/python/core/Py.java b/src/org/python/core/Py.java --- a/src/org/python/core/Py.java +++ b/src/org/python/core/Py.java @@ -363,7 +363,12 @@ public static PyException MemoryError(String message) { return new PyException(Py.MemoryError, message); } + public static PyObject BufferError; + public static PyException BufferError(String message) { + return new PyException(Py.BufferError, message); + } + public static PyObject ArithmeticError; public static PyObject LookupError; public static PyObject StandardError; diff --git a/src/org/python/core/PyBUF.java b/src/org/python/core/PyBUF.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/PyBUF.java @@ -0,0 +1,238 @@ +package org.python.core; + +/** + * This interface provides a base for the key interface of the buffer API, {@link PyBuffer}, + * including symbolic constants used by the consumer of a PyBuffer to specify its + * requirements. The Jython buffer API emulates the CPython buffer API closely. + *

    + *
  • There are two reasons for separating parts of PyBuffer into this interface: The + * constants defined in CPython have the names PyBUF_SIMPLE, + * PyBUF_WRITABLE, etc., and the trick of defining ours here means we can write + * {@link PyBUF#SIMPLE}, {@link PyBUF#WRITABLE}, etc. so source code looks similar.
  • + *
  • It is not so easy in Java as it is in C to treat a byte array as storing + * anything other than byte, and we prepare for the possibility of buffers with a + * series of different primitive types by defining here, those methods that would be in common + * between (Byte)Buffer and an assumed future FloatBuffer or + * TypedBuffer<T>. (Compare java.nio.Buffer.)
  • + *
+ * Except for other interfaces, it is unlikely any classes would implement PyBUF + * directly. + */ +public interface PyBUF { + + /** + * Determine whether the consumer is entitled to write to the exported storage. + * + * @return true if writing is not allowed, false if it is. + */ + boolean isReadonly(); + + /** + * The number of dimensions to the buffer. This number is the length of the shape + * array. + * + * @return number of dimensions + */ + int getNdim(); + + /** + * An array reporting the size of the buffer, considered as a multidimensional array, in each + * dimension and (by its length) number of dimensions. The size is the size in "items". An item + * is the amount of buffer content addressed by one index or set of indices. In the simplest + * case an item is a single unit (byte), and there is one dimension. In complex cases, the array + * is multi-dimensional, and the item at each location is multi-unit (multi-byte). The consumer + * must not modify this array. + * + * @return the dimensions of the buffer as an array + */ + int[] getShape(); + + /** + * The number of units (bytes) stored in each indexable item. + * + * @return the number of units (bytes) comprising each item. + */ + int getItemsize(); + + /** + * The total number of units (bytes) stored, which will be the product of the elements of the + * shape, and the item size. + * + * @return the total number of units stored. + */ + int getLen(); + + /** + * A buffer is (usually) coupled to the internal state of an exporting Python object, and that + * object may have to restrict its behaviour while the buffer exists. The consumer must + * therefore say when it has finished. + */ + void release(); + + /** + * The "strides" array gives the distance in the storage array between adjacent items (in each + * dimension). If the rawest parts of the buffer API, the consumer of the buffer is able to + * navigate the exported storage. The "strides" array is part of the support for interpreting + * the buffer as an n-dimensional array of items. In the one-dimensional case, the "strides" + * array is In more dimensions, it provides the coefficients of the "addressing polynomial". + * (More on this in the CPython documentation.) The consumer must not modify this array. + * + * @return the distance in the storage array between adjacent items (in each dimension) + */ + int[] getStrides(); + + /** + * The "suboffsets" array is a further part of the support for interpreting the buffer as an + * n-dimensional array of items, where the array potentially uses indirect addressing (like a + * real Java array of arrays, in fact). This is only applicable when there are more than 1 + * dimension and works in conjunction with the strides array. (More on this in the + * CPython documentation.) When used, suboffsets[k] is an integer index, bit a byte + * offset as in CPython. The consumer must not modify this array. + * + * @return + */ + int[] getSuboffsets(); + + /** + * Enquire whether the array is represented contiguously in the backing storage, according to C + * or Fortran ordering. A one-dimensional contiguous array is both. + * + * @param order 'C', 'F' or 'A', as the storage order is C, Fortran or either. + * @return true iff the array is stored contiguously in the order specified + */ + boolean isContiguous(char order); + + /* Constants taken from CPython object.h in v3.3.0a */ + + /** + * The maximum allowed number of dimensions (NumPy restriction?). + */ + static final int MAX_NDIM = 64; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it expects to write to the buffer contents. getBuffer will raise an exception if + * the exporter's buffer cannot meet this requirement. + */ + static final int WRITABLE = 0x0001; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it assumes a simple one-dimensional organisation of the exported storage with + * item size of one. getBuffer will raise an exception if the consumer sets this flag and the + * exporter's buffer cannot be navigated that simply. + */ + static final int SIMPLE = 0; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it requires {@link PyBuffer#getFormat()} to return the type of the unit (rather + * than return null). + */ + // I don't understand why we need this, or why format MUST be null of this is not set. + static final int FORMAT = 0x0004; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it it is prepared to navigate the buffer as multi-dimensional. + * getBuffer will raise an exception if consumer does not specify the flag but the + * exporter's buffer cannot be navigated without taking into account its multiple dimensions. + */ + static final int ND = 0x0008 | SIMPLE; // Differs from CPython by or'ing in SIMPLE + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it it expects to use the "strides" array. getBuffer will raise an + * exception if consumer does not specify the flag but the exporter's buffer cannot be navigated + * without using the "strides" array. + */ + static final int STRIDES = 0x0010 | ND; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it will assume C-order organisation of the units. getBuffer will raise an + * exception if the exporter's buffer is not C-ordered. C_CONTIGUOUS implies + * STRIDES. + */ + static final int C_CONTIGUOUS = 0x0020 | STRIDES; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it will assume Fortran-order organisation of the units. getBuffer will raise an + * exception if the exporter's buffer is not Fortran-ordered. F_CONTIGUOUS implies + * STRIDES. + */ + static final int F_CONTIGUOUS = 0x0040 | STRIDES; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it + * + * getBuffer will raise an exception if the exporter's buffer is not contiguous. + * ANY_CONTIGUOUS implies STRIDES. + */ + static final int ANY_CONTIGUOUS = 0x0080 | STRIDES; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it understands the "suboffsets" array. getBuffer will raise an + * exception if consumer does not specify the flag but the exporter's buffer cannot be navigated + * without understanding the "suboffsets" array. INDIRECT implies + * STRIDES. + */ + static final int INDIRECT = 0x0100 | STRIDES; + /** + * Equivalent to (ND | WRITABLE) + */ + static final int CONTIG = ND | WRITABLE; + /** + * Equivalent to ND + */ + static final int CONTIG_RO = ND; + /** + * Equivalent to (STRIDES | WRITABLE) + */ + static final int STRIDED = STRIDES | WRITABLE; + /** + * Equivalent to STRIDES + */ + static final int STRIDED_RO = STRIDES; + /** + * Equivalent to (STRIDES | WRITABLE | FORMAT) + */ + static final int RECORDS = STRIDES | WRITABLE | FORMAT; + /** + * Equivalent to (STRIDES | FORMAT) + */ + static final int RECORDS_RO = STRIDES | FORMAT; + /** + * Equivalent to (INDIRECT | WRITABLE | FORMAT) + */ + static final int FULL = INDIRECT | WRITABLE | FORMAT; + /** + * Equivalent to (INDIRECT | FORMAT) + */ + static final int FULL_RO = INDIRECT | FORMAT; + + /* Constants for readability, not standard for CPython */ + + /** + * Field mask, use as in if ((capabilityFlags&ORGANISATION) == STRIDES) .... + */ + static final int ORGANISATION = SIMPLE | ND | STRIDES | INDIRECT; + /** + * Field mask, use as in if ((capabilityFlags&ORGANIZATION) == STRIDES) .... + * + * @see #ORGANISATION + */ + static final int ORGANIZATION = ORGANISATION; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it will assume C-order organisation of the units, irrespective of whether + * the strides array is to be provided. getBuffer will raise an + * exception if the exporter's buffer is not C-ordered. C_CONTIGUOUS = IS_C_CONTIGUOUS | STRIDES. + */ + static final int IS_C_CONTIGUOUS = C_CONTIGUOUS & ~STRIDES; + /** + * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to + * specify that it will assume Fortran-order organisation of the units, irrespective of whether + * the strides array is to be provided. getBuffer will raise an + * exception if the exporter's buffer is not Fortran-ordered. F_CONTIGUOUS = IS_F_CONTIGUOUS | STRIDES. + */ + static final int IS_F_CONTIGUOUS = F_CONTIGUOUS & ~STRIDES; + /** + * Field mask, use as in if (capabilityFlags&CONTIGUITY== ... ) .... + */ + static final int CONTIGUITY = (C_CONTIGUOUS | F_CONTIGUOUS | ANY_CONTIGUOUS) & ~STRIDES; +} \ No newline at end of file diff --git a/src/org/python/core/MemoryView.java b/src/org/python/core/PyBuffer.java rename from src/org/python/core/MemoryView.java rename to src/org/python/core/PyBuffer.java --- a/src/org/python/core/MemoryView.java +++ b/src/org/python/core/PyBuffer.java @@ -1,12 +1,248 @@ package org.python.core; -public interface MemoryView { - // readonly attributes XXX just the boring stuff so far +/** + * The Jython buffer API for access to a byte array within an exporting object. This interface is + * the counterpart of the CPython Py_buffer struct. Several concrete types implement + * this interface in order to provide tailored support for different storage organisations. + */ +public interface PyBuffer extends PyBUF { - public String get_format(); - public int get_itemsize(); - public PyTuple get_shape(); - public int get_ndim(); - public PyTuple get_strides(); - public boolean get_readonly(); + /* + * The different behaviours required as the actual structure of the buffer changes (from one + * exporter to another, that is) should be dealt with using polymorphism. The implementation of + * those types may then calculate indices etc. without checking e.g for whether the strides + * array must be used, or the array is C or F contiguous, since they know the answer to these + * questions already, and can just get on with the request in their own way. + * + * The issue of consumer requests is different: the strides array will be present if the + * consumer asked for it, yet the methods of the buffer implementation do not have to use it + * (and won't). + */ + + // Informational methods inherited from PyBUF + // + // boolean isReadonly(); + // int getNdim(); + // int[] getShape(); + // int getLen(); + + /** + * Return the byte indexed from a one-dimensional buffer with item size one. This is part of the + * fully-encapsulated API: the exporter takes care of navigating the structure of the buffer. + * Results are undefined where the number of dimensions is not one or if + * itemsize>1. + * + * @param index to retrieve from + * @return the item at index, which is a byte + */ + byte byteAt(int index) throws IndexOutOfBoundsException; + + /** + * Return the unsigned byte value indexed from a one-dimensional buffer with item size one. This + * is part of the fully-encapsulated API: the exporter takes care of navigating the structure of + * the buffer. Results are undefined where the number of dimensions is not one or if + * itemsize>1. + * + * @param index to retrieve from + * @return the item at index, treated as an unsigned byte, =0xff & byteAt(index) + */ + int intAt(int index) throws IndexOutOfBoundsException; + + /** + * Store the given byte at the indexed location in of a one-dimensional buffer with item size + * one. This is part of the fully-encapsulated API: the exporter takes care of navigating the + * structure of the buffer. Results are undefined where the number of dimensions is not one or + * if itemsize>1. + * + * @param value to store + * @param index to location + */ + void storeAt(byte value, int index) throws IndexOutOfBoundsException; + + // Access to n-dimensional array + // + /** + * Return the byte indexed from an N-dimensional buffer with item size one. This is part of the + * fully-encapsulated API: the exporter takes care of navigating the structure of the buffer. + * The indices must be correct in length and value for the array shape. Results are undefined + * where itemsize>1. + * + * @param indices specifying location to retrieve from + * @return the item at location, which is a byte + */ + byte byteAt(int... indices) throws IndexOutOfBoundsException; + + /** + * Return the unsigned byte value indexed from an N-dimensional buffer with item size one. This + * is part of the fully-encapsulated API: the exporter takes care of navigating the structure of + * the buffer. The indices must be correct in length and value for the array shape. Results are + * undefined where itemsize>1. + * + * @param index to retrieve from + * @return the item at location, treated as an unsigned byte, =0xff & byteAt(index) + */ + int intAt(int... indices) throws IndexOutOfBoundsException; + + /** + * Store the given byte at the indexed location in of an N-dimensional buffer with item size + * one. This is part of the fully-encapsulated API: the exporter takes care of navigating the + * structure of the buffer. The indices must be correct in length and value for the array shape. + * Results are undefined where itemsize>1. + * + * @param value to store + * @param indices specifying location to store at + */ + void storeAt(byte value, int... indices) throws IndexOutOfBoundsException; + + // Bulk access in one dimension + // + /** + * Copy the contents of the buffer to the destination byte array. The number of bytes will be + * that returned by {@link #getLen()}, and the order is the natural ordering according to the + * contiguity type. + * + * @param dest destination byte array + * @param destPos index in the destination array of the byte [0] + * @throws IndexOutOfBoundsException if the destination cannot hold it + */ + void copyTo(byte[] dest, int destPos) throws IndexOutOfBoundsException; + + /** + * Copy a simple slice of the buffer to the destination byte array, defined by a starting index + * and length in the source buffer. This may validly be done only for a one-dimensional buffer, + * as the meaning of the starting index is otherwise not defined. + * + * @param srcIndex starting index in the source buffer + * @param dest destination byte array + * @param destPos index in the destination array of the byte [0,...] + * @param length number of bytes to copy + * @throws IndexOutOfBoundsException if access out of bounds in source or destination + */ + void copyTo(int srcIndex, byte[] dest, int destPos, int length) // mimic arraycopy args + throws IndexOutOfBoundsException; + + /** + * Copy bytes from a slice of a (Java) byte array into the buffer. This may validly be done only + * for a one-dimensional buffer, as the meaning of the starting index is otherwise not defined. + * + * @param src source byte array + * @param srcPos location in source of first byte to copy + * @param destIndex starting index in the destination (i.e. this) + * @param length number of bytes to copy in + * @throws IndexOutOfBoundsException if access out of bounds in source or destination + * @throws PyException (BufferError) if read-only buffer + */ + void copyFrom(byte[] src, int srcPos, int destIndex, int length) // mimic arraycopy args + throws IndexOutOfBoundsException, PyException; + + // Bulk access in n-dimensions may be added here if desired semantics can be settled + // + + // Buffer management inherited from PyBUF + // + // void release(); + + // Direct access to actual storage + // + /** + * Return a structure describing the slice of a byte array that holds the data being exported to + * the consumer. For a one-dimensional contiguous buffer, assuming the following client code + * where obj has type BufferProtocol: + * + *
+     *
+     * PyBuffer a = obj.getBuffer();
+     * int itemsize = a.getItemsize();
+     * BufferPointer b = a.getBuf();
+     * 
+ * + * the item with index k is in the array b.storage at index + * [b.offset + k*itemsize] to [b.offset + (k+1)*itemsize - 1] + * inclusive. And if itemsize==1, the item is simply the byte + * b.storage[b.offset + k] + *

+ * If the buffer is multidimensional or non-contiguous, b.storage[b.offset] is + * still the (first byte of) the item at index [0] or [0,...,0]. However, it is necessary to + * navigate b using the shape, strides and sub-offsets provided by the API. + * + * @return structure defining the byte[] slice that is the shared data + */ + BufferPointer getBuf(); + + /** + * Return a structure describing the slice of a byte array that holds a single item from the + * data being exported to the consumer. For a one-dimensional contiguous buffer, assuming the + * following client code where obj has type BufferProtocol: + * + *

+     * int k = ... ;
+     * PyBuffer a = obj.getBuffer();
+     * int itemsize = a.getItemsize();
+     * BufferPointer b = a.getPointer(k);
+     * 
+ * + * the item with index k is in the array b.storage at index + * [b.offset] to [b.offset + itemsize - 1] inclusive. And if + * itemsize==1, the item is simply the byte b.storage[b.offset] + *

+ * Essentially this is a method for computing the offset of a particular index. Although + * b.size==itemsize, the client is free to navigate the underlying buffer + * b.storage without respecting these boundaries. + * + * @param index in the buffer to position the pointer + * @return structure defining the byte[] slice that is the shared data + */ + BufferPointer getPointer(int index); + + /** + * Return a structure describing the slice of a byte array that holds a single item from the + * data being exported to the consumer, in the case that array may be multi-dimensional. For an + * 3-dimensional contiguous buffer, assuming the following client code where obj + * has type BufferProtocol: + * + *

+     * int i, j, k = ... ;
+     * PyBuffer a = obj.getBuffer();
+     * int itemsize = a.getItemsize();
+     * BufferPointer b = a.getPointer(i,j,k);
+     * 
+ * + * the item with index [i,j,k] is in the array b.storage at index + * [b.offset] to [b.offset + itemsize - 1] inclusive. And if + * itemsize==1, the item is simply the byte b.storage[b.offset] + *

+ * Essentially this is a method for computing the offset of a particular index. Although + * b.size==itemsize, the client is free to navigate the underlying buffer + * b.storage without respecting these boundaries. + *

+ * If the buffer is also non-contiguous, b.storage[b.offset] is still the (first + * byte of) the item at index [0,...,0]. However, it is necessary to navigate b + * using the shape, strides and sub-offsets provided by the API. + * + * @param indices multidimensional index at which to position the pointer + * @return structure defining the byte[] slice that is the shared data + */ + BufferPointer getPointer(int... indices); + + // Inherited from PyBUF and belonging here + // + // int[] getStrides(); + // int[] getSuboffsets(); + // boolean isContiguous(char order); + + // Interpretation of bytes as items + /** + * A format string in the language of Python structs describing how the bytes of each item + * should be interpreted (or null if {@link PyBUF#FORMAT} was not part of the consumer's flags). + *

+ * This is provided for compatibility with CPython. Jython only implements "B" so far, and it is + * debatable whether anything fancier than "<n>B" can be supported in Java. + * + * @return the format string + */ + String getFormat(); + + // Inherited from PyBUF and belonging here + // + // int getItemsize(); } diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java --- a/src/org/python/core/PyByteArray.java +++ b/src/org/python/core/PyByteArray.java @@ -2,6 +2,7 @@ import java.util.Arrays; +import org.python.core.buffer.SimpleBuffer; import org.python.expose.ExposedClassMethod; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; @@ -23,7 +24,7 @@ * */ @ExposedType(name = "bytearray", base = PyObject.class, doc = BuiltinDocs.bytearray_doc) -public class PyByteArray extends BaseBytes { +public class PyByteArray extends BaseBytes implements BufferProtocol { public static final PyType TYPE = PyType.fromClass(PyByteArray.class); @@ -85,14 +86,14 @@ } /** - * Create a new array filled exactly by a copy of the contents of the source, which is a - * memoryview. + * Create a new array filled exactly by a copy of the contents of the source, which is an + * object supporting the Jython version of the PEP 3118 buffer API. * * @param value source of the bytes (and size) */ - public PyByteArray(MemoryViewProtocol value) { + public PyByteArray(BufferProtocol value) { super(TYPE); - init(value.getMemoryView()); + init(value); } /** @@ -196,6 +197,55 @@ init(arg); } + /* + * ============================================================================================ + * Support for the Buffer API + * ============================================================================================ + * + * The buffer API allows other classes to access the storage directly. + */ + + /** + * {@inheritDoc} + *

+ * The {@link PyBuffer} returned from this method is a one-dimensional array of single byte + * items, that allows modification of the object state but prohibits resizing the byte array. + * This prohibition is not only on the consumer of the view but extends to any other operations, + * such as any kind or insertion or deletion. + */ + @Override + public synchronized PyBuffer getBuffer(int flags) { + exportCount++; + return new SimpleBuffer(this, new BufferPointer(storage, offset, size), flags) { + + @Override + public void releaseAction() { + // synchronise on the same object as getBuffer() + synchronized (obj) { + exportCount--; + } + } + }; + } + + /** + * Test to see if the byte array may be resized and raise a BufferError if not. + * + * @throws PyException (BufferError) if there are buffer exports preventing a resize + */ + protected void resizeCheck() throws PyException { + // XXX Quite likely this is not called in all the places it should be + if (exportCount!=0) { + throw Py.BufferError("Existing exports of data: object cannot be re-sized"); + } + } + + /** + * Count of PyBuffer exports not yet released, used to prevent untimely resizing. + */ + private int exportCount; + + /* ============================================================================================ * API for org.python.core.PySequence * ============================================================================================ @@ -368,12 +418,12 @@ */ setslice(start, stop, step, (BaseBytes)value); - } else if (value instanceof MemoryViewProtocol) { + } else if (value instanceof BufferProtocol) { /* * Value supports Jython implementation of PEP 3118, and can be can be inserted without * making a copy. */ - setslice(start, stop, step, ((MemoryViewProtocol)value).getMemoryView()); + setslice(start, stop, step, (BufferProtocol)value); } else { /* @@ -449,12 +499,31 @@ * @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 value a memoryview object consistent with the slice assignment + * @param value an object supporting the buffer API consistent with the slice assignment * @throws PyException(SliceSizeError) if the value size is inconsistent with an extended slice */ - private void setslice(int start, int stop, int step, MemoryView value) throws PyException { - // XXX Support memoryview once means of access to bytes is defined - throw Py.NotImplementedError("memoryview not yet supported in bytearray"); + private void setslice(int start, int stop, int step, BufferProtocol value) throws PyException { + PyBuffer view = value.getBuffer(PyBUF.SIMPLE); + + + int len = view.getLen(); + + if (step == 1) { + // Delete this[start:stop] and open a space of the right size + storageReplace(start, stop - start, len); + view.copyTo(storage, start+offset); + + } else { + // This is an extended slice which means we are replacing elements + int n = sliceLength(start, stop, step); + if (n != len) { + throw SliceSizeError("bytes", len, n); + } + + for (int io = start + offset, j = 0; j < n; io += step, j++) { + storage[io] = view.byteAt(j); // Assign this[i] = value[j] + } + } } /** @@ -2089,6 +2158,9 @@ return; } + // This will not be possible if this object has buffer exports + resizeCheck(); + // Compute some handy points of reference final int L = storage.length; final int f = offset; @@ -2351,6 +2423,9 @@ return; // Everything stays where it is. } + // This will not be possible if this object has buffer exports + resizeCheck(); + // Compute some handy points of reference final int L = storage.length; final int f = offset; @@ -2430,6 +2505,9 @@ return; // Everything stays where it is. } + // This will not be possible if this object has buffer exports + resizeCheck(); + // Compute some handy points of reference final int L = storage.length; final int f = offset; diff --git a/src/org/python/core/PyMemoryView.java b/src/org/python/core/PyMemoryView.java --- a/src/org/python/core/PyMemoryView.java +++ b/src/org/python/core/PyMemoryView.java @@ -1,61 +1,140 @@ package org.python.core; import org.python.expose.ExposedGet; -import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; +/** + * Class implementing the Python memoryview type, at present highly incomplete. It + * provides a wrapper around the Jython buffer API, but slice operations and most others are + * missing. + */ @ExposedType(name = "memoryview", base = PyObject.class, isBaseType = false) public class PyMemoryView extends PyObject { + // XXX This should probably extend PySequence to get the slice behaviour + public static final PyType TYPE = PyType.fromClass(PyMemoryView.class); - MemoryView backing; + /** + * The buffer exported by the object. We do not a present implement the buffer sharing strategy + * used by CPython memoryview. + */ + private PyBuffer backing; + /** Cache the result of getting shape here. */ + private PyTuple shape; + /** Cache the result of getting strides here. */ + private PyTuple strides; - public PyMemoryView(MemoryViewProtocol obj) { - backing = obj.getMemoryView(); + /** + * Construct a PyMemoryView from an object that bears the necessary BufferProtocol interface. + * The buffer so obtained will be writable if the underlying object permits it. + * + * @param obj object that will export the buffer + */ + public PyMemoryView(BufferProtocol obj) { + /* + * Ask for the full set of facilities (strides, indirect, etc.) from the object in case they + * are necessary for navigation, but only ask for read access. If the object is writable, + * the PyBuffer will be writable. + */ + backing = obj.getBuffer(PyBUF.FULL_RO); } @ExposedNew - static PyObject memoryview_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, - String[] keywords) { + static PyObject memoryview_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { PyObject obj = args[0]; - if (obj instanceof MemoryViewProtocol) { - return new PyMemoryView((MemoryViewProtocol)obj); + if (obj instanceof BufferProtocol) { + return new PyMemoryView((BufferProtocol)obj); + } else { + throw Py.TypeError("cannot make memory view because object does not have " + + "the buffer interface"); } - else throw Py.TypeError("cannot make memory view because object does not have the buffer interface"); } - @ExposedGet(name = "format") - public String get_format() { - return backing.get_format(); + @ExposedGet(doc = format_doc) + public String format() { + return backing.getFormat(); } - @ExposedGet(name = "itemsize") - public int get_itemsize() { - return backing.get_itemsize(); + @ExposedGet(doc = itemsize_doc) + public int itemsize() { + return backing.getItemsize(); } - @ExposedGet(name = "shape") - public PyTuple get_shape() { - return backing.get_shape(); + @ExposedGet(doc = shape_doc) + public PyTuple shape() { + if (shape == null) { + shape = tupleOf(backing.getShape()); + } + return shape; } - @ExposedGet(name = "ndim") - public int get_ndim() { - return backing.get_ndim(); + @ExposedGet(doc = ndim_doc) + public int ndim() { + return backing.getShape().length; } - @ExposedGet(name = "strides") - public PyTuple get_strides() { - return backing.get_strides(); + @ExposedGet(doc = strides_doc) + public PyTuple strides() { + if (strides == null) { + strides = tupleOf(backing.getStrides()); + } + return strides; } - @ExposedGet(name = "readonly") - public boolean get_readonly() { - return backing.get_readonly(); + @ExposedGet(doc = readonly_doc) + public boolean readonly() { + return backing.isReadonly(); } + /** + * Make an integer array into a PyTuple of PyInteger values. + * + * @param x the array + * @return the PyTuple + */ + private PyTuple tupleOf(int[] x) { + PyInteger[] pyx = new PyInteger[x.length]; + for (int k = 0; k < x.length; k++) { + pyx[k] = new PyInteger(x[k]); + } + return new PyTuple(pyx, false); + } + + /* + * These strings are adapted from the on-line documentation as the attributes do not come with + * any docstrings. + */ + private final static String memoryview_tobytes_doc = "tobytes()\n\n" + + "Return the data in the buffer as a bytestring (an object of class str).\n\n" + + ">>> m = memoryview(\"abc\")\n" + ">>> m.tobytes()\n" + "'abc'"; + + private final static String memoryview_tolist_doc = "tolist()\n\n" + + "Return the data in the buffer as a list of integers.\n\n" + + ">>> memoryview(\"abc\").tolist()\n" + "[97, 98, 99]"; + + private final static String format_doc = "format\n" + + "A string containing the format (in struct module style) for each element in\n" + + "the view. This defaults to 'B', a simple bytestring.\n"; + + private final static String itemsize_doc = "itemsize\n" + + "The size in bytes of each element of the memoryview.\n"; + + private final static String shape_doc = "shape\n" + + "A tuple of integers the length of ndim giving the shape of the memory as an\n" + + "N-dimensional array.\n"; + + private final static String ndim_doc = "ndim\n" + + "An integer indicating how many dimensions of a multi-dimensional array the\n" + + "memory represents.\n"; + + private final static String strides_doc = "strides\n" + + "A tuple of integers the length of ndim giving the size in bytes to access\n" + + "each element for each dimension of the array.\n"; + + private final static String readonly_doc = "readonly\n" + + "A bool indicating whether the memory is read only.\n"; + } - - diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java +++ b/src/org/python/core/PyString.java @@ -1,6 +1,12 @@ /// Copyright (c) Corporation for National Research Initiatives package org.python.core; +import java.math.BigInteger; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; + +import org.python.core.StringFormatter.DecimalFormatTemplate; +import org.python.core.buffer.SimpleStringBuffer; import org.python.core.stringlib.FieldNameIterator; import org.python.core.stringlib.InternalFormatSpec; import org.python.core.stringlib.InternalFormatSpecParser; @@ -12,15 +18,11 @@ import org.python.expose.ExposedType; import org.python.expose.MethodType; -import java.math.BigInteger; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; - /** * A builtin python string. */ @ExposedType(name = "str", doc = BuiltinDocs.str_doc) -public class PyString extends PyBaseString implements MemoryViewProtocol +public class PyString extends PyBaseString implements BufferProtocol { public static final PyType TYPE = PyType.fromClass(PyString.class); protected String string; // cannot make final because of Python intern support @@ -93,28 +95,19 @@ return codePoints; } - public MemoryView getMemoryView() { - return new MemoryView() { - // beginning of support - public String get_format() { - return "B"; - } - public int get_itemsize() { - return 2; - } - public PyTuple get_shape() { - return new PyTuple(Py.newInteger(getString().length())); - } - public int get_ndim() { - return 1; - } - public PyTuple get_strides() { - return new PyTuple(Py.newInteger(1)); - } - public boolean get_readonly() { - return true; - } - }; + /** + * Create a read-only buffer view of the contents of the string, treating it as a sequence of + * unsigned bytes. The caller specifies its requirements and navigational capabilities in the + * flags argument (see the constants in class {@link PyBUF} for an explanation). + * + * @param flags consumer requirements + * @return the requested buffer + */ + public PyBuffer getBuffer(int flags) { + /* + * Return a buffer, but specialised to defer construction of the buf object. + */ + return new SimpleStringBuffer(this, getString(), flags); } public String substring(int start, int end) { diff --git a/src/org/python/core/buffer/BaseBuffer.java b/src/org/python/core/buffer/BaseBuffer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/buffer/BaseBuffer.java @@ -0,0 +1,367 @@ +package org.python.core.buffer; + +import org.python.core.BufferPointer; +import org.python.core.BufferProtocol; +import org.python.core.Py; +import org.python.core.PyBUF; +import org.python.core.PyBuffer; +import org.python.core.PyException; + +/** + * Base implementation of the Buffer API for implementations to extend. The default implementation + * provides some mechanisms for checking the consumer's capabilities against those stated as + * necessary by the exporter. Default implementations of methods are provided for the standard array + * organisations. The implementors of simple buffers will find it more efficient to override methods + * to which performance might be sensitive with a calculation specific to their actual type. + *

+ * The default implementation raises a read-only exception for those methods that store data in the + * buffer, and {@link #isReadonly()} returns true. Writable types must override this + * implementation. Default implementations of other methods are generally oriented towards + * contiguous N-dimensional arrays. + *

+ * At the time of writing, only the SIMPLE organisation (one-dimensional, of item size one) is used + * in the Jython core. + */ +public abstract class BaseBuffer implements PyBuffer { + + /** + * The object from which this buffer export must be released (see {@link PyBuffer#release()}). + * This is normally the original exporter of this buffer and the owner of the underlying + * storage. Exceptions to this occur when some other object is managing release (this is the + * case when a memoryview has provided the buffer), and when disposal can safely be + * left to the Java garbage collector (local temporaries and perhaps exports from immutable + * objects). + */ + protected BufferProtocol obj; + /** + * The dimensions of the array represented by the buffer. The length of the shape + * array is the number of dimensions. The shape array should always be created and + * filled (difference from CPython). + */ + protected int[] shape; + /** + * Step sizes in the underlying buffer essential to correct translation of an index (or indices) + * into an index into the storage. This reference will be null if not needed for + * the storage organisation, and not requested by the consumer in flags. If it is + * either necessary for the buffer navigation, or requested by the consumer in flags, the + * strides array must be correctly filled to at least the length of the + * shape array. + */ + protected int[] strides; + /** + * Reference to a structure that wraps the underlying storage that the exporter is sharing with + * the consumer. + */ + protected BufferPointer buf; + /** + * Bit pattern using the constants defined in {@link PyBUF} that records the actual capabilities + * this buffer offers. See {@link #assignCapabilityFlags(int, int, int, int)}. + */ + protected int capabilityFlags; + + /** + * The result of the operation is to set the {@link #capabilityFlags} according to the + * capabilities this instance should support. This method is normally called in the constructor + * of each particular sub-class of BaseBuffer, passing in a flags + * argument that originated in the consumer's call to {@link BufferProtocol#getBuffer(int)}. + *

+ * The consumer supplies as a set of flags, using constants from {@link PyBUF}, the + * capabilities that it expects from the buffer. These include a statement of which navigational + * arrays it will use ( shape, strides, and suboffsets), + * whether it wants the format string set so it describes the item type or left + * null, and whether it expects the buffer to be writable. The consumer flags are taken by this + * method both as a statement of needs to be met by the buffer, and as a statement of + * capabilities in the consumer to navigate different buffers. + *

+ * In its call to this method, the exporter specifies the capabilities it requires the consumer + * to have (and indicate by asking for them in flags) in order to navigate the + * buffer successfully. For example, if the buffer is a strided array, the consumer must specify + * that it expects the strides array. Otherwise the method concludes the consumer + * is not capable of the navigation required. Capabilities specified in the + * requiredFlags must appear in the consumer's flags request. If any + * don't, a Python BufferError will be raised. If there is no error these flags + * will be set in capabilityFlags as required of the buffer. + *

+ * The exporter specifies some capabilities it allows the consumer to request, such as + * the format string. Depending on the type of exporter, the navigational arrays ( + * shape, strides, and suboffsets) may also be allowed + * rather than required. Capabilities specified in the allowedFlags, if they also + * appear in the consumer's flags, will be set in capabilityFlags. + *

+ * The exporter specifies some capabilities that will be supplied whether requested or not. For + * example (and it might be the only one) this is used only to express that an unstrided, + * one-dimensional array is C_CONTIGUOUS, F_CONTIGUOUS, and + * ANY_CONTIGUOUS, all at once. Capabilities specified in the + * impliedFlags, will be set in capabilityFlags whether in the + * consumer's flags or not. + *

+ * Capabilities specified in the consumer's flags request, if they do not appear in + * the exporter's requiredFlags allowedFlags or + * impliedFlags, will cause a Python BufferError. + *

+ * Note that this method cannot actually set the shape, strides and + * suboffsets properties: the implementation of the specific buffer type must do + * that based on the capabilityFlags. This forms a partial counterpart to CPython + * PyBuffer_FillInfo() but it is not specific to the simple type of buffer, and + * covers the flag processing of all buffer types. This is complex (in CPython) and the Jython + * approach attempts to be compatible yet comprehensible. + */ + protected void assignCapabilityFlags(int flags, int requiredFlags, int allowedFlags, + int impliedFlags) { + + // Ensure what may be requested includes what must be and what comes unasked + allowedFlags = allowedFlags | requiredFlags | impliedFlags; + + // Look for request flags (other than buffer organisation) outside what is allowed + int syndrome = flags & ~(allowedFlags | ORGANISATION); + + if (syndrome != 0) { + // Some flag was set that is neither required nor allowed + if ((syndrome & WRITABLE) != 0) { + throw notWritable(); + } else if ((syndrome & C_CONTIGUOUS) != 0) { + throw bufferIsNot("C-contiguous"); + } else if ((syndrome & F_CONTIGUOUS) != 0) { + throw bufferIsNot("Fortran-contiguous"); + } else if ((syndrome & ANY_CONTIGUOUS) != 0) { + throw bufferIsNot("contiguous"); + } else { + // Catch-all error (never in practice?) + throw bufferIsNot("capable of matching request"); + } + + } else if ((flags & requiredFlags) != requiredFlags) { + // This buffer needs more capability to navigate than the consumer has requested + if ((flags & ND) != ND) { + throw bufferRequires("shape"); + } else if ((flags & STRIDES) != STRIDES) { + throw bufferRequires("strides"); + } else if ((flags & INDIRECT) != INDIRECT) { + throw bufferRequires("suboffsets"); + } else { + // Catch-all error + throw bufferRequires("feature consumer lacks"); + } + + } else { + // These flags control returns from (default) getShape etc.. + capabilityFlags = (flags & allowedFlags) | impliedFlags; + // Note that shape and strides are still to be initialised + } + + /* + * Caller must responds to the requested/required capabilities with shape and strides arrays + * suited to the actual type of buffer. + */ + } + + /** + * Provide an instance of BaseBuffer or a sub-class meeting the consumer's expectations as + * expressed in the flags argument. Compare CPython: + * + *

+     * int PyBuffer_FillInfo(Py_buffer *view, PyObject *exporter,
+     *                       void *buf, Py_ssize_t len,
+     *                       int readonly, int flags)
+     * 
+ * + * @param exporter the exporting object + * @param buf descriptor for the exported buffer itself + */ + protected BaseBuffer(BufferProtocol exporter, BufferPointer buf) { + // Exporting object (is allowed to be null) + this.obj = exporter; + // Exported data (not normally allowed to be null) + this.buf = buf; + } + + @Override + public boolean isReadonly() { + // Default position is read only: mutable buffers must override + return true; + } + + @Override + public int getNdim() { + return shape.length; + } + + @Override + public int[] getShape() { + // Difference from CPython: never null, even when the consumer doesn't request it. + return shape; + } + + @Override + public int getLen() { + // Correct if contiguous. Override if strided or indirect with itemsize*product(shape). + return buf.size; + } + + // Let the sub-class implement: + // @Override public byte byteAt(int index) throws IndexOutOfBoundsException {} + + @Override + public int intAt(int index) throws IndexOutOfBoundsException { + return 0xff & byteAt(index); + } + + @Override + public void storeAt(byte value, int index) throws IndexOutOfBoundsException, PyException { + throw notWritable(); + } + + // Let the sub-class implement: + // @Override public byte byteAt(int... indices) throws IndexOutOfBoundsException {} + + @Override + public int intAt(int... indices) throws IndexOutOfBoundsException { + return 0xff & byteAt(indices); + } + + @Override + public void storeAt(byte value, int... indices) throws IndexOutOfBoundsException, PyException { + throw notWritable(); + } + + @Override + public void copyTo(byte[] dest, int destPos) throws IndexOutOfBoundsException { + // Correct for contiguous arrays (if destination expects same F or C contiguity) + copyTo(0, dest, destPos, getLen()); + } + + // Let the sub-class implement: + // @Override public void copyTo(int srcIndex, byte[] dest, int destPos, int length) + // throws IndexOutOfBoundsException {} + + @Override + public void copyFrom(byte[] src, int srcPos, int destIndex, int length) + throws IndexOutOfBoundsException, PyException { + throw notWritable(); + } + + /** + * {@inheritDoc} + *

+ * The implementation here calls {@link #releaseAction()}, which the implementer of a specific + * buffer type should override with the necessary actions to release the buffer from the + * exporter. It is not an error to call this method more than once (difference from CPython), or + * on a temporary buffer that needs no release action. If not released explicitly, it will be + * called during object finalisation (before garbage collection) of the buffer object. + */ + @Override + public final void release() { + if (obj != null) { + releaseAction(); + } + obj = null; + } + + @Override + public BufferPointer getBuf() { + return buf; + } + + // Let the sub-class implement: + // @Override public BufferPointer getPointer(int index) { return null; } + // @Override public BufferPointer getPointer(int... indices) { return null; } + + @Override + public int[] getStrides() { + return strides; + } + + @Override + public int[] getSuboffsets() { + return null; + } + + @Override + public boolean isContiguous(char order) { + return true; + } + + @Override + public String getFormat() { + // Avoid having to have an actual 'format' member + return ((capabilityFlags & FORMAT) == 0) ? null : "B"; + } + + @Override + public int getItemsize() { + // Avoid having to have an actual 'itemsize' member + return 1; + } + + /** + * Ensure buffer, if not released sooner, is released from the exporter during object + * finalisation (before garbage collection) of the buffer object. + */ + @Override + protected void finalize() throws Throwable { + release(); + super.finalize(); + } + + /** + * This method will be called when the consumer calls {@link #release()} (to be precise, only on + * the first call). The default implementation does nothing. Override this method to add release + * behaviour specific to exporter. A common convention is to do this within the definition of + * {@link BufferProtocol#getBuffer(int)} within the exporting class, where a nested class is + * finally defined. + */ + protected void releaseAction() {} + + /** + * Check the number of indices (but not their values), raising a Python BufferError if this does + * not match the number of dimensions. + * + * @param indices into the buffer (to test) + * @return number of dimensions + * @throws PyException (BufferError) if wrong number of indices + */ + final int checkDimension(int[] indices) throws PyException { + int ndim = shape.length; + if (indices.length != ndim) { + if (indices.length < ndim) { + throw Py.BufferError("too few indices supplied"); + } else { + throw Py.BufferError("too many indices supplied"); + } + } + return ndim; + } + + /** + * Convenience method to create (for the caller to throw) a + * BufferError("underlying buffer is not writable"). + * + * @return the error as a PyException + */ + protected PyException notWritable() { + return bufferIsNot("writable"); + } + + /** + * Convenience method to create (for the caller to throw) a + * BufferError("underlying buffer is not {property}"). + * + * @param property + * @return the error as a PyException + */ + protected PyException bufferIsNot(String property) { + return Py.BufferError("underlying buffer is not " + property); + } + + /** + * Convenience method to create (for the caller to throw) a + * BufferError("underlying buffer requires {feature}"). + * + * @param feature + * @return the error as a PyException + */ + protected PyException bufferRequires(String feature) { + return Py.BufferError("underlying buffer requires " + feature); + } + +} diff --git a/src/org/python/core/buffer/SimpleBuffer.java b/src/org/python/core/buffer/SimpleBuffer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/buffer/SimpleBuffer.java @@ -0,0 +1,66 @@ +package org.python.core.buffer; + +import org.python.core.BufferPointer; +import org.python.core.BufferProtocol; + +/** + * Buffer API over a writable one-dimensional array of one-byte items. + */ +public class SimpleBuffer extends SimpleReadonlyBuffer { + + /** + * SimpleBuffer allows consumer requests that are the same as + * SimpleReadonlyBuffer, with the addition of WRITABLE. + */ + protected static final int ALLOWED_FLAGS = WRITABLE | SimpleReadonlyBuffer.ALLOWED_FLAGS; + + /** + * Provide an instance of SimpleBuffer in a default, semi-constructed state. The + * sub-class constructor takes responsibility for completing construction with a call to + * {@link #assignCapabilityFlags(int, int, int, int)}. + * + * @param exporter the exporting object + * @param buf wrapping the array of bytes storing the implementation of the object + */ + protected SimpleBuffer(BufferProtocol exporter, BufferPointer buf) { + super(exporter, buf); + } + + /** + * Provide an instance of SimpleBuffer meeting the consumer's expectations as expressed in the + * flags argument. + * + * @param exporter the exporting object + * @param buf wrapping the array of bytes storing the implementation of the object + * @param flags consumer requirements + */ + public SimpleBuffer(BufferProtocol exporter, BufferPointer buf, int flags) { + super(exporter, buf); + assignCapabilityFlags(flags, REQUIRED_FLAGS, ALLOWED_FLAGS, IMPLIED_FLAGS); + fillInfo(); + } + + @Override + public boolean isReadonly() { + return false; + } + + @Override + public void storeAt(byte value, int index) { + buf.storage[buf.offset + index] = value; + } + + @Override + public void storeAt(byte value, int... indices) { + if (indices.length != 1) { + checkDimension(indices); + } + storeAt(value, indices[0]); + } + + @Override + public void copyFrom(byte[] src, int srcPos, int destIndex, int length) { + System.arraycopy(src, srcPos, buf.storage, buf.offset + destIndex, length); + } + +} diff --git a/src/org/python/core/buffer/SimpleReadonlyBuffer.java b/src/org/python/core/buffer/SimpleReadonlyBuffer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/buffer/SimpleReadonlyBuffer.java @@ -0,0 +1,128 @@ +package org.python.core.buffer; + +import org.python.core.BufferPointer; +import org.python.core.BufferProtocol; + +/** + * Buffer API over a one-dimensional array of one-byte items providing read-only API. A writable + * simple buffer will extend this implementation. + */ +public class SimpleReadonlyBuffer extends BaseBuffer { + + /** + * Using the PyBUF constants, express capabilities the consumer must request if it is to + * navigate the storage successfully. (None.) + */ + public static final int REQUIRED_FLAGS = 0; + /** + * Using the PyBUF constants, express capabilities the consumer may request so it can navigate + * the storage in its chosen way. The buffer instance has to implement these mechanisms if and + * only if they are requested. (FORMAT | ND | STRIDES | INDIRECT) + */ + public static final int ALLOWED_FLAGS = FORMAT | ND | STRIDES | INDIRECT; + /** + * Using the PyBUF constants, express capabilities the consumer doesn't need to request because + * they will be there anyway. (One-dimensional arrays (including those sliced with step size + * one) are C- and F-contiguous.) + */ + public static final int IMPLIED_FLAGS = CONTIGUITY; + /** + * The strides array for this type is always a single element array with a 1 in it. + */ + protected static final int[] SIMPLE_STRIDES = {1}; + + /** + * Partial counterpart to CPython PyBuffer_FillInfo() specific to the simple type + * of buffer and called from the constructor. The base constructor will already have been + * called, filling {@link #buf} and {@link #obj}. And the method + * {@link #assignCapabilityFlags(int, int, int, int)} has set {@link #capabilityFlags}. + */ + protected void fillInfo() { + /* + * We will already have called: assignCapabilityFlags(flags, requiredFlags, allowedFlags, + * impliedFlags); So capabilityFlags holds the requests for shape, strides, writable, etc.. + */ + // Difference from CPython: never null, even when the consumer doesn't request it + shape = new int[1]; + shape[0] = getLen(); + + // Following CPython: provide strides only when the consumer requests it + if ((capabilityFlags & STRIDES) == STRIDES) { + strides = SIMPLE_STRIDES; + } + + // Even when the consumer requests suboffsets, the exporter is allowed to supply null. + // In theory, the exporter could require that it be requested and still supply null. + } + + /** + * Provide an instance of SimpleReadonlyBuffer in a default, semi-constructed + * state. The sub-class constructor takes responsibility for completing construction including a + * call to {@link #assignCapabilityFlags(int, int, int, int)}. + * + * @param exporter the exporting object + * @param buf wrapping the array of bytes storing the implementation of the object + */ + protected SimpleReadonlyBuffer(BufferProtocol exporter, BufferPointer buf) { + super(exporter, buf); + } + + /** + * Provide an instance of SimpleReadonlyBuffer meeting the consumer's expectations as expressed + * in the flags argument. + * + * @param exporter the exporting object + * @param buf wrapping the array of bytes storing the implementation of the object + * @param flags consumer requirements + */ + public SimpleReadonlyBuffer(BufferProtocol exporter, BufferPointer buf, int flags) { + super(exporter, buf); + assignCapabilityFlags(flags, REQUIRED_FLAGS, ALLOWED_FLAGS, IMPLIED_FLAGS); + fillInfo(); + } + + @Override + public int getNdim() { + return 1; + } + + @Override + public byte byteAt(int index) throws IndexOutOfBoundsException { + // offset is not necessarily zero + return buf.storage[buf.offset + index]; + } + + @Override + public int intAt(int index) throws IndexOutOfBoundsException { + // Implement directly: a bit quicker than the default + return 0xff & buf.storage[buf.offset + index]; + } + + @Override + public byte byteAt(int... indices) throws IndexOutOfBoundsException { + if (indices.length != 1) { + checkDimension(indices); + } + return byteAt(indices[0]); + } + + @Override + public void copyTo(int srcIndex, byte[] dest, int destPos, int length) + throws IndexOutOfBoundsException { + System.arraycopy(buf.storage, buf.offset + srcIndex, dest, destPos, length); + } + + @Override + public BufferPointer getPointer(int index) { + return new BufferPointer(buf.storage, buf.offset + index, 1); + } + + @Override + public BufferPointer getPointer(int... indices) { + if (indices.length != 1) { + checkDimension(indices); + } + return getPointer(indices[0]); + } + +} diff --git a/src/org/python/core/buffer/SimpleStringBuffer.java b/src/org/python/core/buffer/SimpleStringBuffer.java new file mode 100644 --- /dev/null +++ b/src/org/python/core/buffer/SimpleStringBuffer.java @@ -0,0 +1,149 @@ +package org.python.core.buffer; + +import org.python.core.BufferPointer; +import org.python.core.BufferProtocol; +import org.python.core.util.StringUtil; + +/** + * Buffer API that appears to be a one-dimensional array of one-byte items providing read-only API, + * but which is actually backed by a Java String. Some of the buffer API absolutely needs access to + * the data as a byte array (those parts that involve a {@link BufferPointer} result), and therefore + * this class must create a byte array from the String for them. However, it defers creation of a + * byte array until that part of the API is actually used. This class overrides those methods in + * SimpleReadonlyBuffer that would access the buf attribute to work out their results + * from the String instead. + */ +public class SimpleStringBuffer extends SimpleReadonlyBuffer { + + /** + * The string backing this PyBuffer. A substitute for {@link #buf} until we can no longer avoid + * creating it. + */ + private String bufString; + + /** + * Partial counterpart to CPython PyBuffer_FillInfo() specific to the simple type + * of buffer and called from the constructor. The base constructor will already have been + * called, filling {@link #bufString} and {@link #obj}. And the method + * {@link #assignCapabilityFlags(int, int, int, int)} has set {@link #capabilityFlags}. + */ + protected void fillInfo(String bufString) { + /* + * We will already have called: assignCapabilityFlags(flags, requiredFlags, allowedFlags, + * impliedFlags); So capabilityFlags holds the requests for shape, strides, writable, etc.. + */ + // Save the backing string + this.bufString = bufString; + + // Difference from CPython: never null, even when the consumer doesn't request it + shape = new int[1]; + shape[0] = bufString.length(); + + // Following CPython: provide strides only when the consumer requests it + if ((capabilityFlags & STRIDES) == STRIDES) { + strides = SIMPLE_STRIDES; + } + + // Even when the consumer requests suboffsets, the exporter is allowed to supply null. + // In theory, the exporter could require that it be requested and still supply null. + } + + /** + * Provide an instance of SimpleReadonlyBuffer meeting the consumer's expectations as expressed + * in the flags argument. + * + * @param exporter the exporting object + * @param bufString storing the implementation of the object + * @param flags consumer requirements + */ + public SimpleStringBuffer(BufferProtocol exporter, String bufString, int flags) { + super(exporter, null); + assignCapabilityFlags(flags, REQUIRED_FLAGS, ALLOWED_FLAGS, IMPLIED_FLAGS); + fillInfo(bufString); + } + + /** + * {@inheritDoc} + *

+ * This method uses {@link String#length()} rather than create an actual byte buffer. + */ + @Override + public int getLen() { + // Avoid creating buf by using String.length + return bufString.length(); + } + + /** + * {@inheritDoc} + *

+ * This method uses {@link String#charAt(int)} rather than create an actual byte buffer. + */ + @Override + public byte byteAt(int index) throws IndexOutOfBoundsException { + // Avoid creating buf by using String.charAt + return (byte)bufString.charAt(index); + } + + /** + * {@inheritDoc} + *

+ * This method uses {@link String#charAt(int)} rather than create an actual byte buffer. + */ + @Override + public int intAt(int index) throws IndexOutOfBoundsException { + // Avoid creating buf by using String.charAt + return bufString.charAt(index); + } + + /** + * {@inheritDoc} + *

+ * This method uses {@link String#charAt(int)} rather than create an actual byte buffer. + */ + @Override + public void copyTo(int srcIndex, byte[] dest, int destPos, int length) + throws IndexOutOfBoundsException { + // Avoid creating buf by using String.charAt + int endIndex = srcIndex + length, p = destPos; + for (int i = srcIndex; i < endIndex; i++) { + dest[p++] = (byte)bufString.charAt(i); + } + } + + /** + * {@inheritDoc} + *

+ * This method creates an actual byte buffer from the String if none yet exists. + */ + @Override + public BufferPointer getBuf() { + if (buf == null) { + // We can't avoid creating buf any longer + buf = new BufferPointer(StringUtil.toBytes(bufString)); + } + return buf; + } + + /** + * {@inheritDoc} + *

+ * This method creates an actual byte buffer from the String if none yet exists. + */ + @Override + public BufferPointer getPointer(int index) { + getBuf(); // Ensure buffer created + return super.getPointer(index); + } + + /** + * {@inheritDoc} + *

+ * This method creates an actual byte buffer from the String if none yet exists. + */ + @Override + public BufferPointer getPointer(int... indices) { + getBuf(); // Ensure buffer created + return super.getPointer(indices); + } + +} diff --git a/tests/java/org/python/core/BaseBytesTest.java b/tests/java/org/python/core/BaseBytesTest.java --- a/tests/java/org/python/core/BaseBytesTest.java +++ b/tests/java/org/python/core/BaseBytesTest.java @@ -4,10 +4,11 @@ import java.util.List; import java.util.Random; +import junit.framework.TestCase; + +import org.python.core.buffer.SimpleBuffer; import org.python.util.PythonInterpreter; -import junit.framework.TestCase; - /** * Unit test of org.python.core.BaseBytes, a class that supplies much of the behaviour of the Jython * bytearray. In fact, it supplies almost all the immutable behaviour, and is abstract. In order to @@ -517,7 +518,7 @@ return new MyBytes(value); } - public BaseBytes getInstance(MemoryViewProtocol value) throws PyException { + public BaseBytes getInstance(BufferProtocol value) throws PyException { return new MyBytes(value); } @@ -599,9 +600,9 @@ * * @param value source of the bytes (and size) */ - public MyBytes(MemoryViewProtocol value) { + public MyBytes(BufferProtocol value) { super(TYPE); - init(value.getMemoryView()); + init((BufferProtocol)value.getBuffer(PyBUF.SIMPLE)); } /** @@ -769,13 +770,12 @@ /** * An object that for test purposes (of construction and slice assignment) contains an array of - * values that it is able to offer for reading through the MemoryView interface. + * values that it is able to offer for reading through the PyBuffer interface. */ - public static class MemoryViewable extends PyObject implements MemoryViewProtocol { + public static class BufferedObject extends PyObject implements BufferProtocol { - public static final PyType TYPE = PyType.fromClass(MemoryViewable.class); + public static final PyType TYPE = PyType.fromClass(BufferedObject.class); - private MemoryView mv; private byte[] store; /** @@ -783,7 +783,7 @@ * * @param value integers to store */ - MemoryViewable(int[] value) { + BufferedObject(int[] value) { super(TYPE); int n = value.length; store = new byte[n]; @@ -793,56 +793,10 @@ } @Override - public MemoryView getMemoryView() { - if (mv == null) { - mv = new MemoryViewImpl(); - } - return mv; + public PyBuffer getBuffer(int flags) { + return new SimpleBuffer(this, new BufferPointer(store), flags); } - /** - * All instances of MemoryViewable have one dimension with stride one. - */ - private static final PyTuple STRIDES = new PyTuple(Py.One); - - /** - * Very simple MemoryView for one-dimensional byte array. - */ - class MemoryViewImpl implements MemoryView { - - private final PyTuple shape = new PyTuple(new PyInteger(store.length)); - - @Override - public String get_format() { - return "B"; - } - - @Override - public int get_itemsize() { - return 1; - } - - @Override - public PyTuple get_shape() { - return shape; - } - - @Override - public int get_ndim() { - return 1; - } - - @Override - public PyTuple get_strides() { - return STRIDES; - } - - @Override - public boolean get_readonly() { - return true; - } - - } } /** diff --git a/tests/java/org/python/core/PyBufferTest.java b/tests/java/org/python/core/PyBufferTest.java new file mode 100644 --- /dev/null +++ b/tests/java/org/python/core/PyBufferTest.java @@ -0,0 +1,1094 @@ +package org.python.core; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import junit.framework.TestCase; + +import org.python.core.buffer.SimpleBuffer; +import org.python.core.buffer.SimpleReadonlyBuffer; +import org.python.core.buffer.SimpleStringBuffer; +import org.python.util.PythonInterpreter; + +/** + * Test the several implementations (and exporters) of the PyBuffer interface provided in the Jython + * core. + *

+ * The approach is to create test material once that has the necessary variety in byte array values, + * then for each test, when the JUnit framework creates an instance of the function-specific test, + * to use this material to create instances of each read-only type and each writable type. Writable + * instance types go onto the lists buffersToRead and buffersToWrite, while read-only instances go + * onto the lists buffersToRead and buffersToFailToWrite. + *

+ * In general, tests of methods that read data apply themselves to all the elements of the + * buffersToRead list, while tests of methods that write data apply themselves to all the elements + * of the buffersToWrite list and check that members of the buffersToFailToWrite list raise an + * exception. + *

+ * The Jython buffer API follows the structures of the CPython buffer API so that it supports in + * principle the use of multi-dimensional, strided add indirect array structures as buffers. + * However, actual buffers in the Jython core, and therefore these tests, limit themselves to one + * dimensional contiguous buffers with a simple organisation. Some tests apply directly to the + * N-dimensional cases, and some need a complete re-think. Sub-classing this test would probably be + * a good way to extend it to a wider range. + */ +public class PyBufferTest extends TestCase { + + /** + * Generated constructor + * + * @param name + */ + public PyBufferTest(String name) { + super(name); + } + + /** Sometimes we need the interpreter to be initialised **/ + PythonInterpreter interp; + + /* + * Values for initialising the exporters. + */ + private static final ByteMaterial byteMaterial = new ByteMaterial(0, 17, 16); + private static final ByteMaterial abcMaterial = new ByteMaterial("abcdef"); + private static final ByteMaterial stringMaterial = new ByteMaterial("Mon c?t? f?cheux"); + private static final ByteMaterial emptyMaterial = new ByteMaterial(new byte[0]); + private static final ByteMaterial longMaterial = new ByteMaterial(0, 5, 1000); + + protected void setUp() throws Exception { + super.setUp(); + + // Exception raising requires the Jython interpreter + interp = new PythonInterpreter(); + + // Tests using local examples + queueWrite(new SimpleExporter(abcMaterial.getBytes()), abcMaterial); + queueReadonly(new SimpleExporter(byteMaterial.getBytes(), true), byteMaterial); + queueReadonly(new StringExporter(stringMaterial.string), stringMaterial); + queueWrite(new SimpleExporter(emptyMaterial.getBytes()), emptyMaterial); + + // Tests with PyByteArray + queueWrite(new PyByteArray(abcMaterial.getBytes()), abcMaterial); + queueWrite(new PyByteArray(longMaterial.getBytes()), longMaterial); + queueWrite(new PyByteArray(), emptyMaterial); + + // Tests with PyString + queueReadonly(new PyString(abcMaterial.string), abcMaterial); + queueReadonly(new PyString(), emptyMaterial); + + // Ensure case is tested where PyByteArray has an internal offset + PyByteArray truncated = new PyByteArray(stringMaterial.getBytes()); + truncated.delRange(0, 4); + ByteMaterial truncatedMaterial = new ByteMaterial(stringMaterial.string.substring(4)); + assert truncated.__alloc__() > truncatedMaterial.length; + queueWrite(truncated, truncatedMaterial); + } + + private void queueWrite(BufferProtocol exporter, ByteMaterial material) { + BufferTestPair pair = new BufferTestPair(exporter, material); + buffersToRead.add(pair); + buffersToWrite.add(pair); + } + + private void queueReadonly(BufferProtocol exporter, ByteMaterial material) { + BufferTestPair pair = new BufferTestPair(exporter, material); + buffersToRead.add(pair); + buffersToFailToWrite.add(pair); + } + + /** Read operations should succeed on all these objects. */ + private List buffersToRead = new LinkedList(); + /** Write operations should succeed on all these objects. */ + private List buffersToWrite = new LinkedList(); + /** Write operations should fail on all these objects. */ + private List buffersToFailToWrite = new LinkedList(); + + /** We should be able to get a buffer for all these flag types. */ + private int[] validFlags = {PyBUF.SIMPLE, PyBUF.ND, PyBUF.STRIDES, PyBUF.INDIRECT}; + + /** To which we can add any of these (in one dimension, anyway) */ + private int[] validTassles = {PyBUF.FORMAT, + PyBUF.C_CONTIGUOUS, + PyBUF.F_CONTIGUOUS, + PyBUF.ANY_CONTIGUOUS}; + + /** + * Test method for {@link org.python.core.PyBuffer#getBuf()}. + */ + public void testGetBuffer() { + + for (BufferTestPair test : buffersToRead) { + System.out.println("getBuffer(): " + test); + for (int flags : validFlags) { + for (int tassle : validTassles) { + PyBuffer view = test.exporter.getBuffer(flags | tassle); + assertNotNull(view); + } + } + } + + for (BufferTestPair test : buffersToWrite) { + System.out.println("getBuffer(WRITABLE): " + test); + for (int flags : validFlags) { + for (int tassle : validTassles) { + PyBuffer view = test.exporter.getBuffer(flags | tassle | PyBUF.WRITABLE); + assertNotNull(view); + } + } + } + + for (BufferTestPair test : buffersToFailToWrite) { + System.out.println("getBuffer(WRITABLE): " + test); + for (int flags : validFlags) { + try { + test.exporter.getBuffer(flags | PyBUF.WRITABLE); + fail("Write access not prevented: " + test); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + } + + /** + * Test method for {@link org.python.core.PyBUF#isReadonly()}. + */ + public void testIsReadonly() { + + for (BufferTestPair test : buffersToWrite) { + System.out.println("isReadonly: " + test); + assertFalse(test.simple.isReadonly()); + } + + for (BufferTestPair test : buffersToFailToWrite) { + System.out.println("isReadonly: " + test); + assertTrue(test.simple.isReadonly()); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getNdim()}. + */ + public void testGetNdim() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getNdim: " + test); + assertEquals("simple ndim", test.shape.length, test.simple.getNdim()); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getShape()}. + */ + public void testGetShape() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getShape: " + test); + int[] shape = test.simple.getShape(); + assertNotNull(shape); + assertIntsEqual("simple shape", test.shape, shape); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getLen()}. + */ + public void testGetLen() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getLen: " + test); + assertEquals(" simple len", test.material.bytes.length, test.simple.getLen()); + assertEquals("strided len", test.material.bytes.length, test.strided.getLen()); + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#byteAt(int)}. + */ + public void testByteAt() { + for (BufferTestPair test : buffersToRead) { + System.out.println("byteAt: " + test); + int n = test.material.length; + byte[] exp = test.material.bytes; + for (int i = 0; i < n; i++) { + assertEquals(exp[i], test.simple.byteAt(i)); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#byteAt(int[])}. + */ + public void testByteAtNdim() { + int[] index = new int[1]; + for (BufferTestPair test : buffersToRead) { + System.out.println("byteAt(array): " + test); + if (test.strided.getShape().length != 1) { + fail("Test not implemented dimensions != 1"); + } + byte[] exp = test.material.bytes; + int n = test.material.length; + // Run through 1D index for simple + for (int i = 0; i < n; i++) { + index[0] = i; + assertEquals(exp[i], test.simple.byteAt(index)); + } + // Check 2D index throws + try { + test.simple.byteAt(0, 0); + fail("Use of 2D index did not raise exception"); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#intAt(int)}. + */ + public void testIntAt() { + for (BufferTestPair test : buffersToRead) { + System.out.println("intAt: " + test); + int n = test.material.length; + int[] exp = test.material.ints; + for (int i = 0; i < n; i++) { + assertEquals(exp[i], test.simple.intAt(i)); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#intAt(int[])}. + */ + public void testIntAtNdim() { + int[] index = new int[1]; + for (BufferTestPair test : buffersToRead) { + System.out.println("intAt(array): " + test); + if (test.strided.getShape().length != 1) { + fail("Test not implemented dimensions != 1"); + } + int[] exp = test.material.ints; + int n = test.material.length; + // Run through 1D index for simple + for (int i = 0; i < n; i++) { + index[0] = i; + assertEquals(exp[i], test.simple.intAt(index)); + } + // Check 2D index throws + try { + test.simple.intAt(0, 0); + fail("Use of 2D index did not raise exception"); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#storeAt(byte, int)}. + */ + public void testStoreAt() { + for (BufferTestPair test : buffersToWrite) { + System.out.println("storeAt: " + test); + int n = test.material.length; + int[] exp = test.material.ints; + // Write modified test material into each location using storeAt() + for (int i = 0; i < n; i++) { + byte v = (byte)(exp[i] ^ 3); // twiddle some bits + test.simple.storeAt(v, i); + } + // Compare each location with modified test data using intAt() + for (int i = 0; i < n; i++) { + assertEquals(exp[i] ^ 3, test.simple.intAt(i)); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#storeAt(byte, int[])}. + */ + public void testStoreAtNdim() { + for (BufferTestPair test : buffersToWrite) { + System.out.println("storeAt: " + test); + int n = test.material.length; + int[] exp = test.material.ints; + // Write modified test material into each location using storeAt() + for (int i = 0; i < n; i++) { + byte v = (byte)(exp[i] ^ 3); // twiddle some bits + test.simple.storeAt(v, i); + } + // Compare each location with modified test data using intAt() + for (int i = 0; i < n; i++) { + assertEquals(exp[i] ^ 3, test.simple.intAt(i)); + } + // Check 2D index throws + try { + test.simple.storeAt((byte)1, 0, 0); + fail("Use of 2D index did not raise exception"); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#copyTo(byte[], int)}. + */ + public void testCopyTo() { + final int OFFSET = 5; + for (BufferTestPair test : buffersToRead) { + System.out.println("copyTo: " + test); + int n = test.material.length; + // Try with zero offset + byte[] actual = new byte[n]; + test.simple.copyTo(actual, 0); + assertBytesEqual("copyTo() incorrect", test.material.bytes, actual, 0); + // Try to middle of array + actual = new byte[n + 2 * OFFSET]; + test.simple.copyTo(actual, OFFSET); + assertBytesEqual("copyTo(offset) incorrect", test.material.bytes, actual, OFFSET); + assertEquals("data before destination", 0, actual[OFFSET - 1]); + assertEquals("data after destination", 0, actual[OFFSET + n]); + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#copyTo(int, byte[], int, int)}. + */ + public void testSliceCopyTo() { + final int OFFSET = 5; + final byte BLANK = 7; + + for (BufferTestPair test : buffersToRead) { + System.out.println("copyTo(from slice): " + test); + PyBuffer view = test.simple; + + int n = test.material.length; + byte[] actual = new byte[n + 2 * OFFSET]; + + // Try destination positions in actual[] of 0 and OFFSET + for (int destPos = 0; destPos <= OFFSET; destPos += OFFSET) { + // Try source positions in 0 and OFFSET + for (int srcIndex = 0; srcIndex <= OFFSET; srcIndex += OFFSET) { + + // A variety of lengths from zero to (n-srcIndex)-ish + for (int length = 0; srcIndex + length <= n; length = 2 * length + 1) { + /* + * System.out.printf(" copy src[%d:%d] (%d) to dst[%d:%d] (%d)\n", + * srcIndex, srcIndex + length, n, destPos, destPos + length, + * actual.length); + */ + Arrays.fill(actual, BLANK); + + // Test the method + view.copyTo(srcIndex, actual, destPos, length); + + // Check changed part of destination + assertBytesEqual("copyTo(slice) incorrect", test.material.bytes, srcIndex, + actual, destPos, length); + if (destPos > 0) { + assertEquals("data before destination", BLANK, actual[destPos - 1]); + } + assertEquals("data after destination", BLANK, actual[destPos + length]); + } + + // And from exactly n-srcIndex down to zero-ish + for (int trim = 0; srcIndex + trim <= n; trim = 2 * trim + 1) { + int length = n - srcIndex - trim; + /* + * System.out.printf(" copy src[%d:%d] (%d) to dst[%d:%d] (%d)\n", + * srcIndex, srcIndex + length, n, destPos, destPos + length, + * actual.length); + */ + Arrays.fill(actual, BLANK); + + // Test the method + view.copyTo(srcIndex, actual, destPos, length); + + // Check changed part of destination + assertBytesEqual("copyTo(slice) incorrect", test.material.bytes, srcIndex, + actual, destPos, length); + if (destPos > 0) { + assertEquals("data before destination", BLANK, actual[destPos - 1]); + } + assertEquals("data after destination", BLANK, actual[destPos + length]); + } + } + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#copyFrom(byte[], int, int, int)}. + */ + public void testCopyFrom() { + final int OFFSET = 5; + final byte BLANK = 7; + + for (BufferTestPair test : buffersToWrite) { + System.out.println("copyFrom(): " + test); + PyBuffer view = test.simple; + + int n = test.material.length; + byte[] actual = new byte[n]; + byte[] expected = new byte[n]; + + // Make some source material for copies (need to test at OFFSET too). + byte[] src = new byte[n + OFFSET]; + for (int i = 0; i < src.length; i++) { + src[i] = (byte)i; + } + + // Try destination positions in test object of 0 and OFFSET + for (int destIndex = 0; destIndex <= OFFSET; destIndex += OFFSET) { + + // Try source positions in 0 and OFFSET + for (int srcPos = 0; srcPos <= OFFSET; srcPos += OFFSET) { + + // A variety of lengths from zero to (n-destIndex)-ish + for (int length = 0; destIndex + length <= n; length = 2 * length + 1) { + + System.out.printf(" copy src[%d:%d] (%d) to dst[%d:%d] (%d)\n", srcPos, + srcPos + length, n, destIndex, destIndex + length, + actual.length); + + // Initialise the object (have to do each time) and expected value + for (int i = 0; i < n; i++) { + expected[i] = BLANK; + view.storeAt(BLANK, i); + } + + // Test the method and extract the result to actual[] + view.copyFrom(src, srcPos, destIndex, length); + view.copyTo(actual, 0); + + // Complete what is should be in expected[] + for (int i = 0; i < length; i++) { + expected[destIndex + i] = src[srcPos + i]; + } + assertBytesEqual("copyFrom() incorrect", expected, actual, 0); + } + + // And from exactly n-destIndex down to zero-ish + for (int trim = 0; destIndex + trim <= n; trim = 2 * trim + 1) { + int length = n - destIndex - trim; + System.out.printf(" copy src[%d:%d] (%d) to dst[%d:%d] (%d)\n", srcPos, + srcPos + length, n, destIndex, destIndex + length, + actual.length); + + // Initialise the object (have to do each time) and expected value + for (int i = 0; i < n; i++) { + expected[i] = BLANK; + view.storeAt(BLANK, i); + } + + // Test the method and extract the result to actual[] + view.copyFrom(src, srcPos, destIndex, length); + view.copyTo(actual, 0); + + // Complete what is should be in expected[] + for (int i = 0; i < length; i++) { + expected[destIndex + i] = src[srcPos + i]; + } + assertBytesEqual("copyFrom() incorrect", expected, actual, 0); + } + } + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#getBuf()}. + */ + public void testGetBuf() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getBuf: " + test); + PyBuffer view = test.exporter.getBuffer(PyBUF.SIMPLE); + ByteMaterial m = test.material; + + BufferPointer bp = view.getBuf(); + assertBytesEqual("getBuf: ", m.bytes, bp); + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#getPointer(int)}. + */ + public void testGetPointer() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getPointer: " + test); + PyBuffer view = test.strided; + int n = test.material.length, itemsize = view.getItemsize(); + byte[] exp = new byte[itemsize], bytes = test.material.bytes; + + for (int i = 0; i < n; i++) { + // Expected result is one item (allow for itemsize) + int p = i * itemsize; + for (int j = 0; j < itemsize; j++) { + exp[j] = bytes[p + j]; + } + + // Get pointer and check contents for correct data + BufferPointer bp = view.getPointer(i); + assertBytesEqual("getPointer value", exp, bp.storage, bp.offset); + assertEquals("getPointer size wrong", itemsize, bp.size); + } + } + } + + /** + * Test method for {@link org.python.core.PyBuffer#getPointer(int[])}. + */ + public void testGetPointerNdim() { + int[] index = new int[1]; + for (BufferTestPair test : buffersToRead) { + System.out.println("getPointer(array): " + test); + PyBuffer view = test.strided; + int n = test.material.length, itemsize = view.getItemsize(); + byte[] exp = new byte[itemsize], bytes = test.material.bytes; + + for (int i = 0; i < n; i++) { + // Expected result is one item (allow for itemsize) + int p = i * itemsize; + for (int j = 0; j < itemsize; j++) { + exp[j] = bytes[p + j]; + } + + // Get pointer and check contents for correct data + index[0] = i; + BufferPointer bp = view.getPointer(index); + assertBytesEqual("getPointer value", exp, bp.storage, bp.offset); + assertEquals("getPointer size wrong", itemsize, bp.size); + } + // Check 2D index throws + try { + view.getPointer(0, 0); + fail("Use of 2D index did not raise exception"); + } catch (PyException pye) { + // Expect BufferError + assertEquals(Py.BufferError, pye.type); + } + } + } + + /** + * Test method for {@link org.python.core.PyBUF#release()}. + */ + public void testRelease() { + for (BufferTestPair test : buffersToRead) { + System.out.println("release: " + test); + BufferProtocol obj = test.exporter; + // The object should already be exporting test.simple and test.strided + PyBuffer a = test.simple; // 1 + PyBuffer b = test.strided; // 2 + PyBuffer c = obj.getBuffer(PyBUF.SIMPLE | PyBUF.FORMAT); // 3 + checkExporting(obj); + // Multiple releases of the same buffer are just one release + b.release(); // 2 + b.release(); + b.release(); + b.release(); + checkExporting(obj); + // Now see that releasing in some other order works correctly + a.release(); // 1 + checkExporting(obj); + PyBuffer d = obj.getBuffer(PyBUF.STRIDES | PyBUF.FORMAT); // 2 + c.release(); // 1 + checkExporting(obj); + d.release(); // 0 + checkNotExporting(obj); + d.release(); // 0 + checkNotExporting(obj); + } + } + + /** + * Error if exporter is not actually exporting (and is of a type that locks on export). + * + * @param exporter + */ + private void checkExporting(BufferProtocol exporter) { + if (exporter instanceof SimpleExporter) { + assertTrue("exports not being counted", ((SimpleExporter)exporter).exportCount >= 1); + } else if (exporter instanceof PyByteArray) { + // Size-changing access should fail + try { + ((PyByteArray)exporter).bytearray_extend(Py.One); + fail("bytearray_extend with exports should fail"); + } catch (Exception e) { + // Success + } + } + // Other types cannot be checked + } + + /** + * Error if exporter is exporting (and is of a type that locks on export). + * + * @param exporter + */ + private void checkNotExporting(BufferProtocol exporter) { + if (exporter instanceof SimpleExporter) { + assertFalse("exports falsely counted", ((SimpleExporter)exporter).exportCount >= 1); + } else if (exporter instanceof PyByteArray) { + // Size-changing access should fail + try { + ((PyByteArray)exporter).bytearray_extend(Py.One); + } catch (Exception e) { + fail("bytearray unexpectedly locked"); + } + } + // Other types cannot be checked + } + + /** + * Test method for {@link org.python.core.PyBUF#getStrides()}. + */ + public void testGetStrides() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getStrides: " + test); + // When not requested ... + assertNull(test.simple.getStrides()); + // When requested, ought to be as expected + int[] strides = test.strided.getStrides(); + assertNotNull(strides); + assertIntsEqual("strided.strides", test.strides, strides); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getSuboffsets()}. + */ + public void testGetSuboffsets() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getSuboffsets: " + test); + // Null for all test material + assertNull(test.simple.getSuboffsets()); + assertNull(test.strided.getSuboffsets()); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#isContiguous(char)}. + */ + public void testIsContiguous() { + for (BufferTestPair test : buffersToRead) { + System.out.println("isContiguous: " + test); + // True for all test material and orders (since 1-dimensional) + for (char order : validOrders) { + assertTrue(test.simple.isContiguous(order)); + assertTrue(test.strided.isContiguous(order)); + } + } + } + + private static final char[] validOrders = {'C', 'F', 'A'}; + + /** + * Test method for {@link org.python.core.PyBuffer#getFormat()}. + */ + public void testGetFormat() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getFormat: " + test); + // Null for all test material + assertNull(test.simple.getFormat()); + assertNull(test.strided.getFormat()); + // However, we can ask for it explicitly ... + PyBuffer simpleWithFormat = test.exporter.getBuffer(PyBUF.SIMPLE | PyBUF.FORMAT); + PyBuffer stridedWithFormat = test.exporter.getBuffer(PyBUF.STRIDES | PyBUF.FORMAT); + // "B" for all test material where requested in flags + assertEquals("B", simpleWithFormat.getFormat()); + assertEquals("B", stridedWithFormat.getFormat()); + } + } + + /** + * Test method for {@link org.python.core.PyBUF#getItemsize()}. + */ + public void testGetItemsize() { + for (BufferTestPair test : buffersToRead) { + System.out.println("getItemsize: " + test); + // Unity for all test material + assertEquals(1, test.simple.getItemsize()); + assertEquals(1, test.strided.getItemsize()); + } + } + + /** + * A class to act as an exporter that uses the SimpleBuffer (or SimpleReadonlyBuffer). This + * permits testing abstracted from the Jython interpreter. + */ + static class SimpleExporter implements BufferProtocol { + + byte[] storage; + int exportCount; + boolean readonly; + + /** + * Construct a simple exporter from the bytes supplied. + * + * @param storage + */ + public SimpleExporter(byte[] storage) { + this.storage = storage; + } + + /** + * Construct a simple exporter from the bytes supplied, optionally read-only. + * + * @param storage + * @param readonly + */ + public SimpleExporter(byte[] storage, boolean readonly) { + this.storage = storage; + this.readonly = readonly; + } + + @Override + public PyBuffer getBuffer(int flags) { + BufferPointer mb = new BufferPointer(storage); + exportCount++; + if (readonly) { + return new SimpleReadonlyBuffer(this, mb, flags) { + + protected void releaseAction() { + --exportCount; + } + }; + } else { + return new SimpleBuffer(this, mb, flags) { + + protected void releaseAction() { + --exportCount; + } + }; + } + } + } + + /** + * A class to act as an exporter that uses the SimpleStringBuffer. This permits testing + * abstracted from the Jython interpreter. + */ + static class StringExporter implements BufferProtocol { + + String storage; + int exportCount; + + /** + * Construct a simple exporter from the String supplied. + * + * @param s + */ + public StringExporter(String s) { + storage = s; + } + + @Override + public PyBuffer getBuffer(int flags) { + return new SimpleStringBuffer(this, storage, flags); + } + } + + /** + * Class to hold test material representing the same sequence of values 0..255 in several + * different ways. + */ + protected static class ByteMaterial { + + final String string; + final byte[] bytes; + final int[] ints; + final int length; + + /** Construct from String. */ + public ByteMaterial(String s) { + string = s; + length = s.length(); + bytes = new byte[length]; + ints = new int[length]; + for (int i = 0; i < length; i++) { + int x = s.charAt(i); + ints[i] = x; + bytes[i] = (byte)x; + } + } + + /** Construct from byte array. */ + public ByteMaterial(byte[] b) { + length = b.length; + StringBuilder buf = new StringBuilder(length); + bytes = new byte[length]; + ints = new int[length]; + for (int i = 0; i < length; i++) { + int x = 0xff & b[i]; + ints[i] = x; + bytes[i] = (byte)x; + buf.appendCodePoint(x); + } + string = buf.toString(); + } + + /** Construct from int array. */ + public ByteMaterial(int[] a) { + length = a.length; + StringBuilder buf = new StringBuilder(length); + bytes = new byte[length]; + ints = new int[length]; + for (int i = 0; i < length; i++) { + int x = a[i]; + ints[i] = x; + bytes[i] = (byte)x; + buf.appendCodePoint(x); + } + string = buf.toString(); + } + + /** Construct from pattern on values (used modulo 256). */ + public ByteMaterial(int start, int inc, int count) { + length = count; + StringBuilder buf = new StringBuilder(length); + bytes = new byte[length]; + ints = new int[length]; + int x = start; + for (int i = 0; i < length; i++) { + ints[i] = x; + bytes[i] = (byte)x; + buf.appendCodePoint(x); + x = (x + inc) & 0xff; + } + string = buf.toString(); + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(100); + buf.append("byte[").append(length).append("]={ "); + for (int i = 0; i < length; i++) { + if (i > 0) { + buf.append(", "); + } + if (i >= 5) { + buf.append(" ..."); + break; + } else { + buf.append(ints[i]); + } + } + buf.append(" }"); + return buf.toString(); + } + + /** + * @return a copy of the bytes array (that the client is allowed to modify) + */ + byte[] getBytes() { + return bytes.clone(); + } + } + + /** + * Customised assert method comparing a buffer pointer to a byte array, usually the one from + * ByteMaterial. + * + * @param message to issue on failure + * @param expected expected byte array + * @param bp result to test + */ + void assertBytesEqual(String message, byte[] expected, BufferPointer bp) { + int size = bp.size; + if (size != expected.length) { + fail(message + " (size)"); + } else { + int len = bp.storage.length; + if (bp.offset < 0 || bp.offset + size > len) { + fail(message + " (offset)"); + } else { + // Should be safe to compare the bytes + int i = bp.offset, j; + for (j = 0; j < size; j++) { + if (bp.storage[i++] != expected[j]) { + break; + } + } + if (j < size) { + fail(message + " (byte at " + j + ")"); + } + } + } + } + + /** + * Customised assert method comparing a buffer pointer to a byte array, usually the one from + * ByteMaterial. + * + * @param expected expected byte array + * @param bp result to test + */ + void assertBytesEqual(byte[] expected, BufferPointer bp) { + assertBytesEqual("", expected, bp); + } + + /** + * Customised assert method comparing a byte arrays: values in the actual value starting at + * actual[actualStart] must match all those in expected[], and there must be enough of them. + * + * @param message to issue on failure + * @param expected expected byte array + * @param actual result to test + * @param actualStart where to start the comparison in actual + */ + void assertBytesEqual(String message, byte[] expected, byte[] actual, int actualStart) { + assertBytesEqual(message, expected, 0, actual, actualStart, expected.length); + } + + /** + * Customised assert method comparing a byte arrays: values starting at actual[actualStart] must + * those starting at actual[actualStart], for a distance of n bytes. + * + * @param message to issue on failure + * @param expected expected byte array + * @param expectedStart where to start the comparison in expected + * @param actual result to test + * @param actualStart where to start the comparison in actual + * @param n number of bytes to test + */ + void assertBytesEqual(String message, byte[] expected, int expectedStart, byte[] actual, + int actualStart, int n) { + if (actualStart < 0 || expectedStart < 0) { + fail(message + " (start<0)"); + } else if (actualStart + n > actual.length || expectedStart + n > expected.length) { + fail(message + " (too short)"); + } else { + // Should be safe to compare the values + int i = actualStart, j, jLimit = expectedStart + n; + for (j = expectedStart; j < jLimit; j++) { + if (actual[i++] != expected[j]) { + break; + } + } + if (j < jLimit) { + System.out.println(" expected:" + + Arrays.toString(Arrays.copyOfRange(expected, expectedStart, expectedStart + + n))); + System.out.println(" actual:" + + Arrays.toString(Arrays.copyOfRange(actual, actualStart, actualStart + n))); + System.out.println(" _actual_:" + Arrays.toString(actual)); + fail(message + " (byte at " + j + ")"); + } + } + } + + /** + * Customised assert method comparing a int arrays: values in the actual value starting at + * actual[offset] must match all those in expected[], and there must be enough of them. + * + * @param message to issue on failure + * @param expected expected array + * @param actual result to test + * @param offset where to start the comparison in actual + */ + void assertIntsEqual(String message, int[] expected, int[] actual, int offset) { + int n = expected.length; + if (offset < 0) { + fail(message + " (offset<0)"); + } else if (offset + n > actual.length) { + fail(message + " (too short)"); + } else { + // Should be safe to compare the values + int i = offset, j; + for (j = 0; j < n; j++) { + if (actual[i++] != expected[j]) { + break; + } + } + if (j < n) { + System.out.println(" expected:" + Arrays.toString(expected)); + System.out.println(" actual:" + Arrays.toString(actual)); + fail(message + " (int at " + j + ")"); + } + } + } + + /** + * Customised assert method comparing a int arrays: int in the actual value must match all those + * in expected[], and there must be the same number of them. + * + * @param message to issue on failure + * @param expected expected array + * @param actual result to test + */ + void assertIntsEqual(String message, int[] expected, int[] actual) { + int n = expected.length; + assertEquals(message, n, actual.length); + // Should be safe to compare the values + int j; + for (j = 0; j < n; j++) { + if (actual[j] != expected[j]) { + break; + } + } + if (j < n) { + System.out.println(" expected:" + Arrays.toString(expected)); + System.out.println(" actual:" + Arrays.toString(actual)); + fail(message + " (int at " + j + ")"); + } + } + + /** + * Element for queueing tests, wraps an exporter object with (a copy of) the material from which + * it was created, and several PyBuffer views. + */ + static class BufferTestPair { + + static final int[] STRIDES_1D = {1}; + + BufferProtocol exporter; + ByteMaterial material; + PyBuffer simple, strided; + int[] shape, strides; + + /** + * A test to do and the material for constructing it (and its results). + * + * @param exporter + * @param material + * @param shape of the array, when testing in N-dimensions + * @param stride of the array, when testing in N-dimensions + */ + public BufferTestPair(BufferProtocol exporter, ByteMaterial material, int[] shape, + int[] strides) { + this.exporter = exporter; + this.material = new ByteMaterial(material.ints); + this.shape = shape; + this.strides = strides; + try { + simple = exporter.getBuffer(PyBUF.SIMPLE); + strided = exporter.getBuffer(PyBUF.STRIDES); + } catch (Exception e) { + // Leave them null if we can't get a PyBuffer: test being set up will fail. + // Silent here, but explicit test of getBuffer will reproduce and log this failure. + } + } + + /** + * A test to do and the material for constructing it (and its results) in one dimension. + * + * @param exporter + * @param material + */ + public BufferTestPair(BufferProtocol exporter, ByteMaterial material) { + this(exporter, material, new int[1], STRIDES_1D); + shape[0] = material.length; + } + + @Override + public String toString() { + return exporter.getClass().getSimpleName() + "( " + material.toString() + " )"; + } + + } +} -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Wed Jul 18 17:21:17 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Wed, 18 Jul 2012 17:21:17 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Check_for_BaseS?= =?utf-8?q?tring_so_unicode_is_legal=2E?= Message-ID: <3Wchs950GMzPDy@mail.python.org> http://hg.python.org/jython/rev/aa13e5d9a23f changeset: 6799:aa13e5d9a23f branch: 2.5 parent: 6790:36e6f6a4f476 user: Frank Wierzbicki date: Tue Jul 17 10:35:51 2012 -0700 summary: Check for BaseString so unicode is legal. files: src/org/python/core/PyClass.java | 4 ++-- src/org/python/core/PyFunction.java | 2 +- src/org/python/core/imp.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/org/python/core/PyClass.java b/src/org/python/core/PyClass.java --- a/src/org/python/core/PyClass.java +++ b/src/org/python/core/PyClass.java @@ -42,7 +42,7 @@ } public static PyObject classobj___new__(PyObject name, PyObject bases, PyObject dict) { - if (!name.getType().isSubType(PyString.TYPE)) { + if (!name.getType().isSubType(PyBaseString.TYPE)) { throw Py.TypeError("PyClass_New: name must be a string"); } if (!(dict instanceof PyStringMap || dict instanceof PyDictionary)) { @@ -278,7 +278,7 @@ } public void setName(PyObject value) { - if (value == null || !Py.isInstance(value, PyString.TYPE)) { + if (value == null || !Py.isInstance(value, PyBaseString.TYPE)) { throw Py.TypeError("__name__ must be a string object"); } String name = value.toString(); diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java --- a/src/org/python/core/PyFunction.java +++ b/src/org/python/core/PyFunction.java @@ -104,7 +104,7 @@ throw Py.TypeError("function() argument 1 must be code, not " + code.getType().fastGetName()); } - if (name != Py.None && !Py.isInstance(name, PyString.TYPE)) { + if (name != Py.None && !Py.isInstance(name, PyBaseString.TYPE)) { throw Py.TypeError("arg 3 (name) must be None or string"); } if (defaults != Py.None && !(defaults instanceof PyTuple)) { diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java --- a/src/org/python/core/imp.java +++ b/src/org/python/core/imp.java @@ -869,7 +869,7 @@ StringBuilder modNameBuffer = new StringBuilder(name); for (PyObject item : fromlist.asIterable()) { - if (!Py.isInstance(item, PyString.TYPE)) { + if (!Py.isInstance(item, PyBaseString.TYPE)) { throw Py.TypeError("Item in ``from list'' not a string"); } if (item.toString().equals("*")) { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Wed Jul 18 17:21:19 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Wed, 18 Jul 2012 17:21:19 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?q?=3A_Merge_with_2=2E5=2E?= Message-ID: <3WchsC0B55zPDy@mail.python.org> http://hg.python.org/jython/rev/eff0277ba0d9 changeset: 6800:eff0277ba0d9 parent: 6794:940d38d23c83 parent: 6799:aa13e5d9a23f user: Frank Wierzbicki date: Tue Jul 17 10:51:32 2012 -0700 summary: Merge with 2.5. files: src/org/python/core/PyClass.java | 4 ++-- src/org/python/core/PyFunction.java | 2 +- src/org/python/core/imp.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/org/python/core/PyClass.java b/src/org/python/core/PyClass.java --- a/src/org/python/core/PyClass.java +++ b/src/org/python/core/PyClass.java @@ -42,7 +42,7 @@ } public static PyObject classobj___new__(PyObject name, PyObject bases, PyObject dict) { - if (!name.getType().isSubType(PyString.TYPE)) { + if (!name.getType().isSubType(PyBaseString.TYPE)) { throw Py.TypeError("PyClass_New: name must be a string"); } if (!(dict instanceof PyStringMap || dict instanceof PyDictionary)) { @@ -273,7 +273,7 @@ } public void setName(PyObject value) { - if (value == null || !Py.isInstance(value, PyString.TYPE)) { + if (value == null || !Py.isInstance(value, PyBaseString.TYPE)) { throw Py.TypeError("__name__ must be a string object"); } String name = value.toString(); diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java --- a/src/org/python/core/PyFunction.java +++ b/src/org/python/core/PyFunction.java @@ -104,7 +104,7 @@ throw Py.TypeError("function() argument 1 must be code, not " + code.getType().fastGetName()); } - if (name != Py.None && !Py.isInstance(name, PyString.TYPE)) { + if (name != Py.None && !Py.isInstance(name, PyBaseString.TYPE)) { throw Py.TypeError("arg 3 (name) must be None or string"); } if (defaults != Py.None && !(defaults instanceof PyTuple)) { diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java --- a/src/org/python/core/imp.java +++ b/src/org/python/core/imp.java @@ -888,7 +888,7 @@ StringBuilder modNameBuffer = new StringBuilder(name); for (PyObject item : fromlist.asIterable()) { - if (!Py.isInstance(item, PyString.TYPE)) { + if (!Py.isInstance(item, PyBaseString.TYPE)) { throw Py.TypeError("Item in ``from list'' not a string"); } if (item.toString().equals("*")) { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Wed Jul 18 17:21:20 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Wed, 18 Jul 2012 17:21:20 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2Ugd2l0aCAyLjUu?= Message-ID: <3WchsD2p9mzPFg@mail.python.org> http://hg.python.org/jython/rev/d4373bf3ada2 changeset: 6801:d4373bf3ada2 parent: 6798:e8553ae3a804 parent: 6800:eff0277ba0d9 user: Frank Wierzbicki date: Wed Jul 18 08:18:41 2012 -0700 summary: Merge with 2.5. files: src/org/python/core/PyClass.java | 4 ++-- src/org/python/core/PyFunction.java | 2 +- src/org/python/core/imp.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/org/python/core/PyClass.java b/src/org/python/core/PyClass.java --- a/src/org/python/core/PyClass.java +++ b/src/org/python/core/PyClass.java @@ -42,7 +42,7 @@ } public static PyObject classobj___new__(PyObject name, PyObject bases, PyObject dict) { - if (!name.getType().isSubType(PyString.TYPE)) { + if (!name.getType().isSubType(PyBaseString.TYPE)) { throw Py.TypeError("PyClass_New: name must be a string"); } if (!(dict instanceof PyStringMap || dict instanceof PyDictionary)) { @@ -273,7 +273,7 @@ } public void setName(PyObject value) { - if (value == null || !Py.isInstance(value, PyString.TYPE)) { + if (value == null || !Py.isInstance(value, PyBaseString.TYPE)) { throw Py.TypeError("__name__ must be a string object"); } String name = value.toString(); diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java --- a/src/org/python/core/PyFunction.java +++ b/src/org/python/core/PyFunction.java @@ -104,7 +104,7 @@ throw Py.TypeError("function() argument 1 must be code, not " + code.getType().fastGetName()); } - if (name != Py.None && !Py.isInstance(name, PyString.TYPE)) { + if (name != Py.None && !Py.isInstance(name, PyBaseString.TYPE)) { throw Py.TypeError("arg 3 (name) must be None or string"); } if (defaults != Py.None && !(defaults instanceof PyTuple)) { diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java --- a/src/org/python/core/imp.java +++ b/src/org/python/core/imp.java @@ -888,7 +888,7 @@ StringBuilder modNameBuffer = new StringBuilder(name); for (PyObject item : fromlist.asIterable()) { - if (!Py.isInstance(item, PyString.TYPE)) { + if (!Py.isInstance(item, PyBaseString.TYPE)) { throw Py.TypeError("Item in ``from list'' not a string"); } if (item.toString().equals("*")) { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Wed Jul 18 17:21:21 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Wed, 18 Jul 2012 17:21:21 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?b?anl0aG9uIChtZXJnZSAyLjUgLT4gMi41KTog?= =?utf-8?q?Merge=2E?= Message-ID: <3WchsF512bzPGf@mail.python.org> http://hg.python.org/jython/rev/32cee9b9f709 changeset: 6802:32cee9b9f709 branch: 2.5 parent: 6795:e40f741bd904 parent: 6799:aa13e5d9a23f user: Frank Wierzbicki date: Wed Jul 18 08:21:04 2012 -0700 summary: Merge. files: src/org/python/core/PyClass.java | 4 ++-- src/org/python/core/PyFunction.java | 2 +- src/org/python/core/imp.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/org/python/core/PyClass.java b/src/org/python/core/PyClass.java --- a/src/org/python/core/PyClass.java +++ b/src/org/python/core/PyClass.java @@ -42,7 +42,7 @@ } public static PyObject classobj___new__(PyObject name, PyObject bases, PyObject dict) { - if (!name.getType().isSubType(PyString.TYPE)) { + if (!name.getType().isSubType(PyBaseString.TYPE)) { throw Py.TypeError("PyClass_New: name must be a string"); } if (!(dict instanceof PyStringMap || dict instanceof PyDictionary)) { @@ -278,7 +278,7 @@ } public void setName(PyObject value) { - if (value == null || !Py.isInstance(value, PyString.TYPE)) { + if (value == null || !Py.isInstance(value, PyBaseString.TYPE)) { throw Py.TypeError("__name__ must be a string object"); } String name = value.toString(); diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java --- a/src/org/python/core/PyFunction.java +++ b/src/org/python/core/PyFunction.java @@ -104,7 +104,7 @@ throw Py.TypeError("function() argument 1 must be code, not " + code.getType().fastGetName()); } - if (name != Py.None && !Py.isInstance(name, PyString.TYPE)) { + if (name != Py.None && !Py.isInstance(name, PyBaseString.TYPE)) { throw Py.TypeError("arg 3 (name) must be None or string"); } if (defaults != Py.None && !(defaults instanceof PyTuple)) { diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java --- a/src/org/python/core/imp.java +++ b/src/org/python/core/imp.java @@ -869,7 +869,7 @@ StringBuilder modNameBuffer = new StringBuilder(name); for (PyObject item : fromlist.asIterable()) { - if (!Py.isInstance(item, PyString.TYPE)) { + if (!Py.isInstance(item, PyBaseString.TYPE)) { throw Py.TypeError("Item in ``from list'' not a string"); } if (item.toString().equals("*")) { -- Repository URL: http://hg.python.org/jython From pjenvey at underboss.org Wed Jul 18 17:46:57 2012 From: pjenvey at underboss.org (Philip Jenvey) Date: Wed, 18 Jul 2012 08:46:57 -0700 Subject: [Jython-checkins] jython (2.5): Check for BaseString so unicode is legal. In-Reply-To: <3Wchs950GMzPDy@mail.python.org> References: <3Wchs950GMzPDy@mail.python.org> Message-ID: You actually don't want to change all these checks in class/function to match CPython 2.7. On Jul 18, 2012, at 8:21 AM, frank.wierzbicki wrote: > http://hg.python.org/jython/rev/aa13e5d9a23f > changeset: 6799:aa13e5d9a23f > branch: 2.5 > parent: 6790:36e6f6a4f476 > user: Frank Wierzbicki > date: Tue Jul 17 10:35:51 2012 -0700 > summary: > Check for BaseString so unicode is legal. > > files: > src/org/python/core/PyClass.java | 4 ++-- > src/org/python/core/PyFunction.java | 2 +- > src/org/python/core/imp.java | 2 +- > 3 files changed, 4 insertions(+), 4 deletions(-) > > > diff --git a/src/org/python/core/PyClass.java b/src/org/python/core/PyClass.java > --- a/src/org/python/core/PyClass.java > +++ b/src/org/python/core/PyClass.java > @@ -42,7 +42,7 @@ > } > > public static PyObject classobj___new__(PyObject name, PyObject bases, PyObject dict) { > - if (!name.getType().isSubType(PyString.TYPE)) { > + if (!name.getType().isSubType(PyBaseString.TYPE)) { > throw Py.TypeError("PyClass_New: name must be a string"); > } > if (!(dict instanceof PyStringMap || dict instanceof PyDictionary)) { > @@ -278,7 +278,7 @@ > } > > public void setName(PyObject value) { > - if (value == null || !Py.isInstance(value, PyString.TYPE)) { > + if (value == null || !Py.isInstance(value, PyBaseString.TYPE)) { > throw Py.TypeError("__name__ must be a string object"); > } > String name = value.toString(); > diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java > --- a/src/org/python/core/PyFunction.java > +++ b/src/org/python/core/PyFunction.java > @@ -104,7 +104,7 @@ > throw Py.TypeError("function() argument 1 must be code, not " + > code.getType().fastGetName()); > } > - if (name != Py.None && !Py.isInstance(name, PyString.TYPE)) { > + if (name != Py.None && !Py.isInstance(name, PyBaseString.TYPE)) { > throw Py.TypeError("arg 3 (name) must be None or string"); > } > if (defaults != Py.None && !(defaults instanceof PyTuple)) { > diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java > --- a/src/org/python/core/imp.java > +++ b/src/org/python/core/imp.java > @@ -869,7 +869,7 @@ > > StringBuilder modNameBuffer = new StringBuilder(name); > for (PyObject item : fromlist.asIterable()) { > - if (!Py.isInstance(item, PyString.TYPE)) { > + if (!Py.isInstance(item, PyBaseString.TYPE)) { > throw Py.TypeError("Item in ``from list'' not a string"); > } > if (item.toString().equals("*")) { > > -- > Repository URL: http://hg.python.org/jython > _______________________________________________ > Jython-checkins mailing list > Jython-checkins at python.org > http://mail.python.org/mailman/listinfo/jython-checkins -- Philip Jenvey From fwierzbicki at gmail.com Wed Jul 18 17:59:27 2012 From: fwierzbicki at gmail.com (fwierzbicki at gmail.com) Date: Wed, 18 Jul 2012 08:59:27 -0700 Subject: [Jython-checkins] jython (2.5): Check for BaseString so unicode is legal. In-Reply-To: References: <3Wchs950GMzPDy@mail.python.org> Message-ID: On Wed, Jul 18, 2012 at 8:46 AM, Philip Jenvey wrote: > You actually don't want to change all these checks in class/function to match CPython 2.7. > Oops - I'll revert those - it's ok in imp.java though right? -Frank From pjenvey at underboss.org Wed Jul 18 19:27:03 2012 From: pjenvey at underboss.org (Philip Jenvey) Date: Wed, 18 Jul 2012 10:27:03 -0700 Subject: [Jython-checkins] jython (2.5): Check for BaseString so unicode is legal. In-Reply-To: References: <3Wchs950GMzPDy@mail.python.org> Message-ID: On Jul 18, 2012, at 8:59 AM, fwierzbicki at gmail.com wrote: > On Wed, Jul 18, 2012 at 8:46 AM, Philip Jenvey wrote: >> You actually don't want to change all these checks in class/function to match CPython 2.7. >> > Oops - I'll revert those - it's ok in imp.java though right? Now that I've looked, CPython's ensure_fromlist uses PyString_Check too. Which begs the question, why is unicode coming in here and should it? -- Philip Jenvey From fwierzbicki at gmail.com Wed Jul 18 19:30:41 2012 From: fwierzbicki at gmail.com (fwierzbicki at gmail.com) Date: Wed, 18 Jul 2012 10:30:41 -0700 Subject: [Jython-checkins] jython (2.5): Check for BaseString so unicode is legal. In-Reply-To: References: <3Wchs950GMzPDy@mail.python.org> Message-ID: On Wed, Jul 18, 2012 at 10:27 AM, Philip Jenvey wrote: >> Oops - I'll revert those - it's ok in imp.java though right? > > Now that I've looked, CPython's ensure_fromlist uses PyString_Check too. Which begs the question, why is unicode coming in here and should it? > Alex is using the import machinery from Java code I guess (or is importing from Java code and later using the imp module) -- I don't think there is much harm in allowing unicode in imp - and I'd guess he's not the only one out there using (and perhaps abusing) imports from Java code... -Frank From jython-checkins at python.org Wed Jul 18 19:46:28 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Wed, 18 Jul 2012 19:46:28 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Revert_allowing?= =?utf-8?q?_unicode_in_names=2E?= Message-ID: <3Wcm4h19YszPFM@mail.python.org> http://hg.python.org/jython/rev/6ca8838410c2 changeset: 6803:6ca8838410c2 branch: 2.5 user: Frank Wierzbicki date: Wed Jul 18 09:32:56 2012 -0700 summary: Revert allowing unicode in names. files: src/org/python/core/PyClass.java | 4 ++-- src/org/python/core/PyFunction.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/python/core/PyClass.java b/src/org/python/core/PyClass.java --- a/src/org/python/core/PyClass.java +++ b/src/org/python/core/PyClass.java @@ -42,7 +42,7 @@ } public static PyObject classobj___new__(PyObject name, PyObject bases, PyObject dict) { - if (!name.getType().isSubType(PyBaseString.TYPE)) { + if (!name.getType().isSubType(PyString.TYPE)) { throw Py.TypeError("PyClass_New: name must be a string"); } if (!(dict instanceof PyStringMap || dict instanceof PyDictionary)) { @@ -278,7 +278,7 @@ } public void setName(PyObject value) { - if (value == null || !Py.isInstance(value, PyBaseString.TYPE)) { + if (value == null || !Py.isInstance(value, PyString.TYPE)) { throw Py.TypeError("__name__ must be a string object"); } String name = value.toString(); diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java --- a/src/org/python/core/PyFunction.java +++ b/src/org/python/core/PyFunction.java @@ -104,7 +104,7 @@ throw Py.TypeError("function() argument 1 must be code, not " + code.getType().fastGetName()); } - if (name != Py.None && !Py.isInstance(name, PyBaseString.TYPE)) { + if (name != Py.None && !Py.isInstance(name, PyString.TYPE)) { throw Py.TypeError("arg 3 (name) must be None or string"); } if (defaults != Py.None && !(defaults instanceof PyTuple)) { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Wed Jul 18 19:46:29 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Wed, 18 Jul 2012 19:46:29 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?b?OiBNZXJnZSAyLjUu?= Message-ID: <3Wcm4j3S0tzPG9@mail.python.org> http://hg.python.org/jython/rev/bef3eb26155e changeset: 6804:bef3eb26155e parent: 6801:d4373bf3ada2 parent: 6803:6ca8838410c2 user: Frank Wierzbicki date: Wed Jul 18 10:27:57 2012 -0700 summary: Merge 2.5. files: src/org/python/core/PyClass.java | 4 ++-- src/org/python/core/PyFunction.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/python/core/PyClass.java b/src/org/python/core/PyClass.java --- a/src/org/python/core/PyClass.java +++ b/src/org/python/core/PyClass.java @@ -42,7 +42,7 @@ } public static PyObject classobj___new__(PyObject name, PyObject bases, PyObject dict) { - if (!name.getType().isSubType(PyBaseString.TYPE)) { + if (!name.getType().isSubType(PyString.TYPE)) { throw Py.TypeError("PyClass_New: name must be a string"); } if (!(dict instanceof PyStringMap || dict instanceof PyDictionary)) { @@ -273,7 +273,7 @@ } public void setName(PyObject value) { - if (value == null || !Py.isInstance(value, PyBaseString.TYPE)) { + if (value == null || !Py.isInstance(value, PyString.TYPE)) { throw Py.TypeError("__name__ must be a string object"); } String name = value.toString(); diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java --- a/src/org/python/core/PyFunction.java +++ b/src/org/python/core/PyFunction.java @@ -104,7 +104,7 @@ throw Py.TypeError("function() argument 1 must be code, not " + code.getType().fastGetName()); } - if (name != Py.None && !Py.isInstance(name, PyBaseString.TYPE)) { + if (name != Py.None && !Py.isInstance(name, PyString.TYPE)) { throw Py.TypeError("arg 3 (name) must be None or string"); } if (defaults != Py.None && !(defaults instanceof PyTuple)) { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Sat Jul 21 00:35:08 2012 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Jul 2012 00:35:08 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Support_concatenation_str+b?= =?utf-8?q?ytearray?= Message-ID: <3Wf6Nr60sJzPPw@mail.python.org> http://hg.python.org/jython/rev/a7e4a8c63fae changeset: 6805:a7e4a8c63fae parent: 6797:e0aa95bac30e user: Jeff Allen date: Thu Jul 19 20:52:13 2012 +0100 summary: Support concatenation str+bytearray Now down to 6 failures in test_bytes.py. files: src/org/python/core/BaseBytes.java | 47 +++++---------- src/org/python/core/PyByteArray.java | 4 +- src/org/python/core/PyString.java | 10 ++- 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -1479,18 +1479,21 @@ } /** - * Copy the bytes of a byte array to the characters of a String with no change in ordinal value. - * This could also be described as 'latin-1' decoding of the byte array to a String. - * - * @return the byte array as a String, still encoded + * Present the bytes of a byte array, with no decoding, as a Java String. The bytes are treated + * as unsigned character codes, and copied to the to the characters of a String with no change + * in ordinal value. This could also be described as 'latin-1' or 'ISO-8859-1' decoding of the + * byte array to a String, since this character encoding is numerically equal to Unicode. + * + * @return the byte array as a String */ - private synchronized String asEncodedString() { - StringBuilder buf = new StringBuilder(size); - int jmax = offset + size; - for (int j = offset; j < jmax; j++) { - buf.append((char)(0xff & storage[j])); + @Override + public synchronized String asString() { + char[] buf = new char[size]; + int j = offset + size; + for (int i = size; --i >= 0;) { + buf[i] = (char)(0xff & storage[--j]); } - return buf.toString(); + return new String(buf); } /** @@ -1530,7 +1533,7 @@ * expects a PyString. (In Python 3k the codecs decode from the bytes type, so * we can pass this directly.) */ - PyString this_ = new PyString(this.asEncodedString()); + PyString this_ = new PyString(this.asString()); return codecs.decode(this_, encoding, errors); } @@ -1578,7 +1581,7 @@ * @return required tuple of type, arguments needed by init, and any user-added attributes. */ final PyTuple basebytes___reduce__() { - PyUnicode encoded = new PyUnicode(this.asEncodedString()); + PyUnicode encoded = new PyUnicode(this.asString()); PyObject args = new PyTuple(encoded, getPickleEncoding()); PyObject dict = __findattr__("__dict__"); return new PyTuple(getType(), args, (dict != null) ? dict : Py.None); @@ -3964,26 +3967,6 @@ return buf.toString(); } - /** - * Ready-to-expose Python __str__(), returning a PyString by treating - * the bytes as point codes. The built-in function str() is expected to call this - * method. - */ - final synchronized PyString basebytes_str() { - // Get hold of the decoder for ISO-8859-1, which is one-for-one with Unicode - if (defaultCharset == null) { - defaultCharset = Charset.forName("ISO-8859-1"); - } - String s = new String(storage, offset, size, defaultCharset); - return new PyString(s); - } - - /** - * Used in {@link #basebytes_str()}, and when not null, points to the identity Charset for - * decoding bytes to char. - */ - private static Charset defaultCharset; - /* * ============================================================================================ * API for java.util.List diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java --- a/src/org/python/core/PyByteArray.java +++ b/src/org/python/core/PyByteArray.java @@ -1932,12 +1932,12 @@ */ @Override public PyString __str__() { - return basebytes_str(); + return bytearray_str(); } @ExposedMethod(names = {"__str__"}, doc = BuiltinDocs.bytearray___str___doc) final PyString bytearray_str() { - return basebytes_str(); + return new PyString(this.asString()); } /** diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java +++ b/src/org/python/core/PyString.java @@ -740,15 +740,19 @@ public PyObject __add__(PyObject other) { return str___add__(other); } - + @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.str___add___doc) final PyObject str___add__(PyObject other) { if (other instanceof PyUnicode) { return decode().__add__(other); - } - if (other instanceof PyString) { + + } else if (other instanceof PyString) { PyString otherStr = (PyString)other; return new PyString(getString().concat(otherStr.getString())); + + } else if (other instanceof PyByteArray) { + return new PyString(getString().concat(other.asString())); + } return null; } -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Sat Jul 21 00:35:10 2012 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Jul 2012 00:35:10 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Extend_builtin_ord=28=29_to?= =?utf-8?q?_bytearray?= Message-ID: <3Wf6Nt1GB8zPQB@mail.python.org> http://hg.python.org/jython/rev/b3e12788987e changeset: 6806:b3e12788987e user: Jeff Allen date: Thu Jul 19 22:24:30 2012 +0100 summary: Extend builtin ord() to bytearray files: src/org/python/core/__builtin__.java | 52 +++++++++++---- 1 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/org/python/core/__builtin__.java b/src/org/python/core/__builtin__.java --- a/src/org/python/core/__builtin__.java +++ b/src/org/python/core/__builtin__.java @@ -64,10 +64,6 @@ case 2: return __builtin__.range(arg1); case 3: - if (!(arg1 instanceof PyString)) { - throw Py.TypeError("ord() expected string of length 1, but " + - arg1.getType().fastGetName() + " found"); - } return Py.newInteger(__builtin__.ord(arg1)); case 5: return __builtin__.hash(arg1); @@ -766,22 +762,48 @@ return o.__oct__(); } - public static final int ord(PyObject c) { + /** + * Built-in Python function ord() applicable to the string-like types str, + * bytearray, unicode. + * + * @param c string-like object of length 1 + * @return ordinal value of character or byte value in + * @throws PyException (TypeError) if not a string-like type + */ + public static final int ord(PyObject c) throws PyException { final int length; - PyString x = (PyString) c; - if (x instanceof PyUnicode) { - length = x.getString().codePointCount(0, x.getString().length()); + + if (c instanceof PyUnicode) { + String cu = ((PyUnicode)c).getString(); + length = cu.codePointCount(0, cu.length()); if (length == 1) { - return x.getString().codePointAt(0); + return cu.codePointAt(0); } + + } else if (c instanceof PyString) { + String cs = ((PyString)c).getString(); + length = cs.length(); + if (length == 1) { + return cs.charAt(0); + } + + } else if (c instanceof BaseBytes) { + BaseBytes cb = (BaseBytes)c; + length = cb.__len__(); + if (length == 1) { + return cb.intAt(0); + } + } else { - length = x.getString().length(); - if (length == 1) { - return x.getString().charAt(0); - } + // Not any of the acceptable types + throw Py.TypeError("ord() expected string of length 1, but " + + c.getType().fastGetName() + " found"); } - throw Py.TypeError("ord() expected a character, but string of length " + - length + " found"); + /* + * It was a qualifying string-like object, but if we didn't return or throw by now, the + * problem was the length. + */ + throw Py.TypeError("ord() expected a character, but string of length " + length + " found"); } public static PyObject pow(PyObject x, PyObject y) { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Sat Jul 21 00:35:11 2012 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Jul 2012 00:35:11 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Make_int=28=29_accept_bytea?= =?utf-8?q?rray_as_convertible_text=2E?= Message-ID: <3Wf6Nv4vM6zPQF@mail.python.org> http://hg.python.org/jython/rev/31ebee268c70 changeset: 6807:31ebee268c70 user: Jeff Allen date: Fri Jul 20 21:30:58 2012 +0100 summary: Make int() accept bytearray as convertible text. Also improvements to comments and code style in vicinity of change (needed to see how it works). files: src/org/python/core/PyInteger.java | 85 ++++++++++++----- 1 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/org/python/core/PyInteger.java b/src/org/python/core/PyInteger.java --- a/src/org/python/core/PyInteger.java +++ b/src/org/python/core/PyInteger.java @@ -52,75 +52,104 @@ @ExposedNew public static PyObject int_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("int", args, keywords, new String[] {"x", "base"}, 0); PyObject x = ap.getPyObject(0, null); int base = ap.getInt(1, -909); - if (new_.for_type == subtype) { + + if (new_.for_type == subtype) { // A substantive PyInteger is required as the return value + if (x == null) { return Py.Zero; - } - if (base == -909) { + + } else if (base == -909) { if (x instanceof PyBoolean) { return (coerce(x) == 0) ? Py.Zero : Py.One; + } else if (x instanceof PyByteArray) { + // Make use of the string to int conversion in PyString + PyString xs = new PyString(x.asString()); + return asPyInteger(xs); + } else { + return asPyInteger(x); } - return asPyInteger(x); - } - if (!(x instanceof PyString)) { + } else if (!(x instanceof PyString)) { throw Py.TypeError("int: can't convert non-string with explicit base"); } + try { - return Py.newInteger(((PyString) x).atoi(base)); + return Py.newInteger(((PyString)x).atoi(base)); } catch (PyException pye) { if (pye.match(Py.OverflowError)) { - return ((PyString) x).atol(base); + return ((PyString)x).atol(base); } throw pye; } - } else { + + } else { // A PyIntegerDerived(subtype, ... ) is required as the return value + if (x == null) { return new PyIntegerDerived(subtype, 0); - } - if (base == -909) { + } else if (base == -909) { PyObject intOrLong = asPyInteger(x); + if (intOrLong instanceof PyInteger) { - return new PyIntegerDerived(subtype, ((PyInteger) intOrLong).getValue()); + return new PyIntegerDerived(subtype, ((PyInteger)intOrLong).getValue()); } else { throw Py.OverflowError("long int too large to convert to int"); } - } - if (!(x instanceof PyString)) { + + } else if (!(x instanceof PyString)) { throw Py.TypeError("int: can't convert non-string with explicit base"); } - return new PyIntegerDerived(subtype, ((PyString) x).atoi(base)); + + return new PyIntegerDerived(subtype, ((PyString)x).atoi(base)); } } // xxx /** - * @return convert to an int. - * @throws TypeError and AttributeError. + * Convert all sorts of object types to either PyInteger or PyLong, + * using their {@link PyObject#__int__()} method, whether exposed or not, or if that raises an + * exception (as the base PyObject one does), using any __trunc__() + * the type may have exposed. If all this fails, this method raises an exception. Equivalent to CPython + * PyNumber_Int(). + * + * @param x to convert to an int + * @return int or long result. + * @throws PyException (TypeError) if no method of conversion can be found + * @throws PyException (AttributeError) if neither __int__ nor __trunc__ found (?) */ - private static PyObject asPyInteger(PyObject x) { - //XXX: Not sure that this perfectly matches CPython semantics. + private static PyObject asPyInteger(PyObject x) throws PyException { + // XXX: Not sure that this perfectly matches CPython semantics. try { + // Try the object itself (raises AttributeError if not overridden from PyObject) return x.__int__(); + } catch (PyException pye) { if (!pye.match(Py.AttributeError)) { + // x had an __int__ method, but something else went wrong: pass it on throw pye; - } - try { - PyObject integral = x.invoke("__trunc__"); - return convertIntegralToInt(integral); - } catch (PyException pye2) { - if (!pye2.match(Py.AttributeError)) { - throw pye2; + + } else { + // x did not have an __int__ method, but maybe __trunc__ will work + try { + PyObject integral = x.invoke("__trunc__"); + return convertIntegralToInt(integral); + + } catch (PyException pye2) { + if (!pye2.match(Py.AttributeError)) { + throw pye2; + } + String fmt = "int() argument must be a string or a number, not '%.200s'"; + throw Py.TypeError(String.format(fmt, x)); } - throw Py.TypeError( - String.format("int() argument must be a string or a number, not '%.200s'", x)); } } } /** + * Helper called on whatever exposed method __trunc__ returned: it may be + * int, long or something with an exposed __int__. + * * @return convert to an int. * @throws TypeError and AttributeError. */ -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Sat Jul 21 00:35:13 2012 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Jul 2012 00:35:13 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Support_corner_case_in_byte?= =?utf-8?b?YXJyYXkgYlt4Onk6el09Yicn?= Message-ID: <3Wf6Nx1BZ8zPPy@mail.python.org> http://hg.python.org/jython/rev/95bc782dc561 changeset: 6808:95bc782dc561 user: Jeff Allen date: Fri Jul 20 23:01:33 2012 +0100 summary: Support corner case in bytearray b[x:y:z]=b'' Unlike list, CPython bytearray accepts assignment of empty list to extended slice as deletion. Now down to 3 failures in test.test_bytes files: src/org/python/core/BaseBytes.java | 44 +++++++++++++++- src/org/python/core/PySequence.java | 33 ++++++++++++- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -41,7 +41,8 @@ * @param type explicit Jython type */ public BaseBytes(PyType type) { - super(type); // implicit setStorage( emptyStorage ); + super(type, null); + delegator = new IndexDelegate(); setStorage(emptyStorage); } @@ -52,7 +53,8 @@ * @param type explicit Jython type */ public BaseBytes(PyType type, int size) { - super(type); + super(type, null); + delegator = new IndexDelegate(); newStorage(size); } @@ -63,7 +65,8 @@ * @param value source of values (and size) */ public BaseBytes(PyType type, int[] value) { - super(type); + super(type, null); + delegator = new IndexDelegate(); int n = value.length; newStorage(n); for (int i = offset, j = 0; j < n; i++, j++) { @@ -80,7 +83,8 @@ * @throws PyException if any value[i] > 255 */ protected BaseBytes(PyType type, String value) throws PyException { - super(type); + super(type, null); + delegator = new IndexDelegate(); int n = value.length(); newStorage(n); for (int i = offset, j = 0; j < n; j++) { @@ -1127,6 +1131,38 @@ return getslice(start, stop, 1); } + /** + * Class defining the behaviour of bytearray with respect to slice assignment, etc., which + * differs from the default (list) behaviour in small ways. + */ + private class IndexDelegate extends PySequence.DefaultIndexDelegate { + + /* + * bytearray treats assignment of a zero-length object to a slice as equivalent to deletion, + * unlike list, even for an extended slice. + */ + // >>> a = range(10) + // >>> b = bytearray(a) + // >>> a[1:6:2] = [] + // Traceback (most recent call last): + // File "", line 1, in + // ValueError: attempt to assign sequence of size 0 to extended slice of size 3 + // >>> b[1:6:2] = [] + // >>> b + // bytearray(b'\x00\x02\x04\x06\x07\x08\t') + // + @Override + public void checkIdxAndSetSlice(PySlice slice, PyObject value) { + if (value.__len__() != 0) { + // Proceed as default + super.checkIdxAndSetSlice(slice, value); + } else { + // Treat as deletion + super.checkIdxAndDelItem(slice); + } + } + }; + /* * ============================================================================================ * Support for Python API common to mutable and immutable subclasses diff --git a/src/org/python/core/PySequence.java b/src/org/python/core/PySequence.java --- a/src/org/python/core/PySequence.java +++ b/src/org/python/core/PySequence.java @@ -14,8 +14,35 @@ */ public abstract class PySequence extends PyObject { + /** + * A delegate that handles index checking and manipulation for get, set and del operations on + * this sequence in the form of a "pluggable behaviour". Because different types of sequence + * exhibit subtly different behaviour, there is scope for subclasses to customise the behaviour + * with their own extension of SequenceIndexDelegate. + */ + protected SequenceIndexDelegate delegator; + + /** + * Construct a PySequence for the given sub-type with the default index behaviour. + * + * @param type actual (Python) type of sub-class + */ protected PySequence(PyType type) { super(type); + delegator = new DefaultIndexDelegate(); + } + + /** + * Construct a PySequence for the given sub-type with custom index behaviour. In practice, + * restrictions on the construction of inner classes will mean null has to be passed and the + * actual delegator assigned later. + * + * @param type actual (Python) type of sub-class + * @param behaviour specific index behaviour (or null) + */ + protected PySequence(PyType type, SequenceIndexDelegate behaviour) { + super(type); + delegator = behaviour; } // These methods must be defined for any sequence @@ -451,7 +478,11 @@ return true; } - protected final SequenceIndexDelegate delegator = new SequenceIndexDelegate() { + /** + * Class defining the default behaviour of sequences with respect to slice assignment, etc., + * which is the one correct for list. + */ + protected class DefaultIndexDelegate extends SequenceIndexDelegate { @Override public String getTypeName() { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Sat Jul 21 00:35:14 2012 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Jul 2012 00:35:14 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_recent_fixes_related_to_bytearray?= Message-ID: <3Wf6Ny64lszPQ0@mail.python.org> http://hg.python.org/jython/rev/546e63253a0e changeset: 6809:546e63253a0e parent: 6804:bef3eb26155e parent: 6808:95bc782dc561 user: Jeff Allen date: Fri Jul 20 23:15:35 2012 +0100 summary: Merge recent fixes related to bytearray files: src/org/python/core/BaseBytes.java | 91 +++++++++------ src/org/python/core/PyByteArray.java | 4 +- src/org/python/core/PyInteger.java | 85 ++++++++++---- src/org/python/core/PySequence.java | 33 +++++- src/org/python/core/PyString.java | 10 +- src/org/python/core/__builtin__.java | 52 ++++++-- 6 files changed, 190 insertions(+), 85 deletions(-) diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -41,7 +41,8 @@ * @param type explicit Jython type */ public BaseBytes(PyType type) { - super(type); // implicit setStorage( emptyStorage ); + super(type, null); + delegator = new IndexDelegate(); setStorage(emptyStorage); } @@ -52,7 +53,8 @@ * @param type explicit Jython type */ public BaseBytes(PyType type, int size) { - super(type); + super(type, null); + delegator = new IndexDelegate(); newStorage(size); } @@ -63,7 +65,8 @@ * @param value source of values (and size) */ public BaseBytes(PyType type, int[] value) { - super(type); + super(type, null); + delegator = new IndexDelegate(); int n = value.length; newStorage(n); for (int i = offset, j = 0; j < n; i++, j++) { @@ -80,7 +83,8 @@ * @throws PyException if any value[i] > 255 */ protected BaseBytes(PyType type, String value) throws PyException { - super(type); + super(type, null); + delegator = new IndexDelegate(); int n = value.length(); newStorage(n); for (int i = offset, j = 0; j < n; j++) { @@ -1127,6 +1131,38 @@ return getslice(start, stop, 1); } + /** + * Class defining the behaviour of bytearray with respect to slice assignment, etc., which + * differs from the default (list) behaviour in small ways. + */ + private class IndexDelegate extends PySequence.DefaultIndexDelegate { + + /* + * bytearray treats assignment of a zero-length object to a slice as equivalent to deletion, + * unlike list, even for an extended slice. + */ + // >>> a = range(10) + // >>> b = bytearray(a) + // >>> a[1:6:2] = [] + // Traceback (most recent call last): + // File "", line 1, in + // ValueError: attempt to assign sequence of size 0 to extended slice of size 3 + // >>> b[1:6:2] = [] + // >>> b + // bytearray(b'\x00\x02\x04\x06\x07\x08\t') + // + @Override + public void checkIdxAndSetSlice(PySlice slice, PyObject value) { + if (value.__len__() != 0) { + // Proceed as default + super.checkIdxAndSetSlice(slice, value); + } else { + // Treat as deletion + super.checkIdxAndDelItem(slice); + } + } + }; + /* * ============================================================================================ * Support for Python API common to mutable and immutable subclasses @@ -1479,18 +1515,21 @@ } /** - * Copy the bytes of a byte array to the characters of a String with no change in ordinal value. - * This could also be described as 'latin-1' decoding of the byte array to a String. - * - * @return the byte array as a String, still encoded + * Present the bytes of a byte array, with no decoding, as a Java String. The bytes are treated + * as unsigned character codes, and copied to the to the characters of a String with no change + * in ordinal value. This could also be described as 'latin-1' or 'ISO-8859-1' decoding of the + * byte array to a String, since this character encoding is numerically equal to Unicode. + * + * @return the byte array as a String */ - private synchronized String asEncodedString() { - StringBuilder buf = new StringBuilder(size); - int jmax = offset + size; - for (int j = offset; j < jmax; j++) { - buf.append((char)(0xff & storage[j])); + @Override + public synchronized String asString() { + char[] buf = new char[size]; + int j = offset + size; + for (int i = size; --i >= 0;) { + buf[i] = (char)(0xff & storage[--j]); } - return buf.toString(); + return new String(buf); } /** @@ -1530,7 +1569,7 @@ * expects a PyString. (In Python 3k the codecs decode from the bytes type, so * we can pass this directly.) */ - PyString this_ = new PyString(this.asEncodedString()); + PyString this_ = new PyString(this.asString()); return codecs.decode(this_, encoding, errors); } @@ -1578,7 +1617,7 @@ * @return required tuple of type, arguments needed by init, and any user-added attributes. */ final PyTuple basebytes___reduce__() { - PyUnicode encoded = new PyUnicode(this.asEncodedString()); + PyUnicode encoded = new PyUnicode(this.asString()); PyObject args = new PyTuple(encoded, getPickleEncoding()); PyObject dict = __findattr__("__dict__"); return new PyTuple(getType(), args, (dict != null) ? dict : Py.None); @@ -3964,26 +4003,6 @@ return buf.toString(); } - /** - * Ready-to-expose Python __str__(), returning a PyString by treating - * the bytes as point codes. The built-in function str() is expected to call this - * method. - */ - final synchronized PyString basebytes_str() { - // Get hold of the decoder for ISO-8859-1, which is one-for-one with Unicode - if (defaultCharset == null) { - defaultCharset = Charset.forName("ISO-8859-1"); - } - String s = new String(storage, offset, size, defaultCharset); - return new PyString(s); - } - - /** - * Used in {@link #basebytes_str()}, and when not null, points to the identity Charset for - * decoding bytes to char. - */ - private static Charset defaultCharset; - /* * ============================================================================================ * API for java.util.List diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java --- a/src/org/python/core/PyByteArray.java +++ b/src/org/python/core/PyByteArray.java @@ -1932,12 +1932,12 @@ */ @Override public PyString __str__() { - return basebytes_str(); + return bytearray_str(); } @ExposedMethod(names = {"__str__"}, doc = BuiltinDocs.bytearray___str___doc) final PyString bytearray_str() { - return basebytes_str(); + return new PyString(this.asString()); } /** diff --git a/src/org/python/core/PyInteger.java b/src/org/python/core/PyInteger.java --- a/src/org/python/core/PyInteger.java +++ b/src/org/python/core/PyInteger.java @@ -52,75 +52,104 @@ @ExposedNew public static PyObject int_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("int", args, keywords, new String[] {"x", "base"}, 0); PyObject x = ap.getPyObject(0, null); int base = ap.getInt(1, -909); - if (new_.for_type == subtype) { + + if (new_.for_type == subtype) { // A substantive PyInteger is required as the return value + if (x == null) { return Py.Zero; - } - if (base == -909) { + + } else if (base == -909) { if (x instanceof PyBoolean) { return (coerce(x) == 0) ? Py.Zero : Py.One; + } else if (x instanceof PyByteArray) { + // Make use of the string to int conversion in PyString + PyString xs = new PyString(x.asString()); + return asPyInteger(xs); + } else { + return asPyInteger(x); } - return asPyInteger(x); - } - if (!(x instanceof PyString)) { + } else if (!(x instanceof PyString)) { throw Py.TypeError("int: can't convert non-string with explicit base"); } + try { - return Py.newInteger(((PyString) x).atoi(base)); + return Py.newInteger(((PyString)x).atoi(base)); } catch (PyException pye) { if (pye.match(Py.OverflowError)) { - return ((PyString) x).atol(base); + return ((PyString)x).atol(base); } throw pye; } - } else { + + } else { // A PyIntegerDerived(subtype, ... ) is required as the return value + if (x == null) { return new PyIntegerDerived(subtype, 0); - } - if (base == -909) { + } else if (base == -909) { PyObject intOrLong = asPyInteger(x); + if (intOrLong instanceof PyInteger) { - return new PyIntegerDerived(subtype, ((PyInteger) intOrLong).getValue()); + return new PyIntegerDerived(subtype, ((PyInteger)intOrLong).getValue()); } else { throw Py.OverflowError("long int too large to convert to int"); } - } - if (!(x instanceof PyString)) { + + } else if (!(x instanceof PyString)) { throw Py.TypeError("int: can't convert non-string with explicit base"); } - return new PyIntegerDerived(subtype, ((PyString) x).atoi(base)); + + return new PyIntegerDerived(subtype, ((PyString)x).atoi(base)); } } // xxx /** - * @return convert to an int. - * @throws TypeError and AttributeError. + * Convert all sorts of object types to either PyInteger or PyLong, + * using their {@link PyObject#__int__()} method, whether exposed or not, or if that raises an + * exception (as the base PyObject one does), using any __trunc__() + * the type may have exposed. If all this fails, this method raises an exception. Equivalent to CPython + * PyNumber_Int(). + * + * @param x to convert to an int + * @return int or long result. + * @throws PyException (TypeError) if no method of conversion can be found + * @throws PyException (AttributeError) if neither __int__ nor __trunc__ found (?) */ - private static PyObject asPyInteger(PyObject x) { - //XXX: Not sure that this perfectly matches CPython semantics. + private static PyObject asPyInteger(PyObject x) throws PyException { + // XXX: Not sure that this perfectly matches CPython semantics. try { + // Try the object itself (raises AttributeError if not overridden from PyObject) return x.__int__(); + } catch (PyException pye) { if (!pye.match(Py.AttributeError)) { + // x had an __int__ method, but something else went wrong: pass it on throw pye; - } - try { - PyObject integral = x.invoke("__trunc__"); - return convertIntegralToInt(integral); - } catch (PyException pye2) { - if (!pye2.match(Py.AttributeError)) { - throw pye2; + + } else { + // x did not have an __int__ method, but maybe __trunc__ will work + try { + PyObject integral = x.invoke("__trunc__"); + return convertIntegralToInt(integral); + + } catch (PyException pye2) { + if (!pye2.match(Py.AttributeError)) { + throw pye2; + } + String fmt = "int() argument must be a string or a number, not '%.200s'"; + throw Py.TypeError(String.format(fmt, x)); } - throw Py.TypeError( - String.format("int() argument must be a string or a number, not '%.200s'", x)); } } } /** + * Helper called on whatever exposed method __trunc__ returned: it may be + * int, long or something with an exposed __int__. + * * @return convert to an int. * @throws TypeError and AttributeError. */ diff --git a/src/org/python/core/PySequence.java b/src/org/python/core/PySequence.java --- a/src/org/python/core/PySequence.java +++ b/src/org/python/core/PySequence.java @@ -14,8 +14,35 @@ */ public abstract class PySequence extends PyObject { + /** + * A delegate that handles index checking and manipulation for get, set and del operations on + * this sequence in the form of a "pluggable behaviour". Because different types of sequence + * exhibit subtly different behaviour, there is scope for subclasses to customise the behaviour + * with their own extension of SequenceIndexDelegate. + */ + protected SequenceIndexDelegate delegator; + + /** + * Construct a PySequence for the given sub-type with the default index behaviour. + * + * @param type actual (Python) type of sub-class + */ protected PySequence(PyType type) { super(type); + delegator = new DefaultIndexDelegate(); + } + + /** + * Construct a PySequence for the given sub-type with custom index behaviour. In practice, + * restrictions on the construction of inner classes will mean null has to be passed and the + * actual delegator assigned later. + * + * @param type actual (Python) type of sub-class + * @param behaviour specific index behaviour (or null) + */ + protected PySequence(PyType type, SequenceIndexDelegate behaviour) { + super(type); + delegator = behaviour; } // These methods must be defined for any sequence @@ -451,7 +478,11 @@ return true; } - protected final SequenceIndexDelegate delegator = new SequenceIndexDelegate() { + /** + * Class defining the default behaviour of sequences with respect to slice assignment, etc., + * which is the one correct for list. + */ + protected class DefaultIndexDelegate extends SequenceIndexDelegate { @Override public String getTypeName() { diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java +++ b/src/org/python/core/PyString.java @@ -740,15 +740,19 @@ public PyObject __add__(PyObject other) { return str___add__(other); } - + @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.str___add___doc) final PyObject str___add__(PyObject other) { if (other instanceof PyUnicode) { return decode().__add__(other); - } - if (other instanceof PyString) { + + } else if (other instanceof PyString) { PyString otherStr = (PyString)other; return new PyString(getString().concat(otherStr.getString())); + + } else if (other instanceof PyByteArray) { + return new PyString(getString().concat(other.asString())); + } return null; } diff --git a/src/org/python/core/__builtin__.java b/src/org/python/core/__builtin__.java --- a/src/org/python/core/__builtin__.java +++ b/src/org/python/core/__builtin__.java @@ -64,10 +64,6 @@ case 2: return __builtin__.range(arg1); case 3: - if (!(arg1 instanceof PyString)) { - throw Py.TypeError("ord() expected string of length 1, but " + - arg1.getType().fastGetName() + " found"); - } return Py.newInteger(__builtin__.ord(arg1)); case 5: return __builtin__.hash(arg1); @@ -766,22 +762,48 @@ return o.__oct__(); } - public static final int ord(PyObject c) { + /** + * Built-in Python function ord() applicable to the string-like types str, + * bytearray, unicode. + * + * @param c string-like object of length 1 + * @return ordinal value of character or byte value in + * @throws PyException (TypeError) if not a string-like type + */ + public static final int ord(PyObject c) throws PyException { final int length; - PyString x = (PyString) c; - if (x instanceof PyUnicode) { - length = x.getString().codePointCount(0, x.getString().length()); + + if (c instanceof PyUnicode) { + String cu = ((PyUnicode)c).getString(); + length = cu.codePointCount(0, cu.length()); if (length == 1) { - return x.getString().codePointAt(0); + return cu.codePointAt(0); } + + } else if (c instanceof PyString) { + String cs = ((PyString)c).getString(); + length = cs.length(); + if (length == 1) { + return cs.charAt(0); + } + + } else if (c instanceof BaseBytes) { + BaseBytes cb = (BaseBytes)c; + length = cb.__len__(); + if (length == 1) { + return cb.intAt(0); + } + } else { - length = x.getString().length(); - if (length == 1) { - return x.getString().charAt(0); - } + // Not any of the acceptable types + throw Py.TypeError("ord() expected string of length 1, but " + + c.getType().fastGetName() + " found"); } - throw Py.TypeError("ord() expected a character, but string of length " + - length + " found"); + /* + * It was a qualifying string-like object, but if we didn't return or throw by now, the + * problem was the length. + */ + throw Py.TypeError("ord() expected a character, but string of length " + length + " found"); } public static PyObject pow(PyObject x, PyObject y) { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Tue Jul 24 20:03:07 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Tue, 24 Jul 2012 20:03:07 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Put_Java_import?= =?utf-8?q?_at_top_of_file_for_both_pep8_and_for_performance=2E?= Message-ID: <3WhS976LBXzPSg@mail.python.org> http://hg.python.org/jython/rev/f9ccaa02aa02 changeset: 6810:f9ccaa02aa02 branch: 2.5 parent: 6803:6ca8838410c2 user: Frank Wierzbicki date: Wed Jul 18 16:35:37 2012 -0700 summary: Put Java import at top of file for both pep8 and for performance. files: Lib/datetime.py | 104 +++++++++++----------- Lib/test/test_datetime_jy.py | 35 +++++++ 2 files changed, 85 insertions(+), 54 deletions(-) diff --git a/Lib/datetime.py b/Lib/datetime.py --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -18,6 +18,14 @@ import time as _time import math as _math +import sys as _sys + +if _sys.platform.startswith('java'): + from java.lang import Object + from java.sql import Date, Timestamp, Time + from java.util import Calendar + from org.python.core import Py + MINYEAR = 1 MAXYEAR = 9999 @@ -981,22 +989,18 @@ def __reduce__(self): return (self.__class__, self.__getstate()) - def __tojava__(self, java_class): - from java.lang import Object - from java.sql import Date - from java.util import Calendar - from org.python.core import Py + if _sys.platform.startswith('java'): + def __tojava__(self, java_class): + if java_class not in (Calendar, Date, Object): + return Py.NoConversion - if java_class not in (Calendar, Date, Object): - return Py.NoConversion - - calendar = Calendar.getInstance() - calendar.clear() - calendar.set(self.year, self.month - 1, self.day) - if java_class == Calendar: - return calendar - else: - return Date(calendar.getTimeInMillis()) + calendar = Calendar.getInstance() + calendar.clear() + calendar.set(self.year, self.month - 1, self.day) + if java_class == Calendar: + return calendar + else: + return Date(calendar.getTimeInMillis()) _date_class = date # so functions w/ args named "date" can get at the class @@ -1364,26 +1368,22 @@ def __reduce__(self): return (time, self.__getstate()) - def __tojava__(self, java_class): - # TODO, if self.tzinfo is not None, convert time to UTC - from java.lang import Object - from java.sql import Time - from java.util import Calendar - from org.python.core import Py + if _sys.platform.startswith('java'): + def __tojava__(self, java_class): + # TODO, if self.tzinfo is not None, convert time to UTC + if java_class not in (Calendar, Time, Object): + return Py.NoConversion - if java_class not in (Calendar, Time, Object): - return Py.NoConversion - - calendar = Calendar.getInstance() - calendar.clear() - calendar.set(Calendar.HOUR_OF_DAY, self.hour) - calendar.set(Calendar.MINUTE, self.minute) - calendar.set(Calendar.SECOND, self.second) - calendar.set(Calendar.MILLISECOND, self.microsecond // 1000) - if java_class == Calendar: - return calendar - else: - return Time(calendar.getTimeInMillis()) + calendar = Calendar.getInstance() + calendar.clear() + calendar.set(Calendar.HOUR_OF_DAY, self.hour) + calendar.set(Calendar.MINUTE, self.minute) + calendar.set(Calendar.SECOND, self.second) + calendar.set(Calendar.MILLISECOND, self.microsecond // 1000) + if java_class == Calendar: + return calendar + else: + return Time(calendar.getTimeInMillis()) _time_class = time # so functions w/ args named "time" can get at the class @@ -1839,28 +1839,24 @@ def __reduce__(self): return (self.__class__, self.__getstate()) - def __tojava__(self, java_class): - # TODO, if self.tzinfo is not None, convert time to UTC - from java.lang import Object - from java.sql import Timestamp - from java.util import Calendar - from org.python.core import Py + if _sys.platform.startswith('java'): + def __tojava__(self, java_class): + # TODO, if self.tzinfo is not None, convert time to UTC + if java_class not in (Calendar, Timestamp, Object): + return Py.NoConversion - if java_class not in (Calendar, Timestamp, Object): - return Py.NoConversion + calendar = Calendar.getInstance() + calendar.clear() + calendar.set(self.year, self.month - 1, self.day, + self.hour, self.minute, self.second) - calendar = Calendar.getInstance() - calendar.clear() - calendar.set(self.year, self.month - 1, self.day, - self.hour, self.minute, self.second) - - if java_class == Calendar: - calendar.set(Calendar.MILLISECOND, self.microsecond // 1000) - return calendar - else: - timestamp = Timestamp(calendar.getTimeInMillis()) - timestamp.setNanos(self.microsecond * 1000) - return timestamp + if java_class == Calendar: + calendar.set(Calendar.MILLISECOND, self.microsecond // 1000) + return calendar + else: + timestamp = Timestamp(calendar.getTimeInMillis()) + timestamp.setNanos(self.microsecond * 1000) + return timestamp datetime.min = datetime(1, 1, 1) diff --git a/Lib/test/test_datetime_jy.py b/Lib/test/test_datetime_jy.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_datetime_jy.py @@ -0,0 +1,35 @@ +import unittest +from test import test_support + +from datetime import timedelta +from datetime import tzinfo +from datetime import time +from datetime import date, datetime + +from java.util import Calendar +from java.sql import Date + + +class TestJavaDatetime(unittest.TestCase): + + def test_datetime(self): + self.assertTrue(hasattr(datetime, "__tojava__")) + x = datetime(2007, 1, 3) + y = x.__tojava__(Calendar) + self.assertTrue(isinstance(y, Calendar)) + + def test_date(self): + self.assertTrue(hasattr(date, "__tojava__")) + x = date(2007, 1, 3) + y = x.__tojava__(Calendar) + self.assertTrue(isinstance(y, Calendar)) + + def test_time(self): + self.assertTrue(hasattr(time, "__tojava__")) + x = time(1, 3) + y = x.__tojava__(Calendar) + self.assertTrue(isinstance(y, Calendar)) + + +if __name__ == '__main__': + unittest.main() -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Tue Jul 24 20:03:09 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Tue, 24 Jul 2012 20:03:09 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?q?=3A_Merge_2=2E5?= Message-ID: <3WhS993FmhzPYc@mail.python.org> http://hg.python.org/jython/rev/b38eb0998437 changeset: 6811:b38eb0998437 parent: 6804:bef3eb26155e parent: 6810:f9ccaa02aa02 user: Frank Wierzbicki date: Wed Jul 18 16:36:00 2012 -0700 summary: Merge 2.5 files: Lib/datetime.py | 104 +++++++++++----------- Lib/test/test_datetime_jy.py | 35 +++++++ 2 files changed, 85 insertions(+), 54 deletions(-) diff --git a/Lib/datetime.py b/Lib/datetime.py --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -18,6 +18,14 @@ import time as _time import math as _math +import sys as _sys + +if _sys.platform.startswith('java'): + from java.lang import Object + from java.sql import Date, Timestamp, Time + from java.util import Calendar + from org.python.core import Py + MINYEAR = 1 MAXYEAR = 9999 @@ -981,22 +989,18 @@ def __reduce__(self): return (self.__class__, self.__getstate()) - def __tojava__(self, java_class): - from java.lang import Object - from java.sql import Date - from java.util import Calendar - from org.python.core import Py + if _sys.platform.startswith('java'): + def __tojava__(self, java_class): + if java_class not in (Calendar, Date, Object): + return Py.NoConversion - if java_class not in (Calendar, Date, Object): - return Py.NoConversion - - calendar = Calendar.getInstance() - calendar.clear() - calendar.set(self.year, self.month - 1, self.day) - if java_class == Calendar: - return calendar - else: - return Date(calendar.getTimeInMillis()) + calendar = Calendar.getInstance() + calendar.clear() + calendar.set(self.year, self.month - 1, self.day) + if java_class == Calendar: + return calendar + else: + return Date(calendar.getTimeInMillis()) _date_class = date # so functions w/ args named "date" can get at the class @@ -1364,26 +1368,22 @@ def __reduce__(self): return (time, self.__getstate()) - def __tojava__(self, java_class): - # TODO, if self.tzinfo is not None, convert time to UTC - from java.lang import Object - from java.sql import Time - from java.util import Calendar - from org.python.core import Py + if _sys.platform.startswith('java'): + def __tojava__(self, java_class): + # TODO, if self.tzinfo is not None, convert time to UTC + if java_class not in (Calendar, Time, Object): + return Py.NoConversion - if java_class not in (Calendar, Time, Object): - return Py.NoConversion - - calendar = Calendar.getInstance() - calendar.clear() - calendar.set(Calendar.HOUR_OF_DAY, self.hour) - calendar.set(Calendar.MINUTE, self.minute) - calendar.set(Calendar.SECOND, self.second) - calendar.set(Calendar.MILLISECOND, self.microsecond // 1000) - if java_class == Calendar: - return calendar - else: - return Time(calendar.getTimeInMillis()) + calendar = Calendar.getInstance() + calendar.clear() + calendar.set(Calendar.HOUR_OF_DAY, self.hour) + calendar.set(Calendar.MINUTE, self.minute) + calendar.set(Calendar.SECOND, self.second) + calendar.set(Calendar.MILLISECOND, self.microsecond // 1000) + if java_class == Calendar: + return calendar + else: + return Time(calendar.getTimeInMillis()) _time_class = time # so functions w/ args named "time" can get at the class @@ -1839,28 +1839,24 @@ def __reduce__(self): return (self.__class__, self.__getstate()) - def __tojava__(self, java_class): - # TODO, if self.tzinfo is not None, convert time to UTC - from java.lang import Object - from java.sql import Timestamp - from java.util import Calendar - from org.python.core import Py + if _sys.platform.startswith('java'): + def __tojava__(self, java_class): + # TODO, if self.tzinfo is not None, convert time to UTC + if java_class not in (Calendar, Timestamp, Object): + return Py.NoConversion - if java_class not in (Calendar, Timestamp, Object): - return Py.NoConversion + calendar = Calendar.getInstance() + calendar.clear() + calendar.set(self.year, self.month - 1, self.day, + self.hour, self.minute, self.second) - calendar = Calendar.getInstance() - calendar.clear() - calendar.set(self.year, self.month - 1, self.day, - self.hour, self.minute, self.second) - - if java_class == Calendar: - calendar.set(Calendar.MILLISECOND, self.microsecond // 1000) - return calendar - else: - timestamp = Timestamp(calendar.getTimeInMillis()) - timestamp.setNanos(self.microsecond * 1000) - return timestamp + if java_class == Calendar: + calendar.set(Calendar.MILLISECOND, self.microsecond // 1000) + return calendar + else: + timestamp = Timestamp(calendar.getTimeInMillis()) + timestamp.setNanos(self.microsecond * 1000) + return timestamp datetime.min = datetime(1, 1, 1) diff --git a/Lib/test/test_datetime_jy.py b/Lib/test/test_datetime_jy.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_datetime_jy.py @@ -0,0 +1,35 @@ +import unittest +from test import test_support + +from datetime import timedelta +from datetime import tzinfo +from datetime import time +from datetime import date, datetime + +from java.util import Calendar +from java.sql import Date + + +class TestJavaDatetime(unittest.TestCase): + + def test_datetime(self): + self.assertTrue(hasattr(datetime, "__tojava__")) + x = datetime(2007, 1, 3) + y = x.__tojava__(Calendar) + self.assertTrue(isinstance(y, Calendar)) + + def test_date(self): + self.assertTrue(hasattr(date, "__tojava__")) + x = date(2007, 1, 3) + y = x.__tojava__(Calendar) + self.assertTrue(isinstance(y, Calendar)) + + def test_time(self): + self.assertTrue(hasattr(time, "__tojava__")) + x = time(1, 3) + y = x.__tojava__(Calendar) + self.assertTrue(isinstance(y, Calendar)) + + +if __name__ == '__main__': + unittest.main() -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Tue Jul 24 20:03:11 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Tue, 24 Jul 2012 20:03:11 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2Uu?= Message-ID: <3WhS9C28GLzPYx@mail.python.org> http://hg.python.org/jython/rev/f07e2fc66d62 changeset: 6812:f07e2fc66d62 parent: 6811:b38eb0998437 parent: 6809:546e63253a0e user: Frank Wierzbicki date: Sun Jul 22 11:39:49 2012 -0700 summary: Merge. files: src/org/python/core/BaseBytes.java | 91 +++++++++------ src/org/python/core/PyByteArray.java | 4 +- src/org/python/core/PyInteger.java | 85 ++++++++++---- src/org/python/core/PySequence.java | 33 +++++- src/org/python/core/PyString.java | 10 +- src/org/python/core/__builtin__.java | 52 ++++++-- 6 files changed, 190 insertions(+), 85 deletions(-) diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -41,7 +41,8 @@ * @param type explicit Jython type */ public BaseBytes(PyType type) { - super(type); // implicit setStorage( emptyStorage ); + super(type, null); + delegator = new IndexDelegate(); setStorage(emptyStorage); } @@ -52,7 +53,8 @@ * @param type explicit Jython type */ public BaseBytes(PyType type, int size) { - super(type); + super(type, null); + delegator = new IndexDelegate(); newStorage(size); } @@ -63,7 +65,8 @@ * @param value source of values (and size) */ public BaseBytes(PyType type, int[] value) { - super(type); + super(type, null); + delegator = new IndexDelegate(); int n = value.length; newStorage(n); for (int i = offset, j = 0; j < n; i++, j++) { @@ -80,7 +83,8 @@ * @throws PyException if any value[i] > 255 */ protected BaseBytes(PyType type, String value) throws PyException { - super(type); + super(type, null); + delegator = new IndexDelegate(); int n = value.length(); newStorage(n); for (int i = offset, j = 0; j < n; j++) { @@ -1127,6 +1131,38 @@ return getslice(start, stop, 1); } + /** + * Class defining the behaviour of bytearray with respect to slice assignment, etc., which + * differs from the default (list) behaviour in small ways. + */ + private class IndexDelegate extends PySequence.DefaultIndexDelegate { + + /* + * bytearray treats assignment of a zero-length object to a slice as equivalent to deletion, + * unlike list, even for an extended slice. + */ + // >>> a = range(10) + // >>> b = bytearray(a) + // >>> a[1:6:2] = [] + // Traceback (most recent call last): + // File "", line 1, in + // ValueError: attempt to assign sequence of size 0 to extended slice of size 3 + // >>> b[1:6:2] = [] + // >>> b + // bytearray(b'\x00\x02\x04\x06\x07\x08\t') + // + @Override + public void checkIdxAndSetSlice(PySlice slice, PyObject value) { + if (value.__len__() != 0) { + // Proceed as default + super.checkIdxAndSetSlice(slice, value); + } else { + // Treat as deletion + super.checkIdxAndDelItem(slice); + } + } + }; + /* * ============================================================================================ * Support for Python API common to mutable and immutable subclasses @@ -1479,18 +1515,21 @@ } /** - * Copy the bytes of a byte array to the characters of a String with no change in ordinal value. - * This could also be described as 'latin-1' decoding of the byte array to a String. - * - * @return the byte array as a String, still encoded + * Present the bytes of a byte array, with no decoding, as a Java String. The bytes are treated + * as unsigned character codes, and copied to the to the characters of a String with no change + * in ordinal value. This could also be described as 'latin-1' or 'ISO-8859-1' decoding of the + * byte array to a String, since this character encoding is numerically equal to Unicode. + * + * @return the byte array as a String */ - private synchronized String asEncodedString() { - StringBuilder buf = new StringBuilder(size); - int jmax = offset + size; - for (int j = offset; j < jmax; j++) { - buf.append((char)(0xff & storage[j])); + @Override + public synchronized String asString() { + char[] buf = new char[size]; + int j = offset + size; + for (int i = size; --i >= 0;) { + buf[i] = (char)(0xff & storage[--j]); } - return buf.toString(); + return new String(buf); } /** @@ -1530,7 +1569,7 @@ * expects a PyString. (In Python 3k the codecs decode from the bytes type, so * we can pass this directly.) */ - PyString this_ = new PyString(this.asEncodedString()); + PyString this_ = new PyString(this.asString()); return codecs.decode(this_, encoding, errors); } @@ -1578,7 +1617,7 @@ * @return required tuple of type, arguments needed by init, and any user-added attributes. */ final PyTuple basebytes___reduce__() { - PyUnicode encoded = new PyUnicode(this.asEncodedString()); + PyUnicode encoded = new PyUnicode(this.asString()); PyObject args = new PyTuple(encoded, getPickleEncoding()); PyObject dict = __findattr__("__dict__"); return new PyTuple(getType(), args, (dict != null) ? dict : Py.None); @@ -3964,26 +4003,6 @@ return buf.toString(); } - /** - * Ready-to-expose Python __str__(), returning a PyString by treating - * the bytes as point codes. The built-in function str() is expected to call this - * method. - */ - final synchronized PyString basebytes_str() { - // Get hold of the decoder for ISO-8859-1, which is one-for-one with Unicode - if (defaultCharset == null) { - defaultCharset = Charset.forName("ISO-8859-1"); - } - String s = new String(storage, offset, size, defaultCharset); - return new PyString(s); - } - - /** - * Used in {@link #basebytes_str()}, and when not null, points to the identity Charset for - * decoding bytes to char. - */ - private static Charset defaultCharset; - /* * ============================================================================================ * API for java.util.List diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java --- a/src/org/python/core/PyByteArray.java +++ b/src/org/python/core/PyByteArray.java @@ -1932,12 +1932,12 @@ */ @Override public PyString __str__() { - return basebytes_str(); + return bytearray_str(); } @ExposedMethod(names = {"__str__"}, doc = BuiltinDocs.bytearray___str___doc) final PyString bytearray_str() { - return basebytes_str(); + return new PyString(this.asString()); } /** diff --git a/src/org/python/core/PyInteger.java b/src/org/python/core/PyInteger.java --- a/src/org/python/core/PyInteger.java +++ b/src/org/python/core/PyInteger.java @@ -52,75 +52,104 @@ @ExposedNew public static PyObject int_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("int", args, keywords, new String[] {"x", "base"}, 0); PyObject x = ap.getPyObject(0, null); int base = ap.getInt(1, -909); - if (new_.for_type == subtype) { + + if (new_.for_type == subtype) { // A substantive PyInteger is required as the return value + if (x == null) { return Py.Zero; - } - if (base == -909) { + + } else if (base == -909) { if (x instanceof PyBoolean) { return (coerce(x) == 0) ? Py.Zero : Py.One; + } else if (x instanceof PyByteArray) { + // Make use of the string to int conversion in PyString + PyString xs = new PyString(x.asString()); + return asPyInteger(xs); + } else { + return asPyInteger(x); } - return asPyInteger(x); - } - if (!(x instanceof PyString)) { + } else if (!(x instanceof PyString)) { throw Py.TypeError("int: can't convert non-string with explicit base"); } + try { - return Py.newInteger(((PyString) x).atoi(base)); + return Py.newInteger(((PyString)x).atoi(base)); } catch (PyException pye) { if (pye.match(Py.OverflowError)) { - return ((PyString) x).atol(base); + return ((PyString)x).atol(base); } throw pye; } - } else { + + } else { // A PyIntegerDerived(subtype, ... ) is required as the return value + if (x == null) { return new PyIntegerDerived(subtype, 0); - } - if (base == -909) { + } else if (base == -909) { PyObject intOrLong = asPyInteger(x); + if (intOrLong instanceof PyInteger) { - return new PyIntegerDerived(subtype, ((PyInteger) intOrLong).getValue()); + return new PyIntegerDerived(subtype, ((PyInteger)intOrLong).getValue()); } else { throw Py.OverflowError("long int too large to convert to int"); } - } - if (!(x instanceof PyString)) { + + } else if (!(x instanceof PyString)) { throw Py.TypeError("int: can't convert non-string with explicit base"); } - return new PyIntegerDerived(subtype, ((PyString) x).atoi(base)); + + return new PyIntegerDerived(subtype, ((PyString)x).atoi(base)); } } // xxx /** - * @return convert to an int. - * @throws TypeError and AttributeError. + * Convert all sorts of object types to either PyInteger or PyLong, + * using their {@link PyObject#__int__()} method, whether exposed or not, or if that raises an + * exception (as the base PyObject one does), using any __trunc__() + * the type may have exposed. If all this fails, this method raises an exception. Equivalent to CPython + * PyNumber_Int(). + * + * @param x to convert to an int + * @return int or long result. + * @throws PyException (TypeError) if no method of conversion can be found + * @throws PyException (AttributeError) if neither __int__ nor __trunc__ found (?) */ - private static PyObject asPyInteger(PyObject x) { - //XXX: Not sure that this perfectly matches CPython semantics. + private static PyObject asPyInteger(PyObject x) throws PyException { + // XXX: Not sure that this perfectly matches CPython semantics. try { + // Try the object itself (raises AttributeError if not overridden from PyObject) return x.__int__(); + } catch (PyException pye) { if (!pye.match(Py.AttributeError)) { + // x had an __int__ method, but something else went wrong: pass it on throw pye; - } - try { - PyObject integral = x.invoke("__trunc__"); - return convertIntegralToInt(integral); - } catch (PyException pye2) { - if (!pye2.match(Py.AttributeError)) { - throw pye2; + + } else { + // x did not have an __int__ method, but maybe __trunc__ will work + try { + PyObject integral = x.invoke("__trunc__"); + return convertIntegralToInt(integral); + + } catch (PyException pye2) { + if (!pye2.match(Py.AttributeError)) { + throw pye2; + } + String fmt = "int() argument must be a string or a number, not '%.200s'"; + throw Py.TypeError(String.format(fmt, x)); } - throw Py.TypeError( - String.format("int() argument must be a string or a number, not '%.200s'", x)); } } } /** + * Helper called on whatever exposed method __trunc__ returned: it may be + * int, long or something with an exposed __int__. + * * @return convert to an int. * @throws TypeError and AttributeError. */ diff --git a/src/org/python/core/PySequence.java b/src/org/python/core/PySequence.java --- a/src/org/python/core/PySequence.java +++ b/src/org/python/core/PySequence.java @@ -14,8 +14,35 @@ */ public abstract class PySequence extends PyObject { + /** + * A delegate that handles index checking and manipulation for get, set and del operations on + * this sequence in the form of a "pluggable behaviour". Because different types of sequence + * exhibit subtly different behaviour, there is scope for subclasses to customise the behaviour + * with their own extension of SequenceIndexDelegate. + */ + protected SequenceIndexDelegate delegator; + + /** + * Construct a PySequence for the given sub-type with the default index behaviour. + * + * @param type actual (Python) type of sub-class + */ protected PySequence(PyType type) { super(type); + delegator = new DefaultIndexDelegate(); + } + + /** + * Construct a PySequence for the given sub-type with custom index behaviour. In practice, + * restrictions on the construction of inner classes will mean null has to be passed and the + * actual delegator assigned later. + * + * @param type actual (Python) type of sub-class + * @param behaviour specific index behaviour (or null) + */ + protected PySequence(PyType type, SequenceIndexDelegate behaviour) { + super(type); + delegator = behaviour; } // These methods must be defined for any sequence @@ -451,7 +478,11 @@ return true; } - protected final SequenceIndexDelegate delegator = new SequenceIndexDelegate() { + /** + * Class defining the default behaviour of sequences with respect to slice assignment, etc., + * which is the one correct for list. + */ + protected class DefaultIndexDelegate extends SequenceIndexDelegate { @Override public String getTypeName() { diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java +++ b/src/org/python/core/PyString.java @@ -740,15 +740,19 @@ public PyObject __add__(PyObject other) { return str___add__(other); } - + @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.str___add___doc) final PyObject str___add__(PyObject other) { if (other instanceof PyUnicode) { return decode().__add__(other); - } - if (other instanceof PyString) { + + } else if (other instanceof PyString) { PyString otherStr = (PyString)other; return new PyString(getString().concat(otherStr.getString())); + + } else if (other instanceof PyByteArray) { + return new PyString(getString().concat(other.asString())); + } return null; } diff --git a/src/org/python/core/__builtin__.java b/src/org/python/core/__builtin__.java --- a/src/org/python/core/__builtin__.java +++ b/src/org/python/core/__builtin__.java @@ -64,10 +64,6 @@ case 2: return __builtin__.range(arg1); case 3: - if (!(arg1 instanceof PyString)) { - throw Py.TypeError("ord() expected string of length 1, but " + - arg1.getType().fastGetName() + " found"); - } return Py.newInteger(__builtin__.ord(arg1)); case 5: return __builtin__.hash(arg1); @@ -766,22 +762,48 @@ return o.__oct__(); } - public static final int ord(PyObject c) { + /** + * Built-in Python function ord() applicable to the string-like types str, + * bytearray, unicode. + * + * @param c string-like object of length 1 + * @return ordinal value of character or byte value in + * @throws PyException (TypeError) if not a string-like type + */ + public static final int ord(PyObject c) throws PyException { final int length; - PyString x = (PyString) c; - if (x instanceof PyUnicode) { - length = x.getString().codePointCount(0, x.getString().length()); + + if (c instanceof PyUnicode) { + String cu = ((PyUnicode)c).getString(); + length = cu.codePointCount(0, cu.length()); if (length == 1) { - return x.getString().codePointAt(0); + return cu.codePointAt(0); } + + } else if (c instanceof PyString) { + String cs = ((PyString)c).getString(); + length = cs.length(); + if (length == 1) { + return cs.charAt(0); + } + + } else if (c instanceof BaseBytes) { + BaseBytes cb = (BaseBytes)c; + length = cb.__len__(); + if (length == 1) { + return cb.intAt(0); + } + } else { - length = x.getString().length(); - if (length == 1) { - return x.getString().charAt(0); - } + // Not any of the acceptable types + throw Py.TypeError("ord() expected string of length 1, but " + + c.getType().fastGetName() + " found"); } - throw Py.TypeError("ord() expected a character, but string of length " + - length + " found"); + /* + * It was a qualifying string-like object, but if we didn't return or throw by now, the + * problem was the length. + */ + throw Py.TypeError("ord() expected a character, but string of length " + length + " found"); } public static PyObject pow(PyObject x, PyObject y) { -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 27 23:27:45 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 27 Jul 2012 23:27:45 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Move_java_impor?= =?utf-8?q?ts_out_of_functions_for_pep8_and_perf=2E?= Message-ID: <3WkNYs3ZvZzPLx@mail.python.org> http://hg.python.org/jython/rev/005b97117ae9 changeset: 6813:005b97117ae9 branch: 2.5 parent: 6810:f9ccaa02aa02 user: Frank Wierzbicki date: Fri Jul 27 14:00:25 2012 -0700 summary: Move java imports out of functions for pep8 and perf. files: Lib/decimal.py | 8 ++++++++ Lib/isql.py | 6 ++++-- Lib/platform.py | 6 ++++-- Lib/test/test_decimal_jy.py | 19 +++++++++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Lib/decimal.py b/Lib/decimal.py --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -392,6 +392,14 @@ del sys, MockThreading try: + from java.lang import Object + from java.math import BigDecimal + from org.python.core import Py +except ImportError: + #Not Jython, ignore. + pass + +try: threading.local except AttributeError: diff --git a/Lib/isql.py b/Lib/isql.py --- a/Lib/isql.py +++ b/Lib/isql.py @@ -1,5 +1,8 @@ import dbexts, cmd, sys, os +if sys.platform.startswith("java"): + import java.lang.String + """ Isql works in conjunction with dbexts to provide an interactive environment for database work. @@ -24,9 +27,8 @@ if len(self.isql.sqlbuffer) > 0: prompt = "... " return prompt - if os.name == 'java': + if sys.platform.startswith("java"): def __tojava__(self, cls): - import java.lang.String if cls == java.lang.String: return self.__str__() return False diff --git a/Lib/platform.py b/Lib/platform.py --- a/Lib/platform.py +++ b/Lib/platform.py @@ -111,6 +111,10 @@ import sys,string,os,re +if sys.platform.startswith("java"): + from java.lang import System + from org.python.core.Py import newString + ### Platform specific APIs _libc_search = re.compile(r'(__libc_init)' @@ -623,8 +627,6 @@ def _java_getprop(name,default): - from java.lang import System - from org.python.core.Py import newString try: return newString(System.getProperty(name)) except: diff --git a/Lib/test/test_decimal_jy.py b/Lib/test/test_decimal_jy.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_decimal_jy.py @@ -0,0 +1,19 @@ +import unittest +from test import test_support + +from decimal import Decimal + +from java.math import BigDecimal + + +class TestJavaDecimal(unittest.TestCase): + + def test_decimal(self): + self.assertTrue(hasattr(Decimal, "__tojava__")) + x = Decimal("1.1") + y = x.__tojava__(BigDecimal) + self.assertTrue(isinstance(y, BigDecimal)) + + +if __name__ == '__main__': + unittest.main() -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 27 23:27:46 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 27 Jul 2012 23:27:46 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?b?OiBNZXJnZSAyLjUu?= Message-ID: <3WkNYt6BTYzPMR@mail.python.org> http://hg.python.org/jython/rev/d0b31f06f111 changeset: 6814:d0b31f06f111 parent: 6812:f07e2fc66d62 parent: 6813:005b97117ae9 user: Frank Wierzbicki date: Fri Jul 27 14:27:37 2012 -0700 summary: Merge 2.5. files: Lib/decimal.py | 8 ++++++++ Lib/isql.py | 6 ++++-- Lib/platform.py | 6 ++++-- Lib/test/test_decimal_jy.py | 19 +++++++++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Lib/decimal.py b/Lib/decimal.py --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -402,6 +402,14 @@ del sys, MockThreading try: + from java.lang import Object + from java.math import BigDecimal + from org.python.core import Py +except ImportError: + #Not Jython, ignore. + pass + +try: threading.local except AttributeError: diff --git a/Lib/isql.py b/Lib/isql.py --- a/Lib/isql.py +++ b/Lib/isql.py @@ -1,5 +1,8 @@ import dbexts, cmd, sys, os +if sys.platform.startswith("java"): + import java.lang.String + """ Isql works in conjunction with dbexts to provide an interactive environment for database work. @@ -22,9 +25,8 @@ if len(self.isql.sqlbuffer) > 0: prompt = "... " return prompt - if os.name == 'java': + if sys.platform.startswith("java"): def __tojava__(self, cls): - import java.lang.String if cls == java.lang.String: return self.__str__() return False diff --git a/Lib/platform.py b/Lib/platform.py --- a/Lib/platform.py +++ b/Lib/platform.py @@ -114,6 +114,10 @@ import sys,string,os,re +if sys.platform.startswith("java"): + from java.lang import System + from org.python.core.Py import newString + ### Platform specific APIs _libc_search = re.compile(r'(__libc_init)' @@ -805,8 +809,6 @@ def _java_getprop(name,default): - from java.lang import System - from org.python.core.Py import newString try: value = System.getProperty(name) if value is None: diff --git a/Lib/test/test_decimal_jy.py b/Lib/test/test_decimal_jy.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_decimal_jy.py @@ -0,0 +1,19 @@ +import unittest +from test import test_support + +from decimal import Decimal + +from java.math import BigDecimal + + +class TestJavaDecimal(unittest.TestCase): + + def test_decimal(self): + self.assertTrue(hasattr(Decimal, "__tojava__")) + x = Decimal("1.1") + y = x.__tojava__(BigDecimal) + self.assertTrue(isinstance(y, BigDecimal)) + + +if __name__ == '__main__': + unittest.main() -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 27 23:57:18 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 27 Jul 2012 23:57:18 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=282=2E5=29=3A_Remove_java_imp?= =?utf-8?q?orts_from_func_bodies_for_pep8_and_perf=2E?= Message-ID: <3WkPCy6GB8zPMR@mail.python.org> http://hg.python.org/jython/rev/18db8d13c227 changeset: 6815:18db8d13c227 branch: 2.5 parent: 6813:005b97117ae9 user: Frank Wierzbicki date: Fri Jul 27 14:48:44 2012 -0700 summary: Remove java imports from func bodies for pep8 and perf. files: Lib/decimal.py | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/Lib/decimal.py b/Lib/decimal.py --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -3340,9 +3340,6 @@ # support for Jython __tojava__: def __tojava__(self, java_class): - from java.lang import Object - from java.math import BigDecimal - from org.python.core import Py if java_class not in (BigDecimal, Object): return Py.NoConversion return BigDecimal(str(self)) -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Fri Jul 27 23:57:20 2012 From: jython-checkins at python.org (frank.wierzbicki) Date: Fri, 27 Jul 2012 23:57:20 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython_=28merge_2=2E5_-=3E_default=29?= =?utf-8?q?=3A_Merge_with_2=2E5=2E?= Message-ID: <3WkPD01Y64zPMR@mail.python.org> http://hg.python.org/jython/rev/43ea9699b54d changeset: 6816:43ea9699b54d parent: 6814:d0b31f06f111 parent: 6815:18db8d13c227 user: Frank Wierzbicki date: Fri Jul 27 14:57:11 2012 -0700 summary: Merge with 2.5. files: Lib/decimal.py | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Lib/decimal.py b/Lib/decimal.py --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -3689,6 +3689,12 @@ # of the formatting to the _format_number function return _format_number(self._sign, intpart, fracpart, exp, spec) + # support for Jython __tojava__: + def __tojava__(self, java_class): + if java_class not in (BigDecimal, Object): + return Py.NoConversion + return BigDecimal(str(self)) + def _dec_from_triple(sign, coefficient, exponent, special=False): """Create a decimal instance directly, without any validation, normalization (e.g. removal of leading zeros) or argument -- Repository URL: http://hg.python.org/jython