mapres 3.dev20__py3-none-any.whl → 3.dev21__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 CHANGED
@@ -1,4 +1,3 @@
1
- import re
2
1
  from dataclasses import dataclass, fields, is_dataclass
3
2
 
4
3
  # syntax identifiers
@@ -30,15 +29,13 @@ class DataMap:
30
29
 
31
30
  Mode metadata (__mode__) controls behavior:
32
31
  - None: plain static map
33
- - "dynamic": values may be provided by callables/providers
34
- - "config": config-style maps (no dynamic evaluation)
35
- - "callable": map exposes callable methods for nested calls
32
+ - 'dynamic': values may be provided by callables/providers
33
+ - 'config': config-style maps (no dynamic evaluation)
34
+ - 'callable': map exposes callable methods for nested calls
36
35
  '''
37
36
  __syntax__: str = None
38
- __mode__: str | None = None # "dynamic", "config", "callable", or None
39
- __recursive__: bool = False
37
+ __mode__: str | None = None # 'dynamic', 'config', 'callable', or None
40
38
  __missing_key__: str = 'error' # 'error', 'silent', 'placeholder'
41
- __ignore_delimiters__: bool = False
42
39
 
43
40
  def as_map(self):
44
41
  '''
@@ -95,14 +92,11 @@ class DataMap:
95
92
  return out
96
93
 
97
94
 
98
- def datamap(_cls=None, *, syntax=None, mode=None, recursive=None, missing_key=None, ignore_delimiters=None):
99
-
95
+ def datamap(_cls=None, *, syntax=None, mode=None, missing_key=None):
100
96
  def wrap(cls):
101
97
  cls.__syntax__ = syntax
102
98
  cls.__mode__ = mode
103
- cls.__recursive__ = recursive
104
99
  cls.__missing_key__ = missing_key or 'error'
105
- cls.__ignore_delimiters__ = ignore_delimiters or False
106
100
 
107
101
  namespace = dict(cls.__dict__)
108
102
  namespace['__dict__'] = {}
mapres/evaluator.py CHANGED
@@ -40,33 +40,12 @@ class Evaluator:
40
40
  for child in node.children:
41
41
  parts.append(self._eval(child))
42
42
  out = ''.join(parts)
43
-
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
-
60
43
  return out
61
44
 
62
45
  # identifier
63
46
  def _eval_ident(self, node: IdentNode):
64
47
  name = node.name
65
48
 
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
-
70
49
  # cycle detection
71
50
  if name in self._seen:
72
51
  raise EvaluationError(f"Cycle detected in identifier '{name}'")
@@ -98,11 +77,6 @@ class Evaluator:
98
77
  def _eval_call(self, node: CallNode):
99
78
  outer = node.name
100
79
 
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
-
106
80
  if outer in self._seen:
107
81
  raise EvaluationError(f"Cycle detected in call '{outer}'")
108
82
  self._seen.add(outer)
@@ -147,75 +121,3 @@ class Evaluator:
147
121
  return None
148
122
  cur = cur[p]
149
123
  return cur
150
-
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
155
- return False
156
-
157
- def _get_max_depth(self):
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
164
-
165
- def _re_resolve(self, text: str) -> str:
166
- tokens = Tokenizer(text).tokenize()
167
- ast = Parser(tokens).parse()
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mapres
3
- Version: 3.dev20
3
+ Version: 3.dev21
4
4
  Summary: A powerfull mapping utility
5
5
  Author: iFamished
6
6
  License: MIT
@@ -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=lqz781REOWSt0YwliSrKA1gDxrLeNgN--wwtyyl8Cp8,5244
5
- mapres/evaluator.py,sha256=glpB4wzugtst4QtkQyAHwUXliHs13B1P4h4VjRAdgp0,6978
4
+ mapres/datamap.py,sha256=R_5G_mE2OZpZ9YVL4tsNXAGS_SkQ6LKlx6Bz2Pr652Y,5021
5
+ mapres/evaluator.py,sha256=KNZ9aygOClM0kgnOf3anigsupLF175EJ07z_17ubZzU,3441
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.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,,
14
+ mapres-3.dev21.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
15
+ mapres-3.dev21.dist-info/METADATA,sha256=SrQXRywgQfa_pKRb7Egsdagr1pNwn2F9S3bBdpTWdVQ,1476
16
+ mapres-3.dev21.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
17
+ mapres-3.dev21.dist-info/top_level.txt,sha256=5LMVQqJdtyjxfzv7wJBOZ-360m0Yc79w_-Y7s3n6cTw,7
18
+ mapres-3.dev21.dist-info/RECORD,,