python-liquid 2.3.6__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- liquid/__about__.py +1 -0
- liquid/__init__.py +161 -187
- liquid/_base_tag.py +66 -0
- liquid/{utils/chain_map.py → _chain_map.py} +18 -19
- liquid/_context.py +465 -0
- liquid/_drop.py +108 -0
- liquid/_filter.py +174 -0
- liquid/_io.py +18 -0
- liquid/_lax_parser_mixin.py +100 -0
- liquid/_lexer.py +93 -0
- liquid/_lexer_extended.py +623 -0
- liquid/_lexer_legacy.py +536 -0
- liquid/_loader.py +84 -0
- liquid/{utils/lru_cache.py → _lru_cache.py} +28 -36
- liquid/_markup.py +253 -0
- liquid/_messages.py +292 -0
- liquid/_missing.py +3 -0
- liquid/_nothing.py +28 -0
- liquid/_parser.py +460 -0
- liquid/_parser_extended.py +293 -0
- liquid/_parser_legacy.py +819 -0
- liquid/_resource_limits.py +50 -0
- liquid/_slice.py +41 -0
- liquid/_static_analysis.py +503 -0
- liquid/_strftime.py +186 -0
- liquid/_template.py +536 -0
- liquid/drops/__init__.py +20 -0
- liquid/drops/forloop.py +78 -0
- liquid/drops/iterable.py +25 -0
- liquid/drops/range.py +76 -0
- liquid/drops/self_.py +45 -0
- liquid/drops/tablerowloop.py +142 -0
- liquid/drops/undefined.py +228 -0
- liquid/environment.py +717 -551
- liquid/exceptions.py +67 -214
- liquid/expressions.py +1184 -0
- liquid/filters/__init__.py +134 -0
- liquid/filters/abs.py +7 -0
- liquid/filters/append.py +5 -0
- liquid/filters/at_least.py +9 -0
- liquid/filters/at_most.py +9 -0
- liquid/filters/babel.py +560 -0
- liquid/filters/base64.py +26 -0
- liquid/filters/capitalize.py +5 -0
- liquid/filters/ceil.py +8 -0
- liquid/filters/compact.py +25 -0
- liquid/filters/concat.py +11 -0
- liquid/filters/date.py +27 -0
- liquid/filters/default.py +25 -0
- liquid/filters/divided_by.py +21 -0
- liquid/filters/downcase.py +5 -0
- liquid/filters/escape.py +56 -0
- liquid/filters/find.py +56 -0
- liquid/filters/first.py +19 -0
- liquid/filters/floor.py +8 -0
- liquid/filters/html.py +23 -0
- liquid/filters/index.py +12 -0
- liquid/filters/join.py +13 -0
- liquid/filters/json_.py +30 -0
- liquid/filters/last.py +17 -0
- liquid/filters/map.py +5 -0
- liquid/filters/minus.py +13 -0
- liquid/filters/modulo.py +18 -0
- liquid/filters/newline_to_br.py +16 -0
- liquid/filters/plus.py +13 -0
- liquid/filters/prepend.py +5 -0
- liquid/filters/reject.py +19 -0
- liquid/filters/remove.py +36 -0
- liquid/filters/replace.py +32 -0
- liquid/filters/reverse.py +5 -0
- liquid/filters/round.py +35 -0
- liquid/filters/size.py +25 -0
- liquid/filters/slice.py +39 -0
- liquid/filters/sort.py +148 -0
- liquid/filters/split.py +34 -0
- liquid/filters/squish.py +9 -0
- liquid/filters/strip.py +13 -0
- liquid/filters/strip_html.py +19 -0
- liquid/filters/strip_newlines.py +17 -0
- liquid/filters/sum.py +21 -0
- liquid/filters/times.py +13 -0
- liquid/filters/translate.py +380 -0
- liquid/filters/truncate.py +39 -0
- liquid/filters/uniq.py +11 -0
- liquid/filters/upcase.py +5 -0
- liquid/filters/url.py +18 -0
- liquid/filters/where.py +18 -0
- liquid/loaders/__init__.py +17 -0
- liquid/loaders/caching_file_system_loader.py +64 -0
- liquid/loaders/choice_loader.py +93 -0
- liquid/loaders/dict_loader.py +56 -0
- liquid/{builtin/loaders → loaders}/file_system_loader.py +51 -55
- liquid/{builtin/loaders → loaders}/mixins.py +39 -51
- liquid/loaders/package_loader.py +110 -0
- liquid/tags/__init__.py +61 -0
- liquid/tags/assign.py +68 -0
- liquid/tags/capture.py +83 -0
- liquid/tags/case.py +199 -0
- liquid/tags/comment.py +56 -0
- liquid/tags/cycle.py +131 -0
- liquid/tags/decrement.py +55 -0
- liquid/tags/doc.py +56 -0
- liquid/tags/echo.py +65 -0
- liquid/tags/else_.py +53 -0
- liquid/tags/error.py +51 -0
- liquid/tags/extends.py +448 -0
- liquid/tags/for_.py +421 -0
- liquid/tags/if_.py +156 -0
- liquid/tags/ifchanged.py +69 -0
- liquid/tags/include.py +223 -0
- liquid/tags/increment.py +55 -0
- liquid/tags/inline_comment.py +70 -0
- liquid/tags/liquid.py +56 -0
- liquid/tags/macro.py +281 -0
- liquid/tags/output.py +58 -0
- liquid/tags/raw.py +60 -0
- liquid/tags/render.py +245 -0
- liquid/tags/tablerow.py +254 -0
- liquid/tags/template_comment.py +56 -0
- liquid/tags/translate.py +316 -0
- liquid/tags/unless.py +121 -0
- liquid/tags/with_.py +83 -0
- liquid/tokens.py +370 -0
- {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/METADATA +32 -39
- python_liquid-3.0.0.dist-info/RECORD +128 -0
- {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/WHEEL +1 -1
- {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/licenses/LICENSE +1 -1
- liquid/analyze_tags.py +0 -214
- liquid/ast.py +0 -252
- liquid/builtin/__init__.py +0 -203
- liquid/builtin/content.py +0 -41
- liquid/builtin/drops/__init__.py +0 -3
- liquid/builtin/drops/drops.py +0 -13
- liquid/builtin/expressions/__init__.py +0 -47
- liquid/builtin/expressions/_tokenize.py +0 -186
- liquid/builtin/expressions/arguments.py +0 -207
- liquid/builtin/expressions/filtered.py +0 -387
- liquid/builtin/expressions/logical.py +0 -672
- liquid/builtin/expressions/loop.py +0 -275
- liquid/builtin/expressions/path.py +0 -163
- liquid/builtin/expressions/primitive.py +0 -417
- liquid/builtin/filters/__init__.py +0 -0
- liquid/builtin/filters/array.py +0 -329
- liquid/builtin/filters/extra.py +0 -83
- liquid/builtin/filters/math.py +0 -129
- liquid/builtin/filters/misc.py +0 -137
- liquid/builtin/filters/string.py +0 -416
- liquid/builtin/illegal.py +0 -28
- liquid/builtin/loaders/__init__.py +0 -0
- liquid/builtin/loaders/caching_file_system_loader.py +0 -61
- liquid/builtin/loaders/choice_loader.py +0 -94
- liquid/builtin/loaders/dict_loader.py +0 -64
- liquid/builtin/loaders/package_loader.py +0 -132
- liquid/builtin/output.py +0 -74
- liquid/builtin/tags/__init__.py +0 -0
- liquid/builtin/tags/assign_tag.py +0 -75
- liquid/builtin/tags/capture_tag.py +0 -98
- liquid/builtin/tags/case_tag.py +0 -287
- liquid/builtin/tags/comment_tag.py +0 -77
- liquid/builtin/tags/cycle_tag.py +0 -132
- liquid/builtin/tags/decrement_tag.py +0 -59
- liquid/builtin/tags/doc_tag.py +0 -68
- liquid/builtin/tags/echo_tag.py +0 -45
- liquid/builtin/tags/for_tag.py +0 -337
- liquid/builtin/tags/if_tag.py +0 -209
- liquid/builtin/tags/ifchanged_tag.py +0 -94
- liquid/builtin/tags/include_tag.py +0 -251
- liquid/builtin/tags/increment_tag.py +0 -60
- liquid/builtin/tags/inline_comment_tag.py +0 -47
- liquid/builtin/tags/liquid_tag.py +0 -183
- liquid/builtin/tags/render_tag.py +0 -371
- liquid/builtin/tags/tablerow_tag.py +0 -320
- liquid/builtin/tags/unless_tag.py +0 -218
- liquid/context.py +0 -615
- liquid/expression.py +0 -41
- liquid/extra/__init__.py +0 -98
- liquid/extra/filters/__init__.py +0 -33
- liquid/extra/filters/_json.py +0 -33
- liquid/extra/filters/array.py +0 -60
- liquid/extra/filters/babel.py +0 -552
- liquid/extra/filters/html.py +0 -32
- liquid/extra/filters/translate.py +0 -448
- liquid/extra/tags/__init__.py +0 -17
- liquid/extra/tags/_with.py +0 -80
- liquid/extra/tags/extends_tag.py +0 -576
- liquid/extra/tags/macro_tag.py +0 -270
- liquid/extra/tags/snippet_tag.py +0 -107
- liquid/extra/tags/translate_tag.py +0 -388
- liquid/filter.py +0 -230
- liquid/future/__init__.py +0 -3
- liquid/future/environment.py +0 -30
- liquid/future/filters/__init__.py +0 -1
- liquid/future/tags/__init__.py +0 -1
- liquid/lex.py +0 -260
- liquid/limits.py +0 -66
- liquid/loader.py +0 -141
- liquid/messages.py +0 -357
- liquid/mode.py +0 -12
- liquid/output.py +0 -35
- liquid/parser.py +0 -119
- liquid/span.py +0 -35
- liquid/static_analysis.py +0 -443
- liquid/stream.py +0 -148
- liquid/stringify.py +0 -31
- liquid/tag.py +0 -47
- liquid/template.py +0 -658
- liquid/token.py +0 -145
- liquid/undefined.py +0 -218
- liquid/utils/__init__.py +0 -15
- liquid/utils/html.py +0 -57
- liquid/utils/text.py +0 -28
- python_liquid-2.3.6.dist-info/RECORD +0 -96
liquid/extra/filters/babel.py
DELETED
|
@@ -1,552 +0,0 @@
|
|
|
1
|
-
"""A currency, date, time, number and unit formatting filters."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from datetime import date
|
|
6
|
-
from datetime import datetime
|
|
7
|
-
from datetime import time
|
|
8
|
-
from decimal import Decimal
|
|
9
|
-
from functools import wraps
|
|
10
|
-
from typing import TYPE_CHECKING
|
|
11
|
-
from typing import Any
|
|
12
|
-
from typing import Callable
|
|
13
|
-
from typing import Optional
|
|
14
|
-
from typing import Union
|
|
15
|
-
|
|
16
|
-
import pytz
|
|
17
|
-
from babel import Locale
|
|
18
|
-
from babel import UnknownLocaleError
|
|
19
|
-
from babel import dates
|
|
20
|
-
from babel import numbers
|
|
21
|
-
from babel import units
|
|
22
|
-
from dateutil import parser
|
|
23
|
-
|
|
24
|
-
from liquid.exceptions import LiquidTypeError
|
|
25
|
-
from liquid.exceptions import LiquidValueError
|
|
26
|
-
from liquid.filter import num_arg
|
|
27
|
-
from liquid.filter import with_context
|
|
28
|
-
from liquid.undefined import is_undefined
|
|
29
|
-
|
|
30
|
-
if TYPE_CHECKING:
|
|
31
|
-
from liquid import RenderContext
|
|
32
|
-
|
|
33
|
-
FilterT = Callable[..., Any]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def _resolve_locale(
|
|
37
|
-
context: RenderContext,
|
|
38
|
-
locale_var: str,
|
|
39
|
-
default: Locale,
|
|
40
|
-
) -> Locale:
|
|
41
|
-
_locale = context.resolve(locale_var)
|
|
42
|
-
|
|
43
|
-
if is_undefined(_locale):
|
|
44
|
-
locale = default
|
|
45
|
-
elif isinstance(_locale, str):
|
|
46
|
-
try:
|
|
47
|
-
locale = Locale.parse(_locale)
|
|
48
|
-
except UnknownLocaleError:
|
|
49
|
-
locale = default
|
|
50
|
-
else:
|
|
51
|
-
raise LiquidTypeError(
|
|
52
|
-
f"expected a string argument, found {_locale}", token=None
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
return locale
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@with_context
|
|
59
|
-
class Currency:
|
|
60
|
-
"""A Liquid filter for formatting currency values.
|
|
61
|
-
|
|
62
|
-
Args:
|
|
63
|
-
currency_code_var: The name of a render context variable that resolves
|
|
64
|
-
to the current currency code. Defaults to `"currency_code"`.
|
|
65
|
-
default_currency_code: A fallback currency code if `currency_code_var`
|
|
66
|
-
can not be resolved. Defaults to `"USD"`.
|
|
67
|
-
locale_var: The name of a render context variable that resolves to the
|
|
68
|
-
current locale. Defaults to `"locale"`.
|
|
69
|
-
default_locale: A fallback locale to use if `locale_var` can not be
|
|
70
|
-
resolved. Defaults to `"en_US"`.
|
|
71
|
-
format_var: The name of a render context variable that resolves to the
|
|
72
|
-
current currency format string. Defaults to `"currency_format"`.
|
|
73
|
-
default_format: A fallback currency format that is used if `format_var`
|
|
74
|
-
can not be resolved. Defaults to `None`, which means the standard format for
|
|
75
|
-
the current locale will be used.
|
|
76
|
-
currency_digits: Indicates if the format should override locale specific
|
|
77
|
-
trailing digit behavior. Defaults to `False`.
|
|
78
|
-
input_locale_var: The name of a render context variable that resolves to
|
|
79
|
-
a locale suitable for parsing input strings to decimals. Defaults to
|
|
80
|
-
`"input_locale"`.
|
|
81
|
-
default_input_locale: A fallback locale to use if `input_locale_var`
|
|
82
|
-
can not be resolved. Defaults to `"en_US"`.
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
def __init__(
|
|
86
|
-
self,
|
|
87
|
-
*,
|
|
88
|
-
currency_code_var: str = "currency_code",
|
|
89
|
-
default_currency_code: str = "USD",
|
|
90
|
-
locale_var: str = "locale",
|
|
91
|
-
default_locale: str = "en_US",
|
|
92
|
-
format_var: str = "currency_format",
|
|
93
|
-
default_format: Optional[str] = None,
|
|
94
|
-
currency_digits: bool = True,
|
|
95
|
-
input_locale_var: str = "input_locale",
|
|
96
|
-
default_input_locale: str = "en_US",
|
|
97
|
-
) -> None:
|
|
98
|
-
self.currency_code_var = currency_code_var
|
|
99
|
-
self.default_currency_code = default_currency_code
|
|
100
|
-
self.locale_var = locale_var
|
|
101
|
-
self.default_locale = Locale.parse(default_locale)
|
|
102
|
-
self.format_var = format_var
|
|
103
|
-
self.default_format = default_format
|
|
104
|
-
self.currency_digits = currency_digits
|
|
105
|
-
self.input_locale_var = input_locale_var
|
|
106
|
-
self.default_input_locale = Locale.parse(default_input_locale)
|
|
107
|
-
|
|
108
|
-
def __call__(
|
|
109
|
-
self,
|
|
110
|
-
left: object,
|
|
111
|
-
*,
|
|
112
|
-
context: RenderContext,
|
|
113
|
-
group_separator: bool = True,
|
|
114
|
-
) -> str:
|
|
115
|
-
"""Apply the filter and return the result."""
|
|
116
|
-
locale = _resolve_locale(
|
|
117
|
-
context,
|
|
118
|
-
self.locale_var,
|
|
119
|
-
default=self.default_locale,
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
input_locale = _resolve_locale(
|
|
123
|
-
context,
|
|
124
|
-
self.input_locale_var,
|
|
125
|
-
default=self.default_input_locale,
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
_format = context.resolve(self.format_var, default=self.default_format)
|
|
129
|
-
|
|
130
|
-
if _format is not None and not isinstance(_format, str):
|
|
131
|
-
raise LiquidTypeError(
|
|
132
|
-
f"expected a string argument, found {_format}", token=None
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
currency_code = context.resolve(
|
|
136
|
-
self.currency_code_var,
|
|
137
|
-
default=self.default_currency_code,
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
if not isinstance(currency_code, str):
|
|
141
|
-
raise LiquidTypeError(
|
|
142
|
-
f"expected a string argument, found {currency_code}", token=None
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
return numbers.format_currency(
|
|
146
|
-
_parse_decimal(left, input_locale),
|
|
147
|
-
currency_code,
|
|
148
|
-
format=_format,
|
|
149
|
-
locale=locale,
|
|
150
|
-
group_separator=group_separator,
|
|
151
|
-
currency_digits=self.currency_digits,
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def _parse_decimal(val: object, locale: Union[str, Locale]) -> Decimal:
|
|
156
|
-
if isinstance(val, str):
|
|
157
|
-
try:
|
|
158
|
-
return numbers.parse_decimal(val, locale)
|
|
159
|
-
except numbers.NumberFormatError:
|
|
160
|
-
return Decimal(0)
|
|
161
|
-
|
|
162
|
-
if isinstance(val, (Decimal, float, int)):
|
|
163
|
-
return Decimal(val)
|
|
164
|
-
|
|
165
|
-
# Give objects that implement __int__ etc. a chance.
|
|
166
|
-
return Decimal(num_arg(val, 0))
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
@with_context
|
|
170
|
-
class DateTime:
|
|
171
|
-
"""A Liquid filter for formatting datetime objects.
|
|
172
|
-
|
|
173
|
-
Args:
|
|
174
|
-
timezone_var: The name of a render context variable that resolves to
|
|
175
|
-
a timezone. Defaults to `"timezone"`.
|
|
176
|
-
default_timezone: A fallback timezone to use if `timezone_var` can
|
|
177
|
-
not be resolved. Defaults to `"UTC"`.
|
|
178
|
-
locale_var: The name of a render context variable that resolves to the
|
|
179
|
-
current locale. Defaults to `"locale"`.
|
|
180
|
-
default_locale: A fallback locale to use if `locale_var` can not be
|
|
181
|
-
resolved. Defaults to `"en_US"`.
|
|
182
|
-
format_var: The name of a render context variable that resolves to the
|
|
183
|
-
current datetime format string. Defaults to `"datetime_format"`.
|
|
184
|
-
default_format: A fallback datetime format that is used if `format_var`
|
|
185
|
-
can not be resolved. Defaults to `"medium"`.
|
|
186
|
-
input_timezone_var: The name of a render context variable that resolves to
|
|
187
|
-
a timezone for parsing datetimes entered as strings. Defaults to
|
|
188
|
-
`"input_timezone"`.
|
|
189
|
-
default_input_timezone: A fallback timezone to use if `input_timezone_var`
|
|
190
|
-
can not be resolved. Defaults to `"UTC"`.
|
|
191
|
-
"""
|
|
192
|
-
|
|
193
|
-
formats = {
|
|
194
|
-
"short": "short",
|
|
195
|
-
"medium": "medium",
|
|
196
|
-
"long": "long",
|
|
197
|
-
"full": "full",
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
def __init__(
|
|
201
|
-
self,
|
|
202
|
-
*,
|
|
203
|
-
timezone_var: str = "timezone",
|
|
204
|
-
default_timezone: str = "UTC",
|
|
205
|
-
locale_var: str = "locale",
|
|
206
|
-
default_locale: str = "en_US",
|
|
207
|
-
format_var: str = "datetime_format",
|
|
208
|
-
default_format: str = "medium",
|
|
209
|
-
input_timezone_var: str = "input_timezone",
|
|
210
|
-
default_input_timezone: str = "UTC",
|
|
211
|
-
) -> None:
|
|
212
|
-
self.timezone_var = timezone_var
|
|
213
|
-
self.default_timezone = pytz.timezone(default_timezone)
|
|
214
|
-
self.locale_var = locale_var
|
|
215
|
-
self.default_locale = Locale.parse(default_locale)
|
|
216
|
-
self.format_var = format_var
|
|
217
|
-
self.default_format = self.formats.get(default_format, default_format)
|
|
218
|
-
self.input_timezone_var = input_timezone_var
|
|
219
|
-
self.default_input_timezone = pytz.timezone(default_input_timezone)
|
|
220
|
-
|
|
221
|
-
def __call__(
|
|
222
|
-
self,
|
|
223
|
-
left: object,
|
|
224
|
-
*,
|
|
225
|
-
context: RenderContext,
|
|
226
|
-
format: Optional[str] = None, # noqa: A002
|
|
227
|
-
) -> str:
|
|
228
|
-
"""Apply the filter and return the result."""
|
|
229
|
-
locale = _resolve_locale(
|
|
230
|
-
context,
|
|
231
|
-
self.locale_var,
|
|
232
|
-
default=self.default_locale,
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
if format:
|
|
236
|
-
_format = self.formats.get(format, format)
|
|
237
|
-
else:
|
|
238
|
-
format_string = context.resolve(self.format_var)
|
|
239
|
-
|
|
240
|
-
if is_undefined(format_string):
|
|
241
|
-
_format = self.default_format
|
|
242
|
-
elif not isinstance(format_string, str):
|
|
243
|
-
raise LiquidTypeError(
|
|
244
|
-
f"expected a string argument, found {format_string}",
|
|
245
|
-
token=None,
|
|
246
|
-
)
|
|
247
|
-
else:
|
|
248
|
-
_format = self.formats.get(format_string, format_string)
|
|
249
|
-
|
|
250
|
-
tzinfo = self._resolve_timezone(
|
|
251
|
-
context,
|
|
252
|
-
self.timezone_var,
|
|
253
|
-
default=self.default_timezone,
|
|
254
|
-
)
|
|
255
|
-
input_tzinfo = self._resolve_timezone(
|
|
256
|
-
context,
|
|
257
|
-
self.input_timezone_var,
|
|
258
|
-
default=self.default_input_timezone,
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
return dates.format_datetime(
|
|
262
|
-
_parse_datetime(left, input_tzinfo),
|
|
263
|
-
format=_format,
|
|
264
|
-
locale=locale,
|
|
265
|
-
tzinfo=tzinfo,
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
def _resolve_timezone(
|
|
269
|
-
self,
|
|
270
|
-
context: RenderContext,
|
|
271
|
-
timezone_var: str,
|
|
272
|
-
default: pytz.BaseTzInfo,
|
|
273
|
-
) -> pytz.BaseTzInfo:
|
|
274
|
-
_tz = context.resolve(timezone_var)
|
|
275
|
-
|
|
276
|
-
if is_undefined(_tz):
|
|
277
|
-
timezone = default
|
|
278
|
-
elif isinstance(_tz, str):
|
|
279
|
-
try:
|
|
280
|
-
timezone = pytz.timezone(_tz)
|
|
281
|
-
except pytz.UnknownTimeZoneError:
|
|
282
|
-
timezone = default
|
|
283
|
-
else:
|
|
284
|
-
raise LiquidTypeError(
|
|
285
|
-
f"expected a string argument, found {_tz}",
|
|
286
|
-
token=None,
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
return timezone
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
def _parse_number(val: str) -> Union[int, float]:
|
|
293
|
-
try:
|
|
294
|
-
return int(val)
|
|
295
|
-
except ValueError:
|
|
296
|
-
# Let the ValueError raise
|
|
297
|
-
return float(val)
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
def _parse_datetime(
|
|
301
|
-
val: object,
|
|
302
|
-
default_timezone: pytz.BaseTzInfo,
|
|
303
|
-
) -> Union[date, time, datetime, int, float, None]:
|
|
304
|
-
if isinstance(val, str):
|
|
305
|
-
# `date.format_datetime` will use the current timestamp if
|
|
306
|
-
# given `None`.
|
|
307
|
-
if val in ("now", "today"):
|
|
308
|
-
return None
|
|
309
|
-
|
|
310
|
-
# String representations of ints and floats need to be cast
|
|
311
|
-
# to an int or float, but not passed to the fuzzy parser.
|
|
312
|
-
try:
|
|
313
|
-
return _parse_number(val)
|
|
314
|
-
except ValueError:
|
|
315
|
-
pass
|
|
316
|
-
|
|
317
|
-
# Fuzzy parsing using dateutil.
|
|
318
|
-
try:
|
|
319
|
-
_dt = parser.parse(val)
|
|
320
|
-
if _dt.tzinfo is None:
|
|
321
|
-
return _dt.replace(tzinfo=default_timezone)
|
|
322
|
-
return _dt
|
|
323
|
-
except parser.ParserError as err:
|
|
324
|
-
raise LiquidValueError(str(err), token=None) from err
|
|
325
|
-
|
|
326
|
-
if not isinstance(val, (date, time, datetime, int, float)):
|
|
327
|
-
raise LiquidTypeError(
|
|
328
|
-
f"date expected date or time, found {type(val).__name__}", token=None
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
return val
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
@with_context
|
|
335
|
-
class Number:
|
|
336
|
-
"""A Liquid filter for formatting decimal values.
|
|
337
|
-
|
|
338
|
-
Args:
|
|
339
|
-
decimal_quantization_var: The name of a render context variable that
|
|
340
|
-
resolves to the decimal quantization to be used. Defaults to
|
|
341
|
-
`"decimal_quantization"`.
|
|
342
|
-
default_decimal_quantization: A fallback decimal quantization if
|
|
343
|
-
`decimal_quantization_var` can not be resolved. Defaults to `False`.
|
|
344
|
-
locale_var: The name of a render context variable that resolves to the
|
|
345
|
-
current locale. Defaults to `"locale"`.
|
|
346
|
-
default_locale: A fallback locale to use if `locale_var` can not be
|
|
347
|
-
resolved. Defaults to `"en_US"`.
|
|
348
|
-
format_var: The name of a render context variable that resolves to the
|
|
349
|
-
current decimal format string. Defaults to `"decimal_format"`.
|
|
350
|
-
default_format: A fallback decimal format that is used if `format_var`
|
|
351
|
-
can not be resolved. Defaults to `None`, which means the standard format for
|
|
352
|
-
the current locale will be used.
|
|
353
|
-
input_locale_var: The name of a render context variable that resolves to
|
|
354
|
-
a locale suitable for parsing input strings to decimals. Defaults to
|
|
355
|
-
`"input_locale"`.
|
|
356
|
-
default_input_locale: A fallback locale to use if `input_locale_var`
|
|
357
|
-
can not be resolved. Defaults to `"en_US"`.
|
|
358
|
-
"""
|
|
359
|
-
|
|
360
|
-
def __init__(
|
|
361
|
-
self,
|
|
362
|
-
*,
|
|
363
|
-
decimal_quantization_var: str = "decimal_quantization",
|
|
364
|
-
default_decimal_quantization: bool = False,
|
|
365
|
-
locale_var: str = "locale",
|
|
366
|
-
default_locale: str = "en_US",
|
|
367
|
-
format_var: str = "decimal_format",
|
|
368
|
-
default_format: Optional[str] = None,
|
|
369
|
-
input_locale_var: str = "input_locale",
|
|
370
|
-
default_input_locale: str = "en_US",
|
|
371
|
-
) -> None:
|
|
372
|
-
self.decimal_quantization_var = decimal_quantization_var
|
|
373
|
-
self.default_decimal_quantization = default_decimal_quantization
|
|
374
|
-
self.locale_var = locale_var
|
|
375
|
-
self.default_locale = Locale.parse(default_locale)
|
|
376
|
-
self.format_var = format_var
|
|
377
|
-
self.default_format = default_format
|
|
378
|
-
self.input_locale_var = input_locale_var
|
|
379
|
-
self.default_input_locale = Locale.parse(default_input_locale)
|
|
380
|
-
|
|
381
|
-
def __call__(
|
|
382
|
-
self,
|
|
383
|
-
left: object,
|
|
384
|
-
*,
|
|
385
|
-
context: RenderContext,
|
|
386
|
-
group_separator: bool = True,
|
|
387
|
-
) -> str:
|
|
388
|
-
"""Apply the filter and return the result."""
|
|
389
|
-
decimal_quantization = context.resolve(
|
|
390
|
-
self.decimal_quantization_var,
|
|
391
|
-
default=self.default_decimal_quantization,
|
|
392
|
-
)
|
|
393
|
-
|
|
394
|
-
if not isinstance(decimal_quantization, bool):
|
|
395
|
-
raise LiquidTypeError(
|
|
396
|
-
f"expected a Boolean argument, found {decimal_quantization}", token=None
|
|
397
|
-
)
|
|
398
|
-
|
|
399
|
-
locale = _resolve_locale(
|
|
400
|
-
context,
|
|
401
|
-
self.locale_var,
|
|
402
|
-
default=self.default_locale,
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
input_locale = _resolve_locale(
|
|
406
|
-
context,
|
|
407
|
-
self.input_locale_var,
|
|
408
|
-
default=self.default_input_locale,
|
|
409
|
-
)
|
|
410
|
-
|
|
411
|
-
_format = context.resolve(self.format_var, default=self.default_format)
|
|
412
|
-
|
|
413
|
-
if _format is not None and not isinstance(_format, str):
|
|
414
|
-
raise LiquidTypeError(
|
|
415
|
-
f"expected a string argument, found {_format}", token=None
|
|
416
|
-
)
|
|
417
|
-
|
|
418
|
-
return numbers.format_decimal( # type: ignore
|
|
419
|
-
_parse_decimal(left, input_locale),
|
|
420
|
-
format=_format,
|
|
421
|
-
locale=locale,
|
|
422
|
-
group_separator=group_separator,
|
|
423
|
-
decimal_quantization=decimal_quantization,
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
def unit_filter(_filter: FilterT) -> FilterT:
|
|
428
|
-
"""A filter function decorator that handles `TypeError` and `UnknownUnitError`."""
|
|
429
|
-
|
|
430
|
-
@wraps(_filter)
|
|
431
|
-
def wrapper(val: object, *args: Any, **kwargs: Any) -> Any:
|
|
432
|
-
try:
|
|
433
|
-
return _filter(val, *args, **kwargs)
|
|
434
|
-
except TypeError as err:
|
|
435
|
-
raise LiquidTypeError(err, token=None) from err
|
|
436
|
-
except units.UnknownUnitError as err:
|
|
437
|
-
raise LiquidValueError(err, token=None) from err
|
|
438
|
-
|
|
439
|
-
return wrapper
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
class Unit:
|
|
443
|
-
"""A Liquid filter for formatting units of measurement.
|
|
444
|
-
|
|
445
|
-
Args:
|
|
446
|
-
locale_var: The name of a render context variable that resolves to the
|
|
447
|
-
current locale. Defaults to `"locale"`.
|
|
448
|
-
default_locale: A fallback locale to use if `locale_var` can not be
|
|
449
|
-
resolved. Defaults to `"en_US"`.
|
|
450
|
-
length_var: The name of a render context variable that resolves to a
|
|
451
|
-
unit format length. Should be one of "short", "long" or "narrow".
|
|
452
|
-
Defaults to `"long"`.
|
|
453
|
-
default_length: A fallback format length to use if `length_var` can
|
|
454
|
-
not be resolved.
|
|
455
|
-
format_var: The name of a render context variable that resolves to a
|
|
456
|
-
decimal format string. Defaults to `"unit_format"`.
|
|
457
|
-
default_format: A fallback decimal format to use if `format_var` can
|
|
458
|
-
not be resolved. Defaults to `None`, meaning the locale's standard
|
|
459
|
-
decimal format is used.
|
|
460
|
-
input_locale_var: The name of a render context variable that resolves to
|
|
461
|
-
a locale suitable for parsing input strings to decimals. Defaults to
|
|
462
|
-
`"input_locale"`.
|
|
463
|
-
default_input_locale: A fallback locale to use if `input_locale_var`
|
|
464
|
-
can not be resolved. Defaults to `"en_US"`.
|
|
465
|
-
"""
|
|
466
|
-
|
|
467
|
-
with_context = True
|
|
468
|
-
|
|
469
|
-
def __init__(
|
|
470
|
-
self,
|
|
471
|
-
*,
|
|
472
|
-
locale_var: str = "locale",
|
|
473
|
-
default_locale: str = "en_US",
|
|
474
|
-
length_var: str = "unit_length",
|
|
475
|
-
default_length: str = "long",
|
|
476
|
-
format_var: str = "unit_format",
|
|
477
|
-
default_format: Optional[str] = None,
|
|
478
|
-
input_locale_var: str = "input_locale",
|
|
479
|
-
default_input_locale: str = "en_US",
|
|
480
|
-
) -> None:
|
|
481
|
-
self.locale_var = locale_var
|
|
482
|
-
self.default_locale = Locale.parse(default_locale)
|
|
483
|
-
self.length_var = length_var
|
|
484
|
-
self.default_length = default_length
|
|
485
|
-
self.format_var = format_var
|
|
486
|
-
self.default_format = default_format
|
|
487
|
-
self.input_locale_var = input_locale_var
|
|
488
|
-
self.default_input_locale = Locale.parse(default_input_locale)
|
|
489
|
-
|
|
490
|
-
@unit_filter
|
|
491
|
-
def __call__( # noqa: D102
|
|
492
|
-
self,
|
|
493
|
-
left: object,
|
|
494
|
-
measurement_unit: str,
|
|
495
|
-
*,
|
|
496
|
-
context: RenderContext,
|
|
497
|
-
denominator: object = None,
|
|
498
|
-
denominator_unit: Optional[str] = None,
|
|
499
|
-
length: Optional[str] = None,
|
|
500
|
-
format: Optional[str] = None, # noqa: A002
|
|
501
|
-
) -> str:
|
|
502
|
-
locale = _resolve_locale(
|
|
503
|
-
context,
|
|
504
|
-
self.locale_var,
|
|
505
|
-
default=self.default_locale,
|
|
506
|
-
)
|
|
507
|
-
|
|
508
|
-
input_locale = _resolve_locale(
|
|
509
|
-
context,
|
|
510
|
-
self.input_locale_var,
|
|
511
|
-
default=self.default_input_locale,
|
|
512
|
-
)
|
|
513
|
-
|
|
514
|
-
_length = length if length else context.resolve(self.length_var)
|
|
515
|
-
|
|
516
|
-
if _length not in ("short", "long", "narrow"):
|
|
517
|
-
_length = self.default_length
|
|
518
|
-
|
|
519
|
-
assert isinstance(_length, str)
|
|
520
|
-
|
|
521
|
-
if format:
|
|
522
|
-
_format: Optional[str] = format
|
|
523
|
-
else:
|
|
524
|
-
format_string = context.resolve(self.format_var)
|
|
525
|
-
if isinstance(format_string, str):
|
|
526
|
-
_format = format_string
|
|
527
|
-
else:
|
|
528
|
-
_format = self.default_format
|
|
529
|
-
|
|
530
|
-
if denominator is not None or denominator_unit is not None:
|
|
531
|
-
_denominator = (
|
|
532
|
-
_parse_decimal(denominator, input_locale)
|
|
533
|
-
if denominator is not None
|
|
534
|
-
else 1
|
|
535
|
-
)
|
|
536
|
-
return units.format_compound_unit(
|
|
537
|
-
_parse_decimal(left, input_locale),
|
|
538
|
-
numerator_unit=measurement_unit,
|
|
539
|
-
denominator_value=_denominator, # type: ignore
|
|
540
|
-
denominator_unit=denominator_unit,
|
|
541
|
-
length=_length, # type: ignore
|
|
542
|
-
format=_format,
|
|
543
|
-
locale=locale,
|
|
544
|
-
)
|
|
545
|
-
|
|
546
|
-
return units.format_unit(
|
|
547
|
-
_parse_decimal(left, input_locale),
|
|
548
|
-
measurement_unit=measurement_unit,
|
|
549
|
-
length=_length, # type: ignore
|
|
550
|
-
format=_format,
|
|
551
|
-
locale=locale,
|
|
552
|
-
)
|
liquid/extra/filters/html.py
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"""Extra HTML filters."""
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
import html
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
|
-
|
|
7
|
-
from liquid import Markup
|
|
8
|
-
from liquid.filter import string_filter
|
|
9
|
-
from liquid.filter import with_environment
|
|
10
|
-
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from liquid import Environment
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@string_filter
|
|
16
|
-
@with_environment
|
|
17
|
-
def stylesheet_tag(url: str, *, environment: Environment) -> str:
|
|
18
|
-
"""Wrap a URL in an HTML stylesheet tag."""
|
|
19
|
-
tag = '<link href="{}" rel="stylesheet" type="text/css" media="all" />'
|
|
20
|
-
if environment.autoescape:
|
|
21
|
-
return Markup(tag).format(str(url))
|
|
22
|
-
return tag.format(html.escape(url))
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@string_filter
|
|
26
|
-
@with_environment
|
|
27
|
-
def script_tag(url: str, *, environment: Environment) -> str:
|
|
28
|
-
"""Wrap a URL in an HTML script tag."""
|
|
29
|
-
tag = '<script src="{}" type="text/javascript"></script>'
|
|
30
|
-
if environment.autoescape:
|
|
31
|
-
return Markup(tag).format(str(url))
|
|
32
|
-
return tag.format(html.escape(url))
|