python-liquid 2.3.6__tar.gz → 2.3.7__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.3.6 → python_liquid-2.3.7}/PKG-INFO +4 -27
  2. {python_liquid-2.3.6 → python_liquid-2.3.7}/README.md +3 -26
  3. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/__init__.py +1 -1
  4. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/expressions/logical.py +3 -0
  5. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/filters/array.py +23 -33
  6. {python_liquid-2.3.6 → python_liquid-2.3.7}/.gitignore +0 -0
  7. {python_liquid-2.3.6 → python_liquid-2.3.7}/LICENSE +0 -0
  8. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/analyze_tags.py +0 -0
  9. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/ast.py +0 -0
  10. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/__init__.py +0 -0
  11. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/content.py +0 -0
  12. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/drops/__init__.py +0 -0
  13. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/drops/drops.py +0 -0
  14. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/expressions/__init__.py +0 -0
  15. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/expressions/_tokenize.py +0 -0
  16. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/expressions/arguments.py +0 -0
  17. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/expressions/filtered.py +0 -0
  18. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/expressions/loop.py +0 -0
  19. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/expressions/path.py +0 -0
  20. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/expressions/primitive.py +0 -0
  21. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/filters/__init__.py +0 -0
  22. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/filters/extra.py +0 -0
  23. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/filters/math.py +0 -0
  24. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/filters/misc.py +0 -0
  25. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/filters/string.py +0 -0
  26. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/illegal.py +0 -0
  27. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/loaders/__init__.py +0 -0
  28. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/loaders/caching_file_system_loader.py +0 -0
  29. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/loaders/choice_loader.py +0 -0
  30. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/loaders/dict_loader.py +0 -0
  31. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/loaders/file_system_loader.py +0 -0
  32. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/loaders/mixins.py +0 -0
  33. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/loaders/package_loader.py +0 -0
  34. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/output.py +0 -0
  35. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/__init__.py +0 -0
  36. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/assign_tag.py +0 -0
  37. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/capture_tag.py +0 -0
  38. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/case_tag.py +0 -0
  39. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/comment_tag.py +0 -0
  40. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/cycle_tag.py +0 -0
  41. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/decrement_tag.py +0 -0
  42. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/doc_tag.py +0 -0
  43. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/echo_tag.py +0 -0
  44. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/for_tag.py +0 -0
  45. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/if_tag.py +0 -0
  46. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/ifchanged_tag.py +0 -0
  47. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/include_tag.py +0 -0
  48. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/increment_tag.py +0 -0
  49. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/inline_comment_tag.py +0 -0
  50. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/liquid_tag.py +0 -0
  51. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/render_tag.py +0 -0
  52. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/tablerow_tag.py +0 -0
  53. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/builtin/tags/unless_tag.py +0 -0
  54. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/context.py +0 -0
  55. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/environment.py +0 -0
  56. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/exceptions.py +0 -0
  57. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/expression.py +0 -0
  58. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/__init__.py +0 -0
  59. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/filters/__init__.py +0 -0
  60. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/filters/_json.py +0 -0
  61. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/filters/array.py +0 -0
  62. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/filters/babel.py +0 -0
  63. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/filters/html.py +0 -0
  64. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/filters/translate.py +0 -0
  65. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/tags/__init__.py +0 -0
  66. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/tags/_with.py +0 -0
  67. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/tags/extends_tag.py +0 -0
  68. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/tags/macro_tag.py +0 -0
  69. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/tags/snippet_tag.py +0 -0
  70. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/extra/tags/translate_tag.py +0 -0
  71. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/filter.py +0 -0
  72. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/future/__init__.py +0 -0
  73. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/future/environment.py +0 -0
  74. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/future/filters/__init__.py +0 -0
  75. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/future/tags/__init__.py +0 -0
  76. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/lex.py +0 -0
  77. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/limits.py +0 -0
  78. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/loader.py +0 -0
  79. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/messages.py +0 -0
  80. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/mode.py +0 -0
  81. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/output.py +0 -0
  82. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/parser.py +0 -0
  83. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/py.typed +0 -0
  84. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/span.py +0 -0
  85. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/static_analysis.py +0 -0
  86. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/stream.py +0 -0
  87. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/stringify.py +0 -0
  88. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/tag.py +0 -0
  89. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/template.py +0 -0
  90. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/token.py +0 -0
  91. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/undefined.py +0 -0
  92. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/utils/__init__.py +0 -0
  93. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/utils/chain_map.py +0 -0
  94. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/utils/html.py +0 -0
  95. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/utils/lru_cache.py +0 -0
  96. {python_liquid-2.3.6 → python_liquid-2.3.7}/liquid/utils/text.py +0 -0
  97. {python_liquid-2.3.6 → python_liquid-2.3.7}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-liquid
3
- Version: 2.3.6
3
+ Version: 2.3.7
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/
@@ -38,32 +38,9 @@ Python Liquid is a Python engine for <a href="https://shopify.github.io/liquid/"
38
38
  <br>
39
39
  We follow <a href="https://github.com/Shopify/liquid">Shopify/Liquid</a> closely and test against the <a href="https://github.com/jg-rp/golden-liquid">Golden Liquid</a> test suite.
40
40
  </p>
41
- <p align="center">
42
- <a href="https://pypi.org/project/python-liquid/">
43
- <img src="https://img.shields.io/pypi/v/python-liquid.svg?style=flat-square" alt="PyPi - Version">
44
- </a>
45
- <a href="https://anaconda.org/conda-forge/python-liquid">
46
- <img src="https://img.shields.io/conda/vn/conda-forge/python-liquid?style=flat-square" alt="conda-forge">
47
- </a>
48
- <a href="https://pypi.org/project/python-liquid/">
49
- <img src="https://img.shields.io/pypi/pyversions/python-liquid.svg?style=flat-square" alt="Python versions">
50
- </a>
51
- <br>
52
- <a href="https://github.com/jg-rp/liquid/actions/workflows/tests.yaml">
53
- <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/liquid/tests.yaml?branch=main&label=tests&style=flat-square" alt="Tests">
54
- </a>
55
- <a href="https://github.com/jg-rp/liquid/actions/workflows/coverage.yaml">
56
- <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/liquid/coverage.yaml?branch=main&label=coverage&style=flat-square" alt="Coverage">
57
- </a>
58
- <br>
59
- <a href="https://pypi.org/project/python-liquid/">
60
- <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/python-liquid?style=flat-square">
61
- </a>
62
- <br>
63
- <a href="https://github.com/jg-rp/liquid/blob/main/LICENSE">
64
- <img src="https://img.shields.io/pypi/l/python-liquid.svg?style=flat-square" alt="License">
65
- </a>
66
- </p>
41
+
42
+ > [!WARNING]
43
+ > This is the v2 branch of Python Liquid.
67
44
 
68
45
  ---
69
46
 
@@ -5,32 +5,9 @@ Python Liquid is a Python engine for <a href="https://shopify.github.io/liquid/"
5
5
  <br>
6
6
  We follow <a href="https://github.com/Shopify/liquid">Shopify/Liquid</a> closely and test against the <a href="https://github.com/jg-rp/golden-liquid">Golden Liquid</a> test suite.
7
7
  </p>
8
- <p align="center">
9
- <a href="https://pypi.org/project/python-liquid/">
10
- <img src="https://img.shields.io/pypi/v/python-liquid.svg?style=flat-square" alt="PyPi - Version">
11
- </a>
12
- <a href="https://anaconda.org/conda-forge/python-liquid">
13
- <img src="https://img.shields.io/conda/vn/conda-forge/python-liquid?style=flat-square" alt="conda-forge">
14
- </a>
15
- <a href="https://pypi.org/project/python-liquid/">
16
- <img src="https://img.shields.io/pypi/pyversions/python-liquid.svg?style=flat-square" alt="Python versions">
17
- </a>
18
- <br>
19
- <a href="https://github.com/jg-rp/liquid/actions/workflows/tests.yaml">
20
- <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/liquid/tests.yaml?branch=main&label=tests&style=flat-square" alt="Tests">
21
- </a>
22
- <a href="https://github.com/jg-rp/liquid/actions/workflows/coverage.yaml">
23
- <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/liquid/coverage.yaml?branch=main&label=coverage&style=flat-square" alt="Coverage">
24
- </a>
25
- <br>
26
- <a href="https://pypi.org/project/python-liquid/">
27
- <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/python-liquid?style=flat-square">
28
- </a>
29
- <br>
30
- <a href="https://github.com/jg-rp/liquid/blob/main/LICENSE">
31
- <img src="https://img.shields.io/pypi/l/python-liquid.svg?style=flat-square" alt="License">
32
- </a>
33
- </p>
8
+
9
+ > [!WARNING]
10
+ > This is the v2 branch of Python Liquid.
34
11
 
35
12
  ---
36
13
 
@@ -56,7 +56,7 @@ from .tag import Tag
56
56
 
57
57
  from . import future
58
58
 
59
- __version__ = "2.3.6"
59
+ __version__ = "2.3.7"
60
60
 
61
61
  __all__ = (
62
62
  "AwareBoundTemplate",
@@ -618,6 +618,9 @@ def _lt(token: Token, left: object, right: object) -> bool:
618
618
  if isinstance(left, str) and isinstance(right, str):
619
619
  return left < right
620
620
 
621
+ if isinstance(left, bool) or isinstance(right, bool):
622
+ return False
623
+
621
624
  if isinstance(left, (int, float, Decimal)) and isinstance(
622
625
  right, (int, float, Decimal)
623
626
  ):
@@ -73,7 +73,7 @@ def first(left: Any, *, environment: Environment) -> object:
73
73
  return None
74
74
 
75
75
  if isinstance(left, dict):
76
- left = list(islice(left.items(), 1))
76
+ return next(islice(left.items(), 1), None) # pyright: ignore[reportUnknownVariableType, reportUnknownArgumentType]
77
77
 
78
78
  try:
79
79
  return getitem(left, 0)
@@ -101,17 +101,18 @@ def last(obj: Sequence[Any], *, environment: Environment) -> object:
101
101
 
102
102
 
103
103
  @sequence_filter
104
- def concat(sequence: ArrayT, second_array: ArrayT) -> ArrayT:
104
+ def concat(sequence: ArrayT, second_array: object) -> ArrayT:
105
105
  """Return the concatenation of _sequence_ and _second_array_."""
106
106
  if not isinstance(second_array, (list, tuple)):
107
107
  raise FilterArgumentError(
108
- f"concat expected an array, found {type(second_array).__name__}"
108
+ f"concat expected an array, found {type(second_array).__name__}",
109
+ token=None,
109
110
  )
110
111
 
111
112
  if is_undefined(sequence):
112
- return second_array
113
+ return second_array # pyright: ignore[reportUnknownVariableType]
113
114
 
114
- return list(chain(sequence, second_array))
115
+ return list(chain(sequence, second_array)) # pyright: ignore[reportUnknownArgumentType]
115
116
 
116
117
 
117
118
  @sequence_filter
@@ -166,7 +167,7 @@ def where(sequence: ArrayT, attr: object, value: object = None) -> list[object]:
166
167
  if value is not None and not is_undefined(value):
167
168
  return [itm for itm in sequence if _getitem(itm, attr) == value]
168
169
 
169
- return [itm for itm in sequence if _getitem(itm, attr) not in (False, None)]
170
+ return [itm for itm in sequence if _truthy(_getitem(itm, attr))]
170
171
 
171
172
 
172
173
  @sequence_filter
@@ -178,7 +179,7 @@ def reject(sequence: ArrayT, attr: object, value: object = None) -> list[object]
178
179
  if value is not None and not is_undefined(value):
179
180
  return [itm for itm in sequence if _getitem(itm, attr) != value]
180
181
 
181
- return [itm for itm in sequence if _getitem(itm, attr) in (False, None)]
182
+ return [itm for itm in sequence if not _truthy(_getitem(itm, attr))]
182
183
 
183
184
 
184
185
  @sequence_filter
@@ -187,9 +188,7 @@ def find(sequence: ArrayT, attr: object, value: object = None) -> object:
187
188
  if value is not None and not is_undefined(value):
188
189
  return next((itm for itm in sequence if _getitem(itm, attr) == value), None)
189
190
 
190
- return next(
191
- (itm for itm in sequence if _getitem(itm, attr) not in (False, None)), None
192
- )
191
+ return next((itm for itm in sequence if _truthy(_getitem(itm, attr))), None)
193
192
 
194
193
 
195
194
  @sequence_filter
@@ -224,30 +223,11 @@ def has(sequence: ArrayT, attr: object, value: object = None) -> bool:
224
223
  @sequence_filter
225
224
  def uniq(sequence: ArrayT, key: object = None) -> list[object]:
226
225
  """Return a copy of _sequence_ with duplicate elements removed."""
227
- # Note that we're not using a dict or set for deduplication because we need
228
- # to handle sequences containing unhashable objects, like dictionaries.
229
-
230
- # This is probably quite slow.
231
- if key is not None:
232
- keys = []
233
- result = []
234
- for obj in sequence:
235
- try:
236
- item = obj[key]
237
- except KeyError:
238
- item = MISSING
239
- except TypeError as err:
240
- raise FilterArgumentError(
241
- f"can't read property '{key}' of {obj}", token=None
242
- ) from err
243
-
244
- if item not in keys:
245
- keys.append(item)
246
- result.append(obj)
226
+ if _nil(key):
227
+ return [obj for i, obj in enumerate(sequence) if sequence.index(obj) == i]
247
228
 
248
- return result
249
-
250
- return [obj for i, obj in enumerate(sequence) if sequence.index(obj) == i]
229
+ keys = [_getitem(obj, key) for obj in sequence]
230
+ return [sequence[i] for i, key in enumerate(keys) if keys.index(key) == i]
251
231
 
252
232
 
253
233
  @sequence_filter
@@ -327,3 +307,13 @@ class _Null:
327
307
 
328
308
 
329
309
  _NULL = _Null()
310
+
311
+
312
+ def _nil(obj: object) -> bool:
313
+ # Liquid nullish-ness
314
+ return obj is None or is_undefined(obj) or obj is _NULL
315
+
316
+
317
+ def _truthy(obj: object) -> bool:
318
+ # Liquid truthiness. 0 is truthy.
319
+ return obj is not False and obj is not None and not is_undefined(obj)
File without changes
File without changes