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/drops/range.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from .._nothing import NOTHING
|
|
6
|
+
from .._slice import slice_range
|
|
7
|
+
from ..exceptions import ResourceLimitError
|
|
8
|
+
from .iterable import IterableDrop
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
|
|
13
|
+
from .._context import RenderContext
|
|
14
|
+
from .._drop import ContextHint
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Range:
|
|
18
|
+
__slots__ = ("start", "stop")
|
|
19
|
+
|
|
20
|
+
def __init__(self, start: int, stop: int) -> None:
|
|
21
|
+
self.start = start
|
|
22
|
+
self.stop = stop
|
|
23
|
+
|
|
24
|
+
def __liquid_getattr__(self, name: str, context: RenderContext) -> object:
|
|
25
|
+
match name:
|
|
26
|
+
case "first":
|
|
27
|
+
return self.start
|
|
28
|
+
case "last":
|
|
29
|
+
return self.stop
|
|
30
|
+
case "size":
|
|
31
|
+
return len(self)
|
|
32
|
+
case _:
|
|
33
|
+
raise KeyError
|
|
34
|
+
|
|
35
|
+
def __liquid_hasattr__(self, name: str, context: RenderContext) -> bool:
|
|
36
|
+
return name in ("first", "last", "size")
|
|
37
|
+
|
|
38
|
+
def __liquid_iter__(
|
|
39
|
+
self, offset: int, limit: int | None, reversed_: bool
|
|
40
|
+
) -> IterableDrop[int]:
|
|
41
|
+
it = slice_range(range(self.start, self.stop), offset, limit, reversed_)
|
|
42
|
+
return IterableDrop(it, len(it))
|
|
43
|
+
|
|
44
|
+
def __eq__(self, other: object) -> bool:
|
|
45
|
+
return (
|
|
46
|
+
isinstance(other, Range)
|
|
47
|
+
and self.start == other.start
|
|
48
|
+
and self.stop == other.stop
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def __len__(self) -> int:
|
|
52
|
+
return 0 if self.stop < self.start else self.stop - self.start + 1
|
|
53
|
+
|
|
54
|
+
def __bool__(self) -> bool:
|
|
55
|
+
return len(self) > 0
|
|
56
|
+
|
|
57
|
+
def __str__(self) -> str:
|
|
58
|
+
return f"{self.start}..{self.stop}"
|
|
59
|
+
|
|
60
|
+
def __liquid__(self, hint: ContextHint, context: RenderContext) -> object:
|
|
61
|
+
match hint:
|
|
62
|
+
case "output" | "string":
|
|
63
|
+
return str(self)
|
|
64
|
+
case "index" | "property" | "object":
|
|
65
|
+
return self
|
|
66
|
+
case "boolean":
|
|
67
|
+
return len(self) > 0
|
|
68
|
+
case "array":
|
|
69
|
+
if len(self) > 1_000_000: # XXX: arbitrary limit
|
|
70
|
+
raise ResourceLimitError("range limit reached")
|
|
71
|
+
return list(self.__liquid_iter__(0, None, False))
|
|
72
|
+
case _:
|
|
73
|
+
return NOTHING
|
|
74
|
+
|
|
75
|
+
def __iter__(self) -> Iterator[int]:
|
|
76
|
+
return iter(range(self.start, self.stop + 1))
|
liquid/drops/self_.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from .._nothing import NOTHING
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .._context import RenderContext
|
|
9
|
+
from .._drop import ContextHint
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Self:
|
|
13
|
+
__slots__ = ("context",)
|
|
14
|
+
|
|
15
|
+
def __init__(self, context: RenderContext) -> None:
|
|
16
|
+
super().__init__()
|
|
17
|
+
self.context = context
|
|
18
|
+
|
|
19
|
+
def __liquid_hasattr__(self, name: str, context: RenderContext) -> bool:
|
|
20
|
+
# Argument context is not necessarily the same as instance context.
|
|
21
|
+
return name in self.context.scope
|
|
22
|
+
|
|
23
|
+
def __liquid_getattr__(self, name: str, context: RenderContext) -> object:
|
|
24
|
+
# Argument context is not necessarily the same as instance context.
|
|
25
|
+
return self.context.resolve(name)
|
|
26
|
+
|
|
27
|
+
def __liquid__(self, hint: ContextHint, context: RenderContext) -> object:
|
|
28
|
+
match hint:
|
|
29
|
+
case "output" | "string":
|
|
30
|
+
return str(self)
|
|
31
|
+
case "object":
|
|
32
|
+
return self
|
|
33
|
+
case "array":
|
|
34
|
+
return [self]
|
|
35
|
+
case _:
|
|
36
|
+
return NOTHING
|
|
37
|
+
|
|
38
|
+
def __eq__(self, other: object) -> bool:
|
|
39
|
+
return isinstance(other, Self) and self.context is other.context
|
|
40
|
+
|
|
41
|
+
def __str__(self) -> str:
|
|
42
|
+
return "Liquid::SelfDrop"
|
|
43
|
+
|
|
44
|
+
def __contains__(self, item: object) -> bool:
|
|
45
|
+
return False
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from .._nothing import NOTHING
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .._context import RenderContext
|
|
9
|
+
from .._drop import ContextHint
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TableRowLoop:
|
|
13
|
+
"""Table row helper variables."""
|
|
14
|
+
|
|
15
|
+
__slots__ = (
|
|
16
|
+
"col",
|
|
17
|
+
"cols",
|
|
18
|
+
"index",
|
|
19
|
+
"length",
|
|
20
|
+
"row",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def __init__(self, length: int, cols: int) -> None:
|
|
24
|
+
self.length = length
|
|
25
|
+
self.cols = cols
|
|
26
|
+
|
|
27
|
+
self.col = 1
|
|
28
|
+
self.index = 0
|
|
29
|
+
self.row = 1
|
|
30
|
+
|
|
31
|
+
def __liquid_hasattr__(self, name: str, context: RenderContext) -> bool:
|
|
32
|
+
return name in (
|
|
33
|
+
"length",
|
|
34
|
+
"index",
|
|
35
|
+
"index0",
|
|
36
|
+
"rindex",
|
|
37
|
+
"rindex0",
|
|
38
|
+
"first",
|
|
39
|
+
"last",
|
|
40
|
+
"col",
|
|
41
|
+
"col0",
|
|
42
|
+
"col_first",
|
|
43
|
+
"col_last",
|
|
44
|
+
"row",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def __liquid_getattr__(self, name: str, context: RenderContext) -> object:
|
|
48
|
+
if name == "first":
|
|
49
|
+
return self.index == 0
|
|
50
|
+
|
|
51
|
+
if name == "index":
|
|
52
|
+
return self.index + 1
|
|
53
|
+
|
|
54
|
+
if name == "index0":
|
|
55
|
+
return self.index
|
|
56
|
+
|
|
57
|
+
if name == "last":
|
|
58
|
+
return self.index == self.length - 1
|
|
59
|
+
|
|
60
|
+
if name == "length":
|
|
61
|
+
return self.length
|
|
62
|
+
|
|
63
|
+
if name == "rindex":
|
|
64
|
+
return self.length - self.index
|
|
65
|
+
|
|
66
|
+
if name == "rindex0":
|
|
67
|
+
return self.length - self.index - 1
|
|
68
|
+
|
|
69
|
+
if name == "col":
|
|
70
|
+
return self.col
|
|
71
|
+
|
|
72
|
+
if name == "col_first":
|
|
73
|
+
return self.col == 1
|
|
74
|
+
|
|
75
|
+
if name == "col_last":
|
|
76
|
+
return self.col == self.cols
|
|
77
|
+
|
|
78
|
+
if name == "col0":
|
|
79
|
+
return self.col - 1
|
|
80
|
+
|
|
81
|
+
if name == "row":
|
|
82
|
+
return self.row
|
|
83
|
+
|
|
84
|
+
raise AttributeError
|
|
85
|
+
|
|
86
|
+
def __getitem__(self, key: str) -> int:
|
|
87
|
+
if key == "first":
|
|
88
|
+
return self.index == 0
|
|
89
|
+
|
|
90
|
+
if key == "index":
|
|
91
|
+
return self.index + 1
|
|
92
|
+
|
|
93
|
+
if key == "index0":
|
|
94
|
+
return self.index
|
|
95
|
+
|
|
96
|
+
if key == "last":
|
|
97
|
+
return self.index == self.length - 1
|
|
98
|
+
|
|
99
|
+
if key == "length":
|
|
100
|
+
return self.length
|
|
101
|
+
|
|
102
|
+
if key == "rindex":
|
|
103
|
+
return self.length - self.index
|
|
104
|
+
|
|
105
|
+
if key == "rindex0":
|
|
106
|
+
return self.length - self.index - 1
|
|
107
|
+
|
|
108
|
+
if key == "col":
|
|
109
|
+
return self.col
|
|
110
|
+
|
|
111
|
+
if key == "col_first":
|
|
112
|
+
return self.col == 1
|
|
113
|
+
|
|
114
|
+
if key == "col_last":
|
|
115
|
+
return self.col == self.cols
|
|
116
|
+
|
|
117
|
+
if key == "col0":
|
|
118
|
+
return self.col - 1
|
|
119
|
+
|
|
120
|
+
if key == "row":
|
|
121
|
+
return self.row
|
|
122
|
+
|
|
123
|
+
raise KeyError(key)
|
|
124
|
+
|
|
125
|
+
def __liquid__(self, hint: ContextHint, context: RenderContext) -> object:
|
|
126
|
+
match hint:
|
|
127
|
+
case "output" | "string" | "object":
|
|
128
|
+
return str(self)
|
|
129
|
+
case _:
|
|
130
|
+
return NOTHING
|
|
131
|
+
|
|
132
|
+
def __bool__(self) -> bool:
|
|
133
|
+
return True
|
|
134
|
+
|
|
135
|
+
def step(self) -> None:
|
|
136
|
+
self.index += 1
|
|
137
|
+
|
|
138
|
+
if self.col == self.cols:
|
|
139
|
+
self.col = 1
|
|
140
|
+
self.row += 1
|
|
141
|
+
else:
|
|
142
|
+
self.col += 1
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Never
|
|
4
|
+
|
|
5
|
+
from .._nothing import Nothing
|
|
6
|
+
from ..exceptions import UndefinedVariableError
|
|
7
|
+
from .iterable import IterableDrop
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from collections.abc import Iterable, Iterator
|
|
11
|
+
|
|
12
|
+
from .._context import RenderContext
|
|
13
|
+
from .._drop import ContextHint
|
|
14
|
+
from ..tokens import Token
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Blank:
|
|
18
|
+
def __liquid__(self, hint: ContextHint, context: RenderContext) -> object:
|
|
19
|
+
match hint:
|
|
20
|
+
case "output" | "string":
|
|
21
|
+
return ""
|
|
22
|
+
case "numeric":
|
|
23
|
+
return 0
|
|
24
|
+
case _:
|
|
25
|
+
return self
|
|
26
|
+
|
|
27
|
+
def __eq__(self, other: object) -> bool:
|
|
28
|
+
if isinstance(other, (Blank, Empty)):
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
if other is None or other is False or isinstance(other, Undefined):
|
|
32
|
+
return True
|
|
33
|
+
|
|
34
|
+
if isinstance(other, str):
|
|
35
|
+
return not other or other.isspace()
|
|
36
|
+
|
|
37
|
+
if isinstance(other, (list, tuple, dict)):
|
|
38
|
+
return not other
|
|
39
|
+
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
def __lt__(self, other: object) -> bool:
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
def __str__(self) -> str:
|
|
46
|
+
return ""
|
|
47
|
+
|
|
48
|
+
def __bool__(self) -> bool:
|
|
49
|
+
return True
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
BLANK = Blank()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class Empty:
|
|
56
|
+
def __liquid__(self, hint: ContextHint, context: RenderContext) -> object:
|
|
57
|
+
match hint:
|
|
58
|
+
case "output" | "string":
|
|
59
|
+
return ""
|
|
60
|
+
case "numeric":
|
|
61
|
+
return 0
|
|
62
|
+
case _:
|
|
63
|
+
return self
|
|
64
|
+
|
|
65
|
+
def __eq__(self, other: object) -> bool:
|
|
66
|
+
if isinstance(other, Empty):
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
if other is None or isinstance(other, Blank):
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
if isinstance(other, (list, tuple, dict, str)):
|
|
73
|
+
return not other
|
|
74
|
+
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
def __lt__(self, other: object) -> bool:
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
def __str__(self) -> str:
|
|
81
|
+
return ""
|
|
82
|
+
|
|
83
|
+
def __bool__(self) -> bool:
|
|
84
|
+
return True
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
EMPTY = Empty()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Undefined:
|
|
91
|
+
__slots__ = ("path", "source", "template_name", "token")
|
|
92
|
+
|
|
93
|
+
def __init__(
|
|
94
|
+
self, path: str, token: Token, source: str, template_name: str
|
|
95
|
+
) -> None:
|
|
96
|
+
self.path = path
|
|
97
|
+
self.token = token
|
|
98
|
+
self.source = source
|
|
99
|
+
self.template_name = template_name
|
|
100
|
+
|
|
101
|
+
def poke(self) -> None:
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
def __liquid_getattr__(self, name: str, context: RenderContext) -> object:
|
|
105
|
+
if name in ("first", "last", "size"):
|
|
106
|
+
return self
|
|
107
|
+
raise AttributeError
|
|
108
|
+
|
|
109
|
+
def __liquid_hasattr__(self, name: str, context: RenderContext) -> bool:
|
|
110
|
+
return name in ("first", "last", "size")
|
|
111
|
+
|
|
112
|
+
def __liquid__(self, hint: ContextHint, context: RenderContext) -> object:
|
|
113
|
+
match hint:
|
|
114
|
+
case "output" | "string":
|
|
115
|
+
return ""
|
|
116
|
+
case "index" | "property" | "object":
|
|
117
|
+
return None
|
|
118
|
+
case "numeric":
|
|
119
|
+
return 0
|
|
120
|
+
case "boolean":
|
|
121
|
+
return False
|
|
122
|
+
case "array":
|
|
123
|
+
return []
|
|
124
|
+
|
|
125
|
+
def __str__(self) -> str:
|
|
126
|
+
return ""
|
|
127
|
+
|
|
128
|
+
def __bool__(self) -> bool:
|
|
129
|
+
return False
|
|
130
|
+
|
|
131
|
+
def __len__(self) -> int:
|
|
132
|
+
return 3
|
|
133
|
+
|
|
134
|
+
def __liquid_iter__(
|
|
135
|
+
self, start: int, end: int | None, reversed_: bool
|
|
136
|
+
) -> IterableDrop[object]:
|
|
137
|
+
return IterableDrop[object]([], 0)
|
|
138
|
+
|
|
139
|
+
def __eq__(self, other: object) -> bool:
|
|
140
|
+
return other is None or isinstance(other, (Undefined, Nothing, Blank))
|
|
141
|
+
|
|
142
|
+
def __repr__(self) -> str:
|
|
143
|
+
return f"{type(self).__name__}({self.path})"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class StrictUndefined(Undefined):
|
|
147
|
+
def _error(self) -> Never:
|
|
148
|
+
raise UndefinedVariableError(
|
|
149
|
+
f"{self.path} is undefined",
|
|
150
|
+
token=self.token,
|
|
151
|
+
source=self.source,
|
|
152
|
+
name=self.template_name,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
def __iter__(self) -> Iterator[str]:
|
|
156
|
+
self._error()
|
|
157
|
+
|
|
158
|
+
def __liquid_getattr__(self, name: str, context: RenderContext) -> object:
|
|
159
|
+
self._error()
|
|
160
|
+
|
|
161
|
+
def __liquid_hasattr__(self, name: str, context: RenderContext) -> bool:
|
|
162
|
+
self._error()
|
|
163
|
+
|
|
164
|
+
def __liquid__(self, hint: ContextHint, context: RenderContext) -> object:
|
|
165
|
+
self._error()
|
|
166
|
+
|
|
167
|
+
def __liquid_iter__(
|
|
168
|
+
self, start: int, end: int | None, reversed_: bool
|
|
169
|
+
) -> IterableDrop[object]:
|
|
170
|
+
self._error()
|
|
171
|
+
|
|
172
|
+
def __len__(self) -> int: # noqa: PLE0303
|
|
173
|
+
self._error()
|
|
174
|
+
|
|
175
|
+
def __getitem__(self, key: object) -> object:
|
|
176
|
+
self._error()
|
|
177
|
+
|
|
178
|
+
def __eq__(self, other: object) -> bool:
|
|
179
|
+
self._error()
|
|
180
|
+
|
|
181
|
+
def __lt__(self, other: object) -> bool:
|
|
182
|
+
self._error()
|
|
183
|
+
|
|
184
|
+
def __le__(self, other: object) -> bool:
|
|
185
|
+
self._error()
|
|
186
|
+
|
|
187
|
+
def __gt__(self, other: object) -> bool:
|
|
188
|
+
self._error()
|
|
189
|
+
|
|
190
|
+
def __ge__(self, other: object) -> bool:
|
|
191
|
+
self._error()
|
|
192
|
+
|
|
193
|
+
def __contains__(self, item: object) -> bool:
|
|
194
|
+
self._error()
|
|
195
|
+
|
|
196
|
+
def __str__(self) -> str: # noqa: PLE0307
|
|
197
|
+
self._error()
|
|
198
|
+
|
|
199
|
+
def __bool__(self) -> bool: # noqa: PLE0304
|
|
200
|
+
self._error()
|
|
201
|
+
|
|
202
|
+
def __int__(self) -> int:
|
|
203
|
+
self._error()
|
|
204
|
+
|
|
205
|
+
def __hash__(self) -> int: # noqa: PLE0309
|
|
206
|
+
self._error()
|
|
207
|
+
|
|
208
|
+
def __reversed__(self) -> Iterable[object]:
|
|
209
|
+
self._error()
|
|
210
|
+
|
|
211
|
+
def poke(self) -> None:
|
|
212
|
+
self._error()
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class FalsyStrictUndefined(StrictUndefined):
|
|
216
|
+
def __liquid__(self, hint: ContextHint, context: RenderContext) -> object:
|
|
217
|
+
if hint == "boolean":
|
|
218
|
+
return False
|
|
219
|
+
self._error()
|
|
220
|
+
|
|
221
|
+
def __liquid_hasattr__(self, name: str, context: RenderContext) -> bool:
|
|
222
|
+
return name in ("first", "last", "size")
|
|
223
|
+
|
|
224
|
+
def __eq__(self, other: object) -> bool:
|
|
225
|
+
return other is None or isinstance(other, (Undefined, Nothing, Blank))
|
|
226
|
+
|
|
227
|
+
def __bool__(self) -> bool:
|
|
228
|
+
return False
|