python-liquid 2.3.5__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/loaders/file_system_loader.py +143 -0
- liquid/{builtin/loaders → loaders}/mixins.py +40 -52
- 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.5.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.5.dist-info → python_liquid-3.0.0.dist-info}/WHEEL +1 -1
- {python_liquid-2.3.5.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/file_system_loader.py +0 -146
- 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.5.dist-info/RECORD +0 -96
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
"""Built-in filtered expressions."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
|
-
from typing import Union
|
|
7
|
-
|
|
8
|
-
from liquid import Mode
|
|
9
|
-
from liquid.exceptions import FilterArgumentError
|
|
10
|
-
from liquid.exceptions import LiquidSyntaxError
|
|
11
|
-
from liquid.exceptions import LiquidTypeError
|
|
12
|
-
from liquid.exceptions import UnknownFilterError
|
|
13
|
-
from liquid.expression import Expression
|
|
14
|
-
from liquid.token import TOKEN_ASSIGN
|
|
15
|
-
from liquid.token import TOKEN_COLON
|
|
16
|
-
from liquid.token import TOKEN_COMMA
|
|
17
|
-
from liquid.token import TOKEN_DPIPE
|
|
18
|
-
from liquid.token import TOKEN_ELSE
|
|
19
|
-
from liquid.token import TOKEN_EOF
|
|
20
|
-
from liquid.token import TOKEN_FALSE
|
|
21
|
-
from liquid.token import TOKEN_FLOAT
|
|
22
|
-
from liquid.token import TOKEN_IF
|
|
23
|
-
from liquid.token import TOKEN_INTEGER
|
|
24
|
-
from liquid.token import TOKEN_LBRACKET
|
|
25
|
-
from liquid.token import TOKEN_LPAREN
|
|
26
|
-
from liquid.token import TOKEN_NIL
|
|
27
|
-
from liquid.token import TOKEN_NULL
|
|
28
|
-
from liquid.token import TOKEN_PIPE
|
|
29
|
-
from liquid.token import TOKEN_RANGE_LITERAL
|
|
30
|
-
from liquid.token import TOKEN_STRING
|
|
31
|
-
from liquid.token import TOKEN_TRUE
|
|
32
|
-
from liquid.token import TOKEN_WORD
|
|
33
|
-
|
|
34
|
-
from .arguments import KeywordArgument
|
|
35
|
-
from .arguments import PositionalArgument
|
|
36
|
-
from .logical import BooleanExpression
|
|
37
|
-
from .primitive import parse_primitive
|
|
38
|
-
|
|
39
|
-
if TYPE_CHECKING:
|
|
40
|
-
from liquid import Environment
|
|
41
|
-
from liquid import RenderContext
|
|
42
|
-
from liquid import TokenStream
|
|
43
|
-
from liquid.token import Token
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
FILTER_TOKENS = set( # noqa: C405
|
|
47
|
-
[
|
|
48
|
-
TOKEN_INTEGER,
|
|
49
|
-
TOKEN_FLOAT,
|
|
50
|
-
TOKEN_STRING,
|
|
51
|
-
TOKEN_FALSE,
|
|
52
|
-
TOKEN_TRUE,
|
|
53
|
-
TOKEN_NIL,
|
|
54
|
-
TOKEN_NULL,
|
|
55
|
-
TOKEN_RANGE_LITERAL,
|
|
56
|
-
TOKEN_LBRACKET,
|
|
57
|
-
TOKEN_LPAREN,
|
|
58
|
-
TOKEN_WORD,
|
|
59
|
-
]
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class FilteredExpression(Expression):
|
|
64
|
-
"""An expression for the built-in `assign` tag and output statement."""
|
|
65
|
-
|
|
66
|
-
__slots__ = ("left", "filters")
|
|
67
|
-
|
|
68
|
-
def __init__(
|
|
69
|
-
self,
|
|
70
|
-
token: Token,
|
|
71
|
-
left: Expression,
|
|
72
|
-
filters: list[Filter] | None = None,
|
|
73
|
-
) -> None:
|
|
74
|
-
super().__init__(token=token)
|
|
75
|
-
self.left = left
|
|
76
|
-
self.filters = filters
|
|
77
|
-
|
|
78
|
-
def __str__(self) -> str:
|
|
79
|
-
filters = (
|
|
80
|
-
" | " + " | ".join(str(f) for f in self.filters) if self.filters else ""
|
|
81
|
-
)
|
|
82
|
-
return f"{self.left}{filters}"
|
|
83
|
-
|
|
84
|
-
def evaluate(self, context: RenderContext) -> object:
|
|
85
|
-
rv = self.left.evaluate(context)
|
|
86
|
-
if self.filters:
|
|
87
|
-
for f in self.filters:
|
|
88
|
-
rv = f.evaluate(rv, context)
|
|
89
|
-
return rv
|
|
90
|
-
|
|
91
|
-
async def evaluate_async(self, context: RenderContext) -> object:
|
|
92
|
-
rv = await self.left.evaluate_async(context)
|
|
93
|
-
if self.filters:
|
|
94
|
-
for f in self.filters:
|
|
95
|
-
rv = await f.evaluate_async(rv, context)
|
|
96
|
-
return rv
|
|
97
|
-
|
|
98
|
-
def children(self) -> list[Expression]:
|
|
99
|
-
children = [self.left]
|
|
100
|
-
if self.filters:
|
|
101
|
-
for filter_ in self.filters:
|
|
102
|
-
children.extend(filter_.children())
|
|
103
|
-
return children
|
|
104
|
-
|
|
105
|
-
@staticmethod
|
|
106
|
-
def parse(
|
|
107
|
-
env: Environment, tokens: TokenStream
|
|
108
|
-
) -> Union[FilteredExpression, TernaryFilteredExpression]:
|
|
109
|
-
"""Parse a filtered expression from _tokens_."""
|
|
110
|
-
left = parse_primitive(env, tokens)
|
|
111
|
-
filters = Filter.parse(env, tokens, delim=(TOKEN_PIPE,))
|
|
112
|
-
|
|
113
|
-
if tokens.current.kind == TOKEN_IF:
|
|
114
|
-
if not env.ternary_expressions:
|
|
115
|
-
raise LiquidSyntaxError(
|
|
116
|
-
"disallowed ternary expression", token=tokens.current
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
return TernaryFilteredExpression.parse(
|
|
120
|
-
env, FilteredExpression(left.token, left, filters), tokens
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
tokens.eat(TOKEN_EOF)
|
|
124
|
-
return FilteredExpression(left.token, left, filters)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
class TernaryFilteredExpression(Expression):
|
|
128
|
-
__slots__ = ("left", "condition", "alternative", "filters", "tail_filters")
|
|
129
|
-
|
|
130
|
-
def __init__(
|
|
131
|
-
self,
|
|
132
|
-
token: Token,
|
|
133
|
-
left: FilteredExpression,
|
|
134
|
-
condition: Expression,
|
|
135
|
-
alternative: Expression | None = None,
|
|
136
|
-
filters: list[Filter] | None = None,
|
|
137
|
-
tail_filters: list[Filter] | None = None,
|
|
138
|
-
) -> None:
|
|
139
|
-
super().__init__(token=token)
|
|
140
|
-
self.left = left
|
|
141
|
-
self.condition = condition
|
|
142
|
-
self.alternative = alternative
|
|
143
|
-
self.filters = filters
|
|
144
|
-
self.tail_filters = tail_filters
|
|
145
|
-
|
|
146
|
-
def __str__(self) -> str:
|
|
147
|
-
buf = [f"{self.left} if {self.condition}"]
|
|
148
|
-
|
|
149
|
-
if self.alternative:
|
|
150
|
-
buf.append(f" else {self.alternative}")
|
|
151
|
-
|
|
152
|
-
if self.filters:
|
|
153
|
-
buf.append(" | " + " | ".join(str(f) for f in self.filters))
|
|
154
|
-
|
|
155
|
-
if self.tail_filters:
|
|
156
|
-
buf.append(" || " + " | ".join(str(f) for f in self.tail_filters))
|
|
157
|
-
|
|
158
|
-
return "".join(buf)
|
|
159
|
-
|
|
160
|
-
def evaluate(self, context: RenderContext) -> object:
|
|
161
|
-
rv: object = None
|
|
162
|
-
|
|
163
|
-
if self.condition.evaluate(context):
|
|
164
|
-
rv = self.left.evaluate(context)
|
|
165
|
-
elif self.alternative:
|
|
166
|
-
rv = self.alternative.evaluate(context)
|
|
167
|
-
if self.filters:
|
|
168
|
-
for f in self.filters:
|
|
169
|
-
rv = f.evaluate(rv, context)
|
|
170
|
-
|
|
171
|
-
if self.tail_filters:
|
|
172
|
-
for f in self.tail_filters:
|
|
173
|
-
rv = f.evaluate(rv, context)
|
|
174
|
-
|
|
175
|
-
return rv
|
|
176
|
-
|
|
177
|
-
async def evaluate_async(self, context: RenderContext) -> object:
|
|
178
|
-
rv: object = None
|
|
179
|
-
|
|
180
|
-
if await self.condition.evaluate_async(context):
|
|
181
|
-
rv = await self.left.evaluate_async(context)
|
|
182
|
-
elif self.alternative:
|
|
183
|
-
rv = await self.alternative.evaluate_async(context)
|
|
184
|
-
if self.filters:
|
|
185
|
-
for f in self.filters:
|
|
186
|
-
rv = await f.evaluate_async(rv, context)
|
|
187
|
-
|
|
188
|
-
if self.tail_filters:
|
|
189
|
-
for f in self.tail_filters:
|
|
190
|
-
rv = await f.evaluate_async(rv, context)
|
|
191
|
-
|
|
192
|
-
return rv
|
|
193
|
-
|
|
194
|
-
def children(self) -> list[Expression]:
|
|
195
|
-
children = self.left.children()
|
|
196
|
-
children.append(self.condition)
|
|
197
|
-
|
|
198
|
-
if self.alternative:
|
|
199
|
-
children.append(self.alternative)
|
|
200
|
-
|
|
201
|
-
if self.filters:
|
|
202
|
-
for filter_ in self.filters:
|
|
203
|
-
children.extend(filter_.children())
|
|
204
|
-
|
|
205
|
-
if self.tail_filters:
|
|
206
|
-
for filter_ in self.tail_filters:
|
|
207
|
-
children.extend(filter_.children())
|
|
208
|
-
|
|
209
|
-
return children
|
|
210
|
-
|
|
211
|
-
@staticmethod
|
|
212
|
-
def parse(
|
|
213
|
-
env: Environment, expr: FilteredExpression, tokens: TokenStream
|
|
214
|
-
) -> TernaryFilteredExpression:
|
|
215
|
-
"""Parse a ternary expression from _tokens_."""
|
|
216
|
-
tokens.eat(TOKEN_IF)
|
|
217
|
-
condition = BooleanExpression.parse(env, tokens, inline=True)
|
|
218
|
-
alternative: Expression | None = None
|
|
219
|
-
filters: list[Filter] | None = None
|
|
220
|
-
tail_filters: list[Filter] | None = None
|
|
221
|
-
|
|
222
|
-
if tokens.current.kind == TOKEN_ELSE:
|
|
223
|
-
next(tokens) # else
|
|
224
|
-
alternative = parse_primitive(env, tokens)
|
|
225
|
-
|
|
226
|
-
if tokens.current.kind == TOKEN_PIPE:
|
|
227
|
-
filters = Filter.parse(env, tokens, delim=(TOKEN_PIPE,))
|
|
228
|
-
|
|
229
|
-
if tokens.current.kind == TOKEN_DPIPE:
|
|
230
|
-
tail_filters = Filter.parse(env, tokens, delim=(TOKEN_PIPE, TOKEN_DPIPE))
|
|
231
|
-
|
|
232
|
-
tokens.eat(TOKEN_EOF)
|
|
233
|
-
return TernaryFilteredExpression(
|
|
234
|
-
expr.token, expr, condition, alternative, filters, tail_filters
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
class Filter:
|
|
239
|
-
__slots__ = ("name", "args", "token")
|
|
240
|
-
|
|
241
|
-
def __init__(
|
|
242
|
-
self,
|
|
243
|
-
token: Token,
|
|
244
|
-
name: str,
|
|
245
|
-
arguments: list[KeywordArgument | PositionalArgument],
|
|
246
|
-
) -> None:
|
|
247
|
-
self.token = token
|
|
248
|
-
self.name = name
|
|
249
|
-
self.args = arguments
|
|
250
|
-
|
|
251
|
-
def __str__(self) -> str:
|
|
252
|
-
if self.args:
|
|
253
|
-
return f"{self.name}: {', '.join(str(arg) for arg in self.args)}"
|
|
254
|
-
return self.name
|
|
255
|
-
|
|
256
|
-
def validate_filter_arguments(self, env: Environment) -> None:
|
|
257
|
-
try:
|
|
258
|
-
func = env.filters[self.name]
|
|
259
|
-
except KeyError as err:
|
|
260
|
-
raise UnknownFilterError(
|
|
261
|
-
f"unknown filter '{self.name}'", token=self.token
|
|
262
|
-
) from err
|
|
263
|
-
|
|
264
|
-
if hasattr(func, "validate"):
|
|
265
|
-
func.validate(env, self.token, self.name, self.args)
|
|
266
|
-
|
|
267
|
-
def evaluate(self, left: object, context: RenderContext) -> object:
|
|
268
|
-
func = context.filter(self.name, token=self.token)
|
|
269
|
-
positional_args, keyword_args = self.evaluate_args(context)
|
|
270
|
-
try:
|
|
271
|
-
return func(left, *positional_args, **keyword_args)
|
|
272
|
-
except TypeError as err:
|
|
273
|
-
raise LiquidTypeError(f"{self.name}: {err}", token=self.token) from err
|
|
274
|
-
except (LiquidTypeError, FilterArgumentError) as err:
|
|
275
|
-
err.token = self.token
|
|
276
|
-
raise err
|
|
277
|
-
|
|
278
|
-
async def evaluate_async(self, left: object, context: RenderContext) -> object:
|
|
279
|
-
func = context.filter(self.name, token=self.token)
|
|
280
|
-
positional_args, keyword_args = await self.evaluate_args_async(context)
|
|
281
|
-
|
|
282
|
-
try:
|
|
283
|
-
if hasattr(func, "filter_async"):
|
|
284
|
-
return await func.filter_async(left, *positional_args, **keyword_args)
|
|
285
|
-
return func(left, *positional_args, **keyword_args)
|
|
286
|
-
except TypeError as err:
|
|
287
|
-
raise LiquidTypeError(f"{self.name}: {err}", token=self.token) from err
|
|
288
|
-
except (LiquidTypeError, FilterArgumentError) as err:
|
|
289
|
-
err.token = self.token
|
|
290
|
-
raise err
|
|
291
|
-
|
|
292
|
-
def evaluate_args(
|
|
293
|
-
self, context: RenderContext
|
|
294
|
-
) -> tuple[list[object], dict[str, object]]:
|
|
295
|
-
positional_args: list[object] = []
|
|
296
|
-
keyword_args: dict[str, object] = {}
|
|
297
|
-
for arg in self.args:
|
|
298
|
-
name, value = arg.evaluate(context)
|
|
299
|
-
if name:
|
|
300
|
-
keyword_args[name] = value
|
|
301
|
-
else:
|
|
302
|
-
positional_args.append(value)
|
|
303
|
-
|
|
304
|
-
return positional_args, keyword_args
|
|
305
|
-
|
|
306
|
-
async def evaluate_args_async(
|
|
307
|
-
self, context: RenderContext
|
|
308
|
-
) -> tuple[list[object], dict[str, object]]:
|
|
309
|
-
positional_args: list[object] = []
|
|
310
|
-
keyword_args: dict[str, object] = {}
|
|
311
|
-
for arg in self.args:
|
|
312
|
-
name, value = await arg.evaluate_async(context)
|
|
313
|
-
if name:
|
|
314
|
-
keyword_args[name] = value
|
|
315
|
-
else:
|
|
316
|
-
positional_args.append(value)
|
|
317
|
-
|
|
318
|
-
return positional_args, keyword_args
|
|
319
|
-
|
|
320
|
-
def children(self) -> list[Expression]:
|
|
321
|
-
return [arg.value for arg in self.args]
|
|
322
|
-
|
|
323
|
-
@staticmethod
|
|
324
|
-
def parse(
|
|
325
|
-
env: Environment, tokens: TokenStream, *, delim: tuple[str, ...]
|
|
326
|
-
) -> list[Filter]:
|
|
327
|
-
"""Parse filters from _tokens_."""
|
|
328
|
-
filters: list[Filter] = []
|
|
329
|
-
argument_separators = (
|
|
330
|
-
(TOKEN_COLON, TOKEN_ASSIGN) if env.keyword_assignment else (TOKEN_COLON,)
|
|
331
|
-
)
|
|
332
|
-
|
|
333
|
-
while tokens.current.kind in delim:
|
|
334
|
-
next(tokens)
|
|
335
|
-
token = tokens.eat(TOKEN_WORD)
|
|
336
|
-
args: list[Union[KeywordArgument, PositionalArgument]] = []
|
|
337
|
-
|
|
338
|
-
if tokens.current.kind != TOKEN_COLON:
|
|
339
|
-
# No arguments
|
|
340
|
-
filters.append(Filter(token, token.value, args))
|
|
341
|
-
continue
|
|
342
|
-
|
|
343
|
-
tokens.eat(TOKEN_COLON)
|
|
344
|
-
while True:
|
|
345
|
-
tok = tokens.current
|
|
346
|
-
if tok.kind == TOKEN_WORD:
|
|
347
|
-
if tokens.peek.kind in argument_separators:
|
|
348
|
-
next(tokens) # word
|
|
349
|
-
next(tokens) # : or =
|
|
350
|
-
args.append(
|
|
351
|
-
KeywordArgument(
|
|
352
|
-
tok, tok.value, parse_primitive(env, tokens)
|
|
353
|
-
)
|
|
354
|
-
)
|
|
355
|
-
else:
|
|
356
|
-
args.append(PositionalArgument(parse_primitive(env, tokens)))
|
|
357
|
-
|
|
358
|
-
if tokens.current.kind in FILTER_TOKENS:
|
|
359
|
-
raise LiquidSyntaxError(
|
|
360
|
-
"expected a comma separated list of arguments, "
|
|
361
|
-
f"found {tokens.current.kind}",
|
|
362
|
-
token=tokens.current,
|
|
363
|
-
)
|
|
364
|
-
elif tok.kind in FILTER_TOKENS:
|
|
365
|
-
args.append(PositionalArgument(parse_primitive(env, tokens)))
|
|
366
|
-
|
|
367
|
-
# There should be a comma between filter tokens.
|
|
368
|
-
if tokens.current.kind in FILTER_TOKENS:
|
|
369
|
-
raise LiquidSyntaxError(
|
|
370
|
-
"expected a comma separated list of arguments, "
|
|
371
|
-
f"found {tokens.current.kind}",
|
|
372
|
-
token=tokens.current,
|
|
373
|
-
)
|
|
374
|
-
elif tok.kind == TOKEN_COMMA:
|
|
375
|
-
if env.mode == Mode.STRICT and tokens.peek.kind == TOKEN_COMMA:
|
|
376
|
-
raise LiquidSyntaxError(
|
|
377
|
-
"expected a comma separated list of arguments, "
|
|
378
|
-
f"found {tokens.peek.kind}",
|
|
379
|
-
token=tokens.peek,
|
|
380
|
-
)
|
|
381
|
-
next(tokens)
|
|
382
|
-
else:
|
|
383
|
-
break
|
|
384
|
-
|
|
385
|
-
filters.append(Filter(token, token.value, args))
|
|
386
|
-
|
|
387
|
-
return filters
|