From 862cafb653cfaada29a741c89daa7d3509042714 Mon Sep 17 00:00:00 2001 From: viclpk Date: Tue, 21 Jan 2025 20:25:56 -0300 Subject: [PATCH] Implement Node and NodeManager classes The Node class represents a node with an 'id' and 'parent', ensuring valid values through type hints and validation. It includes methods for initialization, string representation, and equality comparison. The NodeManager class manages a list of Node objects, with methods for retrieving, adding, and removing nodes. It includes a cascade removal feature, which ensures that nodes and their children are properly removed from the list. The class also validates that the input is a list of Node instances and prevents mutations to the original list. --- nodes/manager.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++-- nodes/node.py | 25 +++++++++++++++++++--- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/nodes/manager.py b/nodes/manager.py index b3c1178..cccbf44 100644 --- a/nodes/manager.py +++ b/nodes/manager.py @@ -1,5 +1,55 @@ -# Create here the NodeManager Class +from typing import List +import copy +import sys +import os +sys.path.append(os.path.dirname(os.path.abspath(__file__))) +from nodes.node import Node class NodeManager: - pass + nodes: List[Node] # Adding the type hint for the 'nodes' attribute + + # Initializes the NodeManager with a list of Node objects. + # Ensures that the input is a list of Node instances. + def __init__(self, nodes: List[Node]): + if not isinstance(nodes, list): + raise ValueError("The nodes must be a list of Node objects.") + + if not all(isinstance(node, Node) for node in nodes): + raise ValueError("The nodes must be a list of Node objects.") + + #This object must not mutate the received List + self.nodes: List[Node] = copy.deepcopy(nodes) + + # Returns the number of nodes in the NodeManager. + def __len__(self) -> int: + return len(self.nodes) + + # Retrieves a Node object by index from the nodes list. + def __getitem__(self, index: int) -> Node: + return self.nodes[index] + + + # Removes a Node from the manager. + # Raises a ValueError if the node is not in the list of nodes. + def remove(self, node: Node) -> None: + if node not in self.nodes: + raise ValueError("The node does not exist in the nodes member.") + + self.nodes.remove(node) + + + # Removes a Node and all its children (cascade removal). + # If the node has children, they are recursively removed as well. + def remove_cascade(self, node: Node) -> None: + #Check if the node exists in the list + if node not in self.nodes: + raise ValueError("The node does not exist in the nodes member.") + + # First remove the node itself + self.remove(node) + + # Cascade removal of nodes where the parent is the removed node + to_remove = [n for n in self.nodes if n.parent == node.id] + for child in to_remove: + self.remove_cascade(child) \ No newline at end of file diff --git a/nodes/node.py b/nodes/node.py index 644ab4e..c380c23 100644 --- a/nodes/node.py +++ b/nodes/node.py @@ -1,5 +1,24 @@ -# Create here the Node Class +class Node: + id: int # Adding the type hint for the 'id' attribute + parent: int # Adding the type hint for the 'parent' attribute -class Node: - pass + # Initializes the Node with id and parent, ensuring valid values. + def __init__(self, id: int, parent: int): + if not isinstance(id, int) or not isinstance(parent, int): + raise ValueError("Both id and parent must be integers.") + if parent >= id: + raise ValueError("The parent cannot be greater than or equal to the id.") + + self.id: int = id + self.parent: int = parent + + # Returns a string representation of the Node. + def __repr__(self): + return f"Node({self.id}, {self.parent})" + + # Compares two Nodes based on id and parent. + def __eq__(self, other): + if isinstance(other, Node): + return self.id == other.id and self.parent == other.parent + return False \ No newline at end of file