Test Failed
Push — master ( 8ecc8b...fbff38 )
by P.R.
01:31
created

Port.get_node_name()   A

Complexity

Conditions 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
1
"""
2
Enarksh
3
4
Copyright 2015-2016 Set Based IT Consultancy
5
6
Licence MIT
7
"""
8
import abc
9
from xml.etree.ElementTree import SubElement
10
11
12
class Port:
13
    """
14
    Class Port
15
    Class for generating XML messages for elements of type 'InputPortType' and 'OutputPortType'.
16
    """
17
18
    NODE_SELF_NAME = '.'  # -- @todo Discuss about this constant, because I can't import Node.
19
    """
20
    Token for node self.
21
    """
22
23
    # ------------------------------------------------------------------------------------------------------------------
24
    def __init__(self, node, port_name):
25
        """
26
        Object constructor.
27
        """
28
29
        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
        self.port_name = port_name
37
        """
38
        The name of this port.
39
40
        :type: str
41
        """
42
43
        self._predecessors = []
44
        """
45
        The dependencies of this port.
46
47
        :type: list[enarksh_lib.xml_generator.port.Port.Port]
48
        """
49
50
        self._successors = []
51
        """
52
        The dependants of this port.
53
54
        :type: list[enarksh_lib.xml_generator.port.Port.Port]
55
        """
56
57
    # ------------------------------------------------------------------------------------------------------------------
58
    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
        if port not in self._predecessors:
67
            self._predecessors.append(port)
68
69
    # ------------------------------------------------------------------------------------------------------------------
70
    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
        port = SubElement(parent, 'Port')
77
78
        port_name = SubElement(port, 'PortName')
79
        port_name.text = self.port_name
80
81
        if self._predecessors:
82
            dependencies_element = SubElement(port, 'Dependencies')
83
84
            for predecessor in self._predecessors:
85
                dependency = SubElement(dependencies_element, 'Dependency')
86
87
                node_name = SubElement(dependency, 'NodeName')
88
                if predecessor.node == self.node.parent:
89
                    node_name.text = self.NODE_SELF_NAME
90
                else:
91
                    node_name.text = predecessor.node.name
92
93
                port_name = SubElement(dependency, 'PortName')
94
                port_name.text = self.port_name
95
96
    # ------------------------------------------------------------------------------------------------------------------
97
    def get_all_dependencies(self):
98
        """
99
        Returns all the dependencies of this port.
100
101
        :rtype: enarksh_lib.xml_generator.port.Port.Port port:
102
        """
103
        return self._predecessors
104
105
    # ------------------------------------------------------------------------------------------------------------------
106
    def get_dependencies_ports(self, ports, level):
107
        """
108
109
        :param list[enarksh_lib.xml_generator.port.Port.Port] ports:
110
        :param int                                            level:
111
112
        :rtype: list[]
113
        """
114
        for port in self._predecessors:
115
            if port not in ports:
116
                if level:
117
                    ports.append(port)
118
                port.get_implicit_dependencies_ports(ports, level + 1)
119
120
    # ------------------------------------------------------------------------------------------------------------------
121
    @abc.abstractmethod
122
    def get_implicit_dependencies_ports(self, ports, level):
123
        """
124
        :param list[enarksh_lib.xml_generator.port.Port.Port] ports:
125
        :param int                                            level:
126
        """
127
        raise NotImplementedError()
128
129
    # ------------------------------------------------------------------------------------------------------------------
130
    def purge(self):
131
        """
132
        Removes dependencies from this port that are implicit dependencies (via one or more predecessors).
133
        """
134
        # Get all implicit dependencies ports.
135
        implicit_dependencies = []
136
        for port in self._predecessors:
137
            port.get_implicit_dependencies_ports(implicit_dependencies, 0)
138
139
        # Create a new dependency array without implicit dependencies.
140
        direct_dependencies = []
141
        for port in self._predecessors:
142
            if port not in implicit_dependencies:
143
144
                # Prevent duplicate dependencies.
145
                if port not in direct_dependencies:
146
                    direct_dependencies.append(port)
147
148
        self._predecessors = direct_dependencies
149
150
    # ------------------------------------------------------------------------------------------------------------------
151
    def replace_node_dependency(self, node_name, dependencies):
152
        """
153
        Replaces any dependency of this port on node 'node_name' with dependencies 'dependencies'.
154
155
        :param str    node_name:
156
        :param list[] dependencies:
157
        """
158
        obsolete = []
159
160
        # Find any predecessor that depends on node 'node_name'.
161
        for index, port in enumerate(self._predecessors):
162
            if port.node.name == node_name:
163
                obsolete.append(index)
164
165
        if obsolete:
166
            # Remove all dependencies of node 'node_name'.
167
            for index in obsolete:
168
                self._predecessors.pop(index)
169
170
            # And replace those dependencies with 'dependencies'.
171
            for dep in dependencies:
172
                self._predecessors.append(dep)
173
174
# ----------------------------------------------------------------------------------------------------------------------
175