diff --git a/CHANGELOG.md b/CHANGELOG.md index c3a4a87d..b7240e5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.2] - 2025-10-23 +### Added: +- Optional checks: Able to toggle for optional checks after importing bigtree. Previously, you can only set the +environment variables before import. + ## [1.0.2] - 2025-10-23 ### Added: - Test: Fix code coverage. diff --git a/bigtree/__init__.py b/bigtree/__init__.py index dee74eef..e6d6cbc6 100644 --- a/bigtree/__init__.py +++ b/bigtree/__init__.py @@ -6,6 +6,7 @@ from bigtree.dag.dag import DAG from bigtree.dag.export import dag_to_dataframe, dag_to_dict, dag_to_dot, dag_to_list from bigtree.dag.parsing import get_path_dag +from bigtree.globals import ASSERTIONS from bigtree.node.basenode import BaseNode from bigtree.node.binarynode import BinaryNode from bigtree.node.dagnode import DAGNode diff --git a/bigtree/globals.py b/bigtree/globals.py index 52e79771..26b5fb64 100644 --- a/bigtree/globals.py +++ b/bigtree/globals.py @@ -1,3 +1,5 @@ import os -ASSERTIONS: bool = bool(os.environ.get("BIGTREE_CONF_ASSERTIONS", True)) + +class ASSERTIONS: + FLAG: bool = bool(os.environ.get("BIGTREE_CONF_ASSERTIONS", True)) diff --git a/bigtree/node/basenode.py b/bigtree/node/basenode.py index 6af8f728..f9262522 100644 --- a/bigtree/node/basenode.py +++ b/bigtree/node/basenode.py @@ -192,7 +192,7 @@ def parent(self: T, new_parent: T) -> None: Args: new_parent: parent node """ - if ASSERTIONS: + if ASSERTIONS.FLAG: self.__check_parent_type(new_parent) self.__check_parent_loop(new_parent) @@ -335,7 +335,7 @@ def children(self: T, new_children: list[T] | tuple[T] | set[T]) -> None: Args: new_children: child node """ - if ASSERTIONS: + if ASSERTIONS.FLAG: self.__check_children_type(new_children) self.__check_children_loop(new_children) new_children = list(new_children) diff --git a/bigtree/node/binarynode.py b/bigtree/node/binarynode.py index 1fc6d574..89e856ea 100644 --- a/bigtree/node/binarynode.py +++ b/bigtree/node/binarynode.py @@ -166,7 +166,7 @@ def parent(self: T, new_parent: T | None) -> None: Args: new_parent: parent node """ - if ASSERTIONS: + if ASSERTIONS.FLAG: self.__check_parent_type(new_parent) self._BaseNode__check_parent_loop(new_parent) # type: ignore @@ -296,7 +296,7 @@ def children(self: T, _new_children: list[T | None]) -> None: """ self._BaseNode__check_children_type(_new_children) # type: ignore new_children = self.__check_children_type(_new_children) - if ASSERTIONS: + if ASSERTIONS.FLAG: self.__check_children_loop(new_children) current_new_children = { diff --git a/bigtree/node/dagnode.py b/bigtree/node/dagnode.py index ede174b8..a64f3f65 100644 --- a/bigtree/node/dagnode.py +++ b/bigtree/node/dagnode.py @@ -212,7 +212,7 @@ def parents(self: T, new_parents: list[T]) -> None: Args: new_parents: parent nodes """ - if ASSERTIONS: + if ASSERTIONS.FLAG: self.__check_parent_type(new_parents) self.__check_parent_loop(new_parents) @@ -311,7 +311,7 @@ def children(self: T, new_children: Iterable[T]) -> None: Args: new_children: child node """ - if ASSERTIONS: + if ASSERTIONS.FLAG: self.__check_children_type(new_children) self.__check_children_loop(new_children) diff --git a/bigtree/node/node.py b/bigtree/node/node.py index bbd473bb..ece0cb43 100644 --- a/bigtree/node/node.py +++ b/bigtree/node/node.py @@ -84,7 +84,7 @@ def __init__(self, name: str, sep: str = "/", **kwargs: Any): self.name = name self._sep = sep super().__init__(**kwargs) - if ASSERTIONS and not self.node_name: + if ASSERTIONS.FLAG and not self.node_name: raise exceptions.TreeError("Node must have a `name` attribute") @property @@ -133,7 +133,7 @@ def _BaseNode__pre_assign_parent(self: T, new_parent: T) -> None: Args: new_parent: new parent to be added """ - if ASSERTIONS and new_parent is not None: + if ASSERTIONS.FLAG and new_parent is not None: if any( child.node_name == self.node_name and child is not self for child in new_parent.children @@ -149,7 +149,7 @@ def _BaseNode__pre_assign_children(self: T, new_children: list[T]) -> None: Args: new_children: new children to be added """ - if ASSERTIONS: + if ASSERTIONS.FLAG: children_names = [node.node_name for node in new_children] duplicate_names = [ item[0] for item in Counter(children_names).items() if item[1] > 1 diff --git a/docs/others/remove_checks.md b/docs/others/remove_checks.md index 3636c38c..99ee9acc 100644 --- a/docs/others/remove_checks.md +++ b/docs/others/remove_checks.md @@ -27,3 +27,10 @@ os.environ["BIGTREE_CONF_ASSERTIONS"] = "" import bigtree ``` + +Alternatively, if you have already imported bigtree, you can set the configuration manually. + +```python +import bigtree +bigtree.ASSERTIONS.FLAG = False +``` diff --git a/tests/node/test_basenode_no_assertions.py b/tests/node/test_basenode_no_assertions.py index c701b4df..1dff2fc6 100644 --- a/tests/node/test_basenode_no_assertions.py +++ b/tests/node/test_basenode_no_assertions.py @@ -6,7 +6,7 @@ from bigtree.node import basenode -@patch("bigtree.node.basenode.ASSERTIONS", "") +@patch("bigtree.node.basenode.ASSERTIONS.FLAG", "") class TestBaseNodeNoAssertions(unittest.TestCase): def setUp(self): """ diff --git a/tests/node/test_binarynode_no_assertions.py b/tests/node/test_binarynode_no_assertions.py index 80efc405..357b3015 100644 --- a/tests/node/test_binarynode_no_assertions.py +++ b/tests/node/test_binarynode_no_assertions.py @@ -7,7 +7,7 @@ from bigtree.utils.exceptions import TreeError -@patch("bigtree.node.binarynode.ASSERTIONS", "") +@patch("bigtree.node.binarynode.ASSERTIONS.FLAG", "") class TestBinaryNodeNoAssertions(unittest.TestCase): def setUp(self): self.a = binarynode.BinaryNode(1) diff --git a/tests/node/test_dagnode_no_assertions.py b/tests/node/test_dagnode_no_assertions.py index dca2c4d0..53adaeaf 100644 --- a/tests/node/test_dagnode_no_assertions.py +++ b/tests/node/test_dagnode_no_assertions.py @@ -6,7 +6,7 @@ from bigtree.node import basenode, dagnode, node -@patch("bigtree.node.dagnode.ASSERTIONS", "") +@patch("bigtree.node.dagnode.ASSERTIONS.FLAG", "") class TestDAGNodeNoAssertions(unittest.TestCase): def setUp(self): """ diff --git a/tests/node/test_node.py b/tests/node/test_node.py index 14605a46..c4a9eb37 100644 --- a/tests/node/test_node.py +++ b/tests/node/test_node.py @@ -182,7 +182,7 @@ def test_set_children_sep_different_error(self): path=path ) - @patch("bigtree.node.node.ASSERTIONS", "") + @patch("bigtree.node.node.ASSERTIONS.FLAG", "") def test_set_children_sep_different_no_assertion(self): b = node.Node("b", sep="\\") self.a.children = [self.b, b] diff --git a/tests/node/test_node_benchmark.py b/tests/node/test_node_benchmark.py index 431a64e5..6564a4f9 100644 --- a/tests/node/test_node_benchmark.py +++ b/tests/node/test_node_benchmark.py @@ -3,6 +3,7 @@ import pytest +import bigtree from bigtree.node import node sys.setrecursionlimit(2000) @@ -49,24 +50,52 @@ def test_node_benchmark_width_2_depth_10(benchmark): @pytest.mark.benchmark(group="width_1_depth_10") -@patch("bigtree.node.basenode.ASSERTIONS", "") +@patch("bigtree.node.basenode.ASSERTIONS.FLAG", "") def test_node_benchmark_width_1_depth_10_no_assertions(benchmark): benchmark.pedantic(run_construct_node, (10, 1), iterations=10, rounds=2) +@pytest.mark.benchmark(group="width_1_depth_10") +def test_node_benchmark_width_1_depth_10_no_assertions_config(benchmark): + bigtree.ASSERTIONS.FLAG = False + benchmark.pedantic(run_construct_node, (10, 1), iterations=10, rounds=2) + bigtree.ASSERTIONS.FLAG = True + + @pytest.mark.benchmark(group="width_1_depth_100") -@patch("bigtree.node.basenode.ASSERTIONS", "") +@patch("bigtree.node.basenode.ASSERTIONS.FLAG", "") def test_node_benchmark_width_1_depth_100_no_assertions(benchmark): benchmark.pedantic(run_construct_node, (100, 1), iterations=10, rounds=2) +@pytest.mark.benchmark(group="width_1_depth_100") +def test_node_benchmark_width_1_depth_100_no_assertions_config(benchmark): + bigtree.ASSERTIONS.FLAG = False + benchmark.pedantic(run_construct_node, (100, 1), iterations=10, rounds=2) + bigtree.ASSERTIONS.FLAG = True + + @pytest.mark.benchmark(group="width_1_depth_1000") -@patch("bigtree.node.basenode.ASSERTIONS", "") +@patch("bigtree.node.basenode.ASSERTIONS.FLAG", "") def test_node_benchmark_width_1_depth_1000_no_assertions(benchmark): benchmark.pedantic(run_construct_node, (1000, 1), iterations=10, rounds=2) +@pytest.mark.benchmark(group="width_1_depth_1000") +def test_node_benchmark_width_1_depth_1000_no_assertions_config(benchmark): + bigtree.ASSERTIONS.FLAG = False + benchmark.pedantic(run_construct_node, (1000, 1), iterations=10, rounds=2) + bigtree.ASSERTIONS.FLAG = True + + @pytest.mark.benchmark(group="width_2_depth_10") -@patch("bigtree.node.basenode.ASSERTIONS", "") +@patch("bigtree.node.basenode.ASSERTIONS.FLAG", "") def test_node_benchmark_width_2_depth_10_no_assertions(benchmark): benchmark.pedantic(run_construct_node, (10, 2), iterations=10, rounds=2) + + +@pytest.mark.benchmark(group="width_2_depth_10") +def test_node_benchmark_width_2_depth_10_no_assertions_config(benchmark): + bigtree.ASSERTIONS.FLAG = False + benchmark.pedantic(run_construct_node, (10, 2), iterations=10, rounds=2) + bigtree.ASSERTIONS.FLAG = True