Passed
Push — master ( bd4b5e...fa3bf6 )
by P.R.
01:57
created

Port   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Test Coverage

Coverage 82.69%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 23
c 2
b 0
f 0
dl 0
loc 152
ccs 43
cts 52
cp 0.8269
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A add_dependency() 0 10 2
B replace_node_dependency() 0 22 6
A get_dependencies_ports() 0 13 4
B __init__() 0 32 1
B purge() 0 19 5
A get_implicit_dependencies_ports() 0 7 1
B generate_xml() 0 25 4
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:
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 I 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
        # -- @todo Validate owner of port and owner of this port.
65
66 1
        if port not in self.predecessors:
67 1
            self.predecessors.append(port)
68
69
    # ------------------------------------------------------------------------------------------------------------------
70 1
    def generate_xml(self, parent):
71
        """
72
        Generates the XML element for this port.
73
74
        :param xml.etree.ElementTree.Element parent: The parent XML element.
75
        """
76 1
        port = SubElement(parent, 'Port')
77
78 1
        port_name = SubElement(port, 'PortName')
79 1
        port_name.text = self.port_name
80
81 1
        if self.predecessors:
82 1
            dependencies_element = SubElement(port, 'Dependencies')
83
84 1
            for predecessor in self.predecessors:
85 1
                dependency = SubElement(dependencies_element, 'Dependency')
86
87 1
                node_name = SubElement(dependency, 'NodeName')
88 1
                if predecessor.node == self.node.parent:
89 1
                    node_name.text = self.NODE_SELF_NAME
90
                else:
91 1
                    node_name.text = predecessor.node.name
92
93 1
                port_name = SubElement(dependency, 'PortName')
94 1
                port_name.text = predecessor.port_name
95
96
    # ------------------------------------------------------------------------------------------------------------------
97 1
    def get_dependencies_ports(self, ports, level):
98
        """
99
100
        :param list[enarksh_lib.xml_generator.port.Port.Port] ports:
101
        :param int                                            level:
102
103
        :rtype: list[]
104
        """
105 1
        for port in self.predecessors:
106 1
            if port not in ports:
107 1
                if level:
108 1
                    ports.append(port)
109 1
                port.get_implicit_dependencies_ports(ports, level + 1)
110
111
    # ------------------------------------------------------------------------------------------------------------------
112 1
    @abc.abstractmethod
113
    def get_implicit_dependencies_ports(self, ports, level):
114
        """
115
        :param list[enarksh_lib.xml_generator.port.Port.Port] ports:
116
        :param int                                            level:
117
        """
118
        raise NotImplementedError()
119
120
    # ------------------------------------------------------------------------------------------------------------------
121 1
    def purge(self):
122
        """
123
        Removes dependencies from this port that are implicit dependencies (via one or more predecessors).
124
        """
125
        # Get all implicit dependencies ports.
126 1
        implicit_dependencies = []
127 1
        for port in self.predecessors:
128 1
            port.get_implicit_dependencies_ports(implicit_dependencies, 0)
129
130
        # Create a new dependency array without implicit dependencies.
131 1
        direct_dependencies = []
132 1
        for port in self.predecessors:
133 1
            if port not in implicit_dependencies:
134
135
                # Prevent duplicate dependencies.
136 1
                if port not in direct_dependencies:
137 1
                    direct_dependencies.append(port)
138
139 1
        self.predecessors = direct_dependencies
140
141
    # ------------------------------------------------------------------------------------------------------------------
142 1
    def replace_node_dependency(self, node_name, dependencies):
143
        """
144
        Replaces any dependency of this port on node 'node_name' with dependencies 'dependencies'.
145
146
        :param str    node_name:
147
        :param list[] dependencies:
148
        """
149
        obsolete = []
150
151
        # Find any predecessor that depends on node 'node_name'.
152
        for index, port in enumerate(self.predecessors):
153
            if port.node.name == node_name:
154
                obsolete.append(index)
155
156
        if obsolete:
157
            # Remove all dependencies of node 'node_name'.
158
            for index in obsolete:
159
                self.predecessors.pop(index)
160
161
            # And replace those dependencies with 'dependencies'.
162
            for dep in dependencies:
163
                self.predecessors.append(dep)
164
165
# ----------------------------------------------------------------------------------------------------------------------
166