Passed
Push — master ( c58024...645373 )
by Vinicius
01:59 queued 17s
created

build.utils   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 112
Duplicated Lines 0 %

Test Coverage

Coverage 73.52%

Importance

Changes 0
Metric Value
wmc 26
eloc 71
dl 0
loc 112
rs 10
c 0
b 0
f 0
ccs 50
cts 68
cp 0.7352

15 Methods

Rating   Name   Duplication   Size   Complexity  
A Flows.sort() 0 4 3
A Flows.add_flow() 0 5 2
A Flows.get_flows() 0 5 2
A IPv6AddressWithMask.__repr__() 0 2 1
A IPv6AddressWithMask.__init__() 0 4 1
A IPv4AddressWithMask.as_dot_string() 0 12 3
A Flows.__init__() 0 3 1
A IPv4AddressWithMask.__str__() 0 2 1
A IPv4AddressWithMask.unpack() 0 4 1
A Flows.clear() 0 3 1
A IPv6AddressWithMask.__str__() 0 2 1
A IPv6AddressWithMask.as_comma_string() 0 16 4
A IPv4AddressWithMask.__init__() 0 4 1
A IPv4AddressWithMask.__repr__() 0 2 1
A IPv6AddressWithMask.unpack() 0 4 1

1 Function

Rating   Name   Duplication   Size   Complexity  
A format_request() 0 6 2
1
"""Utility classes and definitions."""
2 1
import struct
3
4 1
from napps.amlight.sdntrace.shared.singleton import Singleton
5
6
7 1
class Flows(metaclass=Singleton):
8
    """Class to store all flows installed in the switches."""
9
10 1
    def __init__(self):
11
        """Institate an empty flow dict."""
12
        self._flows = {}
13
14 1
    def clear(self, dpid):
15
        """Clear the list of flows of the given switch."""
16
        self._flows[dpid] = []
17
18 1
    def add_flow(self, dpid, flow):
19
        """Add a flow to the list of flows of the given switch."""
20
        if dpid not in self._flows:
21
            self._flows[dpid] = []
22
        self._flows[dpid].append(flow)
23
24 1
    def get_flows(self, dpid):
25
        """Return the list of flows of the given switch."""
26
        if dpid in self._flows:
27
            return self._flows[dpid]
28
        return None
29
30 1
    def sort(self, dpid):
31
        """Sort the list of flows of the given switch by priority."""
32
        if dpid in self._flows:
33
            self._flows[dpid].sort(key=lambda f: f.priority, reverse=True)
34
35
36 1
class IPv4AddressWithMask:
37
    """Class to represent an IPv4 address with netmask."""
38
39 1
    def __init__(self, address=0, netmask=0):
40
        """Instatiate with given ip address and netmask."""
41 1
        self.address = address
42 1
        self.netmask = netmask
43
44 1
    def __repr__(self):
45
        return f'<{self.__class__.__name__}: {self.as_dot_string()}>'
46
47 1
    def __str__(self):
48
        return self.as_dot_string()
49
50 1
    def as_dot_string(self):
51
        # pylint: disable=W0631
52
        """Represent an IPv4 address with mask as 0.0.0.0/0."""
53 1
        packed = struct.pack('!I', self.address)
54 1
        unpacked_bytes = struct.unpack('!4B', packed)
55 1
        address = '.'.join([str(x) for x in unpacked_bytes])
56 1
        for i in range(1, 33):
57 1
            stripped_mask = self.netmask >> i << i
58 1
            if stripped_mask != self.netmask:
59 1
                break
60 1
        mask = 33 - i
0 ignored issues
show
introduced by
The variable i does not seem to be defined in case the for loop on line 56 is not entered. Are you sure this can never be the case?
Loading history...
61 1
        return f'{address}/{mask}'
62
63 1
    def unpack(self, buffer, start=0):
64
        """Unpack IPv4 address and netmask."""
65
        self.address, self.netmask = struct.unpack('!2I',
66
                                                   buffer[start:start+8])
67
68
69 1
class IPv6AddressWithMask:
70
    """Class to represent an IPv6 address with netmask."""
71
72 1
    def __init__(self, address=0, netmask=0):
73
        """Instantiate with given ip address and netmask."""
74 1
        self.address = address
75 1
        self.netmask = netmask
76
77 1
    def __repr__(self):
78
        return f'<{self.__class__.__name__}: {self.as_comma_string()}>'
79
80 1
    def __str__(self):
81
        return self.as_comma_string()
82
83 1
    def as_comma_string(self):
84
        # pylint: disable=W0631
85
        """Represent an IPv6 address with mask as ffff::0/0."""
86 1
        address = []
87 1
        addrs = divmod(self.address, 2**64)
88 1
        for addr in addrs:
89 1
            packed = struct.pack('!Q', addr)
90 1
            unpacked_bytes = struct.unpack('!4H', packed)
91 1
            address.append(':'.join([f'{b:x}' for b in unpacked_bytes]))
92 1
        address = ':'.join(address)
93 1
        for i in range(1, 129):
94 1
            stripped_mask = self.netmask >> i << i
95 1
            if stripped_mask != self.netmask:
96 1
                break
97 1
        mask = 129 - i
0 ignored issues
show
introduced by
The variable i does not seem to be defined in case the for loop on line 93 is not entered. Are you sure this can never be the case?
Loading history...
98 1
        return f'{address}/{mask}'
99
100 1
    def unpack(self, buffer, start=0):
101
        """Unpack IPv6 address and mask."""
102
        self.address = int.from_bytes(buffer[start:start+16], 'big')
103
        self.netmask = int.from_bytes(buffer[start+16:start+32], 'big')
104
105
106 1
def format_request(request):
107
    """Format user request to match function format."""
108 1
    args = {}
109 1
    for key, value in request.items():
110
        args[key] = value
111
    return args
112