omlish 0.0.0.dev285__py3-none-any.whl → 0.0.0.dev287__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 +6 -2
- omlish/collections/persistent/treapmap.py +5 -5
- omlish/collections/ranked.py +8 -2
- omlish/collections/sorted/skiplist.py +1 -1
- omlish/collections/sorted/sorted.py +9 -9
- omlish/dataclasses/generation/processor.py +9 -4
- omlish/dataclasses/internals.py +4 -1
- omlish/dataclasses/processing/driving.py +7 -3
- omlish/dispatch/__init__.py +12 -3
- omlish/dispatch/functions.py +3 -0
- omlish/dispatch/impls.py +10 -13
- omlish/dispatch/methods.py +69 -14
- omlish/iterators/iterators.py +3 -0
- omlish/iterators/recipes.py +3 -0
- omlish/iterators/tools.py +3 -0
- omlish/iterators/unique.py +3 -0
- omlish/lang/__init__.py +4 -0
- omlish/lang/attrs.py +70 -2
- omlish/lang/functions.py +8 -1
- omlish/lang/maybes.py +17 -0
- omlish/lite/maybes.py +17 -0
- omlish/text/minja.py +81 -25
- omlish/text/templating.py +116 -0
- {omlish-0.0.0.dev285.dist-info → omlish-0.0.0.dev287.dist-info}/METADATA +4 -1
- {omlish-0.0.0.dev285.dist-info → omlish-0.0.0.dev287.dist-info}/RECORD +29 -28
- {omlish-0.0.0.dev285.dist-info → omlish-0.0.0.dev287.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev285.dist-info → omlish-0.0.0.dev287.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev285.dist-info → omlish-0.0.0.dev287.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev285.dist-info → omlish-0.0.0.dev287.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
__version__ = '0.0.0.
|
2
|
-
__revision__ = '
|
1
|
+
__version__ = '0.0.0.dev287'
|
2
|
+
__revision__ = 'b5569962801bfa1ab3457339502eb364ee51bb0e'
|
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
|
],
|
@@ -70,11 +70,11 @@ class TreapMap(PersistentMap[K, V]):
|
|
70
70
|
return n.value
|
71
71
|
|
72
72
|
def __iter__(self) -> ta.Iterator[tuple[K, V]]:
|
73
|
-
i = self.
|
73
|
+
i = self.items()
|
74
74
|
while i.has_next():
|
75
75
|
yield i.next()
|
76
76
|
|
77
|
-
def
|
77
|
+
def items(self) -> 'TreapMapIterator[K, V]':
|
78
78
|
i = TreapMapIterator(
|
79
79
|
_st=[],
|
80
80
|
_n=self._n,
|
@@ -84,7 +84,7 @@ class TreapMap(PersistentMap[K, V]):
|
|
84
84
|
i._n = n.left # noqa
|
85
85
|
return i
|
86
86
|
|
87
|
-
def
|
87
|
+
def items_from(self, k: K) -> 'TreapMapIterator[K, V]':
|
88
88
|
lst = treap.place(self._n, (k, None), self._c) # type: ignore
|
89
89
|
i = TreapMapIterator(
|
90
90
|
_st=lst,
|
@@ -92,7 +92,7 @@ class TreapMap(PersistentMap[K, V]):
|
|
92
92
|
)
|
93
93
|
return i
|
94
94
|
|
95
|
-
def
|
95
|
+
def items_desc(self) -> 'TreapMapReverseIterator[K, V]':
|
96
96
|
i = TreapMapReverseIterator(
|
97
97
|
_st=[],
|
98
98
|
_n=self._n,
|
@@ -102,7 +102,7 @@ class TreapMap(PersistentMap[K, V]):
|
|
102
102
|
i._n = n.right # noqa
|
103
103
|
return i
|
104
104
|
|
105
|
-
def
|
105
|
+
def items_from_desc(self, k: K) -> 'TreapMapReverseIterator[K, V]':
|
106
106
|
lst = treap.place(self._n, (k, None), self._c, desc=True) # type: ignore
|
107
107
|
i = TreapMapReverseIterator(
|
108
108
|
_st=lst,
|
omlish/collections/ranked.py
CHANGED
@@ -15,7 +15,10 @@ class RankedSeq(ta.Sequence[T]):
|
|
15
15
|
super().__init__()
|
16
16
|
|
17
17
|
self._lst = list(it)
|
18
|
-
self._ranks: ta.Mapping[T, int] = (
|
18
|
+
self._ranks: ta.Mapping[T, int] = (
|
19
|
+
(IdentityKeyDict if identity else dict)
|
20
|
+
((e, i) for i, e in enumerate(self._lst))
|
21
|
+
)
|
19
22
|
if len(self._ranks) != len(self._lst):
|
20
23
|
raise ValueError(f'{len(self._ranks)} != {len(self._lst)}')
|
21
24
|
|
@@ -51,7 +54,10 @@ class RankedSetSeq(ta.Sequence[ta.AbstractSet[T]]):
|
|
51
54
|
super().__init__()
|
52
55
|
|
53
56
|
self._lst = [(IdentitySet if identity else set)(e) for e in it]
|
54
|
-
self._ranks: ta.Mapping[T, int] = (
|
57
|
+
self._ranks: ta.Mapping[T, int] = (
|
58
|
+
(IdentityKeyDict if identity else dict)
|
59
|
+
((e, i) for i, es in enumerate(self._lst) for e in es)
|
60
|
+
)
|
55
61
|
if len(self._ranks) != sum(map(len, self._lst)):
|
56
62
|
raise ValueError(f'{len(self._ranks)} != {sum(map(len, self._lst))}')
|
57
63
|
|
@@ -182,7 +182,7 @@ class SkipList(SortedCollection[T]):
|
|
182
182
|
yield cur.value # type: ignore
|
183
183
|
cur = cur.next[0]
|
184
184
|
|
185
|
-
def
|
185
|
+
def iter_desc(self, base: T | None = None) -> ta.Iterable[T]:
|
186
186
|
if base is not None:
|
187
187
|
cur = self._find(base)
|
188
188
|
while cur is not self._head and self._compare(base, cur.value) < 0: # type: ignore
|
@@ -51,7 +51,7 @@ class SortedCollection(lang.Abstract, ta.Collection[T]):
|
|
51
51
|
raise NotImplementedError
|
52
52
|
|
53
53
|
@abc.abstractmethod
|
54
|
-
def
|
54
|
+
def iter_desc(self, base: T | None = None) -> ta.Iterable[T]:
|
55
55
|
raise NotImplementedError
|
56
56
|
|
57
57
|
|
@@ -61,15 +61,15 @@ class SortedMapping(ta.Mapping[K, V]):
|
|
61
61
|
raise NotImplementedError
|
62
62
|
|
63
63
|
@abc.abstractmethod
|
64
|
-
def
|
64
|
+
def items_desc(self) -> ta.Iterator[tuple[K, V]]:
|
65
65
|
raise NotImplementedError
|
66
66
|
|
67
67
|
@abc.abstractmethod
|
68
|
-
def
|
68
|
+
def items_from(self, key: K) -> ta.Iterator[tuple[K, V]]:
|
69
69
|
raise NotImplementedError
|
70
70
|
|
71
71
|
@abc.abstractmethod
|
72
|
-
def
|
72
|
+
def items_from_desc(self, key: K) -> ta.Iterator[tuple[K, V]]:
|
73
73
|
raise NotImplementedError
|
74
74
|
|
75
75
|
|
@@ -115,11 +115,11 @@ class SortedListDict(SortedMutableMapping[K, V]):
|
|
115
115
|
def items(self) -> ta.Iterator[tuple[K, V]]: # type: ignore
|
116
116
|
yield from self._impl.iter()
|
117
117
|
|
118
|
-
def
|
119
|
-
yield from self._impl.
|
118
|
+
def items_desc(self) -> ta.Iterator[tuple[K, V]]:
|
119
|
+
yield from self._impl.iter_desc()
|
120
120
|
|
121
|
-
def
|
121
|
+
def items_from(self, key: K) -> ta.Iterator[tuple[K, V]]:
|
122
122
|
yield from self._impl.iter((key, None))
|
123
123
|
|
124
|
-
def
|
125
|
-
yield from self._impl.
|
124
|
+
def items_from_desc(self, key: K) -> ta.Iterator[tuple[K, V]]:
|
125
|
+
yield from self._impl.iter_desc((key, None))
|
@@ -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
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
omlish/dataclasses/internals.py
CHANGED
@@ -75,9 +75,12 @@ class StdFieldType(enum.Enum):
|
|
75
75
|
INIT_VAR = dc._FIELD_INITVAR # type: ignore # noqa
|
76
76
|
|
77
77
|
|
78
|
+
STD_FIELD_TYPE_MAP: ta.Mapping[ta.Any, StdFieldType] = {v.value: v for v in StdFieldType}
|
79
|
+
|
80
|
+
|
78
81
|
def std_field_type(f: dc.Field) -> StdFieldType:
|
79
82
|
if (ft := getattr(f, '_field_type')) is not None:
|
80
|
-
return
|
83
|
+
return STD_FIELD_TYPE_MAP[ft]
|
81
84
|
else:
|
82
85
|
return StdFieldType.INSTANCE
|
83
86
|
|
@@ -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
|
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/dispatch/__init__.py
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
-
from .dispatch import
|
2
|
-
|
3
|
-
|
1
|
+
from .dispatch import ( # noqa
|
2
|
+
Dispatcher,
|
3
|
+
)
|
4
|
+
|
5
|
+
from .functions import ( # noqa
|
6
|
+
function,
|
7
|
+
)
|
8
|
+
|
9
|
+
from .methods import ( # noqa
|
10
|
+
install_method,
|
11
|
+
method,
|
12
|
+
)
|
omlish/dispatch/functions.py
CHANGED
omlish/dispatch/impls.py
CHANGED
@@ -5,8 +5,8 @@ TODO:
|
|
5
5
|
- multidispatch? never solved..
|
6
6
|
- just generic on tuple[A0, A1, ...]
|
7
7
|
"""
|
8
|
+
import inspect
|
8
9
|
import typing as ta
|
9
|
-
import weakref
|
10
10
|
|
11
11
|
from .. import c3
|
12
12
|
from .. import check
|
@@ -19,15 +19,7 @@ T = ta.TypeVar('T')
|
|
19
19
|
##
|
20
20
|
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def get_impl_func_cls_set(func: ta.Callable) -> frozenset[type]:
|
26
|
-
try:
|
27
|
-
return _IMPL_FUNC_CLS_SET_CACHE[func]
|
28
|
-
except KeyError:
|
29
|
-
pass
|
30
|
-
|
22
|
+
def get_impl_func_cls_set(func: ta.Callable, *, arg_offset: int = 0) -> frozenset[type]:
|
31
23
|
ann = getattr(func, '__annotations__', {})
|
32
24
|
if not ann:
|
33
25
|
raise TypeError(f'Invalid impl func: {func!r}')
|
@@ -39,8 +31,11 @@ def get_impl_func_cls_set(func: ta.Callable) -> frozenset[type]:
|
|
39
31
|
return check.isinstance(a, type)
|
40
32
|
|
41
33
|
# Exclude 'return' to support difficult to handle return types - they are unimportant.
|
42
|
-
|
43
|
-
|
34
|
+
th_dct = rfl.get_filtered_type_hints(func, exclude=['return'])
|
35
|
+
|
36
|
+
ps = inspect.signature(func).parameters
|
37
|
+
p = list(ps.values())[arg_offset]
|
38
|
+
cls = th_dct[p.name]
|
44
39
|
|
45
40
|
rty = rfl.type_(cls)
|
46
41
|
if isinstance(rty, rfl.Union):
|
@@ -48,10 +43,12 @@ def get_impl_func_cls_set(func: ta.Callable) -> frozenset[type]:
|
|
48
43
|
else:
|
49
44
|
ret = frozenset([erase(rty)])
|
50
45
|
|
51
|
-
_IMPL_FUNC_CLS_SET_CACHE[func] = ret
|
52
46
|
return ret
|
53
47
|
|
54
48
|
|
49
|
+
##
|
50
|
+
|
51
|
+
|
55
52
|
def find_impl(cls: type, registry: ta.Mapping[type, T]) -> T | None:
|
56
53
|
mro = c3.compose_mro(cls, registry.keys())
|
57
54
|
|
omlish/dispatch/methods.py
CHANGED
@@ -18,14 +18,25 @@ from .impls import get_impl_func_cls_set
|
|
18
18
|
T = ta.TypeVar('T')
|
19
19
|
|
20
20
|
|
21
|
+
##
|
22
|
+
|
23
|
+
|
21
24
|
class Method:
|
22
|
-
def __init__(
|
25
|
+
def __init__(
|
26
|
+
self,
|
27
|
+
func: ta.Callable,
|
28
|
+
*,
|
29
|
+
installable: bool = False,
|
30
|
+
) -> None:
|
31
|
+
super().__init__()
|
32
|
+
|
23
33
|
if not callable(func) and not hasattr(func, '__get__'): # type: ignore
|
24
34
|
raise TypeError(f'{func!r} is not callable or a descriptor')
|
25
35
|
|
26
36
|
self._func = func
|
37
|
+
self._installable = installable
|
27
38
|
|
28
|
-
self._impls: ta.
|
39
|
+
self._impls: ta.MutableMapping[ta.Callable, frozenset[type] | None] = weakref.WeakKeyDictionary()
|
29
40
|
|
30
41
|
# bpo-45678: special-casing for classmethod/staticmethod in Python <=3.9, as functools.update_wrapper doesn't
|
31
42
|
# work properly in singledispatchmethod.__get__ if it is applied to an unbound classmethod/staticmethod
|
@@ -48,6 +59,15 @@ class Method:
|
|
48
59
|
|
49
60
|
self._dispatch_func_cache_remove = dispatch_func_cache_remove
|
50
61
|
|
62
|
+
self._owner: type | None = None
|
63
|
+
self._name: str | None = None
|
64
|
+
|
65
|
+
def __set_name__(self, owner, name):
|
66
|
+
if self._owner is None:
|
67
|
+
self._owner = owner
|
68
|
+
if self._name is None:
|
69
|
+
self._name = name
|
70
|
+
|
51
71
|
def __repr__(self) -> str:
|
52
72
|
return f'<{type(self).__module__}.{type(self).__qualname__}:{self._func} at 0x{id(self):x}>'
|
53
73
|
|
@@ -61,7 +81,7 @@ class Method:
|
|
61
81
|
setattr(wrapper, '__isabstractmethod__', self._is_abstractmethod) # noqa
|
62
82
|
return wrapper
|
63
83
|
|
64
|
-
def register(self, impl: T) -> T:
|
84
|
+
def register(self, impl: T, cls_set: frozenset[type] | None = None) -> T:
|
65
85
|
# bpo-39679: in Python <= 3.9, classmethods and staticmethods don't inherit __annotations__ of the wrapped
|
66
86
|
# function (fixed in 3.10+ as a side-effect of bpo-43682) but we need that for annotation-derived
|
67
87
|
# singledispatches. So we add that just-in-time here.
|
@@ -70,7 +90,7 @@ class Method:
|
|
70
90
|
|
71
91
|
check.callable(impl)
|
72
92
|
if impl not in self._impls:
|
73
|
-
self._impls
|
93
|
+
self._impls[impl] = cls_set # type: ignore
|
74
94
|
self._dispatch_func_cache.clear()
|
75
95
|
|
76
96
|
return impl
|
@@ -85,14 +105,23 @@ class Method:
|
|
85
105
|
hash(att)
|
86
106
|
except TypeError:
|
87
107
|
continue
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
108
|
+
|
109
|
+
if att not in self._impls:
|
110
|
+
continue
|
111
|
+
cls_set = self._impls[att]
|
112
|
+
|
113
|
+
if cls_set is None:
|
114
|
+
cls_set = get_impl_func_cls_set(att, arg_offset=1)
|
115
|
+
self._impls[att] = cls_set
|
116
|
+
|
117
|
+
try:
|
118
|
+
ex_nam = seen[att]
|
119
|
+
except KeyError:
|
120
|
+
pass
|
121
|
+
else:
|
122
|
+
raise TypeError(f'Duplicate impl: {owner_cls} {instance_cls} {nam} {ex_nam}')
|
123
|
+
|
124
|
+
disp.register(nam, cls_set)
|
96
125
|
|
97
126
|
return disp
|
98
127
|
|
@@ -106,9 +135,11 @@ class Method:
|
|
106
135
|
def __call__(self, *args, **kwargs): # noqa
|
107
136
|
if not args:
|
108
137
|
raise TypeError(f'{func_name} requires at least 1 positional argument')
|
138
|
+
|
109
139
|
if (impl_att := dispatch(type_(args[0]))) is not None:
|
110
140
|
fn = getattr_(self, impl_att)
|
111
141
|
return fn(*args, **kwargs)
|
142
|
+
|
112
143
|
return base_func.__get__(self)(*args, **kwargs) # noqa
|
113
144
|
|
114
145
|
self.update_wrapper(__call__)
|
@@ -148,5 +179,29 @@ class Method:
|
|
148
179
|
return func.__get__(instance)(*args, **kwargs) # noqa
|
149
180
|
|
150
181
|
|
151
|
-
def method(func): # noqa
|
152
|
-
|
182
|
+
def method(func=None, /, *, installable=False): # noqa
|
183
|
+
kw = dict(installable=installable)
|
184
|
+
if func is None:
|
185
|
+
return functools.partial(Method, **kw)
|
186
|
+
return Method(func, **kw)
|
187
|
+
|
188
|
+
|
189
|
+
def install_method(mth: ta.Any, *, name: str | None = None) -> ta.Callable[[T], T]:
|
190
|
+
mth = check.isinstance(mth, Method)
|
191
|
+
if not mth._installable: # noqa
|
192
|
+
raise TypeError(f'Method not installable: {mth}')
|
193
|
+
|
194
|
+
def inner(fn):
|
195
|
+
a = name
|
196
|
+
if a is None:
|
197
|
+
a = fn.__name__
|
198
|
+
|
199
|
+
cls: type = check.not_none(mth._owner) # noqa
|
200
|
+
check.arg(not hasattr(cls, a))
|
201
|
+
setattr(cls, a, fn)
|
202
|
+
|
203
|
+
mth.register(fn)
|
204
|
+
|
205
|
+
return fn
|
206
|
+
|
207
|
+
return inner
|
omlish/iterators/iterators.py
CHANGED
omlish/iterators/recipes.py
CHANGED
omlish/iterators/tools.py
CHANGED
omlish/iterators/unique.py
CHANGED
omlish/lang/__init__.py
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
from .attrs import ( # noqa
|
2
2
|
AttrOps,
|
3
|
+
AttributePresentError,
|
3
4
|
DictAttrOps,
|
4
5
|
STD_ATTR_OPS,
|
6
|
+
SetAttrIfPresent,
|
5
7
|
StdAttrOps,
|
6
8
|
TRANSIENT_ATTR_OPS,
|
7
9
|
TransientAttrOps,
|
8
10
|
TransientDict,
|
11
|
+
set_attr,
|
9
12
|
transient_delattr,
|
10
13
|
transient_getattr,
|
11
14
|
transient_setattr,
|
@@ -130,6 +133,7 @@ from .functions import ( # noqa
|
|
130
133
|
Args,
|
131
134
|
VoidError,
|
132
135
|
as_async,
|
136
|
+
call_with,
|
133
137
|
coalesce,
|
134
138
|
constant,
|
135
139
|
finally_,
|
omlish/lang/attrs.py
CHANGED
@@ -1,8 +1,76 @@
|
|
1
1
|
import abc
|
2
2
|
import collections.abc
|
3
|
+
import functools
|
3
4
|
import typing as ta
|
4
5
|
|
5
6
|
|
7
|
+
T = ta.TypeVar('T')
|
8
|
+
|
9
|
+
|
10
|
+
##
|
11
|
+
|
12
|
+
|
13
|
+
class AttributePresentError(Exception):
|
14
|
+
pass
|
15
|
+
|
16
|
+
|
17
|
+
SetAttrIfPresent: ta.TypeAlias = ta.Literal['overwrite', 'leave', 'raise']
|
18
|
+
|
19
|
+
|
20
|
+
_NO_SET_ATTR_VALUE = object()
|
21
|
+
|
22
|
+
|
23
|
+
@ta.overload
|
24
|
+
def set_attr(
|
25
|
+
obj: ta.Any,
|
26
|
+
name: str,
|
27
|
+
*,
|
28
|
+
if_present: SetAttrIfPresent = 'overwrite',
|
29
|
+
) -> ta.Callable[[T], T]:
|
30
|
+
...
|
31
|
+
|
32
|
+
|
33
|
+
@ta.overload
|
34
|
+
def set_attr(
|
35
|
+
obj: ta.Any,
|
36
|
+
name: str,
|
37
|
+
value: T,
|
38
|
+
*,
|
39
|
+
if_present: SetAttrIfPresent = 'overwrite',
|
40
|
+
) -> T:
|
41
|
+
...
|
42
|
+
|
43
|
+
|
44
|
+
def set_attr(
|
45
|
+
obj,
|
46
|
+
name,
|
47
|
+
value=_NO_SET_ATTR_VALUE,
|
48
|
+
*,
|
49
|
+
if_present='overwrite',
|
50
|
+
):
|
51
|
+
if value is _NO_SET_ATTR_VALUE:
|
52
|
+
return functools.partial(
|
53
|
+
set_attr,
|
54
|
+
obj,
|
55
|
+
name,
|
56
|
+
if_present=if_present,
|
57
|
+
)
|
58
|
+
|
59
|
+
if hasattr(obj, name):
|
60
|
+
if if_present == 'overwrite':
|
61
|
+
pass
|
62
|
+
elif if_present == 'leave':
|
63
|
+
return value
|
64
|
+
elif if_present == 'raise':
|
65
|
+
raise AttributePresentError(name)
|
66
|
+
else:
|
67
|
+
raise ValueError(if_present)
|
68
|
+
|
69
|
+
setattr(obj, name, value)
|
70
|
+
|
71
|
+
return value
|
72
|
+
|
73
|
+
|
6
74
|
##
|
7
75
|
|
8
76
|
|
@@ -24,7 +92,7 @@ class AttrOps(abc.ABC):
|
|
24
92
|
raise NotImplementedError
|
25
93
|
|
26
94
|
|
27
|
-
|
95
|
+
#
|
28
96
|
|
29
97
|
|
30
98
|
class StdAttrOps(AttrOps):
|
@@ -44,7 +112,7 @@ class StdAttrOps(AttrOps):
|
|
44
112
|
STD_ATTR_OPS = StdAttrOps()
|
45
113
|
|
46
114
|
|
47
|
-
|
115
|
+
#
|
48
116
|
|
49
117
|
|
50
118
|
class DictAttrOps(AttrOps):
|
omlish/lang/functions.py
CHANGED
@@ -22,7 +22,14 @@ def is_lambda(f: ta.Any) -> bool:
|
|
22
22
|
##
|
23
23
|
|
24
24
|
|
25
|
-
def
|
25
|
+
def call_with(fn: ta.Any, *args: ta.Any, **kwargs: ta.Any) -> ta.Callable[[T], T]:
|
26
|
+
def inner(obj):
|
27
|
+
fn(obj, *args, **kwargs)
|
28
|
+
return obj
|
29
|
+
return inner
|
30
|
+
|
31
|
+
|
32
|
+
def maybe_call(obj: ta.Any, att: str, *args, default: ta.Any = None, **kwargs: ta.Any) -> ta.Any:
|
26
33
|
try:
|
27
34
|
fn = getattr(obj, att)
|
28
35
|
except AttributeError:
|
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
|
-
|
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.
|
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) ->
|
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
|
-
|
132
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
210
|
+
lines.append(self._indent(stmt + ':', -1))
|
154
211
|
elif stmt.strip() == 'else':
|
155
212
|
check.equal(self._stack[-1], 'if')
|
156
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
177
|
-
|
178
|
-
ns = {
|
179
|
-
'__StringIO': io.StringIO,
|
180
|
-
}
|
233
|
+
lines.append(self._indent('return __output.getvalue()'))
|
181
234
|
|
182
|
-
return ('\n'.join(
|
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
|
-
|
256
|
+
rendered = self.render()
|
204
257
|
|
205
258
|
render_fn = self._make_fn(
|
206
259
|
self._RENDER_FN_NAME,
|
207
|
-
|
208
|
-
|
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(
|
218
|
-
|
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.
|
3
|
+
Version: 0.0.0.dev287
|
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=
|
2
|
+
omlish/__about__.py,sha256=i-F-KstjC74KdNV4E5DhZUVUlbu5XeNyaWrDZaDrQtw,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
|
@@ -153,7 +153,7 @@ omlish/collections/hasheq.py,sha256=swOBPEnU_C0SU3VqWJX9mr0BfZLD0A-4Ke9Vahj3fE4,
|
|
153
153
|
omlish/collections/identity.py,sha256=xtoczgBPYzr6r2lJS-eti2kEnN8rVDvNGDCG3TA6vRo,3405
|
154
154
|
omlish/collections/mappings.py,sha256=iXb7oq1rCQak0KgzblgrzWCJLrkfJAYHFvl9lprOVUI,2804
|
155
155
|
omlish/collections/ordered.py,sha256=7zTbrAt12rf6i33XHkQERKar258fJacaw_WbtGEBgWo,2338
|
156
|
-
omlish/collections/ranked.py,sha256=
|
156
|
+
omlish/collections/ranked.py,sha256=McB8C2UQfUvrbmxGTpBz1-EZuyCLkBFtktzncMdt8_Y,2287
|
157
157
|
omlish/collections/unmodifiable.py,sha256=X7kKhPFdZF4m28SfLDxZL-riWlhbZffdPv35aTP30YM,4753
|
158
158
|
omlish/collections/utils.py,sha256=voqecDPFuqSLN8IwJDKyy-HnecEU4JYOXxd1HAaEuMY,2900
|
159
159
|
omlish/collections/cache/__init__.py,sha256=D1gO71VcwxFTZP9gAc9isHfg_TEdalwhsJcgGLvS9hg,233
|
@@ -170,10 +170,10 @@ omlish/collections/kv/wrappers.py,sha256=nUtoiArK1Fu2TgxFrqZU69bEoAxKJ_nA7qMeeih
|
|
170
170
|
omlish/collections/persistent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
171
171
|
omlish/collections/persistent/persistent.py,sha256=6CuzeZjZMqBLflU-CuWu32SrtZXFrJOV-H_UUuYoTkg,880
|
172
172
|
omlish/collections/persistent/treap.py,sha256=o7vhnn8kHde_Plk0sojlJZkkKwp8hpj2IekhcvbYqHs,7739
|
173
|
-
omlish/collections/persistent/treapmap.py,sha256=
|
173
|
+
omlish/collections/persistent/treapmap.py,sha256=lLxjHeR5pFFperrlw3tKIpe20xtszETG3_26EMAwhB4,5793
|
174
174
|
omlish/collections/sorted/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
175
|
-
omlish/collections/sorted/skiplist.py,sha256=
|
176
|
-
omlish/collections/sorted/sorted.py,sha256=
|
175
|
+
omlish/collections/sorted/skiplist.py,sha256=4BqAAxOAb0VM33bny-rdrFM9d2jVbyxsN7yHz3jrqG4,6035
|
176
|
+
omlish/collections/sorted/sorted.py,sha256=IWQm5uyxuskCoX1fCtlBcYlGKdyxQQNMwnTj__eoZS8,3356
|
177
177
|
omlish/concurrent/__init__.py,sha256=9p-s8MvBEYDqHIoYU3OYoe-Nni22QdkW7nhZGEukJTM,197
|
178
178
|
omlish/concurrent/executors.py,sha256=mF-rjJWzNFxwB1-_H7rHuwoImpl4FtNM6W3wcqM3NEE,1291
|
179
179
|
omlish/concurrent/futures.py,sha256=870tx8ELI8THvMnTrQoYIlEFKO9hM4KUrlehckJqKBU,4238
|
@@ -206,7 +206,7 @@ omlish/dataclasses/__init__.py,sha256=xo5rJYrQ2JE5jcX4fHv5e9bC6RIXFd-K8yurUP20oO
|
|
206
206
|
omlish/dataclasses/debug.py,sha256=giBiv6aXvX0IagwNCW64qBzNjfOFr3-VmgDy_KYlb-k,29
|
207
207
|
omlish/dataclasses/errors.py,sha256=tyv3WR6az66uGGiq9FIuCHvy1Ef-G7zeMY7mMG6hy2Y,2527
|
208
208
|
omlish/dataclasses/inspect.py,sha256=BlpPghVCU3w_YDnONEqqE99YHzJM2q3eoqe39YX25Ko,4596
|
209
|
-
omlish/dataclasses/internals.py,sha256=
|
209
|
+
omlish/dataclasses/internals.py,sha256=vIGCZnStgD3ef4drYRtVOrxhxmAPa0vJpo4pXcDcQvM,3073
|
210
210
|
omlish/dataclasses/reflection.py,sha256=5N4acL27xwSnQJvoks6ts2JseGfwL_P9D2gM9vqtAFM,2243
|
211
211
|
omlish/dataclasses/specs.py,sha256=h9qD2xAijKAS95Iw3GUPx3mj1peoUOlgh7aXtqVfmDU,6073
|
212
212
|
omlish/dataclasses/utils.py,sha256=_1B6tEkkcxHVoLBEo34ebR_0E-iZW7W0zFTo27EdSqY,1854
|
@@ -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=
|
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=
|
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
|
@@ -286,13 +286,13 @@ omlish/diag/replserver/__init__.py,sha256=uLo6V2aQ29v9z3IMELlPDSlG3_2iOT4-_X8Vni
|
|
286
286
|
omlish/diag/replserver/__main__.py,sha256=LmU41lQ58bm1h4Mx7S8zhE_uEBSC6kPcp9mn5JRpulA,32
|
287
287
|
omlish/diag/replserver/console.py,sha256=XzBDVhYlr8FY6ym4OwoaIHuFOHnGK3dTYlMDIOMUUlA,7410
|
288
288
|
omlish/diag/replserver/server.py,sha256=pqJZXKnD-Cc03hnL_FNqGYaW9kH-IM3e11vCyDAcBD8,5374
|
289
|
-
omlish/dispatch/__init__.py,sha256=
|
289
|
+
omlish/dispatch/__init__.py,sha256=UwVT6SSk5HKk9xF9vc_UJD8BDSIQWSw98Ldx-G-6PC0,166
|
290
290
|
omlish/dispatch/_dispatch2.py,sha256=70k1tKKvuhxtAu6v4skECfHKIKVWrmlt7G_JKLUsKEs,1966
|
291
291
|
omlish/dispatch/_dispatch3.py,sha256=9Zjd7bINAC3keiaBdssc4v5dY0-8OI6XooV2DR9U7Z0,2818
|
292
292
|
omlish/dispatch/dispatch.py,sha256=KA5l49AiGLRjp4J7RDJW9RiDp9WUD1ewR1AOPEF8g38,3062
|
293
|
-
omlish/dispatch/functions.py,sha256=
|
294
|
-
omlish/dispatch/impls.py,sha256=
|
295
|
-
omlish/dispatch/methods.py,sha256=
|
293
|
+
omlish/dispatch/functions.py,sha256=cwNzGIg2ZIalEgn9I03cnJVbMTHjWloyDTaowlO3UPs,1524
|
294
|
+
omlish/dispatch/impls.py,sha256=K_okKvpZml4NkTHJmTVyMQSrIaIJcqTEgkreGwukaOw,1895
|
295
|
+
omlish/dispatch/methods.py,sha256=7jNKvwGNW9CJRTMDZyedmrWJN7Y9-ToI7YOAQ8VJu5Q,6786
|
296
296
|
omlish/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
297
297
|
omlish/docker/all.py,sha256=xXRgJgLGPwAtr7bDMJ_Dp9jTfOwfGvohNhc6LsoELJc,514
|
298
298
|
omlish/docker/cli.py,sha256=gtb9kitVfGnd4cr587NsVVk8D5Ok5y5SAsqD_SwGrSA,2565
|
@@ -455,12 +455,12 @@ omlish/io/fdio/kqueue.py,sha256=YgGBQibkAUYODYDiGl7Enjtx1oQsJXuDsBLBXgqlLQw,3832
|
|
455
455
|
omlish/io/fdio/manager.py,sha256=q4wWf7nKrNtjx6yPEvrVnFt4UtK_BTvVlquEGw7poEo,1250
|
456
456
|
omlish/io/fdio/pollers.py,sha256=yNadAt3W5wd90PFmd3vD77bq5QwoVb2A6SM2JjZpKRs,5507
|
457
457
|
omlish/iterators/__init__.py,sha256=yMavf5FofiS1EU4UFuWPXiFZ03W0H-y7MuMxW8FUaEE,358
|
458
|
-
omlish/iterators/iterators.py,sha256=
|
459
|
-
omlish/iterators/recipes.py,sha256=
|
460
|
-
omlish/iterators/tools.py,sha256=
|
461
|
-
omlish/iterators/unique.py,sha256=
|
462
|
-
omlish/lang/__init__.py,sha256=
|
463
|
-
omlish/lang/attrs.py,sha256=
|
458
|
+
omlish/iterators/iterators.py,sha256=RxW35yQ5ed8vBQ22IqpDXFx-i5JiLQdp7-pkMZXhJJ8,3159
|
459
|
+
omlish/iterators/recipes.py,sha256=wOwOZg-zWG9Zc3wcAxJFSe2rtavVBYwZOfG09qYEx_4,472
|
460
|
+
omlish/iterators/tools.py,sha256=c4hArZEVV8y9_dFfmRwakusv1cWJLT4MkTkGRjnGN5U,2556
|
461
|
+
omlish/iterators/unique.py,sha256=Nw0pSaNEcHAkve0ugfLPvJcirDOn9ECyC5wIL8JlJKI,1395
|
462
|
+
omlish/lang/__init__.py,sha256=hv6BlnJfD7gHFyOGXl1lgbo3vHkmsivqy462JwA04tM,5316
|
463
|
+
omlish/lang/attrs.py,sha256=i7euRF81uNF8QDmUVXSK_BtqLGshaMi4VVdUnMjiMwg,5050
|
464
464
|
omlish/lang/clsdct.py,sha256=HAGIvBSbCefzRjXriwYSBLO7QHKRv2UsE78jixOb-fA,1828
|
465
465
|
omlish/lang/collections.py,sha256=aGi0j6VzVe2nz4l357Y4RD5_XNl8OJbmM5qM6BclrrY,1895
|
466
466
|
omlish/lang/comparison.py,sha256=MOwEG0Yny-jBPHO9kQto9FSRyeNpQW24UABsghkrHxY,1356
|
@@ -468,11 +468,11 @@ omlish/lang/contextmanagers.py,sha256=UPH6daYwSP9cH5AfSVsJyEHk1UURMGhVPM5ZRhp_Hv
|
|
468
468
|
omlish/lang/datetimes.py,sha256=mrTtA67JYpfQwSlzdPcBtvm6dAyYM_dXNnlxFwFQH0M,228
|
469
469
|
omlish/lang/descriptors.py,sha256=zBtgO9LjdSTGHNUgiIqswh78WOVoGH6KzS0NbgB1Wls,6572
|
470
470
|
omlish/lang/enums.py,sha256=F9tflHfaAoV2MpyuhZzpfX9-H55M3zNa9hCszsngEo8,111
|
471
|
-
omlish/lang/functions.py,sha256=
|
471
|
+
omlish/lang/functions.py,sha256=bg2IxTFmd_J22qF3XWIRBvSIpLwPRiH_KxGXcm0QVrc,5944
|
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=
|
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=
|
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=
|
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.
|
833
|
-
omlish-0.0.0.
|
834
|
-
omlish-0.0.0.
|
835
|
-
omlish-0.0.0.
|
836
|
-
omlish-0.0.0.
|
837
|
-
omlish-0.0.0.
|
833
|
+
omlish-0.0.0.dev287.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
834
|
+
omlish-0.0.0.dev287.dist-info/METADATA,sha256=2lOtfXV-sPk2hcxlOFk_TruhqdiAsg_MTdrhMSxI0o0,4316
|
835
|
+
omlish-0.0.0.dev287.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
836
|
+
omlish-0.0.0.dev287.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
837
|
+
omlish-0.0.0.dev287.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
838
|
+
omlish-0.0.0.dev287.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|