omlish 0.0.0.dev285__py3-none-any.whl → 0.0.0.dev286__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.dev285'
2
- __revision__ = 'e95058137e322e352c2579564d041f21cdf1220c'
1
+ __version__ = '0.0.0.dev286'
2
+ __revision__ = '07fa507e06f16ab8f3ccba3d580382b07079b73e'
3
3
 
4
4
 
5
5
  #
@@ -106,6 +106,10 @@ class Project(ProjectBase):
106
106
  'duckdb ~= 1.2',
107
107
  ],
108
108
 
109
+ 'templates': [
110
+ 'jinja2 ~= 3.1',
111
+ ],
112
+
109
113
  'testing': [
110
114
  'pytest ~= 8.3',
111
115
  ],
@@ -36,6 +36,10 @@ class PlanOnly(ta.NamedTuple):
36
36
  b: bool
37
37
 
38
38
 
39
+ class Verbose(ta.NamedTuple):
40
+ b: bool
41
+
42
+
39
43
  @register_processor_type(priority=ProcessorPriority.GENERATION)
40
44
  class GeneratorProcessor(Processor):
41
45
  class Mode(abc.ABC):
@@ -67,10 +71,11 @@ class GeneratorProcessor(Processor):
67
71
  gp.ops(),
68
72
  )
69
73
 
70
- # print(gp.prepare().plans.render())
71
- # print()
72
- # print(comp.src)
73
- # print()
74
+ if (vo := gp._ctx.option(Verbose)) is not None and vo.b: # noqa
75
+ print(gp.prepare().plans.render(), file=sys.stderr)
76
+ print(file=sys.stderr)
77
+ print(comp.src, file=sys.stderr)
78
+ print(file=sys.stderr)
74
79
 
75
80
  ns: dict = {}
76
81
  ns.update(compiler.style.globals_ns()) # noqa
@@ -1,8 +1,7 @@
1
1
  import typing as ta
2
2
 
3
3
  from .. import concerns as _concerns # noqa # imported for registration
4
- from ..generation import processor as _generation_processor # noqa # imported for registration
5
- from ..generation.processor import PlanOnly
4
+ from ..generation import processor as gp
6
5
  from ..specs import ClassSpec
7
6
  from .base import ProcessingContext
8
7
  from .base import Processor
@@ -18,10 +17,15 @@ def drive_cls_processing(
18
17
  cs: ClassSpec,
19
18
  *,
20
19
  plan_only: bool = False,
20
+ verbose: bool = False,
21
21
  ) -> type:
22
22
  options: list[ta.Any] = []
23
23
  if plan_only:
24
- options.append(PlanOnly(True))
24
+ options.append(gp.PlanOnly(True))
25
+ if verbose:
26
+ options.append(gp.Verbose(True))
27
+
28
+ #
25
29
 
26
30
  ctx = ProcessingContext(
27
31
  cls,
omlish/lang/maybes.py CHANGED
@@ -1,6 +1,9 @@
1
1
  import abc
2
2
  import typing as ta
3
3
 
4
+ from ..lite.maybes import Maybe as _LiteMaybe
5
+ from ..lite.maybes import as_maybe as _as_lite_maybe
6
+
4
7
 
5
8
  T = ta.TypeVar('T')
6
9
  U = ta.TypeVar('U')
@@ -123,6 +126,9 @@ class _Maybe(Maybe[T], tuple):
123
126
  raise exception_supplier()
124
127
 
125
128
 
129
+ #
130
+
131
+
126
132
  def just(v: T) -> Maybe[T]:
127
133
  return tuple.__new__(_Maybe, (v,)) # noqa
128
134
 
@@ -138,3 +144,14 @@ def maybe(o: T | None) -> Maybe[T]:
138
144
  if o is None:
139
145
  return _empty # noqa
140
146
  return just(o)
147
+
148
+
149
+ ##
150
+
151
+
152
+ @_as_lite_maybe.register
153
+ def _(obj: Maybe) -> _LiteMaybe:
154
+ if obj.present:
155
+ return _LiteMaybe.just(obj.must())
156
+ else:
157
+ return _LiteMaybe.empty()
omlish/lite/maybes.py CHANGED
@@ -1,10 +1,14 @@
1
1
  import abc
2
+ import functools
2
3
  import typing as ta
3
4
 
4
5
 
5
6
  T = ta.TypeVar('T')
6
7
 
7
8
 
9
+ ##
10
+
11
+
8
12
  class Maybe(ta.Generic[T]):
9
13
  @property
10
14
  @abc.abstractmethod
@@ -43,3 +47,16 @@ class _Maybe(Maybe[T], tuple):
43
47
 
44
48
 
45
49
  Maybe._empty = tuple.__new__(_Maybe, ()) # noqa
50
+
51
+
52
+ ##
53
+
54
+
55
+ @functools.singledispatch
56
+ def as_maybe(obj: ta.Any) -> Maybe:
57
+ raise TypeError(obj)
58
+
59
+
60
+ @as_maybe.register
61
+ def _(obj: Maybe) -> Maybe:
62
+ return obj
omlish/text/minja.py CHANGED
@@ -5,12 +5,14 @@ TODO:
5
5
  - raw
6
6
  - blocks / inheritance
7
7
  """
8
+ import dataclasses as dc
8
9
  import io
9
10
  import re
10
11
  import typing as ta
11
12
 
12
13
  from ..lite.cached import cached_nullary
13
14
  from ..lite.check import check
15
+ from ..lite.maybes import Maybe
14
16
 
15
17
 
16
18
  ##
@@ -29,6 +31,34 @@ class MinjaTemplate:
29
31
  ##
30
32
 
31
33
 
34
+ @dc.dataclass(frozen=True)
35
+ class MinjaTemplateParam:
36
+ name: str
37
+ default: Maybe[ta.Any] = Maybe.empty()
38
+
39
+ def __post_init__(self) -> None:
40
+ check.arg(self.name.isidentifier())
41
+
42
+ @classmethod
43
+ def of(cls, obj: ta.Union[str, 'MinjaTemplateParam']) -> 'MinjaTemplateParam':
44
+ if isinstance(obj, MinjaTemplateParam):
45
+ return obj
46
+ elif isinstance(obj, str):
47
+ return MinjaTemplateParam.new(obj)
48
+ else:
49
+ raise TypeError(obj)
50
+
51
+ @classmethod
52
+ def new(cls, name: str, *defaults: ta.Any) -> 'MinjaTemplateParam':
53
+ dfl: Maybe[ta.Any]
54
+ if defaults:
55
+ [dv] = defaults
56
+ dfl = Maybe.just(dv)
57
+ else:
58
+ dfl = Maybe.empty()
59
+ return cls(name, dfl)
60
+
61
+
32
62
  class MinjaTemplateCompiler:
33
63
  """
34
64
  Compiles a template string into a Python function. The returned function takes a dictionary 'context' and returns
@@ -43,23 +73,28 @@ class MinjaTemplateCompiler:
43
73
  - {# comment #}: Ignored completely.
44
74
  """
45
75
 
46
- DEFAULT_INDENT: str = ' '
76
+ DEFAULT_INDENT: str = ' ' * 4
47
77
 
48
78
  def __init__(
49
79
  self,
50
80
  src: str,
51
- args: ta.Sequence[str],
81
+ params: ta.Sequence[ta.Union[str, MinjaTemplateParam]],
52
82
  *,
53
83
  indent: str = DEFAULT_INDENT,
54
84
  ) -> None:
55
85
  super().__init__()
56
86
 
87
+ check.not_isinstance(params, str)
88
+
57
89
  self._src = check.isinstance(src, str)
58
- self._args = check.not_isinstance(args, str)
90
+ self._params = [
91
+ MinjaTemplateParam.of(p)
92
+ for p in params
93
+ ]
94
+ check.unique(p.name for p in self._params)
59
95
  self._indent_str: str = check.non_empty_str(indent)
60
96
 
61
97
  self._stack: ta.List[ta.Literal['for', 'if']] = []
62
- self._lines: ta.List[str] = []
63
98
 
64
99
  #
65
100
 
@@ -124,41 +159,63 @@ class MinjaTemplateCompiler:
124
159
 
125
160
  _RENDER_FN_NAME = '__render'
126
161
 
162
+ class Rendered(ta.NamedTuple):
163
+ src: str
164
+ ns: ta.Dict[str, ta.Any]
165
+
127
166
  @cached_nullary
128
- def render(self) -> ta.Tuple[str, ta.Mapping[str, ta.Any]]:
167
+ def render(self) -> Rendered:
168
+ lines: ta.List[str] = []
169
+
170
+ ns: ta.Dict[str, ta.Any] = {
171
+ '__StringIO': io.StringIO,
172
+ }
173
+
129
174
  parts = self._split_tags(self._src)
130
175
 
131
- self._lines.append(f'def {self._RENDER_FN_NAME}({", ".join(self._args)}):')
132
- self._lines.append(self._indent('__output = __StringIO()'))
176
+ if not self._params:
177
+ lines.append(f'def {self._RENDER_FN_NAME}():')
178
+ else:
179
+ lines.append(f'def {self._RENDER_FN_NAME}(')
180
+ for p in self._params:
181
+ if p.default.present:
182
+ check.not_in(p.name, ns)
183
+ ns[p.name] = p.default.must()
184
+ lines.append(self._indent(f'{p.name}={p.name},'))
185
+ else:
186
+ lines.append(self._indent(f'{p.name},'))
187
+ lines.append('):')
188
+
189
+ lines.append(self._indent('__output = __StringIO()'))
133
190
 
134
191
  for g, s in parts:
135
192
  if g == '{':
136
193
  expr = s.strip()
137
- self._lines.append(self._indent(f'__output.write(str({expr}))'))
194
+ lines.append(self._indent(f'__output.write(str({expr}))'))
138
195
 
139
196
  elif g == '%':
140
197
  stmt = s.strip()
141
198
 
142
199
  if stmt.startswith('for '):
143
- self._lines.append(self._indent(stmt + ':'))
200
+ lines.append(self._indent(stmt + ':'))
144
201
  self._stack.append('for')
145
202
  elif stmt.startswith('endfor'):
146
203
  check.equal(self._stack.pop(), 'for')
147
204
 
148
205
  elif stmt.startswith('if '):
149
- self._lines.append(self._indent(stmt + ':'))
206
+ lines.append(self._indent(stmt + ':'))
150
207
  self._stack.append('if')
151
208
  elif stmt.startswith('elif '):
152
209
  check.equal(self._stack[-1], 'if')
153
- self._lines.append(self._indent(stmt + ':', -1))
210
+ lines.append(self._indent(stmt + ':', -1))
154
211
  elif stmt.strip() == 'else':
155
212
  check.equal(self._stack[-1], 'if')
156
- self._lines.append(self._indent('else:', -1))
213
+ lines.append(self._indent('else:', -1))
157
214
  elif stmt.startswith('endif'):
158
215
  check.equal(self._stack.pop(), 'if')
159
216
 
160
217
  else:
161
- self._lines.append(self._indent(stmt))
218
+ lines.append(self._indent(stmt))
162
219
 
163
220
  elif g == '#':
164
221
  pass
@@ -166,20 +223,16 @@ class MinjaTemplateCompiler:
166
223
  elif not g:
167
224
  if s:
168
225
  safe_text = s.replace('"""', '\\"""')
169
- self._lines.append(self._indent(f'__output.write("""{safe_text}""")'))
226
+ lines.append(self._indent(f'__output.write("""{safe_text}""")'))
170
227
 
171
228
  else:
172
229
  raise KeyError(g)
173
230
 
174
231
  check.empty(self._stack)
175
232
 
176
- self._lines.append(self._indent('return __output.getvalue()'))
177
-
178
- ns = {
179
- '__StringIO': io.StringIO,
180
- }
233
+ lines.append(self._indent('return __output.getvalue()'))
181
234
 
182
- return ('\n'.join(self._lines), ns)
235
+ return self.Rendered('\n'.join(lines), ns)
183
236
 
184
237
  #
185
238
 
@@ -200,12 +253,12 @@ class MinjaTemplateCompiler:
200
253
 
201
254
  @cached_nullary
202
255
  def compile(self) -> MinjaTemplate:
203
- render_src, render_ns = self.render()
256
+ rendered = self.render()
204
257
 
205
258
  render_fn = self._make_fn(
206
259
  self._RENDER_FN_NAME,
207
- render_src,
208
- render_ns,
260
+ rendered.src,
261
+ rendered.ns,
209
262
  )
210
263
 
211
264
  return MinjaTemplate(render_fn)
@@ -214,8 +267,11 @@ class MinjaTemplateCompiler:
214
267
  ##
215
268
 
216
269
 
217
- def compile_minja_template(src: str, args: ta.Sequence[str] = ()) -> MinjaTemplate:
218
- return MinjaTemplateCompiler(src, args).compile()
270
+ def compile_minja_template(
271
+ src: str,
272
+ params: ta.Sequence[ta.Union[str, MinjaTemplateParam]] = (),
273
+ ) -> MinjaTemplate:
274
+ return MinjaTemplateCompiler(src, params).compile()
219
275
 
220
276
 
221
277
  def render_minja_template(src: str, **kwargs: ta.Any) -> str:
@@ -0,0 +1,116 @@
1
+ import abc
2
+ import dataclasses as dc
3
+ import string
4
+ import typing as ta
5
+
6
+ from .. import lang
7
+ from .minja import MinjaTemplate
8
+ from .minja import MinjaTemplateParam
9
+ from .minja import compile_minja_template
10
+
11
+
12
+ if ta.TYPE_CHECKING:
13
+ import jinja2
14
+ else:
15
+ jinja2 = lang.proxy_import('jinja2')
16
+
17
+
18
+ ##
19
+
20
+
21
+ class Templater(lang.Abstract):
22
+ @dc.dataclass(frozen=True)
23
+ class Context:
24
+ env: ta.Mapping[str, ta.Any] | None = None
25
+
26
+ @abc.abstractmethod
27
+ def render(self, ctx: Context) -> str:
28
+ raise NotImplementedError
29
+
30
+
31
+ ##
32
+
33
+
34
+ @dc.dataclass(frozen=True)
35
+ class FormatTemplater(Templater):
36
+ """https://docs.python.org/3/library/string.html#format-specification-mini-language"""
37
+
38
+ fmt: str
39
+
40
+ def render(self, ctx: Templater.Context) -> str:
41
+ return self.fmt.format(**(ctx.env or {}))
42
+
43
+
44
+ ##
45
+
46
+
47
+ @dc.dataclass(frozen=True)
48
+ class Pep292Templater(Templater):
49
+ """https://peps.python.org/pep-0292/"""
50
+
51
+ tmpl: string.Template
52
+
53
+ def render(self, ctx: Templater.Context) -> str:
54
+ return self.tmpl.substitute(ctx.env or {})
55
+
56
+ @classmethod
57
+ def from_string(cls, src: str) -> 'Pep292Templater':
58
+ return cls(string.Template(src))
59
+
60
+ ##
61
+
62
+
63
+ @dc.dataclass(frozen=True)
64
+ class MinjaTemplater(Templater):
65
+ tmpl: MinjaTemplate
66
+
67
+ ENV_IDENT: ta.ClassVar[str] = 'env'
68
+
69
+ def render(self, ctx: Templater.Context) -> str:
70
+ return self.tmpl(**{self.ENV_IDENT: ctx.env or {}})
71
+
72
+ @classmethod
73
+ def from_string(
74
+ cls,
75
+ src: str,
76
+ **ns: ta.Any,
77
+ ) -> 'MinjaTemplater':
78
+ tmpl = compile_minja_template(
79
+ src,
80
+ [
81
+ MinjaTemplateParam(cls.ENV_IDENT),
82
+ *[
83
+ MinjaTemplateParam.new(k, v)
84
+ for k, v in ns.items()
85
+ ],
86
+ ],
87
+ )
88
+
89
+ return cls(tmpl)
90
+
91
+
92
+ ##
93
+
94
+
95
+ @dc.dataclass(frozen=True)
96
+ class JinjaTemplater(Templater):
97
+ tmpl: jinja2.Template
98
+
99
+ def render(self, ctx: Templater.Context) -> str:
100
+ return self.tmpl.render(**(ctx.env or {}))
101
+
102
+ @classmethod
103
+ def from_string(
104
+ cls,
105
+ src: str,
106
+ *,
107
+ env: jinja2.Environment | None = None,
108
+ **kwargs: ta.Any,
109
+ ) -> 'JinjaTemplater':
110
+ if env is None:
111
+ env = jinja2.Environment()
112
+ tmpl = env.from_string(src)
113
+ return cls(
114
+ tmpl,
115
+ **kwargs,
116
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev285
3
+ Version: 0.0.0.dev286
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -42,6 +42,7 @@ Requires-Dist: asyncpg~=0.30; extra == "all"
42
42
  Requires-Dist: apsw~=3.49; extra == "all"
43
43
  Requires-Dist: sqlean.py~=3.47; extra == "all"
44
44
  Requires-Dist: duckdb~=1.2; extra == "all"
45
+ Requires-Dist: jinja2~=3.1; extra == "all"
45
46
  Requires-Dist: pytest~=8.3; extra == "all"
46
47
  Requires-Dist: anyio~=4.9; extra == "all"
47
48
  Requires-Dist: sniffio~=1.3; extra == "all"
@@ -88,6 +89,8 @@ Requires-Dist: asyncpg~=0.30; extra == "sqldrivers"
88
89
  Requires-Dist: apsw~=3.49; extra == "sqldrivers"
89
90
  Requires-Dist: sqlean.py~=3.47; extra == "sqldrivers"
90
91
  Requires-Dist: duckdb~=1.2; extra == "sqldrivers"
92
+ Provides-Extra: templates
93
+ Requires-Dist: jinja2~=3.1; extra == "templates"
91
94
  Provides-Extra: testing
92
95
  Requires-Dist: pytest~=8.3; extra == "testing"
93
96
  Provides-Extra: plus
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=pjGUyLHaoWpPqRP3jz2u1fC1qoRc2lvrEcpU_Ax2tdg,8253
2
- omlish/__about__.py,sha256=HdBvgJvGybfoC0HT12EdWHXOYyK8r8Y4UmpMPI4FqC0,3380
2
+ omlish/__about__.py,sha256=ZhuYDjbIjfMV2ZweBFzU-Nn4cTzE8Xb5UKLXCDiLtzI,3444
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
@@ -249,7 +249,7 @@ omlish/dataclasses/generation/mangling.py,sha256=AUtTMjAAuQ_kUfE-CypnpRsiM10EAkM
249
249
  omlish/dataclasses/generation/manifests.py,sha256=tRLO59eysC13z_lbPxaErPy-xM3BIBRpj8MhmbYoGnE,309
250
250
  omlish/dataclasses/generation/ops.py,sha256=dWse_SsoXtpDqXzDPJOqBeb9G5F7RrEChfGl4iTL0QE,1718
251
251
  omlish/dataclasses/generation/plans.py,sha256=c3TRwa20quN-DrM-eI2KoTG4XVyL3n12RcwZoJxEgB0,536
252
- omlish/dataclasses/generation/processor.py,sha256=Va-8RV19jIzqreXCUeP4nFMPglAfIxeIaGOzgYTU_IY,4496
252
+ omlish/dataclasses/generation/processor.py,sha256=_rt_GHdx_pi5seRMzIu6DvLEx4MYGsG8CKykxqDiu1s,4689
253
253
  omlish/dataclasses/generation/registry.py,sha256=_Cfvs9QY6f8Pvf9cKUi-OTI-qaDem3z5jcWkSDNk3kQ,1006
254
254
  omlish/dataclasses/generation/utils.py,sha256=u6DWRvzxgqrxqyfAGzNOyDvnOJYdMTYyZ7l1oOOiXrI,2089
255
255
  omlish/dataclasses/metaclass/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -259,7 +259,7 @@ omlish/dataclasses/metaclass/meta.py,sha256=0MQG7Sl1y8QccGRgLOC0VoLDTMBG6VoyT-wZ
259
259
  omlish/dataclasses/metaclass/specs.py,sha256=djzkHK95h06Cgrx8rr3SGkv2gOvL-fPOhWOBWbbN8h4,789
260
260
  omlish/dataclasses/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
261
261
  omlish/dataclasses/processing/base.py,sha256=wkPDfeojZ2mg72yifMW7VNpJBEgEbaC3Qr_bd8_aV5E,1827
262
- omlish/dataclasses/processing/driving.py,sha256=k3SrbY1fAvRegYs_OorOeh3f5j6O7NEmL7yL7RnwVic,1033
262
+ omlish/dataclasses/processing/driving.py,sha256=AwT4kvh_GdSDfYVLBjBdkVmbO7U5LK95A_K3qTK01MY,1031
263
263
  omlish/dataclasses/processing/priority.py,sha256=57jdwUZ29Z9ZtKWIzyar4raNLHNrWd0c29ZLv2hcfjo,260
264
264
  omlish/dataclasses/processing/registry.py,sha256=iNDHwW1gsq8gTMi4XvNBBzab0OYdSKvDLQw9gCBt2FI,1884
265
265
  omlish/dataclasses/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -472,7 +472,7 @@ omlish/lang/functions.py,sha256=kSdVUJZmRcncMdU43rcQLZ5E2NMcRz6X6pppwLNHiWk,5762
472
472
  omlish/lang/generators.py,sha256=5tbjVAywiZH6oAdj1sJLRMtIkC9y3rAkecLT7Z3m7_g,5251
473
473
  omlish/lang/imports.py,sha256=aC1u2eTrxHhhxShKbJvXswe3aJ7K76vT4YK8LrsvRWU,10476
474
474
  omlish/lang/iterables.py,sha256=HOjcxOwyI5bBApDLsxRAGGhTTmw7fdZl2kEckxRVl-0,1994
475
- omlish/lang/maybes.py,sha256=IPlfurHCebyDamB2scqP-JmUODN1TWr7ZL1T7qz6Jzo,3421
475
+ omlish/lang/maybes.py,sha256=pb1YrxmpXy-hWKmWR89GxXqZq1MoUD1uuTaTX30peh0,3697
476
476
  omlish/lang/objects.py,sha256=q1T26cxLkejU5XMl5iEVC9IIhjib0VBpe7JCo2bz2Ws,5411
477
477
  omlish/lang/outcomes.py,sha256=mpFy_VoM-b74L1aCFsjsZVUHx_icZ1AHMOKeVesjOp4,8628
478
478
  omlish/lang/params.py,sha256=QmNVBfJsfxjDG5ilDPgHV7sK4UwRztkSQdLTo0umb8I,6648
@@ -508,7 +508,7 @@ omlish/lite/inject.py,sha256=-tTsOqqef-Ix5Tgl2DP_JAsNWJQDFUptERl3lk14Uzs,29007
508
508
  omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
509
509
  omlish/lite/logs.py,sha256=CWFG0NKGhqNeEgryF5atN2gkPYbUdTINEw_s1phbINM,51
510
510
  omlish/lite/marshal.py,sha256=4DCbLoimLwJakihpvMjJ_kpc7v9aZQY8P3-gkoqEGUE,18471
511
- omlish/lite/maybes.py,sha256=7OlHJ8Q2r4wQ-aRbZSlJY7x0e8gDvufFdlohGEIJ3P4,833
511
+ omlish/lite/maybes.py,sha256=I7b2dJFkDll4B_QDlI6iKJG8fy91L6_Tj_s5eB3KI7Q,1013
512
512
  omlish/lite/pycharm.py,sha256=pUOJevrPClSqTCEOkQBO11LKX2003tfDcp18a03QFrc,1163
513
513
  omlish/lite/reflect.py,sha256=pzOY2PPuHH0omdtglkN6DheXDrGopdL3PtTJnejyLFU,2189
514
514
  omlish/lite/reprs.py,sha256=QI5VBtvq_TW1TojWL25c04QfOABLi8Smt5jc5J-bArc,2008
@@ -816,9 +816,10 @@ omlish/text/glyphsplit.py,sha256=HI8TWDUaF_tJG5RnIdIjtUH_lYnjYZ7KZBANSxOXGZc,380
816
816
  omlish/text/indent.py,sha256=LOQgHskHMLVrRC6HLL9uIWay517dpvPEYQK0Igm-wm8,1341
817
817
  omlish/text/linecache.py,sha256=hRYlEhD63ZfA6_ZOTkQIcnON-3W56QMAhcG3vEJqj9M,1858
818
818
  omlish/text/mangle.py,sha256=d7j2_HPxoxF5VrLD1TShOSfnhBLH_-lQe_OH2kl0yHg,2790
819
- omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
819
+ omlish/text/minja.py,sha256=e7XiY8IvF4Df-7hxhdC_qizHm9T4SIbFJR7enUg_Zmc,7252
820
820
  omlish/text/parts.py,sha256=Q9NvoyEGQKIWgiPD4D_Qc66cWAuyEKE033dT9m7c3Wk,6662
821
821
  omlish/text/random.py,sha256=8feS5JE_tSjYlMl-lp0j93kCfzBae9AM2cXlRLebXMA,199
822
+ omlish/text/templating.py,sha256=UyYIs0wMigCDws0XfO3mYkJFH0-tO1IBaxWL7v2J3pw,2417
822
823
  omlish/text/go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
823
824
  omlish/text/go/quoting.py,sha256=N9EYdnFdEX_A8fOviH-1w4jwV3XOQ7VU2WsoUNubYVY,9137
824
825
  omlish/typedvalues/__init__.py,sha256=c3IQmRneMmH6JRcafprqmBILWD89b-IyIll6MgahGCI,562
@@ -829,9 +830,9 @@ omlish/typedvalues/holder.py,sha256=4SwRezsmuDDEO5gENGx8kTm30pblF5UktoEAu02i-Gk,
829
830
  omlish/typedvalues/marshal.py,sha256=Rr-4DZ90BoD5Z9gT18QhZH2yMA3-gPJBK8GUrGkp8VA,4245
830
831
  omlish/typedvalues/reflect.py,sha256=y_7IY8_4cLVRvD3ug-_-cDaO5RtzC1rLVFzkeAPALf8,683
831
832
  omlish/typedvalues/values.py,sha256=Q_5IiQM3Vka4wGVd-scaslb4-oCMjFcIOksIrKE-JIM,1229
832
- omlish-0.0.0.dev285.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
833
- omlish-0.0.0.dev285.dist-info/METADATA,sha256=i6luxJ7Bytyt00Qr_PwO9pmz0PIFJcjUNOnpdl-6g0U,4198
834
- omlish-0.0.0.dev285.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
835
- omlish-0.0.0.dev285.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
836
- omlish-0.0.0.dev285.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
837
- omlish-0.0.0.dev285.dist-info/RECORD,,
833
+ omlish-0.0.0.dev286.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
834
+ omlish-0.0.0.dev286.dist-info/METADATA,sha256=BEzmqld_-rBasXOChJ8Y3nUGtxUxj1Ck952qZyvSHbE,4316
835
+ omlish-0.0.0.dev286.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
836
+ omlish-0.0.0.dev286.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
837
+ omlish-0.0.0.dev286.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
838
+ omlish-0.0.0.dev286.dist-info/RECORD,,