Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions src/core/IronPython.Modules/_collections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -572,14 +572,20 @@ public deque InPlaceAdd(object other) {

#region binary operators

public static deque operator +([NotNone] deque x, object y) {
if (y is deque t) return x + t;
[SpecialName]
public static deque Add(CodeContext context, [NotNone] deque x, object y) {
if (y is deque t) return Add(context, x, t);
throw PythonOps.TypeError($"can only concatenate deque (not \"{PythonOps.GetPythonTypeName(y)}\") to deque");
}

public static deque operator +([NotNone] deque x, [NotNone] deque y) {
var d = new deque(x._maxLen);
d.extend(x);
[SpecialName]
public static deque Add(CodeContext context, [NotNone] deque x, [NotNone] deque y) {
var d = (deque)__new__(context, DynamicHelpers.GetPythonType(x), null, null);
if (x._maxLen > 0) {
d.__init__(x, x._maxLen);
} else {
d.__init__(x);
}
d.extend(y);
return d;
}
Expand Down Expand Up @@ -812,6 +818,27 @@ public int __length_hint__() {

#region private members

private object[] GetObjectArray() {
lock (_lockObj) {
if (_itemCnt == 0) return [];

object[] arr = new object[_itemCnt];
int cnt1, cnt2;
if (_head >= _tail) {
cnt1 = _data.Length - _head;
cnt2 = _itemCnt - cnt1;
} else {
cnt1 = _itemCnt;
cnt2 = 0;
}

Array.Copy(_data, _head, arr, 0, cnt1);
Array.Copy(_data, 0, arr, cnt1, cnt2);
return arr;
}
}


private void GrowArray() {
// do nothing if array is already at its max length
if (_data.Length == _maxLen) return;
Expand Down Expand Up @@ -961,7 +988,7 @@ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
int res;
CompareUtil.Push(this);
try {
res = ((IStructuralEquatable)new PythonTuple(this)).GetHashCode(comparer);
res = ((IStructuralEquatable)PythonTuple.MakeTuple(GetObjectArray())).GetHashCode(comparer);
} finally {
CompareUtil.Pop(this);
}
Expand Down
36 changes: 36 additions & 0 deletions tests/suite/test_deque.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,40 @@ def test_maxlen_value(self):
self.assertRaises(OverflowError, deque, [], -1<<64)
self.assertRaisesMessage(ValueError, "maxlen must be non-negative", deque, [], -1)


def test_add(self):
d1 = deque([1, 2, 3], maxlen=6)
d2 = deque([4, 5, 6], maxlen=4)
d2 = deque([4, 5, 6])
d3 = d1 + d2
self.assertEqual(d3, deque([1, 2, 3, 4, 5, 6]))
self.assertIsInstance(d3, deque)
self.assertEqual(d3.maxlen, 6)

class Deque(deque): pass
sd1 = Deque([1, 2, 3])
sd2 = Deque([4, 5, 6])
sd3 = sd1 + sd2
self.assertEqual(sd3, deque([1, 2, 3, 4, 5, 6]))
self.assertIsInstance(sd3, Deque)


def test_multiply(self):
class Deque(deque): pass
d1 = Deque([1, 2, 3], maxlen=6)
d2 = d1 * 2
self.assertEqual(d2, deque([1, 2, 3, 1, 2, 3]))
self.assertIsInstance(d2, deque)


def test_copy(self):
import copy
class Deque(deque): pass
original = Deque([1, 2, 3], 6)
copy_instance = copy.copy(original)
self.assertEqual(original, copy_instance)
self.assertIsNot(original, copy_instance)
self.assertIsInstance(copy_instance, deque)


run_test(__name__)
Loading