Projet

Général

Profil

0001-templatetags-add-maths-filters-29337.patch

Thomas Noël, 24 décembre 2018 19:40

Télécharger (11,8 ko)

Voir les différences:

Subject: [PATCH] templatetags: add maths filters (#29337)

 tests/test_templates.py           | 127 ++++++++++++++++++++++++++++++
 wcs/qommon/templatetags/qommon.py |  41 ++++++++++
 2 files changed, 168 insertions(+)
tests/test_templates.py
2 2

  
3 3
import pytest
4 4

  
5
import datetime
6
from decimal import Decimal
7

  
5 8
from quixote import cleanup
6 9
from qommon.template import Template, TemplateError
7 10
from wcs.conditions import Condition
......
257 260
    assert tmpl.render({'plop': '1.99'}) == ''
258 261
    assert tmpl.render({'plop': 'x'}) == 'hello'
259 262
    assert tmpl.render({'plop': None}) == 'hello'  # will be str > int, always True.
263

  
264
def test_add_templatetag():
265
    for a in ('2', '"2"', '2.0', '"2.0"'):
266
        for b in (3, '"3"', '3.0', '"3.0"'):
267
            assert Template('{{ %s|add:%s }}' % (a, b)).render() == '5'
268
        for b in (3.01, '"3.01"'):
269
            assert Template('{{ %s|add:%s }}' % (a, b)).render() == '5.01'
270
        for b in ('""', '"x"'):
271
            assert Template('{{ %s|add:%s }}' % (a, b)).render() == ''
272
            assert Template('{{ %s|add:%s }}' % (b, a)).render() == ''
273
        # no 'foo' variable: template error
274
        assert Template('{{ %s|add:foo }}' % a).render() == '{{ %s|add:foo }}' % a
275
    for a in ('2.01', '"2.01"'):
276
        for b in (3, '"3"', '3.0', '"3.0"'):
277
            assert Template('{{ %s|add:%s }}' % (a, b)).render() == '5.01'
278
        for b in (3.01, '"3.01"'):
279
            assert Template('{{ %s|add:%s }}' % (a, b)).render() == '5.02'
280
        for b in ('""', '"x"'):
281
            assert Template('{{ %s|add:%s }}' % (a, b)).render() == ''
282
            assert Template('{{ %s|add:%s }}' % (b, a)).render() == ''
283
        assert Template('{{ %s|add:foo }}' % a).render() == '{{ %s|add:foo }}' % a
284

  
285
    for a in (2, '2', '2.0', 2.0, Decimal(2)):
286
        for b in (3, '3', '3.0', 3.0, Decimal(3)):
287
            assert Template('{{ a|add:b }}').render({'a': a, 'b': b}) == '5'
288
        for b in (3.01, '3.01', Decimal(3.01)):
289
            assert Template('{{ a|add:b }}').render({'a': a, 'b': b}) == '5.01'
290
        for b in ('', 'x', None):
291
            assert Template('{{ a|add:b }}').render({'a': a, 'b': b}) == ''
292
            assert Template('{{ b|add:a }}').render({'a': a, 'b': b}) == ''
293
        assert Template('{{ a|add:foo }}').render({'a': a}) == '{{ a|add:foo }}'
294
    for a in (2.01, '2.01', Decimal(2.01)):
295
        for b in (3, '3', '3.0', 3.0, Decimal(3)):
296
            assert Template('{{ a|add:b }}').render({'a': a, 'b': b}) == '5.01'
297
        for b in (3.01, '3.01', Decimal(3.01)):
298
            assert Template('{{ a|add:b }}').render({'a': a, 'b': b}) == '5.02'
299
        for b in ('', 'x', None):
300
            assert Template('{{ a|add:b }}').render({'a': a, 'b': b}) == ''
301
            assert Template('{{ b|add:a }}').render({'a': a, 'b': b}) == ''
302
        assert Template('{{ a|add:foo }}').render({'a': a}) == '{{ a|add:foo }}'
303

  
304
    assert Template('{{ ""|add:"" }}').render() == ''
305
    assert Template('{{ ""|add:"x" }}').render() == ''
306
    assert Template('{{ "x"|add:"x" }}').render() == ''
307
    assert Template('{{ "x"|add:"" }}').render() == ''
308
    assert Template('{{ foo|add:2 }}').render() == ''
309
    assert Template('{{ foo|add:bar }}').render() == '{{ foo|add:bar }}'
310

  
311
def test_add_templatetag_dates():
312
    assert Template('{{ "2017-12-21"|date|add:"2" }}').render() == 'Dec. 23, 2017'
313
    assert Template('{{ "2017-12-21"|date|add:2 }}').render() == 'Dec. 23, 2017'
314
    assert Template('{{ "2017-12-21"|date|add:"2d" }}').render() == 'Dec. 23, 2017'
315
    assert Template('{{ "2017-12-21"|date|add:"2 days" }}').render() == 'Dec. 23, 2017'
316
    assert Template('{{ "2017-12-21"|date|add:"2 DAYS" }}').render() == 'Dec. 23, 2017'
317
    assert Template('{{ "2017-12-21"|date|add:"2j" }}').render() == 'Dec. 23, 2017'
318
    assert Template('{{ "2017-12-21"|datetime|add:"2" }}').render() == 'Dec. 23, 2017, midnight'
319
    # forgot cast -> not a date -> no result
320
    assert Template('{{ "2017-12-21"|add:"2" }}').render() == ''
321
    assert Template('{{ "2017-12-21 10:32"|add:"2" }}').render() == ''
322
    # not a date -> cannot cast -> no result
323
    assert Template('{{ "foobar"|date|add:"2" }}').render() == ''
324
    assert Template('{{ "foobar"|datetime|add:"2" }}').render() == ''
325

  
326
    assert Template('{{ "2017-12-21 10:32"|datetime|add:2 }}').render() == 'Dec. 23, 2017, 10:32 a.m.'
327
    assert Template('{{ "2017-12-21 10:32"|date|add:2 }}').render() == 'Dec. 23, 2017'
328
    assert Template('{{ "2017-12-21 10:32"|datetime|add:2.0 }}').render() == 'Dec. 23, 2017, 10:32 a.m.'
329
    assert Template('{{ "2017-12-21 10:32"|datetime|add:-2 }}').render() == 'Dec. 19, 2017, 10:32 a.m.'
330
    assert Template('{{ "2017-12-21 10:32"|datetime|add:-2.0 }}').render() == 'Dec. 19, 2017, 10:32 a.m.'
331
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"2" }}').render() == 'Dec. 23, 2017, 10:32 a.m.'
332
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"2.0" }}').render() == 'Dec. 23, 2017, 10:32 a.m.'
333
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"-2" }}').render() == 'Dec. 19, 2017, 10:32 a.m.'
334
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"-2.0" }}').render() == 'Dec. 19, 2017, 10:32 a.m.'
335
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"2.5" }}').render() == 'Dec. 23, 2017, 10:32 p.m.'
336
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"-2.5" }}').render() == 'Dec. 18, 2017, 10:32 p.m.'
337

  
338
    # with units
339
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"2h" }}').render() == 'Dec. 21, 2017, 12:32 p.m.'
340
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"-2h" }}').render() == 'Dec. 21, 2017, 8:32 a.m.'
341
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"2.5h" }}').render() == 'Dec. 21, 2017, 1:02 p.m.'
342
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"-2.5h" }}').render() == 'Dec. 21, 2017, 8:02 a.m.'
343
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"20m" }}').render() == 'Dec. 21, 2017, 10:52 a.m.'
344
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"20min" }}').render() == 'Dec. 21, 2017, 10:52 a.m.'
345
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"-20m" }}').render() == 'Dec. 21, 2017, 10:12 a.m.'
346
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"120s" }}').render() == 'Dec. 21, 2017, 10:34 a.m.'
347
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"120seconds" }}').render() == 'Dec. 21, 2017, 10:34 a.m.'
348
    assert Template('{{ "2017-12-21 10:32"|datetime|add:"-120sec" }}').render() == 'Dec. 21, 2017, 10:30 a.m.'
349

  
350
    # compare after math
351
    assert Template('{% if "2017-12-21"|date|add:"2" > "2017-12-21"|date %}OK{% endif %}').render() == 'OK'
352
    assert Template('{% if "2017-12-21"|datetime|add:"2" > "2017-12-21"|datetime %}OK{% endif %}').render() == 'OK'
353
    assert Template('{% if "2017-12-21"|date|add:"1" == "2017-12-22"|date %}OK{% endif %}').render() == 'OK'
354
    assert Template('{% if "2017-12-21"|datetime|add:"1" == "2017-12-22"|datetime %}OK{% endif %}').render() == 'OK'
355
    assert Template('{% if "2017-12-21 12:00"|datetime|add:"12h" == "2017-12-22"|datetime %}OK{% endif %}').render() == 'OK'
356

  
357
    foo = "2017-12-21"
358
    bar = "2017-12-23"
359
    assert Template('{% if foo|date|add:"2" > foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
360
    assert Template('{% if foo|date|add:"1" < bar|date %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
361
    assert Template('{% if foo|date|add:"2" == bar|date %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
362
    assert Template('{% if foo|date|add:"3" > bar|date %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
363
    assert Template('{% if foo|date|add:"3" == bar|date|add:"1" %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
364
    assert Template('{% if foo|date|add:"2" > "2017-12-22"|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
365
    # with units
366
    assert Template('{% if foo|date|add:"2s" == foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
367
    assert Template('{% if foo|date|add:"2m" == foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
368
    assert Template('{% if foo|date|add:"2h" == foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
369
    assert Template('{% if foo|date|add:"0j" == foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
370
    assert Template('{% if foo|date|add:"25h" > foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
371
    assert Template('{% if foo|date|add:"1441min" > foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
372
    assert Template('{% if foo|date|add:"25h" > foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
373
    assert Template('{% if foo|date|add:"80 hours" > bar|date %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
374

  
375
    # incompatible types: always KO
376
    assert Template('{% if "2017-12-21"|date|add:"2" == "2017-12-21" %}OK{% else %}KO{% endif %}').render() == 'KO'
377
    assert Template('{% if "2017-12-21"|date|add:"2" > "2017-12-21" %}OK{% else %}KO{% endif %}').render() == 'KO'
378
    assert Template('{% if "2017-12-21"|date|add:"2" < "2017-12-21" %}OK{% else %}KO{% endif %}').render() == 'KO'
379
    # Python cannot compare datetime.date and datetime.datetime !
380
    assert Template('{% if "2017-12-21"|date|add:"2" > "2017-12-21"|datetime %}OK{% else %}KO{% endif %}').render() == 'KO'
381

  
382
    # forgot cast -> strange results ! All of these tests are just
383
    # side effects of comparing "" and "2017-12-21"
384
    assert Template('{% if "2017-12-21"|add:"2" == "2017-12-21" %}OK{% else %}KO{% endif %}').render() == 'KO'
385
    assert Template('{% if "2017-12-21"|add:"2" > "2017-12-21" %}OK{% else %}KO{% endif %}').render() == 'KO'
386
    assert Template('{% if "2017-12-21"|add:"2" < "2017-12-21" %}OK{% else %}KO{% endif %}').render() == 'OK'
wcs/qommon/templatetags/qommon.py
16 16

  
17 17
import datetime
18 18
from decimal import Decimal
19
import re
19 20

  
20 21
from django import template
21 22
from django.template import defaultfilters
......
122 123
        value = parse_decimal(value)
123 124
    return defaultfilters.floatformat(value, arg=arg)
124 125

  
126
def add_date(value, delta):
127
    time_unit = 'd'
128
    if isinstance(delta, basestring):
129
        delta = delta.strip().lower()
130
        # replace , by . for French users comfort
131
        delta = delta.replace(',', '.')
132
        re_delta = re.match('^([+-]?[\d\.]+)\s*([smhd]?).*', delta)
133
        if not re_delta:
134
            return value
135
        delta, time_unit = re_delta.group(1), re_delta.group(2)
136
    try:
137
        delta = int(delta)
138
    except ValueError:
139
        try:
140
            delta = float(delta)
141
        except ValueError:
142
            return ''
143
    if time_unit == 'h':
144
        delta = datetime.timedelta(hours=delta)
145
    elif time_unit == 'm':
146
        delta = datetime.timedelta(minutes=delta)
147
    elif time_unit == 's':
148
        delta = datetime.timedelta(seconds=delta)
149
    else:
150
        delta = datetime.timedelta(days=delta)
151
    return value + delta
152

  
153
@register.filter(expects_localtime=True, is_safe=False)
154
def add(value, term):
155
    if isinstance(value, (datetime.datetime, datetime.date)):
156
        return add_date(value, term)
157

  
158
    value = parse_decimal(value)
159
    if value is None:
160
        return ''
161
    term = parse_decimal(term)
162
    if term is None:
163
        return ''
164
    return value + term
165

  
125 166
@register.simple_tag
126 167
def standard_text(text_id):
127 168
    return mark_safe(TextsDirectory.get_html_text(str(text_id)))
128
-