Index: Lib/test/test_java_list_delegate.py =================================================================== --- Lib/test/test_java_list_delegate.py (revision 6507) +++ Lib/test/test_java_list_delegate.py (working copy) @@ -20,18 +20,26 @@ return op_func(value) except Exception, e: return type(e) + + def _arraylist_of(self, xs): + """ + Converts a python list to a java.util.ArrayList + """ + a = ArrayList() + a.addAll( xs ) + return a - def check_list(self, control, results, initial): - for result in results: + def check_list(self, control, results, list_type_names, initial, test_name): + for result, type_name in zip(results, list_type_names): try: len(result) except: print result - self.assertEquals(len(control), len(result), "%s is wrong for %s" % (type(result), initial)) - for pvalue, jvalue in zip(control, result): - self.assertEquals(pvalue, jvalue) + self.assertEquals(len(control), len(result), "%s: length for %s does not match that of list" % (test_name, type_name)) + for control_value, result_value in zip(control, result): + self.assertEquals(control_value, result_value, "%s: values from %s do not match those from list" % (test_name, type_name)) - def _list_op_test(self, initial_value, op_func, check_value): + def _list_op_test(self, initial_value, op_func, test_name): """ Tests a list operation @@ -39,24 +47,33 @@ - a python list - a java.util.List instance - givens the same result in both cases + gives the same result in both cases """ lists = [list(initial_value), ArrayList(initial_value), Vector(initial_value)] + list_type_names = ['list', 'ArrayList', 'Vector'] results = [self._perform_op(l, op_func) for l in lists] - self.check_list(lists[0], lists[1:], initial_value) - if check_value or not isinstance(results[0], list): - for r in results[1:]: - self.assertEquals(results[0], r) + self.check_list(lists[0], lists[1:], list_type_names[1:], initial_value, test_name) + if not isinstance(results[0], list): + for r,n in zip(results[1:], list_type_names[1:]): + self.assertEquals(results[0], r, '%s: result for list does not match result for java type %s' % (test_name,n) ) else: - self.check_list(results[0], results[1:], initial_value) + self.check_list(results[0], results[1:], list_type_names[1:], initial_value, test_name) def test_get_integer(self): initial_value = range(0, 5) for i in xrange(-7, 7): - self._list_op_test(initial_value, lambda xs: xs[i], True) + self._list_op_test(initial_value, lambda xs: xs[i], 'get_integer [%d]' % (i,)) + def test_get_slice(self): + initial_value = range(0, 5) + + for i in [None] + range(-7, 7): + for j in [None] + range(-7, 7): + for k in [None] + range(-7, 7): + self._list_op_test(initial_value, lambda xs: xs[i:j:k], 'get_slice [%s:%s:%s]' % (i,j,k)) + def test_set_integer(self): initial_value = range(0, 5) @@ -66,24 +83,27 @@ return _f for i in xrange(-7, 7): - self._list_op_test(initial_value, make_op_func(i), True) + self._list_op_test(initial_value, make_op_func(i), 'set_integer [%d]' % (i,)) def test_set_slice(self): - initial_value = range(0, 10) + initial_value = range(0, 5) def make_op_func(i, j, k, v): def _f(xs): xs[i:j:k] = v return _f - for i in xrange(-12, 12): - for j in xrange(-12, 12): - for k in xrange(-12, 12): - self._list_op_test(initial_value, make_op_func(i, j, k, []), True) - self._list_op_test(initial_value, make_op_func(i, j, k, range(0,2)), True) - self._list_op_test(initial_value, make_op_func(i, j, k, range(0,4)), True) - self._list_op_test(initial_value, make_op_func(i, j, k, xrange(0,2)), True) + for i in [None] + range(-7, 7): + for j in [None] + range(-7, 7): + for k in [None] + range(-7, 7): + self._list_op_test(initial_value, make_op_func(i, j, k, []), 'set_slice [%s:%s:%s]=[]' % (i,j,k)) + self._list_op_test(initial_value, make_op_func(i, j, k, range(0,2)), 'set_slice [%s:%s:%s]=range(0,2)' % (i,j,k)) + self._list_op_test(initial_value, make_op_func(i, j, k, range(0,4)), 'set_slice [%s:%s:%s]=range(0,4)' % (i,j,k)) + self._list_op_test(initial_value, make_op_func(i, j, k, xrange(0,2)), 'set_slice [%s:%s:%s]=xrange(0,2)' % (i,j,k)) + self._list_op_test(initial_value, make_op_func(i, j, k, self._arraylist_of(range(0,2))), 'set_slice [%s:%s:%s]=ArrayList(range(0,2))' % (i,j,k)) + self._list_op_test([1,2,3,4,5], make_op_func(1, None, None, [1,2,3,4,5]), 'set_slice [1:]=[1,2,3,4,5]') + def test_del_integer(self): initial_value = range(0,5) @@ -93,20 +113,20 @@ return _f for i in xrange(-7, 7): - self._list_op_test(initial_value, make_op_func(i), True) + self._list_op_test(initial_value, make_op_func(i), 'del_integer [%d]' % (i,)) def test_del_slice(self): - initial_value = range(0,10) + initial_value = range(0,5) def make_op_func(i, j, k): def _f(xs): del xs[i:j:k] return _f - for i in xrange(-12, 12): - for j in xrange(-12, 12): - for k in xrange(-12, 12): - self._list_op_test(initial_value, make_op_func(i, j, k), True) + for i in [None] + range(-7, 7): + for j in [None] + range(-7, 7): + for k in [None] + range(-7, 7): + self._list_op_test(initial_value, make_op_func(i, j, k), 'del_slice [%s:%s:%s]' % (i,j,k)) def test_len(self): jlist = ArrayList() @@ -174,6 +194,43 @@ self.assert_(m.size() == 11) self.assert_(m.get(10) == 84) + + + def test_set_slice_from_input_types(self): + """ + Tests the slice setting functionality of Python lists + Ensures that the results are all the same, whether the source list is a Python list, a java.util.List or an iterator + """ + initial_value = range(0, 5) + + def make_op_func(i, j, k, v): + def _f(xs): + xs[i:j:k] = v + return _f + + for i in [None] + range(-7, 7): + for j in [None] + range(-7, 7): + for k in [None] + range(-7, 7): + destPy = copy(initial_value) + destJUL = copy(initial_value) + destIter = copy(initial_value) + + sourcePy = range(0, 2) + sourceJUL = self._arraylist_of(range(0, 2)) + sourceIter = xrange(0, 2) + + resultPy = self._perform_op(destPy, make_op_func(i, j, k, sourcePy)) + resultJUL = self._perform_op(destJUL, make_op_func(i, j, k, sourceJUL)) + resultIter = self._perform_op(destIter, make_op_func(i, j, k, sourceIter)) + + self.assertEquals(resultPy, resultJUL) + self.assertEquals(resultPy, resultIter) + + self.assertEquals(destPy, destJUL) + self.assertEquals(destPy, destIter) + + + def test_main(): test.test_support.run_unittest(CollectionProxyTest) Index: src/org/python/core/PyJavaType.java =================================================================== --- src/org/python/core/PyJavaType.java (revision 6507) +++ src/org/python/core/PyJavaType.java (working copy) @@ -896,26 +896,94 @@ public void setItem(int idx, PyObject value) { list.set(idx, value.__tojava__(Object.class)); } - + @Override public void setSlice(int start, int stop, int step, PyObject value) { - if (step == 0) { - return; + if (stop < start) { + stop = start; } - if (value.javaProxy == this) { - List newseq = new ArrayList(len()); - for (Object object : ((List)value.javaProxy)) { - newseq.add(object); + if (value.javaProxy == this.list) { + List xs = Generic.list(); + xs.addAll(this.list); + setsliceList(start, stop, step, xs); + } else if (value instanceof PyList) { + setslicePyList(start, stop, step, (PyList)value); + } else { + Object valueList = value.__tojava__(List.class); + if (valueList != null && valueList != Py.NoConversion) { + setsliceList(start, stop, step, (List)valueList); + } else { + setsliceIterator(start, stop, step, value.asIterable().iterator()); } - value = Py.java2py(newseq); } - int j = start; - for (PyObject obj : value.asIterable()) { - setItem(j, obj); - j += step; + } + + + + final private void setsliceList(int start, int stop, int step, List value) { + if (step == 1) { + list.subList(start, stop).clear(); + list.addAll(start, value); + } else { + int size = list.size(); + Iterator iter = value.listIterator(); + for (int j = start; iter.hasNext(); j += step) { + Object item =iter.next(); + if (j >= size) { + list.add(item); + } else { + list.set(j, item); + } + } } } + final private void setsliceIterator(int start, int stop, int step, Iterator iter) { + if (step == 1) { + List insertion = new ArrayList(); + if (iter != null) { + while (iter.hasNext()) { + insertion.add(iter.next().__tojava__(Object.class)); + } + } + list.subList(start, stop).clear(); + list.addAll(start, insertion); + } else { + int size = list.size(); + for (int j = start; iter.hasNext(); j += step) { + Object item = iter.next().__tojava__(Object.class); + if (j >= size) { + list.add(item); + } else { + list.set(j, item); + } + } + } + } + + final private void setslicePyList(int start, int stop, int step, PyList value) { + if (step == 1) { + list.subList(start, stop).clear(); + int n = value.list.size(); + for (int i=0, j=start; i iter = value.list.listIterator(); + for (int j = start; iter.hasNext(); j += step) { + Object item = iter.next().__tojava__(Object.class); + if (j >= size) { + list.add(item); + } else { + list.set(j, item); + } + } + } + } + + @Override public void delItems(int start, int stop) { int n = stop - start; Index: src/org/python/core/PyList.java =================================================================== --- src/org/python/core/PyList.java (revision 6507) +++ src/org/python/core/PyList.java (working copy) @@ -141,26 +141,38 @@ setslicePyList(start, stop, step, (PyList) value); } else if (value instanceof PySequence) { setsliceIterator(start, stop, step, value.asIterable().iterator()); - } else if (value != null && !(value instanceof List)) { - value = new PyList(value); - setsliceIterator(start, stop, step, value.asIterable().iterator()); + } else if (value instanceof List) { + setsliceList(start, stop, step, (List)value); } else { - List valueList = (List) value.__tojava__(List.class); + Object valueList = value.__tojava__(List.class); if (valueList != null && valueList != Py.NoConversion) { - setsliceList(start, stop, step, valueList); + setsliceList(start, stop, step, (List)valueList); + } else { + value = new PyList(value); + setsliceIterator(start, stop, step, value.asIterable().iterator()); } } } final private void setsliceList(int start, int stop, int step, List value) { - int n = sliceLength(start, stop, step); - if (list instanceof ArrayList) { - ((ArrayList) list).ensureCapacity(start + n); + if (step == 1) { + list.subList(start, stop).clear(); + int n = value.size(); + for (int i=0, j=start; i iter = value.listIterator(); + for (int j = start; iter.hasNext(); j += step) { + PyObject item = Py.java2py(iter.next()); + if (j >= size) { + list.add(item); + } else { + list.set(j, item); + } + } } - ListIterator src = value.listIterator(); - for (int j = start; src.hasNext(); j += step) { - set(j, src.next()); - } } final private void setsliceIterator(int start, int stop, int step, Iterator iter) {