Projet

Général

Profil

0001-templatetags-add-mathematics-filters-27709.patch

Nicolas Roche, 22 février 2019 17:26

Télécharger (9,6 ko)

Voir les différences:

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

 tests/test_formdata.py            | 109 +++++++++++++++++++++++++++++-
 wcs/qommon/templatetags/qommon.py |  58 +++++++++++++++-
 2 files changed, 165 insertions(+), 2 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
from qommon.template import Template, TemplateError
11 11
from qommon.form import PicklableUpload
12 12
from wcs.qommon.http_request import HTTPRequest
13 13
from wcs import fields, formdef
......
1336 1336

  
1337 1337
        tmpl = Template('{{ 4.12|decimal:form_var_arg }}')
1338 1338
        assert tmpl.render(context) == '4.120'
1339

  
1340
def test_mathematics_filters(pub, variable_test_data):
1341
    formdef = FormDef.select()[0]
1342
    formdata = formdef.data_class().select()[0]
1343
    for mode in (None, 'lazy'):
1344
        pub.substitutions.reset()
1345
        pub.substitutions.feed(formdef)
1346
        with pub.substitutions.temporary_feed(formdata, force_mode=mode):
1347
            # string as param
1348
            assert WorkflowStatusItem.compute('{{ "1,1"|add:0 }}', raises=True) == '1.1'
1349
            assert WorkflowStatusItem.compute('{{ "not a number"|add:1.2 }}', raises=True) == '1.2'
1350

  
1351
            # strings as arg
1352
            assert WorkflowStatusItem.compute('{{ 0.3|add:"1" }}', raises=True) == '1.3'
1353
            assert WorkflowStatusItem.compute('{{ 1.4|add:"not a number" }}', raises=True) == '1.4'
1354

  
1355
            # add
1356
            assert WorkflowStatusItem.compute('{{ 4|add:-0.9 }}', raises=True) == '3.1'
1357
            assert WorkflowStatusItem.compute('{{ "4"|add:-0.8 }}', raises=True) == '3.2'
1358
            assert WorkflowStatusItem.compute('{{ 4|add:"-0.7" }}', raises=True) == '3.3'
1359
            assert WorkflowStatusItem.compute('{{ "4"|add:"-0.6" }}', raises=True) == '3.4'
1360
            assert WorkflowStatusItem.compute('{{ ""|add:3.5 }}', raises=True) == '3.5'
1361
            assert WorkflowStatusItem.compute('{{ 3.6|add:"" }}', raises=True) == '3.6'
1362
            assert WorkflowStatusItem.compute('{{ ""|add:"" }}', raises=True) == '0'
1363
            assert WorkflowStatusItem.compute('{{ 0|add:"" }}', raises=True) == '0'
1364
            assert WorkflowStatusItem.compute('{{ ""|add:0 }}', raises=True) == '0'
1365
            assert WorkflowStatusItem.compute('{{ 0|add:0 }}', raises=True) == '0'
1366

  
1367
            # subtract
1368
            assert WorkflowStatusItem.compute('{{ 5.1|subtract:1 }}', raises=True) == '4.1'
1369
            assert WorkflowStatusItem.compute('{{ "5.2"|subtract:1 }}', raises=True) == '4.2'
1370
            assert WorkflowStatusItem.compute('{{ 5.3|subtract:"1" }}', raises=True) == '4.3'
1371
            assert WorkflowStatusItem.compute('{{ "5.4"|subtract:"1" }}', raises=True) == '4.4'
1372
            assert WorkflowStatusItem.compute('{{ ""|subtract:-4.5 }}', raises=True) == '4.5'
1373
            assert WorkflowStatusItem.compute('{{ 4.6|subtract:"" }}', raises=True) == '4.6'
1374
            assert WorkflowStatusItem.compute('{{ ""|subtract:"" }}', raises=True) == '0'
1375
            assert WorkflowStatusItem.compute('{{ 0|subtract:"" }}', raises=True) == '0'
1376
            assert WorkflowStatusItem.compute('{{ ""|subtract:0 }}', raises=True) == '0'
1377
            assert WorkflowStatusItem.compute('{{ 0|subtract:0 }}', raises=True) == '0'
1378

  
1379
            # multiply
1380
            assert WorkflowStatusItem.compute('{{ "3"|multiply:"2" }}', raises=True) == '6'
1381
            assert WorkflowStatusItem.compute('{{ 2.5|multiply:2 }}', raises=True) == '5.0'
1382
            assert WorkflowStatusItem.compute('{{ "2.5"|multiply:2 }}', raises=True) == '5.0'
1383
            assert WorkflowStatusItem.compute('{{ 2.5|multiply:"2" }}', raises=True) == '5.0'
1384
            assert WorkflowStatusItem.compute('{{ "2.5"|multiply:"2" }}', raises=True) == '5.0'
1385
            assert WorkflowStatusItem.compute('{{ ""|multiply:"2" }}', raises=True) == ''
1386
            assert WorkflowStatusItem.compute('{{ 2.5|multiply:"" }}', raises=True) == ''
1387
            assert WorkflowStatusItem.compute('{{ ""|multiply:"" }}', raises=True) == ''
1388
            assert WorkflowStatusItem.compute('{{ 0|multiply:"" }}', raises=True) == ''
1389
            assert WorkflowStatusItem.compute('{{ ""|multiply:0 }}', raises=True) == ''
1390
            assert WorkflowStatusItem.compute('{{ 0|multiply:0 }}', raises=True) == '0'
1391

  
1392
            # divide
1393
            assert WorkflowStatusItem.compute('{{ 16|divide:2 }}', raises=True) == '8'
1394
            assert WorkflowStatusItem.compute('{{ 2|divide:3|decimal:2 }}', raises=True) == '0.67'
1395
            assert WorkflowStatusItem.compute('{{ 6|divide:0.75 }}', raises=True) == '8'
1396
            assert WorkflowStatusItem.compute('{{ "6"|divide:0.75 }}', raises=True) == '8'
1397
            assert WorkflowStatusItem.compute('{{ 6|divide:"0.75" }}', raises=True) == '8'
1398
            assert WorkflowStatusItem.compute('{{ "6"|divide:"0.75" }}', raises=True) == '8'
1399
            assert WorkflowStatusItem.compute('{{ ""|divide:"2" }}', raises=True) == ''
1400
            assert WorkflowStatusItem.compute('{{ 6|divide:"" }}', raises=True) == ''
1401
            assert WorkflowStatusItem.compute('{{ ""|divide:"" }}', raises=True) == ''
1402
            assert WorkflowStatusItem.compute('{{ 0|divide:"" }}', raises=True) == ''
1403
            assert WorkflowStatusItem.compute('{{ ""|divide:0 }}', raises=True) == ''
1404
            assert WorkflowStatusItem.compute('{{ 0|divide:0 }}', raises=True) == ''
1405

  
1406
            # no arg
1407
            with pytest.raises(Exception, match=r'.*Could not find variable at start.*'):
1408
                WorkflowStatusItem.compute('{{ |add:2}}', raises=True)
1409

  
1410
            # no param
1411
            with pytest.raises(Exception, match=r'.*add requires 2 arguments, 1 provided'):
1412
                WorkflowStatusItem.compute('{{ 0|add }}', raises=True)
1413
            with pytest.raises(Exception, match=r'.*add requires 2 arguments, 1 provided'):
1414
                WorkflowStatusItem.compute('{{ 0|add: }}', raises=True)
1415

  
1416
def test_lazy_formdata_mathematics_filters(pub):
1417
    formdef = FormDef()
1418
    formdef.name = 'foobar'
1419
    formdef.url_name = 'foobar'
1420
    formdef.fields = [
1421
        fields.StringField(id='0', label='term1', varname='term1'),
1422
        fields.StringField(id='1', label='term2', varname='term2')
1423
    ]
1424
    formdef.store()
1425
    formdata = formdef.data_class()()
1426
    formdata.data = {'0': '3', '1': '4'}
1427
    formdata.store()
1428
    pub.substitutions.feed(formdata)
1429
    for mode in (None, 'lazy'):
1430
        context = pub.substitutions.get_context_variables(mode=mode)
1431

  
1432
        tmpl = Template('{{ form_var_term1|decimal }}')
1433
        assert tmpl.render(context) == '3'
1434

  
1435
        tmpl = Template('{{ form_var_term1|add:form_var_term2 }}')
1436
        assert tmpl.render(context) == '7'
1437

  
1438
        tmpl = Template('{{ form_var_term1|subtract:form_var_term2 }}')
1439
        assert tmpl.render(context) == '-1'
1440

  
1441
        tmpl = Template('{{ form_var_term1|multiply:form_var_term2 }}')
1442
        assert tmpl.render(context) == '12'
1443

  
1444
        tmpl = Template('{{ form_var_term1|divide:form_var_term2 }}')
1445
        assert tmpl.render(context) == '0.75'
wcs/qommon/templatetags/qommon.py
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import datetime
18
from decimal import Decimal
18
from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
19 19

  
20 20
from django import template
21 21
from django.template import defaultfilters
......
229 229
    }
230 230
    token.store()
231 231
    return '---===BUTTON:%s:%s===---' % (token.id, label)
232

  
233
@register.filter
234
def add(term1, term2):
235
    '''replace the "add" native django filter'''
236
    if hasattr(term1, 'get_value'):
237
        term1 = term1.get_value()  # unlazy
238
    if hasattr(term2, 'get_value'):
239
        term2 = term2.get_value()  # unlazy
240
    term1 = parse_decimal(term1)
241
    term2 = parse_decimal(term2)
242
    if term1 is None:
243
        term1 = Decimal(0)
244
    if term2 is None:
245
        term2 = Decimal(0)
246
    return term1 + term2
247

  
248
@register.filter
249
def subtract(term1, term2):
250
    if hasattr(term1, 'get_value'):
251
        term1 = term1.get_value()  # unlazy
252
    if hasattr(term2, 'get_value'):
253
        term2 = term2.get_value()  # unlazy
254
    term1 = parse_decimal(term1)
255
    term2 = parse_decimal(term2)
256
    if term1 is None:
257
        term1 = Decimal(0)
258
    if term2 is None:
259
        term2 = Decimal(0)
260
    return term1 - term2
261

  
262
@register.filter
263
def multiply(term1, term2):
264
    if hasattr(term1, 'get_value'):
265
        term1 = term1.get_value()  # unlazy
266
    if hasattr(term2, 'get_value'):
267
        term2 = term2.get_value()  # unlazy
268
    term1 = parse_decimal(term1)
269
    term2 = parse_decimal(term2)
270
    if term1 is None or term2 is None:
271
        return ''
272
    return term1 * term2
273

  
274
@register.filter
275
def divide(term1, term2):
276
    if hasattr(term1, 'get_value'):
277
        term1 = term1.get_value()  # unlazy
278
    if hasattr(term2, 'get_value'):
279
        term2 = term2.get_value()  # unlazy
280
    term1 = parse_decimal(term1)
281
    term2 = parse_decimal(term2)
282
    if term1 is None or term2 is None:
283
        return ''
284
    try:
285
        return term1 / term2
286
    except DecimalInvalidOperation:
287
        return ''
232
-