iker-python-common 1.0.63__tar.gz → 1.0.64__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/PKG-INFO +1 -1
- iker_python_common-1.0.63/src/iker/common/utils/sequtils.py → iker_python_common-1.0.64/src/iker/common/utils/iterutils.py +168 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/randutils.py +1 -1
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/shutils.py +1 -1
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/PKG-INFO +1 -1
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/SOURCES.txt +2 -2
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/argutils_test.py +1 -1
- iker_python_common-1.0.63/test/iker_tests/common/utils/sequtils_test.py → iker_python_common-1.0.64/test/iker_tests/common/utils/iterutils_test.py +696 -6
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/span_test.py +1 -1
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/.editorconfig +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/.github/workflows/pr.yml +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/.github/workflows/push.yml +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/.gitignore +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/MANIFEST.in +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/README.md +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/VERSION +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/pyproject.toml +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/config/config.cfg +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/csv/data.csv +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/csv/data.tsv +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.baz/file.bar.baz +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.baz/file.foo.bar +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.baz/file.foo.baz +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/file.bar +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/file.baz +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/file.foo +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/setup.cfg +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/setup.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/__init__.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/__init__.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/argutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/config.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/csv.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/dbutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/dtutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/funcutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/jsonutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/logger.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/numutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/retry.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/span.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/strutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/testutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker/common/utils/typeutils.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/dependency_links.txt +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/not-zip-safe +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/requires.txt +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/top_level.txt +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/__init__.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/config_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/csv_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/dbutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/dtutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/funcutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/jsonutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/logger_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/numutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/randutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/retry_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/shutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/strutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/testutils_test.py +0 -0
- {iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/typeutils_test.py +0 -0
|
@@ -27,6 +27,15 @@ __all__ = [
|
|
|
27
27
|
"chunk_between",
|
|
28
28
|
"chunk_with_key",
|
|
29
29
|
"merge_chunks",
|
|
30
|
+
"dicttree",
|
|
31
|
+
"dicttree_value",
|
|
32
|
+
"dicttree_subtree",
|
|
33
|
+
"dicttree_children",
|
|
34
|
+
"dicttree_lineage",
|
|
35
|
+
"dicttree_make",
|
|
36
|
+
"dicttree_add",
|
|
37
|
+
"dicttree_remove",
|
|
38
|
+
"dicttree_purge",
|
|
30
39
|
"Seq",
|
|
31
40
|
"seq",
|
|
32
41
|
]
|
|
@@ -539,6 +548,165 @@ def merge_chunks[T](
|
|
|
539
548
|
chunk_between(chunks, lambda a, b: not merge_func(a, b)))
|
|
540
549
|
|
|
541
550
|
|
|
551
|
+
# Dicttree, a tree structure implemented using nested dictionaries,
|
|
552
|
+
# where each node can have an optional value and child nodes.
|
|
553
|
+
type dicttree[K, V] = dict[K, tuple[V | None, dicttree[K, V]]]
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
def dicttree_value[K, V](tree: dicttree[K, V], path: list[K]) -> V | None:
|
|
557
|
+
"""
|
|
558
|
+
Gets the value stored at the specified path in the dicttree.
|
|
559
|
+
|
|
560
|
+
:param tree: the dicttree to retrieve the value from.
|
|
561
|
+
:param path: the list of keys representing the path to the desired value.
|
|
562
|
+
:return: the value at the specified path, or ``None`` if the path does not exist.
|
|
563
|
+
"""
|
|
564
|
+
value = None
|
|
565
|
+
for key in path:
|
|
566
|
+
if key not in tree:
|
|
567
|
+
return None
|
|
568
|
+
value, tree = tree[key]
|
|
569
|
+
return value
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
def dicttree_subtree[K, V](tree: dicttree[K, V], path: list[K]) -> dicttree[K, V] | None:
|
|
573
|
+
"""
|
|
574
|
+
Gets the subtree located at the specified path in the dicttree.
|
|
575
|
+
|
|
576
|
+
:param tree: the dicttree to retrieve the subtree from.
|
|
577
|
+
:param path: the list of keys representing the path to the desired subtree.
|
|
578
|
+
:return: the subtree at the specified path, or ``None`` if the path does not exist.
|
|
579
|
+
"""
|
|
580
|
+
for key in path:
|
|
581
|
+
if key not in tree:
|
|
582
|
+
return None
|
|
583
|
+
_, tree = tree[key]
|
|
584
|
+
return tree
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def dicttree_children[K, V](tree: dicttree[K, V], *, leaves_only: bool = False) -> Generator[V, None, None]:
|
|
588
|
+
"""
|
|
589
|
+
Yields all values in the dicttree. If ``leaves_only`` is ``True``, only yields values at leaf nodes.
|
|
590
|
+
|
|
591
|
+
:param tree: the dicttree to traverse.
|
|
592
|
+
:param leaves_only: whether to yield only values at leaf nodes.
|
|
593
|
+
:return: a generator yielding all values in the dicttree.
|
|
594
|
+
"""
|
|
595
|
+
for value, subtree in tree.values():
|
|
596
|
+
if value is not None and (not leaves_only or not subtree):
|
|
597
|
+
yield value
|
|
598
|
+
yield from dicttree_children(subtree, leaves_only=leaves_only)
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
def dicttree_lineage[K, V](tree: dicttree[K, V], path: list[K]) -> Generator[V, None, None]:
|
|
602
|
+
"""
|
|
603
|
+
Yields all values along the specified path in the dicttree.
|
|
604
|
+
|
|
605
|
+
:param tree: the dicttree to traverse.
|
|
606
|
+
:param path: the list of keys representing the path to follow.
|
|
607
|
+
:return: a generator yielding all values along the specified path.
|
|
608
|
+
"""
|
|
609
|
+
for key in path:
|
|
610
|
+
if key not in tree:
|
|
611
|
+
return
|
|
612
|
+
value, tree = tree[key]
|
|
613
|
+
if value is not None:
|
|
614
|
+
yield value
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
def dicttree_make[K, V](tree: dicttree[K, V], path: list[K]) -> dicttree[K, V]:
|
|
618
|
+
"""
|
|
619
|
+
Ensures that the specified path exists in the dicttree, creating any missing nodes along the way.
|
|
620
|
+
|
|
621
|
+
:param tree: the dicttree to modify.
|
|
622
|
+
:param path: the list of keys representing the path to create.
|
|
623
|
+
:return: the subtree at the end of the created path.
|
|
624
|
+
"""
|
|
625
|
+
for key in path:
|
|
626
|
+
tree.setdefault(key, (None, {}))
|
|
627
|
+
_, tree = tree[key]
|
|
628
|
+
return tree
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
def dicttree_add[K, V](
|
|
632
|
+
tree: dicttree[K, V],
|
|
633
|
+
path: list[K],
|
|
634
|
+
value: V,
|
|
635
|
+
*,
|
|
636
|
+
create_prefix: bool = True,
|
|
637
|
+
overwrite: bool = False,
|
|
638
|
+
) -> dicttree[K, V]:
|
|
639
|
+
"""
|
|
640
|
+
Adds a value at the specified path in the dicttree. If ``create_prefix`` is ``True``, any missing nodes along the
|
|
641
|
+
path are created. If ``overwrite`` is ``False``, raises an error if the path already exists.
|
|
642
|
+
|
|
643
|
+
:param tree: the dicttree to modify.
|
|
644
|
+
:param path: the list of keys representing the path to add the value to.
|
|
645
|
+
:param value: the value to add at the specified path.
|
|
646
|
+
:param create_prefix: whether to create missing nodes along the path.
|
|
647
|
+
:param overwrite: whether to overwrite an existing value at the path.
|
|
648
|
+
:return: the modified dicttree.
|
|
649
|
+
"""
|
|
650
|
+
if len(path) == 0:
|
|
651
|
+
raise ValueError("path cannot be empty")
|
|
652
|
+
*prefix, key = path
|
|
653
|
+
if create_prefix:
|
|
654
|
+
subtree = dicttree_make(tree, prefix)
|
|
655
|
+
else:
|
|
656
|
+
subtree = dicttree_subtree(tree, prefix)
|
|
657
|
+
if subtree is None:
|
|
658
|
+
raise ValueError("prefix path does not exist in dicttree")
|
|
659
|
+
if not overwrite and dicttree_value(subtree, [key]) is not None:
|
|
660
|
+
raise ValueError("path already exists in dicttree")
|
|
661
|
+
else:
|
|
662
|
+
subtree[key] = (value, dicttree_subtree(subtree, [key]) or {})
|
|
663
|
+
return tree
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
def dicttree_remove[K, V](
|
|
667
|
+
tree: dicttree[K, V],
|
|
668
|
+
path: list[K],
|
|
669
|
+
*,
|
|
670
|
+
recursive: bool = False,
|
|
671
|
+
) -> dicttree[K, V]:
|
|
672
|
+
"""
|
|
673
|
+
Removes the value at the specified path in the dicttree. If ``recursive`` is ``True``, removes the entire subtree
|
|
674
|
+
at that path; otherwise, only removes the value, leaving any child nodes intact.
|
|
675
|
+
|
|
676
|
+
:param tree: the dicttree to modify.
|
|
677
|
+
:param path: the list of keys representing the path to remove the value from.
|
|
678
|
+
:param recursive: whether to remove the entire subtree at the path.
|
|
679
|
+
:return: the modified dicttree.
|
|
680
|
+
"""
|
|
681
|
+
if len(path) == 0:
|
|
682
|
+
raise ValueError("path cannot be empty")
|
|
683
|
+
*prefix, key = path
|
|
684
|
+
subtree = dicttree_subtree(tree, prefix)
|
|
685
|
+
if subtree is None:
|
|
686
|
+
raise ValueError("prefix path does not exist in dicttree")
|
|
687
|
+
if dicttree_value(subtree, [key]) is None:
|
|
688
|
+
raise ValueError("path does not exist in dicttree")
|
|
689
|
+
else:
|
|
690
|
+
subtree[key] = (None, {} if recursive else dicttree_subtree(subtree, [key]) or {})
|
|
691
|
+
return tree
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
def dicttree_purge[K, V](tree: dicttree[K, V]) -> dicttree[K, V]:
|
|
695
|
+
"""
|
|
696
|
+
Recursively removes all nodes in the dicttree that have no value and no children.
|
|
697
|
+
|
|
698
|
+
:param tree: the dicttree to purge.
|
|
699
|
+
:return: the purged dicttree.
|
|
700
|
+
"""
|
|
701
|
+
for key in list(tree.keys()):
|
|
702
|
+
value, subtree = tree[key]
|
|
703
|
+
dicttree_purge(subtree)
|
|
704
|
+
if subtree or value is not None:
|
|
705
|
+
continue
|
|
706
|
+
del tree[key]
|
|
707
|
+
return tree
|
|
708
|
+
|
|
709
|
+
|
|
542
710
|
class Seq[T](Sequence[T], Sized):
|
|
543
711
|
def __init__(self, data: Iterable[T]):
|
|
544
712
|
if isinstance(data, Seq):
|
|
@@ -8,8 +8,8 @@ from typing import overload
|
|
|
8
8
|
|
|
9
9
|
from iker.common.utils.dtutils import dt_utc_max, dt_utc_min
|
|
10
10
|
from iker.common.utils.funcutils import memorized, singleton
|
|
11
|
+
from iker.common.utils.iterutils import head_or_none
|
|
11
12
|
from iker.common.utils.jsonutils import JsonType
|
|
12
|
-
from iker.common.utils.sequtils import head_or_none
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
15
15
|
"max_int",
|
|
@@ -4,7 +4,7 @@ import shutil
|
|
|
4
4
|
from typing import Protocol
|
|
5
5
|
|
|
6
6
|
from iker.common.utils import logger
|
|
7
|
-
from iker.common.utils.
|
|
7
|
+
from iker.common.utils.iterutils import last, last_or_none, tail_iter
|
|
8
8
|
from iker.common.utils.strutils import is_empty
|
|
9
9
|
|
|
10
10
|
__all__ = [
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/SOURCES.txt
RENAMED
|
@@ -28,12 +28,12 @@ src/iker/common/utils/csv.py
|
|
|
28
28
|
src/iker/common/utils/dbutils.py
|
|
29
29
|
src/iker/common/utils/dtutils.py
|
|
30
30
|
src/iker/common/utils/funcutils.py
|
|
31
|
+
src/iker/common/utils/iterutils.py
|
|
31
32
|
src/iker/common/utils/jsonutils.py
|
|
32
33
|
src/iker/common/utils/logger.py
|
|
33
34
|
src/iker/common/utils/numutils.py
|
|
34
35
|
src/iker/common/utils/randutils.py
|
|
35
36
|
src/iker/common/utils/retry.py
|
|
36
|
-
src/iker/common/utils/sequtils.py
|
|
37
37
|
src/iker/common/utils/shutils.py
|
|
38
38
|
src/iker/common/utils/span.py
|
|
39
39
|
src/iker/common/utils/strutils.py
|
|
@@ -53,12 +53,12 @@ test/iker_tests/common/utils/csv_test.py
|
|
|
53
53
|
test/iker_tests/common/utils/dbutils_test.py
|
|
54
54
|
test/iker_tests/common/utils/dtutils_test.py
|
|
55
55
|
test/iker_tests/common/utils/funcutils_test.py
|
|
56
|
+
test/iker_tests/common/utils/iterutils_test.py
|
|
56
57
|
test/iker_tests/common/utils/jsonutils_test.py
|
|
57
58
|
test/iker_tests/common/utils/logger_test.py
|
|
58
59
|
test/iker_tests/common/utils/numutils_test.py
|
|
59
60
|
test/iker_tests/common/utils/randutils_test.py
|
|
60
61
|
test/iker_tests/common/utils/retry_test.py
|
|
61
|
-
test/iker_tests/common/utils/sequtils_test.py
|
|
62
62
|
test/iker_tests/common/utils/shutils_test.py
|
|
63
63
|
test/iker_tests/common/utils/span_test.py
|
|
64
64
|
test/iker_tests/common/utils/strutils_test.py
|
|
@@ -5,12 +5,16 @@ from typing import Self
|
|
|
5
5
|
|
|
6
6
|
import ddt
|
|
7
7
|
|
|
8
|
-
from iker.common.utils.
|
|
9
|
-
from iker.common.utils.
|
|
10
|
-
from iker.common.utils.
|
|
11
|
-
from iker.common.utils.
|
|
12
|
-
from iker.common.utils.
|
|
13
|
-
from iker.common.utils.
|
|
8
|
+
from iker.common.utils.iterutils import Seq
|
|
9
|
+
from iker.common.utils.iterutils import batched, deduped, flatten, grouped
|
|
10
|
+
from iker.common.utils.iterutils import chunk, chunk_between, chunk_with_key, merge_chunks
|
|
11
|
+
from iker.common.utils.iterutils import dicttree
|
|
12
|
+
from iker.common.utils.iterutils import dicttree_add, dicttree_purge, dicttree_remove
|
|
13
|
+
from iker.common.utils.iterutils import dicttree_children, dicttree_lineage
|
|
14
|
+
from iker.common.utils.iterutils import dicttree_subtree, dicttree_value
|
|
15
|
+
from iker.common.utils.iterutils import head, last
|
|
16
|
+
from iker.common.utils.iterutils import init, init_iter, tail, tail_iter
|
|
17
|
+
from iker.common.utils.iterutils import seq
|
|
14
18
|
|
|
15
19
|
|
|
16
20
|
@ddt.ddt
|
|
@@ -937,6 +941,692 @@ class SeqUtilsTest(unittest.TestCase):
|
|
|
937
941
|
self.assertEqual(expect, list(merge_chunks(data, merge_func=merge_func, drop_exclusive_end=True)))
|
|
938
942
|
|
|
939
943
|
|
|
944
|
+
@ddt.ddt
|
|
945
|
+
class DicttreeTest(unittest.TestCase):
|
|
946
|
+
data_dicttree_value = [
|
|
947
|
+
({}, [[]], [None]),
|
|
948
|
+
(
|
|
949
|
+
{
|
|
950
|
+
"a": (1, {}),
|
|
951
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
952
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
953
|
+
},
|
|
954
|
+
[
|
|
955
|
+
["a"],
|
|
956
|
+
["b"],
|
|
957
|
+
["b", "c"],
|
|
958
|
+
["b", "d"],
|
|
959
|
+
["b", "d", "e"],
|
|
960
|
+
["b", "d", "f"],
|
|
961
|
+
["g"],
|
|
962
|
+
["g", "h"],
|
|
963
|
+
["g", "i"],
|
|
964
|
+
],
|
|
965
|
+
[1, 2, 3, 4, 5, 6, 7, 8, 9],
|
|
966
|
+
),
|
|
967
|
+
(
|
|
968
|
+
{
|
|
969
|
+
"a": (1, {}),
|
|
970
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
971
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
972
|
+
},
|
|
973
|
+
[
|
|
974
|
+
["b", "c", "d"],
|
|
975
|
+
["b", "c", "d", "e"],
|
|
976
|
+
["b", "c", "d", "e", "f"],
|
|
977
|
+
["c"],
|
|
978
|
+
["d"],
|
|
979
|
+
["e"],
|
|
980
|
+
["f"],
|
|
981
|
+
["g", "h", "i"],
|
|
982
|
+
["h"],
|
|
983
|
+
["i"],
|
|
984
|
+
],
|
|
985
|
+
[None, None, None, None, None, None, None, None, None, None],
|
|
986
|
+
),
|
|
987
|
+
(
|
|
988
|
+
{
|
|
989
|
+
"a": (1, {}),
|
|
990
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
991
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
992
|
+
},
|
|
993
|
+
[
|
|
994
|
+
["a"],
|
|
995
|
+
["b"],
|
|
996
|
+
["b", "c"],
|
|
997
|
+
["b", "d"],
|
|
998
|
+
["b", "d", "e"],
|
|
999
|
+
["b", "d", "f"],
|
|
1000
|
+
["g"],
|
|
1001
|
+
["g", "h"],
|
|
1002
|
+
["g", "i"],
|
|
1003
|
+
],
|
|
1004
|
+
[1, 2, None, 4, None, 6, None, 8, None],
|
|
1005
|
+
),
|
|
1006
|
+
(
|
|
1007
|
+
{
|
|
1008
|
+
"a": (1, {}),
|
|
1009
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1010
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1011
|
+
},
|
|
1012
|
+
[
|
|
1013
|
+
["b", "c", "d"],
|
|
1014
|
+
["b", "c", "d", "e"],
|
|
1015
|
+
["b", "c", "d", "e", "f"],
|
|
1016
|
+
["c"],
|
|
1017
|
+
["d"],
|
|
1018
|
+
["e"],
|
|
1019
|
+
["f"],
|
|
1020
|
+
["g", "h", "i"],
|
|
1021
|
+
["h"],
|
|
1022
|
+
["i"],
|
|
1023
|
+
],
|
|
1024
|
+
[None, None, None, None, None, None, None, None, None, None],
|
|
1025
|
+
),
|
|
1026
|
+
]
|
|
1027
|
+
|
|
1028
|
+
@ddt.idata(data_dicttree_value)
|
|
1029
|
+
@ddt.unpack
|
|
1030
|
+
def test_dicttree_value(self, tree: dicttree[str, int], paths, expects):
|
|
1031
|
+
for expect, path in zip(expects, paths):
|
|
1032
|
+
self.assertEqual(expect, dicttree_value(tree, path))
|
|
1033
|
+
|
|
1034
|
+
data_dicttree_subtree = [
|
|
1035
|
+
({}, [[]], [{}]),
|
|
1036
|
+
(
|
|
1037
|
+
{
|
|
1038
|
+
"a": (1, {}),
|
|
1039
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1040
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1041
|
+
},
|
|
1042
|
+
[
|
|
1043
|
+
[],
|
|
1044
|
+
["a"],
|
|
1045
|
+
["b"],
|
|
1046
|
+
["b", "c"],
|
|
1047
|
+
["b", "d"],
|
|
1048
|
+
["b", "d", "e"],
|
|
1049
|
+
["b", "d", "f"],
|
|
1050
|
+
["g"],
|
|
1051
|
+
["g", "h"],
|
|
1052
|
+
["g", "i"],
|
|
1053
|
+
],
|
|
1054
|
+
[
|
|
1055
|
+
{
|
|
1056
|
+
"a": (1, {}),
|
|
1057
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1058
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1059
|
+
},
|
|
1060
|
+
{},
|
|
1061
|
+
{"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})},
|
|
1062
|
+
{},
|
|
1063
|
+
{"e": (5, {}), "f": (6, {})},
|
|
1064
|
+
{},
|
|
1065
|
+
{},
|
|
1066
|
+
{"h": (8, {}), "i": (9, {})},
|
|
1067
|
+
{},
|
|
1068
|
+
{},
|
|
1069
|
+
],
|
|
1070
|
+
),
|
|
1071
|
+
(
|
|
1072
|
+
{
|
|
1073
|
+
"a": (1, {}),
|
|
1074
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1075
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1076
|
+
},
|
|
1077
|
+
[
|
|
1078
|
+
["b", "c", "d"],
|
|
1079
|
+
["b", "c", "d", "e"],
|
|
1080
|
+
["b", "c", "d", "e", "f"],
|
|
1081
|
+
["c"],
|
|
1082
|
+
["d"],
|
|
1083
|
+
["e"],
|
|
1084
|
+
["f"],
|
|
1085
|
+
["g", "h", "i"],
|
|
1086
|
+
["h"],
|
|
1087
|
+
["i"],
|
|
1088
|
+
],
|
|
1089
|
+
[None, None, None, None, None, None, None, None, None, None],
|
|
1090
|
+
),
|
|
1091
|
+
(
|
|
1092
|
+
{
|
|
1093
|
+
"a": (1, {}),
|
|
1094
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1095
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1096
|
+
},
|
|
1097
|
+
[
|
|
1098
|
+
[],
|
|
1099
|
+
["a"],
|
|
1100
|
+
["b"],
|
|
1101
|
+
["b", "c"],
|
|
1102
|
+
["b", "d"],
|
|
1103
|
+
["b", "d", "e"],
|
|
1104
|
+
["b", "d", "f"],
|
|
1105
|
+
["g"],
|
|
1106
|
+
["g", "h"],
|
|
1107
|
+
["g", "i"],
|
|
1108
|
+
],
|
|
1109
|
+
[
|
|
1110
|
+
{
|
|
1111
|
+
"a": (1, {}),
|
|
1112
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1113
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1114
|
+
},
|
|
1115
|
+
{},
|
|
1116
|
+
{"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})},
|
|
1117
|
+
{},
|
|
1118
|
+
{"e": (None, {}), "f": (6, {})},
|
|
1119
|
+
{},
|
|
1120
|
+
{},
|
|
1121
|
+
{"h": (8, {}), "i": (None, {})},
|
|
1122
|
+
{},
|
|
1123
|
+
{},
|
|
1124
|
+
],
|
|
1125
|
+
),
|
|
1126
|
+
(
|
|
1127
|
+
{
|
|
1128
|
+
"a": (1, {}),
|
|
1129
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1130
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1131
|
+
},
|
|
1132
|
+
[
|
|
1133
|
+
["b", "c", "d"],
|
|
1134
|
+
["b", "c", "d", "e"],
|
|
1135
|
+
["b", "c", "d", "e", "f"],
|
|
1136
|
+
["c"],
|
|
1137
|
+
["d"],
|
|
1138
|
+
["e"],
|
|
1139
|
+
["f"],
|
|
1140
|
+
["g", "h", "i"],
|
|
1141
|
+
["h"],
|
|
1142
|
+
["i"],
|
|
1143
|
+
],
|
|
1144
|
+
[None, None, None, None, None, None, None, None, None, None],
|
|
1145
|
+
),
|
|
1146
|
+
]
|
|
1147
|
+
|
|
1148
|
+
@ddt.idata(data_dicttree_subtree)
|
|
1149
|
+
@ddt.unpack
|
|
1150
|
+
def test_dicttree_subtree(self, tree: dicttree[str, int], paths, expects):
|
|
1151
|
+
for expect, path in zip(expects, paths):
|
|
1152
|
+
self.assertEqual(expect, dicttree_subtree(tree, path))
|
|
1153
|
+
|
|
1154
|
+
data_dicttree_children = [
|
|
1155
|
+
({}, [[]], False, [set()]),
|
|
1156
|
+
(
|
|
1157
|
+
{
|
|
1158
|
+
"a": (1, {}),
|
|
1159
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1160
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1161
|
+
},
|
|
1162
|
+
[
|
|
1163
|
+
[],
|
|
1164
|
+
["a"],
|
|
1165
|
+
["b"],
|
|
1166
|
+
["b", "c"],
|
|
1167
|
+
["b", "d"],
|
|
1168
|
+
["b", "d", "e"],
|
|
1169
|
+
["b", "d", "f"],
|
|
1170
|
+
["g"],
|
|
1171
|
+
["g", "h"],
|
|
1172
|
+
["g", "i"],
|
|
1173
|
+
],
|
|
1174
|
+
False,
|
|
1175
|
+
[{1, 2, 3, 4, 5, 6, 7, 8, 9}, set(), {3, 4, 5, 6}, set(), {5, 6}, set(), set(), {8, 9}, set(), set()],
|
|
1176
|
+
),
|
|
1177
|
+
(
|
|
1178
|
+
{
|
|
1179
|
+
"a": (1, {}),
|
|
1180
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1181
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1182
|
+
},
|
|
1183
|
+
[
|
|
1184
|
+
["b", "c", "d"],
|
|
1185
|
+
["b", "c", "d", "e"],
|
|
1186
|
+
["b", "c", "d", "e", "f"],
|
|
1187
|
+
["c"],
|
|
1188
|
+
["d"],
|
|
1189
|
+
["e"],
|
|
1190
|
+
["f"],
|
|
1191
|
+
["g", "h", "i"],
|
|
1192
|
+
["h"],
|
|
1193
|
+
["i"],
|
|
1194
|
+
],
|
|
1195
|
+
False,
|
|
1196
|
+
[set(), set(), set(), set(), set(), set(), set(), set(), set(), set()],
|
|
1197
|
+
),
|
|
1198
|
+
(
|
|
1199
|
+
{
|
|
1200
|
+
"a": (1, {}),
|
|
1201
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1202
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1203
|
+
},
|
|
1204
|
+
[
|
|
1205
|
+
[],
|
|
1206
|
+
["a"],
|
|
1207
|
+
["b"],
|
|
1208
|
+
["b", "c"],
|
|
1209
|
+
["b", "d"],
|
|
1210
|
+
["b", "d", "e"],
|
|
1211
|
+
["b", "d", "f"],
|
|
1212
|
+
["g"],
|
|
1213
|
+
["g", "h"],
|
|
1214
|
+
["g", "i"],
|
|
1215
|
+
],
|
|
1216
|
+
False,
|
|
1217
|
+
[{1, 2, 4, 6, 8}, set(), {4, 6}, set(), {6}, set(), set(), {8}, set(), set()],
|
|
1218
|
+
),
|
|
1219
|
+
(
|
|
1220
|
+
{
|
|
1221
|
+
"a": (1, {}),
|
|
1222
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1223
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1224
|
+
},
|
|
1225
|
+
[
|
|
1226
|
+
["b", "c", "d"],
|
|
1227
|
+
["b", "c", "d", "e"],
|
|
1228
|
+
["b", "c", "d", "e", "f"],
|
|
1229
|
+
["c"],
|
|
1230
|
+
["d"],
|
|
1231
|
+
["e"],
|
|
1232
|
+
["f"],
|
|
1233
|
+
["g", "h", "i"],
|
|
1234
|
+
["h"],
|
|
1235
|
+
["i"],
|
|
1236
|
+
],
|
|
1237
|
+
False,
|
|
1238
|
+
[set(), set(), set(), set(), set(), set(), set(), set(), set(), set()],
|
|
1239
|
+
),
|
|
1240
|
+
(
|
|
1241
|
+
{
|
|
1242
|
+
"a": (1, {}),
|
|
1243
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1244
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1245
|
+
},
|
|
1246
|
+
[
|
|
1247
|
+
[],
|
|
1248
|
+
["a"],
|
|
1249
|
+
["b"],
|
|
1250
|
+
["b", "c"],
|
|
1251
|
+
["b", "d"],
|
|
1252
|
+
["b", "d", "e"],
|
|
1253
|
+
["b", "d", "f"],
|
|
1254
|
+
["g"],
|
|
1255
|
+
["g", "h"],
|
|
1256
|
+
["g", "i"],
|
|
1257
|
+
],
|
|
1258
|
+
True,
|
|
1259
|
+
[{1, 3, 5, 6, 8, 9}, set(), {3, 5, 6}, set(), {5, 6}, set(), set(), {8, 9}, set(), set()],
|
|
1260
|
+
),
|
|
1261
|
+
(
|
|
1262
|
+
{
|
|
1263
|
+
"a": (1, {}),
|
|
1264
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1265
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1266
|
+
},
|
|
1267
|
+
[
|
|
1268
|
+
["b", "c", "d"],
|
|
1269
|
+
["b", "c", "d", "e"],
|
|
1270
|
+
["b", "c", "d", "e", "f"],
|
|
1271
|
+
["c"],
|
|
1272
|
+
["d"],
|
|
1273
|
+
["e"],
|
|
1274
|
+
["f"],
|
|
1275
|
+
["g", "h", "i"],
|
|
1276
|
+
["h"],
|
|
1277
|
+
["i"],
|
|
1278
|
+
],
|
|
1279
|
+
True,
|
|
1280
|
+
[set(), set(), set(), set(), set(), set(), set(), set(), set(), set()],
|
|
1281
|
+
),
|
|
1282
|
+
(
|
|
1283
|
+
{
|
|
1284
|
+
"a": (1, {}),
|
|
1285
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1286
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1287
|
+
},
|
|
1288
|
+
[
|
|
1289
|
+
[],
|
|
1290
|
+
["a"],
|
|
1291
|
+
["b"],
|
|
1292
|
+
["b", "c"],
|
|
1293
|
+
["b", "d"],
|
|
1294
|
+
["b", "d", "e"],
|
|
1295
|
+
["b", "d", "f"],
|
|
1296
|
+
["g"],
|
|
1297
|
+
["g", "h"],
|
|
1298
|
+
["g", "i"],
|
|
1299
|
+
],
|
|
1300
|
+
True,
|
|
1301
|
+
[{1, 6, 8}, set(), {6}, set(), {6}, set(), set(), {8}, set(), set()],
|
|
1302
|
+
),
|
|
1303
|
+
(
|
|
1304
|
+
{
|
|
1305
|
+
"a": (1, {}),
|
|
1306
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1307
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1308
|
+
},
|
|
1309
|
+
[
|
|
1310
|
+
["b", "c", "d"],
|
|
1311
|
+
["b", "c", "d", "e"],
|
|
1312
|
+
["b", "c", "d", "e", "f"],
|
|
1313
|
+
["c"],
|
|
1314
|
+
["d"],
|
|
1315
|
+
["e"],
|
|
1316
|
+
["f"],
|
|
1317
|
+
["g", "h", "i"],
|
|
1318
|
+
["h"],
|
|
1319
|
+
["i"],
|
|
1320
|
+
],
|
|
1321
|
+
True,
|
|
1322
|
+
[set(), set(), set(), set(), set(), set(), set(), set(), set(), set()],
|
|
1323
|
+
),
|
|
1324
|
+
]
|
|
1325
|
+
|
|
1326
|
+
@ddt.idata(data_dicttree_children)
|
|
1327
|
+
@ddt.unpack
|
|
1328
|
+
def test_dicttree_children(self, tree: dicttree[str, int], paths, leaves_only, expects):
|
|
1329
|
+
for expect, path in zip(expects, paths):
|
|
1330
|
+
subtree = dicttree_subtree(tree, path)
|
|
1331
|
+
if subtree is None:
|
|
1332
|
+
self.assertEqual(expect, set())
|
|
1333
|
+
else:
|
|
1334
|
+
self.assertEqual(expect, set(dicttree_children(subtree, leaves_only=leaves_only)))
|
|
1335
|
+
|
|
1336
|
+
data_dicttree_lineage = [
|
|
1337
|
+
({}, [[]], [[]]),
|
|
1338
|
+
(
|
|
1339
|
+
{
|
|
1340
|
+
"a": (1, {}),
|
|
1341
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1342
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1343
|
+
},
|
|
1344
|
+
[
|
|
1345
|
+
[],
|
|
1346
|
+
["a"],
|
|
1347
|
+
["b"],
|
|
1348
|
+
["b", "c"],
|
|
1349
|
+
["b", "d"],
|
|
1350
|
+
["b", "d", "e"],
|
|
1351
|
+
["b", "d", "f"],
|
|
1352
|
+
["g"],
|
|
1353
|
+
["g", "h"],
|
|
1354
|
+
["g", "i"],
|
|
1355
|
+
],
|
|
1356
|
+
[[], [1], [2], [2, 3], [2, 4], [2, 4, 5], [2, 4, 6], [7], [7, 8], [7, 9]],
|
|
1357
|
+
),
|
|
1358
|
+
(
|
|
1359
|
+
{
|
|
1360
|
+
"a": (1, {}),
|
|
1361
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1362
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1363
|
+
},
|
|
1364
|
+
[
|
|
1365
|
+
["b", "c", "d"],
|
|
1366
|
+
["b", "c", "d", "e"],
|
|
1367
|
+
["b", "c", "d", "e", "f"],
|
|
1368
|
+
["c"],
|
|
1369
|
+
["d"],
|
|
1370
|
+
["e"],
|
|
1371
|
+
["f"],
|
|
1372
|
+
["g", "h", "i"],
|
|
1373
|
+
["h"],
|
|
1374
|
+
["i"],
|
|
1375
|
+
],
|
|
1376
|
+
[[2, 3], [2, 3], [2, 3], [], [], [], [], [7, 8], [], []],
|
|
1377
|
+
),
|
|
1378
|
+
(
|
|
1379
|
+
{
|
|
1380
|
+
"a": (1, {}),
|
|
1381
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1382
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1383
|
+
},
|
|
1384
|
+
[
|
|
1385
|
+
[],
|
|
1386
|
+
["a"],
|
|
1387
|
+
["b"],
|
|
1388
|
+
["b", "c"],
|
|
1389
|
+
["b", "d"],
|
|
1390
|
+
["b", "d", "e"],
|
|
1391
|
+
["b", "d", "f"],
|
|
1392
|
+
["g"],
|
|
1393
|
+
["g", "h"],
|
|
1394
|
+
["g", "i"],
|
|
1395
|
+
],
|
|
1396
|
+
[[], [1], [2], [2], [2, 4], [2, 4], [2, 4, 6], [], [8], []],
|
|
1397
|
+
),
|
|
1398
|
+
(
|
|
1399
|
+
{
|
|
1400
|
+
"a": (1, {}),
|
|
1401
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1402
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1403
|
+
},
|
|
1404
|
+
[
|
|
1405
|
+
["b", "c", "d"],
|
|
1406
|
+
["b", "c", "d", "e"],
|
|
1407
|
+
["b", "c", "d", "e", "f"],
|
|
1408
|
+
["c"],
|
|
1409
|
+
["d"],
|
|
1410
|
+
["e"],
|
|
1411
|
+
["f"],
|
|
1412
|
+
["g", "h", "i"],
|
|
1413
|
+
["h"],
|
|
1414
|
+
["i"],
|
|
1415
|
+
],
|
|
1416
|
+
[[2], [2], [2], [], [], [], [], [8], [], []],
|
|
1417
|
+
),
|
|
1418
|
+
]
|
|
1419
|
+
|
|
1420
|
+
@ddt.idata(data_dicttree_lineage)
|
|
1421
|
+
@ddt.unpack
|
|
1422
|
+
def test_dicttree_lineage(self, tree: dicttree[str, int], paths, expects):
|
|
1423
|
+
for expect, path in zip(expects, paths):
|
|
1424
|
+
self.assertEqual(expect, list(dicttree_lineage(tree, path)))
|
|
1425
|
+
|
|
1426
|
+
data_dicttree_purge = [
|
|
1427
|
+
({}, {}),
|
|
1428
|
+
({"a": (1, {})}, {"a": (1, {})}),
|
|
1429
|
+
({"a": (None, {})}, {}),
|
|
1430
|
+
(
|
|
1431
|
+
{
|
|
1432
|
+
"a": (1, {}),
|
|
1433
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1434
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1435
|
+
},
|
|
1436
|
+
{
|
|
1437
|
+
"a": (1, {}),
|
|
1438
|
+
"b": (2, {"c": (3, {}), "d": (4, {"e": (5, {}), "f": (6, {})})}),
|
|
1439
|
+
"g": (7, {"h": (8, {}), "i": (9, {})}),
|
|
1440
|
+
},
|
|
1441
|
+
),
|
|
1442
|
+
(
|
|
1443
|
+
{
|
|
1444
|
+
"a": (1, {}),
|
|
1445
|
+
"b": (2, {"c": (None, {}), "d": (4, {"e": (None, {}), "f": (6, {})})}),
|
|
1446
|
+
"g": (None, {"h": (8, {}), "i": (None, {})}),
|
|
1447
|
+
},
|
|
1448
|
+
{
|
|
1449
|
+
"a": (1, {}),
|
|
1450
|
+
"b": (2, {"d": (4, {"f": (6, {})})}),
|
|
1451
|
+
"g": (None, {"h": (8, {})}),
|
|
1452
|
+
},
|
|
1453
|
+
),
|
|
1454
|
+
]
|
|
1455
|
+
|
|
1456
|
+
@ddt.idata(data_dicttree_purge)
|
|
1457
|
+
@ddt.unpack
|
|
1458
|
+
def test_dicttree_purge(self, tree: dicttree[str, int], expect):
|
|
1459
|
+
self.assertEqual(expect, dicttree_purge(tree))
|
|
1460
|
+
|
|
1461
|
+
data_dicttree_add = [
|
|
1462
|
+
({}, ["a"], 1, True, False, {"a": (1, {})}),
|
|
1463
|
+
({"a": (1, {})}, ["b"], 2, True, False, {"a": (1, {}), "b": (2, {})}),
|
|
1464
|
+
({"a": (1, {})}, ["a"], 2, True, True, {"a": (2, {})}),
|
|
1465
|
+
(
|
|
1466
|
+
{
|
|
1467
|
+
"a": (1, {}),
|
|
1468
|
+
"b": (2, {"c": (3, {})}),
|
|
1469
|
+
"d": (None, {"e": (5, {})}),
|
|
1470
|
+
},
|
|
1471
|
+
["b", "d", "e"],
|
|
1472
|
+
5,
|
|
1473
|
+
True,
|
|
1474
|
+
False,
|
|
1475
|
+
{
|
|
1476
|
+
"a": (1, {}),
|
|
1477
|
+
"b": (2, {"c": (3, {}), "d": (None, {"e": (5, {})})}),
|
|
1478
|
+
"d": (None, {"e": (5, {})}),
|
|
1479
|
+
},
|
|
1480
|
+
),
|
|
1481
|
+
(
|
|
1482
|
+
{
|
|
1483
|
+
"a": (1, {}),
|
|
1484
|
+
"b": (2, {"c": (3, {})}),
|
|
1485
|
+
"d": (None, {"e": (5, {})}),
|
|
1486
|
+
},
|
|
1487
|
+
["d"],
|
|
1488
|
+
4,
|
|
1489
|
+
True,
|
|
1490
|
+
False,
|
|
1491
|
+
{
|
|
1492
|
+
"a": (1, {}),
|
|
1493
|
+
"b": (2, {"c": (3, {})}),
|
|
1494
|
+
"d": (4, {"e": (5, {})}),
|
|
1495
|
+
},
|
|
1496
|
+
),
|
|
1497
|
+
(
|
|
1498
|
+
{
|
|
1499
|
+
"a": (1, {}),
|
|
1500
|
+
"b": (2, {"c": (3, {})}),
|
|
1501
|
+
"d": (None, {"e": (5, {})}),
|
|
1502
|
+
},
|
|
1503
|
+
["b"],
|
|
1504
|
+
22,
|
|
1505
|
+
True,
|
|
1506
|
+
True,
|
|
1507
|
+
{
|
|
1508
|
+
"a": (1, {}),
|
|
1509
|
+
"b": (22, {"c": (3, {})}),
|
|
1510
|
+
"d": (None, {"e": (5, {})}),
|
|
1511
|
+
},
|
|
1512
|
+
),
|
|
1513
|
+
(
|
|
1514
|
+
{
|
|
1515
|
+
"a": (1, {}),
|
|
1516
|
+
"b": (2, {"c": (3, {})}),
|
|
1517
|
+
"d": (None, {"e": (5, {})}),
|
|
1518
|
+
},
|
|
1519
|
+
["d", "e"],
|
|
1520
|
+
55,
|
|
1521
|
+
True,
|
|
1522
|
+
True,
|
|
1523
|
+
{
|
|
1524
|
+
"a": (1, {}),
|
|
1525
|
+
"b": (2, {"c": (3, {})}),
|
|
1526
|
+
"d": (None, {"e": (55, {})}),
|
|
1527
|
+
},
|
|
1528
|
+
),
|
|
1529
|
+
]
|
|
1530
|
+
|
|
1531
|
+
@ddt.idata(data_dicttree_add)
|
|
1532
|
+
@ddt.unpack
|
|
1533
|
+
def test_dicttree_add(self, tree: dicttree[str, int], path, value, create_prefix, overwrite, expect):
|
|
1534
|
+
self.assertEqual(expect, dicttree_add(tree, path, value, create_prefix=create_prefix, overwrite=overwrite))
|
|
1535
|
+
|
|
1536
|
+
data_dicttree_add__bad_cases = [
|
|
1537
|
+
({}, [], 0, True, False),
|
|
1538
|
+
({"a": (1, {})}, ["a"], 2, True, False),
|
|
1539
|
+
(
|
|
1540
|
+
{
|
|
1541
|
+
"a": (1, {}),
|
|
1542
|
+
"b": (2, {"c": (3, {})}),
|
|
1543
|
+
"d": (None, {"e": (5, {})}),
|
|
1544
|
+
},
|
|
1545
|
+
["b", "d", "e"],
|
|
1546
|
+
5,
|
|
1547
|
+
False,
|
|
1548
|
+
False,
|
|
1549
|
+
),
|
|
1550
|
+
]
|
|
1551
|
+
|
|
1552
|
+
@ddt.idata(data_dicttree_add__bad_cases)
|
|
1553
|
+
@ddt.unpack
|
|
1554
|
+
def test_dicttree_add__bad_cases(self, tree: dicttree[str, int], path, value, create_prefix, overwrite):
|
|
1555
|
+
with self.assertRaises(ValueError):
|
|
1556
|
+
dicttree_add(tree, path, value, create_prefix=create_prefix, overwrite=overwrite)
|
|
1557
|
+
|
|
1558
|
+
data_dicttree_remove = [
|
|
1559
|
+
({"a": (1, {})}, ["a"], False, {"a": (None, {})}),
|
|
1560
|
+
(
|
|
1561
|
+
{
|
|
1562
|
+
"a": (1, {}),
|
|
1563
|
+
"b": (2, {"c": (3, {})}),
|
|
1564
|
+
"d": (None, {"e": (5, {})}),
|
|
1565
|
+
},
|
|
1566
|
+
["b"],
|
|
1567
|
+
False,
|
|
1568
|
+
{
|
|
1569
|
+
"a": (1, {}),
|
|
1570
|
+
"b": (None, {"c": (3, {})}),
|
|
1571
|
+
"d": (None, {"e": (5, {})}),
|
|
1572
|
+
},
|
|
1573
|
+
),
|
|
1574
|
+
(
|
|
1575
|
+
{
|
|
1576
|
+
"a": (1, {}),
|
|
1577
|
+
"b": (2, {"c": (3, {})}),
|
|
1578
|
+
"d": (None, {"e": (5, {})}),
|
|
1579
|
+
},
|
|
1580
|
+
["b"],
|
|
1581
|
+
True,
|
|
1582
|
+
{
|
|
1583
|
+
"a": (1, {}),
|
|
1584
|
+
"b": (None, {}),
|
|
1585
|
+
"d": (None, {"e": (5, {})}),
|
|
1586
|
+
},
|
|
1587
|
+
),
|
|
1588
|
+
(
|
|
1589
|
+
{
|
|
1590
|
+
"a": (1, {}),
|
|
1591
|
+
"b": (2, {"c": (3, {})}),
|
|
1592
|
+
"d": (None, {"e": (5, {})}),
|
|
1593
|
+
},
|
|
1594
|
+
["b", "c"],
|
|
1595
|
+
False,
|
|
1596
|
+
{
|
|
1597
|
+
"a": (1, {}),
|
|
1598
|
+
"b": (2, {"c": (None, {})}),
|
|
1599
|
+
"d": (None, {"e": (5, {})}),
|
|
1600
|
+
},
|
|
1601
|
+
),
|
|
1602
|
+
]
|
|
1603
|
+
|
|
1604
|
+
@ddt.idata(data_dicttree_remove)
|
|
1605
|
+
@ddt.unpack
|
|
1606
|
+
def test_dicttree_remove(self, tree: dicttree[str, int], path, recursive, expect):
|
|
1607
|
+
self.assertEqual(expect, dicttree_remove(tree, path, recursive=recursive))
|
|
1608
|
+
|
|
1609
|
+
data_dicttree_remove__bad_cases = [
|
|
1610
|
+
({}, [], False),
|
|
1611
|
+
({"a": (1, {})}, ["b"], False),
|
|
1612
|
+
(
|
|
1613
|
+
{
|
|
1614
|
+
"a": (1, {}),
|
|
1615
|
+
"b": (2, {"c": (3, {})}),
|
|
1616
|
+
"d": (None, {"e": (5, {})}),
|
|
1617
|
+
},
|
|
1618
|
+
["e", "f"],
|
|
1619
|
+
False,
|
|
1620
|
+
),
|
|
1621
|
+
]
|
|
1622
|
+
|
|
1623
|
+
@ddt.idata(data_dicttree_remove__bad_cases)
|
|
1624
|
+
@ddt.unpack
|
|
1625
|
+
def test_dicttree_remove__bad_cases(self, tree: dicttree[str, int], path, recursive):
|
|
1626
|
+
with self.assertRaises(ValueError):
|
|
1627
|
+
dicttree_remove(tree, path, recursive=recursive)
|
|
1628
|
+
|
|
1629
|
+
|
|
940
1630
|
@dataclasses.dataclass(frozen=True, eq=True, order=True)
|
|
941
1631
|
class Naming(object):
|
|
942
1632
|
serial: int
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/span_test.py
RENAMED
|
@@ -3,7 +3,7 @@ import unittest
|
|
|
3
3
|
|
|
4
4
|
import ddt
|
|
5
5
|
|
|
6
|
-
from iker.common.utils.
|
|
6
|
+
from iker.common.utils.iterutils import last
|
|
7
7
|
from iker.common.utils.span import SpanRelation
|
|
8
8
|
from iker.common.utils.span import span_relation, spans_intersect, spans_subtract, spans_union
|
|
9
9
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/config/config.cfg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/file.bar
RENAMED
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/file.baz
RENAMED
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/resources/unittest/shutils/dir.foo/file.foo
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/src/iker_python_common.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/config_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/csv_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/dbutils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/dtutils_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/logger_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/retry_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.63 → iker_python_common-1.0.64}/test/iker_tests/common/utils/shutils_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|