Skip to content

Commit fd90bd2

Browse files
authored
Reorganise files, create common file (#397)
* feat: construct trees with nested_dict_key_to_tree * refactor: test clean up * feat: export trees with tree_to_nested_dict_key * feat: add docs * docs: update CHANGELOG * docs: enhance docstring * refactor: abstract out export tree logic * docs: update CHANGELOG * refactor: shift to common file * refactor: shift to common file * refactor: shift to common file
1 parent 70e2157 commit fd90bd2

File tree

9 files changed

+125
-114
lines changed

9 files changed

+125
-114
lines changed

bigtree/dag/construct.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Any, Collection, Dict, List, Mapping, Optional, Tuple, Type, TypeVar
44

55
from bigtree.node import dagnode
6-
from bigtree.utils import assertions, exceptions
6+
from bigtree.utils import assertions, common, exceptions
77

88
try:
99
import pandas as pd
@@ -201,14 +201,14 @@ def dataframe_to_dag(
201201
for row in data.reset_index(drop=True).to_dict(orient="index").values():
202202
child_name = row[child_col]
203203
parent_name = row[parent_col]
204-
node_attrs = assertions.filter_attributes(
204+
node_attrs = common.filter_attributes(
205205
row, omit_keys=["name", child_col, parent_col], omit_null_values=True
206206
)
207207
child_node = node_dict.get(child_name, node_type(child_name, **node_attrs))
208208
child_node.set_attrs(node_attrs)
209209
node_dict[child_name] = child_node
210210

211-
if not assertions.isnull(parent_name):
211+
if not common.isnull(parent_name):
212212
parent_node = node_dict.get(parent_name, node_type(parent_name))
213213
node_dict[parent_name] = parent_node
214214
child_node.parents = [parent_node]

bigtree/dag/export.py

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Any, Dict, List, Mapping, Optional, Tuple, TypeVar, Union
44

55
from bigtree.node import dagnode
6-
from bigtree.utils import assertions, exceptions, iterators
6+
from bigtree.utils import assertions, common, exceptions, iterators
77

88
try:
99
import pandas as pd
@@ -86,28 +86,18 @@ def dag_to_dict(
8686
for parent_node, child_node in iterators.dag_iterator(dag):
8787
if parent_node.is_root:
8888
data_parent: Dict[str, Any] = {}
89-
if all_attrs:
90-
data_parent.update(
91-
parent_node.describe(
92-
exclude_attributes=["name"], exclude_prefix="_"
93-
)
94-
)
95-
elif attr_dict:
96-
for k, v in attr_dict.items():
97-
data_parent[v] = parent_node.get_attr(k)
89+
data_parent = common.assemble_attributes(
90+
parent_node, attr_dict, all_attrs, data_parent
91+
)
9892
data_dict[parent_node.node_name] = data_parent
9993

10094
if data_dict.get(child_node.node_name):
10195
data_dict[child_node.node_name][parent_key].append(parent_node.node_name)
10296
else:
10397
data_child = {parent_key: [parent_node.node_name]}
104-
if all_attrs:
105-
data_child.update(
106-
child_node.describe(exclude_attributes=["name"], exclude_prefix="_")
107-
)
108-
elif attr_dict:
109-
for k, v in attr_dict.items():
110-
data_child[v] = child_node.get_attr(k)
98+
data_child = common.assemble_attributes(
99+
child_node, attr_dict, all_attrs, data_child
100+
)
111101
data_dict[child_node.node_name] = data_child
112102
return data_dict
113103

@@ -155,25 +145,15 @@ def dag_to_dataframe(
155145
for parent_node, child_node in iterators.dag_iterator(dag):
156146
if parent_node.is_root:
157147
data_parent = {name_col: parent_node.node_name, parent_col: None}
158-
if all_attrs:
159-
data_parent.update(
160-
parent_node.describe(
161-
exclude_attributes=["name"], exclude_prefix="_"
162-
)
163-
)
164-
elif attr_dict:
165-
for k, v in attr_dict.items():
166-
data_parent[v] = parent_node.get_attr(k)
148+
data_parent = common.assemble_attributes(
149+
parent_node, attr_dict, all_attrs, data_parent
150+
)
167151
data_list.append(data_parent)
168152

169153
data_child = {name_col: child_node.node_name, parent_col: parent_node.node_name}
170-
if all_attrs:
171-
data_child.update(
172-
child_node.describe(exclude_attributes=["name"], exclude_prefix="_")
173-
)
174-
elif attr_dict:
175-
for k, v in attr_dict.items():
176-
data_child[v] = child_node.get_attr(k)
154+
data_child = common.assemble_attributes(
155+
child_node, attr_dict, all_attrs, data_child
156+
)
177157
data_list.append(data_child)
178158
return pd.DataFrame(data_list).drop_duplicates().reset_index(drop=True)
179159

bigtree/tree/construct/dataframes.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from bigtree.node import node
66
from bigtree.tree.construct.dictionaries import add_dict_to_tree_by_name
77
from bigtree.tree.construct.strings import add_path_to_tree
8-
from bigtree.utils import assertions
8+
from bigtree.utils import assertions, common
99

1010
try:
1111
import pandas as pd
@@ -118,7 +118,7 @@ def add_dataframe_to_tree_by_path(
118118

119119
root_node = tree.root
120120
for row in data.to_dict(orient="index").values():
121-
node_attrs = assertions.filter_attributes(
121+
node_attrs = common.filter_attributes(
122122
row, omit_keys=["name", path_col], omit_null_values=True
123123
)
124124
add_path_to_tree(
@@ -191,7 +191,7 @@ def add_dataframe_to_tree_by_name(
191191
.to_dict(orient="index")
192192
)
193193
name_attrs = {
194-
k1: {k2: v2 for k2, v2 in v1.items() if not assertions.isnull(v2)}
194+
k1: {k2: v2 for k2, v2 in v1.items() if not common.isnull(v2)}
195195
for k1, v1 in name_attrs.items()
196196
}
197197

@@ -283,7 +283,7 @@ def add_polars_to_tree_by_path(
283283

284284
root_node = tree.root
285285
for row_kwargs in data.to_dicts():
286-
node_attrs = assertions.filter_attributes(
286+
node_attrs = common.filter_attributes(
287287
row_kwargs, omit_keys=["name", path_col], omit_null_values=True
288288
)
289289
add_path_to_tree(
@@ -354,7 +354,7 @@ def add_polars_to_tree_by_name(
354354
.rows_by_key(key=name_col, named=True)
355355
)
356356
name_attrs = {
357-
k1: {k2: v2 for k2, v2 in v1[0].items() if not assertions.isnull(v2)}
357+
k1: {k2: v2 for k2, v2 in v1[0].items() if not common.isnull(v2)}
358358
for k1, v1 in name_attrs.items()
359359
}
360360

@@ -446,15 +446,15 @@ def dataframe_to_tree(
446446
root_node_kwargs = list(
447447
root_node_data[attribute_cols].to_dict(orient="index").values()
448448
)[0]
449-
root_node_kwargs = assertions.filter_attributes(
449+
root_node_kwargs = common.filter_attributes(
450450
root_node_kwargs, omit_keys=["name", path_col], omit_null_values=True
451451
)
452452
root_node = node_type(root_name, **root_node_kwargs)
453453
else:
454454
root_node = node_type(root_name)
455455

456456
for row in data.to_dict(orient="index").values():
457-
node_attrs = assertions.filter_attributes(
457+
node_attrs = common.filter_attributes(
458458
row, omit_keys=["name", path_col], omit_null_values=True
459459
)
460460
add_path_to_tree(
@@ -562,7 +562,7 @@ def _retrieve_attr(_row: Dict[str, Any]) -> Dict[str, Any]:
562562
Returns:
563563
Attribute dictionary
564564
"""
565-
node_attrs = assertions.filter_attributes(
565+
node_attrs = common.filter_attributes(
566566
_row, omit_keys=[child_col, parent_col], omit_null_values=True
567567
)
568568
node_attrs["name"] = _row[child_col]
@@ -678,15 +678,15 @@ def polars_to_tree(
678678
if len(root_node_data):
679679
root_node_kwargs_list = root_node_data[attribute_cols].to_dicts()
680680
root_node_kwargs = root_node_kwargs_list[0] if root_node_kwargs_list else {}
681-
root_node_kwargs = assertions.filter_attributes(
681+
root_node_kwargs = common.filter_attributes(
682682
root_node_kwargs, omit_keys=["name", path_col], omit_null_values=True
683683
)
684684
root_node = node_type(root_name, **root_node_kwargs)
685685
else:
686686
root_node = node_type(root_name)
687687

688688
for row in data.to_dicts():
689-
node_attrs = assertions.filter_attributes(
689+
node_attrs = common.filter_attributes(
690690
row, omit_keys=["name", path_col], omit_null_values=True
691691
)
692692
add_path_to_tree(
@@ -794,7 +794,7 @@ def _retrieve_attr(_row: Dict[str, Any]) -> Dict[str, Any]:
794794
Returns:
795795
Attribute dictionary
796796
"""
797-
node_attrs = assertions.filter_attributes(
797+
node_attrs = common.filter_attributes(
798798
_row, omit_keys=[child_col, parent_col], omit_null_values=True
799799
)
800800
node_attrs["name"] = _row[child_col]

bigtree/tree/construct/dictionaries.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from bigtree.node import node
66
from bigtree.tree.construct.strings import add_path_to_tree
7-
from bigtree.utils import assertions
7+
from bigtree.utils import assertions, common
88

99
__all__ = [
1010
"add_dict_to_tree_by_path",
@@ -127,7 +127,7 @@ def add_dict_to_tree_by_name(tree: T, name_attrs: Mapping[str, Mapping[str, Any]
127127
attr_dict_names = set(name_attrs.keys())
128128

129129
for _node in findall(tree, lambda _node1: _node1.node_name in attr_dict_names):
130-
node_attrs = assertions.filter_attributes(
130+
node_attrs = common.filter_attributes(
131131
name_attrs[_node.node_name], omit_keys=["name"], omit_null_values=False
132132
)
133133
_node.set_attrs(node_attrs)
@@ -201,7 +201,7 @@ def dict_to_tree(
201201
or path_attrs.get(root_name + sep, {})
202202
or path_attrs.get(sep + root_name + sep, {})
203203
)
204-
root_node_attrs = assertions.filter_attributes(
204+
root_node_attrs = common.filter_attributes(
205205
root_node_attrs, omit_keys=["name"], omit_null_values=False
206206
)
207207
root_node = node_type(
@@ -212,7 +212,7 @@ def dict_to_tree(
212212

213213
# Convert dictionary to dataframe
214214
for node_path, node_attrs in path_attrs.items():
215-
node_attrs = assertions.filter_attributes(
215+
node_attrs = common.filter_attributes(
216216
node_attrs, omit_keys=["name"], omit_null_values=False
217217
)
218218
add_path_to_tree(

bigtree/tree/export/dataframes.py

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Any, Dict, Optional, TypeVar
44

55
from bigtree.node import node
6-
from bigtree.utils import exceptions
6+
from bigtree.utils import common, exceptions
77

88
try:
99
import pandas as pd
@@ -106,13 +106,9 @@ def _recursive_append(_node: T) -> None:
106106
parent_name = _node.parent.node_name
107107
data_child[parent_col] = parent_name
108108

109-
if all_attrs:
110-
data_child.update(
111-
_node.describe(exclude_attributes=["name"], exclude_prefix="_")
112-
)
113-
elif attr_dict:
114-
for k, v in attr_dict.items():
115-
data_child[v] = _node.get_attr(k)
109+
data_child = common.assemble_attributes(
110+
_node, attr_dict, all_attrs, data_child
111+
)
116112
data_list.append(data_child)
117113
for _child in _node.children:
118114
_recursive_append(_child)
@@ -211,13 +207,9 @@ def _recursive_append(_node: T) -> None:
211207
parent_name = _node.parent.node_name
212208
data_child[parent_col] = parent_name
213209

214-
if all_attrs:
215-
data_child.update(
216-
_node.describe(exclude_attributes=["name"], exclude_prefix="_")
217-
)
218-
elif attr_dict:
219-
for k, v in attr_dict.items():
220-
data_child[v] = _node.get_attr(k)
210+
data_child = common.assemble_attributes(
211+
_node, attr_dict, all_attrs, data_child
212+
)
221213
data_list.append(data_child)
222214
for _child in _node.children:
223215
_recursive_append(_child)

bigtree/tree/export/dictionaries.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import Any, Dict, List, Optional, TypeVar
44

55
from bigtree.node import node
6+
from bigtree.utils import common
67

78
__all__ = [
89
"tree_to_dict",
@@ -107,7 +108,7 @@ def _recursive_append(_node: T) -> None:
107108
if _node.parent:
108109
parent_name = _node.parent.node_name
109110
data_child[parent_key] = parent_name
110-
data_child = _assemble_attributes(
111+
data_child = common.assemble_attributes(
111112
_node, attr_dict, all_attrs, data_child
112113
)
113114
data_dict[_node.path_name] = data_child
@@ -165,7 +166,7 @@ def _recursive_append(_node: T, parent_dict: Dict[str, Any]) -> None:
165166
if _node:
166167
if not max_depth or _node.depth <= max_depth:
167168
data_child = {name_key: _node.node_name}
168-
data_child = _assemble_attributes(
169+
data_child = common.assemble_attributes(
169170
_node, attr_dict, all_attrs, data_child
170171
)
171172
if child_key in parent_dict:
@@ -224,7 +225,7 @@ def _recursive_append(_node: T, parent_dict: Dict[str, Any]) -> None:
224225
"""
225226
if _node:
226227
if not max_depth or _node.depth <= max_depth:
227-
data_child = _assemble_attributes(_node, attr_dict, all_attrs)
228+
data_child = common.assemble_attributes(_node, attr_dict, all_attrs)
228229
if child_key in parent_dict:
229230
parent_dict[child_key][_node.node_name] = data_child
230231
else:

bigtree/tree/export/stdout.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Any, Collection, Iterable, List, Optional, Tuple, TypeVar, Union
44

55
from bigtree.node import node
6-
from bigtree.utils import assertions, constants
6+
from bigtree.utils import common, constants
77

88
__all__ = [
99
"print_tree",
@@ -201,7 +201,7 @@ def print_tree(
201201
attr_str_list = [
202202
f"{attr_name}={_node.get_attr(attr_name)}"
203203
for attr_name in attr_list
204-
if not assertions.isnull(_node.get_attr(attr_name))
204+
if not common.isnull(_node.get_attr(attr_name))
205205
]
206206
else:
207207
attr_str_list = [

bigtree/utils/assertions.py

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
TYPE_CHECKING,
55
Any,
66
Collection,
7-
Dict,
87
Iterable,
98
List,
109
Mapping,
@@ -44,8 +43,6 @@
4443
"assert_dataframe_no_duplicate_attribute",
4544
"assert_dataframe_no_duplicate_children",
4645
"assert_tree_type",
47-
"isnull",
48-
"filter_attributes",
4946
]
5047

5148

@@ -252,43 +249,3 @@ def assert_tree_type(
252249
raise TypeError(
253250
f"Tree should be of type `{tree_type_name}`, or inherit from `{tree_type_name}`"
254251
)
255-
256-
257-
def isnull(value: Any) -> bool:
258-
"""Check if value is null.
259-
260-
Args:
261-
value: value to check
262-
263-
Returns:
264-
Flag if value is null
265-
"""
266-
import math
267-
268-
if value is None or (isinstance(value, float) and math.isnan(value)):
269-
return True
270-
return False
271-
272-
273-
def filter_attributes(
274-
node_attributes: Mapping[str, Any],
275-
omit_keys: Collection[str],
276-
omit_null_values: bool,
277-
) -> Dict[str, Any]:
278-
"""Filter node attributes to remove certain keys and/or values.
279-
280-
Args:
281-
node_attributes: node attributes information
282-
omit_keys: keys to omit
283-
omit_null_values: indicator whether to omit values that are null
284-
285-
Returns:
286-
Filtered node attributes
287-
"""
288-
if omit_null_values:
289-
return {
290-
k: v
291-
for k, v in node_attributes.items()
292-
if not isnull(v) and k not in omit_keys
293-
}
294-
return {k: v for k, v in node_attributes.items() if k not in omit_keys}

0 commit comments

Comments
 (0)