python-liquid 1.10.2__tar.gz → 1.12.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 (189) hide show
  1. {python_liquid-1.10.2 → python_liquid-1.12.0}/PKG-INFO +8 -2
  2. {python_liquid-1.10.2 → python_liquid-1.12.0}/README.md +5 -1
  3. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/__init__.py +9 -1
  4. python_liquid-1.12.0/liquid/builtin/loaders/__init__.py +133 -0
  5. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/loaders/base_loader.py +6 -5
  6. python_liquid-1.12.0/liquid/builtin/loaders/caching_file_system_loader.py +75 -0
  7. python_liquid-1.12.0/liquid/builtin/loaders/choice_loader.py +143 -0
  8. python_liquid-1.10.2/liquid/builtin/loaders/caching_file_system_loader.py → python_liquid-1.12.0/liquid/builtin/loaders/mixins.py +117 -105
  9. python_liquid-1.12.0/liquid/builtin/loaders/package_loader.py +108 -0
  10. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/exceptions.py +4 -0
  11. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expression.py +68 -47
  12. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/if_tag.py +48 -0
  13. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/loaders.py +8 -0
  14. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/utils/cache.py +5 -0
  15. {python_liquid-1.10.2 → python_liquid-1.12.0}/pyproject.toml +105 -107
  16. python_liquid-1.10.2/liquid/builtin/loaders/__init__.py +0 -24
  17. python_liquid-1.10.2/liquid/builtin/loaders/choice_loader.py +0 -49
  18. {python_liquid-1.10.2 → python_liquid-1.12.0}/.gitignore +0 -0
  19. {python_liquid-1.10.2 → python_liquid-1.12.0}/LICENSE +0 -0
  20. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/analyze_tags.py +0 -0
  21. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/ast.py +0 -0
  22. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/__init__.py +0 -0
  23. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/drops/__init__.py +0 -0
  24. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/drops/drops.py +0 -0
  25. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/filters/__init__.py +0 -0
  26. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/filters/array.py +0 -0
  27. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/filters/extra.py +0 -0
  28. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/filters/math.py +0 -0
  29. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/filters/misc.py +0 -0
  30. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/filters/string.py +0 -0
  31. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/illegal.py +0 -0
  32. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/literal.py +0 -0
  33. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/loaders/file_system_loader.py +0 -0
  34. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/statement.py +0 -0
  35. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/__init__.py +0 -0
  36. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/assign_tag.py +0 -0
  37. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/capture_tag.py +0 -0
  38. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/case_tag.py +0 -0
  39. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/comment_tag.py +0 -0
  40. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/cycle_tag.py +0 -0
  41. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/decrement_tag.py +0 -0
  42. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/echo_tag.py +0 -0
  43. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/for_tag.py +0 -0
  44. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/if_tag.py +0 -0
  45. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/ifchanged_tag.py +0 -0
  46. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/include_tag.py +0 -0
  47. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/increment_tag.py +0 -0
  48. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/inline_comment_tag.py +0 -0
  49. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/liquid_tag.py +0 -0
  50. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/render_tag.py +0 -0
  51. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/tablerow_tag.py +0 -0
  52. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/builtin/tags/unless_tag.py +0 -0
  53. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/chain_map.py +0 -0
  54. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/context.py +0 -0
  55. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/environment.py +0 -0
  56. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/__init__.py +0 -0
  57. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/arguments/__init__.py +0 -0
  58. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/arguments/lex.py +0 -0
  59. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/arguments/parse.py +0 -0
  60. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/boolean/__init__.py +0 -0
  61. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/boolean/lex.py +0 -0
  62. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/boolean/parse.py +0 -0
  63. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/common.py +0 -0
  64. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/conditional/__init__.py +0 -0
  65. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/conditional/lex.py +0 -0
  66. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/conditional/parse.py +0 -0
  67. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/filtered/__init__.py +0 -0
  68. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/filtered/lex.py +0 -0
  69. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/filtered/parse.py +0 -0
  70. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/include/__init__.py +0 -0
  71. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/include/lex.py +0 -0
  72. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/loop/__init__.py +0 -0
  73. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/loop/lex.py +0 -0
  74. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/loop/parse.py +0 -0
  75. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/expressions/stream.py +0 -0
  76. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/__init__.py +0 -0
  77. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/filters/__init__.py +0 -0
  78. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/filters/_json.py +0 -0
  79. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/filters/array.py +0 -0
  80. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/filters/html.py +0 -0
  81. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/tags/__init__.py +0 -0
  82. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/tags/_with.py +0 -0
  83. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/tags/extends.py +0 -0
  84. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/tags/if_expressions.py +0 -0
  85. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/tags/if_not.py +0 -0
  86. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/extra/tags/macro.py +0 -0
  87. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/filter.py +0 -0
  88. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/future/__init__.py +0 -0
  89. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/future/environment.py +0 -0
  90. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/future/filters/__init__.py +0 -0
  91. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/future/filters/_split.py +0 -0
  92. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/__init__.py +0 -0
  93. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/abs_filter.py +0 -0
  94. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/append_filter.py +0 -0
  95. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/assign_tag.py +0 -0
  96. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/at_least_filter.py +0 -0
  97. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/at_most_filter.py +0 -0
  98. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/base64_decode_filter.py +0 -0
  99. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/base64_encode_filter.py +0 -0
  100. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/base64_url_safe_decode_filter.py +0 -0
  101. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/base64_url_safe_encode_filter.py +0 -0
  102. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/capitalize_filter.py +0 -0
  103. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/capture_tag.py +0 -0
  104. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/case.py +0 -0
  105. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/case_tag.py +0 -0
  106. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/ceil_filter.py +0 -0
  107. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/comment_tag.py +0 -0
  108. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/compact_filter.py +0 -0
  109. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/concat_filter.py +0 -0
  110. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/cycle_tag.py +0 -0
  111. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/date_filter.py +0 -0
  112. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/decrement_tag.py +0 -0
  113. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/default_filter.py +0 -0
  114. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/divided_by_filter.py +0 -0
  115. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/downcase_filter.py +0 -0
  116. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/echo_tag.py +0 -0
  117. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/escape_filter.py +0 -0
  118. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/escape_once_filter.py +0 -0
  119. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/first_filter.py +0 -0
  120. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/floor_filter.py +0 -0
  121. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/for_tag.py +0 -0
  122. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/identifiers.py +0 -0
  123. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/ifchanged_tag.py +0 -0
  124. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/illegal.py +0 -0
  125. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/include_tag.py +0 -0
  126. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/increment_tag.py +0 -0
  127. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/inline_comment_tag.py +0 -0
  128. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/join_filter.py +0 -0
  129. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/last_filter.py +0 -0
  130. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/liquid_tag.py +0 -0
  131. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/lstrip_filter.py +0 -0
  132. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/map_filter.py +0 -0
  133. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/minus_filter.py +0 -0
  134. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/modulo_filter.py +0 -0
  135. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/newline_to_br_filter.py +0 -0
  136. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/not_liquid.py +0 -0
  137. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/output_statement.py +0 -0
  138. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/plus_filter.py +0 -0
  139. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/prepend_filter.py +0 -0
  140. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/range_objects.py +0 -0
  141. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/raw_tag.py +0 -0
  142. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/remove_filter.py +0 -0
  143. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/remove_first_filter.py +0 -0
  144. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/remove_last_filter.py +0 -0
  145. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/render_tag.py +0 -0
  146. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/replace_filter.py +0 -0
  147. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/replace_first_filter.py +0 -0
  148. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/replace_last_filter.py +0 -0
  149. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/reverse_filter.py +0 -0
  150. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/round_filter.py +0 -0
  151. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/rstrip_filter.py +0 -0
  152. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/size_filter.py +0 -0
  153. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/slice_filter.py +0 -0
  154. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/sort_filter.py +0 -0
  155. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/sort_natural_filter.py +0 -0
  156. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/special.py +0 -0
  157. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/split_filter.py +0 -0
  158. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/strip_filter.py +0 -0
  159. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/strip_html_filter.py +0 -0
  160. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/strip_newlines_filter.py +0 -0
  161. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/sum_filter.py +0 -0
  162. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/tablerow_tag.py +0 -0
  163. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/times_filter.py +0 -0
  164. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/truncate_filter.py +0 -0
  165. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/truncatewords_filter.py +0 -0
  166. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/uniq_filter.py +0 -0
  167. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/unless_tag.py +0 -0
  168. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/upcase_filter.py +0 -0
  169. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/url_decode_filter.py +0 -0
  170. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/url_encode_filter.py +0 -0
  171. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/where_filter.py +0 -0
  172. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/golden/whitespace_control.py +0 -0
  173. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/lex.py +0 -0
  174. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/limits.py +0 -0
  175. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/mode.py +0 -0
  176. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/output.py +0 -0
  177. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/parse.py +0 -0
  178. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/py.typed +0 -0
  179. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/static_analysis.py +0 -0
  180. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/stream.py +0 -0
  181. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/stringify.py +0 -0
  182. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/tag.py +0 -0
  183. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/template.py +0 -0
  184. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/token.py +0 -0
  185. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/undefined.py +0 -0
  186. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/utils/__init__.py +0 -0
  187. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/utils/cache.pyi +0 -0
  188. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/utils/html.py +0 -0
  189. {python_liquid-1.10.2 → python_liquid-1.12.0}/liquid/utils/text.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-liquid
3
- Version: 1.10.2
3
+ Version: 1.12.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/
@@ -19,9 +19,11 @@ Classifier: Programming Language :: Python :: 3.8
19
19
  Classifier: Programming Language :: Python :: 3.9
20
20
  Classifier: Programming Language :: Python :: 3.10
21
21
  Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
22
23
  Classifier: Programming Language :: Python :: Implementation :: CPython
23
24
  Classifier: Programming Language :: Python :: Implementation :: PyPy
24
25
  Requires-Python: >=3.7
26
+ Requires-Dist: importlib-resources>=5.10.0
25
27
  Requires-Dist: python-dateutil>=2.8.1
26
28
  Requires-Dist: typing-extensions>=4.2.0
27
29
  Provides-Extra: autoescape
@@ -32,8 +34,8 @@ Description-Content-Type: text/markdown
32
34
 
33
35
  <p align="center">
34
36
  A Python engine for <a href="https://shopify.github.io/liquid/">Liquid</a>, the safe customer-facing template language for flexible web apps.
37
+ <br>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.
35
38
  </p>
36
-
37
39
  <p align="center">
38
40
  <a href="https://github.com/jg-rp/liquid/blob/main/LICENSE">
39
41
  <img src="https://img.shields.io/pypi/l/python-liquid.svg?style=flat-square" alt="License">
@@ -59,6 +61,10 @@ A Python engine for <a href="https://shopify.github.io/liquid/">Liquid</a>, the
59
61
  <a href="https://github.com/jg-rp/liquid/actions/workflows/coverage.yaml">
60
62
  <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/liquid/coverage.yaml?branch=main&label=coverage&style=flat-square" alt="Coverage">
61
63
  </a>
64
+ <br>
65
+ <a href="https://pypi.org/project/python-liquid/">
66
+ <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/python-liquid?style=flat-square">
67
+ </a>
62
68
  </p>
63
69
 
64
70
  ---
@@ -2,8 +2,8 @@
2
2
 
3
3
  <p align="center">
4
4
  A Python engine for <a href="https://shopify.github.io/liquid/">Liquid</a>, the safe customer-facing template language for flexible web apps.
5
+ <br>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.
5
6
  </p>
6
-
7
7
  <p align="center">
8
8
  <a href="https://github.com/jg-rp/liquid/blob/main/LICENSE">
9
9
  <img src="https://img.shields.io/pypi/l/python-liquid.svg?style=flat-square" alt="License">
@@ -29,6 +29,10 @@ A Python engine for <a href="https://shopify.github.io/liquid/">Liquid</a>, the
29
29
  <a href="https://github.com/jg-rp/liquid/actions/workflows/coverage.yaml">
30
30
  <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/liquid/coverage.yaml?branch=main&label=coverage&style=flat-square" alt="Coverage">
31
31
  </a>
32
+ <br>
33
+ <a href="https://pypi.org/project/python-liquid/">
34
+ <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/python-liquid?style=flat-square">
35
+ </a>
32
36
  </p>
33
37
 
34
38
  ---
@@ -12,11 +12,15 @@ from .mode import Mode
12
12
  from .token import Token
13
13
  from .expression import Expression
14
14
 
15
+ from .loaders import CachingChoiceLoader
15
16
  from .loaders import CachingFileSystemLoader
16
17
  from .loaders import ChoiceLoader
17
18
  from .loaders import DictLoader
18
19
  from .loaders import FileExtensionLoader
19
20
  from .loaders import FileSystemLoader
21
+ from .loaders import PackageLoader
22
+ from .loaders import make_choice_loader
23
+ from .loaders import make_file_system_loader
20
24
 
21
25
  from .context import Context
22
26
  from .context import DebugUndefined
@@ -42,11 +46,12 @@ from .static_analysis import ContextualTemplateAnalysis
42
46
 
43
47
  from . import future
44
48
 
45
- __version__ = "1.10.2"
49
+ __version__ = "1.12.0"
46
50
 
47
51
  __all__ = (
48
52
  "AwareBoundTemplate",
49
53
  "BoundTemplate",
54
+ "CachingChoiceLoader",
50
55
  "CachingFileSystemLoader",
51
56
  "ChoiceLoader",
52
57
  "Context",
@@ -64,8 +69,11 @@ __all__ = (
64
69
  "FutureBoundTemplate",
65
70
  "FutureContext",
66
71
  "is_undefined",
72
+ "make_choice_loader",
73
+ "make_file_system_loader",
67
74
  "Markup",
68
75
  "Mode",
76
+ "PackageLoader",
69
77
  "soft_str",
70
78
  "StrictDefaultUndefined",
71
79
  "StrictUndefined",
@@ -0,0 +1,133 @@
1
+ from pathlib import Path
2
+ from typing import Iterable
3
+ from typing import List
4
+ from typing import Union
5
+
6
+ from .base_loader import BaseLoader
7
+ from .base_loader import DictLoader
8
+ from .base_loader import TemplateNamespace
9
+ from .base_loader import TemplateSource
10
+ from .base_loader import UpToDate
11
+
12
+ from .choice_loader import CachingChoiceLoader
13
+ from .choice_loader import ChoiceLoader
14
+
15
+ from .file_system_loader import FileExtensionLoader
16
+ from .file_system_loader import FileSystemLoader
17
+
18
+ from .caching_file_system_loader import CachingFileSystemLoader
19
+
20
+ from .package_loader import PackageLoader
21
+
22
+ __all__ = (
23
+ "BaseLoader",
24
+ "CachingChoiceLoader",
25
+ "CachingFileSystemLoader",
26
+ "ChoiceLoader",
27
+ "DictLoader",
28
+ "FileExtensionLoader",
29
+ "FileSystemLoader",
30
+ "make_choice_loader",
31
+ "make_file_system_loader",
32
+ "PackageLoader",
33
+ "TemplateNamespace",
34
+ "TemplateSource",
35
+ "UpToDate",
36
+ )
37
+
38
+
39
+ def make_file_system_loader(
40
+ search_path: Union[str, Path, Iterable[Union[str, Path]]],
41
+ *,
42
+ encoding: str = "utf-8",
43
+ ext: str = ".liquid",
44
+ auto_reload: bool = True,
45
+ namespace_key: str = "",
46
+ cache_size: int = 300,
47
+ ) -> BaseLoader:
48
+ """A _file system_ template loader factory.
49
+
50
+ Returns one of `CachingFileSystemLoader`, `FileExtensionLoader` or
51
+ `FileSystemLoader` depending in the given arguments.
52
+
53
+ A `CachingFileSystemLoader` is returned if _cache_size_ is greater than 0.
54
+ Otherwise a `FileExtensionLoader` is returned if _ext_ is not empty.
55
+ If _ext_ is empty, a `FileSystemLoader` is returned.
56
+
57
+ _auto_reload_ and _namespace_key_ are ignored if _cache_key_ is less than 1.
58
+
59
+ Args:
60
+ search_path: One or more paths to search.
61
+ encoding: Open template files with the given encoding.
62
+ ext: A default file extension. Should include a leading period.
63
+ auto_reload: If `True`, automatically reload a cached template if it has been
64
+ updated.
65
+ namespace_key: The name of a global render context variable or loader keyword
66
+ argument that resolves to the current loader "namespace" or "scope".
67
+
68
+ If you're developing a multi-user application, a good namespace might be
69
+ `uid`, where `uid` is a unique identifier for a user and templates are
70
+ arranged in folders named for each `uid` inside the search path.
71
+ cache_size: The maximum number of templates to hold in the cache before removing
72
+ the least recently used template.
73
+
74
+ _New in version 1.12.0_
75
+ """
76
+ if cache_size > 0:
77
+ return CachingFileSystemLoader(
78
+ search_path=search_path,
79
+ encoding=encoding,
80
+ ext=ext,
81
+ auto_reload=auto_reload,
82
+ namespace_key=namespace_key,
83
+ cache_size=cache_size,
84
+ )
85
+
86
+ if ext:
87
+ return FileExtensionLoader(
88
+ search_path=search_path,
89
+ encoding=encoding,
90
+ ext=ext,
91
+ )
92
+
93
+ return FileSystemLoader(search_path=search_path, encoding=encoding)
94
+
95
+
96
+ def make_choice_loader(
97
+ loaders: List[BaseLoader],
98
+ *,
99
+ auto_reload: bool = True,
100
+ namespace_key: str = "",
101
+ cache_size: int = 300,
102
+ ) -> BaseLoader:
103
+ """A _choice loader_ factory.
104
+
105
+ Returns one of `CachingChoiceLoader` or `ChoiceLoader` depending on the
106
+ given arguments.
107
+
108
+ A `CachingChoiceLoader` is returned if _cache_size_ > 0, otherwise a
109
+ `ChoiceLoader` is returned.
110
+
111
+ _auto_reload_ and _namespace_key_ are ignored if _cache_key_ is less than 1.
112
+
113
+ Args:
114
+ loaders: A list of loaders implementing `liquid.loaders.BaseLoader`.
115
+ auto_reload: If `True`, automatically reload a cached template if it
116
+ has been updated.
117
+ namespace_key: The name of a global render context variable or loader
118
+ keyword argument that resolves to the current loader "namespace" or
119
+ "scope".
120
+ cache_size: The maximum number of templates to hold in the cache before
121
+ removing the least recently used template.
122
+
123
+ _New in version 1.12.0_
124
+ """
125
+ if cache_size > 0:
126
+ return CachingChoiceLoader(
127
+ loaders=loaders,
128
+ auto_reload=auto_reload,
129
+ namespace_key=namespace_key,
130
+ cache_size=cache_size,
131
+ )
132
+
133
+ return ChoiceLoader(loaders=loaders)
@@ -129,11 +129,12 @@ class BaseLoader(ABC): # noqa: B024
129
129
  name: str,
130
130
  globals: TemplateNamespace = None, # noqa: A002
131
131
  ) -> BoundTemplate:
132
- """Load and parse a template.
132
+ """Find and parse template source code.
133
133
 
134
- Used internally by `Environment` to load a template source. Delegates to
135
- `get_source`. A custom loaders would typically implement `get_source` rather
136
- than overriding `load`.
134
+ This is used internally by `liquid.Environment` to load template
135
+ source text. `load()` delegates to `BaseLoader.get_source()`. Custom
136
+ loaders would typically implement `get_source()` rather than overriding
137
+ `load()`.
137
138
  """
138
139
  try:
139
140
  source, filename, uptodate, matter = self.get_source(env, name)
@@ -156,7 +157,7 @@ class BaseLoader(ABC): # noqa: B024
156
157
  name: str,
157
158
  globals: TemplateNamespace = None, # noqa: A002
158
159
  ) -> BoundTemplate:
159
- """An async version of `load`."""
160
+ """An async version of `load()`."""
160
161
  try:
161
162
  template_source = await self.get_source_async(env, name)
162
163
  source, filename, uptodate, matter = template_source
@@ -0,0 +1,75 @@
1
+ """A file system loader that caches parsed templates in memory."""
2
+ from __future__ import annotations
3
+
4
+ from typing import TYPE_CHECKING
5
+ from typing import Iterable
6
+ from typing import Union
7
+
8
+ from .file_system_loader import FileExtensionLoader
9
+ from .mixins import CachingLoaderMixin
10
+
11
+ if TYPE_CHECKING:
12
+ from pathlib import Path
13
+
14
+ from liquid import Context
15
+
16
+ from .base_loader import TemplateSource
17
+
18
+ # ruff: noqa: D102
19
+
20
+
21
+ class CachingFileSystemLoader(CachingLoaderMixin, FileExtensionLoader):
22
+ """A file system loader that caches parsed templates in memory.
23
+
24
+ Args:
25
+ search_path: One or more paths to search.
26
+ encoding: Open template files with the given encoding.
27
+ ext: A default file extension. Should include a leading period.
28
+ auto_reload: If `True`, automatically reload a cached template if it has been
29
+ updated.
30
+ namespace_key: The name of a global render context variable or loader keyword
31
+ argument that resolves to the current loader "namespace" or "scope".
32
+
33
+ If you're developing a multi-user application, a good namespace might be
34
+ `uid`, where `uid` is a unique identifier for a user and templates are
35
+ arranged in folders named for each `uid` inside the search path.
36
+ cache_size: The maximum number of templates to hold in the cache before removing
37
+ the least recently used template.
38
+ """
39
+
40
+ def __init__(
41
+ self,
42
+ search_path: Union[str, Path, Iterable[Union[str, Path]]],
43
+ encoding: str = "utf-8",
44
+ ext: str = ".liquid",
45
+ *,
46
+ auto_reload: bool = True,
47
+ namespace_key: str = "",
48
+ cache_size: int = 300,
49
+ ):
50
+ super().__init__(
51
+ auto_reload=auto_reload,
52
+ namespace_key=namespace_key,
53
+ cache_size=cache_size,
54
+ )
55
+
56
+ FileExtensionLoader.__init__(
57
+ self,
58
+ search_path=search_path,
59
+ encoding=encoding,
60
+ ext=ext,
61
+ )
62
+
63
+ def get_source_with_context(
64
+ self, context: Context, template_name: str, **kwargs: str
65
+ ) -> TemplateSource:
66
+ # In this case, our cache key and real file name are the same.
67
+ name = self.cache_key_with_context(template_name, context, **kwargs)
68
+ return self.get_source(context.env, name)
69
+
70
+ async def get_source_with_context_async(
71
+ self, context: Context, template_name: str, **kwargs: str
72
+ ) -> TemplateSource:
73
+ # In this case, our cache key and real file name are the same.
74
+ name = self.cache_key_with_context(template_name, context, **kwargs)
75
+ return await self.get_source_async(context.env, name)
@@ -0,0 +1,143 @@
1
+ """A template loader that delegates to other template loaders."""
2
+ from __future__ import annotations
3
+
4
+ from typing import TYPE_CHECKING
5
+ from typing import List
6
+
7
+ from liquid.exceptions import TemplateNotFound
8
+
9
+ from .base_loader import BaseLoader
10
+ from .mixins import CachingLoaderMixin
11
+
12
+ if TYPE_CHECKING:
13
+ from liquid import Context
14
+ from liquid import Environment
15
+
16
+ from .base_loader import TemplateSource
17
+
18
+
19
+ class ChoiceLoader(BaseLoader):
20
+ """A template loader that will try each of a list of loaders in turn.
21
+
22
+ Args:
23
+ loaders: A list of loaders implementing `liquid.loaders.BaseLoader`.
24
+ """
25
+
26
+ def __init__(self, loaders: List[BaseLoader]):
27
+ super().__init__()
28
+ self.loaders = loaders
29
+
30
+ def get_source(self, env: Environment, template_name: str) -> TemplateSource:
31
+ """Get source code for a template from one of the configured loaders."""
32
+ for loader in self.loaders:
33
+ try:
34
+ return loader.get_source(env, template_name)
35
+ except TemplateNotFound:
36
+ pass
37
+
38
+ raise TemplateNotFound(template_name)
39
+
40
+ async def get_source_async(
41
+ self,
42
+ env: Environment,
43
+ template_name: str,
44
+ ) -> TemplateSource:
45
+ """An async version of `get_source`."""
46
+ for loader in self.loaders:
47
+ try:
48
+ return await loader.get_source_async(env, template_name)
49
+ except TemplateNotFound:
50
+ pass
51
+
52
+ raise TemplateNotFound(template_name)
53
+
54
+ def get_source_with_args(
55
+ self,
56
+ env: Environment,
57
+ template_name: str,
58
+ **kwargs: object,
59
+ ) -> TemplateSource:
60
+ """Get source code for a template from one of the configured loaders."""
61
+ for loader in self.loaders:
62
+ try:
63
+ return loader.get_source_with_args(env, template_name, **kwargs)
64
+ except TemplateNotFound:
65
+ pass
66
+
67
+ # TODO: include arguments in TemplateNotFound exception.
68
+ raise TemplateNotFound(template_name)
69
+
70
+ async def get_source_with_args_async(
71
+ self,
72
+ env: Environment,
73
+ template_name: str,
74
+ **kwargs: object,
75
+ ) -> TemplateSource:
76
+ """An async version of `get_source_with_args`."""
77
+ for loader in self.loaders:
78
+ try:
79
+ return await loader.get_source_with_args_async(
80
+ env, template_name, **kwargs
81
+ )
82
+ except TemplateNotFound:
83
+ pass
84
+
85
+ raise TemplateNotFound(template_name)
86
+
87
+ def get_source_with_context(
88
+ self, context: Context, template_name: str, **kwargs: str
89
+ ) -> TemplateSource:
90
+ """Get source code for a template from one of the configured loaders."""
91
+ for loader in self.loaders:
92
+ try:
93
+ return loader.get_source_with_context(context, template_name, **kwargs)
94
+ except TemplateNotFound:
95
+ pass
96
+
97
+ raise TemplateNotFound(template_name)
98
+
99
+ async def get_source_with_context_async(
100
+ self, context: Context, template_name: str, **kwargs: str
101
+ ) -> TemplateSource:
102
+ """Get source code for a template from one of the configured loaders."""
103
+ for loader in self.loaders:
104
+ try:
105
+ return await loader.get_source_with_context_async(
106
+ context, template_name, **kwargs
107
+ )
108
+ except TemplateNotFound:
109
+ pass
110
+
111
+ raise TemplateNotFound(template_name)
112
+
113
+
114
+ class CachingChoiceLoader(CachingLoaderMixin, ChoiceLoader):
115
+ """A `ChoiceLoader` that caches parsed templates in memory.
116
+
117
+ Args:
118
+ loaders: A list of loaders implementing `liquid.loaders.BaseLoader`.
119
+ auto_reload: If `True`, automatically reload a cached template if it has been
120
+ updated.
121
+ namespace_key: The name of a global render context variable or loader keyword
122
+ argument that resolves to the current loader "namespace" or "scope".
123
+ cache_size: The maximum number of templates to hold in the cache before removing
124
+ the least recently used template.
125
+
126
+ _New in version 1.11.0._
127
+ """
128
+
129
+ def __init__(
130
+ self,
131
+ loaders: List[BaseLoader],
132
+ *,
133
+ auto_reload: bool = True,
134
+ namespace_key: str = "",
135
+ cache_size: int = 300,
136
+ ):
137
+ super().__init__(
138
+ auto_reload=auto_reload,
139
+ namespace_key=namespace_key,
140
+ cache_size=cache_size,
141
+ )
142
+
143
+ ChoiceLoader.__init__(self, loaders)