mapres 3.dev14__py3-none-any.whl → 3.dev16__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
@@ -35,7 +35,10 @@ class DataMap:
35
35
  - "callable": map exposes callable methods for nested calls
36
36
  '''
37
37
  __syntax__: str = None
38
- __mode__: str | None = None # "dynamic", "config", "callable", or None
38
+ __mode__: str | None = None # "dynamic", "config", "callable", or None
39
+ __recursive__: bool = False
40
+ __missing_key__: str = 'error' # 'error', 'silent', 'placeholder'
41
+ __ignore_delimiters__: bool = False
39
42
 
40
43
  def as_map(self):
41
44
  '''
@@ -47,8 +50,9 @@ class DataMap:
47
50
  '''
48
51
  result = {}
49
52
 
53
+ # dataclass fields
50
54
  for f in fields(self):
51
- if not f.init or f.name in ('__syntax__', '__mode__'):
55
+ if not f.init or f.name.startswith('__'):
52
56
  continue
53
57
 
54
58
  val = getattr(self, f.name)
@@ -63,24 +67,58 @@ class DataMap:
63
67
 
64
68
  result[f.name] = val
65
69
 
70
+ # nested classes > nested dicts
71
+ for name, obj in self.__class__.__dict__.items():
72
+ if name.startswith('__'):
73
+ continue
74
+ if isinstance(obj, type):
75
+ result[name] = self._class_to_dict(obj)
76
+
66
77
  return result
67
78
 
79
+ def _class_to_dict(self, cls):
80
+ out = {}
81
+
82
+ if is_dataclass(cls):
83
+ dummy = cls()
84
+ for f in fields(dummy):
85
+ if not f.init:
86
+ continue
87
+ out[f.name] = getattr(dummy, f.name)
88
+
89
+ for name, obj in cls.__dict__.items():
90
+ if name.startswith('__'):
91
+ continue
92
+ if isinstance(obj, type):
93
+ out[name] = self._class_to_dict(obj)
94
+
95
+ return out
96
+
97
+
98
+ def datamap(_cls=None, *, syntax=None, mode=None, recursive=None,
99
+ missing_key=None, ignore_delimiters=None):
68
100
 
69
- # main decorator factory
70
- def datamap(_cls=None, *, syntax=None, mode=None):
71
- '''@datamap decorator'''
72
101
  def wrap(cls):
73
102
  cls.__syntax__ = syntax
74
103
  cls.__mode__ = mode
104
+ cls.__recursive__ = recursive
105
+ cls.__missing_key__ = missing_key or 'error'
106
+ cls.__ignore_delimiters__ = ignore_delimiters or False
107
+
75
108
  namespace = dict(cls.__dict__)
76
109
  namespace['__dict__'] = {}
77
110
  rules_obj = namespace.get('rules', None)
111
+
78
112
  cls = type(cls.__name__, (DataMap,), namespace)
113
+
79
114
  if rules_obj is not None:
80
115
  setattr(cls, 'rules', rules_obj)
116
+
81
117
  return dataclass(frozen=False)(cls)
82
- if _cls is not None:
118
+
119
+ if _cls is not None and isinstance(_cls, type):
83
120
  return wrap(_cls)
121
+
84
122
  return wrap
85
123
 
86
124
 
@@ -98,30 +136,23 @@ class _SyntaxFactory:
98
136
  self._syntax = syntax_name
99
137
 
100
138
  def __call__(self, _cls=None, **kwargs):
101
- # Case 1: bare decorator: @datamap.angles
102
139
  if _cls is not None and isinstance(_cls, type):
103
140
  return datamap(_cls, syntax=self._syntax)
104
-
105
- # Case 2: decorator with args: @datamap.angles(mode='config')
106
141
  return datamap(syntax=self._syntax, **kwargs)
107
142
 
108
143
  @property
109
144
  def config(self):
110
- # Case 3: @datamap.angles.config
111
145
  return datamap(syntax=self._syntax, mode='config')
112
146
 
113
147
  @property
114
148
  def dynamic(self):
115
- # @datamap.angles.dynamic
116
149
  return datamap(syntax=self._syntax, mode='dynamic')
117
150
 
118
151
  @property
119
152
  def callable(self):
120
- # @datamap.angles.callable
121
153
  return datamap(syntax=self._syntax, mode='callable')
122
154
 
123
155
 
124
- # build syntax shortcuts
125
156
  datamap.braces = _SyntaxFactory(syntax.braces)
126
157
  datamap.dollars = _SyntaxFactory(syntax.dollars)
127
158
  datamap.angles = _SyntaxFactory(syntax.angles)
@@ -132,7 +163,6 @@ datamap.at_tags = _SyntaxFactory(syntax.at_tags)
132
163
  datamap.hash_tags = _SyntaxFactory(syntax.hash_tags)
133
164
  datamap.paren_dollars = _SyntaxFactory(syntax.paren_dollars)
134
165
 
135
- # global mode shortcuts
136
166
  datamap.config = datamap(mode='config')
137
167
  datamap.dynamic = datamap(mode='dynamic')
138
168
  datamap.callable = datamap(mode='callable')
mapres/evaluator.py CHANGED
@@ -1,7 +1,10 @@
1
1
  from .ast import TemplateNode, TextNode, IdentNode, CallNode
2
+ from .tokenizer import Tokenizer
3
+ from .parser import Parser
4
+ from .exceptions import MapResError, MissingKeyError
2
5
 
3
6
 
4
- class EvaluationError(Exception):
7
+ class EvaluationError(MapResError):
5
8
  pass
6
9
 
7
10
 
@@ -29,25 +32,47 @@ class Evaluator:
29
32
  if isinstance(node, CallNode):
30
33
  return self._eval_call(node)
31
34
 
32
- raise EvaluationError(f"Unknown AST node: {node}")
35
+ raise EvaluationError(f'Unknown AST node: {node}')
33
36
 
34
37
  # template
35
38
  def _eval_template(self, node: TemplateNode):
36
39
  parts = []
37
40
  for child in node.children:
38
41
  parts.append(self._eval(child))
39
- return "".join(parts)
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
+ return out
40
61
 
41
62
  # identifier
42
63
  def _eval_ident(self, node: IdentNode):
43
64
  name = node.name
44
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
+
45
70
  # cycle detection
46
71
  if name in self._seen:
47
72
  raise EvaluationError(f"Cycle detected in identifier '{name}'")
48
73
  self._seen.add(name)
49
74
 
50
- parts = name.split(".")
75
+ parts = name.split('.')
51
76
 
52
77
  # 1. ctx first
53
78
  val = self._lookup_hierarchical(self.ctx, parts)
@@ -57,7 +82,7 @@ class Evaluator:
57
82
 
58
83
  # 2. syntax-bound maps
59
84
  for m in self.layerstack.all_maps():
60
- if getattr(m, "__syntax__", None) not in (None, node.syntax):
85
+ if getattr(m, '__syntax__', None) not in (None, node.syntax):
61
86
  continue
62
87
 
63
88
  d = self._map_to_dict(m)
@@ -67,12 +92,17 @@ class Evaluator:
67
92
  return str(val)
68
93
 
69
94
  self._seen.remove(name)
70
- raise EvaluationError(f"Missing key '{name}'")
95
+ raise MissingKeyError(name)
71
96
 
72
97
  # call (nested token)
73
98
  def _eval_call(self, node: CallNode):
74
99
  outer = node.name
75
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
+
76
106
  if outer in self._seen:
77
107
  raise EvaluationError(f"Cycle detected in call '{outer}'")
78
108
  self._seen.add(outer)
@@ -88,7 +118,7 @@ class Evaluator:
88
118
 
89
119
  # syntax-bound maps
90
120
  for m in self.layerstack.all_maps():
91
- if getattr(m, "__syntax__", None) not in (None, node.syntax):
121
+ if getattr(m, '__syntax__', None) not in (None, node.syntax):
92
122
  continue
93
123
 
94
124
  d = self._map_to_dict(m)
@@ -98,15 +128,15 @@ class Evaluator:
98
128
  return str(val)
99
129
 
100
130
  self._seen.remove(outer)
101
- raise EvaluationError(f"Missing nested key '{outer}({arg_value})'")
131
+ raise MissingKeyError(f'{outer}({arg_value})')
102
132
 
103
133
  # helpers
104
134
  def _map_to_dict(self, m):
105
- if hasattr(m, "as_map"):
135
+ if hasattr(m, 'as_map'):
106
136
  return m.as_map()
107
137
  if isinstance(m, dict):
108
138
  return m
109
- raise EvaluationError(f"Invalid map object: {m}")
139
+ raise EvaluationError(f'Invalid map object: {m}')
110
140
 
111
141
  def _lookup_hierarchical(self, root, parts):
112
142
  cur = root
@@ -117,3 +147,75 @@ class Evaluator:
117
147
  return None
118
148
  cur = cur[p]
119
149
  return cur
150
+
151
+ def _has_recursive_maps(self):
152
+ for m in self.layerstack.all_maps():
153
+ if getattr(m, '__recursive__', False):
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)
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
mapres/exceptions.py CHANGED
@@ -2,7 +2,9 @@ class MapResError(Exception):
2
2
  pass
3
3
 
4
4
  class MissingKeyError(MapResError):
5
- pass
5
+ def __init__(self, key):
6
+ super().__init__(f'Missing key {key!r}')
7
+ self.key = key
6
8
 
7
9
  class MapSyntaxError(MapResError):
8
10
  pass
mapres/resolver.py CHANGED
@@ -3,7 +3,7 @@ from .parser import Parser
3
3
  from .evaluator import Evaluator
4
4
  from .layers import LayerStack
5
5
  from .cache import LRUCache
6
- from .exceptions import MapResError
6
+ from .exceptions import MapResError, MissingKeyError
7
7
 
8
8
 
9
9
  class MapResolver:
@@ -65,8 +65,18 @@ class MapResolver:
65
65
 
66
66
  return result
67
67
 
68
+ except MissingKeyError as exc:
69
+ mode = self._resolve_missing_key_mode()
70
+ if mode == 'error':
71
+ raise MapResError(f'Resolver error: {exc}') from exc
72
+ if mode == 'silent':
73
+ return text
74
+ if mode == 'placeholder':
75
+ return f'<missing:{exc.key}>'
76
+ raise MapResError(f'Resolver error: {exc}') from exc
77
+
68
78
  except Exception as exc:
69
- raise MapResError(f"Resolver error: {exc}") from exc
79
+ raise MapResError(f'Resolver error: {exc}') from exc
70
80
 
71
81
  # ---------------------------------------
72
82
  # LAYERSTACK BUILDING
@@ -92,6 +102,13 @@ class MapResolver:
92
102
 
93
103
  return self.layers
94
104
 
105
+ def _resolve_missing_key_mode(self):
106
+ for m in self.layers.all_maps():
107
+ mode = getattr(m, '__missing_key__', None)
108
+ if mode is not None:
109
+ return mode
110
+ return 'error'
111
+
95
112
 
96
113
  # ---------------------------------------
97
114
  # SIMPLE GLOBAL USAGE
mapres/tokenizer.py CHANGED
@@ -28,8 +28,8 @@ class Token:
28
28
 
29
29
  def __repr__(self):
30
30
  if self.value is not None:
31
- return f"Token({self.type}, {self.value!r}, pos={self.pos})"
32
- return f"Token({self.type}, pos={self.pos})"
31
+ return f'Token({self.type}, {self.value!r}, pos={self.pos})'
32
+ return f'Token({self.type}, pos={self.pos})'
33
33
 
34
34
 
35
35
  class Tokenizer:
@@ -38,10 +38,15 @@ class Tokenizer:
38
38
  self.i = 0
39
39
  self.n = len(text)
40
40
  self.tokens = []
41
+
42
+ # toggle states
41
43
  self.in_pipe = False
42
44
  self.in_percent = False
43
45
  self.in_colon = False
44
46
 
47
+ # mixed states
48
+ self.in_dollar = False
49
+
45
50
  def peek(self, k=0):
46
51
  idx = self.i + k
47
52
  if idx >= self.n:
@@ -68,6 +73,7 @@ class Tokenizer:
68
73
  while self.i < self.n:
69
74
  ch = self.peek()
70
75
 
76
+ # escapes
71
77
  if self.match(r'\:'):
72
78
  buf.append(':'); self.advance(2); continue
73
79
  if self.match(r'\<'):
@@ -89,43 +95,57 @@ class Tokenizer:
89
95
  if self.match(r'\)'):
90
96
  buf.append(')'); self.advance(2); continue
91
97
 
92
- if self.match("{{"):
98
+ # --- paired delimiters ---
99
+
100
+ # braces {{ }}
101
+ if self.match('{{'):
93
102
  flush_text()
94
103
  self.emit(TokenType.BRACE_OPEN)
95
104
  self.advance(2)
96
105
  continue
97
106
 
98
- if self.match("}}"):
107
+ if self.match('}}'):
99
108
  flush_text()
100
109
  self.emit(TokenType.BRACE_CLOSE)
101
110
  self.advance(2)
102
111
  continue
103
112
 
104
- if self.match("${"):
113
+ # angles < >
114
+ if self.match('<'):
105
115
  flush_text()
106
- self.emit(TokenType.DOLLAR_OPEN)
107
- self.advance(2)
116
+ self.emit(TokenType.ANGLE_OPEN)
117
+ self.advance()
108
118
  continue
109
119
 
110
- if self.match("}"):
120
+ if self.match('>'):
111
121
  flush_text()
112
- self.emit(TokenType.DOLLAR_CLOSE)
122
+ self.emit(TokenType.ANGLE_CLOSE)
113
123
  self.advance()
114
124
  continue
115
125
 
116
- if self.match("<"):
126
+ # --- mixed delimiters (dollars) ---
127
+
128
+ if self.match('${'):
117
129
  flush_text()
118
- self.emit(TokenType.ANGLE_OPEN)
119
- self.advance()
130
+ self.emit(TokenType.DOLLAR_OPEN)
131
+ self.in_dollar = True
132
+ self.advance(2)
120
133
  continue
121
134
 
122
- if self.match(">"):
135
+ if ch == '}':
123
136
  flush_text()
124
- self.emit(TokenType.ANGLE_CLOSE)
137
+ if self.in_dollar:
138
+ self.emit(TokenType.DOLLAR_CLOSE)
139
+ self.in_dollar = False
140
+ else:
141
+ buf.append('}')
125
142
  self.advance()
126
143
  continue
127
144
 
128
- if self.match("|"):
145
+ # --- toggle delimiters ---
146
+
147
+ # pipes |...|
148
+ if self.match('|'):
129
149
  flush_text()
130
150
  if not self.in_pipe:
131
151
  self.emit(TokenType.PIPE_OPEN)
@@ -136,7 +156,8 @@ class Tokenizer:
136
156
  self.advance()
137
157
  continue
138
158
 
139
- if self.match("%"):
159
+ # percents %...%
160
+ if self.match('%'):
140
161
  flush_text()
141
162
  if not self.in_percent:
142
163
  self.emit(TokenType.PERCENT_OPEN)
@@ -147,7 +168,8 @@ class Tokenizer:
147
168
  self.advance()
148
169
  continue
149
170
 
150
- if self.match(":"):
171
+ # colons :...:
172
+ if self.match(':'):
151
173
  flush_text()
152
174
  if not self.in_colon:
153
175
  self.emit(TokenType.COLON_OPEN)
@@ -158,27 +180,51 @@ class Tokenizer:
158
180
  self.advance()
159
181
  continue
160
182
 
161
- if ch == "(":
183
+ # --- parens ---
184
+
185
+ if ch == '(':
162
186
  flush_text()
163
187
  self.emit(TokenType.LPAREN)
164
188
  self.advance()
165
189
  continue
166
190
 
167
- if ch == ")":
191
+ if ch == ')':
168
192
  flush_text()
169
193
  self.emit(TokenType.RPAREN)
170
194
  self.advance()
171
195
  continue
172
196
 
173
- if ch.isalpha():
197
+ # --- IDENT (your rules) ---
198
+
199
+ if ch.isalnum():
174
200
  flush_text()
175
201
  start = self.i
176
- while self.peek().isalnum() or self.peek() in "._":
177
- self.advance()
202
+
203
+ # first char: [a-zA-Z0-9]
204
+ self.advance()
205
+
206
+ # middle chars: [a-zA-Z0-9._]*
207
+ while True:
208
+ nxt = self.peek()
209
+ if not nxt:
210
+ break
211
+ if nxt.isalnum() or nxt in '._':
212
+ self.advance()
213
+ else:
214
+ break
215
+
178
216
  ident = self.text[start:self.i]
179
- self.emit(TokenType.IDENT, ident)
217
+
218
+ # enforce: no leading/trailing '_', no '-'
219
+ if ident.startswith('_') or ident.endswith('_') or '-' in ident:
220
+ # treat as TEXT instead
221
+ buf.append(ident)
222
+ else:
223
+ self.emit(TokenType.IDENT, ident)
180
224
  continue
181
225
 
226
+ # --- fallback: TEXT ---
227
+
182
228
  buf.append(ch)
183
229
  self.advance()
184
230
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mapres
3
- Version: 3.dev14
3
+ Version: 3.dev16
4
4
  Summary: A powerfull mapping utility
5
5
  Author: iFamished
6
6
  License: MIT
@@ -0,0 +1,18 @@
1
+ mapres/__init__.py,sha256=t23ofM-wzpPByYi1rEQonxyU1yyza4ZzwwHDZUa5QqA,1010
2
+ mapres/ast.py,sha256=6PcMkwtNHYD8xEkdyzDgn_mRTj1ZaWSyuHZK3BtXiuo,427
3
+ mapres/cache.py,sha256=hbvsoc6Qw3RhWAEfOOpKHtC7i9EomoUgWzyd4dnH71w,333
4
+ mapres/datamap.py,sha256=v9DAIYaS-vkBU1BKmshGYnquZa2JPwcct661zaEFocs,5256
5
+ mapres/evaluator.py,sha256=ElKliQ4z0vSTFHtbTxSafRBVrPpksjqFjq5spKKEFwI,6962
6
+ mapres/exceptions.py,sha256=D2XKnrMkZDyUXQt2PmaKbj08FObWU00yXKGHwNpjvww,222
7
+ mapres/layers.py,sha256=sFc1eUOBg2BoB2cBXIleq8RMYcg5GZpUoCnGh-uKN6U,1380
8
+ mapres/parser.py,sha256=8XLCzYosvh81bN-Jddc1AM4w0X7bsHnBzmA8sq5_72w,4018
9
+ mapres/resolver.py,sha256=kQexTdBnPy70Azh_U6--hwUtnIJjoKcuaJ2KlBaG3Rg,3889
10
+ mapres/tokenizer.py,sha256=js0S1s8MkltdQoH5V1cLjdY0fFqZoGqmtP_OhEJEM6M,6539
11
+ mapres/maps/__init__.py,sha256=lIRRfem1Fw4iynuwUQ7BY5qrC4fbJKxqLivao2_Dtm4,239
12
+ mapres/maps/color.py,sha256=noRTGFNo9xLl5YEhX0tttV6i_oDAiptXmRVnkr5EzwM,1348
13
+ mapres/maps/time.py,sha256=TyncycYoIGVZWps32qWlFy2a2hTayvZWVHu9uh2nid8,2050
14
+ mapres-3.dev16.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
15
+ mapres-3.dev16.dist-info/METADATA,sha256=KHiZBTclH89lWV6Kr85_SIuH3igO8i6fm6tarBaD0lE,1476
16
+ mapres-3.dev16.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
17
+ mapres-3.dev16.dist-info/top_level.txt,sha256=5LMVQqJdtyjxfzv7wJBOZ-360m0Yc79w_-Y7s3n6cTw,7
18
+ mapres-3.dev16.dist-info/RECORD,,
@@ -1,18 +0,0 @@
1
- mapres/__init__.py,sha256=t23ofM-wzpPByYi1rEQonxyU1yyza4ZzwwHDZUa5QqA,1010
2
- mapres/ast.py,sha256=6PcMkwtNHYD8xEkdyzDgn_mRTj1ZaWSyuHZK3BtXiuo,427
3
- mapres/cache.py,sha256=hbvsoc6Qw3RhWAEfOOpKHtC7i9EomoUgWzyd4dnH71w,333
4
- mapres/datamap.py,sha256=0kfxBSAaIXwT8srkcurPbXBbbpmc_HbAzL-iJ45pKNc,4439
5
- mapres/evaluator.py,sha256=YZ4SUTMM1XhcxH1Skm2J4QSP6_P79TfuQn33cCekRsI,3348
6
- mapres/exceptions.py,sha256=jirHKK5yCffSCWWkgZY_gTSIOaFCmXOe5NJJf60HeeQ,130
7
- mapres/layers.py,sha256=sFc1eUOBg2BoB2cBXIleq8RMYcg5GZpUoCnGh-uKN6U,1380
8
- mapres/parser.py,sha256=8XLCzYosvh81bN-Jddc1AM4w0X7bsHnBzmA8sq5_72w,4018
9
- mapres/resolver.py,sha256=7N2M-6_6NCiBBxHCNFOjKoU0E3Ntgb8o_3gA00HsKU4,3247
10
- mapres/tokenizer.py,sha256=WvLHVb3x2QA70oyrC2Gd_oNOXj9VIMVGuVS-Ew11RW0,5344
11
- mapres/maps/__init__.py,sha256=lIRRfem1Fw4iynuwUQ7BY5qrC4fbJKxqLivao2_Dtm4,239
12
- mapres/maps/color.py,sha256=noRTGFNo9xLl5YEhX0tttV6i_oDAiptXmRVnkr5EzwM,1348
13
- mapres/maps/time.py,sha256=TyncycYoIGVZWps32qWlFy2a2hTayvZWVHu9uh2nid8,2050
14
- mapres-3.dev14.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
15
- mapres-3.dev14.dist-info/METADATA,sha256=ks3M9DeKQwoDUXQue1vG-pQ5notahc_u0cDV8eYIZaM,1476
16
- mapres-3.dev14.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
17
- mapres-3.dev14.dist-info/top_level.txt,sha256=5LMVQqJdtyjxfzv7wJBOZ-360m0Yc79w_-Y7s3n6cTw,7
18
- mapres-3.dev14.dist-info/RECORD,,