OverridesMixin.create_override()   F
last analyzed

Complexity

Conditions 14

Size

Total Lines 91
Code Lines 52

Duplication

Lines 91
Ratio 100 %

Importance

Changes 0
Metric Value
cc 14
eloc 52
nop 13
dl 91
loc 91
rs 3.6
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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 gvm.protocols.gmpv208.entities.overrides.OverridesMixin.create_override() 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.

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2021 Greenbone Networks GmbH
3
#
4
# SPDX-License-Identifier: GPL-3.0-or-later
5
#
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
from typing import Any, List, Optional
20
21
from gvm.errors import RequiredArgument, InvalidArgumentType
22
from gvm.protocols.gmpv208.entities.severity import Severity, SeverityLevel
23
from gvm.utils import add_filter, to_comma_list, to_bool
24
from gvm.xml import XmlCommand
25
26
27
class OverridesMixin:
28 View Code Duplication
    def create_override(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
29
        self,
30
        text: str,
31
        nvt_oid: str,
32
        *,
33
        days_active: Optional[int] = None,
34
        hosts: Optional[List[str]] = None,
35
        port: Optional[int] = None,
36
        result_id: Optional[str] = None,
37
        severity: Optional[Severity] = None,
38
        new_severity: Optional[Severity] = None,
39
        task_id: Optional[str] = None,
40
        threat: Optional[SeverityLevel] = None,
41
        new_threat: Optional[SeverityLevel] = None,
42
    ) -> Any:
43
        """Create a new override
44
45
        Arguments:
46
            text: Text of the new override
47
            nvt_id: OID of the nvt to which override applies
48
            days_active: Days override will be active. -1 on always, 0 off
49
            hosts: A list of host addresses
50
            port: Port to which the override applies
51
            result_id: UUID of a result to which override applies
52
            severity: Severity to which override applies
53
            new_severity: New severity for result
54
            task_id: UUID of task to which override applies
55
            threat: Severity level to which override applies. Will be converted
56
                to severity.
57
            new_threat: New severity level for results. Will be converted to
58
                new_severity.
59
60
        Returns:
61
            The response. See :py:meth:`send_command` for details.
62
        """
63
        if not text:
64
            raise RequiredArgument(
65
                function=self.create_override.__name__, argument='text'
66
            )
67
68
        if not nvt_oid:
69
            raise RequiredArgument(
70
                function=self.create_override.__name__, argument='nvt_oid'
71
            )
72
73
        cmd = XmlCommand("create_override")
74
        cmd.add_element("text", text)
75
        cmd.add_element("nvt", attrs={"oid": nvt_oid})
76
77
        if days_active is not None:
78
            cmd.add_element("active", str(days_active))
79
80
        if hosts:
81
            cmd.add_element("hosts", to_comma_list(hosts))
82
83
        if port:
84
            cmd.add_element("port", str(port))
85
86
        if result_id:
87
            cmd.add_element("result", attrs={"id": result_id})
88
89
        if severity:
90
            cmd.add_element("severity", str(severity))
91
92
        if new_severity:
93
            cmd.add_element("new_severity", str(new_severity))
94
95
        if task_id:
96
            cmd.add_element("task", attrs={"id": task_id})
97
98
        if threat is not None:
99
            if not isinstance(threat, SeverityLevel):
100
                raise InvalidArgumentType(
101
                    function=self.create_override.__name__,
102
                    argument="threat",
103
                    arg_type=SeverityLevel.__name__,
104
                )
105
106
            cmd.add_element("threat", threat.value)
107
108
        if new_threat is not None:
109
            if not isinstance(new_threat, SeverityLevel):
110
                raise InvalidArgumentType(
111
                    function=self.create_override.__name__,
112
                    argument="new_threat",
113
                    arg_type=SeverityLevel.__name__,
114
                )
115
116
            cmd.add_element("new_threat", new_threat.value)
117
118
        return self._send_xml_command(cmd)
119
120
    def clone_override(self, override_id: str) -> Any:
121
        """Clone an existing override
122
123
        Arguments:
124
            override_id: UUID of an existing override to clone from
125
126
        Returns:
127
            The response. See :py:meth:`send_command` for details.
128
        """
129
        if not override_id:
130
            raise RequiredArgument(
131
                function=self.clone_override.__name__, argument='override_id'
132
            )
133
134
        cmd = XmlCommand("create_override")
135
        cmd.add_element("copy", override_id)
136
        return self._send_xml_command(cmd)
137
138
    def delete_override(
139
        self, override_id: str, *, ultimate: Optional[bool] = False
140
    ) -> Any:
141
        """Deletes an existing override
142
143
        Arguments:
144
            override_id: UUID of the override to be deleted.
145
            ultimate: Whether to remove entirely, or to the trashcan.
146
        """
147
        if not override_id:
148
            raise RequiredArgument(
149
                function=self.delete_override.__name__, argument='override_id'
150
            )
151
152
        cmd = XmlCommand("delete_override")
153
        cmd.set_attribute("override_id", override_id)
154
        cmd.set_attribute("ultimate", to_bool(ultimate))
155
156
        return self._send_xml_command(cmd)
157
158
    def get_overrides(
159
        self,
160
        *,
161
        filter_string: Optional[str] = None,
162
        filter_id: Optional[str] = None,
163
        details: Optional[bool] = None,
164
        result: Optional[bool] = None,
165
    ) -> Any:
166
        """Request a list of overrides
167
168
        Arguments:
169
            filter_string: Filter term to use for the query
170
            filter_id: UUID of an existing filter to use for the query
171
            details: Whether to include full details
172
            result: Whether to include results using the override
173
174
        Returns:
175
            The response. See :py:meth:`send_command` for details.
176
        """
177
        cmd = XmlCommand("get_overrides")
178
179
        add_filter(cmd, filter_string, filter_id)
180
181
        if details is not None:
182
            cmd.set_attribute("details", to_bool(details))
183
184
        if result is not None:
185
            cmd.set_attribute("result", to_bool(result))
186
187
        return self._send_xml_command(cmd)
188
189
    def get_override(self, override_id: str) -> Any:
190
        """Request a single override
191
192
        Arguments:
193
            override_id: UUID of an existing override
194
195
        Returns:
196
            The response. See :py:meth:`send_command` for details.
197
        """
198
        cmd = XmlCommand("get_overrides")
199
200
        if not override_id:
201
            raise RequiredArgument(
202
                function=self.get_override.__name__, argument='override_id'
203
            )
204
205
        cmd.set_attribute("override_id", override_id)
206
207
        # for single entity always request all details
208
        cmd.set_attribute("details", "1")
209
        return self._send_xml_command(cmd)
210
211 View Code Duplication
    def modify_override(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
212
        self,
213
        override_id: str,
214
        text: str,
215
        *,
216
        days_active: Optional[int] = None,
217
        hosts: Optional[List[str]] = None,
218
        port: Optional[int] = None,
219
        result_id: Optional[str] = None,
220
        severity: Optional[Severity] = None,
221
        new_severity: Optional[Severity] = None,
222
        task_id: Optional[str] = None,
223
        threat: Optional[SeverityLevel] = None,
224
        new_threat: Optional[SeverityLevel] = None,
225
    ) -> Any:
226
        """Modifies an existing override.
227
228
        Arguments:
229
            override_id: UUID of override to modify.
230
            text: The text of the override.
231
            days_active: Days override will be active. -1 on always,
232
                0 off.
233
            hosts: A list of host addresses
234
            port: Port to which override applies.
235
            result_id: Result to which override applies.
236
            severity: Severity to which override applies.
237
            new_severity: New severity score for result.
238
            task_id: Task to which override applies.
239
            threat: Threat level to which override applies.
240
                Will be converted to severity.
241
            new_threat: New threat level for results. Will be converted to
242
                new_severity.
243
244
        Returns:
245
            The response. See :py:meth:`send_command` for details.
246
        """
247
        if not override_id:
248
            raise RequiredArgument(
249
                function=self.modify_override.__name__, argument='override_id'
250
            )
251
        if not text:
252
            raise RequiredArgument(
253
                function=self.modify_override.__name__, argument='text'
254
            )
255
256
        cmd = XmlCommand("modify_override")
257
        cmd.set_attribute("override_id", override_id)
258
        cmd.add_element("text", text)
259
260
        if days_active is not None:
261
            cmd.add_element("active", str(days_active))
262
263
        if hosts:
264
            cmd.add_element("hosts", to_comma_list(hosts))
265
266
        if port:
267
            cmd.add_element("port", str(port))
268
269
        if result_id:
270
            cmd.add_element("result", attrs={"id": result_id})
271
272
        if severity:
273
            cmd.add_element("severity", str(severity))
274
275
        if new_severity:
276
            cmd.add_element("new_severity", str(new_severity))
277
278
        if task_id:
279
            cmd.add_element("task", attrs={"id": task_id})
280
281
        if threat is not None:
282
            if not isinstance(threat, SeverityLevel):
283
                raise InvalidArgumentType(
284
                    function=self.modify_override.__name__,
285
                    argument='threat',
286
                    arg_type=SeverityLevel.__name__,
287
                )
288
            cmd.add_element("threat", threat.value)
289
290
        if new_threat is not None:
291
            if not isinstance(new_threat, SeverityLevel):
292
                raise InvalidArgumentType(
293
                    function=self.modify_override.__name__,
294
                    argument='new_threat',
295
                    arg_type=SeverityLevel.__name__,
296
                )
297
298
            cmd.add_element("new_threat", new_threat.value)
299
300
        return self._send_xml_command(cmd)
301