summaryrefslogtreecommitdiff
path: root/talerbank/jinja2.py
blob: 4decaddccac5534a85d1cb1c1f269bef641b14af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
##
# This file is part of TALER
# (C) 2017 Taler Systems SA
#
# TALER 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, or (at your option) any later version.
#
# TALER 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with TALER; see the file COPYING.  If not,
# see <http://www.gnu.org/licenses/>
#
#  @author Florian Dold
#  @brief Extends the Jinja2 API with custom functions.

import os
import math
import json
from urllib.parse import urlparse
from django.urls import reverse, get_script_prefix
from django.conf import settings
from jinja2 import Environment


##
# Check if a URL is absolute or not.
#
# @param urloc the URL to check.
# @return True if the URL is absolute, False otherwise.
def is_absolute(urloc):
    return bool(urlparse(urloc).netloc)


##
# Join URL components held in a list, taking care
# of not having double slashes in the result.
#
# @param parts list of URL components.
# @return the string made of the joined components
def join_urlparts(*parts):
    ret = ""
    part = 0
    while part < len(parts):
        buf = parts[part]
        part += 1
        if ret.endswith("/"):
            buf = buf.lstrip("/")
        elif ret and not buf.startswith("/"):
            buf = "/" + buf
        ret += buf
    return ret


##
# Prefixes the argument with the location for static content.
#
# @param urloc the URL portion that should be prefixed; in
#        other words, this will be in final position in the
#        produced result.
# @return the URL that picks @a urloc from the location for
#         static content.
def static(urloc):
    if is_absolute(urloc):
        return urloc
    return join_urlparts(get_script_prefix(), settings.STATIC_URL, urloc)


##
# Helper function that fetches a value from the settings.
#
# @param name the name to lookup in the settings.
# @return @a name's value as defined in the settings, or
#         a empty string otherwise.
def settings_value(name):
    return getattr(settings, name, "")


##
# Fetch the URL given its "name".
#
# @param url_name URL's name as defined in urlargs.py
# @param kwargs key-value list that will be appended
#        to the URL as the parameter=value pairs.
def url(url_name, *args, **kwargs):
    # strangely, Django's 'reverse' function
    # takes a named parameter 'kwargs' instead
    # of real kwargs.
    return reverse(url_name, args=args, kwargs=kwargs)


##
# Helper function that reads a value from the environment.
#
# @param name env value to read
# @return the value, or None if not found.
def env_get(name, default=None):
    return os.environ.get(name, default)


##
# Jinja2 specific function used to activate the definitions
# of this module.
#
# @param options opaque argument (?) given from the caller.
# @return Jinja2-specific object that contains the new definitions.
def is_valid_amount(amount):
    if math.isnan(amount.value):
        return False
    return True


def tojson(x):
    """Convert object to json"""
    return json.dumps(x)


##
# Stringifies amount.
#
# @param amount amount object.
# @return amount pretty string.
def amount_stringify(amount):
    return amount.stringify(settings.TALER_DIGITS, pretty=True)


def environment(**options):
    env = Environment(**options)
    env.globals.update(
        {
            "static": static,
            "url": url,
            "settings_value": settings_value,
            "env": env_get,
            "is_valid_amount": is_valid_amount,
            "amount_stringify": amount_stringify,
            "tojson": tojson,
        }
    )
    return env