tcms.rpc.api.testrun.update()   F
last analyzed

Complexity

Conditions 15

Size

Total Lines 58
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 58
rs 2.9998
c 0
b 0
f 0
cc 15
nop 2

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 tcms.rpc.api.testrun.update() 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
# -*- coding: utf-8 -*-
2
from modernrpc.core import rpc_method, REQUEST_KEY
3
4
from tcms.core.utils import form_errors_to_list
5
from tcms.management.models import Tag
6
from tcms.testcases.models import TestCase
7
from tcms.testruns.models import TestExecution
8
from tcms.testruns.models import TestRun
9
from tcms.rpc.decorators import permissions_required
10
from tcms.testruns.forms import XMLRPCUpdateRunForm, XMLRPCNewRunForm
11
12
13
__all__ = (
14
    'create',
15
    'update',
16
    'filter',
17
18
    'add_case',
19
    'get_cases',
20
    'remove_case',
21
22
    'add_tag',
23
    'remove_tag',
24
)
25
26
27
@permissions_required('testruns.add_testexecution')
28
@rpc_method(name='TestRun.add_case')
29
def add_case(run_id, case_id):
30
    """
31
    .. function:: XML-RPC TestRun.add_case(run_id, case_id)
32
33
        Add a TestCase to the selected test run.
34
35
        :param run_id: PK of TestRun to modify
36
        :type run_id: int
37
        :param case_id: PK of TestCase to be added
38
        :type case_id: int
39
        :return: Serialized :class:`tcms.testruns.models.TestExecution` object
40
        :raises: DoesNotExist if objects specified by the PKs don't exist
41
        :raises: PermissionDenied if missing *testruns.add_testexecution* permission
42
    """
43
    execution = TestRun.objects.get(pk=run_id).add_case_run(
44
        case=TestCase.objects.get(pk=case_id)
45
    )
46
    return execution.serialize()
47
48
49
@permissions_required('testruns.delete_testexecution')
50
@rpc_method(name='TestRun.remove_case')
51
def remove_case(run_id, case_id):
52
    """
53
    .. function:: XML-RPC TestRun.remove_case(run_id, case_id)
54
55
        Remove a TestCase from the selected test run.
56
57
        :param run_id: PK of TestRun to modify
58
        :type run_id: int
59
        :param case_id: PK of TestCase to be removed
60
        :type case_id: int
61
        :return: None
62
        :raises: PermissionDenied if missing *testruns.delete_testexecution* permission
63
    """
64
    TestExecution.objects.filter(run=run_id, case=case_id).delete()
65
66
67
@rpc_method(name='TestRun.get_cases')
68
def get_cases(run_id):
69
    """
70
    .. function:: XML-RPC TestRun.get_cases(run_id)
71
72
        Get the list of test cases that are attached to a test run.
73
74
        :param run_id: PK of TestRun to inspect
75
        :type run_id: int
76
        :return: Serialized list of :class:`tcms.testcases.models.TestCase` objects
77
                 augmented with ``case_run_id`` and ``status`` information.
78
        :rtype: list(dict)
79
    """
80
    tcs_serializer = TestCase.to_xmlrpc(query={'case_run__run_id': run_id})
81
82
    qs = TestExecution.objects.filter(run_id=run_id).values(
83
        'case', 'pk', 'status__name')
84
    extra_info = dict(((row['case'], row) for row in qs.iterator()))
0 ignored issues
show
Comprehensibility Best Practice introduced by Mr. Senko
The variable row does not seem to be defined.
Loading history...
85
86
    for case in tcs_serializer:
87
        info = extra_info[case['case_id']]
88
        case['case_run_id'] = info['pk']
89
        case['status'] = info['status__name']
90
91
    return tcs_serializer
92
93
94
@permissions_required('testruns.add_testruntag')
95
@rpc_method(name='TestRun.add_tag')
96
def add_tag(run_id, tag_name, **kwargs):
97
    """
98
    .. function:: XML-RPC TestRun.add_tag(run_id, tag)
99
100
        Add one tag to the specified test run.
101
102
        :param run_id: PK of TestRun to modify
103
        :type run_id: int
104
        :param tag_name: Tag name to add
105
        :type tag_name: str
106
        :return: Serialized list of :class:`tcms.management.models.Tag` objects
107
        :raises: PermissionDenied if missing *testruns.add_testruntag* permission
108
        :raises: TestRun.DoesNotExist if object specified by PK doesn't exist
109
        :raises: Tag.DoesNotExist if missing *management.add_tag* permission and *tag_name*
110
                 doesn't exist in the database!
111
    """
112
    request = kwargs.get(REQUEST_KEY)
113
    tag, _ = Tag.get_or_create(request.user, tag_name)
114
    test_run = TestRun.objects.get(pk=run_id)
115
    test_run.add_tag(tag)
116
    return Tag.to_xmlrpc({'pk__in': test_run.tag.all()})
117
118
119
@permissions_required('testruns.delete_testruntag')
120
@rpc_method(name='TestRun.remove_tag')
121
def remove_tag(run_id, tag_name):
122
    """
123
    .. function:: XML-RPC TestRun.remove_tag(run_id, tag)
124
125
        Remove a tag from the specified test run.
126
127
        :param run_id: PK of TestRun to modify
128
        :type run_id: int
129
        :param tag_name: Tag name to add
130
        :type tag_name: str
131
        :return: Serialized list of :class:`tcms.management.models.Tag` objects
132
        :raises: PermissionDenied if missing *testruns.delete_testruntag* permission
133
        :raises: DoesNotExist if objects specified don't exist
134
    """
135
    tag = Tag.objects.get(name=tag_name)
136
    test_run = TestRun.objects.get(pk=run_id)
137
    test_run.remove_tag(tag)
138
    return Tag.to_xmlrpc({'pk__in': test_run.tag.all()})
139
140
141
@permissions_required('testruns.add_testrun')
142
@rpc_method(name='TestRun.create')
143
def create(values):
144
    """
145
    .. function:: XML-RPC TestRun.create(values)
146
147
        Create new TestRun object and store it in the database.
148
149
        :param values: Field values for :class:`tcms.testruns.models.TestRun`
150
        :type values: dict
151
        :return: Serialized :class:`tcms.testruns.models.TestRun` object
152
        :raises: PermissionDenied if missing *testruns.add_testrun* permission
153
        :raises: ValueError if data validations fail
154
155
        Example::
156
157
            >>> values = {'build': 384,
158
                'manager': 137,
159
                'plan': 137,
160
                'summary': 'Testing XML-RPC for TCMS',
161
            }
162
            >>> TestRun.create(values)
163
    """
164
    form = XMLRPCNewRunForm(values)
165
    form.assign_plan(values.get('plan'))
166
167
    if form.is_valid():
168
        test_run = TestRun.objects.create(
169
            product_version=form.cleaned_data['plan'].product_version,
170
            summary=form.cleaned_data['summary'],
171
            notes=form.cleaned_data['notes'],
172
            plan=form.cleaned_data['plan'],
173
            build=form.cleaned_data['build'],
174
            manager=form.cleaned_data['manager'],
175
            default_tester=form.cleaned_data['default_tester'],
176
        )
177
    else:
178
        raise ValueError(form_errors_to_list(form))
179
180
    return test_run.serialize()
181
182
183
@rpc_method(name='TestRun.filter')
184
def filter(query=None):  # pylint: disable=redefined-builtin
185
    """
186
    .. function:: XML-RPC TestRun.filter(query)
187
188
        Perform a search and return the resulting list of test runs.
189
190
        :param query: Field lookups for :class:`tcms.testruns.models.TestRun`
191
        :type query: dict
192
        :return: List of serialized :class:`tcms.testruns.models.TestRun` objects
193
        :rtype: list(dict)
194
    """
195
196
    if query is None:
197
        query = {}
198
199
    return TestRun.to_xmlrpc(query)
200
201
202
@permissions_required('testruns.change_testrun')
203
@rpc_method(name='TestRun.update')
204
def update(run_id, values):
205
    """
206
    .. function:: XML-RPC TestRun.update(run_id, values)
207
208
        Update the selected TestRun
209
210
        :param run_id: PK of TestRun to modify
211
        :type run_id: int
212
        :param values: Field values for :class:`tcms.testruns.models.TestRun`
213
        :type values: dict
214
        :return: Serialized :class:`tcms.testruns.models.TestRun` object
215
        :raises: PermissionDenied if missing *testruns.change_testrun* permission
216
        :raises: ValueError if data validations fail
217
    """
218
    if values.get('product_version') and not values.get('product'):
219
        raise ValueError('Field "product" is required by product_version')
220
221
    form = XMLRPCUpdateRunForm(values)
222
    if values.get('product_version'):
223
        form.populate(product_id=values['product'])
224
225
    if not form.is_valid():
226
        raise ValueError(form_errors_to_list(form))
227
228
    test_run = TestRun.objects.get(pk=run_id)
229
    if form.cleaned_data['plan']:
230
        test_run.plan = form.cleaned_data['plan']
231
232
    if form.cleaned_data['build']:
233
        test_run.build = form.cleaned_data['build']
234
235
    if form.cleaned_data['manager']:
236
        test_run.manager = form.cleaned_data['manager']
237
238
    test_run.default_tester = None
239
240
    if form.cleaned_data['default_tester']:
241
        test_run.default_tester = form.cleaned_data['default_tester']
242
243
    if form.cleaned_data['summary']:
244
        test_run.summary = form.cleaned_data['summary']
245
246
    if form.cleaned_data['product_version']:
247
        test_run.product_version = form.cleaned_data['product_version']
248
249
    if 'notes' in values:
250
        if values['notes'] in (None, ''):
251
            test_run.notes = values['notes']
252
        if form.cleaned_data['notes']:
253
            test_run.notes = form.cleaned_data['notes']
254
255
    if form.cleaned_data['stop_date']:
256
        test_run.stop_date = form.cleaned_data['stop_date']
257
258
    test_run.save()
259
    return test_run.serialize()
260