Skip to content

Commit 8122f8a

Browse files
authored
Miscellaneous improvements in deque (IronLanguages#1942)
1 parent 44c07c4 commit 8122f8a

File tree

2 files changed

+69
-6
lines changed

2 files changed

+69
-6
lines changed

src/core/IronPython.Modules/_collections.cs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -572,14 +572,20 @@ public deque InPlaceAdd(object other) {
572572

573573
#region binary operators
574574

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

580-
public static deque operator +([NotNone] deque x, [NotNone] deque y) {
581-
var d = new deque(x._maxLen);
582-
d.extend(x);
581+
[SpecialName]
582+
public static deque Add(CodeContext context, [NotNone] deque x, [NotNone] deque y) {
583+
var d = (deque)__new__(context, DynamicHelpers.GetPythonType(x), null, null);
584+
if (x._maxLen > 0) {
585+
d.__init__(x, x._maxLen);
586+
} else {
587+
d.__init__(x);
588+
}
583589
d.extend(y);
584590
return d;
585591
}
@@ -812,6 +818,27 @@ public int __length_hint__() {
812818

813819
#region private members
814820

821+
private object[] GetObjectArray() {
822+
lock (_lockObj) {
823+
if (_itemCnt == 0) return [];
824+
825+
object[] arr = new object[_itemCnt];
826+
int cnt1, cnt2;
827+
if (_head >= _tail) {
828+
cnt1 = _data.Length - _head;
829+
cnt2 = _itemCnt - cnt1;
830+
} else {
831+
cnt1 = _itemCnt;
832+
cnt2 = 0;
833+
}
834+
835+
Array.Copy(_data, _head, arr, 0, cnt1);
836+
Array.Copy(_data, 0, arr, cnt1, cnt2);
837+
return arr;
838+
}
839+
}
840+
841+
815842
private void GrowArray() {
816843
// do nothing if array is already at its max length
817844
if (_data.Length == _maxLen) return;
@@ -962,7 +989,7 @@ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
962989
int res;
963990
CompareUtil.Push(this);
964991
try {
965-
res = ((IStructuralEquatable)new PythonTuple(this)).GetHashCode(comparer);
992+
res = ((IStructuralEquatable)PythonTuple.MakeTuple(GetObjectArray())).GetHashCode(comparer);
966993
} finally {
967994
CompareUtil.Pop(this);
968995
}

tests/suite/test_deque.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,40 @@ def test_maxlen_value(self):
5252
self.assertRaises(OverflowError, deque, [], -1<<64)
5353
self.assertRaisesMessage(ValueError, "maxlen must be non-negative", deque, [], -1)
5454

55+
56+
def test_add(self):
57+
d1 = deque([1, 2, 3], maxlen=6)
58+
d2 = deque([4, 5, 6], maxlen=4)
59+
d2 = deque([4, 5, 6])
60+
d3 = d1 + d2
61+
self.assertEqual(d3, deque([1, 2, 3, 4, 5, 6]))
62+
self.assertIsInstance(d3, deque)
63+
self.assertEqual(d3.maxlen, 6)
64+
65+
class Deque(deque): pass
66+
sd1 = Deque([1, 2, 3])
67+
sd2 = Deque([4, 5, 6])
68+
sd3 = sd1 + sd2
69+
self.assertEqual(sd3, deque([1, 2, 3, 4, 5, 6]))
70+
self.assertIsInstance(sd3, Deque)
71+
72+
73+
def test_multiply(self):
74+
class Deque(deque): pass
75+
d1 = Deque([1, 2, 3], maxlen=6)
76+
d2 = d1 * 2
77+
self.assertEqual(d2, deque([1, 2, 3, 1, 2, 3]))
78+
self.assertIsInstance(d2, deque)
79+
80+
81+
def test_copy(self):
82+
import copy
83+
class Deque(deque): pass
84+
original = Deque([1, 2, 3], 6)
85+
copy_instance = copy.copy(original)
86+
self.assertEqual(original, copy_instance)
87+
self.assertIsNot(original, copy_instance)
88+
self.assertIsInstance(copy_instance, deque)
89+
90+
5591
run_test(__name__)

0 commit comments

Comments
 (0)