Skip to content

Commit b7da9da

Browse files
BishalsarangBishal Sarangkoti
authored and
Bishal Sarangkoti
committed
feat-custom-edge: Add custom edge class for edge operations
1 parent b678cd8 commit b7da9da

File tree

4 files changed

+133
-4
lines changed

4 files changed

+133
-4
lines changed

tests/test_edge.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from visualiser import Edge, Node
2+
3+
"""
4+
Test case class for nodes
5+
"""
6+
7+
8+
class TestEdge:
9+
def test_create_new_edge(self):
10+
# Create Node
11+
A = Node('A', color='red', style='filled')
12+
B = Node('B', label='B label', color='red', style='filled')
13+
14+
# Create Edge
15+
edge = Edge(A, B, label='Test Label')
16+
17+
assert edge.label == 'Test Label'
18+
assert edge.source_node.label == 'A'
19+
assert edge.source_node == A

visualiser/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Version of the recursion-visualiser
22
__version__ = "1.0.1"
33

4-
from .node import Node
4+
# Maintain this order to avoid circular import
5+
# because we are using Node inside Edge for type annotations.
6+
from .node import Node
7+
from .edge import Edge
58
from visualiser import *

visualiser/edge.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import copy
2+
3+
4+
from visualiser import Node
5+
class Edge:
6+
7+
def __init__(self, source_node: Node, destination_node: Node, label: str = '',
8+
**attrs: str) -> None:
9+
# TODO: Remove copy after finding a better way to do this.
10+
self._source_node = copy.deepcopy(source_node)
11+
self._destination_node = copy.deepcopy(destination_node)
12+
13+
self._label = label
14+
self._attrs = attrs
15+
16+
@property
17+
def label(self) -> str:
18+
"""
19+
Get label for edge.
20+
:return: str
21+
"""
22+
return self._label
23+
24+
@label.setter
25+
def label(self, _label: str) -> None:
26+
"""
27+
Set label for edge.
28+
:param _label: str
29+
"""
30+
self._label = _label
31+
32+
@property
33+
def source_node(self) -> Node:
34+
"""
35+
Get source node
36+
:return: Node
37+
"""
38+
return self._source_node
39+
40+
@source_node.setter
41+
def source_node(self, _source_node: Node) -> None:
42+
"""
43+
Set source node.
44+
:param _source_node: Node
45+
"""
46+
self._source_node = _source_node
47+
48+
@property
49+
def destination_node(self) -> Node:
50+
"""
51+
Get destination node.
52+
:return: Node
53+
"""
54+
return self._destination_node
55+
56+
@destination_node.setter
57+
def destination_node(self, _destination_node: Node) -> None:
58+
"""
59+
Sets destination node.
60+
:param _destination_node: Node
61+
"""
62+
self._destination_node = _destination_node
63+
64+
def get_attribute(self, key: str) -> str:
65+
"""
66+
Get attribute for edge.
67+
:param key: str
68+
:return: The value of attribute with key
69+
"""
70+
return self._attrs.get(key)
71+
72+
def set_attribute(self, key: str, value: str) -> None:
73+
"""
74+
Set attribute for edge
75+
:param key: str
76+
:param value: str
77+
"""
78+
self._attrs[key] = value
79+
80+
def remove_attribute(self, key: str) -> None:
81+
"""
82+
Remove attribute from edge.
83+
:param key: str
84+
"""
85+
del self._attrs[key]
86+
87+
def get_attributes_string(self) -> str:
88+
"""
89+
Get attributes string enclosed in []
90+
:return:
91+
"""
92+
if len(self._label) == 0:
93+
return '[' + ', '.join([f'{key}="{value}"' for key, value in self._attrs.items()]) + ']'
94+
95+
return '[' + f'label="{self._label}", ' + ', '.join(
96+
[f'{key}="{value}"' for key, value in self._attrs.items()]) + ']'
97+
98+
def to_string(self) -> str:
99+
"""
100+
Converts dot string equivalent of the current edge.
101+
:return: Str
102+
"""
103+
return f'{self._source_node.name} -> {self._destination_node.name} {self.get_attributes_string()}'

visualiser/node.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
12
class Node:
23
def __init__(self, name, label='', **attrs):
34
# TODO: Add support for initialization of attributes from attribute dict
4-
self._name = name
5+
self._name = name
56
self._attrs = attrs
67

78
if len(label) == 0:
@@ -12,6 +13,9 @@ def __init__(self, name, label='', **attrs):
1213
def __repr__(self):
1314
return f"Node('{self.name}')"
1415

16+
def __eq__(self, other):
17+
return self.to_string() == other.to_string()
18+
1519
@property
1620
def name(self):
1721
return self._name
@@ -29,7 +33,7 @@ def label(self, _label):
2933
self._label = _label
3034

3135
def get_attribute(self, key):
32-
return self._attrs[key]
36+
return self._attrs.get(key)
3337

3438
def set_attribute(self, key, value):
3539
self._attrs[key] = value
@@ -42,4 +46,4 @@ def get_attributes_string(self):
4246
[f'{key}="{value}"' for key, value in self._attrs.items()]) + '];'
4347

4448
def to_string(self):
45-
return f'{self.name} {self.get_attributes_string()}'
49+
return f'{self.name} {self.get_attributes_string()}'

0 commit comments

Comments
 (0)