Skip to content

dev(hansbug): add update method #56

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Jul 6, 2022
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
2 changes: 1 addition & 1 deletion docs/source/api_doc/tree/tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ TreeValue
---------------

.. autoclass:: TreeValue
: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, clear
: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, clear, update


.. _apidoc_tree_tree_delayed:
Expand Down
49 changes: 49 additions & 0 deletions test/tree/tree/test_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pytest

from treevalue import raw, TreeValue, delayed
from treevalue.tree.common import create_storage

try:
_ = reversed({}.keys())
Expand Down Expand Up @@ -360,6 +361,54 @@ def test_clear(self):
assert tv1.clear() is None
assert not tv1

# noinspection DuplicatedCode
def test_update(self):
tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
tv1.update({'a': 3, 'c': TreeValue({'x': 3, 'y': 4}), 'd': {'x': 200, 'y': 300}})
assert tv1 == TreeValue({
'a': 3, 'b': 2,
'c': {'x': 3, 'y': 4},
'd': raw({'x': 200, 'y': 300}),
})

tv2 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
tv2.update(a=3, c=TreeValue({'x': 3, 'y': 4}), d={'x': 200, 'y': 300})
assert tv2 == TreeValue({
'a': 3, 'b': 2,
'c': {'x': 3, 'y': 4},
'd': raw({'x': 200, 'y': 300}),
})

tv3 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
tv3.update(TreeValue({'a': 3, 'c': {'x': 3, 'y': 4}, 'd': raw({'x': 200, 'y': 300})}))
assert tv3 == TreeValue({
'a': 3, 'b': 2,
'c': {'x': 3, 'y': 4},
'd': raw({'x': 200, 'y': 300}),
})

tv4 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
tv4.update(create_storage({'a': 3, 'c': {'x': 3, 'y': 4}, 'd': raw({'x': 200, 'y': 300})}))
assert tv4 == TreeValue({
'a': 3, 'b': 2,
'c': {'x': 3, 'y': 4},
'd': raw({'x': 200, 'y': 300}),
})

tv5 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
with pytest.raises(TypeError):
tv5.update('sdklfj')
with pytest.raises(TypeError):
tv5.update(123)

tv6 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
tv6.update({'a': 3, 'c': TreeValue({'x': 3, 'y': 4}), 'd': {'x': 200, 'y': 300}}, a=50, f='dfkl')
assert tv6 == TreeValue({
'a': 50, 'b': 2, 'f': 'dfkl',
'c': {'x': 3, 'y': 4},
'd': raw({'x': 200, 'y': 300}),
})

def test_keys(self):
tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})})
assert len(tv1.keys()) == 4
Expand Down
17 changes: 9 additions & 8 deletions treevalue/tree/tree/tree.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ cdef class TreeValue:
cpdef _getitem_extern(self, object key)
cpdef _setitem_extern(self, object key, object value)
cpdef _delitem_extern(self, object key)
cpdef get(self, str key, object default= *)
cpdef pop(self, str key, object default= *)
cpdef popitem(self)
cpdef void clear(self)

cpdef treevalue_keys keys(self)
cpdef treevalue_values values(self)
cpdef treevalue_items items(self)
cdef void _update(self, object d, dict kwargs) except *
cpdef public get(self, str key, object default= *)
cpdef public pop(self, str key, object default= *)
cpdef public popitem(self)
cpdef public void clear(self)

cpdef public treevalue_keys keys(self)
cpdef public treevalue_values values(self)
cpdef public treevalue_items items(self)

cdef str _prefix_fix(object text, object prefix)
cdef str _title_repr(TreeStorage st, object type_)
Expand Down
68 changes: 67 additions & 1 deletion treevalue/tree/tree/tree.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# cython:language_level=3

import os
from collections.abc import Sized, Container, Reversible
from collections.abc import Sized, Container, Reversible, Mapping
from operator import itemgetter

import cython
Expand Down Expand Up @@ -169,6 +169,72 @@ cdef class TreeValue:
"""
self._st.clear()

cdef void _update(self, object d, dict kwargs) except *:
cdef object dt
if d is None:
dt = {}
elif isinstance(d, Mapping):
dt = d
elif isinstance(d, TreeValue):
dt = d._detach().detach()
elif isinstance(d, TreeStorage):
dt = d.detach()
else:
raise TypeError(f'Invalid type of update dict - {type(d)!r}.')

cdef str key
cdef object value
for key, value in dt.items():
self._st.set(key, self._raw(value))
for key, value in kwargs.items():
self._st.set(key, self._raw(value))

@cython.binding(True)
def update(self, __update_dict=None, **kwargs):
"""
Overview:
Update items in current treevalue.

:param __update_dict: Dictionary object for updating.
:param kwargs: Arguments for updating.

.. note::
The method :meth:`update` is similar to \
`dict.update <https://docs.python.org/3/library/stdtypes.html#dict.update>`_.

Examples::
>>> from treevalue import TreeValue
>>>
>>> t = TreeValue({'a': 1, 'b': 3, 'c': '233'})
>>> t.update({'a': 10, 'f': 'sdkj'}) # with dict
>>> t
<TreeValue 0x7fa31f5ba048>
├── 'a' --> 10
├── 'b' --> 3
├── 'c' --> '233'
└── 'f' --> 'sdkj'
>>>
>>> t.update(a=100, ft='fffff') # with key-word arguments
>>> t
<TreeValue 0x7fa31f5ba048>
├── 'a' --> 100
├── 'b' --> 3
├── 'c' --> '233'
├── 'f' --> 'sdkj'
└── 'ft' --> 'fffff'
>>>
>>> t.update(TreeValue({'f': {'x': 1}, 'b': 40})) # with TreeValue
>>> t
<TreeValue 0x7fa31f5ba048>
├── 'a' --> 100
├── 'b' --> 40
├── 'c' --> '233'
├── 'f' --> <TreeValue 0x7fa31f5ba278>
│ └── 'x' --> 1
└── 'ft' --> 'fffff'
"""
self._update(__update_dict, kwargs)

@cython.binding(True)
cpdef _attr_extern(self, str key):
r"""
Expand Down