exabgp.configuration.static.route()   F
last analyzed

Complexity

Conditions 15

Size

Total Lines 51
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 38
nop 1
dl 0
loc 51
rs 2.9998
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like exabgp.configuration.static.route() 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/__init__.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 exabgp.configuration.static.route import ParseStaticRoute
11
from exabgp.configuration.static.parser import prefix
12
13
from exabgp.configuration.announce.path import AnnouncePath
14
from exabgp.configuration.announce.label import AnnounceLabel
15
from exabgp.configuration.announce.vpn import AnnounceVPN
16
17
from exabgp.protocol.ip import IP
18
from exabgp.protocol.family import SAFI
19
20
from exabgp.bgp.message import OUT
21
from exabgp.bgp.message.update.nlri import CIDR
22
from exabgp.bgp.message.update.nlri import INET
23
from exabgp.bgp.message.update.nlri import Label
24
from exabgp.bgp.message.update.nlri import IPVPN
25
26
from exabgp.bgp.message.update.attribute import Attributes
27
28
from exabgp.rib.change import Change
29
30
from exabgp.configuration.static.mpls import label
31
from exabgp.configuration.static.mpls import route_distinguisher
32
33
34
class ParseStatic(ParseStaticRoute):
35
    syntax = 'route <ip>/<netmask> %s;' % ' '.join(ParseStaticRoute.definition)
36
37
    action = dict(ParseStaticRoute.action)
38
39
    name = 'static'
40
41
    def __init__(self, tokeniser, scope, error):
42
        ParseStaticRoute.__init__(self, tokeniser, scope, error)
43
44
    def clear(self):
45
        return True
46
47
    def pre(self):
48
        return True
49
50
    def post(self):
51
        return True
52
53
54
@ParseStatic.register('route', 'append-route')
55
def route(tokeniser):
56
    action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW
57
    ipmask = prefix(tokeniser)
58
    check = lambda change, afi: True
59
60
    if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens:
61
        nlri = IPVPN(IP.toafi(ipmask.top()), SAFI.mpls_vpn, action)
62
        check = AnnounceVPN.check
63
    elif 'label' in tokeniser.tokens:
64
        nlri = Label(IP.toafi(ipmask.top()), SAFI.nlri_mpls, action)
65
        check = AnnounceLabel.check
66
    else:
67
        nlri = INET(IP.toafi(ipmask.top()), IP.tosafi(ipmask.top()), action)
68
        check = AnnouncePath.check
69
70
    nlri.cidr = CIDR(ipmask.pack(), ipmask.mask)
71
72
    change = Change(nlri, Attributes())
73
74
    while True:
75
        command = tokeniser()
76
77
        if not command:
78
            break
79
80
        if command == 'label':
81
            nlri.labels = label(tokeniser)
82
            continue
83
84
        if command == 'rd' or command == 'route-distinguisher':
85
            nlri.rd = route_distinguisher(tokeniser)
86
            continue
87
88
        action = ParseStatic.action.get(command, '')
89
90
        if action == 'attribute-add':
91
            change.attributes.add(ParseStatic.known[command](tokeniser))
92
        elif action == 'nlri-set':
93
            change.nlri.assign(ParseStatic.assign[command], ParseStatic.known[command](tokeniser))
94
        elif action == 'nexthop-and-attribute':
95
            nexthop, attribute = ParseStatic.known[command](tokeniser)
96
            change.nlri.nexthop = nexthop
97
            change.attributes.add(attribute)
98
        else:
99
            raise ValueError('unknown command "%s"' % command)
100
101
    if not check(change, nlri.afi):
102
        raise ValueError('invalid route (missing next-hop, label or rd ?)')
103
104
    return list(ParseStatic.split(change))
105
106
107
@ParseStatic.register('attributes', 'append-route')
108
def attributes(tokeniser):
109
    action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW
110
    ipmask = prefix(lambda: tokeniser.tokens[-1])
111
    tokeniser.afi = ipmask.afi
112
113
    if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens:
114
        nlri = IPVPN(IP.toafi(ipmask.top()), SAFI.mpls_vpn, action)
115
    elif 'label' in tokeniser.tokens:
116
        nlri = Label(IP.toafi(ipmask.top()), SAFI.nlri_mpls, action)
117
    else:
118
        nlri = INET(IP.toafi(ipmask.top()), IP.tosafi(ipmask.top()), action)
119
120
    nlri.cidr = CIDR(ipmask.pack(), ipmask.mask)
121
    attr = Attributes()
122
123
    labels = None
124
    rd = None
125
126
    while True:
127
        command = tokeniser()
128
129
        if not command:
130
            return []
131
132
        if command == 'nlri':
133
            break
134
135
        if command == 'label':
136
            labels = label(tokeniser)
137
            continue
138
139
        if command == 'rd' or command == 'route-distinguisher':
140
            rd = route_distinguisher(tokeniser)
141
            continue
142
143
        action = ParseStatic.action[command]
144
145
        if action == 'attribute-add':
146
            attr.add(ParseStatic.known[command](tokeniser))
147
        elif action == 'nlri-set':
148
            nlri.assign(ParseStatic.assign[command], ParseStatic.known[command](tokeniser))
149
        elif action == 'nexthop-and-attribute':
150
            nexthop, attribute = ParseStatic.known[command](tokeniser)
151
            nlri.nexthop = nexthop
152
            attr.add(attribute)
153
        else:
154
            raise ValueError('unknown command "%s"' % command)
155
156
    changes = []
157
    while True:
158
        peeked_nlri = tokeniser.peek()
159
        if not peeked_nlri:
160
            break
161
162
        ipmask = prefix(tokeniser)
163
        new = Change(nlri.__class__(nlri.afi, nlri.safi, OUT.UNSET), attr)
164
        new.nlri.cidr = CIDR(ipmask.pack(), ipmask.mask)
165
        if labels:
166
            new.nlri.labels = labels
167
        if rd:
168
            new.nlri.rd = rd
169
        new.nlri.nexthop = nlri.nexthop
170
        changes.append(new)
171
172
    return changes
173