Port   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Test Coverage

Coverage 86%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 23
c 3
b 0
f 0
dl 0
loc 150
ccs 43
cts 50
cp 0.86
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
B __init__() 0 32 1
A add_dependency() 0 8 2
B replace_node_dependency() 0 22 6
A get_dependencies_ports() 0 13 4
B purge() 0 19 5
B generate_xml() 0 25 4
A get_implicit_dependencies_ports() 0 7 1
1
"""
2
Enarksh
3
4
Copyright 2015-2016 Set Based IT Consultancy
5
6
Licence MIT
7
"""
8 1
import abc
9 1
from xml.etree.ElementTree import SubElement
10
11
12 1
class Port(metaclass=abc.ABCMeta):
13
    """
14
    Class Port
15
    Class for generating XML messages for elements of type 'InputPortType' and 'OutputPortType'.
16
    """
17
18 1
    NODE_SELF_NAME = '.'  # -- @todo Discuss about this constant, because we can't import Node.
19
    """
20
    Token for node self.
21
    """
22
23
    # ------------------------------------------------------------------------------------------------------------------
24 1
    def __init__(self, node, port_name):
25
        """
26
        Object constructor.
27
        """
28
29 1
        self.node = node
30
        """
31
        The node of which this port is a port.
32
33
        :type: enarksh_lib.xml_generator.node.Node.Node
34
        """
35
36 1
        self.port_name = port_name
37
        """
38
        The name of this port.
39
40
        :type: str
41
        """
42
43 1
        self.predecessors = []
44
        """
45
        The dependencies of this port.
46
47
        :type: list[enarksh_lib.xml_generator.port.Port.Port]
48
        """
49
50 1
        self.successors = []
51 1
        """
52
        The dependants of this port.
53
54
        :type: list[enarksh_lib.xml_generator.port.Port.Port]
55
        """
56
57
    # ------------------------------------------------------------------------------------------------------------------
58 1
    def add_dependency(self, port):
59
        """
60
        Add a port as a dependency of this port.
61
62
        :param enarksh_lib.xml_generator.port.Port.Port port: The port that depends on this port.
63
        """
64
        if port not in self.predecessors:
65
            self.predecessors.append(port)
66 1
67 1
    # ------------------------------------------------------------------------------------------------------------------
68
    def generate_xml(self, parent):
69
        """
70 1
        Generates the XML element for this port.
71
72
        :param xml.etree.ElementTree.Element parent: The parent XML element.
73
        """
74
        port = SubElement(parent, 'Port')
75
76 1
        port_name = SubElement(port, 'PortName')
77
        port_name.text = self.port_name
78 1
79 1
        if self.predecessors:
80
            dependencies_element = SubElement(port, 'Dependencies')
81 1
82 1
            for predecessor in self.predecessors:
83
                dependency = SubElement(dependencies_element, 'Dependency')
84 1
85 1
                node_name = SubElement(dependency, 'NodeName')
86
                if predecessor.node == self.node.parent:
87 1
                    node_name.text = self.NODE_SELF_NAME
88 1
                else:
89 1
                    node_name.text = predecessor.node.name
90
91 1
                port_name = SubElement(dependency, 'PortName')
92
                port_name.text = predecessor.port_name
93 1
94 1
    # ------------------------------------------------------------------------------------------------------------------
95
    def get_dependencies_ports(self, ports, level):
96
        """
97 1
98
        :param list[enarksh_lib.xml_generator.port.Port.Port] ports:
99
        :param int                                            level:
100
101
        :rtype: list[]
102
        """
103
        for port in self.predecessors:
104
            if port not in ports:
105 1
                if level:
106 1
                    ports.append(port)
107 1
                port.get_implicit_dependencies_ports(ports, level + 1)
108 1
109 1
    # ------------------------------------------------------------------------------------------------------------------
110
    @abc.abstractmethod
111
    def get_implicit_dependencies_ports(self, ports, level):
112 1
        """
113
        :param list[enarksh_lib.xml_generator.port.Port.Port] ports:
114
        :param int                                            level:
115
        """
116
        raise NotImplementedError()
117
118
    # ------------------------------------------------------------------------------------------------------------------
119
    def purge(self):
120
        """
121 1
        Removes dependencies from this port that are implicit dependencies (via one or more predecessors).
122
        """
123
        # Get all implicit dependencies ports.
124
        implicit_dependencies = []
125
        for port in self.predecessors:
126 1
            port.get_implicit_dependencies_ports(implicit_dependencies, 0)
127 1
128 1
        # Create a new dependency array without implicit dependencies.
129
        direct_dependencies = []
130
        for port in self.predecessors:
131 1
            if port not in implicit_dependencies:
132 1
133 1
                # Prevent duplicate dependencies.
134
                if port not in direct_dependencies:
135
                    direct_dependencies.append(port)
136 1
137 1
        self.predecessors = direct_dependencies
138
139 1
    # ------------------------------------------------------------------------------------------------------------------
140
    def replace_node_dependency(self, node_name, dependencies):
141
        """
142 1
        Replaces any dependency of this port on node 'node_name' with dependencies 'dependencies'.
143
144
        :param str    node_name:
145
        :param list[] dependencies:
146
        """
147
        obsolete = []
148
149
        # Find any predecessor that depends on node 'node_name'.
150
        for index, port in enumerate(self.predecessors):
151
            if port.node.name == node_name:
152
                obsolete.append(index)
153
154
        if obsolete:
155
            # Remove all dependencies of node 'node_name'.
156
            for index in obsolete:
157
                self.predecessors.pop(index)
158
159
            # And replace those dependencies with 'dependencies'.
160
            for dep in dependencies:
161
                self.predecessors.append(dep)
162
163
# ----------------------------------------------------------------------------------------------------------------------
164