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
@@ -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