Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

dev(hansbug): add delay feature in treevalue && add mode and missing option to union and subside #23

Merged
merged 29 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
94d4d9f
dev(hansbug): add delayed proxy into treevalue base
HansBug Dec 28, 2021
0089695
dev(hansbug): add all delay support in storage
HansBug Dec 28, 2021
683b07e
dev(hansbug): update get_or_default && add test for __hash__ of TreeS…
HansBug Dec 28, 2021
787b277
dev(hansbug): fix bug of deepcopyx && add lazy delay when no-deep copy
HansBug Dec 28, 2021
da028d5
dev(hansbug): add detached delay proxy
HansBug Dec 28, 2021
82b3207
dev(hansbug): add delay support in flatten.pyx
HansBug Dec 28, 2021
6e13476
dev(hansbug): test delayed flatten
HansBug Dec 28, 2021
9e515b9
dev(hansbug): add delay support for service part
HansBug Dec 28, 2021
cd9eab6
dev(hansbug): add delay support for function treelize
HansBug Dec 28, 2021
f399075
dev(hansbug): add delayed support in functional part
HansBug Dec 28, 2021
5490a78
dev(hansbug): add delayed support for structural part
HansBug Dec 28, 2021
3b089d2
dev(hansbug): add object to _c_common_value
HansBug Dec 29, 2021
c102d03
dev(hansbug): add missing option in subside
HansBug Dec 29, 2021
bb3fb6a
dev(hansbug): add mode, missing function to subside and union
HansBug Dec 29, 2021
b6ad686
dev(hansbug): add doc for delayed
HansBug Dec 29, 2021
007df0b
dev(hansbug): complete doc for delayed part
HansBug Dec 29, 2021
38d94a8
dev(hansbug): add delayed mode to mapping
HansBug Dec 29, 2021
5844679
dev(hansbug): _c_delayed_mapping use cdef instead of def
HansBug Dec 29, 2021
a95cdaa
dev(hansbug): add delayed support to map method
HansBug Dec 29, 2021
a114920
dev(hansbug): merge from main branch
HansBug Dec 30, 2021
7f63f2d
dev(hansbug): remove useless cimport line
HansBug Dec 30, 2021
7078368
Merge branch 'main' into dev/delay
HansBug Dec 31, 2021
3a738c4
dev(hansbug): add base delayed option (not implemented)
HansBug Jan 1, 2022
33ac4c6
dev(hansbug): complete delayed mode for func_treelize
HansBug Jan 1, 2022
401b495
dev(hansbug): add delayed for subside and union
HansBug Jan 1, 2022
1213bcd
dev(hansbug): add delay test for FastTreeValue.func
HansBug Jan 1, 2022
4091183
test(hansbug): add delayed test for union and subside
HansBug Jan 1, 2022
8e35899
Merge branch 'main' into dev/delay
HansBug Jan 1, 2022
17c2ac4
dev(hansbug): use _c_undelay_data when checkout datas
HansBug Jan 2, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 43 additions & 0 deletions docs/source/api_doc/tree/common.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,46 @@ RawWrapper
.. autoclass:: RawWrapper
:members: __init__, value


.. _apidoc_tree_common_delayed_partial:

delayed_partial
----------------------

.. autofunction:: delayed_partial


.. _apidoc_tree_common_undelay:

undelay
---------------

.. autofunction:: undelay


.. _apidoc_tree_common_delayedproxy:

DelayedProxy
-------------------

.. autoclass:: DelayedProxy
:members: value, fvalue


.. _apidoc_tree_common_delayedvalueproxy:

DelayedValueProxy
-------------------

.. autoclass:: DelayedValueProxy
:members: __cinit__, value, fvalue


.. _apidoc_tree_common_delayedfuncproxy:

DelayedFuncProxy
-------------------

.. autoclass:: DelayedFuncProxy
:members: __cinit__, value, fvalue

8 changes: 8 additions & 0 deletions docs/source/api_doc/tree/tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ TreeValue
:members: __init__, __getattribute__, __setattr__, __delattr__, __contains__, __repr__, __iter__, __hash__, __eq__, _attr_extern, __len__, __bool__, __str__, __getstate__, __setstate__, get


.. _apidoc_tree_tree_delayed:

delayed
---------------

.. autofunction:: delayed


.. _apidoc_tree_tree_jsonify:

jsonify
Expand Down
2 changes: 1 addition & 1 deletion requirements-doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ sphinx~=3.2.0
sphinx_rtd_theme~=0.4.3
enum_tools
sphinx-toolbox
plantumlcli>=0.0.2
plantumlcli>=0.0.4
packaging
sphinx-multiversion~=0.2.4
where~=1.0.2
Expand Down
68 changes: 68 additions & 0 deletions test/tree/common/test_delay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import pytest

from treevalue.tree.common import DelayedProxy, delayed_partial


@pytest.mark.unittest
class TestTreeDelay:
def test_delayed_partial_simple(self):
cnt = 0

def f():
nonlocal cnt
cnt += 1
return 1

pv = delayed_partial(f)
assert cnt == 0
assert isinstance(pv, DelayedProxy)

assert pv.value() == 1
assert cnt == 1

assert pv.value() == 1
assert cnt == 1

def test_delayed_partial_func(self):
cnt = 0

def f(x, y):
nonlocal cnt
cnt += 1
return x + y * 2 + 1

pv = delayed_partial(f, 2, y=3)
assert cnt == 0
assert isinstance(pv, DelayedProxy)

assert pv.value() == 9
assert cnt == 1

assert pv.value() == 9
assert cnt == 1

def test_delayed_partial_complex(self):
cnt1, cnt2 = 0, 0

def f1():
nonlocal cnt1
cnt1 += 1
return 1

def f2(x, y):
nonlocal cnt2
cnt2 += 1
return (x + 1) ** 2 + y + 2

pv = delayed_partial(f2, delayed_partial(f1), delayed_partial(f1))
assert cnt1 == 0
assert cnt2 == 0
assert isinstance(pv, DelayedProxy)

assert pv.value() == 7
assert cnt1 == 2
assert cnt2 == 1

assert pv.value() == 7
assert cnt1 == 2
assert cnt2 == 1
171 changes: 167 additions & 4 deletions test/tree/common/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import pytest

from treevalue.tree.common import create_storage, raw, TreeStorage
from treevalue.tree.common import create_storage, raw, TreeStorage, delayed_partial


# noinspection PyArgumentList,DuplicatedCode
# noinspection PyArgumentList,DuplicatedCode,PyTypeChecker
@pytest.mark.unittest
class TestTreeStorage:
def test_init(self):
Expand All @@ -23,6 +23,52 @@ def test_get(self):
with pytest.raises(KeyError):
_ = t.get('fff')

cnt1, cnt2, cnt3 = 0, 0, 0

def f1():
nonlocal cnt1
cnt1 += 1
return 2

def f2(x, y):
nonlocal cnt2
cnt2 += 1
return {'x': x, 'y': y}

def f3(x, y):
nonlocal cnt3
cnt3 += 1
return create_storage({'x': x, 'y': raw(y)})

t2 = create_storage({
'a': 1,
'b': delayed_partial(f1),
'c': delayed_partial(f2, delayed_partial(f1), 3),
'd': delayed_partial(f3, 3, delayed_partial(f2, 3, 4))
})

assert t2.get('a') == 1

assert cnt1 == 0
assert t2.get('b') == 2
assert cnt1 == 1
assert t2.get('b') == 2
assert cnt1 == 1

assert (cnt1, cnt2) == (1, 0)
assert t2.get('c') == {'x': 2, 'y': 3}
assert (cnt1, cnt2) == (2, 1)
assert t2.get('c') == {'x': 2, 'y': 3}
assert (cnt1, cnt2) == (2, 1)

assert (cnt1, cnt2, cnt3) == (2, 1, 0)
assert t2.get('d').get('x') == 3
assert t2.get('d').get('y') == {'x': 3, 'y': 4}
assert (cnt1, cnt2, cnt3) == (2, 2, 1)
assert t2.get('d').get('x') == 3
assert t2.get('d').get('y') == {'x': 3, 'y': 4}
assert (cnt1, cnt2, cnt3) == (2, 2, 1)

def test_get_or_default(self):
t = create_storage({'a': 1, 'b': 2, 'c': raw({'x': 3, 'y': 4}), 'd': {'x': 3, 'y': 4}})
assert t.get_or_default('a', 233) == 1
Expand All @@ -34,6 +80,23 @@ def test_get_or_default(self):

assert t.get_or_default('fff', 233) == 233

t1 = create_storage({
'a': delayed_partial(lambda: t.get('a')),
'b': delayed_partial(lambda: t.get('b')),
'c': delayed_partial(lambda: t.get('c')),
'd': delayed_partial(lambda: t.get('d')),
})
assert t1.get_or_default('a', 233) == 1
assert t1.get_or_default('b', 233) == 2
assert t1.get_or_default('c', 233) == {'x': 3, 'y': 4}
assert isinstance(t1.get_or_default('d', 233), TreeStorage)
assert t1.get_or_default('d', 233).get_or_default('x', 233) == 3
assert t1.get_or_default('d', 233).get_or_default('y', 233) == 4

assert t1.get_or_default('fff', 233) == 233
assert t1.get_or_default('fff', delayed_partial(lambda: 2345)) == 2345
assert not t1.contains('fff')

def test_set(self):
t = create_storage({})
t.set('a', 1)
Expand Down Expand Up @@ -122,6 +185,19 @@ def test_dump(self):
assert _dumped['d']['x'] == 3
assert _dumped['d']['y'] == 4

t2 = create_storage({
'a': 1,
'b': delayed_partial(lambda x: x + 1, 1),
'c': delayed_partial(lambda: h1),
'd': delayed_partial(lambda: create_storage(h2)),
})
_dumped = t2.dump()
assert _dumped['a'] == 1
assert _dumped['b'] == 2
assert _dumped['c'].value() is h1
assert _dumped['d']['x'] == 3
assert _dumped['d']['y'] == 4

def test_deepdump(self):
h1 = {'x': 3, 'y': 4}
h2 = {'x': 3, 'y': 4}
Expand Down Expand Up @@ -177,7 +253,7 @@ def test_deepcopyx(self):
h2 = {'x': 3, 'y': 4}
t = create_storage({'a': 1, 'b': 2, 'c': raw(h1), 'd': h2})

t1 = t.deepcopyx(lambda x: -x if isinstance(x, int) else {'holy': 'shit'})
t1 = t.deepcopyx(lambda x: -x if isinstance(x, int) else {'holy': 'shit'}, False)
assert t1.get('a') == -1
assert t1.get('b') == -2
assert t1.get('c') == {'holy': 'shit'}
Expand Down Expand Up @@ -232,6 +308,19 @@ def test_copy_from(self):
assert t1.get('f').get('y') == 4
assert t1.get('f') is not t.get('f')

t2 = create_storage({
'a': delayed_partial(lambda: 11),
'b': delayed_partial(lambda: 22),
'c': delayed_partial(lambda: {'x': 3, 'y': 5}),
'd': delayed_partial(lambda: create_storage({'x': 3, 'y': 7})),
})
t1.copy_from(t2)
assert t1.get('a') == 11
assert t1.get('b') == 22
assert t1.get('c') == {'x': 3, 'y': 5}
assert t1.get('d').get('x') == 3
assert t1.get('d').get('y') == 7

def test_deepcopy_from(self):
h1 = {'x': 3, 'y': 4}
h2 = {'x': 3, 'y': 4}
Expand All @@ -253,6 +342,19 @@ def test_deepcopy_from(self):
assert t1.get('f').get('y') == 4
assert t1.get('f') is not t.get('f')

t2 = create_storage({
'a': delayed_partial(lambda: 11),
'b': delayed_partial(lambda: 22),
'c': delayed_partial(lambda: {'x': 3, 'y': 5}),
'd': delayed_partial(lambda: create_storage({'x': 3, 'y': 7})),
})
t1.deepcopy_from(t2)
assert t1.get('a') == 11
assert t1.get('b') == 22
assert t1.get('c') == {'x': 3, 'y': 5}
assert t1.get('d').get('x') == 3
assert t1.get('d').get('y') == 7

def test_repr(self):
h1 = {'x': 3, 'y': 4}
h2 = {'x': 3, 'y': 4}
Expand All @@ -272,6 +374,21 @@ def test_eq(self):
assert t == t
assert t == t1
assert t != t2
assert t != None

t3 = create_storage({
'a': delayed_partial(lambda: 11),
'b': delayed_partial(lambda: 22),
'c': delayed_partial(lambda: {'x': 3, 'y': 5}),
'd': delayed_partial(lambda: create_storage({'x': 3, 'y': 7})),
})
t4 = create_storage({
'a': delayed_partial(lambda: t3.get('a')),
'b': delayed_partial(lambda: t3.get('b')),
'c': delayed_partial(lambda: t3.get('c')),
'd': delayed_partial(lambda: t3.get('d')),
})
assert t3 == t4

def test_keys(self):
h1 = {'x': 3, 'y': 4}
Expand All @@ -286,10 +403,20 @@ def test_values(self):
t = create_storage({'a': 1, 'b': 2, 'd': h1})

assert set(t.get('d').values()) == {3, 4}
assert len(t.values()) == 3
assert len(list(t.values())) == 3
assert 1 in t.values()
assert 2 in t.values()

t1 = create_storage({
'a': delayed_partial(lambda: t.get('a')),
'b': delayed_partial(lambda: t.get('b')),
'd': delayed_partial(lambda: t.get('d')),
})
assert set(t1.get('d').values()) == {3, 4}
assert len(list(t1.values())) == 3
assert 1 in t1.values()
assert 2 in t1.values()

def test_items(self):
h1 = {'x': 3, 'y': 4}
t = create_storage({'a': 1, 'b': 2, 'd': raw(h1)})
Expand All @@ -303,3 +430,39 @@ def test_items(self):
assert v == h1
else:
pytest.fail('Should not reach here.')

t1 = create_storage({
'a': delayed_partial(lambda: t.get('a')),
'b': delayed_partial(lambda: t.get('b')),
'd': delayed_partial(lambda: t.get('d')),
})
for k, v in t1.items():
if k == 'a':
assert v == 1
elif k == 'b':
assert v == 2
elif k == 'd':
assert v == h1
else:
pytest.fail('Should not reach here.')

def test_hash(self):
h = {}

h1 = {'x': 3, 'y': 4}
t = create_storage({'a': 1, 'b': 2, 'd': h1})
t1 = create_storage({
'a': delayed_partial(lambda: t.get('a')),
'b': delayed_partial(lambda: t.get('b')),
'd': delayed_partial(lambda: t.get('d')),
})
t2 = create_storage({
'a': delayed_partial(lambda: t.get('a')),
'b': delayed_partial(lambda: 3),
'd': delayed_partial(lambda: t.get('d')),
})

h[t] = 1
assert t1 in h
assert h[t1] == 1
assert t2 not in h