exabgp.configuration.static.mpls   A
last analyzed

Complexity

Total Complexity 40

Size/Duplication

Total Lines 150
Duplicated Lines 8.67 %

Importance

Changes 0
Metric Value
eloc 113
dl 13
loc 150
rs 9.2
c 0
b 0
f 0
wmc 40

4 Functions

Rating   Name   Duplication   Size   Complexity  
A label() 0 14 4
B route_distinguisher() 13 23 7
C prefix_sid_srv6() 0 30 9
F prefix_sid() 0 53 20

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like exabgp.configuration.static.mpls often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# encoding: utf-8
2
"""
3
inet/parser.py
4
5
Created by Thomas Mangin on 2015-06-04.
6
Copyright (c) 2009-2017 Exa Networks. All rights reserved.
7
License: 3-clause BSD. (See the COPYRIGHT file)
8
"""
9
10
from struct import pack
11
12
from exabgp.bgp.message.update.nlri.qualifier import Labels
13
from exabgp.bgp.message.update.nlri.qualifier import RouteDistinguisher
14
from exabgp.bgp.message.update.attribute.sr.prefixsid import PrefixSid
15
from exabgp.bgp.message.update.attribute.sr.labelindex import SrLabelIndex
16
from exabgp.bgp.message.update.attribute.sr.ipv6sid import SrV6Sid
17
from exabgp.bgp.message.update.attribute.sr.srv6vpnsid import Srv6VpnSid
18
from exabgp.bgp.message.update.attribute.sr.srv6l3vpnsid import Srv6L3vpnSid
19
from exabgp.bgp.message.update.attribute.sr.srgb import SrGb
20
21
22
def label(tokeniser):
23
    labels = []
24
    value = tokeniser()
25
26
    if value == '[':
27
        while True:
28
            value = tokeniser()
29
            if value == ']':
30
                break
31
            labels.append(int(value))
32
    else:
33
        labels.append(int(value))
34
35
    return Labels(labels)
36
37
38
def route_distinguisher(tokeniser):
39
    data = tokeniser()
40
41
    separator = data.find(':')
42
    if separator > 0:
43
        prefix = data[:separator]
44
        suffix = int(data[separator + 1 :])
45
46 View Code Duplication
    if '.' in prefix:
0 ignored issues
show
introduced by
The variable prefix does not seem to be defined in case separator > 0 on line 42 is False. Are you sure this can never be the case?
Loading history...
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
47
        data = [bytes([0, 1])]
48
        data.extend([bytes([int(_)]) for _ in prefix.split('.')])
49
        data.extend([bytes([suffix >> 8]), bytes([suffix & 0xFF])])
0 ignored issues
show
introduced by
The variable suffix does not seem to be defined in case separator > 0 on line 42 is False. Are you sure this can never be the case?
Loading history...
50
        rtd = b''.join(data)
51
    else:
52
        number = int(prefix)
53
        if number < pow(2, 16) and suffix < pow(2, 32):
54
            rtd = bytes([0, 0]) + pack('!H', number) + pack('!L', suffix)
55
        elif number < pow(2, 32) and suffix < pow(2, 16):
56
            rtd = bytes([0, 2]) + pack('!L', number) + pack('!H', suffix)
57
        else:
58
            raise ValueError('invalid route-distinguisher %s' % data)
59
60
    return RouteDistinguisher(rtd)
61
62
63
# [ 300, [ ( 800000,100 ), ( 1000000,5000 ) ] ]
64
def prefix_sid(tokeniser):
65
    sr_attrs = []
66
    srgbs = []
67
    srgb_data = []
68
    value = tokeniser()
69
    get_range = False
70
    consume_extra = False
71
    try:
72
        if value == '[':
73
            label_sid = tokeniser()
74
            while True:
75
                value = tokeniser()
76
                if value == '[':
77
                    consume_extra = True
78
                    continue
79
                if value == ',':
80
                    continue
81
                if value == '(':
82
                    while True:
83
                        value = tokeniser()
84
                        if value == ')':
85
                            break
86
                        if value == ',':
87
                            get_range = True
88
                            continue
89
                        if get_range:
90
                            srange = value
91
                            get_range = False
92
                        else:
93
                            base = value
94
                if value == ')':
95
                    srgb_data.append((base, srange))
0 ignored issues
show
introduced by
The variable base does not seem to be defined for all execution paths.
Loading history...
introduced by
The variable srange does not seem to be defined for all execution paths.
Loading history...
96
                    continue
97
                if value == ']':
98
                    break
99
        if consume_extra:
100
            tokeniser()
101
    except Exception as e:
102
        raise ValueError('could not parse BGP PrefixSid attribute: {}'.format(e))
103
104
    if int(label_sid) < pow(2, 32):
0 ignored issues
show
introduced by
The variable label_sid does not seem to be defined in case value == '[' on line 72 is False. Are you sure this can never be the case?
Loading history...
105
        sr_attrs.append(SrLabelIndex(int(label_sid)))
106
107
    for srgb in srgb_data:
108
        if len(srgb) == 2 and int(srgb[0]) < pow(2, 24) and int(srgb[1]) < pow(2, 24):
109
            srgbs.append((int(srgb[0]), int(srgb[1])))
110
        else:
111
            raise ValueError('could not parse SRGB tupple')
112
113
    if srgbs:
114
        sr_attrs.append(SrGb(srgbs))
115
116
    return PrefixSid(sr_attrs)
117
118
119
# { ipv6 <ipv6-addr> | vpn <ipv6-addr> | l3vpn <ipv6-addr> }
120
def prefix_sid_srv6(tokeniser):
121
    sr_attrs = []
122
    value = tokeniser()
123
    try:
124
        if value == '(':
125
            value = tokeniser()
126
            if value == 'ipv6':
127
                value = tokeniser()
128
                sr_attrs.append(SrV6Sid(value))
129
                value = tokeniser()
130
                if value == ')':
131
                    return PrefixSid(sr_attrs)
132
133
            if value == 'vpn':
134
                value = tokeniser()
135
                sr_attrs.append(Srv6VpnSid(value))
136
                value = tokeniser()
137
                if value == ')':
138
                    return PrefixSid(sr_attrs)
139
140
            if value == 'l3vpn':
141
                value = tokeniser()
142
                sr_attrs.append(Srv6L3vpnSid(value))
143
                value = tokeniser()
144
                if value == ')':
145
                    return PrefixSid(sr_attrs)
146
147
        raise Exception("format error")
148
    except Exception as e:
149
        raise ValueError('could not parse BGP PrefixSid Srv6 attribute: {}'.format(e))
150