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.
- liquid/__about__.py +1 -0
- liquid/__init__.py +161 -187
- liquid/_base_tag.py +66 -0
- liquid/{utils/chain_map.py → _chain_map.py} +18 -19
- liquid/_context.py +465 -0
- liquid/_drop.py +108 -0
- liquid/_filter.py +174 -0
- liquid/_io.py +18 -0
- liquid/_lax_parser_mixin.py +100 -0
- liquid/_lexer.py +93 -0
- liquid/_lexer_extended.py +623 -0
- liquid/_lexer_legacy.py +536 -0
- liquid/_loader.py +84 -0
- liquid/{utils/lru_cache.py → _lru_cache.py} +28 -36
- liquid/_markup.py +253 -0
- liquid/_messages.py +292 -0
- liquid/_missing.py +3 -0
- liquid/_nothing.py +28 -0
- liquid/_parser.py +460 -0
- liquid/_parser_extended.py +293 -0
- liquid/_parser_legacy.py +819 -0
- liquid/_resource_limits.py +50 -0
- liquid/_slice.py +41 -0
- liquid/_static_analysis.py +503 -0
- liquid/_strftime.py +186 -0
- liquid/_template.py +536 -0
- liquid/drops/__init__.py +20 -0
- liquid/drops/forloop.py +78 -0
- liquid/drops/iterable.py +25 -0
- liquid/drops/range.py +76 -0
- liquid/drops/self_.py +45 -0
- liquid/drops/tablerowloop.py +142 -0
- liquid/drops/undefined.py +228 -0
- liquid/environment.py +717 -551
- liquid/exceptions.py +67 -214
- liquid/expressions.py +1184 -0
- liquid/filters/__init__.py +134 -0
- liquid/filters/abs.py +7 -0
- liquid/filters/append.py +5 -0
- liquid/filters/at_least.py +9 -0
- liquid/filters/at_most.py +9 -0
- liquid/filters/babel.py +560 -0
- liquid/filters/base64.py +26 -0
- liquid/filters/capitalize.py +5 -0
- liquid/filters/ceil.py +8 -0
- liquid/filters/compact.py +25 -0
- liquid/filters/concat.py +11 -0
- liquid/filters/date.py +27 -0
- liquid/filters/default.py +25 -0
- liquid/filters/divided_by.py +21 -0
- liquid/filters/downcase.py +5 -0
- liquid/filters/escape.py +56 -0
- liquid/filters/find.py +56 -0
- liquid/filters/first.py +19 -0
- liquid/filters/floor.py +8 -0
- liquid/filters/html.py +23 -0
- liquid/filters/index.py +12 -0
- liquid/filters/join.py +13 -0
- liquid/filters/json_.py +30 -0
- liquid/filters/last.py +17 -0
- liquid/filters/map.py +5 -0
- liquid/filters/minus.py +13 -0
- liquid/filters/modulo.py +18 -0
- liquid/filters/newline_to_br.py +16 -0
- liquid/filters/plus.py +13 -0
- liquid/filters/prepend.py +5 -0
- liquid/filters/reject.py +19 -0
- liquid/filters/remove.py +36 -0
- liquid/filters/replace.py +32 -0
- liquid/filters/reverse.py +5 -0
- liquid/filters/round.py +35 -0
- liquid/filters/size.py +25 -0
- liquid/filters/slice.py +39 -0
- liquid/filters/sort.py +148 -0
- liquid/filters/split.py +34 -0
- liquid/filters/squish.py +9 -0
- liquid/filters/strip.py +13 -0
- liquid/filters/strip_html.py +19 -0
- liquid/filters/strip_newlines.py +17 -0
- liquid/filters/sum.py +21 -0
- liquid/filters/times.py +13 -0
- liquid/filters/translate.py +380 -0
- liquid/filters/truncate.py +39 -0
- liquid/filters/uniq.py +11 -0
- liquid/filters/upcase.py +5 -0
- liquid/filters/url.py +18 -0
- liquid/filters/where.py +18 -0
- liquid/loaders/__init__.py +17 -0
- liquid/loaders/caching_file_system_loader.py +64 -0
- liquid/loaders/choice_loader.py +93 -0
- liquid/loaders/dict_loader.py +56 -0
- liquid/{builtin/loaders → loaders}/file_system_loader.py +51 -55
- liquid/{builtin/loaders → loaders}/mixins.py +39 -51
- liquid/loaders/package_loader.py +110 -0
- liquid/tags/__init__.py +61 -0
- liquid/tags/assign.py +68 -0
- liquid/tags/capture.py +83 -0
- liquid/tags/case.py +199 -0
- liquid/tags/comment.py +56 -0
- liquid/tags/cycle.py +131 -0
- liquid/tags/decrement.py +55 -0
- liquid/tags/doc.py +56 -0
- liquid/tags/echo.py +65 -0
- liquid/tags/else_.py +53 -0
- liquid/tags/error.py +51 -0
- liquid/tags/extends.py +448 -0
- liquid/tags/for_.py +421 -0
- liquid/tags/if_.py +156 -0
- liquid/tags/ifchanged.py +69 -0
- liquid/tags/include.py +223 -0
- liquid/tags/increment.py +55 -0
- liquid/tags/inline_comment.py +70 -0
- liquid/tags/liquid.py +56 -0
- liquid/tags/macro.py +281 -0
- liquid/tags/output.py +58 -0
- liquid/tags/raw.py +60 -0
- liquid/tags/render.py +245 -0
- liquid/tags/tablerow.py +254 -0
- liquid/tags/template_comment.py +56 -0
- liquid/tags/translate.py +316 -0
- liquid/tags/unless.py +121 -0
- liquid/tags/with_.py +83 -0
- liquid/tokens.py +370 -0
- {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/METADATA +32 -39
- python_liquid-3.0.0.dist-info/RECORD +128 -0
- {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/WHEEL +1 -1
- {python_liquid-2.3.6.dist-info → python_liquid-3.0.0.dist-info}/licenses/LICENSE +1 -1
- liquid/analyze_tags.py +0 -214
- liquid/ast.py +0 -252
- liquid/builtin/__init__.py +0 -203
- liquid/builtin/content.py +0 -41
- liquid/builtin/drops/__init__.py +0 -3
- liquid/builtin/drops/drops.py +0 -13
- liquid/builtin/expressions/__init__.py +0 -47
- liquid/builtin/expressions/_tokenize.py +0 -186
- liquid/builtin/expressions/arguments.py +0 -207
- liquid/builtin/expressions/filtered.py +0 -387
- liquid/builtin/expressions/logical.py +0 -672
- liquid/builtin/expressions/loop.py +0 -275
- liquid/builtin/expressions/path.py +0 -163
- liquid/builtin/expressions/primitive.py +0 -417
- liquid/builtin/filters/__init__.py +0 -0
- liquid/builtin/filters/array.py +0 -329
- liquid/builtin/filters/extra.py +0 -83
- liquid/builtin/filters/math.py +0 -129
- liquid/builtin/filters/misc.py +0 -137
- liquid/builtin/filters/string.py +0 -416
- liquid/builtin/illegal.py +0 -28
- liquid/builtin/loaders/__init__.py +0 -0
- liquid/builtin/loaders/caching_file_system_loader.py +0 -61
- liquid/builtin/loaders/choice_loader.py +0 -94
- liquid/builtin/loaders/dict_loader.py +0 -64
- liquid/builtin/loaders/package_loader.py +0 -132
- liquid/builtin/output.py +0 -74
- liquid/builtin/tags/__init__.py +0 -0
- liquid/builtin/tags/assign_tag.py +0 -75
- liquid/builtin/tags/capture_tag.py +0 -98
- liquid/builtin/tags/case_tag.py +0 -287
- liquid/builtin/tags/comment_tag.py +0 -77
- liquid/builtin/tags/cycle_tag.py +0 -132
- liquid/builtin/tags/decrement_tag.py +0 -59
- liquid/builtin/tags/doc_tag.py +0 -68
- liquid/builtin/tags/echo_tag.py +0 -45
- liquid/builtin/tags/for_tag.py +0 -337
- liquid/builtin/tags/if_tag.py +0 -209
- liquid/builtin/tags/ifchanged_tag.py +0 -94
- liquid/builtin/tags/include_tag.py +0 -251
- liquid/builtin/tags/increment_tag.py +0 -60
- liquid/builtin/tags/inline_comment_tag.py +0 -47
- liquid/builtin/tags/liquid_tag.py +0 -183
- liquid/builtin/tags/render_tag.py +0 -371
- liquid/builtin/tags/tablerow_tag.py +0 -320
- liquid/builtin/tags/unless_tag.py +0 -218
- liquid/context.py +0 -615
- liquid/expression.py +0 -41
- liquid/extra/__init__.py +0 -98
- liquid/extra/filters/__init__.py +0 -33
- liquid/extra/filters/_json.py +0 -33
- liquid/extra/filters/array.py +0 -60
- liquid/extra/filters/babel.py +0 -552
- liquid/extra/filters/html.py +0 -32
- liquid/extra/filters/translate.py +0 -448
- liquid/extra/tags/__init__.py +0 -17
- liquid/extra/tags/_with.py +0 -80
- liquid/extra/tags/extends_tag.py +0 -576
- liquid/extra/tags/macro_tag.py +0 -270
- liquid/extra/tags/snippet_tag.py +0 -107
- liquid/extra/tags/translate_tag.py +0 -388
- liquid/filter.py +0 -230
- liquid/future/__init__.py +0 -3
- liquid/future/environment.py +0 -30
- liquid/future/filters/__init__.py +0 -1
- liquid/future/tags/__init__.py +0 -1
- liquid/lex.py +0 -260
- liquid/limits.py +0 -66
- liquid/loader.py +0 -141
- liquid/messages.py +0 -357
- liquid/mode.py +0 -12
- liquid/output.py +0 -35
- liquid/parser.py +0 -119
- liquid/span.py +0 -35
- liquid/static_analysis.py +0 -443
- liquid/stream.py +0 -148
- liquid/stringify.py +0 -31
- liquid/tag.py +0 -47
- liquid/template.py +0 -658
- liquid/token.py +0 -145
- liquid/undefined.py +0 -218
- liquid/utils/__init__.py +0 -15
- liquid/utils/html.py +0 -57
- liquid/utils/text.py +0 -28
- python_liquid-2.3.6.dist-info/RECORD +0 -96
liquid/__about__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.0.0"
|
liquid/__init__.py
CHANGED
|
@@ -1,242 +1,216 @@
|
|
|
1
|
-
from
|
|
2
|
-
from typing import
|
|
3
|
-
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
from .
|
|
15
|
-
|
|
16
|
-
from .
|
|
17
|
-
from .
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
20
|
-
from .
|
|
21
|
-
from .
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
from collections.abc import Iterator, Mapping
|
|
2
|
+
from typing import Any, TextIO
|
|
3
|
+
|
|
4
|
+
from ._base_tag import AbstractTag
|
|
5
|
+
from ._context import RenderContext
|
|
6
|
+
from ._drop import (
|
|
7
|
+
ContextHint,
|
|
8
|
+
LiquidAsyncIterable,
|
|
9
|
+
LiquidAsyncObject,
|
|
10
|
+
LiquidIterable,
|
|
11
|
+
LiquidObject,
|
|
12
|
+
LiquidPrimitive,
|
|
13
|
+
)
|
|
14
|
+
from ._filter import Filter, FilterContext
|
|
15
|
+
from ._io import StringBuffer
|
|
16
|
+
from ._lax_parser_mixin import LaxParserMixin
|
|
17
|
+
from ._lexer import Lexer
|
|
18
|
+
from ._lexer_extended import ExtendedLexer
|
|
19
|
+
from ._lexer_legacy import LegacyLexer
|
|
20
|
+
from ._loader import Loader, TemplateSource
|
|
21
|
+
from ._markup import (
|
|
22
|
+
Block,
|
|
23
|
+
Expression,
|
|
24
|
+
Markup,
|
|
25
|
+
Node,
|
|
26
|
+
Partial,
|
|
27
|
+
Scope,
|
|
28
|
+
Tag,
|
|
29
|
+
render_block,
|
|
30
|
+
render_block_async,
|
|
31
|
+
)
|
|
32
|
+
from ._messages import (
|
|
33
|
+
MessageTuple,
|
|
34
|
+
Translations,
|
|
35
|
+
extract_from_template,
|
|
36
|
+
extract_from_templates,
|
|
37
|
+
)
|
|
38
|
+
from ._nothing import NOTHING
|
|
39
|
+
from ._parser import Parser
|
|
40
|
+
from ._parser_extended import ExtendedParser
|
|
41
|
+
from ._parser_legacy import LegacyParser
|
|
42
|
+
from ._resource_limits import ResourceLimits
|
|
43
|
+
from ._slice import slice_range, slice_sequence
|
|
44
|
+
from ._static_analysis import Segments, TemplateAnalysis
|
|
45
|
+
from ._template import Template
|
|
46
|
+
from .drops import (
|
|
47
|
+
AsyncIterableDrop,
|
|
48
|
+
FalsyStrictUndefined,
|
|
49
|
+
IterableDrop,
|
|
50
|
+
StrictUndefined,
|
|
51
|
+
Undefined,
|
|
52
|
+
)
|
|
25
53
|
from .environment import Environment
|
|
26
|
-
from .
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
from .
|
|
37
|
-
from .builtin import CachingFileSystemLoader
|
|
38
|
-
from .builtin import FileSystemLoader
|
|
39
|
-
from .builtin import PackageLoader
|
|
40
|
-
from .builtin import CachingLoaderMixin
|
|
41
|
-
from .loader import BaseLoader
|
|
42
|
-
|
|
43
|
-
from .ast import Node
|
|
44
|
-
from .ast import BlockNode
|
|
45
|
-
from .ast import ConditionalBlockNode
|
|
46
|
-
|
|
47
|
-
from .analyze_tags import TagAnalysis
|
|
48
|
-
from .analyze_tags import DEFAULT_INNER_TAG_MAP
|
|
49
|
-
|
|
50
|
-
from .messages import MessageTuple
|
|
51
|
-
from .messages import Translations
|
|
52
|
-
from .messages import extract_from_template
|
|
53
|
-
|
|
54
|
-
from .stream import TokenStream
|
|
55
|
-
from .tag import Tag
|
|
56
|
-
|
|
57
|
-
from . import future
|
|
58
|
-
|
|
59
|
-
__version__ = "2.3.6"
|
|
54
|
+
from .loaders import (
|
|
55
|
+
CachingChoiceLoader,
|
|
56
|
+
CachingDictLoader,
|
|
57
|
+
CachingFileSystemLoader,
|
|
58
|
+
CachingLoaderMixin,
|
|
59
|
+
ChoiceLoader,
|
|
60
|
+
DictLoader,
|
|
61
|
+
FileSystemLoader,
|
|
62
|
+
PackageLoader,
|
|
63
|
+
)
|
|
64
|
+
from .tokens import TOKEN_NAMES, Token, TokenKind, span, token_value
|
|
60
65
|
|
|
61
66
|
__all__ = (
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
67
|
+
"NOTHING",
|
|
68
|
+
"TOKEN_NAMES",
|
|
69
|
+
"AbstractTag",
|
|
70
|
+
"AsyncIterableDrop",
|
|
71
|
+
"Block",
|
|
65
72
|
"CachingChoiceLoader",
|
|
66
73
|
"CachingDictLoader",
|
|
67
74
|
"CachingFileSystemLoader",
|
|
68
75
|
"CachingLoaderMixin",
|
|
69
76
|
"ChoiceLoader",
|
|
70
|
-
"
|
|
71
|
-
"DebugUndefined",
|
|
72
|
-
"DEFAULT_INNER_TAG_MAP",
|
|
77
|
+
"ContextHint",
|
|
73
78
|
"DictLoader",
|
|
74
79
|
"Environment",
|
|
75
|
-
"escape",
|
|
76
80
|
"Expression",
|
|
77
|
-
"
|
|
81
|
+
"ExtendedLexer",
|
|
82
|
+
"ExtendedParser",
|
|
78
83
|
"FalsyStrictUndefined",
|
|
79
84
|
"FileSystemLoader",
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
85
|
+
"Filter",
|
|
86
|
+
"FilterContext",
|
|
87
|
+
"IterableDrop",
|
|
88
|
+
"LaxExtendedParser",
|
|
89
|
+
"LaxLegacyParser",
|
|
90
|
+
"LaxParserMixin",
|
|
91
|
+
"LegacyLexer",
|
|
92
|
+
"LegacyParser",
|
|
93
|
+
"Lexer",
|
|
94
|
+
"LiquidAsyncIterable",
|
|
95
|
+
"LiquidAsyncObject",
|
|
96
|
+
"LiquidIterable",
|
|
97
|
+
"LiquidObject",
|
|
98
|
+
"LiquidPrimitive",
|
|
99
|
+
"Loader",
|
|
87
100
|
"Markup",
|
|
88
|
-
"MessageTuple",
|
|
89
|
-
"Mode",
|
|
90
101
|
"Node",
|
|
91
102
|
"PackageLoader",
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"render",
|
|
103
|
+
"Parser",
|
|
104
|
+
"Partial",
|
|
95
105
|
"RenderContext",
|
|
96
|
-
"
|
|
97
|
-
"
|
|
106
|
+
"ResourceLimits",
|
|
107
|
+
"Scope",
|
|
108
|
+
"Segments",
|
|
98
109
|
"StrictUndefined",
|
|
110
|
+
"StringBuffer",
|
|
99
111
|
"Tag",
|
|
100
|
-
"TagAnalysis",
|
|
101
112
|
"Template",
|
|
113
|
+
"TemplateAnalysis",
|
|
114
|
+
"TemplateSource",
|
|
102
115
|
"Token",
|
|
103
|
-
"
|
|
116
|
+
"TokenKind",
|
|
104
117
|
"Translations",
|
|
105
118
|
"Undefined",
|
|
119
|
+
"extract_from_templates",
|
|
120
|
+
"render_block",
|
|
121
|
+
"render_block_async",
|
|
122
|
+
"slice_range",
|
|
123
|
+
"slice_sequence",
|
|
124
|
+
"span",
|
|
125
|
+
"token_value",
|
|
106
126
|
)
|
|
107
127
|
|
|
128
|
+
|
|
108
129
|
DEFAULT_ENVIRONMENT = Environment()
|
|
109
130
|
|
|
110
131
|
|
|
111
|
-
def parse(
|
|
112
|
-
|
|
113
|
-
|
|
132
|
+
def parse(
|
|
133
|
+
source: str,
|
|
134
|
+
*,
|
|
135
|
+
name: str = "",
|
|
136
|
+
globals: Mapping[str, Any] | None = None,
|
|
137
|
+
) -> Template:
|
|
138
|
+
"""Parse template source code `source` using the default Liquid environment.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
source
|
|
143
|
+
Template source code.
|
|
144
|
+
name
|
|
145
|
+
A name for the template that will appear in error messages.
|
|
146
|
+
globals
|
|
147
|
+
Variables to pin to the resulting template.
|
|
148
|
+
"""
|
|
149
|
+
return DEFAULT_ENVIRONMENT.parse(source, name=name, globals=globals)
|
|
114
150
|
|
|
115
151
|
|
|
116
|
-
def render(source: str,
|
|
117
|
-
"""Parse and render source
|
|
118
|
-
return DEFAULT_ENVIRONMENT.render(source, **data)
|
|
152
|
+
def render(source: str, data: Mapping[str, Any] | None = None) -> str:
|
|
153
|
+
"""Parse and render `source` with variables from `data` using the default environment.
|
|
119
154
|
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
source
|
|
158
|
+
Template source code.
|
|
159
|
+
data
|
|
160
|
+
Template variables.
|
|
161
|
+
"""
|
|
162
|
+
return DEFAULT_ENVIRONMENT.render(source, data)
|
|
120
163
|
|
|
121
|
-
async def render_async(source: str, **data: object) -> str:
|
|
122
|
-
"""Parse and render source text using the default environment."""
|
|
123
|
-
return await DEFAULT_ENVIRONMENT.render_async(source, **data)
|
|
124
164
|
|
|
165
|
+
async def render_async(source: str, data: Mapping[str, Any] | None = None) -> str:
|
|
166
|
+
"""Parse and render `source` asynchronously with variables from `data` using the
|
|
167
|
+
default environment.
|
|
125
168
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
namespace_key: str = "",
|
|
133
|
-
cache_size: int = 300,
|
|
134
|
-
) -> BaseLoader:
|
|
135
|
-
"""A _file system_ template loader factory.
|
|
136
|
-
|
|
137
|
-
Returns one of `CachingFileSystemLoader` or `FileSystemLoader` depending in
|
|
138
|
-
the given arguments.
|
|
139
|
-
|
|
140
|
-
A `CachingFileSystemLoader` is returned if _cache_size_ is greater than 0.
|
|
141
|
-
Otherwise a `FileExtensionLoader` is returned if _ext_ is not empty.
|
|
142
|
-
If _ext_ is empty, a `FileSystemLoader` is returned.
|
|
143
|
-
|
|
144
|
-
_auto_reload_ and _namespace_key_ are ignored if _cache_key_ is less than 1.
|
|
145
|
-
|
|
146
|
-
Args:
|
|
147
|
-
search_path: One or more paths to search.
|
|
148
|
-
encoding: Open template files with the given encoding.
|
|
149
|
-
ext: A default file extension. Should include a leading period.
|
|
150
|
-
auto_reload: If `True`, automatically reload a cached template if it has been
|
|
151
|
-
updated.
|
|
152
|
-
namespace_key: The name of a global render context variable or loader keyword
|
|
153
|
-
argument that resolves to the current loader "namespace" or "scope".
|
|
154
|
-
|
|
155
|
-
If you're developing a multi-user application, a good namespace might be
|
|
156
|
-
`uid`, where `uid` is a unique identifier for a user and templates are
|
|
157
|
-
arranged in folders named for each `uid` inside the search path.
|
|
158
|
-
cache_size: The maximum number of templates to hold in the cache before removing
|
|
159
|
-
the least recently used template.
|
|
160
|
-
|
|
161
|
-
_New in version 1.12.0_
|
|
169
|
+
Parameters
|
|
170
|
+
----------
|
|
171
|
+
source
|
|
172
|
+
Template source code.
|
|
173
|
+
data
|
|
174
|
+
Template variables.
|
|
162
175
|
"""
|
|
163
|
-
|
|
164
|
-
return CachingFileSystemLoader(
|
|
165
|
-
search_path=search_path,
|
|
166
|
-
encoding=encoding,
|
|
167
|
-
ext=ext,
|
|
168
|
-
auto_reload=auto_reload,
|
|
169
|
-
namespace_key=namespace_key,
|
|
170
|
-
capacity=cache_size,
|
|
171
|
-
)
|
|
176
|
+
return await DEFAULT_ENVIRONMENT.render_async(source, data)
|
|
172
177
|
|
|
173
|
-
return FileSystemLoader(search_path=search_path, encoding=encoding, ext=ext)
|
|
174
178
|
|
|
179
|
+
class LaxLegacyParser(LaxParserMixin, LegacyParser):
|
|
180
|
+
"""A legacy parser that suppresses Liquid syntax errors.
|
|
175
181
|
|
|
176
|
-
|
|
177
|
-
loaders: list[BaseLoader],
|
|
178
|
-
*,
|
|
179
|
-
auto_reload: bool = True,
|
|
180
|
-
namespace_key: str = "",
|
|
181
|
-
cache_size: int = 300,
|
|
182
|
-
) -> BaseLoader:
|
|
183
|
-
"""A _choice loader_ factory.
|
|
184
|
-
|
|
185
|
-
Returns one of `CachingChoiceLoader` or `ChoiceLoader` depending on the
|
|
186
|
-
given arguments.
|
|
187
|
-
|
|
188
|
-
A `CachingChoiceLoader` is returned if _cache_size_ > 0, otherwise a
|
|
189
|
-
`ChoiceLoader` is returned.
|
|
190
|
-
|
|
191
|
-
_auto_reload_ and _namespace_key_ are ignored if _cache_key_ is less than 1.
|
|
192
|
-
|
|
193
|
-
Args:
|
|
194
|
-
loaders: A list of loaders implementing `liquid.loaders.BaseLoader`.
|
|
195
|
-
auto_reload: If `True`, automatically reload a cached template if it
|
|
196
|
-
has been updated.
|
|
197
|
-
namespace_key: The name of a global render context variable or loader
|
|
198
|
-
keyword argument that resolves to the current loader "namespace" or
|
|
199
|
-
"scope".
|
|
200
|
-
cache_size: The maximum number of templates to hold in the cache before
|
|
201
|
-
removing the least recently used template.
|
|
202
|
-
|
|
203
|
-
_New in version 1.12.0_
|
|
182
|
+
Use ``Template.errors()`` to get a list of available ``LiquidSyntaxError`` instances.
|
|
204
183
|
"""
|
|
205
|
-
if cache_size > 0:
|
|
206
|
-
return CachingChoiceLoader(
|
|
207
|
-
loaders=loaders,
|
|
208
|
-
auto_reload=auto_reload,
|
|
209
|
-
namespace_key=namespace_key,
|
|
210
|
-
capacity=cache_size,
|
|
211
|
-
)
|
|
212
184
|
|
|
213
|
-
|
|
185
|
+
|
|
186
|
+
class LaxExtendedParser(LaxParserMixin, ExtendedParser):
|
|
187
|
+
"""An extended parser that suppresses Liquid syntax errors.
|
|
188
|
+
|
|
189
|
+
Use ``Template.errors()`` to get a list of available ``LiquidSyntaxError`` instances.
|
|
190
|
+
"""
|
|
214
191
|
|
|
215
192
|
|
|
216
193
|
def extract_liquid(
|
|
217
194
|
fileobj: TextIO,
|
|
218
195
|
keywords: list[str],
|
|
219
|
-
comment_tags:
|
|
220
|
-
options:
|
|
196
|
+
comment_tags: list[str] | None = None,
|
|
197
|
+
options: Mapping[str, Any] | None = None,
|
|
221
198
|
) -> Iterator[MessageTuple]:
|
|
222
199
|
"""A babel compatible translation message extraction method for Liquid templates.
|
|
223
200
|
|
|
224
201
|
See https://babel.pocoo.org/en/latest/messages.html
|
|
225
202
|
|
|
226
|
-
Keywords are the names of Liquid filters or tags operating on translatable
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
203
|
+
Keywords are the names of Liquid filters or tags operating on translatable strings.
|
|
204
|
+
For a filter to contribute to message extraction, it must also appear as a child of
|
|
205
|
+
a `FilteredExpression` and be a `TranslatableFilter`. Similarly, tags must produce a
|
|
206
|
+
node that is a `TranslatableTag`.
|
|
230
207
|
|
|
231
|
-
Where a Liquid comment contains a prefix in `comment_tags`, the comment
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
supported.
|
|
208
|
+
Where a Liquid comment contains a prefix in `comment_tags`, the comment will be
|
|
209
|
+
attached to the translatable filter or tag immediately following the comment. Python
|
|
210
|
+
Liquid's non-standard shorthand comments are not supported.
|
|
235
211
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
to extract messages from an existing template bound to an existing
|
|
239
|
-
environment.
|
|
212
|
+
Use ``extract_from_template`` to extract messages from an existing template bound to
|
|
213
|
+
an existing environment.
|
|
240
214
|
"""
|
|
241
215
|
template = Environment(extra=True).parse(fileobj.read())
|
|
242
216
|
return extract_from_template(
|
liquid/_base_tag.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from ._context import RenderContext
|
|
8
|
+
from ._io import StringBuffer
|
|
9
|
+
from ._markup import Expression, Markup, Partial
|
|
10
|
+
from ._parser import Parser
|
|
11
|
+
from .expressions import Name
|
|
12
|
+
from .tokens import Token
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AbstractTag(ABC):
|
|
16
|
+
"""An abstract class for implementing custom tags.
|
|
17
|
+
|
|
18
|
+
It is not necessary to inherit from `AbstractTag` when implementing custom tags, but
|
|
19
|
+
it can be convenient if you're not interested in methods supporting static template
|
|
20
|
+
analysis, saving you from writing several empty methods.
|
|
21
|
+
|
|
22
|
+
Internally we use the `Markup` and `Tag` protocols, without a required base class.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def parse(cls, token: Token, parser: Parser) -> Markup:
|
|
28
|
+
"""Parse tokens or text from `parser` into a markup node."""
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def render(self, context: RenderContext, buffer: StringBuffer) -> None:
|
|
32
|
+
"""Render this node to `buffer` using data from `context`."""
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
async def render_async(self, context: RenderContext, buffer: StringBuffer) -> None:
|
|
36
|
+
"""Render this node to `buffer` asynchronously using data from `context`."""
|
|
37
|
+
|
|
38
|
+
def children(self) -> list[Markup]:
|
|
39
|
+
"""Returns markup nodes that are direct children of this node in the syntax tree.
|
|
40
|
+
|
|
41
|
+
This is used to traverse template syntax trees during static analysis.
|
|
42
|
+
"""
|
|
43
|
+
return []
|
|
44
|
+
|
|
45
|
+
def expressions(self) -> list[Expression]:
|
|
46
|
+
"""Return expression owned by this node."""
|
|
47
|
+
return []
|
|
48
|
+
|
|
49
|
+
def block_scope(self) -> list[Name]:
|
|
50
|
+
"""Return variable names that are in scope for the duration of this node's block.
|
|
51
|
+
|
|
52
|
+
This is used during static analysis to isolate and report global variables.
|
|
53
|
+
"""
|
|
54
|
+
return []
|
|
55
|
+
|
|
56
|
+
def template_scope(self) -> list[Name]:
|
|
57
|
+
"""Return variable names that this tag adds to the template scope."""
|
|
58
|
+
return []
|
|
59
|
+
|
|
60
|
+
def partials(self, context: RenderContext) -> list[Partial]:
|
|
61
|
+
"""Return meta data about partial templates rendered from this node."""
|
|
62
|
+
return []
|
|
63
|
+
|
|
64
|
+
async def partials_async(self, context: RenderContext) -> list[Partial]:
|
|
65
|
+
"""Return meta data about partial templates rendered from this node."""
|
|
66
|
+
return []
|
|
@@ -3,26 +3,29 @@
|
|
|
3
3
|
Based on "A greatly simplified read-only version of Chainmap" by Raymond Hettinger.
|
|
4
4
|
https://code.activestate.com/recipes/305268/
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
from collections import deque
|
|
8
|
+
from collections.abc import Iterator, Mapping
|
|
7
9
|
from itertools import chain
|
|
8
|
-
|
|
9
|
-
from
|
|
10
|
-
from typing import Mapping
|
|
10
|
+
|
|
11
|
+
from ._missing import MISSING
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class ReadOnlyChainMap(Mapping[str, object]):
|
|
14
|
-
"""Combine multiple mappings for sequential lookup.
|
|
15
|
+
"""Combine multiple mappings for sequential lookup.
|
|
16
|
+
|
|
17
|
+
This chain map never raises a KeyError. It returns the MISSING sentinel
|
|
18
|
+
if a key does not exist in the chain.
|
|
19
|
+
"""
|
|
15
20
|
|
|
16
21
|
def __init__(self, *maps: Mapping[str, object]):
|
|
17
22
|
self._maps = deque(maps)
|
|
18
23
|
|
|
19
24
|
def __getitem__(self, key: str) -> object:
|
|
20
25
|
for mapping in self._maps:
|
|
21
|
-
|
|
26
|
+
if key in mapping:
|
|
22
27
|
return mapping[key]
|
|
23
|
-
|
|
24
|
-
pass
|
|
25
|
-
raise KeyError(key)
|
|
28
|
+
return MISSING
|
|
26
29
|
|
|
27
30
|
def __iter__(self) -> Iterator[str]:
|
|
28
31
|
return chain(*self._maps)
|
|
@@ -30,21 +33,17 @@ class ReadOnlyChainMap(Mapping[str, object]):
|
|
|
30
33
|
def __len__(self) -> int:
|
|
31
34
|
return sum(len(_map) for _map in self._maps)
|
|
32
35
|
|
|
36
|
+
def __contains__(self, key: object) -> bool:
|
|
37
|
+
return any(key in mapping for mapping in self._maps)
|
|
38
|
+
|
|
33
39
|
def size(self) -> int:
|
|
34
|
-
"""Return the number of maps in the chain."""
|
|
35
40
|
return len(self._maps)
|
|
36
41
|
|
|
37
|
-
def get(self, key: str, default: object =
|
|
38
|
-
|
|
39
|
-
try:
|
|
40
|
-
return self[key]
|
|
41
|
-
except KeyError:
|
|
42
|
-
return default
|
|
42
|
+
def get(self, key: str, default: object = MISSING) -> object:
|
|
43
|
+
return self[key]
|
|
43
44
|
|
|
44
|
-
def push(self, namespace: Mapping[
|
|
45
|
-
"""Add a mapping to the front of the chain map."""
|
|
45
|
+
def push(self, namespace: Mapping[str, object]) -> None:
|
|
46
46
|
self._maps.appendleft(namespace)
|
|
47
47
|
|
|
48
|
-
def pop(self) -> Mapping[
|
|
49
|
-
"""Remove a mapping from the front of the chain map."""
|
|
48
|
+
def pop(self) -> Mapping[str, object]:
|
|
50
49
|
return self._maps.popleft()
|