Skip to content

Commit 2b587f2

Browse files
authored
Merge pull request #294 from kayjan/fix/modify-import
Import by module instead of functions
2 parents 9f28d87 + f0b060a commit 2b587f2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2481
-2542
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Changed:
9+
- Misc: Import module instead of functions, following Google Python Style Guide.
810

911
## [0.21.0] - 2024-08-26
1012
### Added:

bigtree/binarytree/construct.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
from typing import List, Type, TypeVar
22

3-
from bigtree.node.binarynode import BinaryNode
4-
from bigtree.utils.assertions import assert_length_not_empty
3+
from bigtree.node import binarynode
4+
from bigtree.utils import assertions
55

66
__all__ = ["list_to_binarytree"]
77

8-
T = TypeVar("T", bound=BinaryNode)
8+
T = TypeVar("T", bound=binarynode.BinaryNode)
99

1010

1111
def list_to_binarytree(
1212
heapq_list: List[int],
13-
node_type: Type[T] = BinaryNode, # type: ignore[assignment]
13+
node_type: Type[T] = binarynode.BinaryNode, # type: ignore[assignment]
1414
) -> T:
1515
"""Construct tree from a list of numbers (int or float) in heapq format.
1616
@@ -41,7 +41,7 @@ def list_to_binarytree(
4141
Returns:
4242
(BinaryNode)
4343
"""
44-
assert_length_not_empty(heapq_list, "Input list", "heapq_list")
44+
assertions.assert_length_not_empty(heapq_list, "Input list", "heapq_list")
4545

4646
root_node = node_type(heapq_list[0])
4747
node_list = [root_node]

bigtree/dag/construct.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,8 @@
22

33
from typing import Any, Dict, List, Tuple, Type, TypeVar
44

5-
from bigtree.node.dagnode import DAGNode
6-
from bigtree.utils.assertions import (
7-
assert_dataframe_no_duplicate_attribute,
8-
assert_dataframe_not_empty,
9-
assert_length_not_empty,
10-
assert_not_reserved_keywords,
11-
filter_attributes,
12-
isnull,
13-
)
14-
from bigtree.utils.exceptions import optional_dependencies_pandas
5+
from bigtree.node import dagnode
6+
from bigtree.utils import assertions, exceptions
157

168
try:
179
import pandas as pd
@@ -22,12 +14,12 @@
2214

2315
__all__ = ["list_to_dag", "dict_to_dag", "dataframe_to_dag"]
2416

25-
T = TypeVar("T", bound=DAGNode)
17+
T = TypeVar("T", bound=dagnode.DAGNode)
2618

2719

2820
def list_to_dag(
2921
relations: List[Tuple[str, str]],
30-
node_type: Type[T] = DAGNode, # type: ignore[assignment]
22+
node_type: Type[T] = dagnode.DAGNode, # type: ignore[assignment]
3123
) -> T:
3224
"""Construct DAG from list of tuples containing parent-child names.
3325
Note that node names must be unique.
@@ -46,10 +38,10 @@ def list_to_dag(
4638
Returns:
4739
(DAGNode)
4840
"""
49-
assert_length_not_empty(relations, "Input list", "relations")
41+
assertions.assert_length_not_empty(relations, "Input list", "relations")
5042

5143
node_dict: Dict[str, T] = dict()
52-
parent_node: T = DAGNode() # type: ignore[assignment]
44+
parent_node: T = dagnode.DAGNode() # type: ignore[assignment]
5345

5446
for parent_name, child_name in relations:
5547
if parent_name not in node_dict:
@@ -71,7 +63,7 @@ def list_to_dag(
7163
def dict_to_dag(
7264
relation_attrs: Dict[str, Any],
7365
parent_key: str = "parents",
74-
node_type: Type[T] = DAGNode, # type: ignore[assignment]
66+
node_type: Type[T] = dagnode.DAGNode, # type: ignore[assignment]
7567
) -> T:
7668
"""Construct DAG from nested dictionary, ``key``: child name, ``value``: dictionary of parent names, attribute
7769
name, and attribute value.
@@ -99,7 +91,7 @@ def dict_to_dag(
9991
Returns:
10092
(DAGNode)
10193
"""
102-
assert_length_not_empty(relation_attrs, "Dictionary", "relation_attrs")
94+
assertions.assert_length_not_empty(relation_attrs, "Dictionary", "relation_attrs")
10395

10496
node_dict: Dict[str, T] = dict()
10597
parent_node: T | None = None
@@ -109,7 +101,9 @@ def dict_to_dag(
109101
parent_names: List[str] = []
110102
if parent_key in node_attrs:
111103
parent_names = node_attrs.pop(parent_key)
112-
assert_not_reserved_keywords(node_attrs, ["parent", "parents", "children"])
104+
assertions.assert_not_reserved_keywords(
105+
node_attrs, ["parent", "parents", "children"]
106+
)
113107

114108
if child_name in node_dict:
115109
child_node = node_dict[child_name]
@@ -131,13 +125,13 @@ def dict_to_dag(
131125
return parent_node
132126

133127

134-
@optional_dependencies_pandas
128+
@exceptions.optional_dependencies_pandas
135129
def dataframe_to_dag(
136130
data: pd.DataFrame,
137131
child_col: str = "",
138132
parent_col: str = "",
139133
attribute_cols: List[str] = [],
140-
node_type: Type[T] = DAGNode, # type: ignore[assignment]
134+
node_type: Type[T] = dagnode.DAGNode, # type: ignore[assignment]
141135
) -> T:
142136
"""Construct DAG from pandas DataFrame.
143137
Note that node names must be unique.
@@ -180,7 +174,7 @@ def dataframe_to_dag(
180174
Returns:
181175
(DAGNode)
182176
"""
183-
assert_dataframe_not_empty(data)
177+
assertions.assert_dataframe_not_empty(data)
184178

185179
if not child_col:
186180
child_col = data.columns[0]
@@ -194,30 +188,32 @@ def dataframe_to_dag(
194188
attribute_cols = list(data.columns)
195189
attribute_cols.remove(child_col)
196190
attribute_cols.remove(parent_col)
197-
assert_not_reserved_keywords(attribute_cols, ["parent", "parents", "children"])
191+
assertions.assert_not_reserved_keywords(
192+
attribute_cols, ["parent", "parents", "children"]
193+
)
198194

199195
data = data[[child_col, parent_col] + attribute_cols].copy()
200196

201-
assert_dataframe_no_duplicate_attribute(
197+
assertions.assert_dataframe_no_duplicate_attribute(
202198
data, "child name", child_col, attribute_cols
203199
)
204200
if sum(data[child_col].isnull()):
205201
raise ValueError(f"Child name cannot be empty, check column: {child_col}")
206202

207203
node_dict: Dict[str, T] = dict()
208-
parent_node: T = DAGNode() # type: ignore[assignment]
204+
parent_node: T = dagnode.DAGNode() # type: ignore[assignment]
209205

210206
for row in data.reset_index(drop=True).to_dict(orient="index").values():
211207
child_name = row[child_col]
212208
parent_name = row[parent_col]
213-
node_attrs = filter_attributes(
209+
node_attrs = assertions.filter_attributes(
214210
row, omit_keys=["name", child_col, parent_col], omit_null_values=True
215211
)
216212
child_node = node_dict.get(child_name, node_type(child_name, **node_attrs))
217213
child_node.set_attrs(node_attrs)
218214
node_dict[child_name] = child_node
219215

220-
if not isnull(parent_name):
216+
if not assertions.isnull(parent_name):
221217
parent_node = node_dict.get(parent_name, node_type(parent_name))
222218
node_dict[parent_name] = parent_node
223219
child_node.parents = [parent_node]

bigtree/dag/export.py

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,8 @@
22

33
from typing import Any, Dict, List, Tuple, TypeVar, Union
44

5-
from bigtree.node.dagnode import DAGNode
6-
from bigtree.utils.assertions import assert_tree_type
7-
from bigtree.utils.exceptions import (
8-
optional_dependencies_image,
9-
optional_dependencies_pandas,
10-
)
11-
from bigtree.utils.iterators import dag_iterator
5+
from bigtree.node import dagnode
6+
from bigtree.utils import assertions, exceptions, iterators
127

138
try:
149
import pandas as pd
@@ -27,7 +22,7 @@
2722
__all__ = ["dag_to_list", "dag_to_dict", "dag_to_dataframe", "dag_to_dot"]
2823

2924

30-
T = TypeVar("T", bound=DAGNode)
25+
T = TypeVar("T", bound=dagnode.DAGNode)
3126

3227

3328
def dag_to_list(
@@ -52,7 +47,7 @@ def dag_to_list(
5247
(List[Tuple[str, str]])
5348
"""
5449
relations = []
55-
for parent_node, child_node in dag_iterator(dag):
50+
for parent_node, child_node in iterators.dag_iterator(dag):
5651
relations.append((parent_node.node_name, child_node.node_name))
5752
return relations
5853

@@ -90,7 +85,7 @@ def dag_to_dict(
9085
dag = dag.copy()
9186
data_dict = {}
9287

93-
for parent_node, child_node in dag_iterator(dag):
88+
for parent_node, child_node in iterators.dag_iterator(dag):
9489
if parent_node.is_root:
9590
data_parent: Dict[str, Any] = {}
9691
if all_attrs:
@@ -119,7 +114,7 @@ def dag_to_dict(
119114
return data_dict
120115

121116

122-
@optional_dependencies_pandas
117+
@exceptions.optional_dependencies_pandas
123118
def dag_to_dataframe(
124119
dag: T,
125120
name_col: str = "name",
@@ -160,7 +155,7 @@ def dag_to_dataframe(
160155
dag = dag.copy()
161156
data_list: List[Dict[str, Any]] = []
162157

163-
for parent_node, child_node in dag_iterator(dag):
158+
for parent_node, child_node in iterators.dag_iterator(dag):
164159
if parent_node.is_root:
165160
data_parent = {name_col: parent_node.node_name, parent_col: None}
166161
if all_attrs:
@@ -186,7 +181,7 @@ def dag_to_dataframe(
186181
return pd.DataFrame(data_list).drop_duplicates().reset_index(drop=True)
187182

188183

189-
@optional_dependencies_image("pydot")
184+
@exceptions.optional_dependencies_image("pydot")
190185
def dag_to_dot(
191186
dag: Union[T, List[T]],
192187
rankdir: str = "TB",
@@ -257,10 +252,10 @@ def dag_to_dot(
257252
dag = [dag]
258253

259254
for _dag in dag:
260-
assert_tree_type(_dag, DAGNode, "DAGNode")
255+
assertions.assert_tree_type(_dag, dagnode.DAGNode, "DAGNode")
261256
_dag = _dag.copy()
262257

263-
for parent_node, child_node in dag_iterator(_dag):
258+
for parent_node, child_node in iterators.dag_iterator(_dag):
264259
_node_style = node_style.copy()
265260
_edge_style = edge_style.copy()
266261

bigtree/node/basenode.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
from typing import Any, Dict, Generator, Iterable, List, Optional, Set, Tuple, TypeVar
66

77
from bigtree.globals import ASSERTIONS
8-
from bigtree.utils.exceptions import CorruptedTreeError, LoopError, TreeError
9-
from bigtree.utils.iterators import preorder_iter
8+
from bigtree.utils import exceptions, iterators
109

1110
try:
1211
import matplotlib.pyplot as plt
@@ -164,13 +163,15 @@ def __check_parent_loop(self, new_parent: T) -> None:
164163
"""
165164
if new_parent is not None:
166165
if new_parent is self:
167-
raise LoopError("Error setting parent: Node cannot be parent of itself")
166+
raise exceptions.LoopError(
167+
"Error setting parent: Node cannot be parent of itself"
168+
)
168169
if any(
169170
ancestor is self
170171
for ancestor in new_parent.ancestors
171172
if new_parent.ancestors
172173
):
173-
raise LoopError(
174+
raise exceptions.LoopError(
174175
"Error setting parent: Node cannot be ancestor of itself"
175176
)
176177

@@ -205,7 +206,7 @@ def parent(self: T, new_parent: T) -> None:
205206
if not any(
206207
child is self for child in current_parent.children
207208
): # pragma: no cover
208-
raise CorruptedTreeError(
209+
raise exceptions.CorruptedTreeError(
209210
"Error setting parent: Node does not exist as children of its parent"
210211
)
211212
current_child_idx = current_parent.__children.index(self)
@@ -227,7 +228,7 @@ def parent(self: T, new_parent: T) -> None:
227228
self.__parent = current_parent
228229
if current_child_idx is not None:
229230
current_parent.__children.insert(current_child_idx, self)
230-
raise TreeError(exc_info)
231+
raise exceptions.TreeError(exc_info)
231232

232233
def __pre_assign_parent(self, new_parent: T) -> None:
233234
"""Custom method to check before attaching parent
@@ -305,15 +306,17 @@ def __check_children_loop(self: T, new_children: Iterable[T]) -> None:
305306

306307
# Check for loop and tree structure
307308
if new_child is self:
308-
raise LoopError("Error setting child: Node cannot be child of itself")
309+
raise exceptions.LoopError(
310+
"Error setting child: Node cannot be child of itself"
311+
)
309312
if any(child is new_child for child in self.ancestors):
310-
raise LoopError(
313+
raise exceptions.LoopError(
311314
"Error setting child: Node cannot be ancestor of itself"
312315
)
313316

314317
# Check for duplicate children
315318
if id(new_child) in seen_children:
316-
raise TreeError(
319+
raise exceptions.TreeError(
317320
"Error setting child: Node cannot be added multiple times as a child"
318321
)
319322
else:
@@ -376,7 +379,7 @@ def children(self: T, new_children: List[T] | Tuple[T] | Set[T]) -> None:
376379
self.__children = current_children
377380
for child in current_children:
378381
child.__parent = self
379-
raise TreeError(exc_info)
382+
raise exceptions.TreeError(exc_info)
380383

381384
@children.deleter
382385
def children(self) -> None:
@@ -422,7 +425,9 @@ def descendants(self: T) -> Iterable[T]:
422425
Returns:
423426
(Iterable[Self])
424427
"""
425-
yield from preorder_iter(self, filter_condition=lambda _node: _node != self)
428+
yield from iterators.preorder_iter(
429+
self, filter_condition=lambda _node: _node != self
430+
)
426431

427432
@property
428433
def leaves(self: T) -> Iterable[T]:
@@ -431,7 +436,9 @@ def leaves(self: T) -> Iterable[T]:
431436
Returns:
432437
(Iterable[Self])
433438
"""
434-
yield from preorder_iter(self, filter_condition=lambda _node: _node.is_leaf)
439+
yield from iterators.preorder_iter(
440+
self, filter_condition=lambda _node: _node.is_leaf
441+
)
435442

436443
@property
437444
def siblings(self: T) -> Iterable[T]:
@@ -687,7 +694,7 @@ def go_to(self: T, node: T) -> Iterable[T]:
687694
f"Expect node to be BaseNode type, received input type {type(node)}"
688695
)
689696
if self.root != node.root:
690-
raise TreeError(
697+
raise exceptions.TreeError(
691698
f"Nodes are not from the same tree. Check {self} and {node}"
692699
)
693700
if self == node:

0 commit comments

Comments
 (0)