From e66333b93bc2c86a95f3e4733dc32e72042bae78 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 2 Sep 2022 15:55:57 +0200
Subject: [PATCH] misc: remove mathematic filters + split (#68673)

they are defined in publik-django-templatetags
---
 combo/public/templatetags/combo.py |  95 -------------
 tests/test_public_templatetags.py  | 213 -----------------------------
 2 files changed, 308 deletions(-)

diff --git a/combo/public/templatetags/combo.py b/combo/public/templatetags/combo.py
index 0023dbcf..caa817ec 100644
--- a/combo/public/templatetags/combo.py
+++ b/combo/public/templatetags/combo.py
@@ -18,10 +18,6 @@
 import copy
 import datetime
 import json
-import math
-from decimal import Decimal
-from decimal import DivisionByZero as DecimalDivisionByZero
-from decimal import InvalidOperation as DecimalInvalidOperation
 
 import django
 from django import template
@@ -335,11 +331,6 @@ def has_role(user, groupname):
     return user.groups.filter(name=groupname).exists()
 
 
-@register.filter
-def split(string, separator=' '):
-    return (force_str(string) or '').split(separator)
-
-
 @register.filter
 def strip(string, chars=None):
     if not string:
@@ -567,81 +558,6 @@ def iterate_days_until(value, until):
     yield value
 
 
-def parse_decimal(value, default=Decimal(0)):
-    if isinstance(value, str):
-        # replace , by . for French users comfort
-        value = value.replace(',', '.')
-    try:
-        return Decimal(value).quantize(Decimal('1.0000')).normalize()
-    except (ArithmeticError, TypeError):
-        return default
-
-
-@register.filter(is_safe=False)
-def decimal(value, arg=None):
-    if not isinstance(value, Decimal):
-        value = parse_decimal(value)
-    if arg is None:
-        return value
-    return defaultfilters.floatformat(value, arg=arg)
-
-
-@register.filter
-def add(term1, term2):
-    '''replace the "add" native django filter'''
-
-    if term1 is None:
-        term1 = ''
-    if term2 is None:
-        term2 = ''
-    term1_decimal = parse_decimal(term1, default=None)
-    term2_decimal = parse_decimal(term2, default=None)
-
-    if term1_decimal is not None and term2_decimal is not None:
-        return term1_decimal + term2_decimal
-    if term1 == '' and term2_decimal is not None:
-        return term2_decimal
-    if term2 == '' and term1_decimal is not None:
-        return term1_decimal
-    return defaultfilters.add(term1, term2)
-
-
-@register.filter
-def subtract(term1, term2):
-    return parse_decimal(term1) - parse_decimal(term2)
-
-
-@register.filter
-def multiply(term1, term2):
-    return parse_decimal(term1) * parse_decimal(term2)
-
-
-@register.filter
-def divide(term1, term2):
-    try:
-        return parse_decimal(term1) / parse_decimal(term2)
-    except DecimalInvalidOperation:
-        return ''
-    except DecimalDivisionByZero:
-        return ''
-
-
-@register.filter
-def ceil(value):
-    '''the smallest integer value greater than or equal to value'''
-    return decimal(math.ceil(parse_decimal(value)))
-
-
-@register.filter
-def floor(value):
-    return decimal(math.floor(parse_decimal(value)))
-
-
-@register.filter(name='abs')
-def abs_(value):
-    return decimal(abs(parse_decimal(value)))
-
-
 @register.filter(is_safe=False)
 def phonenumber_fr(value, separator=' '):
     DROMS = ('262', '508', '590', '594', '596')
@@ -683,14 +599,3 @@ def extra_context(cell, request):
     if hasattr(cell, 'repeat_index'):
         ctx['repeat_index'] = cell.repeat_index
     return ctx
-
-
-@register.filter(name='sum')
-def sum_(list_):
-    if isinstance(list_, str):
-        # do not consider string as iterable, to avoid misusage
-        return ''
-    try:
-        return sum(parse_decimal(term) for term in list_)
-    except TypeError:  # list_ is not iterable
-        return ''
diff --git a/tests/test_public_templatetags.py b/tests/test_public_templatetags.py
index 8d4aa6e6..e15a1456 100644
--- a/tests/test_public_templatetags.py
+++ b/tests/test_public_templatetags.py
@@ -121,15 +121,6 @@ def test_has_role():
     assert t.render(context) == 'False'
 
 
-def test_split():
-    t = Template('{% for x in plop|split %}{{x}}<br>{% endfor %}')
-    assert t.render(Context({'plop': 'ab cd ef'})) == 'ab<br>cd<br>ef<br>'
-    t = Template('{% for x in plop|split:"|" %}{{x}} {% endfor %}')
-    assert t.render(Context({'plop': 'ab|cd|ef'})) == 'ab cd ef '
-    t = Template('{% for x in plop|split:"|" %}{{x}} {% endfor %}')
-    assert t.render(Context({'plop': 42})) == '42 '
-
-
 def test_strip_templatetag():
     tmpl = Template('{{ foo|strip }}')
     assert tmpl.render(Context()) == ''
@@ -610,197 +601,6 @@ def test_iterate_days_until():
     assert t.render(Context({'value': 'error1', 'value2': 'error2'})) == ''
 
 
-def test_decimal_templatetag():
-    tmpl = Template('{{ plop|decimal }}')
-    assert tmpl.render(Context({'plop': 'toto'})) == '0'
-    assert tmpl.render(Context({'plop': '3.14'})) == '3.14'
-    assert tmpl.render(Context({'plop': '3,14'})) == '3.14'
-    assert tmpl.render(Context({'plop': 3.14})) == '3.14'
-    assert tmpl.render(Context({'plop': 12345.678})) == '12345.678'
-    assert tmpl.render(Context({'plop': None})) == '0'
-    assert tmpl.render(Context({'plop': 0})) == '0'
-
-    tmpl = Template('{{ plop|decimal:3 }}')
-    assert tmpl.render(Context({'plop': '3.14'})) == '3.140'
-    assert tmpl.render(Context({'plop': None})) == '0.000'
-    tmpl = Template('{{ plop|decimal:"3" }}')
-    assert tmpl.render(Context({'plop': '3.14'})) == '3.140'
-    assert tmpl.render(Context({'plop': None})) == '0.000'
-
-    tmpl = Template('{% if plop|decimal > 2 %}hello{% endif %}')
-    assert tmpl.render(Context({'plop': 3})) == 'hello'
-    assert tmpl.render(Context({'plop': '3'})) == 'hello'
-    assert tmpl.render(Context({'plop': 2.001})) == 'hello'
-    assert tmpl.render(Context({'plop': '2.001'})) == 'hello'
-    assert tmpl.render(Context({'plop': 1})) == ''
-    assert tmpl.render(Context({'plop': 1.99})) == ''
-    assert tmpl.render(Context({'plop': '1.99'})) == ''
-    assert tmpl.render(Context({'plop': 'x'})) == ''
-    assert tmpl.render(Context({'plop': None})) == ''
-    assert tmpl.render(Context({'plop': 0})) == ''
-
-    tmpl = Template('{% if "3"|decimal == 3 %}hello{% endif %}')
-    assert tmpl.render(Context()) == 'hello'
-    tmpl = Template('{% if "3"|decimal == 3.0 %}hello{% endif %}')
-    assert tmpl.render(Context()) == 'hello'
-    tmpl = Template('{% if 3|decimal == 3 %}hello{% endif %}')
-    assert tmpl.render(Context()) == 'hello'
-    tmpl = Template('{% if 3.0|decimal == 3 %}hello{% endif %}')
-    assert tmpl.render(Context()) == 'hello'
-    tmpl = Template('{% if 3|decimal|decimal == 3 %}hello{% endif %}')
-    assert tmpl.render(Context()) == 'hello'
-
-
-def test_mathematics_templatetag():
-    tmpl = Template('{{ term1|add:term2 }}')
-
-    # using strings
-    assert tmpl.render(Context({'term1': '1.1', 'term2': 0})) == '1.1'
-    assert tmpl.render(Context({'term1': 'not a number', 'term2': 1.2})) == ''
-    assert tmpl.render(Context({'term1': 0.3, 'term2': "1"})) == '1.3'
-    assert tmpl.render(Context({'term1': 1.4, 'term2': "not a number"})) == ''
-
-    # add
-    assert tmpl.render(Context({'term1': 4, 'term2': -0.9})) == '3.1'
-    assert tmpl.render(Context({'term1': '4', 'term2': -0.8})) == '3.2'
-    assert tmpl.render(Context({'term1': 4, 'term2': '-0.7'})) == '3.3'
-    assert tmpl.render(Context({'term1': '4', 'term2': '-0.6'})) == '3.4'
-    assert tmpl.render(Context({'term1': '', 'term2': 3.5})) == '3.5'
-    assert tmpl.render(Context({'term1': None, 'term2': 3.5})) == '3.5'
-    assert tmpl.render(Context({'term1': 3.6, 'term2': ''})) == '3.6'
-    assert tmpl.render(Context({'term1': '', 'term2': ''})) == ''
-    assert tmpl.render(Context({'term1': 3.6, 'term2': None})) == '3.6'
-    assert tmpl.render(Context({'term1': 0, 'term2': ''})) == '0'
-    assert tmpl.render(Context({'term1': '', 'term2': 0})) == '0'
-    assert tmpl.render(Context({'term1': 0, 'term2': 0})) == '0'
-
-    # if term is '' or None and other term is decimal
-    assert tmpl.render(Context({'term1': '', 'term2': 2.2})) == '2.2'
-    assert tmpl.render(Context({'term1': None, 'term2': 2.2})) == '2.2'
-    assert tmpl.render(Context({'term1': 2.2, 'term2': ''})) == '2.2'
-    assert tmpl.render(Context({'term1': 2.2, 'term2': None})) == '2.2'
-
-    # add using ',' instead of '.' decimal separator
-    assert tmpl.render(Context({'term1': '1,1', 'term2': '2,2'})) == '3.3'
-    assert tmpl.render(Context({'term1': '1,1', 'term2': '2.2'})) == '3.3'
-    assert tmpl.render(Context({'term1': '1,1', 'term2': 2.2})) == '3.3'
-    assert tmpl.render(Context({'term1': '1,1', 'term2': 0})) == '1.1'
-    assert tmpl.render(Context({'term1': '1,1', 'term2': ''})) == '1.1'
-    assert tmpl.render(Context({'term1': '1,1', 'term2': None})) == '1.1'
-    assert tmpl.render(Context({'term1': '1.1', 'term2': '2,2'})) == '3.3'
-    assert tmpl.render(Context({'term1': 1.1, 'term2': '2,2'})) == '3.3'
-    assert tmpl.render(Context({'term1': 0, 'term2': '2,2'})) == '2.2'
-    assert tmpl.render(Context({'term1': '', 'term2': '2,2'})) == '2.2'
-    assert tmpl.render(Context({'term1': None, 'term2': '2,2'})) == '2.2'
-
-    # subtract
-    tmpl = Template('{{ term1|subtract:term2 }}')
-    assert tmpl.render(Context({'term1': 5.1, 'term2': 1})) == '4.1'
-    assert tmpl.render(Context({'term1': '5.2', 'term2': 1})) == '4.2'
-    assert tmpl.render(Context({'term1': 5.3, 'term2': '1'})) == '4.3'
-    assert tmpl.render(Context({'term1': '5.4', 'term2': '1'})) == '4.4'
-    assert tmpl.render(Context({'term1': '', 'term2': -4.5})) == '4.5'
-    assert tmpl.render(Context({'term1': 4.6, 'term2': ''})) == '4.6'
-    assert tmpl.render(Context({'term1': '', 'term2': ''})) == '0'
-    assert tmpl.render(Context({'term1': 0, 'term2': ''})) == '0'
-    assert tmpl.render(Context({'term1': '', 'term2': 0})) == '0'
-    assert tmpl.render(Context({'term1': 0, 'term2': 0})) == '0'
-
-    # multiply
-    tmpl = Template('{{ term1|multiply:term2 }}')
-    assert tmpl.render(Context({'term1': '3', 'term2': '2'})) == '6'
-    assert tmpl.render(Context({'term1': 2.5, 'term2': 2})) == '5.0'
-    assert tmpl.render(Context({'term1': '2.5', 'term2': 2})) == '5.0'
-    assert tmpl.render(Context({'term1': 2.5, 'term2': '2'})) == '5.0'
-    assert tmpl.render(Context({'term1': '2.5', 'term2': '2'})) == '5.0'
-    assert tmpl.render(Context({'term1': '', 'term2': '2'})) == '0'
-    assert tmpl.render(Context({'term1': 2.5, 'term2': ''})) == '0.0'
-    assert tmpl.render(Context({'term1': '', 'term2': ''})) == '0'
-    assert tmpl.render(Context({'term1': 0, 'term2': ''})) == '0'
-    assert tmpl.render(Context({'term1': '', 'term2': 0})) == '0'
-    assert tmpl.render(Context({'term1': 0, 'term2': 0})) == '0'
-
-    # divide
-    tmpl = Template('{{ term1|divide:term2 }}')
-    assert tmpl.render(Context({'term1': 16, 'term2': 2})) == '8'
-    assert tmpl.render(Context({'term1': 6, 'term2': 0.75})) == '8'
-    assert tmpl.render(Context({'term1': '6', 'term2': 0.75})) == '8'
-    assert tmpl.render(Context({'term1': 6, 'term2': '0.75'})) == '8'
-    assert tmpl.render(Context({'term1': '6', 'term2': '0.75'})) == '8'
-    assert tmpl.render(Context({'term1': '', 'term2': '2'})) == '0'
-    assert tmpl.render(Context({'term1': 6, 'term2': ''})) == ''
-    assert tmpl.render(Context({'term1': '', 'term2': ''})) == ''
-    assert tmpl.render(Context({'term1': 0, 'term2': ''})) == ''
-    assert tmpl.render(Context({'term1': '', 'term2': 0})) == ''
-    assert tmpl.render(Context({'term1': 0, 'term2': 0})) == ''
-    tmpl = Template('{{ term1|divide:term2|decimal:2 }}')
-    assert tmpl.render(Context({'term1': 2, 'term2': 3})) == '0.67'
-
-
-def test_concatenation_templatetag():
-    tmpl = Template('{{ term1|add:term2 }}')
-
-    # fallback to Django native add filter
-    assert tmpl.render(Context({'term1': 'foo', 'term2': 'bar'})) == 'foobar'
-    assert tmpl.render(Context({'term1': 'foo', 'term2': ''})) == 'foo'
-    assert tmpl.render(Context({'term1': 'foo', 'term2': None})) == 'foo'
-    assert tmpl.render(Context({'term1': 'foo', 'term2': 0})) == ''
-    assert tmpl.render(Context({'term1': '', 'term2': 'bar'})) == 'bar'
-    assert tmpl.render(Context({'term1': '', 'term2': ''})) == ''
-    assert tmpl.render(Context({'term1': '', 'term2': None})) == ''
-    assert tmpl.render(Context({'term1': None, 'term2': 'bar'})) == 'bar'
-    assert tmpl.render(Context({'term1': None, 'term2': ''})) == ''
-    assert tmpl.render(Context({'term1': None, 'term2': None})) == ''
-    assert tmpl.render(Context({'term1': 0, 'term2': 'bar'})) == ''
-
-
-def test_rounding_templatetag():
-    # ceil
-    tmpl = Template('{{ value|ceil }}')
-    assert tmpl.render(Context({'value': 3.14})) == '4'
-    assert tmpl.render(Context({'value': 3.99})) == '4'
-    assert tmpl.render(Context({'value': -3.14})) == '-3'
-    assert tmpl.render(Context({'value': -3.99})) == '-3'
-    assert tmpl.render(Context({'value': 0})) == '0'
-    assert tmpl.render(Context({'value': '3.14'})) == '4'
-    assert tmpl.render(Context({'value': '3.99'})) == '4'
-    assert tmpl.render(Context({'value': '-3.14'})) == '-3'
-    assert tmpl.render(Context({'value': '-3.99'})) == '-3'
-    assert tmpl.render(Context({'value': '0'})) == '0'
-    assert tmpl.render(Context({'value': 'not a number'})) == '0'
-    assert tmpl.render(Context({'value': ''})) == '0'
-    assert tmpl.render(Context({'value': None})) == '0'
-
-    # floor
-    tmpl = Template('{{ value|floor }}')
-    assert tmpl.render(Context({'value': 3.14})) == '3'
-    assert tmpl.render(Context({'value': 3.99})) == '3'
-    assert tmpl.render(Context({'value': -3.14})) == '-4'
-    assert tmpl.render(Context({'value': -3.99})) == '-4'
-    assert tmpl.render(Context({'value': 0})) == '0'
-    assert tmpl.render(Context({'value': '3.14'})) == '3'
-    assert tmpl.render(Context({'value': '3.99'})) == '3'
-    assert tmpl.render(Context({'value': '-3.14'})) == '-4'
-    assert tmpl.render(Context({'value': '-3.99'})) == '-4'
-    assert tmpl.render(Context({'value': '0'})) == '0'
-    assert tmpl.render(Context({'value': 'not a number'})) == '0'
-    assert tmpl.render(Context({'value': ''})) == '0'
-    assert tmpl.render(Context({'value': None})) == '0'
-
-
-def test_abs_templatetag():
-    tmpl = Template('{{ value|abs }}')
-    assert tmpl.render(Context({'value': 3.14})) == '3.14'
-    assert tmpl.render(Context({'value': -3.14})) == '3.14'
-    assert tmpl.render(Context({'value': 0})) == '0'
-    assert tmpl.render(Context({'value': '3.14'})) == '3.14'
-    assert tmpl.render(Context({'value': '-3.14'})) == '3.14'
-    assert tmpl.render(Context({'value': '0'})) == '0'
-    assert tmpl.render(Context({'value': 'not a number'})) == '0'
-    assert tmpl.render(Context({'value': ''})) == '0'
-    assert tmpl.render(Context({'value': None})) == '0'
-
-
 def test_phonenumber_fr():
     t = Template('{{ number|phonenumber_fr }}')
     assert t.render(Context({'number': '01 23 45 67 89'})) == '01 23 45 67 89'
@@ -837,16 +637,3 @@ def test_django_contrib_humanize_filters():
     with override_settings(LANGUAGE_CODE='fr-fr'):
         assert tmpl.render(Context({'foo': 10000})) == '10 000'
         assert tmpl.render(Context({'foo': '10000'})) == '10 000'
-
-
-def test_sum():
-    t = Template('{{ "2 29.5 9,5 .5"|split|sum }}')
-    assert t.render(Context()) == '41.5'
-    t = Template('{{ list|sum }}')
-    assert t.render(Context({'list': [1, 2, '3']})) == '6'
-    assert t.render(Context({'list': [1, 2, 'x']})) == '3'
-    assert t.render(Context({'list': [None, 2.0, 'x']})) == '2'
-    assert t.render(Context({'list': []})) == '0'
-    assert t.render(Context({'list': None})) == ''  # list is not iterable
-    assert t.render(Context({'list': '123'})) == ''  # consider string as not iterable
-    assert t.render(Context()) == ''
-- 
2.35.1

