All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.org.python.core.PyList Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 2.7.4
Show newest version
// Copyright (c) Corporation for National Research Initiatives
package org.python.core;

import java.util.ArrayList;
import java.util.Arrays;

import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
import org.python.expose.MethodType;
import org.python.util.Generic;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import java.lang.reflect.Array;
import java.util.Map;

@ExposedType(name = "list", base = PyObject.class, doc = BuiltinDocs.list_doc)
public class PyList extends PySequenceList {

    public static final PyType TYPE = PyType.fromClass(PyList.class);
    {
        // Ensure list is not Hashable
        TYPE.object___setattr__("__hash__", Py.None);
    }

    private final List list;
    public volatile int gListAllocatedStatus = -1;

    public PyList() {
        this(TYPE);
    }

    public PyList(PyType type) {
        super(type);
        list = Generic.list();
    }

    private PyList(List list, boolean convert) {
        super(TYPE);
        if (!convert) {
            this.list = (List) list;
        } else {
            this.list = Generic.list();
            for (Object o : list) {
                add(o);
            }
        }
    }

    public PyList(PyType type, PyObject[] elements) {
        super(type);
        list = new ArrayList(Arrays.asList(elements));
    }

    public PyList(PyType type, Collection c) {
        super(type);
        list = new ArrayList(c.size());
        for (Object o : c) {
            add(o);
        }
    }

    public PyList(PyObject[] elements) {
        this(TYPE, elements);
    }

    public PyList(Collection c) {
        this(TYPE, c);
    }

    public PyList(PyObject o) {
        this(TYPE);
        for (PyObject item : o.asIterable()) {
            list.add(item);
        }
    }

    public static PyList fromList(List list) {
        return new PyList(list, false);
    }

    List getList() {
        return Collections.unmodifiableList(list);
    }

    private static List listify(Iterator iter) {
        List list = Generic.list();
        while (iter.hasNext()) {
            list.add(iter.next());
        }
        return list;
    }

    public PyList(Iterator iter) {
        this(TYPE, listify(iter));
    }

    // refactor and put in Py presumably;
    // presumably we can consume an arbitrary iterable too!
    private static void addCollection(List list, Collection seq) {
        Map seen = new HashMap<>();
        for (Object item : seq) {
            long id = Py.java_obj_id(item);
            PyObject seen_obj = seen.get(id);
            if (seen_obj != null) {
                seen_obj = Py.java2py(item);
                seen.put(id, seen_obj);
            }
            list.add(seen_obj);
        }
    }

    @SuppressWarnings("unchecked")
    @ExposedNew
    @ExposedMethod(doc = BuiltinDocs.list___init___doc)
    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;
        }

        /* PyListDerived should be iterated over and not plain copied for cases where someone subclasses list
        and overrides __iter__
         */
        if (seq instanceof PyListDerived) {
            for (PyObject item : seq.asIterable()) {
                append(item);
            }
        } else if (seq instanceof PyList) {
            list.addAll(((PyList) seq).list); // don't convert
        } else if (seq instanceof PyTuple) {
            list.addAll(((PyTuple) seq).getList());
        } else if (seq.getClass().isAssignableFrom(Collection.class)) {
            System.err.println("Adding from collection");
            addCollection(list, (Collection) seq);
        } else {
            for (PyObject item : seq.asIterable()) {
                append(item);
            }
        }
    }

    @Override
    public int __len__() {
        return list___len__();
    }

    @ExposedMethod(doc = BuiltinDocs.list___len___doc)
    final synchronized int list___len__() {
        return size();
    }

    @Override
    protected void del(int i) {
        remove(i);
    }

    @Override
    protected void delRange(int start, int stop) {
        remove(start, stop);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void setslice(int start, int stop, int step, PyObject value) {
        if (stop < start) {
            stop = start;
        }
        if (value instanceof PyList) {
            if (value == this) { // copy
                value = new PyList((PySequence) value);
            }
            setslicePyList(start, stop, step, (PyList) value);
        } else if (value instanceof PySequence) {
            setsliceIterator(start, stop, step, value.asIterable().iterator());
        } else if (value instanceof List) {
                setsliceList(start, stop, step, (List)value);
        } else {
            Object valueList = value.__tojava__(List.class);
            if (valueList != null && valueList != Py.NoConversion) {
                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) {
        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);
                }
            }
        }
    }

    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());
                }
            }
            list.subList(start, stop).clear();
            list.addAll(start, insertion);
        } else {
            int size = list.size();
            for (int j = start; iter.hasNext(); j += step) {
                PyObject item = iter.next();
                if (j >= size) {
                    list.add(item);
                } else {
                    list.set(j, item);
                }
            }
        }
    }

    final private void setslicePyList(int start, int stop, int step, PyList other) {
        if (step == 1) {
            list.subList(start, stop).clear();
            list.addAll(start, other.list);
        } else {
            int size = list.size();
            Iterator iter = other.list.listIterator();
            for (int j = start; iter.hasNext(); j += step) {
                PyObject item = iter.next();
                if (j >= size) {
                    list.add(item);
                } else {
                    list.set(j, item);
                }
            }
        }
    }

    @Override
    protected synchronized PyObject repeat(int count) {
        if (count < 0) {
            count = 0;
        }
        int size = size();
        int newSize = size * count;
        if (count != 0 && newSize / count != size) {
            throw Py.MemoryError("");
        }

        PyObject[] elements = list.toArray(new PyObject[size]);
        PyObject[] newList = new PyObject[newSize];
        for (int i = 0; i < count; i++) {
            System.arraycopy(elements, 0, newList, i * size, size);
        }
        return new PyList(newList);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___ne___doc)
    final synchronized PyObject list___ne__(PyObject o) {
        return seq___ne__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___eq___doc)
    final synchronized PyObject list___eq__(PyObject o) {
        return seq___eq__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___lt___doc)
    final synchronized PyObject list___lt__(PyObject o) {
        return seq___lt__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___le___doc)
    final synchronized PyObject list___le__(PyObject o) {
        return seq___le__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___gt___doc)
    final synchronized PyObject list___gt__(PyObject o) {
        return seq___gt__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___ge___doc)
    final synchronized PyObject list___ge__(PyObject o) {
        return seq___ge__(o);
    }

    @Override
    public PyObject __imul__(PyObject o) {
        return list___imul__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___imul___doc)
    final synchronized PyObject list___imul__(PyObject o) {
        if (!o.isIndex()) {
            return null;
        }
        int count = o.asIndex(Py.OverflowError);

        int size = size();
        if (size == 0 || count == 1) {
            return this;
        }

        if (count < 1) {
            clear();
            return this;
        }

        if (size > Integer.MAX_VALUE / count) {
            throw Py.MemoryError("");
        }

        int newSize = size * count;
        if (list instanceof ArrayList) {
            ((ArrayList) list).ensureCapacity(newSize);
        }
        List oldList = new ArrayList(list);
        for (int i = 1; i < count; i++) {
            list.addAll(oldList);
        }
        gListAllocatedStatus = list.size(); // now omit?
        return this;
    }

    @Override
    public PyObject __mul__(PyObject o) {
        return list___mul__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___mul___doc)
    final synchronized PyObject list___mul__(PyObject o) {
        if (!o.isIndex()) {
            return null;
        }
        return repeat(o.asIndex(Py.OverflowError));
    }

    @Override
    public PyObject __rmul__(PyObject o) {
        return list___rmul__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___rmul___doc)
    final synchronized PyObject list___rmul__(PyObject o) {
        if (!o.isIndex()) {
            return null;
        }
        return repeat(o.asIndex(Py.OverflowError));
    }

    @Override
    public PyObject __add__(PyObject o) {
        return list___add__(o);
    }

    @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___add___doc)
    final synchronized PyObject list___add__(PyObject o) {
        PyList sum = null;
        if (o instanceof PySequenceList && !(o instanceof PyTuple)) {
            if (o instanceof PyList) {
                List oList = ((PyList) o).list;
                ArrayList newList = new ArrayList<>(list.size() + oList.size());
                newList.addAll(list);
                newList.addAll(oList);
                sum = fromList(newList);
            }
        } else if (!(o instanceof PySequenceList)) {
            // also support adding java lists (but not PyTuple!)
            Object oList = o.__tojava__(List.class);
            if (oList != Py.NoConversion && oList != null) {
                @SuppressWarnings("unchecked")
                List otherList = (List) oList;
                sum = new PyList();
                sum.list_extend(this);
                for (Object ob: otherList) {
                    sum.add(ob);
                }
            }
        }
        return sum;
    }

    @Override
    public PyObject __radd__(PyObject o) {
        return list___radd__(o);
    }

    //XXX: needs __doc__
    @SuppressWarnings("unchecked")
    @ExposedMethod(type = MethodType.BINARY)
    final synchronized PyObject list___radd__(PyObject o) {
        // Support adding java.util.List, but prevent adding PyTuple.
        // 'o' should never be a PyNewList since __add__ is defined.
        PyList sum = null;
        if (o instanceof PySequence) {
            return null;
        }
        Object oList = o.__tojava__(List.class);
        if (oList != Py.NoConversion && oList != null) {
            sum = new PyList();
            sum.addAll((List) oList);
            sum.extend(this);
        }
        return sum;
    }

    @ExposedMethod(doc = BuiltinDocs.list___contains___doc)
    final synchronized boolean list___contains__(PyObject o) {
        return object___contains__(o);
    }

    @ExposedMethod(doc = BuiltinDocs.list___delitem___doc)
    final synchronized void list___delitem__(PyObject index) {
        seq___delitem__(index);
    }

    @ExposedMethod(doc = BuiltinDocs.list___setitem___doc)
    final synchronized void list___setitem__(PyObject o, PyObject def) {
        seq___setitem__(o, def);
    }

    @ExposedMethod(doc = BuiltinDocs.list___getitem___doc)
    final synchronized PyObject list___getitem__(PyObject o) {
        PyObject ret = seq___finditem__(o);
        if (ret == null) {
            throw Py.IndexError("index out of range: " + o);
        }
        return ret;
    }

    @Override
    public PyObject __iter__() {
        return list___iter__();
    }

    @ExposedMethod(doc = BuiltinDocs.list___iter___doc)
    final PyObject list___iter__() {
        return new PyListIterator(this);
    }

    //@Override
    public PyIterator __reversed__() {
        return list___reversed__();
    }

    @ExposedMethod(doc = BuiltinDocs.list___reversed___doc)
    final synchronized PyIterator list___reversed__() {
        return new PyReversedIterator(this);
    }

    @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___getslice___doc)
    final synchronized PyObject list___getslice__(PyObject start, PyObject stop, PyObject step) {
        return seq___getslice__(start, stop, step);
    }

    @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___setslice___doc)
    final synchronized void list___setslice__(PyObject start, PyObject stop, PyObject step, PyObject value) {
        seq___setslice__(start, stop, step, value);
    }

    @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___delslice___doc)
    final synchronized void list___delslice__(PyObject start, PyObject stop, PyObject step) {
        seq___delslice__(start, stop, step);
    }

    @Override
    protected String unsupportedopMessage(String op, PyObject o2) {
        if (op.equals("+")) {
            return "can only concatenate list (not \"{2}\") to list";
        }
        return super.unsupportedopMessage(op, o2);
    }

    public String toString() {
        return list_toString();
    }

    //XXX: needs __doc__
    @ExposedMethod(names = "__repr__")
    final synchronized String list_toString() {
        ThreadState ts = Py.getThreadState();
        if (!ts.enterRepr(this)) {
            return "[...]";
        }
        StringBuilder buf = new StringBuilder("[");
        int length = size();
        int i = 0;
        for (PyObject item : list) {
            buf.append(item.__repr__().toString());
            if (i < length - 1) {
                buf.append(", ");
            }
            i++;
        }
        buf.append("]");
        ts.exitRepr(this);
        return buf.toString();
    }

    /**
     * Add a single element to the end of list.
     *
     * @param o
     *            the element to add.
     */
    public void append(PyObject o) {
        list_append(o);
    }

    @ExposedMethod(doc = BuiltinDocs.list_append_doc)
    final synchronized void list_append(PyObject o) {
        pyadd(o);
        gListAllocatedStatus = list.size();
    }

    /**
     * Return the number elements in the list that equals the argument.
     *
     * @param o
     *            the argument to test for. Testing is done with the == operator.
     */
    public int count(PyObject o) {
        return list_count(o);
    }

    @ExposedMethod(doc = BuiltinDocs.list_count_doc)
    final synchronized int list_count(PyObject o) {
        int count = 0;
        for (PyObject item : list) {
            if (item.equals(o)) {
                count++;
            }
        }
        return count;
    }

    /**
     * return smallest index where an element in the list equals the argument.
     *
     * @param o
     *            the argument to test for. Testing is done with the == operator.
     */
    public int index(PyObject o) {
        return index(o, 0);
    }

    public int index(PyObject o, int start) {
        return list_index(o, start, size());
    }

    public int index(PyObject o, int start, int stop) {
        return list_index(o, start, stop);
    }

    @ExposedMethod(defaults = {"null", "null"}, doc = BuiltinDocs.list_index_doc)
    final synchronized int list_index(PyObject o, PyObject start, PyObject stop) {
        int startInt = start == null ? 0 : PySlice.calculateSliceIndex(start);
        int stopInt = stop == null ? size() : PySlice.calculateSliceIndex(stop);
        return list_index(o, startInt, stopInt);
    }

    final synchronized int list_index(PyObject o, int start, int stop) {
        return _index(o, "list.index(x): x not in list", start, stop);
    }

    final synchronized int list_index(PyObject o, int start) {
        return _index(o, "list.index(x): x not in list", start, size());
    }

    final synchronized int list_index(PyObject o) {
        return _index(o, "list.index(x): x not in list", 0, size());
    }

    private int _index(PyObject o, String message, int start, int stop) {
        // Follow Python 2.3+ behavior
        int validStop = boundToSequence(stop);
        int validStart = boundToSequence(start);
        int i = validStart;
        if (validStart <= validStop) {
            try {
                for (PyObject item : list.subList(validStart, validStop)) {
                    if (item.equals(o)) {
                        return i;
                    }
                    i++;
                }
            } catch (ConcurrentModificationException ex) {
                throw Py.ValueError(message);
            }
        }
        throw Py.ValueError(message);
    }

    /**
     * Insert the argument element into the list at the specified index. 
* Same as s[index:index] = [o] if index >= 0. * * @param index * the position where the element will be inserted. * @param o * the element to insert. */ public void insert(int index, PyObject o) { list_insert(index, o); } @ExposedMethod(doc = BuiltinDocs.list_insert_doc) final synchronized void list_insert(int index, PyObject o) { if (index < 0) { index = Math.max(0, size() + index); } if (index > size()) { index = size(); } pyadd(index, o); gListAllocatedStatus = list.size(); } /** * Remove the first occurence of the argument from the list. The elements arecompared with the * == operator.
* Same as del s[s.index(x)] * * @param o * the element to search for and remove. */ public void remove(PyObject o) { list_remove(o); } @ExposedMethod(doc = BuiltinDocs.list_remove_doc) final synchronized void list_remove(PyObject o) { del(_index(o, "list.remove(x): x not in list", 0, size())); gListAllocatedStatus = list.size(); } /** * Reverses the items of s in place. The reverse() methods modify the list in place for economy * of space when reversing a large list. It doesn't return the reversed list to remind you of * this side effect. */ public void reverse() { list_reverse(); } @ExposedMethod(doc = BuiltinDocs.list_reverse_doc) final synchronized void list_reverse() { Collections.reverse(list); gListAllocatedStatus = list.size(); } /** * Removes and return the last element in the list. */ public PyObject pop() { return pop(-1); } /** * Removes and return the n indexed element in the list. * * @param n * the index of the element to remove and return. */ public PyObject pop(int n) { return list_pop(n); } @ExposedMethod(defaults = "-1", doc = BuiltinDocs.list_pop_doc) final synchronized PyObject list_pop(int n) { int length = size(); if (length == 0) { throw Py.IndexError("pop from empty list"); } if (n < 0) { n += length; } if (n < 0 || n >= length) { throw Py.IndexError("pop index out of range"); } PyObject v = list.remove(n); return v; } /** * Append the elements in the argument sequence to the end of the list.
* Same as s[len(s):len(s)] = o. * * @param o * the sequence of items to append to the list. */ public void extend(PyObject o) { list_extend(o); } @ExposedMethod(doc = BuiltinDocs.list_extend_doc) final synchronized void list_extend(PyObject o) { if (o instanceof PyList) { list.addAll(((PyList) o).list); } else { for (PyObject item : o.asIterable()) { list.add(item); } } gListAllocatedStatus = list.size(); } @Override public PyObject __iadd__(PyObject o) { return list___iadd__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___iadd___doc) final synchronized PyObject list___iadd__(PyObject o) { PyType oType = o.getType(); if (oType == TYPE || oType == PyTuple.TYPE || this == o) { extend(fastSequence(o, "argument must be iterable")); return this; } PyObject it; try { it = o.__iter__(); } catch (PyException pye) { if (!pye.match(Py.TypeError)) { throw pye; } return null; } extend(it); return this; } /** * Sort the items of the list in place. The compare argument is a function of two arguments * (list items) which should return -1, 0 or 1 depending on whether the first argument is * considered smaller than, equal to, or larger than the second argument. Note that this slows * the sorting process down considerably; e.g. to sort a list in reverse order it is much faster * to use calls to the methods sort() and reverse() than to use the built-in function sort() * with a comparison function that reverses the ordering of the elements. * * @param compare * the comparison function. */ /** * Sort the items of the list in place. Items is compared with the normal relative comparison * operators. */ @ExposedMethod(doc = BuiltinDocs.list_sort_doc) final synchronized void list_sort(PyObject[] args, String[] kwds) { ArgParser ap = new ArgParser("list", args, kwds, new String[]{"cmp", "key", "reverse"}, 0); PyObject cmp = ap.getPyObject(0, Py.None); PyObject key = ap.getPyObject(1, Py.None); PyObject reverse = ap.getPyObject(2, Py.False); sort(cmp, key, reverse); } public void sort(PyObject cmp, PyObject key, PyObject reverse) { boolean bReverse = reverse.__nonzero__(); if (key == Py.None || key == null) { if (cmp == Py.None || cmp == null) { sort(bReverse); } else { sort(cmp, bReverse); } } else { sort(cmp, key, bReverse); } } // a bunch of optimized paths for sort to avoid unnecessary work, such as DSU or checking compare functions for null public void sort() { sort(false); } private synchronized void sort(boolean reverse) { gListAllocatedStatus = -1; if (reverse) { Collections.reverse(list); // maintain stability of sort by reversing first } final PyObjectDefaultComparator comparator = new PyObjectDefaultComparator(this); Collections.sort(list, comparator); if (comparator.raisedException()) { throw comparator.getRaisedException(); } if (reverse) { Collections.reverse(list); // maintain stability of sort by reversing first } gListAllocatedStatus = list.size(); } private static class PyObjectDefaultComparator implements Comparator { private final PyList list; private PyException comparatorException; PyObjectDefaultComparator(PyList list) { this.list = list; } public PyException getRaisedException() { return comparatorException; } public boolean raisedException() { return comparatorException != null; } @Override public int compare(PyObject o1, PyObject o2) { // PEP 207 specifies that sort should only depend on "less-than" (Issue #1767) int result = 0; // If exception is raised return objects are equal try { if (o1._lt(o2).__nonzero__()) { result = -1; } else if (o2._lt(o1).__nonzero__()) { result = 1; } } catch (PyException pye) { // #2399 Stash the exception so we can rethrow it later, and allow the sort to continue comparatorException = pye; } if (this.list.gListAllocatedStatus >= 0) { throw Py.ValueError("list modified during sort"); } return result; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof PyObjectDefaultComparator) { return true; } return false; } } public void sort(PyObject compare) { sort(compare, false); } private synchronized void sort(PyObject compare, boolean reverse) { gListAllocatedStatus = -1; if (reverse) { Collections.reverse(list); // maintain stability of sort by reversing first } final PyObjectComparator comparator = new PyObjectComparator(this, compare); Collections.sort(list, comparator); if (comparator.raisedException()) { throw comparator.getRaisedException(); } if (reverse) { Collections.reverse(list); } gListAllocatedStatus = list.size(); } private static class PyObjectComparator implements Comparator { private final PyList list; private final PyObject cmp; private PyException comparatorException; PyObjectComparator(PyList list, PyObject cmp) { this.list = list; this.cmp = cmp; } public PyException getRaisedException() { return comparatorException; } public boolean raisedException() { return comparatorException != null; } @Override public int compare(PyObject o1, PyObject o2) { int result = 0; // If exception is raised return objects are equal try { result = cmp.__call__(o1, o2).asInt(); } catch (PyException pye) { // #2399 Stash the exception so we can rethrow it later, and allow the sort to continue comparatorException = pye; } if (this.list.gListAllocatedStatus >= 0) { throw Py.ValueError("list modified during sort"); } return result; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof PyObjectComparator) { return cmp.equals(((PyObjectComparator) o).cmp); } return false; } } private static class KV { private final PyObject key; private final PyObject value; KV(PyObject key, PyObject value) { this.key = key; this.value = value; } } private static class KVComparator implements Comparator { private final PyList list; private final PyObject cmp; KVComparator(PyList list, PyObject cmp) { this.list = list; this.cmp = cmp; } public int compare(KV o1, KV o2) { int result; if (cmp != null && cmp != Py.None) { result = cmp.__call__(o1.key, o2.key).asInt(); } else { // PEP 207 specifies that sort should only depend on "less-than" (Issue #1767) if (o1.key._lt(o2.key).__nonzero__()) { result = -1; } else if (o2.key._lt(o1.key).__nonzero__()) { result = 1; } else { result = 0; } } if (this.list.gListAllocatedStatus >= 0) { throw Py.ValueError("list modified during sort"); } return result; } public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof KVComparator) { return cmp.equals(((KVComparator) o).cmp); } return false; } } private synchronized void sort(PyObject cmp, PyObject key, boolean reverse) { gListAllocatedStatus = -1; int size = list.size(); final ArrayList decorated = new ArrayList(size); for (PyObject value : list) { decorated.add(new KV(key.__call__(value), value)); } list.clear(); KVComparator c = new KVComparator(this, cmp); if (reverse) { Collections.reverse(decorated); // maintain stability of sort by reversing first } Collections.sort(decorated, c); if (reverse) { Collections.reverse(decorated); } if (list instanceof ArrayList) { ((ArrayList) list).ensureCapacity(size); } for (KV kv : decorated) { list.add(kv.value); } gListAllocatedStatus = list.size(); } public int hashCode() { return list___hash__(); } @ExposedMethod(doc = BuiltinDocs.list___hash___doc) final synchronized int list___hash__() { throw Py.TypeError(String.format("unhashable type: '%.200s'", getType().fastGetName())); } @Override public PyTuple __getnewargs__() { return new PyTuple(new PyTuple(getArray())); } @Override public void add(int index, Object element) { pyadd(index, Py.java2py(element)); } @Override public boolean add(Object o) { pyadd(Py.java2py(o)); return true; } @Override public synchronized boolean addAll(int index, Collection c) { PyList elements = new PyList(c); return list.addAll(index, elements.list); } @Override public boolean addAll(Collection c) { return addAll(0, c); } @Override public synchronized void clear() { list.clear(); } @Override public synchronized boolean contains(Object o) { return list.contains(Py.java2py(o)); } @Override public synchronized boolean containsAll(Collection c) { if (c instanceof PyList) { return list.containsAll(((PyList) c).list); } else if (c instanceof PyTuple) { return list.containsAll(((PyTuple) c).getList()); } else { return list.containsAll(new PyList(c)); } } @Override public boolean equals(Object other) { if (this == other) { return true; } if (other instanceof PyObject) { synchronized (this) { return _eq((PyObject)other).__nonzero__(); } } if (other instanceof List) { synchronized (this) { return list.equals(other); } } return false; } @Override public synchronized Object get(int index) { return list.get(index).__tojava__(Object.class); } @Override public synchronized PyObject[] getArray() { return list.toArray(Py.EmptyObjects); } @Override public synchronized int indexOf(Object o) { return list.indexOf(Py.java2py(o)); } @Override public synchronized boolean isEmpty() { return list.isEmpty(); } @Override public Iterator iterator() { return new Iterator() { private final Iterator iter = list.iterator(); public boolean hasNext() { return iter.hasNext(); } public Object next() { return iter.next().__tojava__(Object.class); } public void remove() { iter.remove(); } }; } @Override public synchronized int lastIndexOf(Object o) { return list.lastIndexOf(Py.java2py(o)); } @Override public ListIterator listIterator() { return listIterator(0); } @Override public ListIterator listIterator(final int index) { return new ListIterator() { private final ListIterator iter = list.listIterator(index); public boolean hasNext() { return iter.hasNext(); } public Object next() { return iter.next().__tojava__(Object.class); } public boolean hasPrevious() { return iter.hasPrevious(); } public Object previous() { return iter.previous().__tojava__(Object.class); } public int nextIndex() { return iter.nextIndex(); } public int previousIndex() { return iter.previousIndex(); } public void remove() { iter.remove(); } public void set(Object o) { iter.set(Py.java2py(o)); } public void add(Object o) { iter.add(Py.java2py(o)); } }; } @Override public synchronized void pyadd(int index, PyObject element) { list.add(index, element); } @Override public synchronized boolean pyadd(PyObject o) { list.add(o); return true; } @Override public synchronized PyObject pyget(int index) { return list.get(index); } public synchronized void pyset(int index, PyObject element) { list.set(index, element); } @Override public synchronized Object remove(int index) { return list.remove(index); } @Override public synchronized void remove(int start, int stop) { list.subList(start, stop).clear(); } @Override public synchronized boolean removeAll(Collection c) { if (c instanceof PySequenceList) { return list.removeAll(c); } else { return list.removeAll(new PyList(c)); } } @Override public synchronized boolean retainAll(Collection c) { if (c instanceof PySequenceList) { return list.retainAll(c); } else { return list.retainAll(new PyList(c)); } } @Override public synchronized Object set(int index, Object element) { return list.set(index, Py.java2py(element)).__tojava__(Object.class); } @Override public synchronized int size() { return list.size(); } @Override public synchronized List subList(int fromIndex, int toIndex) { return fromList(list.subList(fromIndex, toIndex)); } @Override public synchronized Object[] toArray() { Object copy[] = list.toArray(); for (int i = 0; i < copy.length; i++) { copy[i] = ((PyObject) copy[i]).__tojava__(Object.class); } return copy; } @Override public synchronized Object[] toArray(Object[] a) { int size = size(); Class type = a.getClass().getComponentType(); if (a.length < size) { a = (Object[])Array.newInstance(type, size); } for (int i = 0; i < size; i++) { a[i] = list.get(i).__tojava__(type); } if (a.length > size) { for (int i = size; i < a.length; i++) { a[i] = null; } } return a; } protected PyObject getslice(int start, int stop, int step) { if (step > 0 && stop < start) { stop = start; } int n = sliceLength(start, stop, step); List newList; if (step == 1) { newList = new ArrayList(list.subList(start, stop)); } else { newList = new ArrayList(n); for (int i = start, j = 0; j < n; i += step, j++) { newList.add(list.get(i)); } } return fromList(newList); } @Override public synchronized boolean remove(Object o) { return list.remove(Py.java2py(o)); } /* Traverseproc implementation */ @Override public int traverse(Visitproc visit, Object arg) { if (list != null) { int retVal; for (PyObject ob: list) { if (ob != null) { retVal = visit.visit(ob, arg); if (retVal != 0) { return retVal; } } } } return 0; } @Override public boolean refersDirectlyTo(PyObject ob) { return list == null ? false : list.contains(ob); } }