Completed
Push — master ( f8c35a...0dc7c6 )
by Thomas
14:34
created

extract_neighbors()   C

Complexity

Conditions 11

Size

Total Lines 49
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 35
nop 1
dl 0
loc 49
rs 5.4
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like exabgp.reactor.api.command.limit.extract_neighbors() 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
command/limit.py
4
5
Created by Thomas Mangin on 2017-07-01.
6
Copyright (c) 2009-2017 Exa Networks. All rights reserved.
7
License: 3-clause BSD. (See the COPYRIGHT file)
8
"""
9
10
import re
11
12
13
def extract_neighbors (command):
14
	"""Return a list of neighbor definition : the neighbor definition is a list of string which are in the neighbor indexing string"""
15
	# This function returns a list and a string
16
	# The first list contains parsed neighbor to match against our defined peers
17
	# The string is the command to be run for those peers
18
	# The parsed neighbor is a list of the element making the neighbor string so each part can be checked against the neighbor name
19
20
	returned = []
21
22
	neiremain = command.split(' ', 1)
23
	if len(neiremain) == 1:
24
		return [], command
25
26
	neighbor, remaining = neiremain
27
	if neighbor != 'neighbor':
28
		return [],command
29
30
	ipcmd = remaining.split(' ', 1)
31
	if len(ipcmd) == 1:
32
		return [], remaining
33
	ip, command = ipcmd
34
	definition = ['neighbor %s' % (ip)]
35
36
	if ' ' not in command:
37
		return definition,command
38
39
	while True:
40
		try:
41
			key,value,remaining = command.split(' ',2)
42
		except ValueError:
43
			# single word command
44
			keyval = command.split(' ', 1)
45
			if len(keyval) == 1:
46
				return definition,command
47
			key, value = keyval
48
		# we have further filtering
49
		if key == ',':
50
			returned.append(definition)
51
			_,command = command.split(' ',1)
52
			definition = []
53
			continue
54
		if key not in ['neighbor','local-ip','local-as','peer-as','router-id','family-allowed']:
55
			if definition:
56
				returned.append(definition)
57
			break
58
		definition.append('%s %s' % (key,value))
59
		command = remaining
60
61
	return returned,command
62
63
64
def match_neighbor (description, name):
65
	for string in description:
66
		if re.search(r'(^|\s)%s($|\s|,)' % re.escape(string), name) is None:
67
			return False
68
	return True
69
70
71
def match_neighbors (peers,descriptions):
72
	"""Return the sublist of peers matching the description passed, or None if no description is given"""
73
	if not descriptions:
74
		return peers
75
76
	returned = []
77
	for peer_name in peers:
78
		for description in descriptions:
79
			if match_neighbor(description, peer_name):
80
				if peer_name not in returned:
81
					returned.append(peer_name)
82
	return returned
83