Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDILab开源决策智能平台
treevalue
提交
029f029e
T
treevalue
项目概览
OpenDILab开源决策智能平台
/
treevalue
大约 1 年 前同步成功
通知
3
Star
213
Fork
3
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
treevalue
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
029f029e
编写于
1月 04, 2022
作者:
HansBug
😆
1
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'main' into dev/potc
上级
042dd730
7a627e8e
变更
32
显示空白变更内容
内联
并排
Showing
32 changed file
with
1280 addition
and
128 deletion
+1280
-128
docs/source/api_doc/tree/common.rst
docs/source/api_doc/tree/common.rst
+43
-0
docs/source/api_doc/tree/tree.rst
docs/source/api_doc/tree/tree.rst
+8
-0
requirements-doc.txt
requirements-doc.txt
+1
-1
test/tree/common/test_delay.py
test/tree/common/test_delay.py
+68
-0
test/tree/common/test_storage.py
test/tree/common/test_storage.py
+167
-4
test/tree/func/test_func.py
test/tree/func/test_func.py
+145
-1
test/tree/func/test_outer.py
test/tree/func/test_outer.py
+43
-0
test/tree/general/base.py
test/tree/general/base.py
+51
-2
test/tree/tree/test_flatten.py
test/tree/tree/test_flatten.py
+43
-3
test/tree/tree/test_functional.py
test/tree/tree/test_functional.py
+66
-1
test/tree/tree/test_service.py
test/tree/tree/test_service.py
+33
-1
test/tree/tree/test_structural.py
test/tree/tree/test_structural.py
+70
-1
test/tree/tree/test_tree.py
test/tree/tree/test_tree.py
+15
-1
treevalue/tree/common/__init__.py
treevalue/tree/common/__init__.py
+1
-0
treevalue/tree/common/base.pyx
treevalue/tree/common/base.pyx
+2
-2
treevalue/tree/common/delay.pxd
treevalue/tree/common/delay.pxd
+27
-0
treevalue/tree/common/delay.pyx
treevalue/tree/common/delay.pyx
+142
-0
treevalue/tree/common/storage.pxd
treevalue/tree/common/storage.pxd
+9
-4
treevalue/tree/common/storage.pyx
treevalue/tree/common/storage.pyx
+69
-25
treevalue/tree/func/cfunc.pxd
treevalue/tree/func/cfunc.pxd
+8
-5
treevalue/tree/func/cfunc.pyx
treevalue/tree/func/cfunc.pyx
+84
-28
treevalue/tree/func/func.py
treevalue/tree/func/func.py
+7
-5
treevalue/tree/general/general.py
treevalue/tree/general/general.py
+8
-6
treevalue/tree/tree/__init__.py
treevalue/tree/tree/__init__.py
+1
-1
treevalue/tree/tree/flatten.pyx
treevalue/tree/tree/flatten.pyx
+7
-4
treevalue/tree/tree/functional.pxd
treevalue/tree/tree/functional.pxd
+3
-2
treevalue/tree/tree/functional.pyx
treevalue/tree/tree/functional.pyx
+31
-9
treevalue/tree/tree/service.pyx
treevalue/tree/tree/service.pyx
+14
-5
treevalue/tree/tree/structural.pxd
treevalue/tree/tree/structural.pxd
+3
-2
treevalue/tree/tree/structural.pyx
treevalue/tree/tree/structural.pyx
+32
-13
treevalue/tree/tree/tree.pxd
treevalue/tree/tree/tree.pxd
+11
-0
treevalue/tree/tree/tree.pyx
treevalue/tree/tree/tree.pyx
+68
-2
未找到文件。
docs/source/api_doc/tree/common.rst
浏览文件 @
029f029e
...
@@ -36,3 +36,46 @@ RawWrapper
...
@@ -36,3 +36,46 @@ RawWrapper
.. autoclass:: RawWrapper
.. autoclass:: RawWrapper
:members: __init__, value
: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
docs/source/api_doc/tree/tree.rst
浏览文件 @
029f029e
...
@@ -12,6 +12,14 @@ TreeValue
...
@@ -12,6 +12,14 @@ TreeValue
:members: __init__, __getattribute__, __setattr__, __delattr__, __contains__, __repr__, __iter__, __hash__, __eq__, _attr_extern, __len__, __bool__, __str__, __getstate__, __setstate__, get
: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:
.. _apidoc_tree_tree_jsonify:
jsonify
jsonify
...
...
requirements-doc.txt
浏览文件 @
029f029e
...
@@ -2,7 +2,7 @@ sphinx~=3.2.0
...
@@ -2,7 +2,7 @@ sphinx~=3.2.0
sphinx_rtd_theme~=0.4.3
sphinx_rtd_theme~=0.4.3
enum_tools
enum_tools
sphinx-toolbox
sphinx-toolbox
plantumlcli>=0.0.
2
plantumlcli>=0.0.
4
packaging
packaging
sphinx-multiversion~=0.2.4
sphinx-multiversion~=0.2.4
where~=1.0.2
where~=1.0.2
...
...
test/tree/common/test_delay.py
0 → 100644
浏览文件 @
029f029e
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
test/tree/common/test_storage.py
浏览文件 @
029f029e
...
@@ -2,10 +2,10 @@ import pickle
...
@@ -2,10 +2,10 @@ import pickle
import
pytest
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
@
pytest
.
mark
.
unittest
class
TestTreeStorage
:
class
TestTreeStorage
:
def
test_init
(
self
):
def
test_init
(
self
):
...
@@ -23,6 +23,52 @@ class TestTreeStorage:
...
@@ -23,6 +23,52 @@ class TestTreeStorage:
with
pytest
.
raises
(
KeyError
):
with
pytest
.
raises
(
KeyError
):
_
=
t
.
get
(
'fff'
)
_
=
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
):
def
test_get_or_default
(
self
):
t
=
create_storage
({
'a'
:
1
,
'b'
:
2
,
'c'
:
raw
({
'x'
:
3
,
'y'
:
4
}),
'd'
:
{
'x'
:
3
,
'y'
:
4
}})
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
assert
t
.
get_or_default
(
'a'
,
233
)
==
1
...
@@ -34,6 +80,23 @@ class TestTreeStorage:
...
@@ -34,6 +80,23 @@ class TestTreeStorage:
assert
t
.
get_or_default
(
'fff'
,
233
)
==
233
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
):
def
test_set
(
self
):
t
=
create_storage
({})
t
=
create_storage
({})
t
.
set
(
'a'
,
1
)
t
.
set
(
'a'
,
1
)
...
@@ -122,6 +185,19 @@ class TestTreeStorage:
...
@@ -122,6 +185,19 @@ class TestTreeStorage:
assert
_dumped
[
'd'
][
'x'
]
==
3
assert
_dumped
[
'd'
][
'x'
]
==
3
assert
_dumped
[
'd'
][
'y'
]
==
4
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
):
def
test_deepdump
(
self
):
h1
=
{
'x'
:
3
,
'y'
:
4
}
h1
=
{
'x'
:
3
,
'y'
:
4
}
h2
=
{
'x'
:
3
,
'y'
:
4
}
h2
=
{
'x'
:
3
,
'y'
:
4
}
...
@@ -177,7 +253,7 @@ class TestTreeStorage:
...
@@ -177,7 +253,7 @@ class TestTreeStorage:
h2
=
{
'x'
:
3
,
'y'
:
4
}
h2
=
{
'x'
:
3
,
'y'
:
4
}
t
=
create_storage
({
'a'
:
1
,
'b'
:
2
,
'c'
:
raw
(
h1
),
'd'
:
h2
})
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
(
'a'
)
==
-
1
assert
t1
.
get
(
'b'
)
==
-
2
assert
t1
.
get
(
'b'
)
==
-
2
assert
t1
.
get
(
'c'
)
==
{
'holy'
:
'shit'
}
assert
t1
.
get
(
'c'
)
==
{
'holy'
:
'shit'
}
...
@@ -232,6 +308,19 @@ class TestTreeStorage:
...
@@ -232,6 +308,19 @@ class TestTreeStorage:
assert
t1
.
get
(
'f'
).
get
(
'y'
)
==
4
assert
t1
.
get
(
'f'
).
get
(
'y'
)
==
4
assert
t1
.
get
(
'f'
)
is
not
t
.
get
(
'f'
)
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
):
def
test_deepcopy_from
(
self
):
h1
=
{
'x'
:
3
,
'y'
:
4
}
h1
=
{
'x'
:
3
,
'y'
:
4
}
h2
=
{
'x'
:
3
,
'y'
:
4
}
h2
=
{
'x'
:
3
,
'y'
:
4
}
...
@@ -253,6 +342,19 @@ class TestTreeStorage:
...
@@ -253,6 +342,19 @@ class TestTreeStorage:
assert
t1
.
get
(
'f'
).
get
(
'y'
)
==
4
assert
t1
.
get
(
'f'
).
get
(
'y'
)
==
4
assert
t1
.
get
(
'f'
)
is
not
t
.
get
(
'f'
)
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
):
def
test_repr
(
self
):
h1
=
{
'x'
:
3
,
'y'
:
4
}
h1
=
{
'x'
:
3
,
'y'
:
4
}
h2
=
{
'x'
:
3
,
'y'
:
4
}
h2
=
{
'x'
:
3
,
'y'
:
4
}
...
@@ -272,6 +374,21 @@ class TestTreeStorage:
...
@@ -272,6 +374,21 @@ class TestTreeStorage:
assert
t
==
t
assert
t
==
t
assert
t
==
t1
assert
t
==
t1
assert
t
!=
t2
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
):
def
test_keys
(
self
):
h1
=
{
'x'
:
3
,
'y'
:
4
}
h1
=
{
'x'
:
3
,
'y'
:
4
}
...
@@ -286,10 +403,20 @@ class TestTreeStorage:
...
@@ -286,10 +403,20 @@ class TestTreeStorage:
t
=
create_storage
({
'a'
:
1
,
'b'
:
2
,
'd'
:
h1
})
t
=
create_storage
({
'a'
:
1
,
'b'
:
2
,
'd'
:
h1
})
assert
set
(
t
.
get
(
'd'
).
values
())
==
{
3
,
4
}
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
1
in
t
.
values
()
assert
2
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
):
def
test_items
(
self
):
h1
=
{
'x'
:
3
,
'y'
:
4
}
h1
=
{
'x'
:
3
,
'y'
:
4
}
t
=
create_storage
({
'a'
:
1
,
'b'
:
2
,
'd'
:
raw
(
h1
)})
t
=
create_storage
({
'a'
:
1
,
'b'
:
2
,
'd'
:
raw
(
h1
)})
...
@@ -303,3 +430,39 @@ class TestTreeStorage:
...
@@ -303,3 +430,39 @@ class TestTreeStorage:
assert
v
==
h1
assert
v
==
h1
else
:
else
:
pytest
.
fail
(
'Should not reach here.'
)
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
test/tree/func/test_func.py
浏览文件 @
029f029e
...
@@ -3,7 +3,7 @@ from operator import __mul__
...
@@ -3,7 +3,7 @@ from operator import __mul__
import
pytest
import
pytest
from
treevalue.tree
import
func_treelize
,
TreeValue
,
method_treelize
,
classmethod_treelize
from
treevalue.tree
import
func_treelize
,
TreeValue
,
method_treelize
,
classmethod_treelize
,
delayed
# noinspection DuplicatedCode
# noinspection DuplicatedCode
...
@@ -257,3 +257,147 @@ class TestTreeFuncFunc:
...
@@ -257,3 +257,147 @@ class TestTreeFuncFunc:
'f'
:
[
4
],
'f'
:
[
4
],
},
},
})
})
def
test_delay_support
(
self
):
@
func_treelize
(
return_type
=
TreeValue
)
def
f
(
x
,
y
,
z
):
return
x
+
y
*
2
+
z
*
3
t1
=
TreeValue
({
'a'
:
1
,
'b'
:
delayed
(
lambda
x
:
x
**
2
,
3
),
'c'
:
{
'x'
:
2
,
'y'
:
delayed
(
lambda
:
4
)},
})
t2
=
TreeValue
({
'a'
:
delayed
(
lambda
x
:
x
+
1
,
t1
.
a
),
'b'
:
delayed
(
lambda
:
t1
.
c
.
y
),
'c'
:
delayed
(
lambda
:
5
),
})
t3
=
delayed
(
lambda
:
6
)
assert
f
(
t1
,
t2
,
t3
)
==
TreeValue
({
'a'
:
23
,
'b'
:
35
,
'c'
:
{
'x'
:
30
,
'y'
:
32
},
})
t1
=
TreeValue
({
'a'
:
1
,
'b'
:
delayed
(
lambda
x
:
x
**
2
,
3
),
'c'
:
{
'x'
:
2
,
'y'
:
delayed
(
lambda
:
4
)},
})
t2
=
TreeValue
({
'a'
:
delayed
(
lambda
x
:
x
+
1
,
t1
.
a
),
'b'
:
delayed
(
lambda
:
t1
.
c
.
y
),
'c'
:
delayed
(
lambda
:
5
),
})
t3
=
delayed
(
lambda
:
6
)
assert
f
(
x
=
t1
,
y
=
t2
,
z
=
t3
)
==
TreeValue
({
'a'
:
23
,
'b'
:
35
,
'c'
:
{
'x'
:
30
,
'y'
:
32
},
})
def
test_delayed_treelize
(
self
):
t1
=
TreeValue
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
},
})
t2
=
TreeValue
({
'a'
:
11
,
'b'
:
23
,
'x'
:
{
'c'
:
35
,
'd'
:
47
},
})
cnt_1
=
0
@
func_treelize
(
delayed
=
True
)
def
total
(
a
,
b
):
nonlocal
cnt_1
cnt_1
+=
1
return
a
+
b
# positional
t3
=
total
(
t1
,
t2
)
assert
cnt_1
==
0
assert
t3
.
a
==
12
assert
cnt_1
==
1
assert
t3
.
x
==
TreeValue
({
'c'
:
38
,
'd'
:
51
})
assert
cnt_1
==
3
assert
t3
==
TreeValue
({
'a'
:
12
,
'b'
:
25
,
'x'
:
{
'c'
:
38
,
'd'
:
51
}
})
assert
cnt_1
==
4
# keyword
cnt_1
=
0
t3
=
total
(
a
=
t1
,
b
=
t2
)
assert
cnt_1
==
0
assert
t3
.
a
==
12
assert
cnt_1
==
1
assert
t3
.
x
==
TreeValue
({
'c'
:
38
,
'd'
:
51
})
assert
cnt_1
==
3
assert
t3
==
TreeValue
({
'a'
:
12
,
'b'
:
25
,
'x'
:
{
'c'
:
38
,
'd'
:
51
}
})
assert
cnt_1
==
4
# positional, with constant
cnt_1
=
0
t3
=
total
(
1
,
t2
)
assert
cnt_1
==
0
assert
t3
.
a
==
12
assert
cnt_1
==
1
assert
t3
.
x
==
TreeValue
({
'c'
:
36
,
'd'
:
48
})
assert
cnt_1
==
3
assert
t3
==
TreeValue
({
'a'
:
12
,
'b'
:
24
,
'x'
:
{
'c'
:
36
,
'd'
:
48
}
})
assert
cnt_1
==
4
# keyword, with constant
cnt_1
=
0
t3
=
total
(
b
=
1
,
a
=
t2
)
assert
cnt_1
==
0
assert
t3
.
a
==
12
assert
cnt_1
==
1
assert
t3
.
x
==
TreeValue
({
'c'
:
36
,
'd'
:
48
})
assert
cnt_1
==
3
assert
t3
==
TreeValue
({
'a'
:
12
,
'b'
:
24
,
'x'
:
{
'c'
:
36
,
'd'
:
48
}
})
assert
cnt_1
==
4
# positional, with delay
cnt_1
=
0
t4
=
TreeValue
({
'v'
:
delayed
(
lambda
:
t1
)})
t5
=
TreeValue
({
'v'
:
delayed
(
lambda
:
t2
)})
t6
=
total
(
t4
,
t5
)
assert
cnt_1
==
0
assert
t6
.
v
.
a
==
12
assert
cnt_1
==
1
assert
t6
.
v
.
x
==
TreeValue
({
'c'
:
38
,
'd'
:
51
})
assert
cnt_1
==
3
assert
t6
==
TreeValue
({
'v'
:
{
'a'
:
12
,
'b'
:
25
,
'x'
:
{
'c'
:
38
,
'd'
:
51
}},
})
assert
cnt_1
==
4
# keyword, with delay
cnt_1
=
0
t4
=
TreeValue
({
'v'
:
delayed
(
lambda
:
t1
)})
t5
=
TreeValue
({
'v'
:
delayed
(
lambda
:
t2
)})
t6
=
total
(
a
=
t4
,
b
=
t5
)
assert
cnt_1
==
0
assert
t6
.
v
.
a
==
12
assert
cnt_1
==
1
assert
t6
.
v
.
x
==
TreeValue
({
'c'
:
38
,
'd'
:
51
})
assert
cnt_1
==
3
assert
t6
==
TreeValue
({
'v'
:
{
'a'
:
12
,
'b'
:
25
,
'x'
:
{
'c'
:
38
,
'd'
:
51
}},
})
assert
cnt_1
==
4
test/tree/func/test_outer.py
浏览文件 @
029f029e
...
@@ -38,3 +38,46 @@ class TestTreeFuncOuter:
...
@@ -38,3 +38,46 @@ class TestTreeFuncOuter:
with
pytest
.
raises
(
KeyError
):
with
pytest
.
raises
(
KeyError
):
_
=
ssum
(
t1
,
t3
)
_
=
ssum
(
t1
,
t3
)
def
test_delayed_treelize
(
self
):
t1
=
TreeValue
({
'a'
:
1
,
'x'
:
{
'c'
:
3
,
'd'
:
4
},
})
t2
=
TreeValue
({
'a'
:
11
,
'b'
:
23
,
'x'
:
{
'c'
:
35
,
},
})
cnt_1
=
0
@
func_treelize
(
delayed
=
True
,
mode
=
'outer'
,
missing
=
0
)
def
total
(
a
,
b
):
nonlocal
cnt_1
cnt_1
+=
1
return
a
+
b
# positional
t3
=
total
(
t1
,
t2
)
assert
cnt_1
==
0
assert
t3
.
a
==
12
assert
cnt_1
==
1
assert
t3
.
x
==
TreeValue
({
'c'
:
38
,
'd'
:
4
})
assert
cnt_1
==
3
assert
t3
==
TreeValue
({
'a'
:
12
,
'b'
:
23
,
'x'
:
{
'c'
:
38
,
'd'
:
4
}
})
assert
cnt_1
==
4
# keyword
cnt_1
=
0
t3
=
total
(
a
=
t1
,
b
=
t2
)
assert
cnt_1
==
0
assert
t3
.
a
==
12
assert
cnt_1
==
1
assert
t3
.
x
==
TreeValue
({
'c'
:
38
,
'd'
:
4
})
assert
cnt_1
==
3
assert
t3
==
TreeValue
({
'a'
:
12
,
'b'
:
23
,
'x'
:
{
'c'
:
38
,
'd'
:
4
}
})
assert
cnt_1
==
4
test/tree/general/base.py
浏览文件 @
029f029e
...
@@ -5,7 +5,7 @@ from typing import Type
...
@@ -5,7 +5,7 @@ from typing import Type
import
numpy
as
np
import
numpy
as
np
import
pytest
import
pytest
from
treevalue.tree
import
func_treelize
,
TreeValue
,
raw
,
mapping
from
treevalue.tree
import
func_treelize
,
TreeValue
,
raw
,
mapping
,
delayed
def
get_tree_test
(
tree_value_clazz
:
Type
[
TreeValue
]):
def
get_tree_test
(
tree_value_clazz
:
Type
[
TreeValue
]):
...
@@ -356,8 +356,38 @@ def get_tree_test(tree_value_clazz: Type[TreeValue]):
...
@@ -356,8 +356,38 @@ def get_tree_test(tree_value_clazz: Type[TreeValue]):
assert
t2
.
add
(
t1
)
==
tree_value_clazz
({
'a'
:
2
,
'b'
:
4
,
'x'
:
{
'c'
:
6
,
'd'
:
8
}})
assert
t2
.
add
(
t1
)
==
tree_value_clazz
({
'a'
:
2
,
'b'
:
4
,
'x'
:
{
'c'
:
6
,
'd'
:
8
}})
def
test_map
(
self
):
def
test_map
(
self
):
cnt
=
0
def
f
(
x
):
nonlocal
cnt
cnt
+=
1
return
x
+
2
t1
=
tree_value_clazz
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
}})
t1
=
tree_value_clazz
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
}})
assert
t1
.
map
(
lambda
x
:
x
+
2
)
==
tree_value_clazz
({
'a'
:
3
,
'b'
:
4
,
'x'
:
{
'c'
:
5
,
'd'
:
6
}})
assert
cnt
==
0
t2
=
t1
.
map
(
f
)
assert
cnt
==
4
assert
t2
==
tree_value_clazz
({
'a'
:
3
,
'b'
:
4
,
'x'
:
{
'c'
:
5
,
'd'
:
6
}})
cnt
=
0
t3
=
tree_value_clazz
({
'a'
:
delayed
(
lambda
:
t1
.
a
),
'b'
:
delayed
(
lambda
:
t1
.
b
),
'x'
:
delayed
(
lambda
:
t1
.
x
),
})
assert
cnt
==
0
t4
=
t3
.
map
(
f
,
delayed
=
True
)
assert
cnt
==
0
assert
t4
.
a
==
3
assert
cnt
==
1
assert
t4
==
tree_value_clazz
({
'a'
:
3
,
'b'
:
4
,
'x'
:
{
'c'
:
5
,
'd'
:
6
}})
assert
cnt
==
4
assert
t4
.
a
==
3
assert
cnt
==
4
def
test_type
(
self
):
def
test_type
(
self
):
t1
=
tree_value_clazz
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
}})
t1
=
tree_value_clazz
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
}})
...
@@ -572,4 +602,23 @@ def get_tree_test(tree_value_clazz: Type[TreeValue]):
...
@@ -572,4 +602,23 @@ def get_tree_test(tree_value_clazz: Type[TreeValue]):
assert
ssum
(
t1
,
t2
)
==
tree_value_clazz
({
'a'
:
12
,
'b'
:
22
,
'x'
:
{
'c'
:
36
,
'd'
:
52
}})
assert
ssum
(
t1
,
t2
)
==
tree_value_clazz
({
'a'
:
12
,
'b'
:
22
,
'x'
:
{
'c'
:
36
,
'd'
:
52
}})
cnt_1
=
0
@
tree_value_clazz
.
func
(
delayed
=
True
)
def
ssumx
(
x
,
y
):
nonlocal
cnt_1
cnt_1
+=
1
return
x
+
y
cnt_1
=
0
t3
=
ssumx
(
t1
,
t2
)
assert
cnt_1
==
0
assert
t3
.
a
==
12
assert
cnt_1
==
1
assert
t3
.
x
==
tree_value_clazz
({
'c'
:
36
,
'd'
:
52
})
assert
cnt_1
==
3
assert
t3
==
tree_value_clazz
({
'a'
:
12
,
'b'
:
22
,
'x'
:
{
'c'
:
36
,
'd'
:
52
}})
assert
cnt_1
==
4
return
_TestClass
return
_TestClass
test/tree/tree/test_flatten.py
浏览文件 @
029f029e
import
pytest
import
pytest
from
treevalue.tree
import
TreeValue
,
raw
,
flatten
,
unflatten
,
flatten_values
,
flatten_keys
from
treevalue.tree
import
TreeValue
,
raw
,
flatten
,
unflatten
,
flatten_values
,
flatten_keys
,
delayed
class
MyTreeValue
(
TreeValue
):
class
MyTreeValue
(
TreeValue
):
...
@@ -22,15 +22,37 @@ class TestTreeTreeFlatten:
...
@@ -22,15 +22,37 @@ class TestTreeTreeFlatten:
((
'd'
,
'y'
),
4
)
((
'd'
,
'y'
),
4
)
]
]
t1
=
TreeValue
({
'a'
:
delayed
(
lambda
:
t
.
a
),
'b'
:
delayed
(
lambda
:
t
.
b
),
'c'
:
delayed
(
lambda
:
t
.
c
),
'd'
:
delayed
(
lambda
:
t
.
d
),
})
flatted
=
sorted
(
flatten
(
t1
))
assert
flatted
==
[
((
'a'
,),
1
),
((
'b'
,),
2
),
((
'c'
,),
{
'x'
:
3
,
'y'
:
4
}),
((
'd'
,
'x'
),
3
),
((
'd'
,
'y'
),
4
)
]
def
test_flatten_values
(
self
):
def
test_flatten_values
(
self
):
t
=
TreeValue
({
'a'
:
1
,
'b'
:
5
,
'c'
:
{
'x'
:
3
,
'y'
:
4
},
'd'
:
{
'x'
:
3
,
'y'
:
4
}})
t
=
TreeValue
({
'a'
:
1
,
'b'
:
5
,
'c'
:
{
'x'
:
3
,
'y'
:
4
},
'd'
:
{
'x'
:
3
,
'y'
:
4
}})
flatted_values
=
sorted
(
flatten_values
(
t
))
flatted_values
=
sorted
(
flatten_values
(
t
))
assert
flatted_values
==
[
1
,
3
,
3
,
4
,
4
,
5
]
assert
flatted_values
==
[
1
,
3
,
3
,
4
,
4
,
5
]
t1
=
TreeValue
({
'a'
:
delayed
(
lambda
:
t
.
a
),
'b'
:
delayed
(
lambda
:
t
.
b
),
'c'
:
delayed
(
lambda
:
t
.
c
),
'd'
:
delayed
(
lambda
:
t
.
d
),
})
flatted_values
=
sorted
(
flatten_values
(
t1
))
assert
flatted_values
==
[
1
,
3
,
3
,
4
,
4
,
5
]
def
test_flatten_keys
(
self
):
def
test_flatten_keys
(
self
):
t
=
TreeValue
({
'a'
:
1
,
'd'
:
{
'x'
:
3
,
'y'
:
4
},
'e'
:
raw
({
'x'
:
3
,
'y'
:
4
}),
'b'
:
5
,
'c'
:
{
'x'
:
3
,
'y'
:
4
}})
t
=
TreeValue
({
'a'
:
1
,
'd'
:
{
'x'
:
3
,
'y'
:
4
},
'e'
:
raw
({
'x'
:
3
,
'y'
:
4
}),
'b'
:
5
,
'c'
:
{
'x'
:
3
,
'y'
:
4
}})
flatted_keys
=
sorted
(
flatten_keys
(
t
))
flatted_keys
=
sorted
(
flatten_keys
(
t
))
assert
flatted_keys
==
[
assert
flatted_keys
==
[
(
'a'
,),
(
'a'
,),
...
@@ -42,6 +64,24 @@ class TestTreeTreeFlatten:
...
@@ -42,6 +64,24 @@ class TestTreeTreeFlatten:
(
'e'
,),
(
'e'
,),
]
]
t1
=
TreeValue
({
'a'
:
delayed
(
lambda
:
t
.
a
),
'b'
:
delayed
(
lambda
:
t
.
b
),
'c'
:
delayed
(
lambda
:
t
.
c
),
'd'
:
delayed
(
lambda
:
t
.
d
),
'e'
:
delayed
(
lambda
:
t
.
e
),
})
flatted_keys
=
sorted
(
flatten_keys
(
t1
))
assert
flatted_keys
==
[
(
'a'
,),
(
'b'
,),
(
'c'
,
'x'
,),
(
'c'
,
'y'
,),
(
'd'
,
'x'
,),
(
'd'
,
'y'
,),
(
'e'
,),
]
def
test_unflatten
(
self
):
def
test_unflatten
(
self
):
flatted
=
[
flatted
=
[
((
'a'
,),
1
),
((
'a'
,),
1
),
...
...
test/tree/tree/test_functional.py
浏览文件 @
029f029e
...
@@ -3,7 +3,7 @@ from operator import __mul__
...
@@ -3,7 +3,7 @@ from operator import __mul__
import
pytest
import
pytest
from
treevalue.tree
import
TreeValue
,
mapping
,
raw
,
mask
,
filter_
,
reduce_
from
treevalue.tree
import
TreeValue
,
mapping
,
raw
,
mask
,
filter_
,
reduce_
,
delayed
# noinspection DuplicatedCode
# noinspection DuplicatedCode
...
@@ -30,6 +30,59 @@ class TestTreeTreeFunctional:
...
@@ -30,6 +30,59 @@ class TestTreeTreeFunctional:
})
})
assert
tv6
==
TreeValue
({
'a'
:
1.0
,
'b'
:
2.0
,
'c'
:
{
'x'
:
2.0
,
'y'
:
3.0
}})
assert
tv6
==
TreeValue
({
'a'
:
1.0
,
'b'
:
2.0
,
'c'
:
{
'x'
:
2.0
,
'y'
:
3.0
}})
tv8
=
TreeValue
({
'v'
:
delayed
(
lambda
:
tv1
)})
assert
mapping
(
tv8
,
lambda
x
:
x
+
2
)
==
TreeValue
({
'v'
:
{
'a'
:
3
,
'b'
:
4
,
'c'
:
{
'x'
:
4
,
'y'
:
5
}
}})
def
test_mapping_delayed
(
self
):
tv1
=
TreeValue
({
'a'
:
1
,
'b'
:
2
,
'c'
:
{
'x'
:
2
,
'y'
:
3
}})
tv8
=
TreeValue
({
'v'
:
delayed
(
lambda
:
tv1
)})
assert
mapping
(
tv8
,
lambda
x
:
x
+
2
,
delayed
=
True
)
==
TreeValue
({
'v'
:
{
'a'
:
3
,
'b'
:
4
,
'c'
:
{
'x'
:
4
,
'y'
:
5
}
}})
cnt_f
,
cnt_v
=
0
,
0
def
f
(
x
):
nonlocal
cnt_f
cnt_f
+=
1
return
TreeValue
({
'a'
:
x
*
2
,
'b'
:
x
+
1
,
'c'
:
x
**
2
,
})
def
v
():
nonlocal
cnt_v
cnt_v
+=
1
return
3
t
=
TreeValue
({
'a'
:
1
,
'b'
:
delayed
(
f
,
1
),
'x'
:
{
'c'
:
delayed
(
v
),
'd'
:
4
,
},
'y'
:
delayed
(
f
,
3
),
})
t1
=
mapping
(
t
,
lambda
x
:
(
x
+
3
)
**
2
,
delayed
=
True
)
assert
cnt_v
==
0
assert
cnt_f
==
0
assert
t1
==
TreeValue
({
'a'
:
16
,
'b'
:
{
'a'
:
25
,
'b'
:
25
,
'c'
:
16
,
},
'x'
:
{
'c'
:
36
,
'd'
:
49
,
},
'y'
:
{
'a'
:
81
,
'b'
:
49
,
'c'
:
144
,
},
})
assert
cnt_v
==
1
assert
cnt_f
==
2
assert
t
==
TreeValue
({
'a'
:
1
,
'b'
:
{
'a'
:
2
,
'b'
:
2
,
'c'
:
1
,
},
'x'
:
{
'c'
:
3
,
'd'
:
4
,
},
'y'
:
{
'a'
:
6
,
'b'
:
4
,
'c'
:
9
,
},
})
assert
cnt_v
==
1
assert
cnt_f
==
2
def
test_mask
(
self
):
def
test_mask
(
self
):
class
MyTreeValue
(
TreeValue
):
class
MyTreeValue
(
TreeValue
):
pass
pass
...
@@ -46,6 +99,10 @@ class TestTreeTreeFunctional:
...
@@ -46,6 +99,10 @@ class TestTreeTreeFunctional:
with
pytest
.
raises
(
TypeError
):
with
pytest
.
raises
(
TypeError
):
assert
mask
(
t2
,
m2
)
assert
mask
(
t2
,
m2
)
t1
=
TreeValue
({
'v'
:
delayed
(
lambda
:
t
)})
m11
=
TreeValue
({
'v'
:
delayed
(
lambda
:
m1
)})
assert
mask
(
t1
,
m11
)
==
TreeValue
({
'v'
:
{
'a'
:
1
}})
def
test_filter
(
self
):
def
test_filter
(
self
):
class
MyTreeValue
(
TreeValue
):
class
MyTreeValue
(
TreeValue
):
pass
pass
...
@@ -56,6 +113,9 @@ class TestTreeTreeFunctional:
...
@@ -56,6 +113,9 @@ class TestTreeTreeFunctional:
assert
filter_
(
t
,
lambda
x
:
x
<
3
,
remove_empty
=
False
)
==
MyTreeValue
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{}})
assert
filter_
(
t
,
lambda
x
:
x
<
3
,
remove_empty
=
False
)
==
MyTreeValue
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{}})
assert
filter_
(
t
,
lambda
x
:
x
%
2
==
1
)
==
MyTreeValue
({
'a'
:
1
,
'x'
:
{
'c'
:
3
}})
assert
filter_
(
t
,
lambda
x
:
x
%
2
==
1
)
==
MyTreeValue
({
'a'
:
1
,
'x'
:
{
'c'
:
3
}})
t2
=
TreeValue
({
'v'
:
delayed
(
lambda
:
t
)})
assert
filter_
(
t2
,
lambda
x
:
x
<
3
)
==
TreeValue
({
'v'
:
{
'a'
:
1
,
'b'
:
2
}})
def
test_reduce
(
self
):
def
test_reduce
(
self
):
class
MyTreeValue
(
TreeValue
):
class
MyTreeValue
(
TreeValue
):
pass
pass
...
@@ -74,3 +134,8 @@ class TestTreeTreeFunctional:
...
@@ -74,3 +134,8 @@ class TestTreeTreeFunctional:
assert
reduce_
(
t2
,
lambda
**
kwargs
:
TreeValue
(
assert
reduce_
(
t2
,
lambda
**
kwargs
:
TreeValue
(
{
k
+
k
:
(
v
**
2
if
not
isinstance
(
v
,
TreeValue
)
else
v
)
for
k
,
v
in
kwargs
.
items
()}))
==
MyTreeValue
(
{
k
+
k
:
(
v
**
2
if
not
isinstance
(
v
,
TreeValue
)
else
v
)
for
k
,
v
in
kwargs
.
items
()}))
==
MyTreeValue
(
{
'aa'
:
1
,
'bb'
:
4
,
'xx'
:
{
'cc'
:
9
,
'dd'
:
16
}})
{
'aa'
:
1
,
'bb'
:
4
,
'xx'
:
{
'cc'
:
9
,
'dd'
:
16
}})
t1
=
MyTreeValue
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
}})
t3
=
TreeValue
({
'v'
:
delayed
(
lambda
:
t1
),
'v2'
:
delayed
(
lambda
:
t1
)})
assert
reduce_
(
t3
,
lambda
**
kwargs
:
sum
(
kwargs
.
values
()))
==
20
assert
reduce_
(
t3
,
lambda
**
kwargs
:
reduce
(
__mul__
,
list
(
kwargs
.
values
())))
==
576
test/tree/tree/test_service.py
浏览文件 @
029f029e
import
pytest
import
pytest
from
treevalue.tree
import
jsonify
,
TreeValue
,
clone
,
typetrans
,
raw
,
walk
from
treevalue.tree
import
jsonify
,
TreeValue
,
clone
,
typetrans
,
raw
,
walk
,
delayed
# noinspection DuplicatedCode
# noinspection DuplicatedCode
...
@@ -19,6 +19,18 @@ class TestTreeTreeService:
...
@@ -19,6 +19,18 @@ class TestTreeTreeService:
}
}
assert
tv2
.
c
==
{
'x'
:
2
,
'y'
:
3
}
assert
tv2
.
c
==
{
'x'
:
2
,
'y'
:
3
}
tv3
=
TreeValue
({
'a'
:
delayed
(
lambda
:
tv1
.
a
),
'b'
:
delayed
(
lambda
:
tv1
.
b
),
'c1'
:
delayed
(
lambda
:
tv1
.
c
),
'c2'
:
delayed
(
lambda
:
tv2
.
c
),
})
assert
jsonify
(
tv3
)
==
{
'a'
:
1
,
'b'
:
2
,
'c1'
:
{
'x'
:
2
,
'y'
:
3
},
'c2'
:
{
'x'
:
2
,
'y'
:
3
}
}
assert
tv3
.
c1
==
TreeValue
({
'x'
:
2
,
'y'
:
3
})
assert
tv3
.
c2
==
{
'x'
:
2
,
'y'
:
3
}
def
test_clone
(
self
):
def
test_clone
(
self
):
tv1
=
TreeValue
({
'a'
:
1
,
'b'
:
2
,
'c'
:
{
'x'
:
2
,
'y'
:
3
}})
tv1
=
TreeValue
({
'a'
:
1
,
'b'
:
2
,
'c'
:
{
'x'
:
2
,
'y'
:
3
}})
tv2
=
clone
(
tv1
)
tv2
=
clone
(
tv1
)
...
@@ -63,6 +75,14 @@ class TestTreeTreeService:
...
@@ -63,6 +75,14 @@ class TestTreeTreeService:
assert
tv5
.
x
.
c
is
not
tv3
.
x
.
c
assert
tv5
.
x
.
c
is
not
tv3
.
x
.
c
assert
tv5
.
x
.
d
is
not
tv3
.
x
.
d
assert
tv5
.
x
.
d
is
not
tv3
.
x
.
d
tv6
=
TreeValue
({
'a'
:
delayed
(
lambda
:
tv3
.
a
),
'b'
:
delayed
(
lambda
:
tv3
.
b
),
'x'
:
delayed
(
lambda
:
tv3
.
x
),
})
tv7
=
clone
(
tv6
,
lambda
x
:
x
)
assert
tv7
==
tv3
def
test_typetrans
(
self
):
def
test_typetrans
(
self
):
class
MyTreeValue
(
TreeValue
):
class
MyTreeValue
(
TreeValue
):
pass
pass
...
@@ -99,3 +119,15 @@ class TestTreeTreeService:
...
@@ -99,3 +119,15 @@ class TestTreeTreeService:
(
'c'
,
'x'
,):
2
,
(
'c'
,
'x'
,):
2
,
(
'c'
,
'y'
,):
3
,
(
'c'
,
'y'
,):
3
,
}
}
tv2
=
MyTreeValue
({
'a'
:
delayed
(
lambda
:
tv1
.
a
),
'b'
:
delayed
(
lambda
:
tv1
.
b
),
'c'
:
delayed
(
lambda
:
tv1
.
c
),
})
assert
dict
(
walk
(
tv2
))
==
{
(
'a'
,):
1
,
(
'b'
,):
2
,
(
'c'
,
'x'
,):
2
,
(
'c'
,
'y'
,):
3
,
}
test/tree/tree/test_structural.py
浏览文件 @
029f029e
import
pytest
import
pytest
from
treevalue.tree
import
TreeValue
,
mapping
,
union
,
raw
,
subside
,
rise
from
treevalue.tree
import
TreeValue
,
mapping
,
union
,
raw
,
subside
,
rise
,
delayed
# noinspection DuplicatedCode
# noinspection DuplicatedCode
...
@@ -16,10 +16,37 @@ class TestTreeTreeStructural:
...
@@ -16,10 +16,37 @@ class TestTreeTreeStructural:
t1
=
MyTreeValue
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
}})
t1
=
MyTreeValue
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
}})
assert
union
(
t
,
t1
)
==
TreeValue
({
'a'
:
(
1
,
1
),
'b'
:
(
2
,
2
),
'x'
:
{
'c'
:
(
3
,
3
),
'd'
:
(
4
,
4
)}})
assert
union
(
t
,
t1
)
==
TreeValue
({
'a'
:
(
1
,
1
),
'b'
:
(
2
,
2
),
'x'
:
{
'c'
:
(
3
,
3
),
'd'
:
(
4
,
4
)}})
assert
union
(
t
,
t1
,
return_type
=
MyTreeValue
)
==
MyTreeValue
(
{
'a'
:
(
1
,
1
),
'b'
:
(
2
,
2
),
'x'
:
{
'c'
:
(
3
,
3
),
'd'
:
(
4
,
4
)}})
assert
union
(
t1
,
t
)
==
MyTreeValue
({
'a'
:
(
1
,
1
),
'b'
:
(
2
,
2
),
'x'
:
{
'c'
:
(
3
,
3
),
'd'
:
(
4
,
4
)}})
assert
union
(
t1
,
t
)
==
MyTreeValue
({
'a'
:
(
1
,
1
),
'b'
:
(
2
,
2
),
'x'
:
{
'c'
:
(
3
,
3
),
'd'
:
(
4
,
4
)}})
assert
union
(
1
,
2
)
==
(
1
,
2
)
assert
union
(
1
,
2
)
==
(
1
,
2
)
assert
union
(
1
,
2
,
return_type
=
TreeValue
)
==
(
1
,
2
)
assert
union
(
1
,
2
,
return_type
=
TreeValue
)
==
(
1
,
2
)
tp
=
MyTreeValue
({
'v'
:
delayed
(
lambda
:
t
)})
tp1
=
TreeValue
({
'v'
:
delayed
(
lambda
:
t1
)})
assert
union
(
tp
,
tp1
)
==
MyTreeValue
({
'v'
:
{
'a'
:
(
1
,
1
),
'b'
:
(
2
,
2
),
'x'
:
{
'c'
:
(
3
,
3
),
'd'
:
(
4
,
4
)}}})
assert
union
(
tp1
,
tp
)
==
TreeValue
({
'v'
:
{
'a'
:
(
1
,
1
),
'b'
:
(
2
,
2
),
'x'
:
{
'c'
:
(
3
,
3
),
'd'
:
(
4
,
4
)}}})
t
=
MyTreeValue
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
}})
t1
=
TreeValue
({
'a'
:
delayed
(
lambda
:
t
.
x
.
c
),
'x'
:
{
'c'
:
delayed
(
lambda
:
t
.
a
),
'd'
:
delayed
(
lambda
:
t
.
b
),
}
})
assert
union
(
t
,
t1
,
mode
=
'outer'
,
missing
=
None
)
==
MyTreeValue
({
'a'
:
(
1
,
3
),
'b'
:
(
2
,
None
),
'x'
:
{
'c'
:
(
3
,
1
),
'd'
:
(
None
,
2
)},
})
def
test_union_delayed
(
self
):
class
MyTreeValue
(
TreeValue
):
pass
t
=
TreeValue
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
}})
t1
=
MyTreeValue
({
'a'
:
11
,
'b'
:
22
,
'x'
:
{
'c'
:
33
,
'd'
:
44
}})
assert
union
(
t
,
t1
,
delayed
=
True
)
==
TreeValue
({
'a'
:
(
1
,
11
),
'b'
:
(
2
,
22
),
'x'
:
{
'c'
:
(
3
,
33
),
'd'
:
(
4
,
44
)}})
def
test_subside
(
self
):
def
test_subside
(
self
):
assert
subside
({
'a'
:
(
1
,
2
),
'b'
:
[
3
,
4
]})
==
{
'a'
:
(
1
,
2
),
'b'
:
[
3
,
4
]}
assert
subside
({
'a'
:
(
1
,
2
),
'b'
:
[
3
,
4
]})
==
{
'a'
:
(
1
,
2
),
'b'
:
[
3
,
4
]}
assert
subside
({
'a'
:
(
1
,
2
),
'b'
:
[
3
,
4
]},
return_type
=
TreeValue
)
==
{
'a'
:
(
1
,
2
),
'b'
:
[
3
,
4
]}
assert
subside
({
'a'
:
(
1
,
2
),
'b'
:
[
3
,
4
]},
return_type
=
TreeValue
)
==
{
'a'
:
(
1
,
2
),
'b'
:
[
3
,
4
]}
...
@@ -88,6 +115,30 @@ class TestTreeTreeStructural:
...
@@ -88,6 +115,30 @@ class TestTreeTreeStructural:
assert
subside
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
},
'e'
:
[
3
,
4
,
5
]})
==
\
assert
subside
({
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
},
'e'
:
[
3
,
4
,
5
]})
==
\
{
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
},
'e'
:
[
3
,
4
,
5
]}
{
'a'
:
1
,
'b'
:
2
,
'x'
:
{
'c'
:
3
,
'd'
:
4
},
'e'
:
[
3
,
4
,
5
]}
def
test_subside_delayed
(
self
):
class
MyTreeValue
(
TreeValue
):
pass
original2
=
{
'a'
:
TreeValue
({
'a'
:
1
,
'b'
:
2
}),
'x'
:
{
'c'
:
MyTreeValue
({
'a'
:
3
,
'b'
:
4
}),
'd'
:
[
MyTreeValue
({
'a'
:
5
,
'b'
:
6
}),
MyTreeValue
({
'a'
:
7
,
'b'
:
8
}),
]
},
'k'
:
'233'
}
assert
subside
(
original2
,
delayed
=
True
)
==
TreeValue
({
'a'
:
raw
({
'a'
:
1
,
'k'
:
'233'
,
'x'
:
{
'c'
:
3
,
'd'
:
[
5
,
7
]}}),
'b'
:
raw
({
'a'
:
2
,
'k'
:
'233'
,
'x'
:
{
'c'
:
4
,
'd'
:
[
6
,
8
]}}),
})
assert
subside
(
original2
,
return_type
=
MyTreeValue
,
delayed
=
True
)
==
MyTreeValue
({
'a'
:
raw
({
'a'
:
1
,
'k'
:
'233'
,
'x'
:
{
'c'
:
3
,
'd'
:
[
5
,
7
]}}),
'b'
:
raw
({
'a'
:
2
,
'k'
:
'233'
,
'x'
:
{
'c'
:
4
,
'd'
:
[
6
,
8
]}}),
})
def
test_rise
(
self
):
def
test_rise
(
self
):
t1
=
TreeValue
({
'x'
:
raw
({
'a'
:
[
1
,
2
],
'b'
:
[
2
,
3
]}),
'y'
:
raw
({
'a'
:
[
5
,
6
,
7
],
'b'
:
[
7
,
8
]})})
t1
=
TreeValue
({
'x'
:
raw
({
'a'
:
[
1
,
2
],
'b'
:
[
2
,
3
]}),
'y'
:
raw
({
'a'
:
[
5
,
6
,
7
],
'b'
:
[
7
,
8
]})})
assert
rise
(
t1
)
==
{
assert
rise
(
t1
)
==
{
...
@@ -203,3 +254,21 @@ class TestTreeTreeStructural:
...
@@ -203,3 +254,21 @@ class TestTreeTreeStructural:
rise
(
t5
,
template
=
[
object
,
object
,
object
,
object
,
object
,
...])
rise
(
t5
,
template
=
[
object
,
object
,
object
,
object
,
object
,
...])
assert
rise
(
1
)
==
1
assert
rise
(
1
)
==
1
t1
=
TreeValue
({
'x'
:
raw
({
'a'
:
[
1
,
2
],
'b'
:
[
2
,
3
]}),
'y'
:
raw
({
'a'
:
[
5
,
6
,
7
],
'b'
:
[
7
,
8
]})})
assert
rise
(
t1
)
==
{
'a'
:
TreeValue
({
'x'
:
[
1
,
2
],
'y'
:
[
5
,
6
,
7
]}),
'b'
:
[
TreeValue
({
'x'
:
2
,
'y'
:
7
}),
TreeValue
({
'x'
:
3
,
'y'
:
8
}),
]
}
t10
=
MyTreeValue
({
'v'
:
delayed
(
lambda
:
t1
)})
assert
rise
(
t10
)
==
{
'a'
:
MyTreeValue
({
'v'
:
{
'x'
:
[
1
,
2
],
'y'
:
[
5
,
6
,
7
]}}),
'b'
:
[
MyTreeValue
({
'v'
:
{
'x'
:
2
,
'y'
:
7
}}),
MyTreeValue
({
'v'
:
{
'x'
:
3
,
'y'
:
8
}}),
]
}
test/tree/tree/test_tree.py
浏览文件 @
029f029e
...
@@ -3,7 +3,7 @@ import re
...
@@ -3,7 +3,7 @@ import re
import
pytest
import
pytest
from
treevalue
import
raw
,
TreeValue
from
treevalue
import
raw
,
TreeValue
,
delayed
class
_Container
:
class
_Container
:
...
@@ -121,6 +121,20 @@ class TestTreeTreeTree:
...
@@ -121,6 +121,20 @@ class TestTreeTreeTree:
assert
"c --> <TreeValue"
in
repr
(
tv2
)
assert
"c --> <TreeValue"
in
repr
(
tv2
)
assert
"(The same address as <root>)"
in
repr
(
tv2
)
assert
"(The same address as <root>)"
in
repr
(
tv2
)
tv3
=
TreeValue
({
'a'
:
delayed
(
lambda
:
tv1
.
a
),
'b'
:
delayed
(
lambda
:
tv1
.
b
),
'c'
:
delayed
(
lambda
:
tv1
.
c
),
})
assert
re
.
match
(
r
"<TreeValue 0x[0-9a-f]+>"
,
repr
(
tv3
))
assert
re
.
match
(
r
"<TreeValue 0x[0-9a-f]+>"
,
repr
(
tv3
.
c
))
assert
"a --> 1"
in
str
(
tv3
)
assert
"b --> 2"
in
str
(
tv3
)
assert
"x --> 2"
in
str
(
tv3
)
assert
"y --> 3"
in
str
(
tv3
)
assert
"c --> <TreeValue"
in
str
(
tv3
)
def
test_tree_value_iter
(
self
):
def
test_tree_value_iter
(
self
):
# Attention: dict(tv1) is not supported in python 3.7+
# Attention: dict(tv1) is not supported in python 3.7+
tv1
=
TreeValue
({
'a'
:
1
,
'b'
:
2
,
'c'
:
{
'x'
:
2
,
'y'
:
3
}})
tv1
=
TreeValue
({
'a'
:
1
,
'b'
:
2
,
'c'
:
{
'x'
:
2
,
'y'
:
3
}})
...
...
treevalue/tree/common/__init__.py
浏览文件 @
029f029e
from
.base
import
raw
,
unraw
,
RawWrapper
from
.base
import
raw
,
unraw
,
RawWrapper
from
.delay
import
DelayedProxy
,
delayed_partial
,
undelay
,
DelayedValueProxy
,
DelayedFuncProxy
from
.storage
import
TreeStorage
,
create_storage
from
.storage
import
TreeStorage
,
create_storage
treevalue/tree/common/base.pyx
浏览文件 @
029f029e
...
@@ -39,7 +39,7 @@ cdef class RawWrapper:
...
@@ -39,7 +39,7 @@ cdef class RawWrapper:
self
.
val
=
state
self
.
val
=
state
@
cython
.
binding
(
True
)
@
cython
.
binding
(
True
)
cpdef
public
object
raw
(
object
obj
):
cpdef
inline
object
raw
(
object
obj
):
"""
"""
Overview:
Overview:
Try wrap the given ``obj`` to raw wrapper.
Try wrap the given ``obj`` to raw wrapper.
...
@@ -57,7 +57,7 @@ cpdef public object raw(object obj):
...
@@ -57,7 +57,7 @@ cpdef public object raw(object obj):
return
obj
return
obj
@
cython
.
binding
(
True
)
@
cython
.
binding
(
True
)
cpdef
public
object
unraw
(
object
wrapped
):
cpdef
inline
object
unraw
(
object
wrapped
):
"""
"""
Overview:
Overview:
Try unwrap the given ``wrapped`` to original object.
Try unwrap the given ``wrapped`` to original object.
...
...
treevalue/tree/common/delay.pxd
0 → 100644
浏览文件 @
029f029e
# distutils:language=c++
# cython:language_level=3
from
libcpp
cimport
bool
cdef
class
DelayedProxy
:
cpdef
object
value
(
self
)
cpdef
object
fvalue
(
self
)
cdef
class
DelayedValueProxy
(
DelayedProxy
):
cdef
readonly
object
func
cdef
readonly
bool
calculated
cdef
object
val
cpdef
object
value
(
self
)
cdef
class
DelayedFuncProxy
(
DelayedProxy
):
cdef
readonly
object
func
cdef
readonly
tuple
args
cdef
readonly
dict
kwargs
cdef
readonly
bool
calculated
cdef
object
val
cpdef
object
value
(
self
)
cdef
DelayedProxy
_c_delayed_partial
(
func
,
args
,
kwargs
)
cpdef
object
undelay
(
object
p
,
bool
is_final
=
*
)
treevalue/tree/common/delay.pyx
0 → 100644
浏览文件 @
029f029e
# distutils:language=c++
# cython:language_level=3
import
cython
from
libcpp
cimport
bool
cdef
class
DelayedProxy
:
"""
Overview:
Base class of all the delayed proxy class.
"""
cpdef
object
value
(
self
):
r
"""
Overview:
Get value of the delayed proxy.
Should make sure the result is cached.
Can be accessed in :func:`treevalue.tree.common.undelay` when ``is_final`` is ``False``.
Returns:
- value (:obj:`object`): Calculation result.
"""
raise
NotImplementedError
# pragma: no cover
cpdef
object
fvalue
(
self
):
r
"""
Overview:
Get value of the delayed proxy.
Can be accessed in :func:`treevalue.tree.common.undelay` when ``is_final`` is ``True``.
Returns:
- value (:obj:`object`): Calculation result.
"""
return
self
.
value
()
cdef
class
DelayedValueProxy
(
DelayedProxy
):
"""
Overview:
Simple function delayed proxy.
"""
def
__cinit__
(
self
,
object
func
):
"""
Overview:
Constructor of class :class:`treevalue.tree.common.DelayedValueProxy`.
Arguments:
- func (:obj:`object`): Function to be called, which can be called without arguments.
\
Delayed proxy is supported.
"""
self
.
func
=
func
self
.
calculated
=
False
self
.
val
=
None
cpdef
object
value
(
self
):
cdef
object
f
if
not
self
.
calculated
:
f
=
undelay
(
self
.
func
,
False
)
self
.
val
=
f
()
self
.
calculated
=
True
return
self
.
val
cdef
class
DelayedFuncProxy
(
DelayedProxy
):
"""
Overview:
Simple function delayed proxy.
"""
def
__cinit__
(
self
,
object
func
,
tuple
args
,
dict
kwargs
):
"""
Overview:
Constructor of class :class:`treevalue.tree.common.DelayedFuncProxy`.
Arguments:
- func (:obj:`object`): Function to be called, which can be called with given arguments.
\
Delayed proxy is supported.
- args (:obj:`tuple`): Positional arguments to be used, delayed proxy is supported.
- kwargs (:obj:`dict`): Key-word arguments to be used, delayed proxy is supported.
"""
self
.
func
=
func
self
.
args
=
args
self
.
kwargs
=
kwargs
self
.
calculated
=
False
self
.
val
=
None
cpdef
object
value
(
self
):
cdef
list
pas
cdef
dict
pks
cdef
str
key
cdef
object
item
cdef
object
f
if
not
self
.
calculated
:
pas
=
[]
pks
=
{}
f
=
undelay
(
self
.
func
,
False
)
for
item
in
self
.
args
:
pas
.
append
(
undelay
(
item
,
False
))
for
key
,
item
in
self
.
kwargs
.
items
():
pks
[
key
]
=
undelay
(
item
,
False
)
self
.
val
=
f
(
*
pas
,
**
pks
)
self
.
calculated
=
True
return
self
.
val
cdef
inline
DelayedProxy
_c_delayed_partial
(
func
,
args
,
kwargs
):
if
args
or
kwargs
:
return
DelayedFuncProxy
(
func
,
args
,
kwargs
)
else
:
return
DelayedValueProxy
(
func
)
@
cython
.
binding
(
True
)
def
delayed_partial
(
func
,
*
args
,
**
kwargs
):
"""
Overview:
Build a delayed partial object.
Similar to :func:`functools.partial`.
Returns:
- delayed: Delayed object.
"""
return
_c_delayed_partial
(
func
,
args
,
kwargs
)
@
cython
.
binding
(
True
)
cpdef
inline
object
undelay
(
object
p
,
bool
is_final
=
True
):
r
"""
Overview:
Get the value of a given object, it can be a delayed proxy, a simple object or \
a nested delayed proxy.
Arguments:
- p (:obj:`object`): Given object to be undelay.
- is_final (:obj:`bool`): Is final value getting or not, default is ``True``.
Returns:
- value (:obj:`object): Actual value of the given ``p``.
"""
if
isinstance
(
p
,
DelayedProxy
):
if
is_final
:
return
p
.
fvalue
()
else
:
return
p
.
value
()
else
:
return
p
treevalue/tree/common/storage.pxd
浏览文件 @
029f029e
# distutils:language=c++
# distutils:language=c++
# cython:language_level=3
# cython:language_level=3
from
libcpp
cimport
bool
ctypedef
unsigned
char
boolean
ctypedef
unsigned
char
boolean
ctypedef
unsigned
int
uint
ctypedef
unsigned
int
uint
cdef
void
_key_validate
(
const
char
*
key
)
except
*
cdef
void
_key_validate
(
const
char
*
key
)
except
*
cdef
class
TreeStorage
:
cdef
class
TreeStorage
:
cdef
readonly
dict
map
cdef
readonly
dict
map
...
@@ -19,13 +21,16 @@ cdef class TreeStorage:
...
@@ -19,13 +21,16 @@ cdef class TreeStorage:
cpdef
public
dict
dump
(
self
)
cpdef
public
dict
dump
(
self
)
cpdef
public
dict
deepdump
(
self
)
cpdef
public
dict
deepdump
(
self
)
cpdef
public
dict
deepdumpx
(
self
,
copy_func
)
cpdef
public
dict
deepdumpx
(
self
,
copy_func
)
cpdef
public
dict
jsondumpx
(
self
,
copy_func
,
object
need_raw
)
cpdef
public
dict
jsondumpx
(
self
,
copy_func
,
bool
need_raw
,
bool
allow_delayed
)
cpdef
public
TreeStorage
copy
(
self
)
cpdef
public
TreeStorage
copy
(
self
)
cpdef
public
TreeStorage
deepcopy
(
self
)
cpdef
public
TreeStorage
deepcopy
(
self
)
cpdef
public
TreeStorage
deepcopyx
(
self
,
copy_func
)
cpdef
public
TreeStorage
deepcopyx
(
self
,
copy_func
,
bool
allow_delayed
)
cpdef
public
dict
detach
(
self
)
cpdef
public
dict
detach
(
self
)
cpdef
public
void
copy_from
(
self
,
TreeStorage
ts
)
cpdef
public
void
copy_from
(
self
,
TreeStorage
ts
)
cpdef
public
void
deepcopy_from
(
self
,
TreeStorage
ts
)
cpdef
public
void
deepcopy_from
(
self
,
TreeStorage
ts
)
cpdef
public
void
deepcopyx_from
(
self
,
TreeStorage
ts
,
copy_func
)
cpdef
public
void
deepcopyx_from
(
self
,
TreeStorage
ts
,
copy_func
,
bool
allow_delayed
)
cpdef
public
object
create_storage
(
dict
value
)
cpdef
public
object
create_storage
(
dict
value
)
cdef
object
_c_undelay_data
(
dict
data
,
object
k
,
object
v
)
cdef
object
_c_undelay_not_none_data
(
dict
data
,
object
k
,
object
v
)
cdef
object
_c_undelay_check_data
(
dict
data
,
object
k
,
object
v
)
treevalue/tree/common/storage.pyx
浏览文件 @
029f029e
...
@@ -4,13 +4,15 @@
...
@@ -4,13 +4,15 @@
from
copy
import
deepcopy
from
copy
import
deepcopy
from
libc.string
cimport
strlen
from
libc.string
cimport
strlen
from
libcpp
cimport
bool
from
.base
cimport
raw
,
unraw
from
.base
cimport
raw
,
unraw
from
.delay
cimport
undelay
cdef
inline
object
_keep_object
(
object
obj
):
cdef
inline
object
_keep_object
(
object
obj
):
return
obj
return
obj
cdef
inline
void
_key_validate
(
const
char
*
key
)
except
*
:
cdef
inline
void
_key_validate
(
const
char
*
key
)
except
*
:
cdef
int
n
=
strlen
(
key
)
cdef
int
n
=
strlen
(
key
)
if
n
<
1
:
if
n
<
1
:
raise
KeyError
(
f
'Key
{
repr
(
key
)
}
is too short, minimum length is 1 but
{
n
}
found.'
)
raise
KeyError
(
f
'Key
{
repr
(
key
)
}
is too short, minimum length is 1 but
{
n
}
found.'
)
...
@@ -35,13 +37,17 @@ cdef class TreeStorage:
...
@@ -35,13 +37,17 @@ cdef class TreeStorage:
self
.
map
[
key
]
=
value
self
.
map
[
key
]
=
value
cpdef
public
object
get
(
self
,
str
key
):
cpdef
public
object
get
(
self
,
str
key
):
cdef
object
v
,
nv
try
:
try
:
return
self
.
map
[
key
]
v
=
self
.
map
[
key
]
return
_c_undelay_data
(
self
.
map
,
key
,
v
)
except
KeyError
:
except
KeyError
:
raise
KeyError
(
f
"Key
{
repr
(
key
)
}
not found in this tree."
)
raise
KeyError
(
f
"Key
{
repr
(
key
)
}
not found in this tree."
)
cpdef
public
object
get_or_default
(
self
,
str
key
,
object
default
):
cpdef
public
object
get_or_default
(
self
,
str
key
,
object
default
):
return
self
.
map
.
get
(
key
,
default
)
cdef
object
v
,
nv
v
=
self
.
map
.
get
(
key
,
default
)
return
_c_undelay_check_data
(
self
.
map
,
key
,
v
)
cpdef
public
void
del_
(
self
,
str
key
)
except
*
:
cpdef
public
void
del_
(
self
,
str
key
)
except
*
:
try
:
try
:
...
@@ -65,17 +71,20 @@ cdef class TreeStorage:
...
@@ -65,17 +71,20 @@ cdef class TreeStorage:
return
self
.
deepdumpx
(
deepcopy
)
return
self
.
deepdumpx
(
deepcopy
)
cpdef
public
dict
deepdumpx
(
self
,
copy_func
):
cpdef
public
dict
deepdumpx
(
self
,
copy_func
):
return
self
.
jsondumpx
(
copy_func
,
True
)
return
self
.
jsondumpx
(
copy_func
,
True
,
False
)
cpdef
public
dict
jsondumpx
(
self
,
copy_func
,
object
need_raw
):
cpdef
public
dict
jsondumpx
(
self
,
copy_func
,
bool
need_raw
,
bool
allow_delayed
):
cdef
dict
result
=
{}
cdef
dict
result
=
{}
cdef
str
k
cdef
str
k
cdef
object
v
,
obj
cdef
object
v
,
obj
,
nv
for
k
,
v
in
self
.
map
.
items
():
for
k
,
v
in
self
.
map
.
items
():
if
not
allow_delayed
:
v
=
_c_undelay_data
(
self
.
map
,
k
,
v
)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
result
[
k
]
=
v
.
jsondumpx
(
copy_func
,
need_raw
)
result
[
k
]
=
v
.
jsondumpx
(
copy_func
,
need_raw
,
allow_delayed
)
else
:
else
:
obj
=
copy_func
(
v
)
obj
=
copy_func
(
v
)
if
not
allow_delayed
else
v
if
need_raw
:
if
need_raw
:
obj
=
raw
(
obj
)
obj
=
raw
(
obj
)
result
[
k
]
=
obj
result
[
k
]
=
obj
...
@@ -83,43 +92,48 @@ cdef class TreeStorage:
...
@@ -83,43 +92,48 @@ cdef class TreeStorage:
return
result
return
result
cpdef
public
TreeStorage
copy
(
self
):
cpdef
public
TreeStorage
copy
(
self
):
return
self
.
deepcopyx
(
_keep_object
)
return
self
.
deepcopyx
(
_keep_object
,
True
)
cpdef
public
TreeStorage
deepcopy
(
self
):
cpdef
public
TreeStorage
deepcopy
(
self
):
return
self
.
deepcopyx
(
deepcopy
)
return
self
.
deepcopyx
(
deepcopy
,
False
)
cpdef
public
TreeStorage
deepcopyx
(
self
,
copy_func
):
cpdef
public
TreeStorage
deepcopyx
(
self
,
copy_func
,
bool
allow_delayed
):
cdef
type
cls
=
type
(
self
)
return
create_storage
(
self
.
jsondumpx
(
copy_func
,
True
,
allow_delayed
))
return
create_storage
(
self
.
deepdumpx
(
copy_func
))
cpdef
public
dict
detach
(
self
):
cpdef
public
dict
detach
(
self
):
return
self
.
map
return
self
.
map
cpdef
public
void
copy_from
(
self
,
TreeStorage
ts
):
cpdef
public
void
copy_from
(
self
,
TreeStorage
ts
):
self
.
deepcopyx_from
(
ts
,
_keep_object
)
self
.
deepcopyx_from
(
ts
,
_keep_object
,
True
)
cpdef
public
void
deepcopy_from
(
self
,
TreeStorage
ts
):
cpdef
public
void
deepcopy_from
(
self
,
TreeStorage
ts
):
self
.
deepcopyx_from
(
ts
,
deepcopy
)
self
.
deepcopyx_from
(
ts
,
deepcopy
,
False
)
cpdef
public
void
deepcopyx_from
(
self
,
TreeStorage
ts
,
copy_func
):
cpdef
public
void
deepcopyx_from
(
self
,
TreeStorage
ts
,
copy_func
,
bool
allow_delayed
):
cdef
dict
detached
=
ts
.
detach
()
cdef
dict
detached
=
ts
.
detach
()
cdef
set
keys
=
set
(
self
.
map
.
keys
())
|
set
(
detached
.
keys
())
cdef
set
keys
=
set
(
self
.
map
.
keys
())
|
set
(
detached
.
keys
())
cdef
str
k
cdef
str
k
cdef
object
cdef
object
v
,
nv
cdef
TreeStorage
newv
cdef
TreeStorage
newv
for
k
in
keys
:
for
k
in
keys
:
if
k
in
detached
:
if
k
in
detached
:
v
=
detached
[
k
]
v
=
detached
[
k
]
if
not
allow_delayed
:
v
=
_c_undelay_data
(
detached
,
k
,
v
)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
if
k
in
self
.
map
and
isinstance
(
self
.
map
[
k
],
TreeStorage
):
if
k
in
self
.
map
and
isinstance
(
self
.
map
[
k
],
TreeStorage
):
self
.
map
[
k
].
copy_from
(
v
)
self
.
map
[
k
].
deepcopyx_from
(
v
,
copy_func
,
allow_delayed
)
else
:
else
:
newv
=
TreeStorage
({})
newv
=
TreeStorage
({})
newv
.
copy_from
(
v
)
newv
.
deepcopyx_from
(
v
,
copy_func
,
allow_delayed
)
self
.
map
[
k
]
=
newv
self
.
map
[
k
]
=
newv
else
:
else
:
if
not
allow_delayed
:
self
.
map
[
k
]
=
copy_func
(
v
)
self
.
map
[
k
]
=
copy_func
(
v
)
else
:
self
.
map
[
k
]
=
v
else
:
else
:
del
self
.
map
[
k
]
del
self
.
map
[
k
]
...
@@ -145,12 +159,16 @@ cdef class TreeStorage:
...
@@ -145,12 +159,16 @@ cdef class TreeStorage:
cdef
list
other_keys
=
sorted
(
other
.
detach
().
keys
())
cdef
list
other_keys
=
sorted
(
other
.
detach
().
keys
())
cdef
str
key
cdef
str
key
cdef
object
self_v
cdef
object
self_v
,
self_nv
cdef
object
other_v
cdef
object
other_v
,
other_nv
if
self_keys
==
other_keys
:
if
self_keys
==
other_keys
:
for
key
in
self_keys
:
for
key
in
self_keys
:
self_v
=
self
.
map
[
key
]
self_v
=
self
.
map
[
key
]
self_v
=
_c_undelay_data
(
self
.
map
,
key
,
self_v
)
other_v
=
other_map
[
key
]
other_v
=
other_map
[
key
]
other_v
=
_c_undelay_data
(
other_map
,
key
,
other_v
)
if
self_v
!=
other_v
:
if
self_v
!=
other_v
:
return
False
return
False
return
True
return
True
...
@@ -161,7 +179,7 @@ cdef class TreeStorage:
...
@@ -161,7 +179,7 @@ cdef class TreeStorage:
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
cdef
list
_items
=
[]
cdef
list
_items
=
[]
for
k
,
v
in
sorted
(
self
.
map
.
items
(),
key
=
lambda
x
:
x
[
0
]):
for
k
,
v
in
sorted
(
self
.
items
(),
key
=
lambda
x
:
x
[
0
]):
_items
.
append
((
k
,
v
))
_items
.
append
((
k
,
v
))
return
hash
(
tuple
(
_items
))
return
hash
(
tuple
(
_items
))
...
@@ -170,10 +188,18 @@ cdef class TreeStorage:
...
@@ -170,10 +188,18 @@ cdef class TreeStorage:
return
self
.
map
.
keys
()
return
self
.
map
.
keys
()
def
values
(
self
):
def
values
(
self
):
return
self
.
map
.
values
()
cdef
str
k
cdef
object
v
,
nv
for
k
,
v
in
self
.
map
.
items
():
yield
_c_undelay_data
(
self
.
map
,
k
,
v
)
def
items
(
self
):
def
items
(
self
):
return
self
.
map
.
items
()
cdef
str
k
cdef
object
v
,
nv
for
k
,
v
in
self
.
map
.
items
():
v
=
_c_undelay_data
(
self
.
map
,
k
,
v
)
yield
k
,
v
cpdef
object
create_storage
(
dict
value
):
cpdef
object
create_storage
(
dict
value
):
cdef
dict
_map
=
{}
cdef
dict
_map
=
{}
...
@@ -187,3 +213,21 @@ cpdef object create_storage(dict value):
...
@@ -187,3 +213,21 @@ cpdef object create_storage(dict value):
_map
[
k
]
=
unraw
(
v
)
_map
[
k
]
=
unraw
(
v
)
return
TreeStorage
(
_map
)
return
TreeStorage
(
_map
)
cdef
inline
object
_c_undelay_data
(
dict
data
,
object
k
,
object
v
):
cdef
object
nv
=
undelay
(
v
)
if
nv
is
not
v
:
data
[
k
]
=
nv
return
nv
cdef
inline
object
_c_undelay_not_none_data
(
dict
data
,
object
k
,
object
v
):
cdef
object
nv
=
undelay
(
v
)
if
nv
is
not
v
and
k
is
not
None
:
data
[
k
]
=
nv
return
nv
cdef
inline
object
_c_undelay_check_data
(
dict
data
,
object
k
,
object
v
):
cdef
object
nv
=
undelay
(
v
)
if
nv
is
not
v
and
k
in
data
:
data
[
k
]
=
nv
return
nv
\ No newline at end of file
treevalue/tree/func/cfunc.pxd
浏览文件 @
029f029e
...
@@ -5,11 +5,14 @@ from libcpp cimport bool
...
@@ -5,11 +5,14 @@ from libcpp cimport bool
from
.modes
cimport
_e_tree_mode
from
.modes
cimport
_e_tree_mode
cdef
object
_c_func_treelize_run
(
object
func
,
list
args
,
dict
kwargs
,
cdef
object
_c_wrap_func_treelize_run
(
object
func
,
list
args
,
dict
kwargs
,
_e_tree_mode
mode
,
bool
inherit
,
_e_tree_mode
mode
,
bool
inherit
,
bool
allow_missing
,
object
missing_func
)
bool
allow_missing
,
object
missing_func
,
bool
delayed
)
cdef
object
_c_func_treelize_run
(
object
func
,
list
args
,
dict
kwargs
,
_e_tree_mode
mode
,
bool
inherit
,
bool
allow_missing
,
object
missing_func
,
bool
delayed
)
cpdef
object
_d_func_treelize
(
object
func
,
object
mode
,
object
return_type
,
bool
inherit
,
object
missing
,
cpdef
object
_d_func_treelize
(
object
func
,
object
mode
,
object
return_type
,
bool
inherit
,
object
missing
,
object
subside
,
object
rise
)
bool
delayed
,
object
subside
,
object
rise
)
cdef
_c_common_value
(
object
item
)
cdef
object
_c_common_value
(
object
item
)
cdef
tuple
_c_missing_process
(
object
missing
)
cpdef
object
func_treelize
(
object
mode
=
*
,
object
return_type
=
*
,
bool
inherit
=
*
,
object
missing
=
*
,
cpdef
object
func_treelize
(
object
mode
=
*
,
object
return_type
=
*
,
bool
inherit
=
*
,
object
missing
=
*
,
object
subside
=
*
,
object
rise
=
*
)
bool
delayed
=
*
,
object
subside
=
*
,
object
rise
=
*
)
treevalue/tree/func/cfunc.pyx
浏览文件 @
029f029e
...
@@ -8,20 +8,40 @@ from hbutils.design import SingletonMark
...
@@ -8,20 +8,40 @@ from hbutils.design import SingletonMark
from
libcpp
cimport
bool
from
libcpp
cimport
bool
from
.modes
cimport
_e_tree_mode
,
_c_keyset
,
_c_load_mode
,
_c_check
from
.modes
cimport
_e_tree_mode
,
_c_keyset
,
_c_load_mode
,
_c_check
from
..common.storage
cimport
TreeStorage
from
..common.delay
import
delayed_partial
from
..common.delay
cimport
undelay
from
..common.storage
cimport
TreeStorage
,
_c_undelay_not_none_data
,
_c_undelay_data
from
..tree.structural
cimport
_c_subside
,
_c_rise
from
..tree.structural
cimport
_c_subside
,
_c_rise
from
..tree.tree
cimport
TreeValue
from
..tree.tree
cimport
TreeValue
_VALUE_IS_MISSING
=
SingletonMark
(
'value_is_missing'
)
_VALUE_IS_MISSING
=
SingletonMark
(
'value_is_missing'
)
MISSING_NOT_ALLOW
=
SingletonMark
(
"missing_not_allow"
)
cdef
inline
object
_c_wrap_func_treelize_run
(
object
func
,
list
args
,
dict
kwargs
,
_e_tree_mode
mode
,
bool
inherit
,
bool
allow_missing
,
object
missing_func
,
bool
delayed
):
cdef
list
_l_args
=
[]
cdef
dict
_d_kwargs
=
{}
cdef
str
k
,
ak
cdef
object
av
,
v
,
nv
for
av
,
k
,
v
in
args
:
_l_args
.
append
(
_c_undelay_not_none_data
(
av
,
k
,
v
))
cdef
object
_c_func_treelize_run
(
object
func
,
list
args
,
dict
kwargs
,
for
ak
,
(
av
,
k
,
v
)
in
kwargs
.
items
():
_e_tree_mode
mode
,
bool
inherit
,
bool
allow_missing
,
object
missing_func
):
_d_kwargs
[
ak
]
=
_c_undelay_not_none_data
(
av
,
k
,
v
)
return
_c_func_treelize_run
(
func
,
_l_args
,
_d_kwargs
,
mode
,
inherit
,
allow_missing
,
missing_func
,
delayed
)
cdef
object
_c_func_treelize_run
(
object
func
,
list
args
,
dict
kwargs
,
_e_tree_mode
mode
,
bool
inherit
,
bool
allow_missing
,
object
missing_func
,
bool
delayed
):
cdef
list
ck_args
=
[]
cdef
list
ck_args
=
[]
cdef
list
ck_kwargs
=
[]
cdef
list
ck_kwargs
=
[]
cdef
bool
has_tree
=
False
cdef
bool
has_tree
=
False
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
for
v
in
args
:
for
v
in
args
:
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
ck_args
.
append
((
v
.
detach
(),
True
))
ck_args
.
append
((
v
.
detach
(),
True
))
...
@@ -66,9 +86,17 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs,
...
@@ -66,9 +86,17 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs,
for
i
,
(
av
,
at
)
in
enumerate
(
ck_args
):
for
i
,
(
av
,
at
)
in
enumerate
(
ck_args
):
if
at
:
if
at
:
try
:
try
:
_l_args
.
append
(
av
[
k
])
v
=
av
[
k
]
if
delayed
:
_l_args
.
append
((
av
,
k
,
v
))
else
:
v
=
_c_undelay_data
(
av
,
k
,
v
)
_l_args
.
append
(
v
)
except
KeyError
:
except
KeyError
:
if
allow_missing
:
if
allow_missing
:
if
delayed
:
_l_args
.
append
((
None
,
None
,
_VALUE_IS_MISSING
))
else
:
_l_args
.
append
(
_VALUE_IS_MISSING
)
_l_args
.
append
(
_VALUE_IS_MISSING
)
else
:
else
:
raise
KeyError
(
"Missing is off, key {key} not found in {item}."
.
format
(
raise
KeyError
(
"Missing is off, key {key} not found in {item}."
.
format
(
...
@@ -76,7 +104,10 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs,
...
@@ -76,7 +104,10 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs,
))
))
else
:
else
:
if
inherit
:
if
inherit
:
_l_args
.
append
(
av
)
if
delayed
:
_l_args
.
append
((
None
,
None
,
av
))
else
:
_l_args
.
append
(
undelay
(
av
))
else
:
else
:
raise
TypeError
(
"Inherit is off, tree value expected but {type} found in args {index}."
.
format
(
raise
TypeError
(
"Inherit is off, tree value expected but {type} found in args {index}."
.
format
(
type
=
repr
(
type
(
av
).
__name__
),
index
=
repr
(
i
),
type
=
repr
(
type
(
av
).
__name__
),
index
=
repr
(
i
),
...
@@ -86,9 +117,17 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs,
...
@@ -86,9 +117,17 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs,
for
ak
,
av
,
at
in
ck_kwargs
:
for
ak
,
av
,
at
in
ck_kwargs
:
if
at
:
if
at
:
try
:
try
:
_d_kwargs
[
ak
]
=
av
[
k
]
v
=
av
[
k
]
if
delayed
:
_d_kwargs
[
ak
]
=
(
av
,
k
,
v
)
else
:
v
=
_c_undelay_data
(
av
,
k
,
v
)
_d_kwargs
[
ak
]
=
v
except
KeyError
:
except
KeyError
:
if
allow_missing
:
if
allow_missing
:
if
delayed
:
_d_kwargs
[
ak
]
=
(
None
,
None
,
_VALUE_IS_MISSING
)
else
:
_d_kwargs
[
ak
]
=
_VALUE_IS_MISSING
_d_kwargs
[
ak
]
=
_VALUE_IS_MISSING
else
:
else
:
raise
KeyError
(
"Missing is off, key {key} not found in {item}."
.
format
(
raise
KeyError
(
"Missing is off, key {key} not found in {item}."
.
format
(
...
@@ -96,19 +135,27 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs,
...
@@ -96,19 +135,27 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs,
))
))
else
:
else
:
if
inherit
:
if
inherit
:
_d_kwargs
[
ak
]
=
av
if
delayed
:
_d_kwargs
[
ak
]
=
(
None
,
None
,
av
)
else
:
_d_kwargs
[
ak
]
=
undelay
(
av
)
else
:
else
:
raise
TypeError
(
"Inherit is off, tree value expected but {type} found in args {index}."
.
format
(
raise
TypeError
(
"Inherit is off, tree value expected but {type} found in args {index}."
.
format
(
type
=
repr
(
type
(
av
).
__name__
),
index
=
repr
(
ak
),
type
=
repr
(
type
(
av
).
__name__
),
index
=
repr
(
ak
),
))
))
if
delayed
:
_d_res
[
k
]
=
delayed_partial
(
_c_wrap_func_treelize_run
,
func
,
_l_args
,
_d_kwargs
,
mode
,
inherit
,
allow_missing
,
missing_func
,
delayed
)
else
:
_d_res
[
k
]
=
_c_func_treelize_run
(
func
,
_l_args
,
_d_kwargs
,
_d_res
[
k
]
=
_c_func_treelize_run
(
func
,
_l_args
,
_d_kwargs
,
mode
,
inherit
,
allow_missing
,
missing_func
)
mode
,
inherit
,
allow_missing
,
missing_func
,
delayed
)
return
TreeStorage
(
_d_res
)
return
TreeStorage
(
_d_res
)
def
_w_subside_func
(
object
value
,
bool
dict_
=
True
,
bool
list_
=
True
,
bool
tuple_
=
True
,
bool
inherit
=
True
):
def
_w_subside_func
(
object
value
,
bool
dict_
=
True
,
bool
list_
=
True
,
bool
tuple_
=
True
,
bool
inherit
=
True
,
return
_c_subside
(
value
,
dict_
,
list_
,
tuple_
,
inherit
)[
0
]
object
mode
=
'strict'
,
object
missing
=
MISSING_NOT_ALLOW
,
bool
delayed
=
False
):
return
_c_subside
(
value
,
dict_
,
list_
,
tuple_
,
inherit
,
mode
,
missing
,
delayed
)[
0
]
def
_w_rise_func
(
object
tree
,
bool
dict_
=
True
,
bool
list_
=
True
,
bool
tuple_
=
True
,
object
template
=
None
):
def
_w_rise_func
(
object
tree
,
bool
dict_
=
True
,
bool
list_
=
True
,
bool
tuple_
=
True
,
object
template
=
None
):
return
_c_rise
(
tree
,
dict_
,
list_
,
tuple_
,
template
)
return
_c_rise
(
tree
,
dict_
,
list_
,
tuple_
,
template
)
...
@@ -116,16 +163,18 @@ def _w_rise_func(object tree, bool dict_=True, bool list_=True, bool tuple_=True
...
@@ -116,16 +163,18 @@ def _w_rise_func(object tree, bool dict_=True, bool list_=True, bool tuple_=True
# runtime function
# runtime function
def
_w_func_treelize_run
(
*
args
,
object
__w_func
,
_e_tree_mode
__w_mode
,
object
__w_return_type
,
def
_w_func_treelize_run
(
*
args
,
object
__w_func
,
_e_tree_mode
__w_mode
,
object
__w_return_type
,
bool
__w_inherit
,
bool
__w_allow_missing
,
object
__w_missing_func
,
bool
__w_inherit
,
bool
__w_allow_missing
,
object
__w_missing_func
,
object
__w_subside
,
object
__w_rise
,
**
kwargs
):
bool
__w_delayed
,
object
__w_subside
,
object
__w_rise
,
**
kwargs
):
cdef
list
_a_args
=
[(
item
.
_detach
()
if
isinstance
(
item
,
TreeValue
)
else
item
)
for
item
in
args
]
cdef
list
_a_args
=
[(
item
.
_detach
()
if
isinstance
(
item
,
TreeValue
)
else
item
)
for
item
in
args
]
cdef
dict
_a_kwargs
=
{
k
:
(
v
.
_detach
()
if
isinstance
(
v
,
TreeValue
)
else
v
)
for
k
,
v
in
kwargs
.
items
()}
cdef
dict
_a_kwargs
=
{
k
:
(
v
.
_detach
()
if
isinstance
(
v
,
TreeValue
)
else
v
)
for
k
,
v
in
kwargs
.
items
()}
cdef
dict
_w_subside_cfg
if
__w_subside
is
not
None
:
if
__w_subside
is
not
None
:
_a_args
=
[
_w_subside_func
(
item
,
**
__w_subside
)
for
item
in
_a_args
]
_w_subside_cfg
=
{
'delayed'
:
__w_delayed
,
**
__w_subside
}
_a_kwargs
=
{
key
:
_w_subside_func
(
value
,
**
__w_subside
)
for
key
,
value
in
_a_kwargs
.
items
()}
_a_args
=
[
_w_subside_func
(
item
,
**
_w_subside_cfg
)
for
item
in
_a_args
]
_a_kwargs
=
{
key
:
_w_subside_func
(
value
,
**
_w_subside_cfg
)
for
key
,
value
in
_a_kwargs
.
items
()}
cdef
object
_st_res
=
_c_func_treelize_run
(
__w_func
,
_a_args
,
_a_kwargs
,
__w_mode
,
cdef
object
_st_res
=
_c_func_treelize_run
(
__w_func
,
_a_args
,
_a_kwargs
,
__w_mode
,
__w_inherit
,
__w_allow_missing
,
__w_missing_func
)
__w_inherit
,
__w_allow_missing
,
__w_missing_func
,
__w_delayed
)
cdef
object
_o_res
cdef
object
_o_res
if
__w_return_type
is
not
None
:
if
__w_return_type
is
not
None
:
...
@@ -144,15 +193,10 @@ def _w_func_treelize_run(*args, object __w_func, _e_tree_mode __w_mode, object _
...
@@ -144,15 +193,10 @@ def _w_func_treelize_run(*args, object __w_func, _e_tree_mode __w_mode, object _
else
:
else
:
return
None
return
None
MISSING_NOT_ALLOW
=
SingletonMark
(
"missing_not_allow"
)
cdef
object
_c_common_value
(
object
item
):
cdef
_c_common_value
(
object
item
):
return
item
return
item
# build-time function
cdef
inline
tuple
_c_missing_process
(
object
missing
):
cpdef
object
_d_func_treelize
(
object
func
,
object
mode
,
object
return_type
,
bool
inherit
,
object
missing
,
object
subside
,
object
rise
):
cdef
_e_tree_mode
_v_mode
=
_c_load_mode
(
mode
)
cdef
bool
allow_missing
cdef
bool
allow_missing
cdef
object
missing_func
cdef
object
missing_func
if
missing
is
MISSING_NOT_ALLOW
:
if
missing
is
MISSING_NOT_ALLOW
:
...
@@ -162,6 +206,16 @@ cpdef object _d_func_treelize(object func, object mode, object return_type, bool
...
@@ -162,6 +206,16 @@ cpdef object _d_func_treelize(object func, object mode, object return_type, bool
allow_missing
=
True
allow_missing
=
True
missing_func
=
missing
if
callable
(
missing
)
else
partial
(
_c_common_value
,
missing
)
missing_func
=
missing
if
callable
(
missing
)
else
partial
(
_c_common_value
,
missing
)
return
allow_missing
,
missing_func
# build-time function
cpdef
object
_d_func_treelize
(
object
func
,
object
mode
,
object
return_type
,
bool
inherit
,
object
missing
,
bool
delayed
,
object
subside
,
object
rise
):
cdef
_e_tree_mode
_v_mode
=
_c_load_mode
(
mode
)
cdef
bool
allow_missing
cdef
object
missing_func
allow_missing
,
missing_func
=
_c_missing_process
(
missing
)
cdef
object
_v_subside
,
_v_rise
cdef
object
_v_subside
,
_v_rise
if
subside
is
not
None
and
not
isinstance
(
subside
,
dict
):
if
subside
is
not
None
and
not
isinstance
(
subside
,
dict
):
_v_subside
=
{}
if
subside
else
None
_v_subside
=
{}
if
subside
else
None
...
@@ -175,12 +229,12 @@ cpdef object _d_func_treelize(object func, object mode, object return_type, bool
...
@@ -175,12 +229,12 @@ cpdef object _d_func_treelize(object func, object mode, object return_type, bool
_c_check
(
_v_mode
,
return_type
,
inherit
,
allow_missing
,
missing_func
)
_c_check
(
_v_mode
,
return_type
,
inherit
,
allow_missing
,
missing_func
)
return
partial
(
_w_func_treelize_run
,
__w_func
=
func
,
__w_mode
=
_v_mode
,
__w_return_type
=
return_type
,
return
partial
(
_w_func_treelize_run
,
__w_func
=
func
,
__w_mode
=
_v_mode
,
__w_return_type
=
return_type
,
__w_inherit
=
inherit
,
__w_allow_missing
=
allow_missing
,
__w_missing_func
=
missing_func
,
__w_inherit
=
inherit
,
__w_allow_missing
=
allow_missing
,
__w_missing_func
=
missing_func
,
__w_subside
=
_v_subside
,
__w_rise
=
_v_rise
)
__w_
delayed
=
delayed
,
__w_
subside
=
_v_subside
,
__w_rise
=
_v_rise
)
@
cython
.
binding
(
True
)
@
cython
.
binding
(
True
)
cpdef
object
func_treelize
(
object
mode
=
'strict'
,
object
return_type
=
TreeValue
,
cpdef
object
func_treelize
(
object
mode
=
'strict'
,
object
return_type
=
TreeValue
,
bool
inherit
=
True
,
object
missing
=
MISSING_NOT_ALLOW
,
bool
inherit
=
True
,
object
missing
=
MISSING_NOT_ALLOW
,
object
subside
=
None
,
object
rise
=
None
):
bool
delayed
=
False
,
object
subside
=
None
,
object
rise
=
None
):
"""
"""
Overview:
Overview:
Wrap a common function to tree-supported function.
Wrap a common function to tree-supported function.
...
@@ -191,6 +245,8 @@ cpdef object func_treelize(object mode='strict', object return_type=TreeValue,
...
@@ -191,6 +245,8 @@ cpdef object func_treelize(object mode='strict', object return_type=TreeValue,
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
- delayed (:obj:`bool`): Enable delayed mode or not, the calculation will be delayed when enabled,
\
default is ``False``, which means to all the calculation at once.
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
and subside configuration, default is `None` which means do not use subside.
\
and subside configuration, default is `None` which means do not use subside.
\
When subside is `True`, it will use all the default arguments in `subside` function.
When subside is `True`, it will use all the default arguments in `subside` function.
...
@@ -213,4 +269,4 @@ cpdef object func_treelize(object mode='strict', object return_type=TreeValue,
...
@@ -213,4 +269,4 @@ cpdef object func_treelize(object mode='strict', object return_type=TreeValue,
>>> ssum(t1, t2) # TreeValue({'a': 12, 'b': 24, 'x': {'c': 36, 'd': 9}})
>>> ssum(t1, t2) # TreeValue({'a': 12, 'b': 24, 'x': {'c': 36, 'd': 9}})
"""
"""
return
partial
(
_d_func_treelize
,
mode
=
mode
,
return_type
=
return_type
,
return
partial
(
_d_func_treelize
,
mode
=
mode
,
return_type
=
return_type
,
inherit
=
inherit
,
missing
=
missing
,
subside
=
subside
,
rise
=
rise
)
inherit
=
inherit
,
missing
=
missing
,
delayed
=
delayed
,
subside
=
subside
,
rise
=
rise
)
treevalue/tree/func/func.py
浏览文件 @
029f029e
...
@@ -12,7 +12,7 @@ TreeClassType_ = TypeVar("TreeClassType_", bound=TreeValue)
...
@@ -12,7 +12,7 @@ TreeClassType_ = TypeVar("TreeClassType_", bound=TreeValue)
def
func_treelize
(
mode
:
str
=
'strict'
,
return_type
:
Optional
[
Type
[
TreeClassType_
]]
=
TreeValue
,
def
func_treelize
(
mode
:
str
=
'strict'
,
return_type
:
Optional
[
Type
[
TreeClassType_
]]
=
TreeValue
,
inherit
:
bool
=
True
,
missing
:
Union
[
Any
,
Callable
]
=
MISSING_NOT_ALLOW
,
inherit
:
bool
=
True
,
missing
:
Union
[
Any
,
Callable
]
=
MISSING_NOT_ALLOW
,
delayed
:
bool
=
False
,
subside
:
Union
[
Mapping
,
bool
,
None
]
=
None
,
rise
:
Union
[
Mapping
,
bool
,
None
]
=
None
):
subside
:
Union
[
Mapping
,
bool
,
None
]
=
None
,
rise
:
Union
[
Mapping
,
bool
,
None
]
=
None
):
"""
"""
Overview:
Overview:
...
@@ -21,9 +21,11 @@ def func_treelize(mode: str = 'strict', return_type: Optional[Type[TreeClassType
...
@@ -21,9 +21,11 @@ def func_treelize(mode: str = 'strict', return_type: Optional[Type[TreeClassType
Arguments:
Arguments:
- mode (:obj:`str`): Mode of the wrapping, default is `strict`.
- mode (:obj:`str`): Mode of the wrapping, default is `strict`.
- return_type (:obj:`Optional[Type[TreeClassType_]]`): Return type of the wrapped function, default is `TreeValue`.
- return_type (:obj:`Optional[Type[TreeClassType_]]`): Return type of the wrapped function, default is `TreeValue`.
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- inherit (:obj:`bool`): Allow inherit
ing
in wrapped function, default is `True`.
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
- delayed (:obj:`bool`): Enable delayed mode or not, the calculation will be delayed when enabled,
\
default is ``False``, which means to all the calculation at once.
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
and subside configuration, default is `None` which means do not use subside.
\
and subside configuration, default is `None` which means do not use subside.
\
When subside is `True`, it will use all the default arguments in `subside` function.
When subside is `True`, it will use all the default arguments in `subside` function.
...
@@ -47,7 +49,7 @@ def func_treelize(mode: str = 'strict', return_type: Optional[Type[TreeClassType
...
@@ -47,7 +49,7 @@ def func_treelize(mode: str = 'strict', return_type: Optional[Type[TreeClassType
"""
"""
def
_decorator
(
func
):
def
_decorator
(
func
):
_treelized
=
_c_func_treelize
(
mode
,
return_type
,
inherit
,
missing
,
subside
,
rise
)(
func
)
_treelized
=
_c_func_treelize
(
mode
,
return_type
,
inherit
,
missing
,
delayed
,
subside
,
rise
)(
func
)
@
wraps
(
func
)
@
wraps
(
func
)
def
_new_func
(
*
args
,
**
kwargs
):
def
_new_func
(
*
args
,
**
kwargs
):
...
@@ -82,7 +84,7 @@ def method_treelize(mode: str = 'strict', return_type: Optional[Type[TreeClassTy
...
@@ -82,7 +84,7 @@ def method_treelize(mode: str = 'strict', return_type: Optional[Type[TreeClassTy
- mode (:obj:`str`): Mode of the wrapping, default is `strict`.
- mode (:obj:`str`): Mode of the wrapping, default is `strict`.
- return_type (:obj:`Optional[Type[TreeClassType_]]`): Return type of the wrapped function,
\
- return_type (:obj:`Optional[Type[TreeClassType_]]`): Return type of the wrapped function,
\
default is `AUTO_DETECT_RETURN_VALUE`, which means automatically use the decorated method's class.
default is `AUTO_DETECT_RETURN_VALUE`, which means automatically use the decorated method's class.
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- inherit (:obj:`bool`): Allow inherit
ing
in wrapped function, default is `True`.
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
...
@@ -154,7 +156,7 @@ def classmethod_treelize(mode: str = 'strict', return_type: Optional[Type[TreeCl
...
@@ -154,7 +156,7 @@ def classmethod_treelize(mode: str = 'strict', return_type: Optional[Type[TreeCl
- mode (:obj:`str`): Mode of the wrapping, default is `strict`.
- mode (:obj:`str`): Mode of the wrapping, default is `strict`.
- return_type (:obj:`Optional[Type[TreeClassType_]]`): Return type of the wrapped function,
\
- return_type (:obj:`Optional[Type[TreeClassType_]]`): Return type of the wrapped function,
\
default is `AUTO_DETECT_RETURN_VALUE`, which means automatically use the decorated method's class.
default is `AUTO_DETECT_RETURN_VALUE`, which means automatically use the decorated method's class.
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- inherit (:obj:`bool`): Allow inherit
ing
in wrapped function, default is `True`.
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
...
...
treevalue/tree/general/general.py
浏览文件 @
029f029e
...
@@ -147,13 +147,14 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
...
@@ -147,13 +147,14 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
return
typetrans
(
self
,
clazz
)
return
typetrans
(
self
,
clazz
)
@
_decorate_method
@
_decorate_method
def
map
(
self
,
mapper
):
def
map
(
self
,
mapper
,
delayed
=
False
):
"""
"""
Overview:
Overview:
Do mapping on every value in this tree.
Do mapping on every value in this tree.
Arguments:
Arguments:
- func (:obj:): Function for mapping
- func (:obj:): Function for mapping
- delayed (:obj:`bool`): Enable delayed mode for this mapping.
Returns:
Returns:
- tree (:obj:`_TreeValue`): Mapped tree value object.
- tree (:obj:`_TreeValue`): Mapped tree value object.
...
@@ -164,7 +165,7 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
...
@@ -164,7 +165,7 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
>>> t.map(lambda: 1) # FastTreeValue({'a': 1, 'b': 1, 'x': {'c': 1, 'd': 1}})
>>> t.map(lambda: 1) # FastTreeValue({'a': 1, 'b': 1, 'x': {'c': 1, 'd': 1}})
>>> t.map(lambda x, p: p) # FastTreeValue({'a': ('a',), 'b': ('b',), 'x': {'c': ('x', 'c'), 'd': ('x', 'd')}})
>>> t.map(lambda x, p: p) # FastTreeValue({'a': ('a',), 'b': ('b',), 'x': {'c': ('x', 'c'), 'd': ('x', 'd')}})
"""
"""
return
mapping
(
self
,
mapper
)
return
mapping
(
self
,
mapper
,
delayed
)
@
_decorate_method
@
_decorate_method
def
mask
(
self
,
mask_
:
TreeValue
,
remove_empty
:
bool
=
True
):
def
mask
(
self
,
mask_
:
TreeValue
,
remove_empty
:
bool
=
True
):
...
@@ -308,9 +309,8 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
...
@@ -308,9 +309,8 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
@
classmethod
@
classmethod
@
_decorate_method
@
_decorate_method
def
func
(
cls
,
mode
:
str
=
'strict'
,
inherit
:
bool
=
True
,
def
func
(
cls
,
mode
:
str
=
'strict'
,
inherit
:
bool
=
True
,
missing
:
Union
[
Any
,
Callable
]
=
MISSING_NOT_ALLOW
,
missing
:
Union
[
Any
,
Callable
]
=
MISSING_NOT_ALLOW
,
delayed
:
bool
=
False
,
subside
:
Union
[
Mapping
,
bool
,
None
]
=
None
,
subside
:
Union
[
Mapping
,
bool
,
None
]
=
None
,
rise
:
Union
[
Mapping
,
bool
,
None
]
=
None
):
rise
:
Union
[
Mapping
,
bool
,
None
]
=
None
):
"""
"""
Overview:
Overview:
Wrap a common function to tree-supported function based on this type.
Wrap a common function to tree-supported function based on this type.
...
@@ -320,6 +320,8 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
...
@@ -320,6 +320,8 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
- delayed (:obj:`bool`): Enable delayed mode or not, the calculation will be delayed when enabled,
\
default is ``False``, which means to all the calculation at once.
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
- subside (:obj:`Union[Mapping, bool, None]`): Subside enabled to function's arguments or not,
\
and subside configuration, default is `None` which means do not use subside.
\
and subside configuration, default is `None` which means do not use subside.
\
When subside is `True`, it will use all the default arguments in `subside` function.
When subside is `True`, it will use all the default arguments in `subside` function.
...
@@ -343,7 +345,7 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
...
@@ -343,7 +345,7 @@ def general_tree_value(base: Optional[Mapping[str, Any]] = None,
>>> ssum(1, 2) # 3
>>> ssum(1, 2) # 3
>>> ssum(t1, t2) # FastTreeValue({'a': 12, 'b': 24, 'x': {'c': 36, 'd': 9}})
>>> ssum(t1, t2) # FastTreeValue({'a': 12, 'b': 24, 'x': {'c': 36, 'd': 9}})
"""
"""
return
func_treelize
(
mode
,
cls
,
inherit
,
missing
,
subside
,
rise
)
return
func_treelize
(
mode
,
cls
,
inherit
,
missing
,
delayed
,
subside
,
rise
)
@
classmethod
@
classmethod
@
_decorate_method
@
_decorate_method
...
...
treevalue/tree/tree/__init__.py
浏览文件 @
029f029e
...
@@ -4,4 +4,4 @@ from .graph import graphics
...
@@ -4,4 +4,4 @@ from .graph import graphics
from
.io
import
loads
,
load
,
dumps
,
dump
from
.io
import
loads
,
load
,
dumps
,
dump
from
.service
import
jsonify
,
clone
,
typetrans
,
walk
from
.service
import
jsonify
,
clone
,
typetrans
,
walk
from
.structural
import
subside
,
union
,
rise
from
.structural
import
subside
,
union
,
rise
from
.tree
import
TreeValue
from
.tree
import
TreeValue
,
delayed
treevalue/tree/tree/flatten.pyx
浏览文件 @
029f029e
...
@@ -6,15 +6,16 @@
...
@@ -6,15 +6,16 @@
import
cython
import
cython
from
.tree
cimport
TreeValue
from
.tree
cimport
TreeValue
from
..common.storage
cimport
TreeStorage
from
..common.storage
cimport
TreeStorage
,
_c_undelay_data
cdef
void
_c_flatten
(
TreeStorage
st
,
tuple
path
,
list
res
)
except
*
:
cdef
void
_c_flatten
(
TreeStorage
st
,
tuple
path
,
list
res
)
except
*
:
cdef
dict
data
=
st
.
detach
()
cdef
dict
data
=
st
.
detach
()
cdef
tuple
curpath
cdef
tuple
curpath
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
for
k
,
v
in
data
.
items
():
for
k
,
v
in
data
.
items
():
v
=
_c_undelay_data
(
data
,
k
,
v
)
curpath
=
path
+
(
k
,)
curpath
=
path
+
(
k
,)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
_c_flatten
(
v
,
curpath
,
res
)
_c_flatten
(
v
,
curpath
,
res
)
...
@@ -47,8 +48,9 @@ cdef void _c_flatten_values(TreeStorage st, list res) except *:
...
@@ -47,8 +48,9 @@ cdef void _c_flatten_values(TreeStorage st, list res) except *:
cdef
dict
data
=
st
.
detach
()
cdef
dict
data
=
st
.
detach
()
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
for
k
,
v
in
data
.
items
():
for
k
,
v
in
data
.
items
():
v
=
_c_undelay_data
(
data
,
k
,
v
)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
_c_flatten_values
(
v
,
res
)
_c_flatten_values
(
v
,
res
)
else
:
else
:
...
@@ -75,8 +77,9 @@ cdef void _c_flatten_keys(TreeStorage st, tuple path, list res) except *:
...
@@ -75,8 +77,9 @@ cdef void _c_flatten_keys(TreeStorage st, tuple path, list res) except *:
cdef
tuple
curpath
cdef
tuple
curpath
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
for
k
,
v
in
data
.
items
():
for
k
,
v
in
data
.
items
():
v
=
_c_undelay_data
(
data
,
k
,
v
)
curpath
=
path
+
(
k
,)
curpath
=
path
+
(
k
,)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
_c_flatten_keys
(
v
,
curpath
,
res
)
_c_flatten_keys
(
v
,
curpath
,
res
)
...
...
treevalue/tree/tree/functional.pxd
浏览文件 @
029f029e
...
@@ -12,8 +12,9 @@ cdef object _c_no_arg(object func, object v, object p)
...
@@ -12,8 +12,9 @@ cdef object _c_no_arg(object func, object v, object p)
cdef
object
_c_one_arg
(
object
func
,
object
v
,
object
p
)
cdef
object
_c_one_arg
(
object
func
,
object
v
,
object
p
)
cdef
object
_c_two_args
(
object
func
,
object
v
,
object
p
)
cdef
object
_c_two_args
(
object
func
,
object
v
,
object
p
)
cdef
object
_c_wrap_mapping_func
(
object
func
)
cdef
object
_c_wrap_mapping_func
(
object
func
)
cdef
TreeStorage
_c_mapping
(
TreeStorage
st
,
object
func
,
tuple
path
)
cdef
object
_c_delayed_mapping
(
object
so
,
object
func
,
tuple
path
,
bool
delayed
)
cpdef
TreeValue
mapping
(
TreeValue
tree
,
object
func
)
cdef
TreeStorage
_c_mapping
(
TreeStorage
st
,
object
func
,
tuple
path
,
bool
delayed
)
cpdef
TreeValue
mapping
(
TreeValue
tree
,
object
func
,
bool
delayed
=
*
)
cdef
TreeStorage
_c_filter_
(
TreeStorage
st
,
object
func
,
tuple
path
,
bool
remove_empty
)
cdef
TreeStorage
_c_filter_
(
TreeStorage
st
,
object
func
,
tuple
path
,
bool
remove_empty
)
cpdef
TreeValue
filter_
(
TreeValue
tree
,
object
func
,
bool
remove_empty
=
*
)
cpdef
TreeValue
filter_
(
TreeValue
tree
,
object
func
,
bool
remove_empty
=
*
)
cdef
object
_c_mask
(
TreeStorage
st
,
object
sm
,
tuple
path
,
bool
remove_empty
)
cdef
object
_c_mask
(
TreeStorage
st
,
object
sm
,
tuple
path
,
bool
remove_empty
)
...
...
treevalue/tree/tree/functional.pyx
浏览文件 @
029f029e
...
@@ -8,7 +8,9 @@ from functools import partial
...
@@ -8,7 +8,9 @@ from functools import partial
from
libcpp
cimport
bool
from
libcpp
cimport
bool
from
.tree
cimport
TreeValue
from
.tree
cimport
TreeValue
from
..common.storage
cimport
TreeStorage
from
..common.delay
cimport
undelay
from
..common.delay
import
delayed_partial
from
..common.storage
cimport
TreeStorage
,
_c_undelay_data
cdef
inline
object
_c_no_arg
(
object
func
,
object
v
,
object
p
):
cdef
inline
object
_c_no_arg
(
object
func
,
object
v
,
object
p
):
return
func
()
return
func
()
...
@@ -33,24 +35,40 @@ cdef inline object _c_wrap_mapping_func(object func):
...
@@ -33,24 +35,40 @@ cdef inline object _c_wrap_mapping_func(object func):
else
:
else
:
return
partial
(
_c_no_arg
,
func
)
return
partial
(
_c_no_arg
,
func
)
cdef
TreeStorage
_c_mapping
(
TreeStorage
st
,
object
func
,
tuple
path
):
cdef
object
_c_delayed_mapping
(
object
so
,
object
func
,
tuple
path
,
bool
delayed
):
cdef
object
nso
=
undelay
(
so
)
if
isinstance
(
nso
,
TreeValue
):
nso
=
nso
.
_detach
()
if
isinstance
(
nso
,
TreeStorage
):
return
_c_mapping
(
nso
,
func
,
path
,
delayed
)
else
:
return
func
(
nso
,
path
)
cdef
TreeStorage
_c_mapping
(
TreeStorage
st
,
object
func
,
tuple
path
,
bool
delayed
):
cdef
dict
_d_st
=
st
.
detach
()
cdef
dict
_d_st
=
st
.
detach
()
cdef
dict
_d_res
=
{}
cdef
dict
_d_res
=
{}
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
cdef
tuple
curpath
cdef
tuple
curpath
for
k
,
v
in
_d_st
.
items
():
for
k
,
v
in
_d_st
.
items
():
if
not
delayed
:
v
=
_c_undelay_data
(
_d_st
,
k
,
v
)
curpath
=
path
+
(
k
,)
curpath
=
path
+
(
k
,)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
_d_res
[
k
]
=
_c_mapping
(
v
,
func
,
curpath
)
_d_res
[
k
]
=
_c_mapping
(
v
,
func
,
curpath
,
delayed
)
else
:
if
delayed
:
_d_res
[
k
]
=
delayed_partial
(
_c_delayed_mapping
,
v
,
func
,
curpath
,
delayed
)
else
:
else
:
_d_res
[
k
]
=
func
(
v
,
curpath
)
_d_res
[
k
]
=
func
(
v
,
curpath
)
return
TreeStorage
(
_d_res
)
return
TreeStorage
(
_d_res
)
@
cython
.
binding
(
True
)
@
cython
.
binding
(
True
)
cpdef
TreeValue
mapping
(
TreeValue
tree
,
object
func
):
cpdef
TreeValue
mapping
(
TreeValue
tree
,
object
func
,
bool
delayed
=
False
):
"""
"""
Overview:
Overview:
Do mapping on every value in this tree.
Do mapping on every value in this tree.
...
@@ -80,17 +98,18 @@ cpdef TreeValue mapping(TreeValue tree, object func):
...
@@ -80,17 +98,18 @@ cpdef TreeValue mapping(TreeValue tree, object func):
>>> mapping(t, lambda: 1) # TreeValue({'a': 1, 'b': 1, 'x': {'c': 1, 'd': 1}})
>>> mapping(t, lambda: 1) # TreeValue({'a': 1, 'b': 1, 'x': {'c': 1, 'd': 1}})
>>> mapping(t, lambda x, p: p) # TreeValue({'a': ('a',), 'b': ('b',), 'x': {'c': ('x', 'c'), 'd': ('x', 'd')}})
>>> mapping(t, lambda x, p: p) # TreeValue({'a': ('a',), 'b': ('b',), 'x': {'c': ('x', 'c'), 'd': ('x', 'd')}})
"""
"""
return
type
(
tree
)(
_c_mapping
(
tree
.
_detach
(),
_c_wrap_mapping_func
(
func
),
()))
return
type
(
tree
)(
_c_mapping
(
tree
.
_detach
(),
_c_wrap_mapping_func
(
func
),
()
,
delayed
))
cdef
TreeStorage
_c_filter_
(
TreeStorage
st
,
object
func
,
tuple
path
,
bool
remove_empty
):
cdef
TreeStorage
_c_filter_
(
TreeStorage
st
,
object
func
,
tuple
path
,
bool
remove_empty
):
cdef
dict
_d_st
=
st
.
detach
()
cdef
dict
_d_st
=
st
.
detach
()
cdef
dict
_d_res
=
{}
cdef
dict
_d_res
=
{}
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
cdef
tuple
curpath
cdef
tuple
curpath
cdef
TreeStorage
curst
cdef
TreeStorage
curst
for
k
,
v
in
_d_st
.
items
():
for
k
,
v
in
_d_st
.
items
():
v
=
_c_undelay_data
(
_d_st
,
k
,
v
)
curpath
=
path
+
(
k
,)
curpath
=
path
+
(
k
,)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
curst
=
_c_filter_
(
v
,
func
,
curpath
,
remove_empty
)
curst
=
_c_filter_
(
v
,
func
,
curpath
,
remove_empty
)
...
@@ -148,9 +167,11 @@ cdef object _c_mask(TreeStorage st, object sm, tuple path, bool remove_empty):
...
@@ -148,9 +167,11 @@ cdef object _c_mask(TreeStorage st, object sm, tuple path, bool remove_empty):
cdef
tuple
curpath
cdef
tuple
curpath
cdef
object
curres
cdef
object
curres
for
k
,
v
in
_d_st
.
items
():
for
k
,
v
in
_d_st
.
items
():
v
=
_c_undelay_data
(
_d_st
,
k
,
v
)
curpath
=
path
+
(
k
,)
curpath
=
path
+
(
k
,)
if
_b_tree_mask
:
if
_b_tree_mask
:
mv
=
_d_sm
[
k
]
mv
=
_d_sm
[
k
]
mv
=
_c_undelay_data
(
_d_sm
,
k
,
mv
)
else
:
else
:
mv
=
sm
mv
=
sm
...
@@ -194,10 +215,11 @@ cdef object _c_reduce(TreeStorage st, object func, tuple path, object return_typ
...
@@ -194,10 +215,11 @@ cdef object _c_reduce(TreeStorage st, object func, tuple path, object return_typ
cdef
dict
_d_kwargs
=
{}
cdef
dict
_d_kwargs
=
{}
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
cdef
tuple
curpath
cdef
tuple
curpath
cdef
object
curst
cdef
object
curst
for
k
,
v
in
_d_st
.
items
():
for
k
,
v
in
_d_st
.
items
():
v
=
_c_undelay_data
(
_d_st
,
k
,
v
)
curpath
=
path
+
(
k
,)
curpath
=
path
+
(
k
,)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
curst
=
_c_reduce
(
v
,
func
,
curpath
,
return_type
)
curst
=
_c_reduce
(
v
,
func
,
curpath
,
return_type
)
...
...
treevalue/tree/tree/service.pyx
浏览文件 @
029f029e
...
@@ -9,7 +9,7 @@ import cython
...
@@ -9,7 +9,7 @@ import cython
from
libcpp
cimport
bool
from
libcpp
cimport
bool
from
.tree
cimport
TreeValue
from
.tree
cimport
TreeValue
from
..common.storage
cimport
TreeStorage
from
..common.storage
cimport
TreeStorage
,
_c_undelay_data
cdef
object
_keep_object
(
object
obj
):
cdef
object
_keep_object
(
object
obj
):
return
obj
return
obj
...
@@ -29,7 +29,7 @@ cpdef object jsonify(TreeValue val):
...
@@ -29,7 +29,7 @@ cpdef object jsonify(TreeValue val):
Example:
Example:
>>> jsonify(TreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})) # {'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}
>>> jsonify(TreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})) # {'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}
"""
"""
return
val
.
_detach
().
jsondumpx
(
_keep_object
,
False
)
return
val
.
_detach
().
jsondumpx
(
_keep_object
,
False
,
False
)
@
cython
.
binding
(
True
)
@
cython
.
binding
(
True
)
cpdef
TreeValue
clone
(
TreeValue
t
,
object
copy_value
=
None
):
cpdef
TreeValue
clone
(
TreeValue
t
,
object
copy_value
=
None
):
...
@@ -50,10 +50,18 @@ cpdef TreeValue clone(TreeValue t, object copy_value=None):
...
@@ -50,10 +50,18 @@ cpdef TreeValue clone(TreeValue t, object copy_value=None):
>>> t = TreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})
>>> t = TreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})
>>> clone(t.x) # TreeValue({'c': 3, 'd': 4})
>>> clone(t.x) # TreeValue({'c': 3, 'd': 4})
"""
"""
cdef
bool
need_copy
if
not
callable
(
copy_value
):
if
not
callable
(
copy_value
):
copy_value
=
copy
.
deepcopy
if
copy_value
else
_keep_object
if
copy_value
:
need_copy
=
True
copy_value
=
copy
.
deepcopy
else
:
need_copy
=
False
copy_value
=
_keep_object
else
:
need_copy
=
True
return
type
(
t
)(
t
.
_detach
().
deepcopyx
(
copy_value
))
return
type
(
t
)(
t
.
_detach
().
deepcopyx
(
copy_value
,
not
need_copy
))
@
cython
.
binding
(
True
)
@
cython
.
binding
(
True
)
cpdef
TreeValue
typetrans
(
TreeValue
t
,
object
return_type
):
cpdef
TreeValue
typetrans
(
TreeValue
t
,
object
return_type
):
...
@@ -87,9 +95,10 @@ def _p_walk(TreeStorage tree, object type_, tuple path, bool include_nodes):
...
@@ -87,9 +95,10 @@ def _p_walk(TreeStorage tree, object type_, tuple path, bool include_nodes):
cdef
dict
data
=
tree
.
detach
()
cdef
dict
data
=
tree
.
detach
()
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
cdef
tuple
curpath
cdef
tuple
curpath
for
k
,
v
in
data
.
items
():
for
k
,
v
in
data
.
items
():
v
=
_c_undelay_data
(
data
,
k
,
v
)
curpath
=
path
+
(
k
,)
curpath
=
path
+
(
k
,)
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
yield
from
_p_walk
(
v
,
type_
,
curpath
,
include_nodes
)
yield
from
_p_walk
(
v
,
type_
,
curpath
,
include_nodes
)
...
...
treevalue/tree/tree/structural.pxd
浏览文件 @
029f029e
...
@@ -11,10 +11,11 @@ cdef class _SubsideCall:
...
@@ -11,10 +11,11 @@ cdef class _SubsideCall:
cdef
object
_c_subside_process
(
tuple
value
,
object
it
)
cdef
object
_c_subside_process
(
tuple
value
,
object
it
)
cdef
tuple
_c_subside_build
(
object
value
,
bool
dict_
,
bool
list_
,
bool
tuple_
)
cdef
tuple
_c_subside_build
(
object
value
,
bool
dict_
,
bool
list_
,
bool
tuple_
)
cdef
void
_c_subside_missing
()
cdef
void
_c_subside_missing
()
cdef
object
_c_subside
(
object
value
,
bool
dict_
,
bool
list_
,
bool
tuple_
,
bool
inherit
)
cdef
object
_c_subside
(
object
value
,
bool
dict_
,
bool
list_
,
bool
tuple_
,
bool
inherit
,
object
mode
,
object
missing
,
bool
delayed
)
cdef
object
_c_subside_keep_type
(
object
t
)
cdef
object
_c_subside_keep_type
(
object
t
)
cpdef
object
subside
(
object
value
,
bool
dict_
=
*
,
bool
list_
=
*
,
bool
tuple_
=
*
,
cpdef
object
subside
(
object
value
,
bool
dict_
=
*
,
bool
list_
=
*
,
bool
tuple_
=
*
,
object
return_type
=
*
,
bool
inherit
=
*
)
object
return_type
=
*
,
bool
inherit
=
*
,
object
mode
=
*
,
object
missing
=
*
,
bool
delayed
=
*
)
cdef
object
_c_rise_tree_builder
(
tuple
p
,
object
it
)
cdef
object
_c_rise_tree_builder
(
tuple
p
,
object
it
)
cdef
tuple
_c_rise_tree_process
(
object
t
)
cdef
tuple
_c_rise_tree_process
(
object
t
)
...
...
treevalue/tree/tree/structural.pyx
浏览文件 @
029f029e
...
@@ -6,13 +6,16 @@
...
@@ -6,13 +6,16 @@
from
itertools
import
chain
from
itertools
import
chain
import
cython
import
cython
from
hbutils.design
import
SingletonMark
from
libcpp
cimport
bool
from
libcpp
cimport
bool
from
.tree
cimport
TreeValue
from
.tree
cimport
TreeValue
from
..common.storage
cimport
TreeStorage
from
..common.storage
cimport
TreeStorage
,
_c_undelay_data
from
..func.cfunc
cimport
_c_func_treelize_run
from
..func.cfunc
cimport
_c_func_treelize_run
,
_c_missing_process
from
..func.modes
cimport
_c_load_mode
from
..func.modes
cimport
_c_load_mode
MISSING_NOT_ALLOW
=
SingletonMark
(
"missing_not_allow"
)
cdef
object
_c_subside_process
(
tuple
value
,
object
it
):
cdef
object
_c_subside_process
(
tuple
value
,
object
it
):
cdef
type
type_
cdef
type
type_
cdef
list
items
cdef
list
items
...
@@ -76,25 +79,29 @@ cdef tuple _c_subside_build(object value, bool dict_, bool list_, bool tuple_):
...
@@ -76,25 +79,29 @@ cdef tuple _c_subside_build(object value, bool dict_, bool list_, bool tuple_):
else
:
else
:
return
(
object
,
None
),
(
value
,),
()
return
(
object
,
None
),
(
value
,),
()
STRICT
=
_c_load_mode
(
'STRICT'
)
cdef
inline
void
_c_subside_missing
():
cdef
inline
void
_c_subside_missing
():
pass
pass
cdef
object
_c_subside
(
object
value
,
bool
dict_
,
bool
list_
,
bool
tuple_
,
bool
inherit
):
cdef
object
_c_subside
(
object
value
,
bool
dict_
,
bool
list_
,
bool
tuple_
,
bool
inherit
,
object
mode
,
object
missing
,
bool
delayed
):
cdef
object
builder
,
_i_args
,
_i_types
cdef
object
builder
,
_i_args
,
_i_types
builder
,
_i_args
,
_i_types
=
_c_subside_build
(
value
,
dict_
,
list_
,
tuple_
)
builder
,
_i_args
,
_i_types
=
_c_subside_build
(
value
,
dict_
,
list_
,
tuple_
)
cdef
list
args
=
list
(
_i_args
)
cdef
list
args
=
list
(
_i_args
)
cdef
bool
allow_missing
cdef
object
missing_func
allow_missing
,
missing_func
=
_c_missing_process
(
missing
)
return
_c_func_treelize_run
(
_SubsideCall
(
builder
),
args
,
{},
return
_c_func_treelize_run
(
_SubsideCall
(
builder
),
args
,
{},
STRICT
,
inherit
,
False
,
_c_subside_missing
),
_i_types
_c_load_mode
(
mode
),
inherit
,
allow_missing
,
missing_func
,
delayed
),
_i_types
cdef
inline
object
_c_subside_keep_type
(
object
t
):
cdef
inline
object
_c_subside_keep_type
(
object
t
):
return
t
return
t
@
cython
.
binding
(
True
)
@
cython
.
binding
(
True
)
cpdef
object
subside
(
object
value
,
bool
dict_
=
True
,
bool
list_
=
True
,
bool
tuple_
=
True
,
cpdef
object
subside
(
object
value
,
bool
dict_
=
True
,
bool
list_
=
True
,
bool
tuple_
=
True
,
object
return_type
=
None
,
bool
inherit
=
True
):
object
return_type
=
None
,
bool
inherit
=
True
,
object
mode
=
'strict'
,
object
missing
=
MISSING_NOT_ALLOW
,
bool
delayed
=
False
):
"""
"""
Overview:
Overview:
Drift down the structures (list, tuple, dict) down to the tree's value.
Drift down the structures (list, tuple, dict) down to the tree's value.
...
@@ -108,6 +115,11 @@ cpdef object subside(object value, bool dict_=True, bool list_=True, bool tuple_
...
@@ -108,6 +115,11 @@ cpdef object subside(object value, bool dict_=True, bool list_=True, bool tuple_
will be auto detected when there is exactly one tree value type in this original value,
\
will be auto detected when there is exactly one tree value type in this original value,
\
otherwise the default will be `TreeValue`.
otherwise the default will be `TreeValue`.
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- mode (:obj:`str`): Mode of the wrapping, default is `strict`.
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
- delayed (:obj:`bool`): Enable delayed mode or not, the calculation will be delayed when enabled,
\
default is ``False``, which means to all the calculation at once.
Returns:
Returns:
- return (:obj:`_TreeValue`): Subsided tree value.
- return (:obj:`_TreeValue`): Subsided tree value.
...
@@ -132,7 +144,7 @@ cpdef object subside(object value, bool dict_=True, bool list_=True, bool tuple_
...
@@ -132,7 +144,7 @@ cpdef object subside(object value, bool dict_=True, bool list_=True, bool tuple_
>>> #}), all structures above the tree values are subsided to the bottom of the tree.
>>> #}), all structures above the tree values are subsided to the bottom of the tree.
"""
"""
cdef
object
result
,
_i_types
cdef
object
result
,
_i_types
result
,
_i_types
=
_c_subside
(
value
,
dict_
,
list_
,
tuple_
,
inherit
)
result
,
_i_types
=
_c_subside
(
value
,
dict_
,
list_
,
tuple_
,
inherit
,
mode
,
missing
,
delayed
)
cdef
object
type_
cdef
object
type_
cdef
set
types
cdef
set
types
...
@@ -150,7 +162,8 @@ cpdef object subside(object value, bool dict_=True, bool list_=True, bool tuple_
...
@@ -150,7 +162,8 @@ cpdef object subside(object value, bool dict_=True, bool list_=True, bool tuple_
return
type_
(
result
)
return
type_
(
result
)
@
cython
.
binding
(
True
)
@
cython
.
binding
(
True
)
def
union
(
*
trees
,
object
return_type
=
None
,
bool
inherit
=
True
):
def
union
(
*
trees
,
object
return_type
=
None
,
bool
inherit
=
True
,
object
mode
=
'strict'
,
object
missing
=
MISSING_NOT_ALLOW
,
bool
delayed
=
False
):
"""
"""
Overview:
Overview:
Union tree values together.
Union tree values together.
...
@@ -158,7 +171,12 @@ def union(*trees, object return_type=None, bool inherit=True):
...
@@ -158,7 +171,12 @@ def union(*trees, object return_type=None, bool inherit=True):
Arguments:
Arguments:
- trees (:obj:`_TreeValue`): Tree value objects.
- trees (:obj:`_TreeValue`): Tree value objects.
- return_type (:obj:`Optional[Type[_ClassType]]`): Return type of the wrapped function, default is `TreeValue`.
- return_type (:obj:`Optional[Type[_ClassType]]`): Return type of the wrapped function, default is `TreeValue`.
- inherit (:obj:`bool`): Allow inherit in wrapped function, default is `True`.
- inherit (:obj:`bool`): Allow inheriting in wrapped function, default is `True`.
- mode (:obj:`str`): Mode of the wrapping, default is `strict`.
- missing (:obj:`Union[Any, Callable]`): Missing value or lambda generator of when missing,
\
default is `MISSING_NOT_ALLOW`, which means raise `KeyError` when missing detected.
- delayed (:obj:`bool`): Enable delayed mode or not, the calculation will be delayed when enabled,
\
default is ``False``, which means to all the calculation at once.
Returns:
Returns:
- result (:obj:`TreeValue`): Unionised tree value.
- result (:obj:`TreeValue`): Unionised tree value.
...
@@ -169,7 +187,7 @@ def union(*trees, object return_type=None, bool inherit=True):
...
@@ -169,7 +187,7 @@ def union(*trees, object return_type=None, bool inherit=True):
>>> union(t, tx) # TreeValue({'a': (1, True), 'b': (2, False), 'x': {'c': (3, True), 'd': (4, False)}})
>>> union(t, tx) # TreeValue({'a': (1, True), 'b': (2, False), 'x': {'c': (3, True), 'd': (4, False)}})
"""
"""
cdef
object
result
,
_i_types
cdef
object
result
,
_i_types
result
,
_i_types
=
_c_subside
(
tuple
(
trees
),
True
,
True
,
True
,
inherit
)
result
,
_i_types
=
_c_subside
(
tuple
(
trees
),
True
,
True
,
True
,
inherit
,
mode
,
missing
,
delayed
)
cdef
object
type_
cdef
object
type_
cdef
list
types
cdef
list
types
...
@@ -200,7 +218,7 @@ cdef object _c_rise_tree_builder(tuple p, object it):
...
@@ -200,7 +218,7 @@ cdef object _c_rise_tree_builder(tuple p, object it):
cdef
tuple
_c_rise_tree_process
(
object
t
):
cdef
tuple
_c_rise_tree_process
(
object
t
):
cdef
str
k
cdef
str
k
cdef
object
v
cdef
object
v
,
nv
cdef
list
_l_items
,
_l_values
cdef
list
_l_items
,
_l_values
cdef
object
_i_item
,
_i_value
cdef
object
_i_item
,
_i_value
cdef
dict
detached
cdef
dict
detached
...
@@ -209,6 +227,7 @@ cdef tuple _c_rise_tree_process(object t):
...
@@ -209,6 +227,7 @@ cdef tuple _c_rise_tree_process(object t):
_l_items
=
[]
_l_items
=
[]
_l_values
=
[]
_l_values
=
[]
for
k
,
v
in
detached
.
items
():
for
k
,
v
in
detached
.
items
():
v
=
_c_undelay_data
(
detached
,
k
,
v
)
_i_item
,
_i_value
=
_c_rise_tree_process
(
v
)
_i_item
,
_i_value
=
_c_rise_tree_process
(
v
)
_l_items
.
append
((
k
,
_i_item
))
_l_items
.
append
((
k
,
_i_item
))
_l_values
.
append
(
_i_value
)
_l_values
.
append
(
_i_value
)
...
...
treevalue/tree/tree/tree.pxd
浏览文件 @
029f029e
# distutils:language=c++
# distutils:language=c++
# cython:language_level=3
# cython:language_level=3
from
libcpp
cimport
bool
from
..common.delay
cimport
DelayedProxy
from
..common.storage
cimport
TreeStorage
from
..common.storage
cimport
TreeStorage
cdef
class
TreeValue
:
cdef
class
TreeValue
:
...
@@ -15,3 +18,11 @@ cdef class TreeValue:
...
@@ -15,3 +18,11 @@ cdef class TreeValue:
cdef
str
_prefix_fix
(
object
text
,
object
prefix
)
cdef
str
_prefix_fix
(
object
text
,
object
prefix
)
cdef
object
_build_tree
(
TreeStorage
st
,
object
type_
,
str
prefix
,
dict
id_pool
,
tuple
path
)
cdef
object
_build_tree
(
TreeStorage
st
,
object
type_
,
str
prefix
,
dict
id_pool
,
tuple
path
)
cdef
class
DetachedDelayedProxy
(
DelayedProxy
):
cdef
DelayedProxy
proxy
cdef
readonly
bool
calculated
cdef
object
val
cpdef
object
value
(
self
)
cpdef
object
fvalue
(
self
)
\ No newline at end of file
treevalue/tree/tree/tree.pyx
浏览文件 @
029f029e
...
@@ -7,7 +7,8 @@ from operator import itemgetter
...
@@ -7,7 +7,8 @@ from operator import itemgetter
import
cython
import
cython
from
hbutils.design
import
SingletonMark
from
hbutils.design
import
SingletonMark
from
..common.storage
cimport
TreeStorage
,
create_storage
from
..common.delay
cimport
undelay
,
_c_delayed_partial
,
DelayedProxy
from
..common.storage
cimport
TreeStorage
,
create_storage
,
_c_undelay_data
from
...utils
import
format_tree
from
...utils
import
format_tree
_GET_NO_DEFAULT
=
SingletonMark
(
'get_no_default'
)
_GET_NO_DEFAULT
=
SingletonMark
(
'get_no_default'
)
...
@@ -385,7 +386,7 @@ cdef object _build_tree(TreeStorage st, object type_, str prefix, dict id_pool,
...
@@ -385,7 +386,7 @@ cdef object _build_tree(TreeStorage st, object type_, str prefix, dict id_pool,
cdef
list
children
=
[]
cdef
list
children
=
[]
cdef
str
k
,
_t_prefix
cdef
str
k
,
_t_prefix
cdef
object
v
cdef
object
v
,
nv
cdef
dict
data
cdef
dict
data
cdef
tuple
curpath
cdef
tuple
curpath
if
nid
in
id_pool
:
if
nid
in
id_pool
:
...
@@ -395,6 +396,7 @@ cdef object _build_tree(TreeStorage st, object type_, str prefix, dict id_pool,
...
@@ -395,6 +396,7 @@ cdef object _build_tree(TreeStorage st, object type_, str prefix, dict id_pool,
id_pool
[
nid
]
=
path
id_pool
[
nid
]
=
path
data
=
st
.
detach
()
data
=
st
.
detach
()
for
k
,
v
in
sorted
(
data
.
items
()):
for
k
,
v
in
sorted
(
data
.
items
()):
v
=
_c_undelay_data
(
data
,
k
,
v
)
curpath
=
path
+
(
k
,)
curpath
=
path
+
(
k
,)
_t_prefix
=
f
'
{
k
}
--> '
_t_prefix
=
f
'
{
k
}
--> '
if
isinstance
(
v
,
TreeStorage
):
if
isinstance
(
v
,
TreeStorage
):
...
@@ -404,3 +406,67 @@ cdef object _build_tree(TreeStorage st, object type_, str prefix, dict id_pool,
...
@@ -404,3 +406,67 @@ cdef object _build_tree(TreeStorage st, object type_, str prefix, dict id_pool,
self_repr
=
_prefix_fix
(
self_repr
,
prefix
)
self_repr
=
_prefix_fix
(
self_repr
,
prefix
)
return
self_repr
,
children
return
self_repr
,
children
cdef
class
DetachedDelayedProxy
(
DelayedProxy
):
def
__init__
(
self
,
DelayedProxy
proxy
):
self
.
proxy
=
proxy
self
.
calculated
=
False
self
.
val
=
None
cpdef
object
value
(
self
):
if
not
self
.
calculated
:
self
.
val
=
undelay
(
self
.
proxy
,
False
)
self
.
calculated
=
True
return
self
.
val
cpdef
object
fvalue
(
self
):
cdef
object
v
=
self
.
value
()
if
isinstance
(
v
,
TreeValue
):
v
=
v
.
_detach
()
return
v
@
cython
.
binding
(
True
)
def
delayed
(
func
,
*
args
,
**
kwargs
):
r
"""
Overview:
Use delayed function in treevalue.
The given ``func`` will not be called until its value is accessed, and \
it will be only called once, after that the delayed node will be replaced by the actual value.
Arguments:
- func: Delayed function.
- args: Positional arguments.
- kwargs: Key-word arguments.
Examples::
>>> from treevalue import TreeValue, delayed
>>>
>>> def f(x):
>>> print('f is called, x is', x)
>>> return x ** x
>>>
>>> t = TreeValue({'a': delayed(f, 2), 'x': delayed(f, 3)})
>>> t.a
f is called, x is 2
4
>>> t.x
f is called, x is 3
27
>>> t.a
4
>>> t.x
27
>>> t = TreeValue({'a': delayed(f, 2), 'x': delayed(f, 3)})
>>> print(t)
f is called, x is 2
f is called, x is 3
<TreeValue 0x7f0fb7f03198>
├── a --> 4
└── x --> 27
>>> print(t)
<TreeValue 0x7f0fb7f03198>
├── a --> 4
└── x --> 27
"""
return
DetachedDelayedProxy
(
_c_delayed_partial
(
func
,
args
,
kwargs
))
HansBug
😆
@HansBug
mentioned in commit
03354468
·
1月 05, 2022
mentioned in commit
03354468
mentioned in commit 033544685d52647a7053c86eb54730344231c239
开关提交列表
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录