mapres 3.dev19__py3-none-any.whl → 3.dev20__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.
- mapres/datamap.py +2 -4
- mapres/evaluator.py +87 -3
- {mapres-3.dev19.dist-info → mapres-3.dev20.dist-info}/METADATA +1 -1
- {mapres-3.dev19.dist-info → mapres-3.dev20.dist-info}/RECORD +7 -7
- {mapres-3.dev19.dist-info → mapres-3.dev20.dist-info}/WHEEL +0 -0
- {mapres-3.dev19.dist-info → mapres-3.dev20.dist-info}/licenses/LICENSE +0 -0
- {mapres-3.dev19.dist-info → mapres-3.dev20.dist-info}/top_level.txt +0 -0
mapres/datamap.py
CHANGED
|
@@ -95,14 +95,12 @@ class DataMap:
|
|
|
95
95
|
return out
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def datamap(_cls=None, *, syntax=None, mode=None, recursive=None,
|
|
99
|
-
missing_key=None, ignore_delimiters=None):
|
|
98
|
+
def datamap(_cls=None, *, syntax=None, mode=None, recursive=None, missing_key=None, ignore_delimiters=None):
|
|
100
99
|
|
|
101
100
|
def wrap(cls):
|
|
102
101
|
cls.__syntax__ = syntax
|
|
103
102
|
cls.__mode__ = mode
|
|
104
|
-
cls.__recursive__ = recursive
|
|
105
|
-
# cls.__recursive__ = recursive
|
|
103
|
+
cls.__recursive__ = recursive
|
|
106
104
|
cls.__missing_key__ = missing_key or 'error'
|
|
107
105
|
cls.__ignore_delimiters__ = ignore_delimiters or False
|
|
108
106
|
|
mapres/evaluator.py
CHANGED
|
@@ -41,13 +41,32 @@ class Evaluator:
|
|
|
41
41
|
parts.append(self._eval(child))
|
|
42
42
|
out = ''.join(parts)
|
|
43
43
|
|
|
44
|
-
# recursion
|
|
44
|
+
# recursion over full template output
|
|
45
|
+
if self._has_recursive_maps():
|
|
46
|
+
seen = set()
|
|
47
|
+
depth = 0
|
|
48
|
+
max_depth = self._get_max_depth()
|
|
49
|
+
|
|
50
|
+
while depth < max_depth:
|
|
51
|
+
new_out = self._re_resolve(out)
|
|
52
|
+
if new_out == out:
|
|
53
|
+
break
|
|
54
|
+
if new_out in seen:
|
|
55
|
+
raise EvaluationError('Cycle detected in template recursion')
|
|
56
|
+
seen.add(new_out)
|
|
57
|
+
out = new_out
|
|
58
|
+
depth += 1
|
|
59
|
+
|
|
45
60
|
return out
|
|
46
61
|
|
|
47
62
|
# identifier
|
|
48
63
|
def _eval_ident(self, node: IdentNode):
|
|
49
64
|
name = node.name
|
|
50
65
|
|
|
66
|
+
# ignore_delimiters: treat token as literal for this syntax
|
|
67
|
+
if self._syntax_ignores_delimiters(node.syntax):
|
|
68
|
+
return self._literal_from_syntax(name, node.syntax)
|
|
69
|
+
|
|
51
70
|
# cycle detection
|
|
52
71
|
if name in self._seen:
|
|
53
72
|
raise EvaluationError(f"Cycle detected in identifier '{name}'")
|
|
@@ -79,6 +98,11 @@ class Evaluator:
|
|
|
79
98
|
def _eval_call(self, node: CallNode):
|
|
80
99
|
outer = node.name
|
|
81
100
|
|
|
101
|
+
# ignore_delimiters: treat call token as literal
|
|
102
|
+
if self._syntax_ignores_delimiters(node.syntax):
|
|
103
|
+
arg_text = self._eval(node.arg)
|
|
104
|
+
return self._literal_from_syntax(outer, node.syntax, is_call=True, arg_text=arg_text)
|
|
105
|
+
|
|
82
106
|
if outer in self._seen:
|
|
83
107
|
raise EvaluationError(f"Cycle detected in call '{outer}'")
|
|
84
108
|
self._seen.add(outer)
|
|
@@ -124,14 +148,74 @@ class Evaluator:
|
|
|
124
148
|
cur = cur[p]
|
|
125
149
|
return cur
|
|
126
150
|
|
|
127
|
-
# recursion helpers now effectively disabled
|
|
128
151
|
def _has_recursive_maps(self):
|
|
152
|
+
for m in self.layerstack.all_maps():
|
|
153
|
+
if getattr(m, '__recursive__', False) is True:
|
|
154
|
+
return True
|
|
129
155
|
return False
|
|
130
156
|
|
|
131
157
|
def _get_max_depth(self):
|
|
132
|
-
|
|
158
|
+
depths = [
|
|
159
|
+
getattr(m, '__max_depth__', 10)
|
|
160
|
+
for m in self.layerstack.all_maps()
|
|
161
|
+
if getattr(m, '__recursive__', False) is True
|
|
162
|
+
]
|
|
163
|
+
return max(depths) if depths else 0
|
|
133
164
|
|
|
134
165
|
def _re_resolve(self, text: str) -> str:
|
|
135
166
|
tokens = Tokenizer(text).tokenize()
|
|
136
167
|
ast = Parser(tokens).parse()
|
|
137
168
|
return self.evaluate(ast)
|
|
169
|
+
|
|
170
|
+
def _syntax_ignores_delimiters(self, syntax_name: str) -> bool:
|
|
171
|
+
for m in self.layerstack.all_maps():
|
|
172
|
+
if getattr(m, '__syntax__', None) == syntax_name:
|
|
173
|
+
if getattr(m, '__ignore_delimiters__', False):
|
|
174
|
+
return True
|
|
175
|
+
return False
|
|
176
|
+
|
|
177
|
+
def _literal_from_syntax(self, name: str, syntax_name: str, is_call: bool = False, arg_text: str | None = None) -> str:
|
|
178
|
+
if not is_call:
|
|
179
|
+
if syntax_name == 'colons':
|
|
180
|
+
return f':{name}:'
|
|
181
|
+
if syntax_name == 'braces':
|
|
182
|
+
return f'{{{{{name}}}}}'
|
|
183
|
+
if syntax_name == 'dollars':
|
|
184
|
+
return f'${{{name}}}'
|
|
185
|
+
if syntax_name == 'angles':
|
|
186
|
+
return f'<{name}>'
|
|
187
|
+
if syntax_name == 'pipes':
|
|
188
|
+
return f'|{name}|'
|
|
189
|
+
if syntax_name == 'percents':
|
|
190
|
+
return f'%{name}%'
|
|
191
|
+
if syntax_name == 'paren_dollars':
|
|
192
|
+
return f'$({name})'
|
|
193
|
+
if syntax_name == 'at_tags':
|
|
194
|
+
return f'@{name}@'
|
|
195
|
+
if syntax_name == 'hash_tags':
|
|
196
|
+
return f'#{name}#'
|
|
197
|
+
return name
|
|
198
|
+
|
|
199
|
+
# call literal: syntax-specific wrapping of name(arg_text)
|
|
200
|
+
arg = arg_text or ''
|
|
201
|
+
inner = f'{name}({arg})'
|
|
202
|
+
|
|
203
|
+
if syntax_name == 'colons':
|
|
204
|
+
return f':{inner}:'
|
|
205
|
+
if syntax_name == 'braces':
|
|
206
|
+
return f'{{{{{inner}}}}}'
|
|
207
|
+
if syntax_name == 'dollars':
|
|
208
|
+
return f'${{{inner}}}'
|
|
209
|
+
if syntax_name == 'angles':
|
|
210
|
+
return f'<{inner}>'
|
|
211
|
+
if syntax_name == 'pipes':
|
|
212
|
+
return f'|{inner}|'
|
|
213
|
+
if syntax_name == 'percents':
|
|
214
|
+
return f'%{inner}%'
|
|
215
|
+
if syntax_name == 'paren_dollars':
|
|
216
|
+
return f'$({inner})'
|
|
217
|
+
if syntax_name == 'at_tags':
|
|
218
|
+
return f'@{inner}@'
|
|
219
|
+
if syntax_name == 'hash_tags':
|
|
220
|
+
return f'#{inner}#'
|
|
221
|
+
return inner
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
mapres/__init__.py,sha256=t23ofM-wzpPByYi1rEQonxyU1yyza4ZzwwHDZUa5QqA,1010
|
|
2
2
|
mapres/ast.py,sha256=6PcMkwtNHYD8xEkdyzDgn_mRTj1ZaWSyuHZK3BtXiuo,427
|
|
3
3
|
mapres/cache.py,sha256=hbvsoc6Qw3RhWAEfOOpKHtC7i9EomoUgWzyd4dnH71w,333
|
|
4
|
-
mapres/datamap.py,sha256=
|
|
5
|
-
mapres/evaluator.py,sha256=
|
|
4
|
+
mapres/datamap.py,sha256=lqz781REOWSt0YwliSrKA1gDxrLeNgN--wwtyyl8Cp8,5244
|
|
5
|
+
mapres/evaluator.py,sha256=glpB4wzugtst4QtkQyAHwUXliHs13B1P4h4VjRAdgp0,6978
|
|
6
6
|
mapres/exceptions.py,sha256=D2XKnrMkZDyUXQt2PmaKbj08FObWU00yXKGHwNpjvww,222
|
|
7
7
|
mapres/layers.py,sha256=sFc1eUOBg2BoB2cBXIleq8RMYcg5GZpUoCnGh-uKN6U,1380
|
|
8
8
|
mapres/parser.py,sha256=8XLCzYosvh81bN-Jddc1AM4w0X7bsHnBzmA8sq5_72w,4018
|
|
@@ -11,8 +11,8 @@ mapres/tokenizer.py,sha256=js0S1s8MkltdQoH5V1cLjdY0fFqZoGqmtP_OhEJEM6M,6539
|
|
|
11
11
|
mapres/maps/__init__.py,sha256=lIRRfem1Fw4iynuwUQ7BY5qrC4fbJKxqLivao2_Dtm4,239
|
|
12
12
|
mapres/maps/color.py,sha256=noRTGFNo9xLl5YEhX0tttV6i_oDAiptXmRVnkr5EzwM,1348
|
|
13
13
|
mapres/maps/time.py,sha256=TyncycYoIGVZWps32qWlFy2a2hTayvZWVHu9uh2nid8,2050
|
|
14
|
-
mapres-3.
|
|
15
|
-
mapres-3.
|
|
16
|
-
mapres-3.
|
|
17
|
-
mapres-3.
|
|
18
|
-
mapres-3.
|
|
14
|
+
mapres-3.dev20.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
15
|
+
mapres-3.dev20.dist-info/METADATA,sha256=aOvYC-_w1Kk_sBwqdIpEfEwTamgHFHepWYf0uDGo_4E,1476
|
|
16
|
+
mapres-3.dev20.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
17
|
+
mapres-3.dev20.dist-info/top_level.txt,sha256=5LMVQqJdtyjxfzv7wJBOZ-360m0Yc79w_-Y7s3n6cTw,7
|
|
18
|
+
mapres-3.dev20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|