Completed
Push — master ( 55dedd...16663f )
by Paolo
30s queued 14s
created

SubmissionHelper.finalize()   B

Complexity

Conditions 5

Size

Total Lines 51
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 51
rs 8.8373
c 0
b 0
f 0
cc 5
nop 1

How to fix   Long Method   

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:

1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Thu May 28 16:06:56 2020
5
6
@author: Paolo Cozzi <[email protected]>
7
8
Fetch the Orphan submissions and track BioSamples removal
9
10
"""
11
12
import json
13
import logging
14
15
import pyUSIrest.usi
16
17
from django.core.management import BaseCommand
18
from django.utils import timezone
19
20
from biosample.helpers import get_manager_auth
21
from biosample.models import OrphanSubmission
22
from biosample.tasks.retrieval import FetchStatusHelper
23
from common.constants import SUBMITTED, NEED_REVISION, COMPLETED
24
25
26
# Get an instance of a logger
27
logger = logging.getLogger(__name__)
28
29
30
class SubmissionHelper(FetchStatusHelper):
31
    def __init__(self, root, usi_submission, can_finalize=False):
32
        self.root = root
33
        self.usi_submission = usi_submission
34
        self.can_finalize = can_finalize
35
        self.submission_name = usi_submission.usi_submission_name
36
37
        logger.info(
38
            "Getting info for usi submission '%s'" % (self.submission_name))
39
40
        self.submission = root.get_submission_by_name(
41
            submission_name=self.submission_name)
42
43
    # override finalize method
44
    def finalize(self):
45
        """Finalize a submission by closing document and send it to
46
        biosample"""
47
48
        if not self.can_finalize:
49
            # skip finalizing a submission
50
            logger.warning(
51
                "Ignoring finalization: please call with '--finalize'"
52
                " argument")
53
            return
54
55
        logger.info("Finalizing submission '%s'" % (
56
            self.submission_name))
57
58
        # get errors for a submission
59
        errors = self.submission.has_errors()
60
61
        # collect all error messages in a list
62
        messages = []
63
64
        if True in errors:
65
            # get sample with errors then update database
66
            samples = self.submission.get_samples(has_errors=True)
67
68
            for sample in samples:
69
                if sample.has_errors():
70
                    logger.error("%s has errors!!!" % sample)
71
72
                    # mark this sample since has problems
73
                    errorMessages = self.sample_has_errors(sample)
74
75
                    # append this into error messages list
76
                    messages.append(errorMessages)
77
78
                # if a sample has no errors, status will be the same
79
80
            logger.error(
81
                "Errors for submission: '%s'" % (self.submission_name))
82
            logger.error("Fix them, then finalize")
83
84
            # report error
85
            message = json.dumps(messages, indent=2)
86
87
            # Update status for biosample.models.Submission
88
            self.usi_submission.status = NEED_REVISION
89
            self.usi_submission.message = message
90
            self.usi_submission.save()
91
92
        else:
93
            # TODO: model and test exception in finalization
94
            self.submission.finalize()
95
96
    # override complete method
97
    def complete(self):
98
        """Complete a submission and fetch biosample names"""
99
100
        logger.info("Completing submission '%s'" % (
101
            self.submission_name))
102
103
        for sample in self.submission.get_samples():
104
            # if no accession, return without doing anything
105
            if sample.accession is None:
106
                logger.error("No accession found for sample '%s'" % (sample))
107
                logger.error("Ignoring submission '%s'" % (self.submission))
108
                return
109
110
            orphan_sample = self.usi_submission.submission_data.get(
111
                biosample_id=sample.accession)
112
            orphan_sample.status = COMPLETED
113
            orphan_sample.removed = True
114
            orphan_sample.removed_at = timezone.now()
115
            orphan_sample.save()
116
117
        # update submission
118
        self.usi_submission.status = COMPLETED
119
        self.usi_submission.message = "Successful removal from biosample"
120
        self.usi_submission.save()
121
122
        logger.info(
123
            "Submission %s is now completed and its samples "
124
            "removed from BioSamples" % (self.submission_name)
125
        )
126
127
    # custom implementation: here I don't have a record in UID and I
128
    # can't use the base method of this class
129
    def sample_has_errors(self, sample):
130
        """
131
        Get USI error for sample
132
133
        Args:
134
            sample (pyUSIrest.usi.sample): a USI sample object
135
        """
136
137
        # track status in db like FetchStatusHelper
138
        orphan_sample = self.usi_submission.submission_data.get(
139
            biosample_id=sample.accession)
140
        orphan_sample.status = NEED_REVISION
141
        orphan_sample.save()
142
143
        # get a USI validation result
144
        validation_result = sample.get_validation_result()
145
146
        # track errors  in validation tables
147
        errorMessages = validation_result.errorMessages
148
149
        # return an error for each object
150
        return {str(sample): errorMessages}
151
152
153
class Command(BaseCommand):
154
    help = 'Fetch the Orphan submissions and track BioSamples removal'
155
156
    def add_arguments(self, parser):
157
        parser.add_argument(
158
            '--finalize',
159
            default=False,
160
            action='store_true',
161
        )
162
163
    def handle(self, *args, **options):
164
        # call commands and fill tables.
165
        logger.info("Called fetch_orphan_biosamples")
166
167
        # Ok get all Orphaned BioSample submission in SUBMITTED status
168
        qs = OrphanSubmission.objects.filter(status=SUBMITTED)
169
170
        if qs.count() > 0:
171
            # ok do stuff
172
            auth = get_manager_auth()
173
            root = pyUSIrest.usi.Root(auth)
174
175
            for orphan_submission in qs:
176
                submission_helper = SubmissionHelper(
177
                    root,
178
                    orphan_submission,
179
                    options['finalize'])
180
                submission_helper.check_submission_status()
181
182
        # call commands and fill tables.
183
        logger.info("fetch_orphan_biosamples finished")
184