diff --git a/nodes/manager.py b/nodes/manager.py index b3c1178..ab8f64f 100644 --- a/nodes/manager.py +++ b/nodes/manager.py @@ -1,5 +1,87 @@ # Create here the NodeManager Class +from typing import List + +from nodes.node import Node class NodeManager: - pass + """ + A class to represent a manager of the nodes object. + + ... + + Attributes + ---------- + nodes : List[Node] + List of the nodes + + Methods + ------- + remove(elem: Node): + Remove a node + remove_cascade(elem: Node): + Remove a node with its parents + """ + + nodes: List[Node] + + def __init__(self, nodes: List[Node]) -> None: + """ + Constructs all the necessary attributes for the node manager object + + Parameters + ---------- + nodes : List[Node] + List of the nodes object + """ + + if not isinstance(nodes, list): + raise ValueError("Needs a list of Node object to instance it") + + self.nodes = nodes.copy() + + def __len__(self): + return len(self.nodes) + + def __getitem__(self, key): + return self.nodes[key] + + def remove(self, elem: Node) -> None: + """ + Remove a node object + + Parameters + ---------- + elem : Node + Node object + + Returns + ------- + None + """ + if elem not in self.nodes: + raise ValueError("Node object not found") + + self.nodes.remove(elem) + + def remove_cascade(self, elem: Node) -> None: + """ + Remove a node object with its parents + + Parameters + ---------- + elem : Node + Node object + + Returns + ------- + None + """ + if elem not in self.nodes: + raise ValueError("Node object not found") + + parents = [item for item in self.nodes if item.parent == elem.id] + for item in parents: + self.remove_cascade(item) + else: + self.remove(elem) diff --git a/nodes/node.py b/nodes/node.py index 644ab4e..b4512a5 100644 --- a/nodes/node.py +++ b/nodes/node.py @@ -2,4 +2,47 @@ class Node: - pass + """ + A class to represent a node. + + ... + + Attributes + ---------- + id : int + Identification key of the node + parent : int + Identification key of the node parent + """ + + id: int + parent: int + + def __init__(self, id: int, parent: int) -> None: + """ + Constructs all the necessary attributes for the node object + + Parameters + ---------- + id : int + Identification key of the node + parent : int + Identification key of the node parent + """ + + self.id = id + self.parent = parent + + if not self.id and self.parent: + raise ValueError("Id and parent is required") + if not isinstance(self.id, int): + raise ValueError("Id must be integer") + if not isinstance(self.parent, int): + raise ValueError("Parent must be integer") + if self.id == self.parent: + raise ValueError("Id cannot be equal to parent") + if self.id < self.parent: + raise ValueError("Id cannot be less than parent") + + def __repr__(self) -> str: + return f"Node({self.id}, {self.parent})" diff --git a/tests/conftest.py b/tests/conftest.py index d64f5aa..aebc17d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,13 +13,15 @@ def random_integers() -> Tuple[int, int]: return random.randint(25000, 50000), random.randint(0, 25000) +@pytest.fixture def generate_random_node() -> Node: id, parent = random_integers() return Node(id, parent) -def random_nodes() -> List[Node]: - return [generate_random_node() for _ in range(100)] +@pytest.fixture +def random_nodes(generate_random_node) -> List[Node]: + return [generate_random_node for _ in range(100)] @pytest.fixture diff --git a/tests/test_manager.py b/tests/test_manager.py index c9b970e..6b4760c 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -1,5 +1,4 @@ import pytest -from . import conftest from typing import get_type_hints, List, Dict, Any from nodes.manager import NodeManager from nodes.node import Node @@ -7,7 +6,7 @@ def assert_nodes_type_hint_on_hints(hints: Dict[str, Any]): assert "nodes" in hints - assert List[Node] == hints.get("nodes") + assert hints.get("nodes") is List[Node] def test_nodemanager_nodes_attr_has_type_hints(): @@ -30,8 +29,8 @@ def test_nodemanager_raises_given_non_sequence(): NodeManager(1) -def test_nodemanager_accepts_list(): - node_list = conftest.random_nodes() +def test_nodemanager_accepts_list(random_nodes): + node_list = random_nodes NodeManager(node_list) diff --git a/tests/test_node.py b/tests/test_node.py index 661d817..3852bed 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -1,25 +1,24 @@ import pytest from nodes.node import Node from typing import get_type_hints, Dict, Any -from . import conftest def test_node_class_id_attr_has_type_hint(node_type_hints: Dict[str, Any]): assert "id" in node_type_hints - assert int == node_type_hints.get("id") + assert node_type_hints.get("id") is int def test_node_class_parent_attr_has_type_hint(node_type_hints: Dict[str, Any]): assert "parent" in node_type_hints - assert int == node_type_hints.get("parent") + assert node_type_hints.get("parent") is int def test_node_class_init_has_type_hints(): hints = get_type_hints(Node.__init__) assert "id" in hints - assert int == hints.get("id") + assert hints.get("id") is int assert "parent" in hints - assert int == hints.get("parent") + assert hints.get("parent") is int def test_node_class_init_raises_given_non_integer(): @@ -48,8 +47,8 @@ def test_node_init_holds_id_parent_attrs(): assert getattr(node, "parent", 0) == 1 -def test_node_repr_can_be_instanced_and_is_equals_to_node(): - node: Node = conftest.generate_random_node() +def test_node_repr_can_be_instanced_and_is_equals_to_node(generate_random_node): + node: Node = generate_random_node node_repr = repr(node) node_from_repr = eval(node_repr) assert node_from_repr.id == node.id