Revision: 3864
http://jython.svn.sourceforge.net/jython/?rev=3864&view=rev
Author: zyasoft
Date: 2007-12-24 17:31:13 -0800 (Mon, 24 Dec 2007)
Log Message:
-----------
Resolved conflicts. Now supports using ConcurrentHashMap as the underlying map for PyDictionary, PyStringMap. (This was forced by a pattern of usage of how iteration - and deletion - is different between Python and Java. CHM makes this possible.) However, this does introduce the following: there is no stable ordering on keys, items, values and iter equivalents. Certain tests depend on this, but that of course is silly. In addition, test_mutants and test_hmac both have more serious issues. The Machiavelli test seems pathological, so I will worry about that later. hmac is dependent on the ClassDictInit pattern of usage; that's currently causing an NPE. Lastly, the new Java <=> PyDictionary mapping on EntrySet, etc., is also experiencing some issues where the mapping is not complete. This may be a subtle reentrancy issue. In any event CHM seems to be like the best choice, if we can work around these last issues.
Modified Paths:
--------------
branches/modern/src/org/python/core/PyDictionary.java
branches/modern/src/org/python/core/PyList.java
branches/modern/src/org/python/core/PyStringMap.java
branches/modern/src/org/python/core/__builtin__.java
Modified: branches/modern/src/org/python/core/PyDictionary.java
===================================================================
--- branches/modern/src/org/python/core/PyDictionary.java 2007-12-24 19:36:03 UTC (rev 3863)
+++ branches/modern/src/org/python/core/PyDictionary.java 2007-12-25 01:31:13 UTC (rev 3864)
@@ -4,8 +4,7 @@
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -594,7 +593,7 @@
* Create an empty dictionary.
*/
public PyDictionary() {
- this(Collections.synchronizedMap(new HashMap()));
+ this(new ConcurrentHashMap());
}
/**
@@ -603,7 +602,7 @@
*/
public PyDictionary(PyType subtype) {
super(subtype);
- table = Collections.synchronizedMap(new HashMap());
+ table = new ConcurrentHashMap();
}
/**
@@ -612,7 +611,7 @@
* is and must only contain PyObject key:value pairs.
*/
public PyDictionary(Map t) {
- table = Collections.synchronizedMap(new HashMap(t));
+ table = new ConcurrentHashMap(t);
}
/**
@@ -766,14 +765,13 @@
}
StringBuffer buf = new StringBuffer("{");
- synchronized(table) {
- for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry)it.next();
- buf.append(((PyObject)entry.getKey()).__repr__().toString());
- buf.append(": ");
- buf.append(((PyObject)entry.getValue()).__repr__().toString());
- buf.append(", ");
- }
+
+ for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
+ Entry entry = (Entry)it.next();
+ buf.append(((PyObject)entry.getKey()).__repr__().toString());
+ buf.append(": ");
+ buf.append(((PyObject)entry.getValue()).__repr__().toString());
+ buf.append(", ");
}
if(buf.length() > 1){
buf.delete(buf.length() - 2, buf.length());
@@ -1057,15 +1055,14 @@
}
final PyObject dict_popitem() {
- synchronized(table) {
- Iterator it = table.entrySet().iterator();
- if (!it.hasNext())
- throw Py.KeyError("popitem(): dictionary is empty");
- Map.Entry entry = (Map.Entry)it.next();
- it.remove();
- return new PyTuple(new PyObject[]
- { (PyObject)entry.getKey(), (PyObject)entry.getValue() });
- }
+ Iterator it = table.entrySet().iterator();
+ if (!it.hasNext())
+ throw Py.KeyError("popitem(): dictionary is empty");
+ Entry entry = (Entry)it.next();
+ PyTuple tuple = new PyTuple(
+ (PyObject)entry.getKey(), (PyObject)entry.getValue());
+ it.remove();
+ return tuple;
}
/**
@@ -1077,16 +1074,13 @@
}
final PyList dict_items() {
- List lst = null;
- synchronized(table) {
- lst = new ArrayList(table.size());
- for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry)it.next();
- lst.add(new PyTuple(new PyObject[]
- { (PyObject)entry.getKey(), (PyObject)entry.getValue() }));
- }
+ List list = new ArrayList(table.size());
+ for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
+ Entry entry = (Entry)it.next();
+ list.add(new PyTuple(
+ (PyObject)entry.getKey(), (PyObject)entry.getValue() ));
}
- return new PyList(lst);
+ return new PyList(list);
}
/**
@@ -1112,7 +1106,7 @@
}
final PyObject dict_iteritems() {
- return new PDEntriesIter(table.entrySet());
+ return new ItemsIter(table.entrySet());
}
/**
@@ -1123,7 +1117,7 @@
}
final PyObject dict_iterkeys() {
- return new PDCollectionIter(table.keySet());
+ return new ValuesIter(table.keySet());
}
/**
@@ -1134,7 +1128,7 @@
}
final PyObject dict_itervalues() {
- return new PDCollectionIter(table.values());
+ return new ValuesIter(table.values());
}
public int hashCode() {
@@ -1149,10 +1143,9 @@
return false;
}
- // just a lightweight wrapper for now...
- class PDCollectionIter extends PyIterator {
+ class ValuesIter extends PyIterator {
private final Iterator iterator;
- public PDCollectionIter(Collection c) {
+ public ValuesIter(Collection c) {
this.iterator = c.iterator();
}
@@ -1163,16 +1156,16 @@
}
}
- class PDEntriesIter extends PyIterator {
+ class ItemsIter extends PyIterator {
private Iterator iterator;
- public PDEntriesIter(Set s) {
+ public ItemsIter(Set s) {
this.iterator = s.iterator();
}
public PyObject __iternext__() {
if (!iterator.hasNext())
return null;
- Map.Entry entry = (Map.Entry)iterator.next();
+ Entry entry = (Entry)iterator.next();
return new PyTuple(new PyObject[]
{ (PyObject)entry.getKey(), (PyObject)entry.getValue() });
}
@@ -1205,7 +1198,7 @@
public void putAll(Map map) {
Iterator i = map.entrySet().iterator();
while (i.hasNext()) {
- Map.Entry entry = (Map.Entry)i.next();
+ Entry entry = (Entry)i.next();
table.put(Py.java2py(entry.getKey()), Py.java2py(entry.getValue()));
}
}
@@ -1252,26 +1245,26 @@
}
/**
- * Wrapper for a Map.Entry object returned from the java.util.Set
+ * Wrapper for a Entry object returned from the java.util.Set
* object which in turn is returned by the entrySet method of
* java.util.Map. This is needed to correctly convert from PyObjects
* to java Objects. Note that we take care in the equals and hashCode
- * methods to make sure these methods are consistent with Map.Entry
+ * methods to make sure these methods are consistent with Entry
* objects that contain java Objects for a value so that on the java
* side they can be reliable compared.
*/
-class PyToJavaMapEntry implements Map.Entry {
+class PyToJavaMapEntry implements Entry {
- private Map.Entry entry;
+ private Entry entry;
- /** Create a copy of the Map.Entry with Py.None coverted to null */
- PyToJavaMapEntry(Map.Entry entry) {
+ /** Create a copy of the Entry with Py.None coverted to null */
+ PyToJavaMapEntry(Entry entry) {
this.entry = entry;
}
public boolean equals(Object o) {
- if (o == null || !(o instanceof Map.Entry)) return false;
- Map.Entry me = new JavaToPyMapEntry((Map.Entry)o);
+ if (o == null || !(o instanceof Entry)) return false;
+ Entry me = new JavaToPyMapEntry((Entry)o);
return o.equals(me);
}
@@ -1284,7 +1277,7 @@
}
public int hashCode() {
- // formula for the hash code is taken from the Map.Entry documentation.
+ // formula for the hash code is taken from the Entry documentation.
// Given the source we assume that key is not null.
Object val = entry.getValue();
return getKey().hashCode() ^ (val == null ? 0 : val.hashCode());
@@ -1294,7 +1287,7 @@
return entry.setValue(Py.java2py(value));
}
- public Map.Entry getEntry() {
+ public Entry getEntry() {
return entry;
}
@@ -1306,19 +1299,19 @@
* PyDictionary. Essentially like PyTojavaMapEntry, but going the
* other way converting java Objects to PyObjects.
*/
-class JavaToPyMapEntry implements Map.Entry {
+class JavaToPyMapEntry implements Entry {
private PyObject key;
private PyObject val;
- public JavaToPyMapEntry(Map.Entry entry) {
+ public JavaToPyMapEntry(Entry entry) {
this.key = Py.java2py(entry.getKey());
this.val = Py.java2py(entry.getValue());
}
public boolean equals(Object o) {
- if (o == null || !(o instanceof Map.Entry)) return false;
- Map.Entry oe = (Map.Entry)o;
- // The objects comming in will always be a Map.Entry from a
+ if (o == null || !(o instanceof Entry)) return false;
+ Entry oe = (Entry)o;
+ // The objects comming in will always be a Entry from a
// PyDictionary, so getKey and getValue will always be PyObjects
return oe.getKey().equals(key) && oe.getValue().equals(val);
}
@@ -1361,13 +1354,13 @@
}
/**
- * Set wrapper for the java.util.Map.entrySet method. Map.Entry
+ * Set wrapper for the java.util.EntrySet method. Entry
* objects are wrapped further in JavaToPyMapEntry and
* PyToJavaMapEntry. Note - The set interface is reliable for
* standard objects like strings and integers, but may be inconstant
* for other types of objects since the equals method may return false
- * for Map.Entry object that hold more elaborate PyObject types.
- * However, We insure that this iterface works when the Map.Entry
+ * for Entry object that hold more elaborate PyObject types.
+ * However, We insure that this iterface works when the Entry
* object originates from a Set object retrieved from a PyDictionary.
*/
class PyMapEntrySet extends PyMapSet {
@@ -1376,20 +1369,20 @@
super(coll);
}
- // We know that PyMapEntrySet will only contains Map.Entrys, so
- // if the object being passed in is null or not a Map.Entry, then
+ // We know that PyMapEntrySet will only contains Entrys, so
+ // if the object being passed in is null or not a Entry, then
// return null which will match nothing for remove and contains methods.
Object toPython(Object o) {
- if (o == null || !(o instanceof Map.Entry)) return null;
+ if (o == null || !(o instanceof Entry)) return null;
if (o instanceof PyToJavaMapEntry)
// Use the original entry from PyDictionary
return ((PyToJavaMapEntry)o).getEntry();
else
- return new JavaToPyMapEntry((Map.Entry)o);
+ return new JavaToPyMapEntry((Entry)o);
}
Object toJava(Object o) {
- return new PyToJavaMapEntry((Map.Entry)o);
+ return new PyToJavaMapEntry((Entry)o);
}
}
Modified: branches/modern/src/org/python/core/PyList.java
===================================================================
--- branches/modern/src/org/python/core/PyList.java 2007-12-24 19:36:03 UTC (rev 3863)
+++ branches/modern/src/org/python/core/PyList.java 2007-12-25 01:31:13 UTC (rev 3864)
@@ -6,7 +6,6 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import java.util.Vector;
/**
* A builtin python list.
@@ -283,6 +282,82 @@
}
dict.__setitem__("__setslice__",new PyMethodDescr("__setslice__",PyList.class,3,4,new exposed___setslice__(null,null)));
+ class exposed___add__ extends PyBuiltinMethodNarrow {
+
+ exposed___add__(PyObject self,PyBuiltinFunction.Info info) {
+ super(self,info);
+ }
+
+ public PyBuiltinFunction bind(PyObject self) {
+ return new exposed___add__(self,info);
+ }
+
+ public PyObject __call__(PyObject arg0) {
+ PyObject ret=((PyList)self).list___add__(arg0);
+ if (ret==null)
+ return Py.NotImplemented;
+ return ret;
+ }
+
+ }
+ dict.__setitem__("__add__",new PyMethodDescr("__add__",PyList.class,1,1,new exposed___add__(null,null)));
+ class exposed___radd__ extends PyBuiltinMethodNarrow {
+
+ exposed___radd__(PyObject self,PyBuiltinFunction.Info info) {
+ super(self,info);
+ }
+
+ public PyBuiltinFunction bind(PyObject self) {
+ return new exposed___radd__(self,info);
+ }
+
+ public PyObject __call__(PyObject arg0) {
+ PyObject ret=((PyList)self).list___radd__(arg0);
+ if (ret==null)
+ return Py.NotImplemented;
+ return ret;
+ }
+
+ }
+ dict.__setitem__("__radd__",new PyMethodDescr("__radd__",PyList.class,1,1,new exposed___radd__(null,null)));
+ class exposed___mul__ extends PyBuiltinMethodNarrow {
+
+ exposed___mul__(PyObject self,PyBuiltinFunction.Info info) {
+ super(self,info);
+ }
+
+ public PyBuiltinFunction bind(PyObject self) {
+ return new exposed___mul__(self,info);
+ }
+
+ public PyObject __call__(PyObject arg0) {
+ PyObject ret=((PyList)self).list___mul__(arg0);
+ if (ret==null)
+ return Py.NotImplemented;
+ return ret;
+ }
+
+ }
+ dict.__setitem__("__mul__",new PyMethodDescr("__mul__",PyList.class,1,1,new exposed___mul__(null,null)));
+ class exposed___rmul__ extends PyBuiltinMethodNarrow {
+
+ exposed___rmul__(PyObject self,PyBuiltinFunction.Info info) {
+ super(self,info);
+ }
+
+ public PyBuiltinFunction bind(PyObject self) {
+ return new exposed___rmul__(self,info);
+ }
+
+ public PyObject __call__(PyObject arg0) {
+ PyObject ret=((PyList)self).list___rmul__(arg0);
+ if (ret==null)
+ return Py.NotImplemented;
+ return ret;
+ }
+
+ }
+ dict.__setitem__("__rmul__",new PyMethodDescr("__rmul__",PyList.class,1,1,new exposed___rmul__(null,null)));
class exposed_append extends PyBuiltinMethodNarrow {
exposed_append(PyObject self,PyBuiltinFunction.Info info) {
@@ -515,38 +590,6 @@
}
dict.__setitem__("__len__",new PyMethodDescr("__len__",PyList.class,0,0,new exposed___len__(null,null)));
- class exposed___add__ extends PyBuiltinMethodNarrow {
-
- exposed___add__(PyObject self,PyBuiltinFunction.Info info) {
- super(self,info);
- }
-
- public PyBuiltinFunction bind(PyObject self) {
- return new exposed___add__(self,info);
- }
-
- public PyObject __call__(PyObject arg0) {
- return((PyList)self).list___add__(arg0);
- }
-
- }
- dict.__setitem__("__add__",new PyMethodDescr("__add__",PyList.class,1,1,new exposed___add__(null,null)));
- class exposed___radd__ extends PyBuiltinMethodNarrow {
-
- exposed___radd__(PyObject self,PyBuiltinFunction.Info info) {
- super(self,info);
- }
-
- public PyBuiltinFunction bind(PyObject self) {
- return new exposed___radd__(self,info);
- }
-
- public PyObject __call__(PyObject arg0) {
- return((PyList)self).list___radd__(arg0);
- }
-
- }
- dict.__setitem__("__radd__",new PyMethodDescr("__radd__",PyList.class,1,1,new exposed___radd__(null,null)));
class exposed___iadd__ extends PyBuiltinMethodNarrow {
exposed___iadd__(PyObject self,PyBuiltinFunction.Info info) {
@@ -579,38 +622,6 @@
}
dict.__setitem__("__imul__",new PyMethodDescr("__imul__",PyList.class,1,1,new exposed___imul__(null,null)));
- class exposed___mul__ extends PyBuiltinMethodNarrow {
-
- exposed___mul__(PyObject self,PyBuiltinFunction.Info info) {
- super(self,info);
- }
-
- public PyBuiltinFunction bind(PyObject self) {
- return new exposed___mul__(self,info);
- }
-
- public PyObject __call__(PyObject arg0) {
- return((PyList)self).list___mul__(arg0);
- }
-
- }
- dict.__setitem__("__mul__",new PyMethodDescr("__mul__",PyList.class,1,1,new exposed___mul__(null,null)));
- class exposed___rmul__ extends PyBuiltinMethodNarrow {
-
- exposed___rmul__(PyObject self,PyBuiltinFunction.Info info) {
- super(self,info);
- }
-
- public PyBuiltinFunction bind(PyObject self) {
- return new exposed___rmul__(self,info);
- }
-
- public PyObject __call__(PyObject arg0) {
- return((PyList)self).list___rmul__(arg0);
- }
-
- }
- dict.__setitem__("__rmul__",new PyMethodDescr("__rmul__",PyList.class,1,1,new exposed___rmul__(null,null)));
class exposed___hash__ extends PyBuiltinMethodNarrow {
exposed___hash__(PyObject self,PyBuiltinFunction.Info info) {
@@ -700,24 +711,14 @@
super(type, c);
}
- // apparently this doesn't work properly if used...
+ public PyList(PyObject[] elements) {
+ this(LISTTYPE, elements);
+ }
- // TODO: fix dependency so it can be removed.
- // Shouldn't be required (see PyList(Collection c), but test_re.py fails
- // without it. Probably used by reflection.
- public PyList(Vector v) {
- super(LISTTYPE, v);
- }
-
- // or super? - added to support PyDictionary
public PyList(Collection c) {
- this(LISTTYPE, c);
+ super(LISTTYPE, c);
}
-
- public PyList(PyObject[] elements) {
- this(LISTTYPE, elements);
- }
public PyList(PyObject o) {
this(LISTTYPE);
@@ -730,6 +731,8 @@
final void list_init(PyObject[] args,String[] kwds) {
ArgParser ap = new ArgParser("list", args, kwds, new String[] { "sequence"}, 0);
PyObject seq = ap.getPyObject(0, null);
+
+ clear();
if (seq == null) {
return;
}
@@ -802,119 +805,106 @@
list.pyset(i, value);
}
-// protected void setslice(int start, int stop, int step, PyObject value) {
-//
-// if (step != 1)
-// throw Py.ValueError("step size must be 1 for setting list slice");
-// if (stop < start)
-// stop = start;
-//
-// if (value instanceof PySequenceList) {
-//
-// if (value instanceof PyList) {
-// PyObject[] otherArray = null;
-// PyObject[] array = getArray();
-// PySequenceList seqList = (PySequenceList)value;
-// otherArray = seqList.getArray();
-// if (otherArray == array) {
-// otherArray = (PyObject[])otherArray.clone();
-// }
-// list.replaceSubArray(start, stop, otherArray, 0, seqList.size());
-// } else {
-// throw Py.TypeError("can only concatenate list (not \"" +
-// value.getType() + "\") to list");
-// }
-// } else {
-//
-// // also allow java.util.List
-// List other = (List)value.__tojava__(List.class);
-// if(other != Py.NoConversion) {
-// int n = other.size();
-// list.ensureCapacity(start + n);
-// for(int i=0; i<n; i++) {
-// list.add(i+start, other.get(i));
-// }
-// } else {
-// throw Py.TypeError(
-// "rhs of setslice must be a sequence or java.util.List");
-// }
-// }
-// }
protected void setslice(int start, int stop, int step, PyObject value) {
-
if (stop < start)
stop = start;
+ if (value instanceof PySequence) {
+ PySequence sequence = (PySequence)value;
+ setslicePySequence(start, stop, step, sequence);
+ }
+ else if (value instanceof List) {
+ List list = (List)value.__tojava__(List.class);
+ if (list != null && list != Py.NoConversion) {
+ setsliceList(start, stop, step, list);
+ }
+ }
+ else {
+ setsliceIterable(start, stop, step, value);
+ }
+ }
+
+ protected void setslicePySequence(int start, int stop, int step, PySequence value) {
if (step == 1) {
- if (value instanceof PySequence) {
-
- PySequence seq = (PySequence)value;
+ PyObject[] otherArray = null;
+ PyObject[] array = getArray();
- PyObject[] otherArray = null;
- PyObject[] array = getArray();
-
- if (value instanceof PySequenceList) {
- PySequenceList seqList = (PySequenceList)value;
- otherArray = seqList.getArray();
- if (otherArray == array) {
- otherArray = (PyObject[])otherArray.clone();
- }
- list.replaceSubArray(start, stop, otherArray, 0, seqList.size());
- } else {
- int n = seq.__len__();
- list.ensureCapacity(start + n);
- for(int i=0; i<n; i++) {
- list.add(i+start, seq.pyget(i));
- }
+ if (value instanceof PySequenceList) {
+ PySequenceList seqList = (PySequenceList)value;
+ otherArray = seqList.getArray();
+ if (otherArray == array) {
+ otherArray = otherArray.clone();
}
- } else if (value instanceof List) {
- List other = (List)value.__tojava__(List.class);
- if(other != Py.NoConversion && other != null) {
- int n = other.size();
- list.ensureCapacity(start + n);
- for(int i=0; i<n; i++) {
- list.add(i+start, other.get(i));
- }
- }
- } else {
- throw Py.TypeError(
- "rhs of setslice must be a sequence or java.util.List");
+ list.replaceSubArray(start, stop, otherArray, 0, seqList.size());
}
- } else if (step > 1){
- if (value instanceof PySequence) {
- PySequence seq = (PySequence)value;
- int n = seq.__len__();
- for(int i=0,j=0; i<n; i++,j+=step) {
- list.pyset(j+start, seq.pyget(i));
+ else {
+ int n = value.__len__();
+ list.ensureCapacity(start + n);
+ for (int i=0; i < n; i++) {
+ list.add(i + start, value.pyget(i));
}
- } else {
- throw Py.TypeError(
- "setslice with java.util.List and step != 1 not supported yet.");
}
-
- } else if (step < 0) {
- if (value instanceof PySequence) {
- PySequence seq = (PySequence)value;
- int n = seq.__len__();
- if (seq == this) {
- PyList newseq = new PyList();
- PyObject iter = seq.__iter__();
- for (PyObject item = null; (item = iter.__iternext__()) != null; ) {
- newseq.append(item);
- }
- seq = newseq;
+ }
+ else if (step > 1) {
+ int n = value.__len__();
+ for (int i=0, j=0; i < n; i++, j += step) {
+ list.pyset(j + start, value.pyget(i));
+ }
+ }
+ else if (step < 0) {
+ int n = value.__len__();
+ if (value == this) {
+ PyList newseq = new PyList();
+ PyObject iter = value.__iter__();
+ for (PyObject item = null; (item = iter.__iternext__()) != null;) {
+ newseq.append(item);
}
- for(int i=0,j=list.size() - 1; i<n; i++,j+=step) {
- list.pyset(j, seq.pyget(i));
- }
- } else {
- throw Py.TypeError(
- "setslice with java.util.List and step != 1 not supported yet.");
+ value = newseq;
}
- }
+ for (int i=0, j=list.size() - 1; i < n; i++, j += step) {
+ list.pyset(j, value.pyget(i));
+ }
+ }
}
-
+
+ protected void setsliceList(int start, int stop, int step, List value) {
+ if (step != 1) {
+ throw Py.TypeError("setslice with java.util.List and step != 1 not " +
+ "supported yet");
+ }
+ int n = value.size();
+ list.ensureCapacity(start + n);
+ for(int i=0; i < n; i++) {
+ list.add(i + start, value.get(i));
+ }
+ }
+
+ protected void setsliceIterable(int start, int stop, int step, PyObject value) {
+ PyObject iter;
+ try {
+ iter = value.__iter__();
+ }
+ catch (PyException pye) {
+ if (Py.matchException(pye, Py.TypeError)) {
+ throw Py.TypeError("can only assign an iterable");
+ }
+ throw pye;
+ }
+ PyObject next;
+ for (int j = 0; (next = iter.__iternext__()) != null; j += step) {
+ if (step < 0) {
+ list.pyset(start + j, next);
+ }
+ else {
+ list.add(start + j, next);
+ }
+ }
+ }
+
protected PyObject repeat(int count) {
+ if (count < 0) {
+ count = 0;
+ }
int l = size();
PyObject[] newList = new PyObject[l*count];
for (int i=0; i<count; i++) {
@@ -924,37 +914,46 @@
}
public PyObject __imul__(PyObject o) {
- return list___imul__(o);
+ PyObject result = list___imul__(o);
+ if (result == null) {
+ // We can't perform an in-place multiplication on o's
+ // type, so let o try to rmul this list. A new list will
+ // be created instead of modifying this one, but that's
+ // preferable to just blowing up on this operation.
+ result = o.__rmul__(this);
+ if (result == null) {
+ throw Py.TypeError(_unsupportedop("*", o));
+ }
+ }
+ return result;
}
final PyObject list___imul__(PyObject o) {
if (!(o instanceof PyInteger || o instanceof PyLong))
- throw Py.TypeError("can't multiply sequence to non-int");
+ return null;
int l = size();
int count = ((PyInteger)o.__int__()).getValue();
int newSize = l * count;
- list.ensureCapacity(newSize);
list.setSize(newSize);
- //resize(l * count);
PyObject[] array = getArray();
- for (int i=1; i<count; i++) {
- System.arraycopy(array, 0, array, i*l, l);
+ for(int i = 1; i < count; i++) {
+ System.arraycopy(array, 0, array, i * l, l);
}
return this;
}
final PyObject list___mul__(PyObject o) {
if (!(o instanceof PyInteger || o instanceof PyLong))
- throw Py.TypeError("can't multiply sequence to non-int");
+ return null;
int count = ((PyInteger)o.__int__()).getValue();
return repeat(count);
}
final PyObject list___rmul__(PyObject o) {
if (!(o instanceof PyInteger || o instanceof PyLong))
- throw Py.TypeError("can't multiply sequence to non-int");
+ return null;
int count = ((PyInteger)o.__int__()).getValue();
return repeat(count);
}
@@ -1012,15 +1011,8 @@
if (op.equals("+")) {
return "can only concatenate list (not \"{2}\") to list";
}
- return null;
+ return super.unsupportedopMessage(op, o2);
}
-
- protected String runsupportedopMessage(String op, PyObject o2) {
- if (op.equals("+")) {
- return "can only concatenate list (not \"{1}\") to list";
- }
- return null;
- }
public String toString() {
return list_toString();
@@ -1120,14 +1112,12 @@
int validStart = calculateIndex(start);
PyObject[] array = getArray();
- int i=validStart;
- for (; i<validStop; i++) {
+ int i = validStart;
+ for (; i < validStop && i < size(); i++) {
if (array[i].equals(o))
- break;
+ return i;
}
- if (i == validStop)
- throw Py.ValueError(message);
- return i;
+ throw Py.ValueError(message);
}
//This is closely related to fixindex in PySequence, but less strict
Modified: branches/modern/src/org/python/core/PyStringMap.java
===================================================================
--- branches/modern/src/org/python/core/PyStringMap.java 2007-12-24 19:36:03 UTC (rev 3863)
+++ branches/modern/src/org/python/core/PyStringMap.java 2007-12-25 01:31:13 UTC (rev 3864)
@@ -1,6 +1,13 @@
// Copyright (c) Corporation for National Research Initiatives
package org.python.core;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
/**
* this used to be "A faster Dictionary where the keys have to be strings", but no more.
@@ -14,11 +21,11 @@
private final Map table;
public PyStringMap(int capacity) {
- table = Collections.synchronizedMap(new HashMap(capacity));
+ table = new ConcurrentHashMap(capacity);
}
public PyStringMap(java.util.Map map) {
- table = Collections.synchronizedMap(new HashMap(map));
+ table = new ConcurrentHashMap(map);
}
public PyStringMap() {
@@ -26,7 +33,7 @@
}
public PyStringMap(PyObject elements[]) {
- table = Collections.synchronizedMap(new HashMap(elements.length));
+ table = new ConcurrentHashMap(elements.length);
for (int i=0; i<elements.length; i+=2) {
__setitem__(elements[i], elements[i+1]);
}
@@ -123,21 +130,17 @@
}
StringBuffer buf = new StringBuffer("{");
- synchronized(table) {
- for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry)it.next();
- Object key = entry.getKey();
- if (key instanceof String) {
- buf.append(key);
- }
- else {
- buf.append(((PyObject)entry.getKey()).__repr__().toString());
- }
- buf.append(": ");
- buf.append(((PyObject)entry.getValue()).__repr__().toString());
- buf.append(", ");
- }
- }
+ for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
+ Entry entry = (Entry)it.next();
+ Object key = entry.getKey();
+ if (key instanceof String)
+ buf.append(key);
+ else
+ buf.append(((PyObject)entry.getKey()).__repr__().toString());
+ buf.append(": ");
+ buf.append(((PyObject)entry.getValue()).__repr__().toString());
+ buf.append(", ");
+ }
if(buf.length() > 1){
buf.delete(buf.length() - 2, buf.length());
}
@@ -245,11 +248,9 @@
* this mapping.
*/
public void update(PyDictionary dict) {
- synchronized(dict.table) {
- for (Iterator it = dict.table.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry)it.next();
- __setitem__((PyObject)entry.getKey(), (PyObject)entry.getValue());
- }
+ for (Iterator it = dict.table.entrySet().iterator(); it.hasNext(); ) {
+ Entry entry = (Entry)it.next();
+ __setitem__((PyObject)entry.getKey(), (PyObject)entry.getValue());
}
}
@@ -283,40 +284,64 @@
* from the mapping.
*/
public PyObject popitem() {
- synchronized(table) {
- java.util.Iterator it = table.entrySet().iterator();
- if (!it.hasNext())
- throw Py.KeyError("popitem(): dictionary is empty");
- java.util.Map.Entry entry = (java.util.Map.Entry)it.next();
- it.remove();
- return new PyTuple((PyObject)entry.getKey(), (PyObject)entry.getValue());
+ Iterator it = table.entrySet().iterator();
+ if (!it.hasNext())
+ throw Py.KeyError("popitem(): dictionary is empty");
+ Entry entry = (Entry)it.next();
+ Object objKey = entry.getKey();
+ PyObject value = (PyObject)entry.getValue();
+ PyTuple tuple;
+ if (objKey instanceof String)
+ tuple = new PyTuple(new PyString((String)objKey), value);
+ else
+ tuple = new PyTuple((PyObject)objKey, value);
+ it.remove();
+ return tuple;
+ }
+
+ // not correct - we need to determine size and remove at the same time!
+ public PyObject pop(PyObject key) {
+ if (table.size() == 0)
+ throw Py.KeyError("pop(): dictionary is empty");
+ return pop(key, null);
+ }
+
+ public PyObject pop(PyObject key, PyObject failobj) {
+ Object objKey;
+ if (key instanceof PyString)
+ objKey = ((PyString)key).internedString();
+ else
+ objKey = key;
+ PyObject value = (PyObject)table.remove(objKey);
+ if(value == null) {
+ if (failobj == null) {
+ throw Py.KeyError(key.__repr__().toString());
+ } else {
+ return failobj;
+ }
}
+ return value;
}
-
/**
* Return a copy of the mappings list of (key, value) tuple
* pairs.
*/
public PyList items() {
- List lst = null;
- synchronized(table) {
- int n = table.size();
- lst = new ArrayList(n);
+ final List list = new ArrayList(table.size());
- for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry)it.next();
- Object objKey = entry.getKey();
- PyObject key = null;
- PyObject value = (PyObject)entry.getValue();
- if (objKey instanceof String)
- key = new PyString((String)objKey);
- else
- key = (PyObject)objKey;
- lst.add(new PyTuple(key, value ));
- }
+ for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
+ Entry entry = (Entry)it.next();
+ Object objKey = entry.getKey();
+ PyObject key = null;
+ PyObject value = (PyObject)entry.getValue();
+ if (objKey instanceof String)
+ key = new PyString((String)objKey);
+ else
+ key = (PyObject)objKey;
+ list.add(new PyTuple(key, value ));
}
- return new PyList(lst);
-}
+ return new PyList(list);
+ }
@@ -325,20 +350,16 @@
* account that we could be storing String or PyObject objects
*/
public PyList keys() {
- List lst = null;
- synchronized(table) {
- lst = new ArrayList(table.size());
- for (Iterator it = table.keySet().iterator(); it.hasNext(); ) {
- Object obj = it.next();
- if (obj instanceof String) {
- lst.add(new PyString((String)obj));
- }
- else {
- lst.add(obj);
- }
+ final List list = new ArrayList(table.size());
+ for (Iterator it = table.keySet().iterator(); it.hasNext(); ) {
+ Object obj = it.next();
+ if (obj instanceof String) {
+ list.add(new PyString((String)obj));
}
+ else
+ list.add(obj);
}
- return new PyList(lst);
+ return new PyList(list);
}
/**
@@ -351,28 +372,29 @@
* return an iterator over (key, value) pairs
*/
public PyObject iteritems() {
- return new PDEntriesIter(table.entrySet());
+ return new ItemsIter(table.entrySet());
}
/**
* return an iterator over the keys
*/
+
+ // Python allows one to change the dict while iterating over it,
+ // including deletion. Java does not. Can we resolve with CHM?
public PyObject iterkeys() {
- return new PDKeysIter(table.keySet());
+ return new KeysIter(table.keySet());
}
/**
* return an iterator over the values
*/
public PyObject itervalues() {
- return new PDCollectionIter(table.values());
+ return new ValuesIter(table.values());
}
- // TODO: this is not going to work for String keys...
- // just a lightweight wrapper for now...
- private class PDCollectionIter extends PyIterator {
+ private class ValuesIter extends PyIterator {
private final Iterator iterator;
- public PDCollectionIter(Collection c) {
+ public ValuesIter(Collection c) {
this.iterator = c.iterator();
}
@@ -383,9 +405,9 @@
}
}
- private class PDKeysIter extends PyIterator {
+ private class KeysIter extends PyIterator {
private final Iterator iterator;
- public PDKeysIter(java.util.Set s) {
+ public KeysIter(Set s) {
this.iterator = s.iterator();
}
@@ -401,17 +423,17 @@
return key;
}
}
- // same bug - need to check entry.getKey()
- private class PDEntriesIter extends PyIterator {
+
+ private class ItemsIter extends PyIterator {
private final Iterator iterator;
- public PDEntriesIter(java.util.Set s) {
+ public ItemsIter(Set s) {
this.iterator = s.iterator();
}
public PyObject __iternext__() {
if (!iterator.hasNext())
return null;
- Map.Entry entry = (Map.Entry)iterator.next();
+ Entry entry = (Entry)iterator.next();
Object objKey = entry.getKey();
PyObject key = null;
PyObject value = (PyObject)entry.getValue();
Modified: branches/modern/src/org/python/core/__builtin__.java
===================================================================
--- branches/modern/src/org/python/core/__builtin__.java 2007-12-24 19:36:03 UTC (rev 3863)
+++ branches/modern/src/org/python/core/__builtin__.java 2007-12-25 01:31:13 UTC (rev 3864)
@@ -1,8 +1,11 @@
// Copyright (c) Corporation for National Research Initiatives
package org.python.core;
-import org.python.modules.sets.PySet;
-import org.python.modules.sets.PyImmutableSet;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Map;
+
import org.python.core.util.RelativeFile;
import org.python.modules.sets.PyImmutableSet;
import org.python.modules.sets.PySet;
@@ -43,7 +46,7 @@
case 1:
return Py.newInteger(__builtin__.len(arg1));
case 2:
- return __builtin__.range(Py.py2int(arg1, "range(): 1st arg can't be coerced to int"));
+ return __builtin__.range(arg1);
case 3:
if (!(arg1 instanceof PyString))
throw Py.TypeError("ord() expected string of length 1, but " + arg1.getType().getFullName() + " found");
@@ -73,7 +76,7 @@
} catch (ConversionException e) {
throw Py.TypeError("execfile's first argument must be str");
}
- return null;
+ return Py.None;
case 23:
return __builtin__.hex(arg1);
case 24:
@@ -110,6 +113,8 @@
return fancyCall(new PyObject[] { arg1 });
case 43:
return fancyCall(new PyObject[] { arg1 });
+ case 45:
+ return __builtin__.reversed(arg1);
default:
throw info.unexpectedCall(1, false);
}
@@ -118,8 +123,7 @@
public PyObject __call__(PyObject arg1, PyObject arg2) {
switch (this.index) {
case 2:
- return __builtin__.range(Py.py2int(arg1, "range(): 1st arg can't be coerced to int"), Py.py2int(arg2,
- "range(): 2nd arg can't be coerced to int"));
+ return __builtin__.range(arg1, arg2);
case 6:
return Py.newInteger(__builtin__.cmp(arg1, arg2));
case 9:
@@ -132,7 +136,7 @@
return __builtin__.coerce(arg1, arg2);
case 15:
__builtin__.delattr(arg1, asString(arg2, "delattr(): attribute name must be string"));
- return null;
+ return Py.None;
case 17:
return __builtin__.divmod(arg1, arg2);
case 18:
@@ -143,7 +147,7 @@
} catch (ConversionException e) {
throw Py.TypeError("execfile's first argument must be str");
}
- return null;
+ return Py.None;
case 20:
return __builtin__.filter(arg1, arg2);
case 21:
@@ -178,9 +182,7 @@
public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3) {
switch (this.index) {
case 2:
- return __builtin__.range(Py.py2int(arg1, "range(): 1st arg can't be coerced to int"), Py.py2int(arg2,
- "range(): 2nd arg can't be coerced to int"), Py.py2int(arg3,
- "range(): 3rd arg can't be coerced to int"));
+ return __builtin__.range(arg1, arg2, arg3);
case 9:
try {
if (arg3 instanceof PyStringMap) {
@@ -200,7 +202,7 @@
return __builtin__.eval(arg1, arg2, arg3);
case 19:
__builtin__.execfile(asString(arg1, "execfile's first argument must be str", false), arg2, arg3);
- return null;
+ return Py.None;
case 21:
return __builtin__.getattr(arg1, asString(arg2, "getattr(): attribute name must be string"), arg3);
case 33:
@@ -209,7 +211,7 @@
return __builtin__.reduce(arg1, arg2, arg3);
case 39:
__builtin__.setattr(arg1, asString(arg2, "setattr(): attribute name must be string"), arg3);
- return null;
+ return Py.None;
case 42:
return __builtin__.xrange(Py.py2int(arg1), Py.py2int(arg2), Py.py2int(arg3));
case 44:
@@ -382,9 +384,8 @@
dict.__setitem__("vars", new BuiltinFunctions("vars", 41, 0, 1));
dict.__setitem__("xrange", new BuiltinFunctions("xrange", 42, 1, 3));
dict.__setitem__("zip", new BuiltinFunctions("zip", 43, 1, -1));
-
+ dict.__setitem__("reversed", new BuiltinFunctions("reversed", 45, 1));
dict.__setitem__("__import__", new ImportFunction());
-
}
public static PyObject abs(PyObject o) {
@@ -401,24 +402,25 @@
public static PyObject apply(PyObject o, PyObject args, PyDictionary kws) {
PyObject[] a;
String[] kw;
- java.util.Map table = kws.table;
+ Map table = kws.table;
if (table.size() > 0) {
- java.util.Iterator ik = table.keySet().iterator();
- java.util.Iterator iv = table.values().iterator();
- int n = table.size();
- kw = new String[n];
- PyObject[] aargs = Py.make_array(args);
- a = new PyObject[n + aargs.length];
- System.arraycopy(aargs, 0, a, 0, aargs.length);
- int offset = aargs.length;
+ Iterator ik = table.keySet().iterator();
+ Iterator iv = table.values().iterator();
+ int n = table.size();
+ kw = new String[n];
+ PyObject[] aargs = Py.make_array(args);
+ a = new PyObject[n + aargs.length];
+ System.arraycopy(aargs, 0, a, 0, aargs.length);
+ int offset = aargs.length;
- for (int i = 0; i < n; i++) {
- kw[i] = ((PyString) ik.next()).internedString();
- a[i + offset] = (PyObject) iv.next();
- }
- return o.__call__(a, kw);
- } else {
- return apply(o, args);
+ for (int i = 0; i < n; i++) {
+ kw[i] = ((PyString)ik.next()).internedString();
+ a[i + offset] = (PyObject)iv.next();
+ }
+ return o.__call__(a, kw);
+ }
+ else {
+ return apply(o, args);
}
}
@@ -739,7 +741,7 @@
if (n == 1) {
list.append(args[0]);
} else {
- list.append(new PyTuple((PyObject[]) args.clone()));
+ list.append(new PyTuple(args.clone()));
}
} else {
list.append(f.__call__(args));
@@ -792,9 +794,16 @@
return min;
}
- public static PyString oct(PyObject o) {
- return o.__oct__();
- }
+ public static PyString oct(PyObject o) {
+ try {
+ return o.__oct__();
+ } catch(PyException e) {
+ if(Py.matchException(e, Py.AttributeError)) {
+ throw Py.TypeError("oct() argument can't be converted to oct");
+ }
+ throw e;
+ }
+ }
public static final int ord(char c) {
return c;
@@ -872,34 +881,58 @@
throw Py.TypeError("__pow__ not defined for these operands");
}
- public static PyObject range(int start, int stop, int step) {
- if (step == 0) {
- throw Py.ValueError("zero step for range()");
- }
- int n;
- if (step > 0) {
- n = (stop - start + step - 1) / step;
- } else {
- n = (stop - start + step + 1) / step;
- }
- if (n <= 0) {
- return new PyList();
- }
- PyObject[] l = new PyObject[n];
- int j = start;
- for (int i = 0; i < n; i++) {
- l[i] = Py.newInteger(j);
- j += step;
- }
- return new PyList(l);
- }
+ public static PyObject range(PyObject start, PyObject stop, PyObject step) {
+ // Check that step is valid.
+ int stepCmp = step.__cmp__(Py.Zero);
+ if(stepCmp == -2) {
+ throw Py.TypeError("non-integer type for step in range()");
+ } else if(stepCmp == 0) {
+ throw Py.ValueError("zero step for range()");
+ }
+
+ // Calculate the number of values in the range.
+ PyObject n = stop.__sub__(start);
+ if(n == null) {
+ throw Py.TypeError("non-integer type for start or stop in range()");
+ }
+ n = n.__add__(step);
+ if(stepCmp == 1) { // step is positive
+ n = n.__sub__(Py.One).__div__(step);
+ } else { // step is negative
+ n = n.__add__(Py.One).__div__(step);
+ }
+
+ // Check that the number of values is valid.
+ if(n.__cmp__(Py.Zero) <= 0) {
+ return new PyList();
+ }
+ Object nAsInteger = n.__tojava__(Integer.TYPE);
+ if(nAsInteger == Py.NoConversion) {
+ if(n instanceof PyLong) {
+ throw Py.OverflowError("Can't use range for more than " + Integer.MAX_VALUE
+ + " items. Try xrange instead.");
+ } else {
+ throw Py.TypeError("non-integer type for start or stop in range()");
+ }
+ }
+
+ // Fill in the range.
+ int nAsInt = ((Integer)nAsInteger).intValue();
+ PyObject j = start;
+ PyObject[] objs = new PyObject[nAsInt];
+ for(int i = 0; i < nAsInt; i++) {
+ objs[i] = j;
+ j = j.__add__(step);
+ }
+ return new PyList(objs);
+ }
- public static PyObject range(int n) {
- return range(0, n, 1);
+ public static PyObject range(PyObject n) {
+ return range(Py.Zero, n, Py.One);
}
- public static PyObject range(int start, int stop) {
- return range(start, stop, 1);
+ public static PyObject range(PyObject start, PyObject stop) {
+ return range(start, stop, Py.One);
}
private static PyString readline(PyObject file) {
@@ -1000,7 +1033,16 @@
}
return result;
}
-
+
+ public static PyObject reversed(PyObject seq) {
+ if(hasattr(seq, "__getitem__") && hasattr(seq, "__len__") &&
+ !hasattr(seq, "keys")) {
+ return new PyReversedIterator(seq);
+ } else {
+ throw Py.TypeError("argument to reversed() must be a sequence");
+ }
+ }
+
public static PyObject sum(PyObject seq) {
return sum(seq, Py.Zero);
}
@@ -1117,7 +1159,7 @@
}
PyObject builtins = frame.f_builtins;
if (builtins == null) {
- builtins = Py.getSystemState().builtins;
+ builtins = PySystemState.builtins;
}
PyObject __import__ = builtins.__finditem__("__import__");
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|