publik: use list/add filters to create list from simple values (#81223)
gitea/publik-django-templatetags/pipeline/head This commit looks good Details

This commit is contained in:
Lauréline Guérin 2023-09-19 10:55:26 +02:00
parent 6e9d0a8b63
commit 063f03c491
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 61 additions and 8 deletions

View File

@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import collections
import datetime
import math
from decimal import Decimal
@ -124,19 +125,35 @@ def decimal(value, arg=None):
def add(term1, term2):
'''replace the "add" native django filter'''
# consider None content as the empty string
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 available number if the other term is the empty string
if term1 == '':
try:
return parse_decimal(term2, do_raise=True)
except (ArithmeticError, TypeError):
pass
if term2 == '':
try:
return parse_decimal(term1, do_raise=True)
except (ArithmeticError, TypeError):
pass
# compute addition if both terms are numbers
try:
return parse_decimal(term1, do_raise=True) + parse_decimal(term2, do_raise=True)
except (ArithmeticError, TypeError, ValueError):
pass
# append to term1 if term1 is a list and not term2
if isinstance(term1, list) and not isinstance(term2, list):
return list(term1) + [term2]
# fallback to django add filter
return defaultfilters.add(term1, term2)
@ -224,3 +241,12 @@ def duration(value, arg='short'):
except (TypeError, ValueError):
return ''
return utils.seconds2humanduration(int(value.total_seconds()), short=bool(arg != 'long'))
@register.filter(name='list')
def list_(value):
# turn a generator into a list
if isinstance(value, collections.abc.Iterable) and not isinstance(value, (collections.abc.Mapping, str)):
return list(value)
else:
return [value]

View File

@ -1,3 +1,5 @@
import html
from django.template import Context, Template
@ -409,3 +411,28 @@ def test_duration():
Template('{{ value|duration:"long" }}').render(context)
== '3 years, 1 month, 30 days, 15 hours and 46 minutes'
)
def test_convert_as_list():
tmpl = Template('{{ foo|list|first }}')
assert tmpl.render(Context({'foo': ['foo']})) == 'foo'
def list_generator():
yield from range(5)
assert tmpl.render(Context({'foo': list_generator})) == '0'
def list_range():
return range(5)
assert tmpl.render(Context({'foo': list_range})) == '0'
def test_convert_as_list_with_add():
tmpl = Template('{{ foo|list|add:bar|join:", " }}')
assert tmpl.render(Context({'foo': [1, 2], 'bar': ['a', 'b']})) == '1, 2, a, b'
assert tmpl.render(Context({'foo': [1, 2], 'bar': 'ab'})) == '1, 2, ab'
assert tmpl.render(Context({'foo': 12, 'bar': ['a', 'b']})) == '12, a, b'
assert tmpl.render(Context({'foo': 12, 'bar': 'ab'})) == '12, ab'
assert html.unescape(tmpl.render(Context({'foo': [1, 2], 'bar': {'a': 'b'}}))) == "1, 2, {'a': 'b'}"
assert html.unescape(tmpl.render(Context({'foo': {'a': 'b'}, 'bar': ['a', 'b']}))) == "{'a': 'b'}, a, b"