Test Failed
Pull Request — master (#68)
by Arturo
02:47
created

build.main   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 157
Duplicated Lines 19.75 %

Test Coverage

Coverage 92.73%

Importance

Changes 0
Metric Value
eloc 100
dl 31
loc 157
rs 10
c 0
b 0
f 0
ccs 51
cts 55
cp 0.9273
wmc 27

8 Methods

Rating   Name   Duplication   Size   Complexity  
A Main.shortest_path() 0 18 2
A Main.shortest_constrained_path() 0 22 3
A Main.shutdown() 0 2 1
A Main.setup() 0 4 1
A Main.execute() 0 2 1
D Main._filter_paths() 31 43 13
A Main.path_exact_delay() 0 21 2
A Main.update_topology() 0 18 4

How to fix   Duplicated Code   

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:

1
"""Main module of kytos/pathfinder Kytos Network Application."""
2
3 1
from flask import jsonify, request
4 1
from kytos.core import KytosNApp, log, rest
5 1
from kytos.core.helpers import listen_to
6
import traceback
7
# pylint: disable=import-error
8 1
# from napps.kytos.pathfinder.graph import KytosGraph
9
from graph import KytosGraph
10
# pylint: enable=import-error
11
12
13 1
class Main(KytosNApp):
14
    """
15
    Main class of kytos/pathfinder NApp.
16
17
    This class is the entry point for this napp.
18
    """
19 1
20
    def setup(self):
21 1
        """Create a graph to handle the nodes and edges."""
22 1
        self.graph = KytosGraph()
23
        self._topology = None
24 1
25
    def execute(self):
26
        """Do nothing."""
27 1
28
    def shutdown(self):
29
        """Shutdown the napp."""
30 1
31
    def _filter_paths(self, paths, desired, undesired):
32
        """
33
        Apply filters to the paths list.
34
35
        Make sure that each path in the list has all the desired links and none
36 1
        of the undesired ones.
37
        """
38 1
        filtered_paths = []
39 1
40 1 View Code Duplication
        if desired:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
41 1
            for link_id in desired:
42 1
                try:
43
                    endpoint_a = self._topology.links[link_id].endpoint_a.id
44
                    endpoint_b = self._topology.links[link_id].endpoint_b.id
45
                except KeyError:
46 1
                    return []
47 1
48 1
                for path in paths:
49 1
                    head = path['hops'][:-1]
50
                    tail = path['hops'][1:]
51 1
                    if (((endpoint_a, endpoint_b) in zip(head, tail)) or
52
                            ((endpoint_b, endpoint_a) in zip(head, tail))):
53 1
                        filtered_paths.append(path)
54
        else:
55 1
            filtered_paths = paths
56 1
57 1 View Code Duplication
        if undesired:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
58 1
            for link_id in undesired:
59 1
                try:
60
                    endpoint_a = self._topology.links[link_id].endpoint_a.id
61
                    endpoint_b = self._topology.links[link_id].endpoint_b.id
62
                except KeyError:
63 1
                    continue
64 1
65 1
                for path in paths:
66 1
                    head = path['hops'][:-1]
67
                    tail = path['hops'][1:]
68
                    if (((endpoint_a, endpoint_b) in zip(head, tail)) or
69 1
                            ((endpoint_b, endpoint_a) in zip(head, tail))):
70
71 1
                        filtered_paths.remove(path)
72
73 1
        return filtered_paths
74
75
    @rest('v2/', methods=['POST'])
76 1
    def shortest_path(self):
77
        """Calculate the best path between the source and destination."""
78 1
        data = request.get_json()
79 1
80 1
        desired = data.get('desired_links')
81
        undesired = data.get('undesired_links')
82 1
        parameter = data.get('parameter')
83 1
84
        paths = []
85
        for path in self.graph.shortest_paths(data['source'],
86
                                              data['destination'],
87 1
                                              parameter):
88
89 1
            paths.append({'hops': path})
90 1
91
        paths = self._filter_paths(paths, desired, undesired)
92 1
        return jsonify({'paths': paths})
93
94
    @rest('v2/path-exact-delay', methods=['POST'])
95
    def path_exact_delay(self):
96
        """
97
        Calculate the path with the exact delay
98 1
        between the source and destination.
99 1
        """
100 1
        data = request.get_json()
101 1
102 1
        source = data.get('source')
103 1
        destination = data.get('destination')
104
        delay = data.get('delay')
105
106
        graph_data = {}
107
        try:
108
            result = self.graph.exact_path(delay, source, destination)
109
        except Exception:
110
            return jsonify({"exception": str(traceback.format_exc())})
111
            
112
        graph_data["Exact Path Result"] = result
113
114
        return jsonify(graph_data)
115
116
    @rest('v2/best-constrained-paths', methods=['POST'])
117
    def shortest_constrained_path(self):
118
        """
119
        Get the set of shortest paths between the source and destination.
120
        """
121
        data = request.get_json()
122
123
        source = data.get('source')
124
        destination = data.get('destination')
125
        base_metrics = data.get('base_metrics', {})
126
        fle_metrics = data.get('flexible_metrics', {})
127
        minimum_hits = data.get('minimum_flexible_hits')
128
        try:
129
            paths = self.graph.constrained_flexible_paths(source, destination,
130
                                                          minimum_hits,
131
                                                          base=base_metrics,
132
                                                          flexible=fle_metrics)
133
            return jsonify(paths)
134
        except TypeError as err:
135
            return jsonify({"error": str(err)}), 400
136
        except Exception as err:
137
            return jsonify({"error": str(err)}), 500
138
139
    @listen_to('kytos.topology.updated')
140
    def update_topology(self, event):
141
        """
142
        Update the graph when the network topology was updated.
143
144
        Clear the current graph and create a new with the most topology updated.
145
        """
146
        if 'topology' not in event.content:
147
            return
148
        try:
149
            topology = event.content['topology']
150
            self._topology = topology
151
            self.graph.update_topology(topology)
152
            log.debug('Topology graph updated.')
153
        except TypeError as err:
154
            log.debug(err)
155
        except Exception as err:
156
            log.debug(err)
157