Passed
Pull Request — master (#41)
by Paolo
07:36
created

animals.tasks   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 198
Duplicated Lines 22.73 %

Importance

Changes 0
Metric Value
wmc 10
eloc 100
dl 45
loc 198
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A BatchDeleteAnimals.on_failure() 0 27 1
B BatchDeleteAnimals.run() 0 82 7
A BatchUpdateAnimals.on_failure() 19 19 1
A BatchUpdateAnimals.run() 12 12 1

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
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Wed Feb 27 16:38:37 2019
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
from celery.utils.log import get_task_logger
10
11
from django.db import transaction
12
13
from common.constants import ERROR, NEED_REVISION
14
from common.tasks import BatchUpdateMixin
15
from image.celery import app as celery_app, MyTask
16
from image_app.models import Submission, Animal, Name
17
from submissions.helpers import send_message
18
from validation.helpers import construct_validation_message
19
from validation.models import ValidationSummary
20
21
# Get an instance of a logger
22
logger = get_task_logger(__name__)
23
24
25
class BatchDeleteAnimals(MyTask):
26
    name = "Batch delete animals"
27
    description = """Batch remove animals and associated samples"""
28
29
    # Ovverride default on failure method
30
    # This is not a failed validation for a wrong value, this is an
31
    # error in task that mean an error in coding
32
    def on_failure(self, exc, task_id, args, kwargs, einfo):
33
        logger.error('{0!r} failed: {1!r}'.format(task_id, exc))
34
35
        submission_id, animal_ids = args[0], args[1]
36
37
        logger.error(
38
            ("BatchDeleteAnimals called with submission_id: %s and "
39
             "animal_ids: %s" % (submission_id, animal_ids))
40
        )
41
42
        # get submission object
43
        submission_obj = Submission.objects.get(pk=submission_id)
44
45
        # mark submission with ERROR
46
        submission_obj.status = ERROR
47
        submission_obj.message = (
48
            "Error in animal batch delete: %s" % (str(exc)))
49
        submission_obj.save()
50
51
        send_message(submission_obj)
52
53
        # send a mail to the user with the stacktrace (einfo)
54
        submission_obj.owner.email_user(
55
            "Error in animal batch delete for submission: %s" % (
56
                submission_obj.id),
57
            ("Something goes wrong in batch delete for animals. Please report "
58
             "this to InjectTool team\n\n %s" % str(einfo)),
59
        )
60
61
        # TODO: submit mail to admin
62
63
    def run(self, submission_id, animal_ids):
64
        """Function for batch update attribute in animals
65
        Args:
66
            submission_id (int): id of submission
67
            animal_ids (list): set with ids to delete
68
        """
69
70
        # get a submisision object
71
        submission_obj = Submission.objects.get(pk=submission_id)
72
73
        logger.info("Start batch delete for animals")
74
        success_ids = list()
75
        failed_ids = list()
76
77
        for animal_id in animal_ids:
78
            try:
79
                name = Name.objects.get(
80
                    name=animal_id, submission=submission_obj)
81
82
                animal_object = Animal.objects.get(name=name)
83
                samples = animal_object.sample_set.all()
84
85
                with transaction.atomic():
86
                    for sample in samples:
87
                        sample_name = sample.name
88
                        sample.delete()
89
                        sample_name.delete()
90
91
                    logger.debug("Clearing all childs from this animal")
92
                    name.mother_of.clear()
93
                    name.father_of.clear()
94
95
                    # delete this animal object
96
                    logger.debug(
97
                        "Deleting animal:%s and name:%s" % (
98
                            animal_object, name))
99
                    animal_object.delete()
100
                    name.delete()
101
102
                success_ids.append(animal_id)
103
104
            except Name.DoesNotExist:
105
                failed_ids.append(animal_id)
106
107
            except Animal.DoesNotExist:
108
                failed_ids.append(animal_id)
109
110
        # Update submission
111
        submission_obj.refresh_from_db()
112
        submission_obj.status = NEED_REVISION
113
114
        if len(failed_ids) != 0:
115
            submission_obj.message = f"You've removed {len(success_ids)} " \
116
                f"animals. It wasn't possible to find records with these " \
117
                f"ids: {', '.join(failed_ids)}. Rerun validation please!"
118
        else:
119
            submission_obj.message = f"You've removed {len(success_ids)} " \
120
                f"animals. Rerun validation please!"
121
122
        submission_obj.save()
123
124
        summary_obj, created = ValidationSummary.objects.get_or_create(
125
            submission=submission_obj, type='animal')
126
        summary_obj.reset()
127
128
        # after removing animal associated samples, we need to update also
129
        # sample all count
130
        summary_obj, created = ValidationSummary.objects.get_or_create(
131
            submission=submission_obj, type='sample')
132
        summary_obj.reset()
133
134
        # TODO: validation summary could be updated relying database, instead
135
        # doing validation. Define a method in validation.helpers to update
136
        # summary relying only on database
137
138
        send_message(
139
            submission_obj, construct_validation_message(submission_obj)
140
        )
141
142
        logger.info("batch delete for animals completed")
143
144
        return 'success'
145
146
147 View Code Duplication
class BatchUpdateAnimals(MyTask, BatchUpdateMixin):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
148
    name = "Batch update animals"
149
    description = """Batch update of field in animals"""
150
151
    item_cls = Animal
152
    submission_cls = Submission
153
154
    # Ovverride default on failure method
155
    # This is not a failed validation for a wrong value, this is an
156
    # error in task that mean an error in coding
157
    def on_failure(self, exc, task_id, args, kwargs, einfo):
158
        logger.error('{0!r} failed: {1!r}'.format(task_id, exc))
159
160
        # get submission object
161
        submission_obj = Submission.objects.get(pk=args[0])
162
163
        # mark submission with ERROR
164
        submission_obj.status = ERROR
165
        submission_obj.message = ("Error in batch update for animals: %s"
166
                                  % (str(exc)))
167
        submission_obj.save()
168
169
        send_message(submission_obj)
170
171
        # send a mail to the user with the stacktrace (einfo)
172
        submission_obj.owner.email_user(
173
            "Error in batch update for animals: %s" % (args[0]),
174
            ("Something goes wrong  in batch update for animals. Please "
175
             "report this to InjectTool team\n\n %s" % str(einfo)),
176
        )
177
178
        # TODO: submit mail to admin
179
180
    def run(self, submission_id, animal_ids, attribute):
181
        """Function for batch update attribute in animals
182
        Args:
183
            submission_id (int): id of submission
184
            animal_ids (dict): dict with id and values to update
185
            attribute (str): attribute to update
186
        """
187
188
        logger.info("Start batch update for animals")
189
        super(BatchUpdateAnimals, self).batch_update(submission_id, animal_ids,
190
                                                     attribute)
191
        return 'success'
192
193
194
# register explicitly tasks
195
# https://github.com/celery/celery/issues/3744#issuecomment-271366923
196
celery_app.tasks.register(BatchDeleteAnimals)
197
celery_app.tasks.register(BatchUpdateAnimals)
198