python-liquid 2.2.1__tar.gz → 2.3.0__tar.gz

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 (97) hide show
  1. {python_liquid-2.2.1 → python_liquid-2.3.0}/PKG-INFO +1 -1
  2. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/__init__.py +1 -1
  3. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/expressions/loop.py +12 -18
  4. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/expressions/primitive.py +14 -1
  5. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/loaders/file_system_loader.py +15 -1
  6. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/cycle_tag.py +5 -0
  7. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/liquid_tag.py +2 -1
  8. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/context.py +7 -2
  9. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/environment.py +6 -1
  10. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/exceptions.py +4 -0
  11. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/tags/_with.py +10 -13
  12. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/parser.py +6 -0
  13. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/stream.py +2 -4
  14. {python_liquid-2.2.1 → python_liquid-2.3.0}/pyproject.toml +2 -0
  15. {python_liquid-2.2.1 → python_liquid-2.3.0}/.gitignore +0 -0
  16. {python_liquid-2.2.1 → python_liquid-2.3.0}/LICENSE +0 -0
  17. {python_liquid-2.2.1 → python_liquid-2.3.0}/README.md +0 -0
  18. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/analyze_tags.py +0 -0
  19. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/ast.py +0 -0
  20. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/__init__.py +0 -0
  21. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/content.py +0 -0
  22. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/drops/__init__.py +0 -0
  23. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/drops/drops.py +0 -0
  24. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/expressions/__init__.py +0 -0
  25. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/expressions/_tokenize.py +0 -0
  26. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/expressions/arguments.py +0 -0
  27. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/expressions/filtered.py +0 -0
  28. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/expressions/logical.py +0 -0
  29. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/expressions/path.py +0 -0
  30. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/filters/__init__.py +0 -0
  31. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/filters/array.py +0 -0
  32. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/filters/extra.py +0 -0
  33. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/filters/math.py +0 -0
  34. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/filters/misc.py +0 -0
  35. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/filters/string.py +0 -0
  36. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/illegal.py +0 -0
  37. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/loaders/__init__.py +0 -0
  38. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/loaders/caching_file_system_loader.py +0 -0
  39. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/loaders/choice_loader.py +0 -0
  40. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/loaders/dict_loader.py +0 -0
  41. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/loaders/mixins.py +0 -0
  42. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/loaders/package_loader.py +0 -0
  43. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/output.py +0 -0
  44. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/__init__.py +0 -0
  45. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/assign_tag.py +0 -0
  46. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/capture_tag.py +0 -0
  47. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/case_tag.py +0 -0
  48. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/comment_tag.py +0 -0
  49. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/decrement_tag.py +0 -0
  50. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/doc_tag.py +0 -0
  51. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/echo_tag.py +0 -0
  52. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/for_tag.py +0 -0
  53. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/if_tag.py +0 -0
  54. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/ifchanged_tag.py +0 -0
  55. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/include_tag.py +0 -0
  56. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/increment_tag.py +0 -0
  57. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/inline_comment_tag.py +0 -0
  58. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/render_tag.py +0 -0
  59. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/tablerow_tag.py +0 -0
  60. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/builtin/tags/unless_tag.py +0 -0
  61. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/expression.py +0 -0
  62. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/__init__.py +0 -0
  63. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/filters/__init__.py +0 -0
  64. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/filters/_json.py +0 -0
  65. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/filters/array.py +0 -0
  66. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/filters/babel.py +0 -0
  67. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/filters/html.py +0 -0
  68. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/filters/translate.py +0 -0
  69. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/tags/__init__.py +0 -0
  70. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/tags/extends_tag.py +0 -0
  71. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/tags/macro_tag.py +0 -0
  72. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/tags/snippet_tag.py +0 -0
  73. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/extra/tags/translate_tag.py +0 -0
  74. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/filter.py +0 -0
  75. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/future/__init__.py +0 -0
  76. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/future/environment.py +0 -0
  77. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/future/filters/__init__.py +0 -0
  78. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/future/tags/__init__.py +0 -0
  79. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/lex.py +0 -0
  80. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/limits.py +0 -0
  81. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/loader.py +0 -0
  82. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/messages.py +0 -0
  83. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/mode.py +0 -0
  84. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/output.py +0 -0
  85. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/py.typed +0 -0
  86. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/span.py +0 -0
  87. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/static_analysis.py +0 -0
  88. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/stringify.py +0 -0
  89. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/tag.py +0 -0
  90. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/template.py +0 -0
  91. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/token.py +0 -0
  92. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/undefined.py +0 -0
  93. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/utils/__init__.py +0 -0
  94. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/utils/chain_map.py +0 -0
  95. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/utils/html.py +0 -0
  96. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/utils/lru_cache.py +0 -0
  97. {python_liquid-2.2.1 → python_liquid-2.3.0}/liquid/utils/text.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-liquid
3
- Version: 2.2.1
3
+ Version: 2.3.0
4
4
  Summary: A Python engine for the Liquid template language.
5
5
  Project-URL: Change Log, https://github.com/jg-rp/liquid/blob/main/CHANGES.md
6
6
  Project-URL: Documentation, https://jg-rp.github.io/liquid/
@@ -56,7 +56,7 @@ from .tag import Tag
56
56
 
57
57
  from . import future
58
58
 
59
- __version__ = "2.2.1"
59
+ __version__ = "2.3.0"
60
60
 
61
61
  __all__ = (
62
62
  "AwareBoundTemplate",
@@ -123,29 +123,23 @@ class LoopExpression(Expression):
123
123
  ) -> tuple[Iterator[object], int]:
124
124
  offset_key = f"{self.identifier}-{self.iterable}"
125
125
 
126
- if limit is None and offset is None:
127
- context.stopindex(key=offset_key, index=length)
128
- if self.reversed:
129
- return reversed(list(it)), length
130
- return it, length
131
-
132
126
  if offset == "continue":
133
- offset = context.stopindex(key=offset_key)
134
- length = max(length - offset, 0)
135
- elif offset is not None:
136
- assert isinstance(offset, int), f"found {offset!r}"
137
- length = max(length - offset, 0)
127
+ start = context.stopindex(offset_key)
128
+ else:
129
+ start = int(offset or 0)
130
+
131
+ stop = None if limit is None else limit + start
138
132
 
139
- if limit is not None:
140
- length = min(length, limit)
133
+ start_ = min(max(start, 0), length)
134
+ stop_ = min(stop or length, length)
135
+ length_ = max(stop_ - start_, 0)
141
136
 
142
- stop = offset + length if offset else length
143
- context.stopindex(key=offset_key, index=stop)
144
- it = islice(it, offset, stop)
137
+ context.stopindex(key=offset_key, index=stop_)
138
+ it = islice(it, start_, stop_)
145
139
 
146
140
  if self.reversed:
147
- return reversed(list(it)), length
148
- return it, length
141
+ return reversed(list(it)), length_
142
+ return it, length_
149
143
 
150
144
  def evaluate(self, context: RenderContext) -> tuple[Iterator[object], int]:
151
145
  it, length = self._to_iter(self.iterable.evaluate(context), context)
@@ -39,6 +39,12 @@ if TYPE_CHECKING:
39
39
  from liquid import TokenStream
40
40
 
41
41
 
42
+ # MAX_RANGE = (2**53) - 1
43
+ # MIN_RANGE = -(2**53) + 1
44
+ MAX_RANGE = 1024
45
+ MIN_RANGE = -1024
46
+
47
+
42
48
  class Nil(Expression):
43
49
  __slots__ = ()
44
50
 
@@ -249,7 +255,9 @@ class RangeLiteral(Expression):
249
255
  if start > stop:
250
256
  return range(0)
251
257
 
252
- return range(start, stop + 1)
258
+ return range(
259
+ clamp(start, MIN_RANGE, MAX_RANGE), clamp(stop + 1, MIN_RANGE, MAX_RANGE)
260
+ )
253
261
 
254
262
  def evaluate(self, context: RenderContext) -> range:
255
263
  return self._make_range(
@@ -415,3 +423,8 @@ def parse_string_or_path(
415
423
  def is_empty(obj: object) -> bool:
416
424
  """Return True if _obj_ is considered empty."""
417
425
  return isinstance(obj, (list, dict, str)) and not obj
426
+
427
+
428
+ def clamp(n: int, min_value: int, max_value: int) -> int:
429
+ """Clamp _n_ between _min_value_ and _max_value_."""
430
+ return max(min_value, min(n, max_value))
@@ -29,6 +29,9 @@ class FileSystemLoader(BaseLoader):
29
29
  ext: A default file extension. Should include a leading period.
30
30
  reject_symlinks: When `True`, reject paths to symlinks that resolve to files
31
31
  outside the search path. Defaults to `False`.
32
+
33
+ Raise:
34
+ ValueError if `ext` is not a valid suffix.
32
35
  """
33
36
 
34
37
  def __init__(
@@ -48,6 +51,10 @@ class FileSystemLoader(BaseLoader):
48
51
  self.ext = ext
49
52
  self.reject_symlinks = reject_symlinks
50
53
 
54
+ # Raise a ValueError early if `ext` is invalid.
55
+ if ext:
56
+ Path("x").with_suffix(ext)
57
+
51
58
  def resolve_path(self, template_name: str) -> Path:
52
59
  """Return a path to the template identified by _template_name_.
53
60
 
@@ -57,6 +64,9 @@ class FileSystemLoader(BaseLoader):
57
64
  """
58
65
  template_path = Path(template_name)
59
66
 
67
+ if not template_path.name:
68
+ raise TemplateNotFoundError(template_name)
69
+
60
70
  if self.ext and not template_path.suffix:
61
71
  template_path = template_path.with_suffix(self.ext)
62
72
 
@@ -66,7 +76,11 @@ class FileSystemLoader(BaseLoader):
66
76
  for base in self.search_path:
67
77
  source_path = base.joinpath(template_path)
68
78
 
69
- if not source_path.exists() or not source_path.is_file():
79
+ try:
80
+ if not source_path.exists() or not source_path.is_file():
81
+ continue
82
+ except OSError:
83
+ # "File name too long", for example
70
84
  continue
71
85
 
72
86
  if self.reject_symlinks:
@@ -11,6 +11,7 @@ from typing import TextIO
11
11
  from liquid.ast import Node
12
12
  from liquid.builtin.expressions import PositionalArgument
13
13
  from liquid.builtin.expressions import parse_primitive
14
+ from liquid.exceptions import LiquidSyntaxError
14
15
  from liquid.stringify import to_liquid_string
15
16
  from liquid.tag import Tag
16
17
  from liquid.token import TOKEN_COLON
@@ -124,4 +125,8 @@ class CycleTag(Tag):
124
125
  tokens.eat(TOKEN_COLON)
125
126
 
126
127
  args = PositionalArgument.parse(self.env, tokens)
128
+
129
+ if not args:
130
+ raise LiquidSyntaxError("expected at least one argument", token=token)
131
+
127
132
  return self.node_class(token, group_name, [arg.value for arg in args])
@@ -127,7 +127,8 @@ class LiquidTag(Tag):
127
127
  self._tokenize(
128
128
  token_.value,
129
129
  token=token_,
130
- )
130
+ ),
131
+ block_depth_carry=stream.block_depth,
131
132
  ),
132
133
  end=(),
133
134
  )
@@ -175,7 +175,12 @@ class RenderContext:
175
175
  """
176
176
  it = iter(path)
177
177
  root = next(it)
178
- assert isinstance(root, str)
178
+
179
+ if not isinstance(root, str):
180
+ if default == UNDEFINED:
181
+ hint = f"{root} is undefined"
182
+ return self.env.undefined(str(root), hint=hint, token=token)
183
+ return default
179
184
 
180
185
  try:
181
186
  obj = self.scope[root]
@@ -316,7 +321,7 @@ class RenderContext:
316
321
  """Return the index of the next item in the cycle."""
317
322
  namespace: dict[object, int] = self.tag_namespace["cycles"]
318
323
  idx = namespace.setdefault(key, 0)
319
- namespace[key] = (idx + 1) % length
324
+ namespace[key] = (idx + 1) % (length or 1) # Just in case.
320
325
  return idx
321
326
 
322
327
  def ifchanged(self, val: str) -> bool:
@@ -18,6 +18,7 @@ from . import builtin
18
18
  from .analyze_tags import InnerTagMap
19
19
  from .analyze_tags import TagAnalysis
20
20
  from .builtin import DictLoader
21
+ from .exceptions import BlockNestingError
21
22
  from .exceptions import LiquidError
22
23
  from .exceptions import LiquidSyntaxError
23
24
  from .exceptions import TemplateInheritanceError
@@ -79,6 +80,10 @@ class Environment:
79
80
  template loaded from this environment.
80
81
  """
81
82
 
83
+ block_nesting_limit: ClassVar[int] = 30
84
+ """The maximum markup block nesting depth allowed before a `BlockNestingError`
85
+ exception is raised."""
86
+
82
87
  context_depth_limit: ClassVar[int] = 30
83
88
  """The maximum number of times a render context can be extended or wrapped before
84
89
  raising a `ContextDepthError`."""
@@ -275,7 +280,7 @@ class Environment:
275
280
  """
276
281
  try:
277
282
  nodes = self._parse(source)
278
- except (LiquidSyntaxError, TemplateInheritanceError) as err:
283
+ except (LiquidSyntaxError, TemplateInheritanceError, BlockNestingError) as err:
279
284
  err.template_name = path
280
285
  raise err
281
286
  except Exception as err: # noqa: BLE001
@@ -191,6 +191,10 @@ class ResourceLimitError(LiquidError):
191
191
  """Base class for exceptions relating to resource limits."""
192
192
 
193
193
 
194
+ class BlockNestingError(ResourceLimitError):
195
+ """The exception raised when block nesting limit is reached."""
196
+
197
+
194
198
  class ContextDepthError(ResourceLimitError):
195
199
  """Exception raised when the maximum context depth is reached.
196
200
 
@@ -35,16 +35,20 @@ class WithNode(Node):
35
35
  self.block = block
36
36
  self.blank = self.block.blank
37
37
 
38
- def render_to_output(self, context: RenderContext, buffer: TextIO) -> int:
39
- namespace = dict(arg.evaluate(context) for arg in self.args)
40
-
41
- with context.extend(namespace):
38
+ def render_to_output(
39
+ self,
40
+ context: RenderContext,
41
+ buffer: TextIO,
42
+ ) -> int:
43
+ with context.extend({a.name: a.value.evaluate(context) for a in self.args}):
42
44
  return self.block.render(context, buffer)
43
45
 
44
46
  async def render_to_output_async(
45
- self, context: RenderContext, buffer: TextIO
47
+ self,
48
+ context: RenderContext,
49
+ buffer: TextIO,
46
50
  ) -> int:
47
- namespace = dict([await arg.evaluate_async(context) for arg in self.args])
51
+ namespace = {a.name: await a.value.evaluate_async(context) for a in self.args}
48
52
  with context.extend(namespace):
49
53
  return await self.block.render_async(context, buffer)
50
54
 
@@ -54,21 +58,16 @@ class WithNode(Node):
54
58
  *,
55
59
  include_partials: bool = True, # noqa: ARG002
56
60
  ) -> Iterable[Node]:
57
- """Return this node's children."""
58
61
  yield self.block
59
62
 
60
63
  def expressions(self) -> Iterable[Expression]:
61
- """Return this node's expressions."""
62
64
  yield from (arg.value for arg in self.args)
63
65
 
64
66
  def block_scope(self) -> Iterable[Identifier]:
65
- """Return variables this node adds to the node's block scope."""
66
67
  yield from (Identifier(p.name, token=p.token) for p in self.args)
67
68
 
68
69
 
69
70
  class WithTag(Tag):
70
- """The extra _with_ tag."""
71
-
72
71
  name = TAG_WITH
73
72
  end = TAG_ENDWITH
74
73
  node_class = WithNode
@@ -76,8 +75,6 @@ class WithTag(Tag):
76
75
  def parse(self, stream: TokenStream) -> Node:
77
76
  token = stream.eat(TOKEN_TAG)
78
77
  args = KeywordArgument.parse(self.env, stream.into_inner(tag=token))
79
-
80
- # Parse the block
81
78
  block = get_parser(self.env).parse_block(stream, (TAG_ENDWITH, TOKEN_EOF))
82
79
  stream.expect(TOKEN_TAG, value=TAG_ENDWITH)
83
80
  return self.node_class(token, args=args, block=block)
@@ -9,6 +9,7 @@ from typing import Iterator
9
9
 
10
10
  from .ast import BlockNode
11
11
  from .ast import Node
12
+ from .exceptions import BlockNestingError
12
13
  from .exceptions import LiquidError
13
14
  from .token import TOKEN_COMMENT
14
15
  from .token import TOKEN_CONTENT
@@ -69,6 +70,10 @@ class Parser:
69
70
  output = tags[TOKEN_OUTPUT]
70
71
 
71
72
  nodes: list[Node] = []
73
+ stream.block_depth += 1
74
+
75
+ if stream.block_depth > self.env.block_nesting_limit:
76
+ raise BlockNestingError("block nesting limit reached", token=None)
72
77
 
73
78
  while stream.current.kind != TOKEN_EOF:
74
79
  if stream.current.kind == TOKEN_TAG and stream.current.value in end:
@@ -92,6 +97,7 @@ class Parser:
92
97
 
93
98
  next(stream)
94
99
 
100
+ stream.block_depth -= 1
95
101
  return BlockNode(stream.current, nodes)
96
102
 
97
103
 
@@ -18,12 +18,10 @@ class TokenStream:
18
18
 
19
19
  eof = Token(TOKEN_EOF, TOKEN_EOF, -1, "")
20
20
 
21
- def __init__(
22
- self,
23
- tokens: Iterator[Token],
24
- ):
21
+ def __init__(self, tokens: Iterator[Token], block_depth_carry: int = 0):
25
22
  self.tokens = list(tokens)
26
23
  self.pos = 0
24
+ self.block_depth = block_depth_carry
27
25
 
28
26
  def __next__(self) -> Token:
29
27
  return self.next_token()
@@ -46,6 +46,7 @@ packages = ["liquid"]
46
46
 
47
47
  [tool.hatch.envs.default]
48
48
  dependencies = [
49
+ "hypothesis",
49
50
  "pytest",
50
51
  "pytest-cov",
51
52
  "pytest-mock",
@@ -159,6 +160,7 @@ convention = "google"
159
160
  "liquid/builtin/loaders/__init__.py" = ["D104", "I001"]
160
161
  "liquid/builtin/tags/__init__.py" = ["D104", "I001"]
161
162
  "tests/*" = ["D100", "D101", "D104", "D103", "D102", "D209", "D205", "SIM117"]
163
+ "tests/test_compliance.py" = ["E501"]
162
164
  "performance/*" = ["D103", "PLR2004", "T201", "D100"]
163
165
  "liquid/builtin/expressions/primitive.py" = ["D101", "D102"]
164
166
  "liquid/builtin/expressions/path.py" = ["D101", "D102"]
File without changes
File without changes
File without changes