Completed
Branch master (d329f3)
by Jordi
03:26
created

ResultOutOfRange.__call__()   F

Complexity

Conditions 22

Size

Total Lines 82
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 55
dl 0
loc 82
rs 0
c 0
b 0
f 0
cc 22
nop 4

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 bika.health.browser.analysis.resultoutofrange.ResultOutOfRange.__call__() 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
#
3
# This file is part of SENAITE.HEALTH
4
#
5
# Copyright 2018 by it's authors.
6
# Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst.
7
8
from Products.CMFCore.utils import getToolByName
9
from bika.lims import bikaMessageFactory as _
10
from bika.lims.interfaces import IAnalysis
11
from bika.lims.interfaces import IFieldIcons
12
from zope.interface import implements
13
from zope.component import adapts
14
15
16
class ResultOutOfRange(object):
17
    """An alert provider for Analysis results outside of panic ranges
18
    """
19
20
    implements(IFieldIcons)
21
    adapts(IAnalysis)
22
23
    def __init__(self, context):
24
        self.context = context
25
26
    def __call__(self, result=None, specification=None, **kwargs):
27
        """ Check if result value is 'in panic'.
28
        """
29
        analysis = self.context
30
        path = '++resource++bika.health.images'
31
32
        translate = self.context.translate
33
        workflow = getToolByName(self.context, 'portal_workflow')
34
35
        astate = workflow.getInfoFor(analysis, 'review_state')
36
        if astate == 'retracted':
37
            return {}
38
39
        result = result is not None and str(result) or analysis.getResult()
40
        if result == '':
41
            return {}
42
        # if analysis result is not a number, then we assume in range
43
        try:
44
            result = float(str(result))
45
        except ValueError:
46
            return {}
47
        # No specs available, assume in range
48
        specs = analysis.getAnalysisSpecs(specification) \
49
            if hasattr(analysis, 'getAnalysisSpecs') else None
50
        if specs is None:
51
            return {}
52
53
        keyword = analysis.getKeyword()
54
        spec = specs.getResultsRangeDict()
55
        if keyword in spec:
56
            try:
57
                spec_min = float(spec[keyword]['minpanic'])
58
            except (ValueError, TypeError):
59
                spec_min = None
60
61
            try:
62
                spec_max = float(spec[keyword]['maxpanic'])
63
            except (ValueError, TypeError):
64
                spec_max = None
65
66
            if not (spec_min or spec_max):
67
                # No min and max values defined
68
                outofrange, acceptable, o_spec = False, None, None
69
70
            elif spec_min and spec_max and spec_min <= result <= spec_max:
71
                # min and max values defined
72
                outofrange, acceptable, o_spec = False, None, None
73
74
            elif spec_min and not spec_max and spec_min <= result:
75
                # max value not defined
76
                outofrange, acceptable, o_spec = False, None, None
77
78
            elif not spec_min and spec_max and spec_max >= result:
79
                # min value not defined
80
                outofrange, acceptable, o_spec = False, None, None
81
82
            else:
83
                outofrange, acceptable, o_spec = True, False, spec[keyword]
84
85
        else:
86
            # Analysis without specification values. Assume in range
87
            outofrange, acceptable, o_spec = False, None, None
88
89
        alerts = {}
90
        if outofrange:
91
            range_str = "{0} {1}, {2} {3}".format(
92
                translate(_("minpanic")), str(o_spec['minpanic']),
93
                translate(_("maxpanic")), str(o_spec['maxpanic'])
94
            )
95
96
            if acceptable:
97
                message = "{0} ({1})".format(
98
                    translate(_('Result in shoulder panic range')), range_str)
99
            else:
100
                message = "{0} ({1})".format(
101
                    translate(_('Result exceeded panic level')), range_str)
102
103
            alerts[analysis.UID()] = [{
104
                'msg': message,
105
                'icon': path + '/lifethreat.png',
106
                'field': 'Result', }, ]
107
        return alerts
108