omlish 0.0.0.dev1__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.
Potentially problematic release.
This version of omlish might be problematic. Click here for more details.
- omlish/__about__.py +7 -0
- omlish/__init__.py +0 -0
- omlish/argparse.py +223 -0
- omlish/asyncs/__init__.py +17 -0
- omlish/asyncs/anyio.py +23 -0
- omlish/asyncs/asyncio.py +19 -0
- omlish/asyncs/asyncs.py +76 -0
- omlish/asyncs/futures.py +179 -0
- omlish/asyncs/trio.py +11 -0
- omlish/c3.py +173 -0
- omlish/cached.py +9 -0
- omlish/check.py +231 -0
- omlish/collections/__init__.py +63 -0
- omlish/collections/_abc.py +156 -0
- omlish/collections/_io_abc.py +78 -0
- omlish/collections/cache/__init__.py +11 -0
- omlish/collections/cache/descriptor.py +188 -0
- omlish/collections/cache/impl.py +485 -0
- omlish/collections/cache/types.py +37 -0
- omlish/collections/coerce.py +337 -0
- omlish/collections/frozen.py +148 -0
- omlish/collections/identity.py +106 -0
- omlish/collections/indexed.py +75 -0
- omlish/collections/mappings.py +127 -0
- omlish/collections/ordered.py +81 -0
- omlish/collections/persistent.py +36 -0
- omlish/collections/skiplist.py +193 -0
- omlish/collections/sorted.py +126 -0
- omlish/collections/treap.py +228 -0
- omlish/collections/treapmap.py +144 -0
- omlish/collections/unmodifiable.py +174 -0
- omlish/collections/utils.py +110 -0
- omlish/configs/__init__.py +0 -0
- omlish/configs/flattening.py +147 -0
- omlish/configs/props.py +64 -0
- omlish/dataclasses/__init__.py +83 -0
- omlish/dataclasses/impl/__init__.py +6 -0
- omlish/dataclasses/impl/api.py +260 -0
- omlish/dataclasses/impl/as_.py +76 -0
- omlish/dataclasses/impl/exceptions.py +2 -0
- omlish/dataclasses/impl/fields.py +148 -0
- omlish/dataclasses/impl/frozen.py +55 -0
- omlish/dataclasses/impl/hashing.py +85 -0
- omlish/dataclasses/impl/init.py +173 -0
- omlish/dataclasses/impl/internals.py +118 -0
- omlish/dataclasses/impl/main.py +150 -0
- omlish/dataclasses/impl/metaclass.py +126 -0
- omlish/dataclasses/impl/metadata.py +74 -0
- omlish/dataclasses/impl/order.py +47 -0
- omlish/dataclasses/impl/params.py +150 -0
- omlish/dataclasses/impl/processing.py +16 -0
- omlish/dataclasses/impl/reflect.py +173 -0
- omlish/dataclasses/impl/replace.py +40 -0
- omlish/dataclasses/impl/repr.py +34 -0
- omlish/dataclasses/impl/simple.py +92 -0
- omlish/dataclasses/impl/slots.py +80 -0
- omlish/dataclasses/impl/utils.py +167 -0
- omlish/defs.py +193 -0
- omlish/dispatch/__init__.py +3 -0
- omlish/dispatch/dispatch.py +137 -0
- omlish/dispatch/functions.py +52 -0
- omlish/dispatch/methods.py +162 -0
- omlish/docker.py +149 -0
- omlish/dynamic.py +220 -0
- omlish/graphs/__init__.py +0 -0
- omlish/graphs/dot/__init__.py +19 -0
- omlish/graphs/dot/items.py +162 -0
- omlish/graphs/dot/rendering.py +147 -0
- omlish/graphs/dot/utils.py +30 -0
- omlish/graphs/trees.py +249 -0
- omlish/http/__init__.py +0 -0
- omlish/http/consts.py +20 -0
- omlish/http/wsgi.py +34 -0
- omlish/inject/__init__.py +85 -0
- omlish/inject/binder.py +12 -0
- omlish/inject/bindings.py +49 -0
- omlish/inject/eagers.py +21 -0
- omlish/inject/elements.py +43 -0
- omlish/inject/exceptions.py +49 -0
- omlish/inject/impl/__init__.py +0 -0
- omlish/inject/impl/bindings.py +19 -0
- omlish/inject/impl/elements.py +154 -0
- omlish/inject/impl/injector.py +182 -0
- omlish/inject/impl/inspect.py +98 -0
- omlish/inject/impl/private.py +109 -0
- omlish/inject/impl/providers.py +132 -0
- omlish/inject/impl/scopes.py +198 -0
- omlish/inject/injector.py +40 -0
- omlish/inject/inspect.py +14 -0
- omlish/inject/keys.py +43 -0
- omlish/inject/managed.py +24 -0
- omlish/inject/overrides.py +18 -0
- omlish/inject/private.py +29 -0
- omlish/inject/providers.py +111 -0
- omlish/inject/proxy.py +48 -0
- omlish/inject/scopes.py +84 -0
- omlish/inject/types.py +21 -0
- omlish/iterators.py +184 -0
- omlish/json.py +194 -0
- omlish/lang/__init__.py +112 -0
- omlish/lang/cached.py +267 -0
- omlish/lang/classes/__init__.py +24 -0
- omlish/lang/classes/abstract.py +74 -0
- omlish/lang/classes/restrict.py +137 -0
- omlish/lang/classes/simple.py +120 -0
- omlish/lang/classes/test/__init__.py +0 -0
- omlish/lang/classes/test/test_abstract.py +89 -0
- omlish/lang/classes/test/test_restrict.py +71 -0
- omlish/lang/classes/test/test_simple.py +58 -0
- omlish/lang/classes/test/test_virtual.py +72 -0
- omlish/lang/classes/virtual.py +130 -0
- omlish/lang/clsdct.py +67 -0
- omlish/lang/cmp.py +63 -0
- omlish/lang/contextmanagers.py +249 -0
- omlish/lang/datetimes.py +67 -0
- omlish/lang/descriptors.py +52 -0
- omlish/lang/functions.py +126 -0
- omlish/lang/imports.py +153 -0
- omlish/lang/iterables.py +54 -0
- omlish/lang/maybes.py +136 -0
- omlish/lang/objects.py +103 -0
- omlish/lang/resolving.py +50 -0
- omlish/lang/strings.py +128 -0
- omlish/lang/typing.py +92 -0
- omlish/libc.py +532 -0
- omlish/logs/__init__.py +9 -0
- omlish/logs/_abc.py +247 -0
- omlish/logs/configs.py +62 -0
- omlish/logs/filters.py +9 -0
- omlish/logs/formatters.py +67 -0
- omlish/logs/utils.py +20 -0
- omlish/marshal/__init__.py +52 -0
- omlish/marshal/any.py +25 -0
- omlish/marshal/base.py +201 -0
- omlish/marshal/base64.py +25 -0
- omlish/marshal/dataclasses.py +115 -0
- omlish/marshal/datetimes.py +90 -0
- omlish/marshal/enums.py +43 -0
- omlish/marshal/exceptions.py +7 -0
- omlish/marshal/factories.py +129 -0
- omlish/marshal/global_.py +33 -0
- omlish/marshal/iterables.py +57 -0
- omlish/marshal/mappings.py +66 -0
- omlish/marshal/naming.py +17 -0
- omlish/marshal/objects.py +106 -0
- omlish/marshal/optionals.py +49 -0
- omlish/marshal/polymorphism.py +147 -0
- omlish/marshal/primitives.py +43 -0
- omlish/marshal/registries.py +57 -0
- omlish/marshal/standard.py +80 -0
- omlish/marshal/utils.py +23 -0
- omlish/marshal/uuids.py +29 -0
- omlish/marshal/values.py +30 -0
- omlish/math.py +184 -0
- omlish/os.py +32 -0
- omlish/reflect.py +359 -0
- omlish/replserver/__init__.py +5 -0
- omlish/replserver/__main__.py +4 -0
- omlish/replserver/console.py +247 -0
- omlish/replserver/server.py +146 -0
- omlish/runmodule.py +28 -0
- omlish/stats.py +342 -0
- omlish/term.py +222 -0
- omlish/testing/__init__.py +7 -0
- omlish/testing/pydevd.py +225 -0
- omlish/testing/pytest/__init__.py +8 -0
- omlish/testing/pytest/helpers.py +35 -0
- omlish/testing/pytest/inject/__init__.py +1 -0
- omlish/testing/pytest/inject/harness.py +159 -0
- omlish/testing/pytest/plugins/__init__.py +20 -0
- omlish/testing/pytest/plugins/_registry.py +6 -0
- omlish/testing/pytest/plugins/logging.py +13 -0
- omlish/testing/pytest/plugins/pycharm.py +54 -0
- omlish/testing/pytest/plugins/repeat.py +19 -0
- omlish/testing/pytest/plugins/skips.py +32 -0
- omlish/testing/pytest/plugins/spacing.py +19 -0
- omlish/testing/pytest/plugins/switches.py +70 -0
- omlish/testing/testing.py +102 -0
- omlish/text/__init__.py +0 -0
- omlish/text/delimit.py +171 -0
- omlish/text/indent.py +50 -0
- omlish/text/parts.py +265 -0
- omlish-0.0.0.dev1.dist-info/LICENSE +21 -0
- omlish-0.0.0.dev1.dist-info/METADATA +17 -0
- omlish-0.0.0.dev1.dist-info/RECORD +187 -0
- omlish-0.0.0.dev1.dist-info/WHEEL +5 -0
- omlish-0.0.0.dev1.dist-info/top_level.txt +1 -0
omlish/graphs/trees.py
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- @property dfs, bfs
|
|
4
|
+
"""
|
|
5
|
+
import functools
|
|
6
|
+
import typing as ta
|
|
7
|
+
import weakref
|
|
8
|
+
|
|
9
|
+
from .. import cached
|
|
10
|
+
from .. import check
|
|
11
|
+
from .. import collections as col
|
|
12
|
+
from .. import lang
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
T = ta.TypeVar('T')
|
|
16
|
+
NodeT = ta.TypeVar('NodeT')
|
|
17
|
+
NodeWalker = ta.Callable[[NodeT], ta.Iterable[NodeT]]
|
|
18
|
+
NodeGenerator = ta.Generator[NodeT, None, None]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class NodeException(ta.Generic[NodeT], Exception):
|
|
22
|
+
def __init__(self, node: NodeT, msg: str, *args, **kwargs) -> None:
|
|
23
|
+
super().__init__(msg, *args, **kwargs) # noqa
|
|
24
|
+
self._node = node
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def node(self) -> NodeT:
|
|
28
|
+
return self._node
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class DuplicateNodeException(NodeException[NodeT]):
|
|
32
|
+
def __init__(self, node: NodeT, *args, **kwargs) -> None:
|
|
33
|
+
super().__init__(node, f'Duplicate node: {node!r}', *args, **kwargs)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class UnknownNodeException(NodeException[NodeT]):
|
|
37
|
+
def __init__(self, node: NodeT, *args, **kwargs) -> None:
|
|
38
|
+
super().__init__(node, f'Unknown node: {node!r}', *args, **kwargs)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
root: NodeT,
|
|
46
|
+
walker: NodeWalker[NodeT],
|
|
47
|
+
*,
|
|
48
|
+
identity: bool = False,
|
|
49
|
+
) -> None:
|
|
50
|
+
super().__init__()
|
|
51
|
+
|
|
52
|
+
self._root = root
|
|
53
|
+
self._walker = walker
|
|
54
|
+
self._identity = identity
|
|
55
|
+
|
|
56
|
+
self._set_fac: ta.Callable[..., ta.MutableSet[NodeT]] = col.IdentitySet if identity else set
|
|
57
|
+
self._dict_fac: ta.Callable[..., ta.MutableMapping[NodeT, ta.Any]] = col.IdentityKeyDict if identity else dict
|
|
58
|
+
self._idx_seq_fac: ta.Callable[..., col.IndexedSeq[NodeT]] = functools.partial(col.IndexedSeq, identity=identity) # noqa
|
|
59
|
+
|
|
60
|
+
def walk(cur: NodeT, parent: ta.Optional[NodeT]) -> None:
|
|
61
|
+
check.not_none(cur)
|
|
62
|
+
if cur in node_set:
|
|
63
|
+
raise DuplicateNodeException(cur)
|
|
64
|
+
|
|
65
|
+
nodes.append(cur)
|
|
66
|
+
node_set.add(cur)
|
|
67
|
+
if parent is None:
|
|
68
|
+
check.state(cur is root)
|
|
69
|
+
elif parent not in node_set:
|
|
70
|
+
raise UnknownNodeException(parent)
|
|
71
|
+
|
|
72
|
+
parents_by_node[cur] = parent
|
|
73
|
+
|
|
74
|
+
children_by_node[cur] = children = list(walker(cur))
|
|
75
|
+
child_sets_by_node[cur] = self._set_fac(children)
|
|
76
|
+
for child in children:
|
|
77
|
+
walk(child, cur)
|
|
78
|
+
|
|
79
|
+
nodes: list[NodeT] = []
|
|
80
|
+
node_set: ta.MutableSet[NodeT] = self._set_fac() # type: ignore
|
|
81
|
+
children_by_node: ta.MutableMapping[ta.Optional[NodeT], ta.Sequence[NodeT]] = self._dict_fac() # type: ignore
|
|
82
|
+
child_sets_by_node: ta.MutableMapping[ta.Optional[NodeT], ta.AbstractSet[NodeT]] = self._dict_fac() # type: ignore # noqa
|
|
83
|
+
parents_by_node: ta.MutableMapping[NodeT, ta.Optional[NodeT]] = self._dict_fac() # type: ignore
|
|
84
|
+
|
|
85
|
+
children_by_node[None] = [root]
|
|
86
|
+
child_sets_by_node[None] = self._set_fac([root]) # type: ignore
|
|
87
|
+
|
|
88
|
+
walk(root, None)
|
|
89
|
+
|
|
90
|
+
self._nodes = self._idx_seq_fac(nodes) # type: ignore
|
|
91
|
+
self._node_set: ta.AbstractSet[NodeT] = node_set
|
|
92
|
+
self._children_by_node: ta.Mapping[ta.Optional[NodeT], col.IndexedSeq[NodeT]] = self._dict_fac( # type: ignore
|
|
93
|
+
[(n, self._idx_seq_fac(cs)) for n, cs in children_by_node.items()])
|
|
94
|
+
self._child_sets_by_node: ta.Mapping[ta.Optional[NodeT], ta.AbstractSet[NodeT]] = child_sets_by_node
|
|
95
|
+
self._parents_by_node: ta.Mapping[NodeT, ta.Optional[NodeT]] = parents_by_node
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def root(self) -> NodeT:
|
|
99
|
+
return self._root
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def nodes(self) -> col.IndexedSeq[NodeT]:
|
|
103
|
+
return self._nodes
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def walker(self) -> NodeWalker[NodeT]:
|
|
107
|
+
return self._walker
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def identity(self) -> bool:
|
|
111
|
+
return self._identity
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def node_set(self) -> ta.AbstractSet[NodeT]:
|
|
115
|
+
return self._node_set
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def children_by_node(self) -> ta.Mapping[ta.Optional[NodeT], col.IndexedSeq[NodeT]]:
|
|
119
|
+
return self._children_by_node
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def child_sets_by_node(self) -> ta.Mapping[ta.Optional[NodeT], ta.AbstractSet[NodeT]]:
|
|
123
|
+
return self._child_sets_by_node
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def parents_by_node(self) -> ta.Mapping[NodeT, ta.Optional[NodeT]]:
|
|
127
|
+
return self._parents_by_node
|
|
128
|
+
|
|
129
|
+
@classmethod
|
|
130
|
+
def from_parents(
|
|
131
|
+
cls,
|
|
132
|
+
src: ta.Union[
|
|
133
|
+
ta.Mapping[NodeT, ta.Optional[NodeT]],
|
|
134
|
+
ta.Iterable[tuple[NodeT, ta.Optional[NodeT]]],
|
|
135
|
+
],
|
|
136
|
+
*,
|
|
137
|
+
identity: bool = False,
|
|
138
|
+
**kwargs
|
|
139
|
+
) -> 'BasicTreeAnalysis[NodeT]':
|
|
140
|
+
pairs: ta.Sequence[tuple[NodeT, NodeT]]
|
|
141
|
+
if isinstance(src, ta.Mapping):
|
|
142
|
+
pairs = list(src.items()) # type: ignore
|
|
143
|
+
elif isinstance(src, ta.Iterable):
|
|
144
|
+
pairs = list(src) # type: ignore
|
|
145
|
+
else:
|
|
146
|
+
raise TypeError(src)
|
|
147
|
+
|
|
148
|
+
pairs = [(check.not_none(n), p) for n, p in pairs]
|
|
149
|
+
|
|
150
|
+
root = check.single([n for n, p in pairs if p is None]) # noqa
|
|
151
|
+
|
|
152
|
+
children_by_node: ta.MutableMapping[NodeT, ta.MutableSequence[NodeT]] = col.IdentityKeyDict() if identity else {} # noqa
|
|
153
|
+
for n, _ in pairs:
|
|
154
|
+
children_by_node[n] = []
|
|
155
|
+
for n, p in pairs:
|
|
156
|
+
if p is not None:
|
|
157
|
+
children_by_node[p].append(n)
|
|
158
|
+
|
|
159
|
+
return cls(
|
|
160
|
+
root,
|
|
161
|
+
children_by_node.__getitem__,
|
|
162
|
+
identity=identity,
|
|
163
|
+
**kwargs,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
@classmethod
|
|
167
|
+
def from_children(
|
|
168
|
+
cls,
|
|
169
|
+
src: ta.Union[
|
|
170
|
+
ta.Mapping[NodeT, ta.Iterable[NodeT]],
|
|
171
|
+
ta.Iterable[tuple[NodeT, ta.Iterable[NodeT]]],
|
|
172
|
+
],
|
|
173
|
+
*,
|
|
174
|
+
identity: bool = False,
|
|
175
|
+
**kwargs
|
|
176
|
+
) -> 'BasicTreeAnalysis[NodeT]':
|
|
177
|
+
pairs: ta.Sequence[tuple[NodeT, ta.Sequence[NodeT]]]
|
|
178
|
+
if isinstance(src, ta.Mapping):
|
|
179
|
+
pairs = list(src.items()) # type: ignore
|
|
180
|
+
elif isinstance(src, ta.Iterable):
|
|
181
|
+
pairs = list(src) # type: ignore
|
|
182
|
+
else:
|
|
183
|
+
raise TypeError(src)
|
|
184
|
+
|
|
185
|
+
pairs = [(check.not_none(n), [check.not_none(c) for c in cs]) for n, cs in pairs]
|
|
186
|
+
|
|
187
|
+
children_by_node: ta.MutableMapping[NodeT, ta.Sequence[NodeT]] = col.IdentityKeyDict() if identity else {}
|
|
188
|
+
parents_by_node: ta.MutableMapping[NodeT, NodeT] = col.IdentityKeyDict() if identity else {}
|
|
189
|
+
for n, cs in pairs:
|
|
190
|
+
check.not_in(n, children_by_node)
|
|
191
|
+
children_by_node[n] = cs
|
|
192
|
+
for c in cs:
|
|
193
|
+
check.not_in(c, parents_by_node)
|
|
194
|
+
parents_by_node[c] = n
|
|
195
|
+
|
|
196
|
+
e: ta.Any
|
|
197
|
+
d: ta.Any
|
|
198
|
+
if identity:
|
|
199
|
+
e, d = id, col.unique_dict((id(n), n) for n, _ in pairs)
|
|
200
|
+
else:
|
|
201
|
+
e, d = lang.identity, lang.identity
|
|
202
|
+
tsd = {e(n): {e(p)} for n, p in parents_by_node.items()}
|
|
203
|
+
ts = list(col.mut_toposort(tsd))
|
|
204
|
+
root = d(check.single(ts[0]))
|
|
205
|
+
|
|
206
|
+
return cls(
|
|
207
|
+
root,
|
|
208
|
+
children_by_node.__getitem__,
|
|
209
|
+
identity=identity,
|
|
210
|
+
**kwargs,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
@cached.property
|
|
214
|
+
def _node_sets_by_type(self) -> ta.MutableMapping[type, ta.AbstractSet[NodeT]]:
|
|
215
|
+
return weakref.WeakKeyDictionary()
|
|
216
|
+
|
|
217
|
+
def get_node_type_set(self, ty: type[T]) -> ta.AbstractSet[T]:
|
|
218
|
+
try:
|
|
219
|
+
return self._node_sets_by_type[ty] # type: ignore
|
|
220
|
+
except KeyError:
|
|
221
|
+
ret = self._node_sets_by_type[ty] = self._set_fac(n for n in self.nodes if isinstance(n, ty))
|
|
222
|
+
return ret # type: ignore
|
|
223
|
+
|
|
224
|
+
def iter_ancestors(self, node: NodeT) -> NodeGenerator[NodeT]:
|
|
225
|
+
cur: ta.Optional[NodeT] = node
|
|
226
|
+
while True:
|
|
227
|
+
cur = self.parents_by_node.get(cur) # type: ignore
|
|
228
|
+
if cur is None:
|
|
229
|
+
break
|
|
230
|
+
yield cur
|
|
231
|
+
|
|
232
|
+
def get_lineage(self, node: NodeT) -> col.IndexedSeq[NodeT]:
|
|
233
|
+
return self._idx_seq_fac(reversed([node, *self.iter_ancestors(node)]))
|
|
234
|
+
|
|
235
|
+
def get_first_parent_of_type(self, node: NodeT, ty: type[T]) -> ta.Optional[T]:
|
|
236
|
+
for cur in self.iter_ancestors(node):
|
|
237
|
+
if isinstance(cur, ty):
|
|
238
|
+
return cur
|
|
239
|
+
return None
|
|
240
|
+
|
|
241
|
+
@cached.property
|
|
242
|
+
def depths_by_node(self) -> ta.Mapping[NodeT, int]:
|
|
243
|
+
def rec(n, d):
|
|
244
|
+
dct[n] = d
|
|
245
|
+
for c in self._children_by_node[n]:
|
|
246
|
+
rec(c, d + 1)
|
|
247
|
+
dct: ta.MutableMapping[NodeT, int] = self._dict_fac()
|
|
248
|
+
rec(self._root, 0)
|
|
249
|
+
return dct
|
omlish/http/__init__.py
ADDED
|
File without changes
|
omlish/http/consts.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import http # noqa
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def format_status(status: http.HTTPStatus) -> str:
|
|
5
|
+
return '%d %s' % (int(status), status.phrase)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
STATUS_OK = format_status(http.HTTPStatus.OK)
|
|
9
|
+
STATUS_BAD_REQUEST = format_status(http.HTTPStatus.BAD_REQUEST)
|
|
10
|
+
STATUS_FORBIDDEN = format_status(http.HTTPStatus.FORBIDDEN)
|
|
11
|
+
STATUS_NOT_FOUND = format_status(http.HTTPStatus.NOT_FOUND)
|
|
12
|
+
STATUS_METHOD_NOT_ALLOWED = format_status(http.HTTPStatus.METHOD_NOT_ALLOWED)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
HEADER_CONTENT_TYPE = b'Content-Type'
|
|
16
|
+
CONTENT_TYPE_TEXT = b'text/plain'
|
|
17
|
+
CONTENT_TYPE_TEXT_UTF8 = CONTENT_TYPE_TEXT + b'; charset=utf-8'
|
|
18
|
+
CONTENT_TYPE_JSON = b'application/json'
|
|
19
|
+
CONTENT_TYPE_ICON = b'image/x-icon'
|
|
20
|
+
CONTENT_TYPE_BYTES = b'application/octet-stream'
|
omlish/http/wsgi.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from .. import lang
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Environ = ta.Mapping[str, ta.Any]
|
|
7
|
+
StartResponse = ta.Callable[[str, ta.Iterable[tuple[str | bytes, str | bytes]]], ta.Callable[[lang.BytesLike], None]]
|
|
8
|
+
App = ta.Callable[[Environ, StartResponse], ta.Iterable[lang.BytesLike]]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# class App(lang.Abstract):
|
|
12
|
+
#
|
|
13
|
+
# def __enter__(self: AppT) -> AppT:
|
|
14
|
+
# return self
|
|
15
|
+
#
|
|
16
|
+
# def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
17
|
+
# return None
|
|
18
|
+
#
|
|
19
|
+
# @abc.abstractmethod
|
|
20
|
+
# def __call__(self, environ: Environ, start_response: StartResponse) -> ta.Iterable[bytes]:
|
|
21
|
+
# raise NotImplementedError
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# class AsyncApp(lang.Abstract):
|
|
25
|
+
#
|
|
26
|
+
# async def __aenter__(self: AppT) -> AppT:
|
|
27
|
+
# return self
|
|
28
|
+
#
|
|
29
|
+
# async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
30
|
+
# return None
|
|
31
|
+
#
|
|
32
|
+
# @abc.abstractmethod
|
|
33
|
+
# async def __call__(self, scope, receive, send) -> ta.Iterable[bytes]:
|
|
34
|
+
# raise NotImplementedError
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
~> https://github.com/google/guice/commit/70248eafa90cd70a68b293763e53f6aec656e73c
|
|
3
|
+
"""
|
|
4
|
+
from .bindings import ( # noqa
|
|
5
|
+
Binding,
|
|
6
|
+
as_,
|
|
7
|
+
as_binding,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from .eagers import ( # noqa
|
|
11
|
+
eager,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from .elements import ( # noqa
|
|
15
|
+
as_elements,
|
|
16
|
+
Element,
|
|
17
|
+
Elements,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .exceptions import ( # noqa
|
|
21
|
+
CyclicDependencyException,
|
|
22
|
+
DuplicateKeyException,
|
|
23
|
+
KeyException,
|
|
24
|
+
ScopeAlreadyOpenException,
|
|
25
|
+
ScopeException,
|
|
26
|
+
ScopeNotOpenException,
|
|
27
|
+
UnboundKeyException,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
from .injector import ( # noqa
|
|
31
|
+
create_injector,
|
|
32
|
+
Injector,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
from .inspect import ( # noqa
|
|
36
|
+
Kwarg,
|
|
37
|
+
KwargsTarget,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
from .keys import ( # noqa
|
|
41
|
+
Key,
|
|
42
|
+
as_key,
|
|
43
|
+
multi,
|
|
44
|
+
tag,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
from .managed import ( # noqa
|
|
48
|
+
create_managed_injector,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
from .overrides import ( # noqa
|
|
52
|
+
override,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
from .private import ( # noqa
|
|
56
|
+
expose,
|
|
57
|
+
private,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
from .providers import ( # noqa
|
|
61
|
+
Provider,
|
|
62
|
+
as_provider,
|
|
63
|
+
const,
|
|
64
|
+
ctor,
|
|
65
|
+
fn,
|
|
66
|
+
link,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
from .scopes import ( # noqa
|
|
70
|
+
ScopeBinding,
|
|
71
|
+
SeededScope,
|
|
72
|
+
Singleton,
|
|
73
|
+
Thread,
|
|
74
|
+
bind_scope,
|
|
75
|
+
bind_scope_seed,
|
|
76
|
+
enter_seeded_scope,
|
|
77
|
+
in_,
|
|
78
|
+
singleton,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
from .types import ( # noqa
|
|
82
|
+
Cls,
|
|
83
|
+
Scope,
|
|
84
|
+
Unscoped,
|
|
85
|
+
)
|
omlish/inject/binder.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from .elements import Element
|
|
4
|
+
from .elements import Elements
|
|
5
|
+
from .elements import as_elements
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def bind(*args: ta.Any) -> Elements:
|
|
9
|
+
if all(isinstance(a, (Element, Elements)) for a in args):
|
|
10
|
+
return as_elements(*args)
|
|
11
|
+
|
|
12
|
+
raise TypeError(args)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from .. import check
|
|
4
|
+
from .. import dataclasses as dc
|
|
5
|
+
from .. import lang
|
|
6
|
+
from .elements import Element
|
|
7
|
+
from .elements import Elements
|
|
8
|
+
from .keys import Key
|
|
9
|
+
from .keys import as_key
|
|
10
|
+
from .providers import Provider
|
|
11
|
+
from .providers import as_provider
|
|
12
|
+
from .providers import const
|
|
13
|
+
from .providers import ctor
|
|
14
|
+
from .providers import fn
|
|
15
|
+
from .types import Scope
|
|
16
|
+
from .types import Unscoped
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dc.dataclass(frozen=True)
|
|
23
|
+
@dc.extra_params(cache_hash=True)
|
|
24
|
+
class Binding(Element, lang.Final):
|
|
25
|
+
key: Key
|
|
26
|
+
provider: Provider
|
|
27
|
+
scope: Scope = Unscoped()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def as_binding(o: ta.Any) -> Binding:
|
|
34
|
+
check.not_none(o)
|
|
35
|
+
if isinstance(o, Binding):
|
|
36
|
+
return o
|
|
37
|
+
check.not_isinstance(o, (Element, Elements))
|
|
38
|
+
if isinstance(o, Provider):
|
|
39
|
+
return Binding(Key(check.not_none(o.provided_cls())), o) # type: ignore # noqa
|
|
40
|
+
if isinstance(o, type):
|
|
41
|
+
return as_binding(ctor(o))
|
|
42
|
+
if callable(o):
|
|
43
|
+
return as_binding(fn(o))
|
|
44
|
+
cls = type(o)
|
|
45
|
+
return Binding(Key(cls), const(o, cls))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def as_(k: ta.Any, p: ta.Any) -> Binding:
|
|
49
|
+
return Binding(as_key(k), as_provider(p))
|
omlish/inject/eagers.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- SCOPED - eagers for EACH SCOPE
|
|
4
|
+
"""
|
|
5
|
+
import typing as ta
|
|
6
|
+
|
|
7
|
+
from .. import dataclasses as dc
|
|
8
|
+
from .. import lang
|
|
9
|
+
from .elements import Element
|
|
10
|
+
from .keys import Key
|
|
11
|
+
from .keys import as_key
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dc.dataclass(frozen=True)
|
|
15
|
+
@dc.extra_params(cache_hash=True)
|
|
16
|
+
class Eager(Element, lang.Final):
|
|
17
|
+
key: Key
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def eager(k: ta.Any) -> Element:
|
|
21
|
+
return Eager(as_key(k))
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- as_element[s] - universal
|
|
4
|
+
"""
|
|
5
|
+
import typing as ta
|
|
6
|
+
|
|
7
|
+
from .. import dataclasses as dc
|
|
8
|
+
from .. import lang
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Element(lang.Abstract):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dc.dataclass(frozen=True)
|
|
16
|
+
class Elements(lang.Final):
|
|
17
|
+
es: frozenset[Element] | None = None
|
|
18
|
+
cs: frozenset['Elements'] | None = None
|
|
19
|
+
|
|
20
|
+
def __iter__(self) -> ta.Generator[Element, None, None]:
|
|
21
|
+
if self.es:
|
|
22
|
+
yield from self.es
|
|
23
|
+
if self.cs:
|
|
24
|
+
for c in self.cs:
|
|
25
|
+
yield from c
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def as_elements(*args: ta.Union[Element, Elements]) -> Elements:
|
|
29
|
+
es: set[Element] = set()
|
|
30
|
+
cs: set['Elements'] = set()
|
|
31
|
+
for a in args:
|
|
32
|
+
if isinstance(a, Element):
|
|
33
|
+
es.add(a)
|
|
34
|
+
elif isinstance(a, Elements):
|
|
35
|
+
cs.add(a)
|
|
36
|
+
else:
|
|
37
|
+
raise TypeError(a)
|
|
38
|
+
if not es and len(cs) == 1:
|
|
39
|
+
return next(iter(cs))
|
|
40
|
+
return Elements(
|
|
41
|
+
frozenset(es) if es else None,
|
|
42
|
+
frozenset(cs) if cs else None,
|
|
43
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from .. import dataclasses as dc
|
|
4
|
+
from .keys import Key
|
|
5
|
+
from .types import Scope
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dc.dataclass()
|
|
12
|
+
class KeyException(Exception):
|
|
13
|
+
key: Key
|
|
14
|
+
|
|
15
|
+
source: ta.Any = None
|
|
16
|
+
name: ta.Optional[str] = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dc.dataclass()
|
|
20
|
+
class UnboundKeyException(KeyException):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dc.dataclass()
|
|
25
|
+
class DuplicateKeyException(KeyException):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dc.dataclass()
|
|
30
|
+
class CyclicDependencyException(KeyException):
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dc.dataclass()
|
|
38
|
+
class ScopeException(Exception):
|
|
39
|
+
scope: Scope
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dc.dataclass()
|
|
43
|
+
class ScopeAlreadyOpenException(ScopeException):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dc.dataclass()
|
|
48
|
+
class ScopeNotOpenException(ScopeException):
|
|
49
|
+
pass
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from ... import dataclasses as dc
|
|
2
|
+
from ... import lang
|
|
3
|
+
from ..bindings import Binding
|
|
4
|
+
from ..keys import Key
|
|
5
|
+
from ..types import Scope
|
|
6
|
+
from ..types import Unscoped
|
|
7
|
+
from .providers import ProviderImpl
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dc.dataclass(frozen=True, eq=False)
|
|
14
|
+
@dc.extra_params(cache_hash=True)
|
|
15
|
+
class BindingImpl(lang.Final):
|
|
16
|
+
key: Key
|
|
17
|
+
provider: ProviderImpl
|
|
18
|
+
scope: Scope = Unscoped()
|
|
19
|
+
binding: Binding | None = None
|