diff --git a/debian/control b/debian/control
index 2ce27dd..8ac794f 100644
--- a/debian/control
+++ b/debian/control
@@ -17,7 +17,8 @@ Depends: ${misc:Depends},
python3-prometheus-client,
python3-djangorestframework,
python3-dnspython,
- python3-systemd
+ python3-systemd,
+ python3-num2words
Breaks: python-hobo (<< 1.53.post2)
Replaces: python-hobo (<< 1.53.post2)
Recommends:
diff --git a/debian/debian_config_common.py b/debian/debian_config_common.py
index 6fe009c..570ce48 100644
--- a/debian/debian_config_common.py
+++ b/debian/debian_config_common.py
@@ -375,6 +375,9 @@ if PROJECT_NAME != 'wcs':
if 'authentic2' not in INSTALLED_APPS:
MELLON_ADAPTER = ('hobo.multitenant.mellon.MellonAdapter',)
+if PROJECT_NAME in ('wcs', 'combo'):
+ TEMPLATES[0]['OPTIONS'].setdefault('builtins', []).append('hobo.templatetags.hobo')
+
if 'authentic2' not in INSTALLED_APPS:
MELLON_DEFAULT_ASSERTION_CONSUMER_BINDING = 'artifact'
diff --git a/hobo/templatetags/__init__.py b/hobo/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/hobo/templatetags/hobo.py b/hobo/templatetags/hobo.py
new file mode 100644
index 0000000..86b19a7
--- /dev/null
+++ b/hobo/templatetags/hobo.py
@@ -0,0 +1,46 @@
+# hobo - portal to configure and deploy applications
+# Copyright (C) 2015-2021 Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import decimal
+
+from django import template
+from django.template.defaultfilters import stringfilter
+from django.utils.translation import get_language
+from num2words import num2words
+
+register = template.Library()
+
+
+def unlazy(x):
+ return x.get_value() if hasattr(x, 'get_value') else x
+
+
+@register.filter
+@stringfilter
+def as_numeral(number):
+ try:
+ return num2words(unlazy(number), lang=get_language())
+ except (TypeError, ValueError, decimal.InvalidOperation, OverflowError):
+ return ''
+
+
+@register.filter
+@stringfilter
+def as_numeral_currency(number):
+ try:
+ return num2words(unlazy(number), lang=get_language(), to='currency')
+ except (TypeError, ValueError, decimal.InvalidOperation, OverflowError):
+ return ''
diff --git a/tests/settings.py b/tests/settings.py
index 5068ca0..952c142 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -24,3 +24,5 @@ DATABASES = {
},
}
}
+
+TEMPLATES[0]['OPTIONS'].setdefault('builtins', []).append('hobo.templatetags.hobo')
diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py
new file mode 100644
index 0000000..64ba5dd
--- /dev/null
+++ b/tests/test_templatetags.py
@@ -0,0 +1,52 @@
+# hobo - portal to configure and deploy applications
+# Copyright (C) 2015-2021 Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from django.template import Context, Template
+
+
+def test_as_numeral(settings):
+ t = Template('{{ number|as_numeral }}')
+ assert t.render(Context({'number': 42})) == 'forty-two'
+ assert t.render(Context({'number': '42'})) == 'forty-two'
+ assert t.render(Context({'number': 42.15})) == 'forty-two point one five'
+ assert t.render(Context({'number': -42})) == 'minus forty-two'
+ assert t.render(Context({'number': None})) == ''
+ assert t.render(Context({'number': 'foo'})) == ''
+ assert t.render(Context({'number': ['foo', 'bar']})) == ''
+ assert t.render(Context({'number': {'foo': 'bar'}})) == ''
+ assert t.render(Context({'number': 10 ** 500})) == ''
+
+ settings.LANGUAGE_CODE = 'fr'
+ assert t.render(Context({'number': 42})) == 'quarante-deux'
+ assert t.render(Context({'number': 42.15})) == 'quarante-deux virgule un cinq'
+
+
+def test_as_numeral_currency(settings):
+ t = Template('{{ number|as_numeral_currency }}')
+ assert t.render(Context({'number': 42})) == 'forty-two euro, zero cents'
+ assert t.render(Context({'number': '42'})) == 'forty-two euro, zero cents'
+ assert t.render(Context({'number': 42.15})) == 'forty-two euro, fifteen cents'
+ assert t.render(Context({'number': -42})) == 'minus forty-two euro, zero cents'
+ assert t.render(Context({'number': None})) == ''
+ assert t.render(Context({'number': 'foo'})) == ''
+ assert t.render(Context({'number': ['foo', 'bar']})) == ''
+ assert t.render(Context({'number': {'foo': 'bar'}})) == ''
+ assert t.render(Context({'number': 10 ** 500})) == ''
+
+ settings.LANGUAGE_CODE = 'fr'
+ assert t.render(Context({'number': 42})) == 'quarante-deux euros et zéro centimes'
+ assert t.render(Context({'number': 42.15})) == 'quarante-deux euros et quinze centimes'
+ assert t.render(Context({'number': '1'})) == 'un euro et zéro centimes'
diff --git a/tox.ini b/tox.ini
index 832cee8..a1b5096 100644
--- a/tox.ini
+++ b/tox.ini
@@ -55,6 +55,7 @@ deps:
xmlschema<1.1
enum34<=1.1.6
psycopg2-binary<2.9
+ num2words
black: pre-commit
commands =
./getlasso3.sh