omlish 0.0.0.dev371__py3-none-any.whl → 0.0.0.dev373__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.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev371'
2
- __revision__ = 'c37d96ddcd83d914205dd76b0f859b9ca93b0397'
1
+ __version__ = '0.0.0.dev373'
2
+ __revision__ = '0a27e61ad530198ac027dde9d0b88d9bd995d0b5'
3
3
 
4
4
 
5
5
  #
omlish/lite/marshal.py CHANGED
@@ -1,7 +1,6 @@
1
1
  """
2
2
  TODO:
3
3
  - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
4
- - literals
5
4
  - Options.sequence_cls = list, mapping_cls = dict, ... - def with_mutable_containers() -> Options
6
5
  """
7
6
  # ruff: noqa: UP006 UP007 UP045
@@ -24,7 +23,6 @@ from .check import check
24
23
  from .reflect import deep_subclasses
25
24
  from .reflect import get_literal_type_args
26
25
  from .reflect import get_new_type_supertype
27
- from .reflect import get_optional_alias_arg
28
26
  from .reflect import is_generic_alias
29
27
  from .reflect import is_literal_type
30
28
  from .reflect import is_new_type
@@ -144,6 +142,28 @@ class OptionalObjMarshaler(ObjMarshaler):
144
142
  return self.item.unmarshal(o, ctx)
145
143
 
146
144
 
145
+ @dc.dataclass(frozen=True)
146
+ class PrimitiveUnionObjMarshaler(ObjMarshaler):
147
+ pt: ta.Tuple[type, ...]
148
+ x: ta.Optional[ObjMarshaler] = None
149
+
150
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
151
+ if isinstance(o, self.pt):
152
+ return o
153
+ elif self.x is not None:
154
+ return self.x.marshal(o, ctx)
155
+ else:
156
+ raise TypeError(o)
157
+
158
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
159
+ if isinstance(o, self.pt):
160
+ return o
161
+ elif self.x is not None:
162
+ return self.x.unmarshal(o, ctx)
163
+ else:
164
+ raise TypeError(o)
165
+
166
+
147
167
  @dc.dataclass(frozen=True)
148
168
  class LiteralObjMarshaler(ObjMarshaler):
149
169
  item: ObjMarshaler
@@ -342,6 +362,13 @@ _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES: ta.Dict[ta.Any, type] = {
342
362
  collections.abc.MutableSequence: list,
343
363
  }
344
364
 
365
+ _OBJ_MARSHALER_PRIMITIVE_TYPES: ta.Set[type] = {
366
+ int,
367
+ float,
368
+ bool,
369
+ str,
370
+ }
371
+
345
372
 
346
373
  ##
347
374
 
@@ -490,8 +517,16 @@ class ObjMarshalerManager:
490
517
 
491
518
  if is_literal_type(ty):
492
519
  lvs = frozenset(get_literal_type_args(ty))
520
+ if None in lvs:
521
+ is_opt = True
522
+ lvs -= frozenset([None])
523
+ else:
524
+ is_opt = False
493
525
  lty = check.single(set(map(type, lvs)))
494
- return LiteralObjMarshaler(rec(lty), lvs)
526
+ lm: ObjMarshaler = LiteralObjMarshaler(rec(lty), lvs)
527
+ if is_opt:
528
+ lm = OptionalObjMarshaler(lm)
529
+ return lm
495
530
 
496
531
  if is_generic_alias(ty):
497
532
  try:
@@ -511,7 +546,31 @@ class ObjMarshalerManager:
511
546
  return IterableObjMarshaler(st, rec(e))
512
547
 
513
548
  if is_union_alias(ty):
514
- return OptionalObjMarshaler(rec(get_optional_alias_arg(ty)))
549
+ uts = frozenset(ta.get_args(ty))
550
+ if None in uts or type(None) in uts:
551
+ is_opt = True
552
+ uts = frozenset(ut for ut in uts if ut not in (None, type(None)))
553
+ else:
554
+ is_opt = False
555
+
556
+ um: ObjMarshaler
557
+ if not uts:
558
+ raise TypeError(ty)
559
+ elif len(uts) == 1:
560
+ um = rec(check.single(uts))
561
+ else:
562
+ pt = tuple({ut for ut in uts if ut in _OBJ_MARSHALER_PRIMITIVE_TYPES})
563
+ np_uts = {ut for ut in uts if ut not in _OBJ_MARSHALER_PRIMITIVE_TYPES}
564
+ if not np_uts:
565
+ um = PrimitiveUnionObjMarshaler(pt)
566
+ elif len(np_uts) == 1:
567
+ um = PrimitiveUnionObjMarshaler(pt, x=rec(check.single(np_uts)))
568
+ else:
569
+ raise TypeError(ty)
570
+
571
+ if is_opt:
572
+ um = OptionalObjMarshaler(um)
573
+ return um
515
574
 
516
575
  raise TypeError(ty)
517
576
 
omlish/text/minja.py CHANGED
@@ -15,6 +15,9 @@ from ..lite.check import check
15
15
  from ..lite.maybes import Maybe
16
16
 
17
17
 
18
+ MinjaTemplateFragmentKind = ta.Literal['expr', 'stmt', 'for', 'if', 'elif'] # ta.TypeAlias
19
+
20
+
18
21
  ##
19
22
 
20
23
 
@@ -90,6 +93,9 @@ class MinjaTemplateCompiler:
90
93
  params: ta.Sequence[ta.Union[str, MinjaTemplateParam]],
91
94
  *,
92
95
  indent: str = DEFAULT_INDENT,
96
+ fragment_processor: ta.Optional[ta.Callable[[MinjaTemplateFragmentKind, str], str]] = None,
97
+ strict_strings: bool = False,
98
+ stringifier: ta.Optional[ta.Callable[[ta.Any], str]] = None,
93
99
  ) -> None:
94
100
  super().__init__()
95
101
 
@@ -103,8 +109,25 @@ class MinjaTemplateCompiler:
103
109
  check.unique(p.name for p in self._params)
104
110
  self._indent_str: str = check.non_empty_str(indent)
105
111
 
112
+ if fragment_processor is None:
113
+ fragment_processor = lambda _, s: s # noqa
114
+ self._fragment_processor = fragment_processor
115
+
116
+ if stringifier is None:
117
+ if strict_strings:
118
+ stringifier = self._strict_stringify
119
+ else:
120
+ stringifier = lambda o: str(o)
121
+ self._stringifier = stringifier
122
+
106
123
  self._stack: ta.List[ta.Literal['for', 'if']] = []
107
124
 
125
+ @staticmethod
126
+ def _strict_stringify(o: ta.Any) -> str:
127
+ if not isinstance(o, str):
128
+ raise TypeError(o)
129
+ return o
130
+
108
131
  #
109
132
 
110
133
  _TAG_PAT = re.compile(
@@ -166,7 +189,7 @@ class MinjaTemplateCompiler:
166
189
 
167
190
  #
168
191
 
169
- _RENDER_FN_NAME = '__render'
192
+ _RENDER_FN_NAME = '__minja__render'
170
193
 
171
194
  class Rendered(ta.NamedTuple):
172
195
  src: str
@@ -177,7 +200,8 @@ class MinjaTemplateCompiler:
177
200
  lines: ta.List[str] = []
178
201
 
179
202
  ns: ta.Dict[str, ta.Any] = {
180
- '__StringIO': io.StringIO,
203
+ '__minja__StringIO': io.StringIO,
204
+ '__minja__stringify': self._stringifier,
181
205
  }
182
206
 
183
207
  parts = self._split_tags(self._src)
@@ -195,36 +219,36 @@ class MinjaTemplateCompiler:
195
219
  lines.append(self._indent(f'{p.name},'))
196
220
  lines.append('):')
197
221
 
198
- lines.append(self._indent('__output = __StringIO()'))
222
+ lines.append(self._indent('__minja__output = __minja__StringIO()'))
199
223
 
200
224
  for g, s in parts:
201
225
  if g == '{':
202
226
  expr = s.strip()
203
- lines.append(self._indent(f'__output.write(str({expr}))'))
227
+ lines.append(self._indent(f'__minja__output.write(__minja__stringify({self._fragment_processor("expr", expr)}))')) # noqa
204
228
 
205
229
  elif g == '%':
206
230
  stmt = s.strip()
207
231
 
208
232
  if stmt.startswith('for '):
209
- lines.append(self._indent(stmt + ':'))
233
+ lines.append(self._indent(f'for {self._fragment_processor("for", stmt[4:])}:'))
210
234
  self._stack.append('for')
211
235
  elif stmt.startswith('endfor'):
212
236
  check.equal(self._stack.pop(), 'for')
213
237
 
214
238
  elif stmt.startswith('if '):
215
- lines.append(self._indent(stmt + ':'))
239
+ lines.append(self._indent(f'if {self._fragment_processor("if", stmt[3:])}:'))
216
240
  self._stack.append('if')
217
241
  elif stmt.startswith('elif '):
218
242
  check.equal(self._stack[-1], 'if')
219
- lines.append(self._indent(stmt + ':', -1))
243
+ lines.append(self._indent(f'elif {self._fragment_processor("elif", stmt[5:])}:', -1))
220
244
  elif stmt.strip() == 'else':
221
245
  check.equal(self._stack[-1], 'if')
222
246
  lines.append(self._indent('else:', -1))
223
- elif stmt.startswith('endif'):
247
+ elif stmt.strip() == 'endif':
224
248
  check.equal(self._stack.pop(), 'if')
225
249
 
226
250
  else:
227
- lines.append(self._indent(stmt))
251
+ lines.append(self._indent(self._fragment_processor('stmt', stmt)))
228
252
 
229
253
  elif g == '#':
230
254
  pass
@@ -232,14 +256,14 @@ class MinjaTemplateCompiler:
232
256
  elif not g:
233
257
  if s:
234
258
  safe_text = s.replace('"""', '\\"""')
235
- lines.append(self._indent(f'__output.write("""{safe_text}""")'))
259
+ lines.append(self._indent(f'__minja__output.write("""{safe_text}""")'))
236
260
 
237
261
  else:
238
262
  raise KeyError(g)
239
263
 
240
264
  check.empty(self._stack)
241
265
 
242
- lines.append(self._indent('return __output.getvalue()'))
266
+ lines.append(self._indent('return __minja__output.getvalue()'))
243
267
 
244
268
  return self.Rendered('\n'.join(lines), ns)
245
269
 
@@ -258,16 +282,22 @@ class MinjaTemplateCompiler:
258
282
  exec(src, glo)
259
283
  return glo[name]
260
284
 
261
- #
262
-
263
- @cached_nullary
264
- def compile(self) -> MinjaTemplate:
285
+ def compile(
286
+ self,
287
+ ns: ta.Optional[ta.Mapping[str, ta.Any]] = None,
288
+ ) -> MinjaTemplate:
265
289
  rendered = self.render()
266
290
 
291
+ ns = dict(ns or {})
292
+ for k, v in rendered.ns.items():
293
+ if k in ns:
294
+ raise KeyError(k)
295
+ ns[k] = v
296
+
267
297
  render_fn = self._make_fn(
268
298
  self._RENDER_FN_NAME,
269
299
  rendered.src,
270
- rendered.ns,
300
+ ns,
271
301
  )
272
302
 
273
303
  return MinjaTemplate(
@@ -282,8 +312,15 @@ class MinjaTemplateCompiler:
282
312
  def compile_minja_template(
283
313
  src: str,
284
314
  params: ta.Sequence[ta.Union[str, MinjaTemplateParam]] = (),
315
+ *,
316
+ ns: ta.Optional[ta.Mapping[str, ta.Any]] = None,
317
+ **kwargs: ta.Any,
285
318
  ) -> MinjaTemplate:
286
- return MinjaTemplateCompiler(src, params).compile()
319
+ return MinjaTemplateCompiler(
320
+ src,
321
+ params,
322
+ **kwargs,
323
+ ).compile(ns)
287
324
 
288
325
 
289
326
  def render_minja_template(src: str, **kwargs: ta.Any) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev371
3
+ Version: 0.0.0.dev373
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=aT8yZ-Zh-9wfHl5Ym5ouiWC1i0cy7Q7RlhzavB6VLPI,8587
2
- omlish/__about__.py,sha256=IuPF6dQwqBF37vj4nM3a2rfw3IW2B0qdP0SrL4-B5BI,3478
2
+ omlish/__about__.py,sha256=a_E5lH9U0Zxuae2uxWKtn3a6hmcIp8G2BThTgUgh_H0,3478
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=rer-TPOFDU6fYq_AWio_AmA-ckZ8JDY5shIzQ_yXfzA,8414
5
5
  omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
@@ -472,7 +472,7 @@ omlish/lite/imports.py,sha256=JDYRFxu-ofHEBfd5VV3b27oKOLhtTpuzte1_Nt7yLgw,1352
472
472
  omlish/lite/inject.py,sha256=xvmLmtD3_2INnkurJQv76_Rkh9usbApEQrXJ4cvuVAk,29019
473
473
  omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
474
474
  omlish/lite/logs.py,sha256=CWFG0NKGhqNeEgryF5atN2gkPYbUdTINEw_s1phbINM,51
475
- omlish/lite/marshal.py,sha256=43fWY7CyLw3NGKHGxFqkiqKFGzXIHqayMVgfeHT02AU,18477
475
+ omlish/lite/marshal.py,sha256=dxiDtmSXt4EBpTprMNkPsOYkRs0W9AC3Kby9UGEjuRo,20400
476
476
  omlish/lite/maybes.py,sha256=0p_fzb6yiOjEpvMKaQ53Q6CH1VPW1or7v7Lt1JIKcgM,4359
477
477
  omlish/lite/pycharm.py,sha256=FRHGcCDo42UzZXqNwW_DkhI-6kb_CmJKPiQ8F6mYkLA,1174
478
478
  omlish/lite/reflect.py,sha256=pzOY2PPuHH0omdtglkN6DheXDrGopdL3PtTJnejyLFU,2189
@@ -804,7 +804,7 @@ omlish/text/glyphsplit.py,sha256=ZX9mhwTtmUE8rJpuD1jBO1CTc6xzmBCtbfiHmp5vMM8,381
804
804
  omlish/text/indent.py,sha256=BWVVaHs_B1ppwHJJIxKCDG3iCutkYy5e1qr59Z_Suzg,1524
805
805
  omlish/text/linecache.py,sha256=hRYlEhD63ZfA6_ZOTkQIcnON-3W56QMAhcG3vEJqj9M,1858
806
806
  omlish/text/mangle.py,sha256=k7mYavVgxJ2ENV2wfjw3c9u3hqH5NeVpjoxYbyaYC0Y,2796
807
- omlish/text/minja.py,sha256=eyOA_zUCzyqaBfiPX-hV2xdK9_cqlDEhbVTkZUTZgQo,7521
807
+ omlish/text/minja.py,sha256=wz4ZkjPTvlVkLBkWyTCoyERyiofBMvDXZZcNsGtk8gU,8999
808
808
  omlish/text/parts.py,sha256=MpiCUyfpcL4PLb2Etj8V7Yj4qofhy0xVwBrIL6RfNdg,6646
809
809
  omlish/text/random.py,sha256=8feS5JE_tSjYlMl-lp0j93kCfzBae9AM2cXlRLebXMA,199
810
810
  omlish/text/templating.py,sha256=Nf5BVDgrYBf0WmYwV6SnHPDvl9XVMu8v7MX78pInLTw,3325
@@ -888,9 +888,9 @@ omlish/typedvalues/marshal.py,sha256=AtBz7Jq-BfW8vwM7HSxSpR85JAXmxK2T0xDblmm1HI0
888
888
  omlish/typedvalues/of_.py,sha256=UXkxSj504WI2UrFlqdZJbu2hyDwBhL7XVrc2qdR02GQ,1309
889
889
  omlish/typedvalues/reflect.py,sha256=PAvKW6T4cW7u--iX80w3HWwZUS3SmIZ2_lQjT65uAyk,1026
890
890
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
891
- omlish-0.0.0.dev371.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
892
- omlish-0.0.0.dev371.dist-info/METADATA,sha256=oPFYGURgWGkPAhtJkRCmiXVNzNFuNn8sXTBZAHZh1TI,4416
893
- omlish-0.0.0.dev371.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
894
- omlish-0.0.0.dev371.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
895
- omlish-0.0.0.dev371.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
896
- omlish-0.0.0.dev371.dist-info/RECORD,,
891
+ omlish-0.0.0.dev373.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
892
+ omlish-0.0.0.dev373.dist-info/METADATA,sha256=fed55fYjKmKimj_-64adhKjxXvjVgpztmAzJhqRHczs,4416
893
+ omlish-0.0.0.dev373.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
894
+ omlish-0.0.0.dev373.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
895
+ omlish-0.0.0.dev373.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
896
+ omlish-0.0.0.dev373.dist-info/RECORD,,