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.
Files changed (212) hide show
  1. liquid/__about__.py +1 -0
  2. liquid/__init__.py +161 -187
  3. liquid/_base_tag.py +66 -0
  4. liquid/{utils/chain_map.py → _chain_map.py} +18 -19
  5. liquid/_context.py +465 -0
  6. liquid/_drop.py +108 -0
  7. liquid/_filter.py +174 -0
  8. liquid/_io.py +18 -0
  9. liquid/_lax_parser_mixin.py +100 -0
  10. liquid/_lexer.py +93 -0
  11. liquid/_lexer_extended.py +623 -0
  12. liquid/_lexer_legacy.py +536 -0
  13. liquid/_loader.py +84 -0
  14. liquid/{utils/lru_cache.py → _lru_cache.py} +28 -36
  15. liquid/_markup.py +253 -0
  16. liquid/_messages.py +292 -0
  17. liquid/_missing.py +3 -0
  18. liquid/_nothing.py +28 -0
  19. liquid/_parser.py +460 -0
  20. liquid/_parser_extended.py +293 -0
  21. liquid/_parser_legacy.py +819 -0
  22. liquid/_resource_limits.py +50 -0
  23. liquid/_slice.py +41 -0
  24. liquid/_static_analysis.py +503 -0
  25. liquid/_strftime.py +186 -0
  26. liquid/_template.py +536 -0
  27. liquid/drops/__init__.py +20 -0
  28. liquid/drops/forloop.py +78 -0
  29. liquid/drops/iterable.py +25 -0
  30. liquid/drops/range.py +76 -0
  31. liquid/drops/self_.py +45 -0
  32. liquid/drops/tablerowloop.py +142 -0
  33. liquid/drops/undefined.py +228 -0
  34. liquid/environment.py +717 -551
  35. liquid/exceptions.py +67 -214
  36. liquid/expressions.py +1184 -0
  37. liquid/filters/__init__.py +134 -0
  38. liquid/filters/abs.py +7 -0
  39. liquid/filters/append.py +5 -0
  40. liquid/filters/at_least.py +9 -0
  41. liquid/filters/at_most.py +9 -0
  42. liquid/filters/babel.py +560 -0
  43. liquid/filters/base64.py +26 -0
  44. liquid/filters/capitalize.py +5 -0
  45. liquid/filters/ceil.py +8 -0
  46. liquid/filters/compact.py +25 -0
  47. liquid/filters/concat.py +11 -0
  48. liquid/filters/date.py +27 -0
  49. liquid/filters/default.py +25 -0
  50. liquid/filters/divided_by.py +21 -0
  51. liquid/filters/downcase.py +5 -0
  52. liquid/filters/escape.py +56 -0
  53. liquid/filters/find.py +56 -0
  54. liquid/filters/first.py +19 -0
  55. liquid/filters/floor.py +8 -0
  56. liquid/filters/html.py +23 -0
  57. liquid/filters/index.py +12 -0
  58. liquid/filters/join.py +13 -0
  59. liquid/filters/json_.py +30 -0
  60. liquid/filters/last.py +17 -0
  61. liquid/filters/map.py +5 -0
  62. liquid/filters/minus.py +13 -0
  63. liquid/filters/modulo.py +18 -0
  64. liquid/filters/newline_to_br.py +16 -0
  65. liquid/filters/plus.py +13 -0
  66. liquid/filters/prepend.py +5 -0
  67. liquid/filters/reject.py +19 -0
  68. liquid/filters/remove.py +36 -0
  69. liquid/filters/replace.py +32 -0
  70. liquid/filters/reverse.py +5 -0
  71. liquid/filters/round.py +35 -0
  72. liquid/filters/size.py +25 -0
  73. liquid/filters/slice.py +39 -0
  74. liquid/filters/sort.py +148 -0
  75. liquid/filters/split.py +34 -0
  76. liquid/filters/squish.py +9 -0
  77. liquid/filters/strip.py +13 -0
  78. liquid/filters/strip_html.py +19 -0
  79. liquid/filters/strip_newlines.py +17 -0
  80. liquid/filters/sum.py +21 -0
  81. liquid/filters/times.py +13 -0
  82. liquid/filters/translate.py +380 -0
  83. liquid/filters/truncate.py +39 -0
  84. liquid/filters/uniq.py +11 -0
  85. liquid/filters/upcase.py +5 -0
  86. liquid/filters/url.py +18 -0
  87. liquid/filters/where.py +18 -0
  88. liquid/loaders/__init__.py +17 -0
  89. liquid/loaders/caching_file_system_loader.py +64 -0
  90. liquid/loaders/choice_loader.py +93 -0
  91. liquid/loaders/dict_loader.py +56 -0
  92. liquid/{builtin/loaders → loaders}/file_system_loader.py +51 -55
  93. liquid/{builtin/loaders → loaders}/mixins.py +39 -51
  94. liquid/loaders/package_loader.py +110 -0
  95. liquid/tags/__init__.py +61 -0
  96. liquid/tags/assign.py +68 -0
  97. liquid/tags/capture.py +83 -0
  98. liquid/tags/case.py +199 -0
  99. liquid/tags/comment.py +56 -0
  100. liquid/tags/cycle.py +131 -0
  101. liquid/tags/decrement.py +55 -0
  102. liquid/tags/doc.py +56 -0
  103. liquid/tags/echo.py +65 -0
  104. liquid/tags/else_.py +53 -0
  105. liquid/tags/error.py +51 -0
  106. liquid/tags/extends.py +448 -0
  107. liquid/tags/for_.py +421 -0
  108. liquid/tags/if_.py +156 -0
  109. liquid/tags/ifchanged.py +69 -0
  110. liquid/tags/include.py +223 -0
  111. liquid/tags/increment.py +55 -0
  112. liquid/tags/inline_comment.py +70 -0
  113. liquid/tags/liquid.py +56 -0
  114. liquid/tags/macro.py +281 -0
  115. liquid/tags/output.py +58 -0
  116. liquid/tags/raw.py +60 -0
  117. liquid/tags/render.py +245 -0
  118. liquid/tags/tablerow.py +254 -0
  119. liquid/tags/template_comment.py +56 -0
  120. liquid/tags/translate.py +316 -0
  121. liquid/tags/unless.py +121 -0
  122. liquid/tags/with_.py +83 -0
  123. liquid/tokens.py +370 -0
  124. {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/METADATA +32 -39
  125. python_liquid-3.0.0.dist-info/RECORD +128 -0
  126. {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/WHEEL +1 -1
  127. {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/licenses/LICENSE +1 -1
  128. liquid/analyze_tags.py +0 -214
  129. liquid/ast.py +0 -252
  130. liquid/builtin/__init__.py +0 -203
  131. liquid/builtin/content.py +0 -41
  132. liquid/builtin/drops/__init__.py +0 -3
  133. liquid/builtin/drops/drops.py +0 -13
  134. liquid/builtin/expressions/__init__.py +0 -47
  135. liquid/builtin/expressions/_tokenize.py +0 -186
  136. liquid/builtin/expressions/arguments.py +0 -207
  137. liquid/builtin/expressions/filtered.py +0 -387
  138. liquid/builtin/expressions/logical.py +0 -672
  139. liquid/builtin/expressions/loop.py +0 -275
  140. liquid/builtin/expressions/path.py +0 -163
  141. liquid/builtin/expressions/primitive.py +0 -417
  142. liquid/builtin/filters/__init__.py +0 -0
  143. liquid/builtin/filters/array.py +0 -329
  144. liquid/builtin/filters/extra.py +0 -83
  145. liquid/builtin/filters/math.py +0 -129
  146. liquid/builtin/filters/misc.py +0 -137
  147. liquid/builtin/filters/string.py +0 -416
  148. liquid/builtin/illegal.py +0 -28
  149. liquid/builtin/loaders/__init__.py +0 -0
  150. liquid/builtin/loaders/caching_file_system_loader.py +0 -61
  151. liquid/builtin/loaders/choice_loader.py +0 -94
  152. liquid/builtin/loaders/dict_loader.py +0 -64
  153. liquid/builtin/loaders/package_loader.py +0 -132
  154. liquid/builtin/output.py +0 -74
  155. liquid/builtin/tags/__init__.py +0 -0
  156. liquid/builtin/tags/assign_tag.py +0 -75
  157. liquid/builtin/tags/capture_tag.py +0 -98
  158. liquid/builtin/tags/case_tag.py +0 -287
  159. liquid/builtin/tags/comment_tag.py +0 -77
  160. liquid/builtin/tags/cycle_tag.py +0 -132
  161. liquid/builtin/tags/decrement_tag.py +0 -59
  162. liquid/builtin/tags/doc_tag.py +0 -68
  163. liquid/builtin/tags/echo_tag.py +0 -45
  164. liquid/builtin/tags/for_tag.py +0 -337
  165. liquid/builtin/tags/if_tag.py +0 -209
  166. liquid/builtin/tags/ifchanged_tag.py +0 -94
  167. liquid/builtin/tags/include_tag.py +0 -251
  168. liquid/builtin/tags/increment_tag.py +0 -60
  169. liquid/builtin/tags/inline_comment_tag.py +0 -47
  170. liquid/builtin/tags/liquid_tag.py +0 -183
  171. liquid/builtin/tags/render_tag.py +0 -371
  172. liquid/builtin/tags/tablerow_tag.py +0 -320
  173. liquid/builtin/tags/unless_tag.py +0 -218
  174. liquid/context.py +0 -615
  175. liquid/expression.py +0 -41
  176. liquid/extra/__init__.py +0 -98
  177. liquid/extra/filters/__init__.py +0 -33
  178. liquid/extra/filters/_json.py +0 -33
  179. liquid/extra/filters/array.py +0 -60
  180. liquid/extra/filters/babel.py +0 -552
  181. liquid/extra/filters/html.py +0 -32
  182. liquid/extra/filters/translate.py +0 -448
  183. liquid/extra/tags/__init__.py +0 -17
  184. liquid/extra/tags/_with.py +0 -80
  185. liquid/extra/tags/extends_tag.py +0 -576
  186. liquid/extra/tags/macro_tag.py +0 -270
  187. liquid/extra/tags/snippet_tag.py +0 -107
  188. liquid/extra/tags/translate_tag.py +0 -388
  189. liquid/filter.py +0 -230
  190. liquid/future/__init__.py +0 -3
  191. liquid/future/environment.py +0 -30
  192. liquid/future/filters/__init__.py +0 -1
  193. liquid/future/tags/__init__.py +0 -1
  194. liquid/lex.py +0 -260
  195. liquid/limits.py +0 -66
  196. liquid/loader.py +0 -141
  197. liquid/messages.py +0 -357
  198. liquid/mode.py +0 -12
  199. liquid/output.py +0 -35
  200. liquid/parser.py +0 -119
  201. liquid/span.py +0 -35
  202. liquid/static_analysis.py +0 -443
  203. liquid/stream.py +0 -148
  204. liquid/stringify.py +0 -31
  205. liquid/tag.py +0 -47
  206. liquid/template.py +0 -658
  207. liquid/token.py +0 -145
  208. liquid/undefined.py +0 -218
  209. liquid/utils/__init__.py +0 -15
  210. liquid/utils/html.py +0 -57
  211. liquid/utils/text.py +0 -28
  212. python_liquid-2.3.6.dist-info/RECORD +0 -96
liquid/analyze_tags.py DELETED
@@ -1,214 +0,0 @@
1
- """Analyze template tags from tokenized source text."""
2
-
3
- from __future__ import annotations
4
-
5
- from collections import defaultdict
6
- from typing import TYPE_CHECKING
7
- from typing import DefaultDict
8
- from typing import Iterable
9
- from typing import Mapping
10
- from typing import Optional
11
-
12
- from .span import Span
13
- from .token import TOKEN_TAG
14
-
15
- if TYPE_CHECKING:
16
- from .environment import Environment
17
- from .token import Token
18
-
19
-
20
- DEFAULT_INNER_TAG_MAP = {
21
- "for": ["break", "continue"],
22
- "if": ["else", "elsif"],
23
- "case": ["when"],
24
- "unless": ["else", "elsif"],
25
- }
26
-
27
-
28
- InnerTagMap = Mapping[str, Iterable[str]]
29
- TagMap = dict[str, list[Span]]
30
-
31
-
32
- class TagAnalysis:
33
- """The result of analyzing a template's tags with `Environment.analyze_tags()`.
34
-
35
- Each of the following properties maps tag names to a list of their locations.
36
- Locations are (template_name, start_index) tuples.
37
-
38
- Note that `raw` tags are not included at all. The lexer converts them to text
39
- tokens before we get a chance to analyze them.
40
-
41
- Also be aware that reported `unexpected_tags` don't handle the possibility of an
42
- "inner" tag appearing in a partial template (using `{% include %}`), where
43
- appropriate enclosing block tags are in the parent template.
44
-
45
- Attributes:
46
- all_tags: A mapping of all tags to their locations. Includes "end", "inner"
47
- and unknown tags.
48
- tags: A mapping of tag names to their locations. Excludes "end" and "inner"
49
- tags.
50
- unclosed_tags: Block tags that don't have a matching "end" tag.
51
- unexpected_tags: Inner tags that are not properly enclosed by appropriate
52
- block tags. For example, an `{% else %}` that is not enclosed by a
53
- `{% for %}` or `{% unless %}` block.
54
- unknown_tags: Tags that are unknown to the environment.
55
- """
56
-
57
- def __init__(
58
- self,
59
- *,
60
- env: Environment,
61
- name: str,
62
- tokens: list[Token],
63
- inner_tags: Optional[InnerTagMap] = None,
64
- ) -> None:
65
- self.template_name = name
66
-
67
- # A mapping of all tags to their locations. Includes "end" and inner tags.
68
- self.all_tags = self._all_tags(tokens)
69
-
70
- # Reverse map of inner tags to possible enclosing block tags.
71
- inner_tags = inner_tags or DEFAULT_INNER_TAG_MAP
72
- self._inner_tags = defaultdict(set)
73
- for tag, inner in inner_tags.items():
74
- for inner_tag in inner:
75
- self._inner_tags[inner_tag].add(tag)
76
-
77
- # A mapping of tag names to their locations. Excludes inner tags and "end" tags.
78
- self.tags = {
79
- tag: loc
80
- for tag, loc in self.all_tags.items()
81
- if not tag.startswith("end") and tag not in self._inner_tags
82
- }
83
-
84
- (
85
- self.unclosed_tags,
86
- self.unexpected_tags,
87
- self.unknown_tags,
88
- ) = self._audit_tags(env, tokens)
89
-
90
- def _all_tags(self, tokens: list[Token]) -> TagMap:
91
- """Map tag names to their locations, similar to `Template.analyze` etc."""
92
- tags: DefaultDict[str, list[Span]] = defaultdict(list)
93
- for token in tokens:
94
- if token.kind == TOKEN_TAG:
95
- tags[token.value].append(Span(self.template_name, token.start_index))
96
- return dict(tags)
97
-
98
- def _audit_tags( # noqa: PLR0912
99
- self,
100
- env: Environment,
101
- tokens: list[Token],
102
- ) -> tuple[TagMap, TagMap, TagMap]:
103
- block_stack: list[_BlockStackItem] = []
104
- unclosed_tags: TagMap = defaultdict(list)
105
- unexpected_tags: TagMap = defaultdict(list)
106
- unknown_tags: TagMap = defaultdict(list)
107
-
108
- # Relies on the "end" closing block tag convention.
109
- end_tags = {
110
- token.value
111
- for token in tokens
112
- if token.kind == TOKEN_TAG and token.value.startswith("end")
113
- }
114
-
115
- # Infer which tags are block tags. This may or may not match what the
116
- # environment's tag register believes are block tags.
117
- block_tags = {tag[3:] for tag in end_tags} | {
118
- tag.name for tag in env.tags.values() if tag.block
119
- }
120
-
121
- # Registered tags. "break" and "continue" are a special case.
122
- registered_tags = {
123
- name for name in env.tags if name not in ("break", "continue")
124
- }
125
-
126
- # Registered inline tags. We use this to find erroneous "end" tags.
127
- inline_tags = {tag.name for tag in env.tags.values() if not tag.block}
128
-
129
- # We use this to find unknown "end" tags.
130
- registered_end_blocks = {
131
- tag.end for tag in env.tags.values() if tag.block and tag.end
132
- }
133
-
134
- for token in tokens:
135
- if token.kind != TOKEN_TAG:
136
- continue
137
-
138
- tag_name = token.value
139
-
140
- if tag_name in block_tags:
141
- block_stack.append(_BlockStackItem(token))
142
- elif tag_name in end_tags:
143
- start_block_tag = block_stack.pop()
144
- if start_block_tag != tag_name[3:]:
145
- # if start_block_tag.name not in inline_tags:
146
- unclosed_tags[start_block_tag.name].append(
147
- Span(self.template_name, start_block_tag.token.start_index)
148
- )
149
- continue
150
-
151
- if tag_name not in registered_tags:
152
- # Possible enclosing tags for an inner tag.
153
- enclosing_tags: Iterable[str] = self._inner_tags.get(tag_name, [])
154
- if not enclosing_tags:
155
- # Not an inner tag for any block.
156
- unknown_tags[tag_name].append(
157
- Span(self.template_name, token.start_index)
158
- )
159
- elif not self._valid_inner_tag(
160
- self._inner_tags.get(tag_name, []), block_stack
161
- ):
162
- # An inner tag, but not valid for any blocks currently on the stack.
163
- unexpected_tags[tag_name].append(
164
- Span(self.template_name, token.start_index)
165
- )
166
-
167
- # Catch any unclosed tags.
168
- for block in block_stack:
169
- unclosed_tags[block.name].append(
170
- Span(self.template_name, block.token.start_index)
171
- )
172
-
173
- # Catch bad "end" tags.
174
- for tag_name, locations in self.all_tags.items():
175
- if tag_name.startswith("end"):
176
- start_tag_name = tag_name[3:]
177
- if (
178
- start_tag_name in inline_tags
179
- and start_tag_name not in unknown_tags
180
- or (
181
- tag_name not in registered_end_blocks
182
- and start_tag_name not in unknown_tags
183
- )
184
- ):
185
- unknown_tags[tag_name].extend(locations)
186
-
187
- return dict(unclosed_tags), dict(unexpected_tags), dict(unknown_tags)
188
-
189
- def _valid_inner_tag(
190
- self,
191
- tag_names: Iterable[str],
192
- block_stack: list[_BlockStackItem],
193
- ) -> bool:
194
- return any(tag_name in block_stack for tag_name in tag_names)
195
-
196
-
197
- class _BlockStackItem:
198
- def __init__(self, token: Token) -> None:
199
- self.token = token
200
- self.name = token.value
201
-
202
- def __eq__(self, __o: object) -> bool:
203
- return __o == self.name or (
204
- isinstance(__o, _BlockStackItem) and self.name == __o.name
205
- )
206
-
207
- def __hash__(self) -> int: # pragma: no cover
208
- return hash(self.name)
209
-
210
- def __str__(self) -> str:
211
- return self.name
212
-
213
- def __repr__(self) -> str:
214
- return f"_BlockStackItem({self.name})"
liquid/ast.py DELETED
@@ -1,252 +0,0 @@
1
- """Base class for all template nodes."""
2
-
3
- from __future__ import annotations
4
-
5
- from abc import ABC
6
- from abc import abstractmethod
7
- from enum import Enum
8
- from enum import auto
9
- from typing import TYPE_CHECKING
10
- from typing import Collection
11
- from typing import Iterable
12
- from typing import Optional
13
- from typing import TextIO
14
- from typing import Union
15
-
16
- from .exceptions import DisabledTagError
17
- from .output import NullIO
18
- from .token import TOKEN_TAG
19
- from .token import Token
20
-
21
- if TYPE_CHECKING:
22
- from .builtin.expressions import Identifier
23
- from .context import RenderContext
24
- from .expression import Expression
25
-
26
-
27
- class Node(ABC):
28
- """Base class for all nodes in a parse tree."""
29
-
30
- __slots__ = ("token", "blank")
31
-
32
- def __init__(self, token: Token) -> None:
33
- self.token = token
34
-
35
- self.blank = True
36
- """If True, indicates that the node, when rendered, produces no output text
37
- or only whitespace.
38
-
39
- The output node (`{{ something }}`) and echo tag are exception. Even if they
40
- evaluate to an empty or blank string, they are not considered "blank".
41
- """
42
-
43
- def raise_for_disabled(self, disabled_tags: Collection[str]) -> None:
44
- """Raise a DisabledTagError if this node's type is in the given list."""
45
- if self.token.kind == TOKEN_TAG and self.token.value in disabled_tags:
46
- raise DisabledTagError(
47
- f"{self.token.value} usage is not allowed in this context",
48
- token=self.token,
49
- )
50
-
51
- def render(self, context: RenderContext, buffer: TextIO) -> int:
52
- """Check disabled tags before delegating to `render_to_output`."""
53
- if context.disabled_tags:
54
- self.raise_for_disabled(context.disabled_tags)
55
- return self.render_to_output(context, buffer)
56
-
57
- async def render_async(self, context: RenderContext, buffer: TextIO) -> int:
58
- """An async version of `liquid.ast.Node.render`."""
59
- if context.disabled_tags:
60
- self.raise_for_disabled(context.disabled_tags)
61
- return await self.render_to_output_async(context, buffer)
62
-
63
- @abstractmethod
64
- def render_to_output(
65
- self,
66
- context: RenderContext,
67
- buffer: TextIO,
68
- ) -> int:
69
- """Render this node to the output buffer."""
70
-
71
- async def render_to_output_async(
72
- self,
73
- context: RenderContext,
74
- buffer: TextIO,
75
- ) -> int:
76
- """An async version of `liquid.ast.Node.render_to_output`."""
77
- return self.render_to_output(context, buffer)
78
-
79
- def children(
80
- self,
81
- static_context: RenderContext, # noqa: ARG002
82
- *,
83
- include_partials: bool = True, # noqa: ARG002
84
- ) -> Iterable[Node]:
85
- """Return this node's children."""
86
- return []
87
-
88
- async def children_async(
89
- self,
90
- static_context: RenderContext,
91
- *,
92
- include_partials: bool = True,
93
- ) -> Iterable[Node]:
94
- """An async version of `children()`."""
95
- return self.children(static_context, include_partials=include_partials)
96
-
97
- def expressions(self) -> Iterable[Expression]:
98
- """Return this node's expressions."""
99
- return []
100
-
101
- def template_scope(self) -> Iterable[Identifier]:
102
- """Return variables this node adds to the template local scope."""
103
- return []
104
-
105
- def block_scope(self) -> Iterable[Identifier]:
106
- """Return variables this node adds to the node's block scope."""
107
- return []
108
-
109
- def partial_scope(self) -> Optional[Partial]:
110
- """Return information about a partial template loaded by this node."""
111
- return None
112
-
113
-
114
- class PartialScope(Enum):
115
- """The kind of scope a partial template should have when loaded."""
116
-
117
- SHARED = auto()
118
- ISOLATED = auto()
119
- INHERITED = auto()
120
-
121
-
122
- class Partial:
123
- """Partial template meta data.
124
-
125
- Args:
126
- name: The name of the partial or an expression resolving to the name
127
- associated with the partial template.
128
- scope: The kind of scope the partial template should have when loaded.
129
- in_scope: Names that will be added to the partial template scope.
130
- key: A hash of the partial template name and any arguments the partial
131
- template will be rendered with that might affect its scope. If a
132
- key is provided, static analysis helpers will visit a partial
133
- template once for each distinct key.
134
- """
135
-
136
- __slots__ = ("name", "scope", "in_scope", "key")
137
-
138
- def __init__(
139
- self,
140
- name: Union[Expression, str],
141
- scope: PartialScope,
142
- in_scope: Iterable[Identifier],
143
- *,
144
- key: Optional[int] = None,
145
- ) -> None:
146
- self.name = name
147
- self.scope = scope
148
- self.in_scope = in_scope
149
- self.key = key
150
-
151
-
152
- class IllegalNode(Node):
153
- """Parse tree node representing an illegal or unregistered tag.
154
-
155
- Illegal nodes are necessary when running in "warn" or "lax" mode. In
156
- strict mode, an exception should be raised as soon as an illegal token
157
- is found.
158
- """
159
-
160
- __slots__ = ()
161
-
162
- def __str__(self) -> str:
163
- return ""
164
-
165
- def render_to_output(self, _context: RenderContext, _buffer: TextIO) -> int:
166
- """Render the node to the output buffer."""
167
- return 0
168
-
169
-
170
- class BlockNode(Node):
171
- """A parse tree node representing a sequence of statements."""
172
-
173
- __slots__ = ("nodes", "blank")
174
-
175
- def __init__(self, token: Token, nodes: list[Node]):
176
- super().__init__(token)
177
- self.nodes = nodes
178
- self.blank = all(node.blank for node in nodes)
179
-
180
- def __str__(self) -> str:
181
- return "".join(str(s) for s in self.nodes)
182
-
183
- def render_to_output(self, context: RenderContext, buffer: TextIO) -> int:
184
- """Render the node to the output buffer."""
185
- if context.env.suppress_blank_control_flow_blocks and self.blank:
186
- buf = NullIO()
187
- for node in self.nodes:
188
- node.render(context, buf)
189
- return 0
190
- return sum(node.render(context, buffer) for node in self.nodes)
191
-
192
- async def render_to_output_async(
193
- self, context: RenderContext, buffer: TextIO
194
- ) -> int:
195
- """Render the node to the output buffer."""
196
- if context.env.suppress_blank_control_flow_blocks and self.blank:
197
- buf = NullIO()
198
- for node in self.nodes:
199
- await node.render_async(context, buf)
200
- return 0
201
- return sum([await node.render_async(context, buffer) for node in self.nodes])
202
-
203
- def children(
204
- self,
205
- static_context: RenderContext, # noqa: ARG002
206
- *,
207
- include_partials: bool = True, # noqa: ARG002
208
- ) -> Iterable[Node]:
209
- """Return this node's children."""
210
- return self.nodes
211
-
212
-
213
- class ConditionalBlockNode(Node):
214
- """A node containing a sequence of statements and a conditional expression."""
215
-
216
- __slots__ = ("expression", "block")
217
-
218
- def __init__(self, token: Token, expression: Expression, block: BlockNode):
219
- super().__init__(token)
220
- self.expression = expression
221
- self.block = block
222
- self.blank = block.blank
223
-
224
- def __str__(self) -> str:
225
- return f"{{% elsif {self.expression} %}}{self.block}"
226
-
227
- def render_to_output(self, context: RenderContext, buffer: TextIO) -> int:
228
- """Render the node to the output buffer."""
229
- if self.expression.evaluate(context):
230
- return self.block.render(context, buffer)
231
- return 0
232
-
233
- async def render_to_output_async(
234
- self, context: RenderContext, buffer: TextIO
235
- ) -> int:
236
- """Render the node to the output buffer."""
237
- if await self.expression.evaluate_async(context):
238
- return await self.block.render_async(context, buffer)
239
- return 0
240
-
241
- def children(
242
- self,
243
- static_context: RenderContext, # noqa: ARG002
244
- *,
245
- include_partials: bool = True, # noqa: ARG002
246
- ) -> Iterable[Node]:
247
- """Return this node's children."""
248
- yield self.block
249
-
250
- def expressions(self) -> Iterable[Expression]:
251
- """Return this node's expressions."""
252
- yield self.expression
@@ -1,203 +0,0 @@
1
- from __future__ import annotations # noqa: D104
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- from . import content
6
- from . import illegal
7
- from . import output
8
- from .filters.array import compact
9
- from .filters.array import concat
10
- from .filters.array import find
11
- from .filters.array import find_index
12
- from .filters.array import first
13
- from .filters.array import has
14
- from .filters.array import join
15
- from .filters.array import last
16
- from .filters.array import map_
17
- from .filters.array import reject
18
- from .filters.array import reverse
19
- from .filters.array import sort
20
- from .filters.array import sort_natural
21
- from .filters.array import sum_
22
- from .filters.array import uniq
23
- from .filters.array import where
24
- from .filters.extra import escapejs
25
- from .filters.extra import safe
26
- from .filters.math import abs_
27
- from .filters.math import at_least
28
- from .filters.math import at_most
29
- from .filters.math import ceil
30
- from .filters.math import divided_by
31
- from .filters.math import floor
32
- from .filters.math import minus
33
- from .filters.math import modulo
34
- from .filters.math import plus
35
- from .filters.math import round_
36
- from .filters.math import times
37
- from .filters.misc import date
38
- from .filters.misc import default
39
- from .filters.misc import size
40
- from .filters.string import append
41
- from .filters.string import base64_decode
42
- from .filters.string import base64_encode
43
- from .filters.string import base64_url_safe_decode
44
- from .filters.string import base64_url_safe_encode
45
- from .filters.string import capitalize
46
- from .filters.string import downcase
47
- from .filters.string import escape
48
- from .filters.string import escape_once
49
- from .filters.string import lstrip
50
- from .filters.string import newline_to_br
51
- from .filters.string import prepend
52
- from .filters.string import remove
53
- from .filters.string import remove_first
54
- from .filters.string import remove_last
55
- from .filters.string import replace
56
- from .filters.string import replace_first
57
- from .filters.string import replace_last
58
- from .filters.string import rstrip
59
- from .filters.string import slice_
60
- from .filters.string import split
61
- from .filters.string import squish
62
- from .filters.string import strip
63
- from .filters.string import strip_html
64
- from .filters.string import strip_newlines
65
- from .filters.string import truncate
66
- from .filters.string import truncatewords
67
- from .filters.string import upcase
68
- from .filters.string import url_decode
69
- from .filters.string import url_encode
70
- from .loaders.caching_file_system_loader import CachingFileSystemLoader
71
- from .loaders.choice_loader import CachingChoiceLoader
72
- from .loaders.choice_loader import ChoiceLoader
73
- from .loaders.dict_loader import CachingDictLoader
74
- from .loaders.dict_loader import DictLoader
75
- from .loaders.file_system_loader import FileSystemLoader
76
- from .loaders.mixins import CachingLoaderMixin
77
- from .loaders.package_loader import PackageLoader
78
- from .tags import assign_tag
79
- from .tags import capture_tag
80
- from .tags import case_tag
81
- from .tags import comment_tag
82
- from .tags import cycle_tag
83
- from .tags import decrement_tag
84
- from .tags import doc_tag
85
- from .tags import echo_tag
86
- from .tags import for_tag
87
- from .tags import if_tag
88
- from .tags import ifchanged_tag
89
- from .tags import include_tag
90
- from .tags import increment_tag
91
- from .tags import inline_comment_tag
92
- from .tags import liquid_tag
93
- from .tags import render_tag
94
- from .tags import tablerow_tag
95
- from .tags import unless_tag
96
-
97
- if TYPE_CHECKING:
98
- from liquid import Environment
99
-
100
- __all__ = (
101
- "CachingFileSystemLoader",
102
- "CachingChoiceLoader",
103
- "ChoiceLoader",
104
- "CachingDictLoader",
105
- "DictLoader",
106
- "FileSystemLoader",
107
- "CachingLoaderMixin",
108
- "PackageLoader",
109
- )
110
-
111
-
112
- def register(env: Environment) -> None: # noqa: PLR0915
113
- """Register all built-in tags and filters with an environment."""
114
- env.add_tag(content.Literal)
115
- env.add_tag(output.Output)
116
- env.add_tag(illegal.Illegal)
117
- env.add_tag(if_tag.IfTag)
118
- env.add_tag(comment_tag.CommentTag)
119
- env.add_tag(unless_tag.UnlessTag)
120
- env.add_tag(case_tag.CaseTag)
121
- env.add_tag(for_tag.ForTag)
122
- env.add_tag(for_tag.BreakTag)
123
- env.add_tag(for_tag.ContinueTag)
124
- env.add_tag(tablerow_tag.TablerowTag)
125
- env.add_tag(capture_tag.CaptureTag)
126
- env.add_tag(cycle_tag.CycleTag)
127
- env.add_tag(assign_tag.AssignTag)
128
- env.add_tag(increment_tag.IncrementTag)
129
- env.add_tag(decrement_tag.DecrementTag)
130
- env.add_tag(echo_tag.EchoTag)
131
- env.add_tag(liquid_tag.LiquidTag)
132
- env.add_tag(include_tag.IncludeTag)
133
- env.add_tag(render_tag.RenderTag)
134
- env.add_tag(ifchanged_tag.IfChangedTag)
135
- env.add_tag(inline_comment_tag.InlineCommentTag)
136
- env.add_tag(doc_tag.DocTag)
137
-
138
- env.add_filter("abs", abs_)
139
- env.add_filter("at_most", at_most)
140
- env.add_filter("at_least", at_least)
141
- env.add_filter("ceil", ceil)
142
- env.add_filter("divided_by", divided_by)
143
- env.add_filter("floor", floor)
144
- env.add_filter("minus", minus)
145
- env.add_filter("plus", plus)
146
- env.add_filter("round", round_)
147
- env.add_filter("times", times)
148
- env.add_filter("modulo", modulo)
149
-
150
- env.add_filter("capitalize", capitalize)
151
- env.add_filter("append", append)
152
- env.add_filter("downcase", downcase)
153
- env.add_filter("escape", escape)
154
- env.add_filter("escape_once", escape_once)
155
- env.add_filter("lstrip", lstrip)
156
- env.add_filter("newline_to_br", newline_to_br)
157
- env.add_filter("prepend", prepend)
158
- env.add_filter("remove", remove)
159
- env.add_filter("remove_first", remove_first)
160
- env.add_filter("remove_last", remove_last)
161
- env.add_filter("replace", replace)
162
- env.add_filter("replace_first", replace_first)
163
- env.add_filter("replace_last", replace_last)
164
- env.add_filter("slice", slice_)
165
- env.add_filter("split", split)
166
- env.add_filter("upcase", upcase)
167
- env.add_filter("strip", strip)
168
- env.add_filter("rstrip", rstrip)
169
- env.add_filter("strip_html", strip_html)
170
- env.add_filter("strip_newlines", strip_newlines)
171
- env.add_filter("truncate", truncate)
172
- env.add_filter("truncatewords", truncatewords)
173
- env.add_filter("url_encode", url_encode)
174
- env.add_filter("url_decode", url_decode)
175
- env.add_filter("base64_encode", base64_encode)
176
- env.add_filter("base64_decode", base64_decode)
177
- env.add_filter("base64_url_safe_encode", base64_url_safe_encode)
178
- env.add_filter("base64_url_safe_decode", base64_url_safe_decode)
179
- env.add_filter("squish", squish)
180
-
181
- env.add_filter("find", find)
182
- env.add_filter("find_index", find_index)
183
- env.add_filter("join", join)
184
- env.add_filter("first", first)
185
- env.add_filter("has", has)
186
- env.add_filter("last", last)
187
- env.add_filter("concat", concat)
188
- env.add_filter("map", map_)
189
- env.add_filter("reject", reject)
190
- env.add_filter("reverse", reverse)
191
- env.add_filter("sort", sort)
192
- env.add_filter("sort_natural", sort_natural)
193
- env.add_filter("sum", sum_)
194
- env.add_filter("where", where)
195
- env.add_filter("uniq", uniq)
196
- env.add_filter("compact", compact)
197
-
198
- env.add_filter("size", size)
199
- env.add_filter("default", default)
200
- env.add_filter("date", date)
201
-
202
- env.add_filter("safe", safe)
203
- env.add_filter("escapejs", escapejs)