Projet

Général

Profil

0001-add-mathematics-filters-27709.patch

Nicolas Roche, 19 février 2019 14:41

Télécharger (6,51 ko)

Voir les différences:

Subject: [PATCH] add mathematics filters (#27709)

- correct "0|decimal" : display '0' instead of '',
- add "|add", "|subtract", "|mutliply" and "|divide" filters,
- current default behaviour is to display empty string on error.
 tests/test_formdata.py            | 60 ++++++++++++++++++++++++++++++-
 wcs/qommon/templatetags/qommon.py | 50 +++++++++++++++++++++++---
 2 files changed, 105 insertions(+), 5 deletions(-)
tests/test_formdata.py
7 7

  
8 8
from quixote import cleanup
9 9
from quixote.http_request import Upload
10
from qommon.template import Template
10
import qommon.errors
11
from qommon.template import Template, TemplateError
11 12
from qommon.form import PicklableUpload
12 13
from wcs.qommon.http_request import HTTPRequest
13 14
from wcs import fields, formdef
......
1290 1291
    formdata.data = {'0': time.strptime('2015-05-12', '%Y-%m-%d')}
1291 1292
    formdata.store()
1292 1293
    assert formdef.data_class().get(formdata.id).digest == 'plop  plop'
1294

  
1295
def test_mathematics_operators(pub, variable_test_data):
1296
    formdef = FormDef.select()[0]
1297
    formdata = formdef.data_class().select()[0]
1298
    for mode in (None, 'lazy'):
1299
        pub.substitutions.reset()
1300
        pub.substitutions.feed(formdef)
1301
        with pub.substitutions.temporary_feed(formdata, force_mode=mode):
1302
            # no arg
1303
            with pytest.raises(Exception,
1304
                               match=r'.*Could not find variable at start.*'):
1305
                WorkflowStatusItem.compute('{{ |decimal}}', raises=True)
1306

  
1307
            # no param
1308
            with pytest.raises(Exception,
1309
                               match=r'.*add requires 2 arguments, 1 provided'):
1310
                WorkflowStatusItem.compute('{{ 0|add }}', raises=True)
1311
            with pytest.raises(Exception,
1312
                               match=r'.*add requires 2 arguments, 1 provided'):
1313
                WorkflowStatusItem.compute('{{ 0|add: }}', raises=True)
1314

  
1315
            # string as param
1316
            assert WorkflowStatusItem.compute('{{ "1,1"|decimal }}', raises=True) == '1.1'
1317
            assert WorkflowStatusItem.compute('{{ "not a number"|decimal }}', raises=True) == ''
1318

  
1319
            # strings as arg
1320
            assert WorkflowStatusItem.compute('{{ 0.3|add:"1" }}', raises=True) == '1.3'
1321
            assert WorkflowStatusItem.compute('{{ 1.4|add:"not a number" }}', raises=True) == '1.4'
1322

  
1323
            # decimal
1324
            assert WorkflowStatusItem.compute('{{ ""|decimal }}', raises=True) == ''
1325
            assert WorkflowStatusItem.compute('{{ 0|decimal }}', raises=True) == '0'
1326
            assert WorkflowStatusItem.compute('{{ 2.1|decimal }}', raises=True) == '2.1'
1327
            assert WorkflowStatusItem.compute('{{ 2.2|decimal:2 }}', raises=True) == '2.20'
1328

  
1329
            # add
1330
            assert WorkflowStatusItem.compute('{{ 0|add:"" }}', raises=True) == '0'
1331
            assert WorkflowStatusItem.compute('{{ ""|add:0 }}', raises=True) == '0'
1332
            assert WorkflowStatusItem.compute('{{ 3.1|add:"" }}', raises=True) == '3.1'
1333
            assert WorkflowStatusItem.compute('{{ ""|add:3.2 }}', raises=True) == '3.2'
1334
            assert WorkflowStatusItem.compute('{{ 4|add:-0.7 }}', raises=True) == '3.3'
1335

  
1336
            # subtract
1337
            assert WorkflowStatusItem.compute('{{ 4.1|subtract:"" }}', raises=True) == '4.1'
1338
            assert WorkflowStatusItem.compute('{{ ""|subtract:-4.2 }}', raises=True) == '4.2'
1339
            assert WorkflowStatusItem.compute('{{ 5|subtract:0.7 }}', raises=True) == '4.3'
1340

  
1341
            # multiply
1342
            assert WorkflowStatusItem.compute('{{ "5,1"|multiply:"" }}', raises=True) == ''
1343
            assert WorkflowStatusItem.compute('{{ ""|multiply:"5.2"}}', raises=True) == ''
1344
            assert WorkflowStatusItem.compute('{{ "2.5"|multiply:2 }}', raises=True) == '5.0'
1345
            assert WorkflowStatusItem.compute('{{ "3"|multiply:2 }}', raises=True) == '6'
1346

  
1347
            # divide
1348
            assert WorkflowStatusItem.compute('{{ 6.1|divide:"" }}', raises=True) == ''
1349
            assert WorkflowStatusItem.compute('{{ ""|divide:6.2}}', raises=True) == ''
1350
            assert WorkflowStatusItem.compute('{{ 2|divide:3|decimal:2 }}', raises=True) == '0.67'
wcs/qommon/templatetags/qommon.py
112 112
    return defaultfilters.date(value, arg=arg)
113 113

  
114 114
def parse_decimal(value):
115
    if not value:
115
    if value is None:
116 116
        return None
117 117
    if isinstance(value, basestring):
118 118
        # replace , by . for French users comfort
......
124 124

  
125 125
@register.filter(is_safe=False)
126 126
def decimal(value, arg=None):
127
    if arg is None:
128
        return parse_decimal(value) or ''
129 127
    if not isinstance(value, Decimal):
130 128
        value = parse_decimal(value)
131
    return defaultfilters.floatformat(value, arg=arg)
129
    if value is None:
130
        return ''
131
    if arg is None:
132
        return value
133
    else:
134
        return defaultfilters.floatformat(value, arg=arg)
132 135

  
133 136
@register.filter(expects_localtime=True, is_safe=False)
134 137
def add_days(value, arg):
......
225 228
    }
226 229
    token.store()
227 230
    return '---===BUTTON:%s:%s===---' % (token.id, label)
231

  
232
@register.filter
233
def add(value, arg):
234
    v1 = parse_decimal(value)
235
    v2 = parse_decimal(arg)
236
    if v2 is None:
237
        return v1 if v1 is not None else ''
238
    if v1 is None:
239
        return v2 if v2 is not None else ''
240
    return v1 + v2
241

  
242
@register.filter
243
def subtract(value, arg):
244
    v1 = parse_decimal(value)
245
    v2 = parse_decimal(arg)
246
    if v2 is None:
247
        return v1 if v1 is not None else ''
248
    if v1 is None:
249
        return -v2 if v2 is not None else ''
250
    return v1 - v2
251

  
252
@register.filter
253
def multiply(value, arg):
254
    v1 = parse_decimal(value)
255
    v2 = parse_decimal(arg)
256
    if v1 is None or v2 is None:
257
        return ''
258
    return v1 * v2
259

  
260
@register.filter
261
def divide(value, arg):
262
    v1 = parse_decimal(value)
263
    v2 = parse_decimal(arg)
264
    if v1 is None or v2 is None:
265
        return ''
266
    try:
267
        return v1 / v2
268
    except ZeroDivisionError:
269
        return ''
228
-