Projet

Général

Profil

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

Thomas Noël, 24 décembre 2018 16:15

Télécharger (10,9 ko)

Voir les différences:

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

 tests/test_templates.py           | 117 ++++++++++++++++++++++++++++++
 wcs/qommon/templatetags/qommon.py |  46 ++++++++++++
 2 files changed, 163 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() == '2'
272
            assert Template('{{ %s|add:%s }}' % (b, a)).render() == '2'
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() == '2.01'
282
            assert Template('{{ %s|add:%s }}' % (b, a)).render() == '2.01'
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}) == '2'
292
            assert Template('{{ b|add:a }}').render({'a': a, 'b': b}) == '2'
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}) == '2.01'
301
            assert Template('{{ b|add:a }}').render({'a': a, 'b': b}) == '2.01'
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() == '2'
309
    assert Template('{{ foo|add:"2" }}').render() == '2'
310
    assert Template('{{ foo|add:2.01 }}').render() == '2.01'
311
    assert Template('{{ foo|add:"2.01" }}').render() == '2.01'
312
    assert Template('{{ foo|add:"" }}').render() == ''
313
    assert Template('{{ foo|add:"x" }}').render() == ''
314
    assert Template('{{ foo|add:bar }}').render() == '{{ foo|add:bar }}'
315

  
316
def test_add_templatetag_dates():
317
    assert Template('{{ "2017-12-21"|add:"2" }}').render() == 'Dec. 23, 2017, midnight'
318
    assert Template('{{ "2017-12-21"|add:2 }}').render() == 'Dec. 23, 2017, midnight'
319
    assert Template('{{ "2017-12-21"|add:"2d" }}').render() == 'Dec. 23, 2017, midnight'
320
    assert Template('{{ "2017-12-21"|add:"2 days" }}').render() == 'Dec. 23, 2017, midnight'
321
    assert Template('{{ "2017-12-21"|add:"2 DAYS" }}').render() == 'Dec. 23, 2017, midnight'
322
    assert Template('{{ "2017-12-21"|add:"2j" }}').render() == 'Dec. 23, 2017, midnight'
323
    assert Template('{{ "2017-12-21"|date|add:2 }}').render() == 'Dec. 23, 2017'
324

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

  
336
    assert Template('{{ "2017-12-21 10:32"|add:"2h" }}').render() == 'Dec. 21, 2017, 12:32 p.m.'
337
    assert Template('{{ "2017-12-21 10:32"|add:"-2h" }}').render() == 'Dec. 21, 2017, 8:32 a.m.'
338
    assert Template('{{ "2017-12-21 10:32"|add:"2.5h" }}').render() == 'Dec. 21, 2017, 1:02 p.m.'
339
    assert Template('{{ "2017-12-21 10:32"|add:"-2.5h" }}').render() == 'Dec. 21, 2017, 8:02 a.m.'
340

  
341
    assert Template('{{ "2017-12-21 10:32"|add:"20m" }}').render() == 'Dec. 21, 2017, 10:52 a.m.'
342
    assert Template('{{ "2017-12-21 10:32"|add:"20min" }}').render() == 'Dec. 21, 2017, 10:52 a.m.'
343
    assert Template('{{ "2017-12-21 10:32"|add:"-20m" }}').render() == 'Dec. 21, 2017, 10:12 a.m.'
344

  
345
    assert Template('{{ "2017-12-21 10:32"|add:"120s" }}').render() == 'Dec. 21, 2017, 10:34 a.m.'
346
    assert Template('{{ "2017-12-21 10:32"|add:"120seconds" }}').render() == 'Dec. 21, 2017, 10:34 a.m.'
347
    assert Template('{{ "2017-12-21 10:32"|add:"-120sec" }}').render() == 'Dec. 21, 2017, 10:30 a.m.'
348

  
349
    # compare dates after add
350
    assert Template('{% if "2017-12-21"|date|add:"2" > "2017-12-21"|date %}OK{% endif %}').render() == 'OK'
351
    assert Template('{% if "2017-12-21"|add:"2"|date > "2017-12-21"|date %}OK{% endif %}').render() == 'OK'
352
    assert Template('{% if "2017-12-21"|add:"2" > "2017-12-21"|datetime %}OK{% endif %}').render() == 'OK'
353
    assert Template('{% if "2017-12-21"|add:"1"|date == "2017-12-22"|date %}OK{% endif %}').render() == 'OK'
354
    assert Template('{% if "2017-12-21"|add:"1" == "2017-12-22"|datetime %}OK{% endif %}').render() == 'OK'
355
    foo = datetime.date(2017, 12, 21)
356
    bar = datetime.date(2017, 12, 23)
357
    assert Template('{% if foo|add:"2" > foo %}OK{% endif %}').render({'foo': foo}) == 'OK'
358
    assert Template('{% if foo|add:"1" < bar %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
359
    assert Template('{% if foo|add:"2" == bar %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
360
    assert Template('{% if foo|add:"3" > bar %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
361
    assert Template('{% if foo|add:"3" == bar|add:"1" %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
362
    assert Template('{% if foo|add:"2" > "2017-12-22"|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
363

  
364
    assert Template('{% if foo|add:"2s" == foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
365
    assert Template('{% if foo|add:"2m" == foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
366
    assert Template('{% if foo|add:"2h" == foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
367
    assert Template('{% if foo|add:"0j" == foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
368
    assert Template('{% if foo|add:"25h" > foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
369
    assert Template('{% if foo|add:"1441min" > foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
370
    assert Template('{% if foo|add:"25h" > foo|date %}OK{% endif %}').render({'foo': foo}) == 'OK'
371
    assert Template('{% if foo|add:"80 hours" > bar %}OK{% endif %}').render({'foo': foo, 'bar': bar}) == 'OK'
372

  
373
    # incompatible types
374
    assert Template('{% if "2017-12-21"|add:"2" > "2017-12-21" %}OK{% else %}KO{% endif %}').render() == 'KO'
375
    # Python cannot compare datetime.date and datetime.datetime !
376
    assert Template('{% if "2017-12-21"|add:"2" > "2017-12-21"|date %}OK{% else %}KO{% endif %}').render() == 'KO'
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
        return value + datetime.timedelta(hours=delta)
145
    if time_unit == 'm':
146
        return value + datetime.timedelta(minutes=delta)
147
    if time_unit == 's':
148
        return value + datetime.timedelta(seconds=delta)
149
    return value + datetime.timedelta(days=delta)
150

  
151
@register.filter(expects_localtime=True, is_safe=False)
152
def add(value, arg):
153
    # guess if value looks like a date
154
    if not isinstance(value, (datetime.datetime, datetime.date)):
155
        guess_date = parse_datetime(value) or parse_date(value)
156
        if guess_date:
157
            value = guess_date
158
    if isinstance(value, (datetime.datetime, datetime.date)):
159
        return add_date(value, arg)
160

  
161
    value = parse_decimal(value)
162
    arg = parse_decimal(arg)
163
    if value is None and arg is None:
164
        return ''
165
    if value is None:
166
        return arg
167
    if arg is None:
168
        return value
169
    return value + arg
170

  
125 171
@register.simple_tag
126 172
def standard_text(text_id):
127 173
    return mark_safe(TextsDirectory.get_html_text(str(text_id)))
128
-