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
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
"""Built-in primitive expressions."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import sys
|
|
6
|
-
from typing import TYPE_CHECKING
|
|
7
|
-
from typing import Any
|
|
8
|
-
from typing import Generic
|
|
9
|
-
from typing import TypeVar
|
|
10
|
-
from typing import Union
|
|
11
|
-
|
|
12
|
-
from markupsafe import Markup
|
|
13
|
-
|
|
14
|
-
from liquid.exceptions import LiquidSyntaxError
|
|
15
|
-
from liquid.expression import Expression
|
|
16
|
-
from liquid.limits import to_int
|
|
17
|
-
from liquid.token import TOKEN_BLANK
|
|
18
|
-
from liquid.token import TOKEN_EMPTY
|
|
19
|
-
from liquid.token import TOKEN_FALSE
|
|
20
|
-
from liquid.token import TOKEN_FLOAT
|
|
21
|
-
from liquid.token import TOKEN_IDENTSTRING
|
|
22
|
-
from liquid.token import TOKEN_INTEGER
|
|
23
|
-
from liquid.token import TOKEN_LBRACKET
|
|
24
|
-
from liquid.token import TOKEN_NIL
|
|
25
|
-
from liquid.token import TOKEN_NULL
|
|
26
|
-
from liquid.token import TOKEN_RANGE
|
|
27
|
-
from liquid.token import TOKEN_RANGE_LITERAL
|
|
28
|
-
from liquid.token import TOKEN_RPAREN
|
|
29
|
-
from liquid.token import TOKEN_STRING
|
|
30
|
-
from liquid.token import TOKEN_TRUE
|
|
31
|
-
from liquid.token import TOKEN_WORD
|
|
32
|
-
|
|
33
|
-
from .path import Path
|
|
34
|
-
|
|
35
|
-
if TYPE_CHECKING:
|
|
36
|
-
from liquid import Environment
|
|
37
|
-
from liquid import RenderContext
|
|
38
|
-
from liquid import Token
|
|
39
|
-
from liquid import TokenStream
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class Nil(Expression):
|
|
43
|
-
__slots__ = ()
|
|
44
|
-
|
|
45
|
-
def __eq__(self, other: object) -> bool:
|
|
46
|
-
return other is None or isinstance(other, Nil)
|
|
47
|
-
|
|
48
|
-
def __str__(self) -> str: # pragma: no cover
|
|
49
|
-
return ""
|
|
50
|
-
|
|
51
|
-
def evaluate(self, _: RenderContext) -> None:
|
|
52
|
-
return None
|
|
53
|
-
|
|
54
|
-
def children(self) -> list[Expression]:
|
|
55
|
-
return []
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class Empty(Expression):
|
|
59
|
-
__slots__ = ()
|
|
60
|
-
|
|
61
|
-
def __eq__(self, other: object) -> bool:
|
|
62
|
-
if isinstance(other, Empty):
|
|
63
|
-
return True
|
|
64
|
-
return isinstance(other, (list, dict, str)) and not other
|
|
65
|
-
|
|
66
|
-
def __str__(self) -> str: # pragma: no cover
|
|
67
|
-
return ""
|
|
68
|
-
|
|
69
|
-
def evaluate(self, _: RenderContext) -> Empty:
|
|
70
|
-
return self
|
|
71
|
-
|
|
72
|
-
def children(self) -> list[Expression]:
|
|
73
|
-
return []
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
class Blank(Expression):
|
|
77
|
-
__slots__ = ()
|
|
78
|
-
|
|
79
|
-
def __eq__(self, other: object) -> bool:
|
|
80
|
-
if isinstance(other, str) and (not other or other.isspace()):
|
|
81
|
-
return True
|
|
82
|
-
if isinstance(other, (list, dict)) and not other:
|
|
83
|
-
return True
|
|
84
|
-
return isinstance(other, Blank)
|
|
85
|
-
|
|
86
|
-
def __str__(self) -> str: # pragma: no cover
|
|
87
|
-
return ""
|
|
88
|
-
|
|
89
|
-
def evaluate(self, _: RenderContext) -> Blank:
|
|
90
|
-
return self
|
|
91
|
-
|
|
92
|
-
def children(self) -> list[Expression]:
|
|
93
|
-
return []
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class Continue(Expression):
|
|
97
|
-
__slots__ = ()
|
|
98
|
-
|
|
99
|
-
def __eq__(self, other: object) -> bool:
|
|
100
|
-
return isinstance(other, Continue)
|
|
101
|
-
|
|
102
|
-
def __str__(self) -> str: # pragma: no cover
|
|
103
|
-
return "continue"
|
|
104
|
-
|
|
105
|
-
def evaluate(self, _: RenderContext) -> int:
|
|
106
|
-
return 0
|
|
107
|
-
|
|
108
|
-
def children(self) -> list[Expression]:
|
|
109
|
-
return []
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
T = TypeVar("T")
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
class Literal(Expression, Generic[T]):
|
|
116
|
-
__slots__ = ("value",)
|
|
117
|
-
|
|
118
|
-
def __init__(self, token: Token, value: T):
|
|
119
|
-
super().__init__(token)
|
|
120
|
-
self.value = value
|
|
121
|
-
|
|
122
|
-
def __str__(self) -> str:
|
|
123
|
-
return repr(self.value)
|
|
124
|
-
|
|
125
|
-
def __eq__(self, other: object) -> bool:
|
|
126
|
-
return self.value == other
|
|
127
|
-
|
|
128
|
-
def __hash__(self) -> int:
|
|
129
|
-
return hash(self.value)
|
|
130
|
-
|
|
131
|
-
def __sizeof__(self) -> int:
|
|
132
|
-
return sys.getsizeof(self.value)
|
|
133
|
-
|
|
134
|
-
def evaluate(self, _: RenderContext) -> object:
|
|
135
|
-
return self.value
|
|
136
|
-
|
|
137
|
-
def children(self) -> list[Expression]:
|
|
138
|
-
return []
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
class TrueLiteral(Literal[bool]):
|
|
142
|
-
__slots__ = ()
|
|
143
|
-
|
|
144
|
-
def __init__(self, token: Token):
|
|
145
|
-
super().__init__(token, True)
|
|
146
|
-
|
|
147
|
-
def __eq__(self, other: object) -> bool:
|
|
148
|
-
return isinstance(other, TrueLiteral)
|
|
149
|
-
|
|
150
|
-
def __str__(self) -> str:
|
|
151
|
-
return "true"
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
class FalseLiteral(Literal[bool]):
|
|
155
|
-
__slots__ = ()
|
|
156
|
-
|
|
157
|
-
def __init__(self, token: Token):
|
|
158
|
-
super().__init__(token, False)
|
|
159
|
-
|
|
160
|
-
def __eq__(self, other: object) -> bool:
|
|
161
|
-
return isinstance(other, FalseLiteral)
|
|
162
|
-
|
|
163
|
-
def __str__(self) -> str:
|
|
164
|
-
return "false"
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
class StringLiteral(Literal[str]):
|
|
168
|
-
__slots__ = ()
|
|
169
|
-
|
|
170
|
-
def __init__(self, token: Token, value: str):
|
|
171
|
-
super().__init__(token, value)
|
|
172
|
-
|
|
173
|
-
def __eq__(self, other: object) -> bool:
|
|
174
|
-
return isinstance(other, StringLiteral) and self.value == other.value
|
|
175
|
-
|
|
176
|
-
def __hash__(self) -> int:
|
|
177
|
-
return hash(self.value)
|
|
178
|
-
|
|
179
|
-
def __sizeof__(self) -> int:
|
|
180
|
-
return sys.getsizeof(self.value)
|
|
181
|
-
|
|
182
|
-
def evaluate(self, context: RenderContext) -> Union[str, Markup]:
|
|
183
|
-
if context.autoescape:
|
|
184
|
-
return Markup(self.value)
|
|
185
|
-
return self.value
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
class IntegerLiteral(Literal[int]):
|
|
189
|
-
__slots__ = ()
|
|
190
|
-
|
|
191
|
-
def __init__(self, token: Token, value: int):
|
|
192
|
-
super().__init__(token, value)
|
|
193
|
-
|
|
194
|
-
def __eq__(self, other: object) -> bool:
|
|
195
|
-
return isinstance(other, IntegerLiteral) and self.value == other.value
|
|
196
|
-
|
|
197
|
-
def __hash__(self) -> int:
|
|
198
|
-
return hash(self.value)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
class FloatLiteral(Literal[float]):
|
|
202
|
-
__slots__ = ()
|
|
203
|
-
|
|
204
|
-
def __init__(self, token: Token, value: float):
|
|
205
|
-
super().__init__(token, value)
|
|
206
|
-
|
|
207
|
-
def __eq__(self, other: object) -> bool:
|
|
208
|
-
return isinstance(other, FloatLiteral) and self.value == other.value
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
class RangeLiteral(Expression):
|
|
212
|
-
__slots__ = ("start", "stop")
|
|
213
|
-
|
|
214
|
-
def __init__(self, token: Token, start: Expression, stop: Expression):
|
|
215
|
-
super().__init__(token)
|
|
216
|
-
self.start = start
|
|
217
|
-
self.stop = stop
|
|
218
|
-
|
|
219
|
-
def __eq__(self, other: object) -> bool:
|
|
220
|
-
return (
|
|
221
|
-
isinstance(other, RangeLiteral)
|
|
222
|
-
and self.start == other.start
|
|
223
|
-
and self.stop == other.stop
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
def __str__(self) -> str:
|
|
227
|
-
return f"({self.start}..{self.stop})"
|
|
228
|
-
|
|
229
|
-
def __hash__(self) -> int:
|
|
230
|
-
return hash((self.start, self.stop))
|
|
231
|
-
|
|
232
|
-
def __sizeof__(self) -> int:
|
|
233
|
-
return (
|
|
234
|
-
super().__sizeof__() + sys.getsizeof(self.start) + sys.getsizeof(self.stop)
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
def _make_range(self, start: Any, stop: Any) -> range:
|
|
238
|
-
try:
|
|
239
|
-
start = to_int(start)
|
|
240
|
-
except (ValueError, TypeError):
|
|
241
|
-
start = 0
|
|
242
|
-
|
|
243
|
-
try:
|
|
244
|
-
stop = to_int(stop)
|
|
245
|
-
except (ValueError, TypeError):
|
|
246
|
-
stop = 0
|
|
247
|
-
|
|
248
|
-
# Descending ranges don't work
|
|
249
|
-
if start > stop:
|
|
250
|
-
return range(0)
|
|
251
|
-
|
|
252
|
-
return range(start, stop + 1)
|
|
253
|
-
|
|
254
|
-
def evaluate(self, context: RenderContext) -> range:
|
|
255
|
-
return self._make_range(
|
|
256
|
-
self.start.evaluate(context), self.stop.evaluate(context)
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
async def evaluate_async(self, context: RenderContext) -> range:
|
|
260
|
-
return self._make_range(
|
|
261
|
-
await self.start.evaluate_async(context),
|
|
262
|
-
await self.stop.evaluate_async(context),
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
def children(self) -> list[Expression]:
|
|
266
|
-
return [self.start, self.stop]
|
|
267
|
-
|
|
268
|
-
@staticmethod
|
|
269
|
-
def parse(env: Environment, tokens: TokenStream) -> RangeLiteral:
|
|
270
|
-
token = tokens.eat(TOKEN_RANGE_LITERAL)
|
|
271
|
-
start = parse_primitive(env, tokens)
|
|
272
|
-
tokens.eat(TOKEN_RANGE)
|
|
273
|
-
stop = parse_primitive(env, tokens)
|
|
274
|
-
tokens.eat(TOKEN_RPAREN)
|
|
275
|
-
return RangeLiteral(token, start, stop)
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
def parse_primitive(env: Environment, tokens: TokenStream) -> Expression: # noqa: PLR0911
|
|
279
|
-
"""Parse a primitive expression from _tokens_."""
|
|
280
|
-
token = tokens.current
|
|
281
|
-
kind = token.kind
|
|
282
|
-
|
|
283
|
-
if kind == TOKEN_TRUE:
|
|
284
|
-
return TrueLiteral(next(tokens))
|
|
285
|
-
if kind == TOKEN_FALSE:
|
|
286
|
-
return FalseLiteral(next(tokens))
|
|
287
|
-
if kind in (TOKEN_NIL, TOKEN_NULL):
|
|
288
|
-
return Nil(next(tokens))
|
|
289
|
-
if kind == TOKEN_INTEGER:
|
|
290
|
-
return IntegerLiteral(next(tokens), to_int(token.value))
|
|
291
|
-
if kind == TOKEN_FLOAT:
|
|
292
|
-
return FloatLiteral(next(tokens), float(token.value))
|
|
293
|
-
if kind == TOKEN_STRING:
|
|
294
|
-
return StringLiteral(next(tokens), token.value)
|
|
295
|
-
if kind == TOKEN_RANGE_LITERAL:
|
|
296
|
-
return RangeLiteral.parse(env, tokens)
|
|
297
|
-
if kind == TOKEN_EMPTY:
|
|
298
|
-
return Empty(next(tokens))
|
|
299
|
-
if kind == TOKEN_BLANK:
|
|
300
|
-
return Blank(next(tokens))
|
|
301
|
-
if kind in (TOKEN_WORD, TOKEN_IDENTSTRING, TOKEN_LBRACKET):
|
|
302
|
-
return Path.parse(env, tokens)
|
|
303
|
-
|
|
304
|
-
raise LiquidSyntaxError(
|
|
305
|
-
f"expected a primitive expression, found {token.kind}", token=token
|
|
306
|
-
)
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
class Identifier(str):
|
|
310
|
-
"""A string, token pair."""
|
|
311
|
-
|
|
312
|
-
def __new__(
|
|
313
|
-
cls, obj: object, *args: object, token: Token, **kwargs: object
|
|
314
|
-
) -> Identifier:
|
|
315
|
-
instance = super().__new__(cls, obj, *args, **kwargs)
|
|
316
|
-
instance.token = token
|
|
317
|
-
return instance
|
|
318
|
-
|
|
319
|
-
def __init__(
|
|
320
|
-
self,
|
|
321
|
-
obj: object, # noqa: ARG002
|
|
322
|
-
*args: object, # noqa: ARG002
|
|
323
|
-
token: Token, # noqa: ARG002
|
|
324
|
-
**kwargs: object, # noqa: ARG002
|
|
325
|
-
) -> None:
|
|
326
|
-
super().__init__()
|
|
327
|
-
self.token: Token
|
|
328
|
-
|
|
329
|
-
def __eq__(self, value: object) -> bool:
|
|
330
|
-
return super().__eq__(value)
|
|
331
|
-
|
|
332
|
-
def __hash__(self) -> int:
|
|
333
|
-
return super().__hash__()
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
def parse_identifier(
|
|
337
|
-
env: Environment,
|
|
338
|
-
tokens: TokenStream,
|
|
339
|
-
*,
|
|
340
|
-
allow_trailing_question_mark: bool = True,
|
|
341
|
-
) -> Identifier:
|
|
342
|
-
"""Parse a word that might otherwise be considered a path with one segment."""
|
|
343
|
-
expr = parse_primitive(env, tokens)
|
|
344
|
-
|
|
345
|
-
if isinstance(expr, IntegerLiteral):
|
|
346
|
-
return Identifier(str(expr.value), token=expr.token)
|
|
347
|
-
|
|
348
|
-
if not isinstance(expr, Path):
|
|
349
|
-
raise LiquidSyntaxError(
|
|
350
|
-
f"expected an identifier, found {expr.__class__.__name__}", token=expr.token
|
|
351
|
-
)
|
|
352
|
-
|
|
353
|
-
if len(expr.path) != 1:
|
|
354
|
-
raise LiquidSyntaxError(
|
|
355
|
-
"expected an identifier, found a path with multiple segments",
|
|
356
|
-
token=expr.token,
|
|
357
|
-
)
|
|
358
|
-
|
|
359
|
-
word = expr.path[0]
|
|
360
|
-
|
|
361
|
-
if not isinstance(word, str):
|
|
362
|
-
raise LiquidSyntaxError(
|
|
363
|
-
f"expected an identifier, found {word.__class__.__name__}",
|
|
364
|
-
token=expr.token,
|
|
365
|
-
)
|
|
366
|
-
|
|
367
|
-
if not allow_trailing_question_mark and word.endswith("?"):
|
|
368
|
-
raise LiquidSyntaxError("invalid identifier", token=expr.token)
|
|
369
|
-
|
|
370
|
-
return Identifier(word, token=expr.token)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
def parse_name(env: Environment, tokens: TokenStream) -> Identifier:
|
|
374
|
-
"""Parse a quoted or unquoted word."""
|
|
375
|
-
expr = parse_primitive(env, tokens)
|
|
376
|
-
|
|
377
|
-
if isinstance(expr, StringLiteral):
|
|
378
|
-
return Identifier(expr.value, token=expr.token)
|
|
379
|
-
|
|
380
|
-
if not isinstance(expr, Path):
|
|
381
|
-
raise LiquidSyntaxError(
|
|
382
|
-
f"expected a name, found {expr.__class__.__name__}", token=expr.token
|
|
383
|
-
)
|
|
384
|
-
|
|
385
|
-
if len(expr.path) != 1:
|
|
386
|
-
raise LiquidSyntaxError(
|
|
387
|
-
f"expected a name, found a path with multiple segments, {expr.path!r}",
|
|
388
|
-
token=expr.token,
|
|
389
|
-
)
|
|
390
|
-
|
|
391
|
-
word = expr.path[0]
|
|
392
|
-
|
|
393
|
-
if not isinstance(word, str):
|
|
394
|
-
raise LiquidSyntaxError(
|
|
395
|
-
f"expected a name, found {word.__class__.__name__}",
|
|
396
|
-
token=expr.token,
|
|
397
|
-
)
|
|
398
|
-
|
|
399
|
-
return Identifier(word, token=expr.token)
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
def parse_string_or_path(
|
|
403
|
-
env: Environment, tokens: TokenStream
|
|
404
|
-
) -> Union[Path, StringLiteral]:
|
|
405
|
-
"""Parse a string literal or path to a string variable."""
|
|
406
|
-
expr = parse_primitive(env, tokens)
|
|
407
|
-
if not isinstance(expr, (Path, StringLiteral)):
|
|
408
|
-
raise LiquidSyntaxError(
|
|
409
|
-
f"expected an string or variable, found {expr.__class__.__name__}",
|
|
410
|
-
token=expr.token,
|
|
411
|
-
)
|
|
412
|
-
return expr
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
def is_empty(obj: object) -> bool:
|
|
416
|
-
"""Return True if _obj_ is considered empty."""
|
|
417
|
-
return isinstance(obj, (list, dict, str)) and not obj
|
|
File without changes
|