Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 83 additions & 1 deletion nodes/manager.py
Original file line number Diff line number Diff line change
@@ -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)
45 changes: 44 additions & 1 deletion nodes/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -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})"
6 changes: 4 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions tests/test_manager.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import pytest
from . import conftest
from typing import get_type_hints, List, Dict, Any
from nodes.manager import NodeManager
from nodes.node import Node


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():
Expand All @@ -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)


Expand Down
13 changes: 6 additions & 7 deletions tests/test_node.py
Original file line number Diff line number Diff line change
@@ -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():
Expand Down Expand Up @@ -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
Expand Down