Skip to content

Commit a144b91

Browse files
authored
Merge pull request #52 from opendilab/dev/mutablemapping
dev(hansbug): add popitem method for TreeValue
2 parents 17cdc03 + 5c6ea4d commit a144b91

File tree

7 files changed

+76
-1
lines changed

7 files changed

+76
-1
lines changed

docs/source/api_doc/tree/tree.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ TreeValue
99
---------------
1010

1111
.. autoclass:: TreeValue
12-
:members: __init__, __getattribute__, __setattr__, __delattr__, __contains__, __repr__, __iter__, __hash__, __eq__, _attr_extern, __len__, __bool__, __str__, __getstate__, __setstate__, get, pop, keys, values, items, __getitem__, __setitem__, __delitem__, _getitem_extern, _setitem_extern, _delitem_extern
12+
:members: __init__, __getattribute__, __setattr__, __delattr__, __contains__, __repr__, __iter__, __hash__, __eq__, _attr_extern, __len__, __bool__, __str__, __getstate__, __setstate__, get, pop, keys, values, items, __getitem__, __setitem__, __delitem__, _getitem_extern, _setitem_extern, _delitem_extern, popitem
1313

1414

1515
.. _apidoc_tree_tree_delayed:

test/tree/common/test_storage.py

+27
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,33 @@ def test_pop_or_default(self):
208208
assert t1.pop_or_default('fff', delayed_partial(lambda: 2345)) == 2345
209209
assert not t1.contains('fff')
210210

211+
def test_popitem(self):
212+
t = create_storage({})
213+
with pytest.raises(KeyError):
214+
t.popitem()
215+
216+
t1 = create_storage({'a': 1, 'b': 2, 'c': {'x': 2}})
217+
assert sorted([t1.popitem() for _ in range(t1.size())]) == [
218+
('a', 1), ('b', 2), ('c', create_storage({'x': 2}))
219+
]
220+
221+
t2 = create_storage({
222+
'a': delayed_partial(lambda: 1),
223+
'b': delayed_partial(lambda: 2),
224+
})
225+
assert sorted([t2.popitem() for _ in range(t2.size())]) == [
226+
('a', 1), ('b', 2)
227+
]
228+
229+
d1 = delayed_partial(lambda: 1)
230+
d2 = delayed_partial(lambda x: x + 1, d1)
231+
t3 = create_storage({
232+
'a': d1, 'b': d2, 'c': d1,
233+
})
234+
assert sorted([t3.popitem() for _ in range(t3.size())]) == [
235+
('a', 1), ('b', 2), ('c', 1)
236+
]
237+
211238
def test_set(self):
212239
t = create_storage({})
213240
t.set('a', 1)

test/tree/tree/test_tree.py

+19
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,25 @@ def test_pop(self):
336336
assert tv3.pop('b', 345) == 345
337337
assert tv3.pop('c', 345) == 345
338338

339+
def test_popitem(self):
340+
tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
341+
assert sorted([tv1.popitem() for _ in range(len(tv1))]) == [
342+
('a', 1), ('b', 2),
343+
('c', TreeValue({'x': 2, 'y': 3})),
344+
('d', {'x': 2, 'y': 3}),
345+
]
346+
with pytest.raises(KeyError):
347+
tv1.popitem()
348+
349+
d1 = delayed(lambda: 1)
350+
d2 = delayed(lambda x: x + 1, d1)
351+
tv2 = TreeValue({'a': d1, 'b': d2, 'c': d1, 'd': 100})
352+
assert sorted([tv2.popitem() for _ in range(len(tv2))]) == [
353+
('a', 1), ('b', 2), ('c', 1), ('d', 100),
354+
]
355+
with pytest.raises(KeyError):
356+
tv2.popitem()
357+
339358
def test_keys(self):
340359
tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
341360
assert len(tv1.keys()) == 4

treevalue/tree/common/storage.pxd

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ cdef class TreeStorage:
1414
cpdef public object get_or_default(self, str key, object default)
1515
cpdef public object pop(self, str key)
1616
cpdef public object pop_or_default(self, str key, object default)
17+
cpdef public tuple popitem(self)
1718
cpdef public void del_(self, str key) except *
1819
cpdef public boolean contains(self, str key)
1920
cpdef public uint size(self)

treevalue/tree/common/storage.pyx

+6
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ cdef class TreeStorage:
5555
del self.map[key]
5656
return res
5757

58+
cpdef public tuple popitem(self):
59+
cdef str k
60+
cdef object v
61+
k, v = self.map.popitem()
62+
return k, undelay(v)
63+
5864
cpdef public void del_(self, str key) except *:
5965
try:
6066
del self.map[key]

treevalue/tree/tree/tree.pxd

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ cdef class TreeValue:
2222
cpdef _delitem_extern(self, object key)
2323
cpdef get(self, str key, object default= *)
2424
cpdef pop(self, str key, object default= *)
25+
cpdef popitem(self)
2526

2627
cpdef treevalue_keys keys(self)
2728
cpdef treevalue_values values(self)

treevalue/tree/tree/tree.pyx

+21
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,27 @@ cdef class TreeValue:
140140

141141
return self._unraw(value)
142142

143+
@cython.binding(True)
144+
cpdef popitem(self):
145+
"""
146+
Overview:
147+
Pop item (with a key and its value) from the tree node.
148+
149+
:return: Popped item.
150+
:raise KeyError: When current treevalue is empty.
151+
152+
.. note::
153+
The method :meth:`popitem` will raise ``KeyError`` when empty, like the behaviour in \
154+
`dict.popitem <https://docs.python.org/3/library/stdtypes.html#dict.popitem>`_.
155+
"""
156+
cdef str k
157+
cdef object v
158+
try:
159+
k, v = self._st.popitem()
160+
return k, self._unraw(v)
161+
except KeyError:
162+
raise KeyError(f'popitem(): {self._type.__name__} is empty.')
163+
143164
@cython.binding(True)
144165
cpdef _attr_extern(self, str key):
145166
r"""

0 commit comments

Comments
 (0)