diff --git a/treevalue/tree/common/storage.pxd b/treevalue/tree/common/storage.pxd index 986cb527be..4713bc650e 100644 --- a/treevalue/tree/common/storage.pxd +++ b/treevalue/tree/common/storage.pxd @@ -31,3 +31,6 @@ cdef class TreeStorage: cpdef public void deepcopyx_from(self, TreeStorage ts, copy_func, bool allow_delayed) 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) diff --git a/treevalue/tree/common/storage.pyx b/treevalue/tree/common/storage.pyx index 6f28c7d49a..ffd698db72 100644 --- a/treevalue/tree/common/storage.pyx +++ b/treevalue/tree/common/storage.pyx @@ -40,25 +40,14 @@ cdef class TreeStorage: cdef object v, nv try: v = self.map[key] - nv = undelay(v) - if nv is not v: - self.map[key] = nv - return nv - else: - return v + return _c_undelay_data(self.map, key, v) except KeyError: raise KeyError(f"Key {repr(key)} not found in this tree.") cpdef public object get_or_default(self, str key, object default): cdef object v, nv v = self.map.get(key, default) - nv = undelay(v) - if nv is not v: - v = nv - if key in self.map: - self.map[key] = v - - return v + return _c_undelay_check_data(self.map, key, v) cpdef public void del_(self, str key) except *: try: @@ -90,10 +79,7 @@ cdef class TreeStorage: cdef object v, obj, nv for k, v in self.map.items(): if not allow_delayed: - nv = undelay(v) - if nv is not v: - v = nv - self.map[k] = v + v = _c_undelay_data(self.map, k, v) if isinstance(v, TreeStorage): result[k] = v.jsondumpx(copy_func, need_raw, allow_delayed) @@ -134,10 +120,7 @@ cdef class TreeStorage: if k in detached: v = detached[k] if not allow_delayed: - nv = undelay(v) - if nv is not v: - v = nv - detached[k] = v + v = _c_undelay_data(detached, k, v) if isinstance(v, TreeStorage): if k in self.map and isinstance(self.map[k], TreeStorage): @@ -181,16 +164,10 @@ cdef class TreeStorage: if self_keys == other_keys: for key in self_keys: self_v = self.map[key] - self_nv = undelay(self_v) - if self_nv is not self_v: - self_v = self_nv - self.map[key] = self_v + self_v = _c_undelay_data(self.map, key, self_v) other_v = other_map[key] - other_nv = undelay(other_v) - if other_nv is not other_v: - other_v = other_nv - other_map[key] = other_v + other_v = _c_undelay_data(other_map, key, other_v) if self_v != other_v: return False @@ -214,21 +191,13 @@ cdef class TreeStorage: cdef str k cdef object v, nv for k, v in self.map.items(): - nv = undelay(v) - if nv is not v: - v = nv - self.map[k] = v - - yield v + yield _c_undelay_data(self.map, k, v) def items(self): cdef str k cdef object v, nv for k, v in self.map.items(): - nv = undelay(v) - if nv is not v: - v = nv - self.map[k] = v + v = _c_undelay_data(self.map, k, v) yield k, v @@ -244,3 +213,21 @@ cpdef object create_storage(dict value): _map[k] = unraw(v) 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 diff --git a/treevalue/tree/func/cfunc.pyx b/treevalue/tree/func/cfunc.pyx index 47cc69a148..535fc77b70 100644 --- a/treevalue/tree/func/cfunc.pyx +++ b/treevalue/tree/func/cfunc.pyx @@ -10,13 +10,15 @@ from libcpp cimport bool from .modes cimport _e_tree_mode, _c_keyset, _c_load_mode, _c_check from ..common.delay import delayed_partial from ..common.delay cimport undelay -from ..common.storage cimport TreeStorage +from ..common.storage cimport TreeStorage, _c_undelay_not_none_data, _c_undelay_data from ..tree.structural cimport _c_subside, _c_rise from ..tree.tree cimport TreeValue _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 = [] @@ -24,18 +26,10 @@ cdef inline object _c_wrap_func_treelize_run(object func, list args, dict kwargs cdef str k, ak cdef object av, v, nv for av, k, v in args: - nv = undelay(v) - if nv is not v and k is not None: - av[k] = nv - - _l_args.append(nv) + _l_args.append(_c_undelay_not_none_data(av, k, v)) for ak, (av, k, v) in kwargs.items(): - nv = undelay(v) - if nv is not v and k is not None: - av[k] = nv - - _d_kwargs[ak] = nv + _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) @@ -96,11 +90,7 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs, _e_tree_mo if delayed: _l_args.append((av, k, v)) else: - nv = undelay(v) - if nv is not v: - v = nv - av[k] = v - + v = _c_undelay_data(av, k, v) _l_args.append(v) except KeyError: if allow_missing: @@ -131,11 +121,7 @@ cdef object _c_func_treelize_run(object func, list args, dict kwargs, _e_tree_mo if delayed: _d_kwargs[ak] = (av, k, v) else: - nv = undelay(v) - if nv is not v: - v = nv - av[k] = v - + v = _c_undelay_data(av, k, v) _d_kwargs[ak] = v except KeyError: if allow_missing: diff --git a/treevalue/tree/tree/flatten.pyx b/treevalue/tree/tree/flatten.pyx index aa38e822f1..54449a8c2e 100644 --- a/treevalue/tree/tree/flatten.pyx +++ b/treevalue/tree/tree/flatten.pyx @@ -6,8 +6,7 @@ import cython from .tree cimport TreeValue -from ..common.delay cimport undelay -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 dict data = st.detach() @@ -16,11 +15,7 @@ cdef void _c_flatten(TreeStorage st, tuple path, list res) except *: cdef str k cdef object v, nv for k, v in data.items(): - nv = undelay(v) - if nv is not v: - v = nv - data[k] = v - + v = _c_undelay_data(data, k, v) curpath = path + (k,) if isinstance(v, TreeStorage): _c_flatten(v, curpath, res) @@ -55,11 +50,7 @@ cdef void _c_flatten_values(TreeStorage st, list res) except *: cdef str k cdef object v, nv for k, v in data.items(): - nv = undelay(v) - if nv is not v: - v = nv - data[k] = v - + v = _c_undelay_data(data, k, v) if isinstance(v, TreeStorage): _c_flatten_values(v, res) else: @@ -88,11 +79,7 @@ cdef void _c_flatten_keys(TreeStorage st, tuple path, list res) except *: cdef str k cdef object v, nv for k, v in data.items(): - nv = undelay(v) - if nv is not v: - v = nv - data[k] = v - + v = _c_undelay_data(data, k, v) curpath = path + (k,) if isinstance(v, TreeStorage): _c_flatten_keys(v, curpath, res) diff --git a/treevalue/tree/tree/functional.pyx b/treevalue/tree/tree/functional.pyx index 66b9987298..b94b7300b9 100644 --- a/treevalue/tree/tree/functional.pyx +++ b/treevalue/tree/tree/functional.pyx @@ -10,7 +10,7 @@ from libcpp cimport bool from .tree cimport TreeValue from ..common.delay cimport undelay from ..common.delay import delayed_partial -from ..common.storage cimport TreeStorage +from ..common.storage cimport TreeStorage, _c_undelay_data cdef inline object _c_no_arg(object func, object v, object p): return func() @@ -54,10 +54,7 @@ cdef TreeStorage _c_mapping(TreeStorage st, object func, tuple path, bool delaye cdef tuple curpath for k, v in _d_st.items(): if not delayed: - nv = undelay(v) - if nv is not v: - v = nv - _d_st[k] = v + v = _c_undelay_data(_d_st, k, v) curpath = path + (k,) if isinstance(v, TreeStorage): @@ -112,11 +109,7 @@ cdef TreeStorage _c_filter_(TreeStorage st, object func, tuple path, bool remove cdef tuple curpath cdef TreeStorage curst for k, v in _d_st.items(): - nv = undelay(v) - if nv is not v: - v = nv - _d_st[k] = v - + v = _c_undelay_data(_d_st, k, v) curpath = path + (k,) if isinstance(v, TreeStorage): curst = _c_filter_(v, func, curpath, remove_empty) @@ -170,24 +163,17 @@ cdef object _c_mask(TreeStorage st, object sm, tuple path, bool remove_empty): cdef dict _d_res = {} cdef str k - cdef object v, mv, nv, nmv + cdef object v, mv cdef tuple curpath cdef object curres for k, v in _d_st.items(): - nv = undelay(v) - if nv is not v: - v = nv - _d_st[k] = v - + v = _c_undelay_data(_d_st, k, v) curpath = path + (k,) if _b_tree_mask: mv = _d_sm[k] + mv = _c_undelay_data(_d_sm, k, mv) else: mv = sm - nmv = undelay(mv) - if nmv is not mv: - mv = nmv - _d_sm[k] = mv if isinstance(v, TreeStorage): curres = _c_mask(v, mv, curpath, remove_empty) @@ -233,11 +219,7 @@ cdef object _c_reduce(TreeStorage st, object func, tuple path, object return_typ cdef tuple curpath cdef object curst for k, v in _d_st.items(): - nv = undelay(v) - if nv is not v: - v = nv - _d_st[k] = v - + v = _c_undelay_data(_d_st, k, v) curpath = path + (k,) if isinstance(v, TreeStorage): curst = _c_reduce(v, func, curpath, return_type) diff --git a/treevalue/tree/tree/service.pyx b/treevalue/tree/tree/service.pyx index ed373e02f4..466e277607 100644 --- a/treevalue/tree/tree/service.pyx +++ b/treevalue/tree/tree/service.pyx @@ -9,8 +9,7 @@ import cython from libcpp cimport bool from .tree cimport TreeValue -from ..common.delay cimport undelay -from ..common.storage cimport TreeStorage +from ..common.storage cimport TreeStorage, _c_undelay_data cdef object _keep_object(object obj): return obj @@ -99,11 +98,7 @@ def _p_walk(TreeStorage tree, object type_, tuple path, bool include_nodes): cdef object v, nv cdef tuple curpath for k, v in data.items(): - nv = undelay(v) - if nv is not v: - v = nv - data[k] = v - + v = _c_undelay_data(data, k, v) curpath = path + (k,) if isinstance(v, TreeStorage): yield from _p_walk(v, type_, curpath, include_nodes) diff --git a/treevalue/tree/tree/structural.pyx b/treevalue/tree/tree/structural.pyx index 9d30b6397f..1c5aa049a4 100644 --- a/treevalue/tree/tree/structural.pyx +++ b/treevalue/tree/tree/structural.pyx @@ -10,8 +10,7 @@ from hbutils.design import SingletonMark from libcpp cimport bool from .tree cimport TreeValue -from ..common.delay cimport undelay -from ..common.storage cimport TreeStorage +from ..common.storage cimport TreeStorage, _c_undelay_data from ..func.cfunc cimport _c_func_treelize_run, _c_missing_process from ..func.modes cimport _c_load_mode @@ -228,11 +227,7 @@ cdef tuple _c_rise_tree_process(object t): _l_items = [] _l_values = [] for k, v in detached.items(): - nv = undelay(v) - if nv is not v: - v = nv - detached[k] = v - + v = _c_undelay_data(detached, k, v) _i_item, _i_value = _c_rise_tree_process(v) _l_items.append((k, _i_item)) _l_values.append(_i_value) diff --git a/treevalue/tree/tree/tree.pyx b/treevalue/tree/tree/tree.pyx index fc032e9c44..ced2beb4fa 100644 --- a/treevalue/tree/tree/tree.pyx +++ b/treevalue/tree/tree/tree.pyx @@ -8,7 +8,7 @@ import cython from hbutils.design import SingletonMark from ..common.delay cimport undelay, _c_delayed_partial, DelayedProxy -from ..common.storage cimport TreeStorage, create_storage +from ..common.storage cimport TreeStorage, create_storage, _c_undelay_data from ...utils import format_tree _GET_NO_DEFAULT = SingletonMark('get_no_default') @@ -396,11 +396,7 @@ cdef object _build_tree(TreeStorage st, object type_, str prefix, dict id_pool, id_pool[nid] = path data = st.detach() for k, v in sorted(data.items()): - nv = undelay(v) - if nv is not v: - v = nv - data[k] = v - + v = _c_undelay_data(data, k, v) curpath = path + (k,) _t_prefix = f'{k} --> ' if isinstance(v, TreeStorage):