Skip to content

Commit 4e1953a

Browse files
authored
Merge pull request #457 from senaite/bugfix/issue-408-calcluations-using-python-modules
Issue-408: Calculation referring to additional python module not triggered
2 parents 4e3ba8b + 78cceb3 commit 4e1953a

File tree

3 files changed

+44
-57
lines changed

3 files changed

+44
-57
lines changed

CHANGES.rst

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Changelog
1717

1818
**Fixed**
1919

20+
- #457 Calculation referring to additional python module not triggered
2021
- #459 Traceback in Instruments list after adding a calibration certificate
2122
- #454 Click on some analyses pops up a new page instead of object log
2223
- #452 Traceback error when deleting attachment from Analysis Request

bika/lims/browser/calcs.py

+30-45
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,33 @@
33
# Copyright 2011-2016 by it's authors.
44
# Some rights reserved. See LICENSE.txt, AUTHORS.txt.
55

6+
import json
7+
import math
8+
import plone
9+
10+
from zope.component import adapts
11+
from zope.component import getAdapters
12+
from zope.interface import implements
13+
14+
from Products.Archetypes.config import REFERENCE_CATALOG
15+
from Products.CMFCore.utils import getToolByName
16+
from Products.PythonScripts.standard import html_quote
17+
18+
from bika.lims import bikaMessageFactory as _
619
from bika.lims.browser import BrowserView
720
from bika.lims.interfaces import IAnalysis
821
from bika.lims.interfaces import IFieldIcons
9-
from bika.lims import bikaMessageFactory as _
1022
from bika.lims.utils import t, isnumber
11-
from bika.lims import logger
12-
from bika.lims.utils import to_utf8
13-
from Products.Archetypes.config import REFERENCE_CATALOG
14-
from Products.CMFCore.utils import getToolByName
15-
from Products.PythonScripts.standard import html_quote
1623
from bika.lims.utils.analysis import format_numeric_result
17-
from zope.component import adapts
18-
from zope.component import getAdapters
19-
from zope.interface import implements
20-
21-
import json
22-
import math
23-
import plone
2424

2525

2626
class CalculationResultAlerts(object):
27-
2827
"""This uses IAnalysis.ResultOutOfRange on values in request.
28+
2929
To validate results at ajax calculation time, make more adapters like this
3030
one, from IFieldIcons. Any existing IAnalysis/IFieldIcon adapters
3131
(AnalysisOutOfRange) have already been called.
3232
"""
33-
3433
adapts(IAnalysis)
3534
implements(IFieldIcons)
3635

@@ -62,10 +61,9 @@ def __call__(self, result=None, specification=None, **kwargs):
6261

6362

6463
class ajaxCalculateAnalysisEntry(BrowserView):
65-
66-
""" This view is called by javascript when an analysis' result or interim
67-
field value is entered. Returns a JSON dictionary, or None if no
68-
action is required or possible.
64+
"""This view is called by javascript when an analysis' result or interim
65+
field value is entered.
66+
Returns a JSON dictionary, or None if no action is required or possible.
6967
"""
7068

7169
def __init__(self, context, request):
@@ -94,18 +92,17 @@ def calculate(self, uid=None):
9492
Result['result'] = ""
9593

9694
if calculation:
95+
"""We need first to create the map of available parameters
96+
acording to the interims, analyses and wildcards:
9797
98-
'''
99-
We need first to create the map of available parameters
100-
acording to the interims, analyses and wildcards:
10198
params = {
10299
<as-1-keyword> : <analysis_result>,
103100
<as-1-keyword>.<wildcard-1> : <wildcard_1_value>,
104101
<as-1-keyword>.<wildcard-2> : <wildcard_2_value>,
105102
<interim-1> : <interim_result>,
106103
...
107104
}
108-
'''
105+
"""
109106

110107
# Get dependent analyses results and wildcard values to the
111108
# mapping. If dependent analysis without result found,
@@ -124,17 +121,17 @@ def calculate(self, uid=None):
124121
else:
125122
# Retrieve the result and DLs from the analysis
126123
analysisvalues = {
127-
'keyword': dependency.getKeyword(),
128-
'result': dependency.getResult(),
129-
'ldl': dependency.getLowerDetectionLimit(),
130-
'udl': dependency.getUpperDetectionLimit(),
124+
'keyword': dependency.getKeyword(),
125+
'result': dependency.getResult(),
126+
'ldl': dependency.getLowerDetectionLimit(),
127+
'udl': dependency.getUpperDetectionLimit(),
131128
'belowldl': dependency.isBelowLowerDetectionLimit(),
132129
'aboveudl': dependency.isAboveUpperDetectionLimit(),
133130
}
134-
if analysisvalues['result']=='':
131+
if analysisvalues['result'] == '':
135132
unsatisfied = True
136-
break;
137-
key = analysisvalues.get('keyword',dependency.getKeyword())
133+
break
134+
key = analysisvalues.get('keyword', dependency.getKeyword())
138135

139136
# Analysis result
140137
# All result mappings must be float, or they are ignored.
@@ -215,7 +212,7 @@ def calculate(self, uid=None):
215212
'context': self.context},
216213
{'mapping': mapping})
217214
# calculate
218-
result = eval(formula)
215+
result = eval(formula, calculation._getGlobals())
219216
Result['result'] = result
220217
self.current_results[uid]['result'] = result
221218
except TypeError as e:
@@ -258,18 +255,6 @@ def calculate(self, uid=None):
258255
else:
259256
self.alerts[uid] = [alert, ]
260257

261-
if analysis.portal_type == 'ReferenceAnalysis':
262-
# The analysis is a Control or Blank. We might use the
263-
# reference results instead other specs
264-
_uid = analysis.getServiceUID()
265-
specs = analysis.aq_parent.getResultsRangeDict().get(_uid, {})
266-
267-
else:
268-
# Get the specs directly from the analysis. The getResultsRange
269-
# function already takes care about which are the specs to be used:
270-
# AR, client or lab.
271-
specs = analysis.getResultsRange()
272-
273258
# format result
274259
try:
275260
Result['formatted_result'] = format_numeric_result(analysis,
@@ -322,8 +307,8 @@ def calculate(self, uid=None):
322307
anvals = self.current_results[uid]
323308
isldl = anvals.get('isldl', False)
324309
isudl = anvals.get('isudl', False)
325-
ldl = anvals.get('ldl',0)
326-
udl = anvals.get('udl',0)
310+
ldl = anvals.get('ldl', 0)
311+
udl = anvals.get('udl', 0)
327312
ldl = float(ldl) if isnumber(ldl) else 0
328313
udl = float(udl) if isnumber(udl) else 10000000
329314
belowldl = (isldl or flres < ldl)

bika/lims/content/calculation.py

+13-12
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
import inspect
1010
import math
1111
import re
12-
import sys
1312

1413
import transaction
14+
15+
from zope.interface import implements
16+
1517
from AccessControl import ClassSecurityInfo
1618
from Products.ATContentTypes.lib.historyaware import HistoryAwareMixin
1719
from Products.ATExtensions.field import RecordsField
@@ -21,22 +23,21 @@
2123
from Products.Archetypes.atapi import TextAreaWidget
2224
from Products.Archetypes.atapi import TextField
2325
from Products.Archetypes.atapi import registerType
24-
from Products.Archetypes.references import HoldingReference
2526
from Products.CMFCore.WorkflowCore import WorkflowException
2627
from Products.CMFCore.utils import getToolByName
2728
from Products.CMFPlone.utils import safe_unicode
29+
2830
from bika.lims import bikaMessageFactory as _
2931
from bika.lims.api import get_object_by_uid
30-
from bika.lims.browser.fields import HistoryAwareReferenceField
3132
from bika.lims.browser.fields import InterimFieldsField
32-
from bika.lims.browser.fields.uidreferencefield import UIDReferenceField, \
33-
get_backreferences
33+
from bika.lims.browser.fields.uidreferencefield import UIDReferenceField
34+
from bika.lims.browser.fields.uidreferencefield import get_backreferences
3435
from bika.lims.browser.widgets import RecordsWidget
3536
from bika.lims.browser.widgets import RecordsWidget as BikaRecordsWidget
3637
from bika.lims.config import PROJECTNAME
3738
from bika.lims.content.bikaschema import BikaSchema
3839
from bika.lims.interfaces.calculation import ICalculation
39-
from zope.interface import implements
40+
4041

4142
schema = BikaSchema.copy() + Schema((
4243

@@ -232,12 +233,12 @@ def getCalculationDependencies(self, flat=False, deps=None):
232233

233234
def getCalculationDependants(self):
234235
"""Return a flat list of services who depend on this calculation.
235-
236-
This refers only to services who's Calculation UIDReferenceField
237-
have the value set to point to this calculation.
238-
239-
It has nothing to do with the services referenced in the
240-
calculation's Formula.
236+
237+
This refers only to services who's Calculation UIDReferenceField have
238+
the value set to point to this calculation.
239+
240+
It has nothing to do with the services referenced in the calculation's
241+
Formula.
241242
"""
242243
deps = []
243244
backrefs = get_backreferences(self, 'AnalysisServiceCalculation')

0 commit comments

Comments
 (0)