omlish 0.0.0.dev160__py3-none-any.whl → 0.0.0.dev162__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 +2 -2
- omlish/asyncs/bluelet/LICENSE +6 -0
- omlish/asyncs/bluelet/__init__.py +0 -0
- omlish/asyncs/bluelet/all.py +67 -0
- omlish/asyncs/bluelet/api.py +23 -0
- omlish/asyncs/bluelet/core.py +178 -0
- omlish/asyncs/bluelet/events.py +78 -0
- omlish/asyncs/bluelet/files.py +80 -0
- omlish/asyncs/bluelet/runner.py +416 -0
- omlish/asyncs/bluelet/sockets.py +214 -0
- omlish/lite/inject.py +16 -29
- omlish/os/atomics.py +205 -0
- {omlish-0.0.0.dev160.dist-info → omlish-0.0.0.dev162.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev160.dist-info → omlish-0.0.0.dev162.dist-info}/RECORD +18 -8
- {omlish-0.0.0.dev160.dist-info → omlish-0.0.0.dev162.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev160.dist-info → omlish-0.0.0.dev162.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev160.dist-info → omlish-0.0.0.dev162.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev160.dist-info → omlish-0.0.0.dev162.dist-info}/top_level.txt +0 -0
omlish/lite/inject.py
CHANGED
@@ -610,7 +610,7 @@ class InjectorBinder:
|
|
610
610
|
def __new__(cls, *args, **kwargs): # noqa
|
611
611
|
raise TypeError
|
612
612
|
|
613
|
-
_FN_TYPES: ta.Tuple[type, ...] = (
|
613
|
+
_FN_TYPES: ta.ClassVar[ta.Tuple[type, ...]] = (
|
614
614
|
types.FunctionType,
|
615
615
|
types.MethodType,
|
616
616
|
|
@@ -632,7 +632,7 @@ class InjectorBinder:
|
|
632
632
|
cls._FN_TYPES = (*cls._FN_TYPES, icls)
|
633
633
|
return icls
|
634
634
|
|
635
|
-
_BANNED_BIND_TYPES: ta.Tuple[type, ...] = (
|
635
|
+
_BANNED_BIND_TYPES: ta.ClassVar[ta.Tuple[type, ...]] = (
|
636
636
|
InjectorProvider,
|
637
637
|
)
|
638
638
|
|
@@ -811,45 +811,35 @@ def bind_injector_eager_key(key: ta.Any) -> InjectorBinding:
|
|
811
811
|
##
|
812
812
|
|
813
813
|
|
814
|
-
class
|
815
|
-
def __new__(cls, *args, **kwargs): # noqa
|
816
|
-
raise TypeError
|
817
|
-
|
814
|
+
class InjectionApi:
|
818
815
|
# keys
|
819
816
|
|
820
|
-
|
821
|
-
def as_key(cls, o: ta.Any) -> InjectorKey:
|
817
|
+
def as_key(self, o: ta.Any) -> InjectorKey:
|
822
818
|
return as_injector_key(o)
|
823
819
|
|
824
|
-
|
825
|
-
def array(cls, o: ta.Any) -> InjectorKey:
|
820
|
+
def array(self, o: ta.Any) -> InjectorKey:
|
826
821
|
return dc.replace(as_injector_key(o), array=True)
|
827
822
|
|
828
|
-
|
829
|
-
def tag(cls, o: ta.Any, t: ta.Any) -> InjectorKey:
|
823
|
+
def tag(self, o: ta.Any, t: ta.Any) -> InjectorKey:
|
830
824
|
return dc.replace(as_injector_key(o), tag=t)
|
831
825
|
|
832
826
|
# bindings
|
833
827
|
|
834
|
-
|
835
|
-
def as_bindings(cls, *args: InjectorBindingOrBindings) -> InjectorBindings:
|
828
|
+
def as_bindings(self, *args: InjectorBindingOrBindings) -> InjectorBindings:
|
836
829
|
return as_injector_bindings(*args)
|
837
830
|
|
838
|
-
|
839
|
-
def override(cls, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
|
831
|
+
def override(self, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
|
840
832
|
return injector_override(p, *args)
|
841
833
|
|
842
834
|
# injector
|
843
835
|
|
844
|
-
|
845
|
-
def create_injector(cls, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
|
836
|
+
def create_injector(self, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
|
846
837
|
return _Injector(as_injector_bindings(*args), parent)
|
847
838
|
|
848
839
|
# binder
|
849
840
|
|
850
|
-
@classmethod
|
851
841
|
def bind(
|
852
|
-
|
842
|
+
self,
|
853
843
|
obj: ta.Any,
|
854
844
|
*,
|
855
845
|
key: ta.Any = None,
|
@@ -884,32 +874,29 @@ class Injection:
|
|
884
874
|
|
885
875
|
# helpers
|
886
876
|
|
887
|
-
@classmethod
|
888
877
|
def bind_factory(
|
889
|
-
|
878
|
+
self,
|
890
879
|
fn: ta.Callable[..., T],
|
891
880
|
cls_: U,
|
892
881
|
ann: ta.Any = None,
|
893
882
|
) -> InjectorBindingOrBindings:
|
894
|
-
return
|
883
|
+
return self.bind(make_injector_factory(fn, cls_, ann))
|
895
884
|
|
896
|
-
@classmethod
|
897
885
|
def bind_array(
|
898
|
-
|
886
|
+
self,
|
899
887
|
obj: ta.Any = None,
|
900
888
|
*,
|
901
889
|
tag: ta.Any = None,
|
902
890
|
) -> InjectorBindingOrBindings:
|
903
891
|
return bind_injector_array(obj, tag=tag)
|
904
892
|
|
905
|
-
@classmethod
|
906
893
|
def bind_array_type(
|
907
|
-
|
894
|
+
self,
|
908
895
|
ele: ta.Union[InjectorKey, InjectorKeyCls],
|
909
896
|
cls_: U,
|
910
897
|
ann: ta.Any = None,
|
911
898
|
) -> InjectorBindingOrBindings:
|
912
|
-
return
|
899
|
+
return self.bind(make_injector_array_type(ele, cls_, ann))
|
913
900
|
|
914
901
|
|
915
|
-
inj =
|
902
|
+
inj = InjectionApi()
|
omlish/os/atomics.py
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
# @omlish-lite
|
3
|
+
import abc
|
4
|
+
import os
|
5
|
+
import shutil
|
6
|
+
import tempfile
|
7
|
+
import typing as ta
|
8
|
+
|
9
|
+
from omlish.lite.check import check
|
10
|
+
from omlish.lite.strings import attr_repr
|
11
|
+
|
12
|
+
|
13
|
+
AtomicPathSwapKind = ta.Literal['dir', 'file']
|
14
|
+
AtomicPathSwapState = ta.Literal['open', 'committed', 'aborted'] # ta.TypeAlias
|
15
|
+
|
16
|
+
|
17
|
+
##
|
18
|
+
|
19
|
+
|
20
|
+
class AtomicPathSwap(abc.ABC):
|
21
|
+
def __init__(
|
22
|
+
self,
|
23
|
+
kind: AtomicPathSwapKind,
|
24
|
+
dst_path: str,
|
25
|
+
*,
|
26
|
+
auto_commit: bool = False,
|
27
|
+
) -> None:
|
28
|
+
super().__init__()
|
29
|
+
|
30
|
+
self._kind = kind
|
31
|
+
self._dst_path = dst_path
|
32
|
+
self._auto_commit = auto_commit
|
33
|
+
|
34
|
+
self._state: AtomicPathSwapState = 'open'
|
35
|
+
|
36
|
+
def __repr__(self) -> str:
|
37
|
+
return attr_repr(self, 'kind', 'dst_path', 'tmp_path')
|
38
|
+
|
39
|
+
@property
|
40
|
+
def kind(self) -> AtomicPathSwapKind:
|
41
|
+
return self._kind
|
42
|
+
|
43
|
+
@property
|
44
|
+
def dst_path(self) -> str:
|
45
|
+
return self._dst_path
|
46
|
+
|
47
|
+
@property
|
48
|
+
@abc.abstractmethod
|
49
|
+
def tmp_path(self) -> str:
|
50
|
+
raise NotImplementedError
|
51
|
+
|
52
|
+
#
|
53
|
+
|
54
|
+
@property
|
55
|
+
def state(self) -> AtomicPathSwapState:
|
56
|
+
return self._state
|
57
|
+
|
58
|
+
def _check_state(self, *states: AtomicPathSwapState) -> None:
|
59
|
+
if self._state not in states:
|
60
|
+
raise RuntimeError(f'Atomic path swap not in correct state: {self._state}, {states}')
|
61
|
+
|
62
|
+
#
|
63
|
+
|
64
|
+
@abc.abstractmethod
|
65
|
+
def _commit(self) -> None:
|
66
|
+
raise NotImplementedError
|
67
|
+
|
68
|
+
def commit(self) -> None:
|
69
|
+
if self._state == 'committed':
|
70
|
+
return
|
71
|
+
self._check_state('open')
|
72
|
+
try:
|
73
|
+
self._commit()
|
74
|
+
except Exception: # noqa
|
75
|
+
self._abort()
|
76
|
+
raise
|
77
|
+
else:
|
78
|
+
self._state = 'committed'
|
79
|
+
|
80
|
+
#
|
81
|
+
|
82
|
+
@abc.abstractmethod
|
83
|
+
def _abort(self) -> None:
|
84
|
+
raise NotImplementedError
|
85
|
+
|
86
|
+
def abort(self) -> None:
|
87
|
+
if self._state == 'aborted':
|
88
|
+
return
|
89
|
+
self._abort()
|
90
|
+
self._state = 'aborted'
|
91
|
+
|
92
|
+
#
|
93
|
+
|
94
|
+
def __enter__(self) -> 'AtomicPathSwap':
|
95
|
+
return self
|
96
|
+
|
97
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
98
|
+
if (
|
99
|
+
exc_type is None and
|
100
|
+
self._auto_commit and
|
101
|
+
self._state == 'open'
|
102
|
+
):
|
103
|
+
self.commit()
|
104
|
+
else:
|
105
|
+
self.abort()
|
106
|
+
|
107
|
+
|
108
|
+
class AtomicPathSwapping(abc.ABC):
|
109
|
+
@abc.abstractmethod
|
110
|
+
def begin_atomic_path_swap(
|
111
|
+
self,
|
112
|
+
kind: AtomicPathSwapKind,
|
113
|
+
dst_path: str,
|
114
|
+
*,
|
115
|
+
name_hint: ta.Optional[str] = None,
|
116
|
+
make_dirs: bool = False,
|
117
|
+
**kwargs: ta.Any,
|
118
|
+
) -> AtomicPathSwap:
|
119
|
+
raise NotImplementedError
|
120
|
+
|
121
|
+
|
122
|
+
##
|
123
|
+
|
124
|
+
|
125
|
+
class OsRenameAtomicPathSwap(AtomicPathSwap):
|
126
|
+
def __init__(
|
127
|
+
self,
|
128
|
+
kind: AtomicPathSwapKind,
|
129
|
+
dst_path: str,
|
130
|
+
tmp_path: str,
|
131
|
+
**kwargs: ta.Any,
|
132
|
+
) -> None:
|
133
|
+
if kind == 'dir':
|
134
|
+
check.state(os.path.isdir(tmp_path))
|
135
|
+
elif kind == 'file':
|
136
|
+
check.state(os.path.isfile(tmp_path))
|
137
|
+
else:
|
138
|
+
raise TypeError(kind)
|
139
|
+
|
140
|
+
super().__init__(
|
141
|
+
kind,
|
142
|
+
dst_path,
|
143
|
+
**kwargs,
|
144
|
+
)
|
145
|
+
|
146
|
+
self._tmp_path = tmp_path
|
147
|
+
|
148
|
+
@property
|
149
|
+
def tmp_path(self) -> str:
|
150
|
+
return self._tmp_path
|
151
|
+
|
152
|
+
def _commit(self) -> None:
|
153
|
+
os.rename(self._tmp_path, self._dst_path)
|
154
|
+
|
155
|
+
def _abort(self) -> None:
|
156
|
+
shutil.rmtree(self._tmp_path, ignore_errors=True)
|
157
|
+
|
158
|
+
|
159
|
+
class TempDirAtomicPathSwapping(AtomicPathSwapping):
|
160
|
+
def __init__(
|
161
|
+
self,
|
162
|
+
*,
|
163
|
+
temp_dir: ta.Optional[str] = None,
|
164
|
+
root_dir: ta.Optional[str] = None,
|
165
|
+
) -> None:
|
166
|
+
super().__init__()
|
167
|
+
|
168
|
+
if root_dir is not None:
|
169
|
+
root_dir = os.path.abspath(root_dir)
|
170
|
+
self._root_dir = root_dir
|
171
|
+
self._temp_dir = temp_dir
|
172
|
+
|
173
|
+
def begin_atomic_path_swap(
|
174
|
+
self,
|
175
|
+
kind: AtomicPathSwapKind,
|
176
|
+
dst_path: str,
|
177
|
+
*,
|
178
|
+
name_hint: ta.Optional[str] = None,
|
179
|
+
make_dirs: bool = False,
|
180
|
+
**kwargs: ta.Any,
|
181
|
+
) -> AtomicPathSwap:
|
182
|
+
dst_path = os.path.abspath(dst_path)
|
183
|
+
if self._root_dir is not None and not dst_path.startswith(check.non_empty_str(self._root_dir)):
|
184
|
+
raise RuntimeError(f'Atomic path swap dst must be in root dir: {dst_path}, {self._root_dir}')
|
185
|
+
|
186
|
+
dst_dir = os.path.dirname(dst_path)
|
187
|
+
if make_dirs:
|
188
|
+
os.makedirs(dst_dir, exist_ok=True)
|
189
|
+
if not os.path.isdir(dst_dir):
|
190
|
+
raise RuntimeError(f'Atomic path swap dst dir does not exist: {dst_dir}')
|
191
|
+
|
192
|
+
if kind == 'dir':
|
193
|
+
tmp_path = tempfile.mkdtemp(prefix=name_hint, dir=self._temp_dir)
|
194
|
+
elif kind == 'file':
|
195
|
+
fd, tmp_path = tempfile.mkstemp(prefix=name_hint, dir=self._temp_dir)
|
196
|
+
os.close(fd)
|
197
|
+
else:
|
198
|
+
raise TypeError(kind)
|
199
|
+
|
200
|
+
return OsRenameAtomicPathSwap(
|
201
|
+
kind,
|
202
|
+
dst_path,
|
203
|
+
tmp_path,
|
204
|
+
**kwargs,
|
205
|
+
)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.manifests.json,sha256=RX24SRc6DCEg77PUVnaXOKCWa5TF_c9RQJdGIf7gl9c,1135
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=RGH11TXe-0tI-c-75Cmj5Em5DfZ8d1t-Xincc1SM3bE,3409
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
|
5
5
|
omlish/cached.py,sha256=UI-XTFBwA6YXWJJJeBn-WkwBkfzDjLBBaZf4nIJA9y0,510
|
@@ -92,6 +92,15 @@ omlish/asyncs/asyncio/channels.py,sha256=ZbmsEmdK1fV96liHdcVpRqA2dAMkXJt4Q3rFAg3
|
|
92
92
|
omlish/asyncs/asyncio/streams.py,sha256=Uc9PCWSfBqrK2kdVtfjjQU1eaYTWYmZm8QISDj2xiuw,1004
|
93
93
|
omlish/asyncs/asyncio/subprocesses.py,sha256=XlIWwSxpVB7sMVc75-f7dI6r08JkdipNFRWXUKS8zAw,6960
|
94
94
|
omlish/asyncs/asyncio/timeouts.py,sha256=Rj5OU9BIAPcVZZKp74z7SzUXF5xokh4dgsWkUqOy1aE,355
|
95
|
+
omlish/asyncs/bluelet/LICENSE,sha256=VHf3oPQihOHnWyIR8LcXX0dpONa1lgyJnjWC2qVuRR0,559
|
96
|
+
omlish/asyncs/bluelet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
97
|
+
omlish/asyncs/bluelet/all.py,sha256=aUV6PwnR8DqnEBS9wsZuPW_UtP6G9M8_KY-mmxZeVG0,1516
|
98
|
+
omlish/asyncs/bluelet/api.py,sha256=yeM5SauiIbvKj26mDdxn5mOj8s5fFIw2xBSe-P6HVC0,904
|
99
|
+
omlish/asyncs/bluelet/core.py,sha256=NpGQhb865aeXPKV_67l-6FiuQzdDJJ85zjfvCR5R8Pc,5430
|
100
|
+
omlish/asyncs/bluelet/events.py,sha256=iXpRWmy64YcshT_nuyiJ39jbketZdtj8LrdlX3JmpoY,2440
|
101
|
+
omlish/asyncs/bluelet/files.py,sha256=pgcLV_3oGbpqQmOrii8SeizyYLp8XKofQJhqM82RlKw,2389
|
102
|
+
omlish/asyncs/bluelet/runner.py,sha256=cwgVjwRRXzqfOqRD0rkPHjt_Udyt9ZKpVs36uAJ_Q7c,15473
|
103
|
+
omlish/asyncs/bluelet/sockets.py,sha256=RrC2vU52dOEBYKzvoh1qA39uUE8p3uCB_oxnhaP1AeA,6752
|
95
104
|
omlish/bootstrap/__init__.py,sha256=-Rtsg7uPQNhh1dIT9nqrz96XlqizwoLnWf-FwOEstJI,730
|
96
105
|
omlish/bootstrap/__main__.py,sha256=4jCwsaogp0FrJjJZ85hzF4-WqluPeheHbfeoKynKvNs,194
|
97
106
|
omlish/bootstrap/base.py,sha256=d8hqn4hp1XMMi5PgcJBQXPKmW47epu8CxBlqDZiRZb4,1073
|
@@ -339,7 +348,7 @@ omlish/lite/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
339
348
|
omlish/lite/cached.py,sha256=O7ozcoDNFm1Hg2wtpHEqYSp_i_nCLNOP6Ueq_Uk-7mU,1300
|
340
349
|
omlish/lite/check.py,sha256=KvcO86LqWlh2j4ORaZXRR4FM8fFb7kUkNqq3lTs0Ta0,12821
|
341
350
|
omlish/lite/contextmanagers.py,sha256=m9JO--p7L7mSl4cycXysH-1AO27weDKjP3DZG61cwwM,1683
|
342
|
-
omlish/lite/inject.py,sha256=
|
351
|
+
omlish/lite/inject.py,sha256=EEaioN9ESAveVCMe2s5osjwI97FPRUVoU8P95vGUiYo,23376
|
343
352
|
omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
|
344
353
|
omlish/lite/logs.py,sha256=CWFG0NKGhqNeEgryF5atN2gkPYbUdTINEw_s1phbINM,51
|
345
354
|
omlish/lite/marshal.py,sha256=ldoZs_yiQIUpOjBviV9f4mwm7hSZy0hRLXrvQA-6POU,14257
|
@@ -403,6 +412,7 @@ omlish/math/bits.py,sha256=yip1l8agOYzT7bFyMGc0RR3XlnGCfHMpjw_SECLLh1I,3477
|
|
403
412
|
omlish/math/floats.py,sha256=UimhOT7KRl8LXTzOI5cQWoX_9h6WNWe_3vcOuO7-h_8,327
|
404
413
|
omlish/math/stats.py,sha256=MegzKVsmv2kra4jDWLOUgV0X7Ee2Tbl5u6ql1v4-dEY,10053
|
405
414
|
omlish/os/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
415
|
+
omlish/os/atomics.py,sha256=gArGtyH5l3UjLKwKIqFJ5XkRnNouXntPEtkRbI0ch_0,5071
|
406
416
|
omlish/os/deathsig.py,sha256=hk9Yq2kyDdI-cI7OQH7mOfpRbOKzY_TfPKEqgrjVYbA,641
|
407
417
|
omlish/os/files.py,sha256=1tNy1z5I_CgYKA5c6lOfsXc-hknP4tQDbSShdz8HArw,1308
|
408
418
|
omlish/os/journald.py,sha256=2nI8Res1poXkbLc31--MPUlzYMESnCcPUkIxDOCjZW0,3903
|
@@ -525,9 +535,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329
|
|
525
535
|
omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
|
526
536
|
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
527
537
|
omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
|
528
|
-
omlish-0.0.0.
|
529
|
-
omlish-0.0.0.
|
530
|
-
omlish-0.0.0.
|
531
|
-
omlish-0.0.0.
|
532
|
-
omlish-0.0.0.
|
533
|
-
omlish-0.0.0.
|
538
|
+
omlish-0.0.0.dev162.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
539
|
+
omlish-0.0.0.dev162.dist-info/METADATA,sha256=thW6t3ofpA5bodN1Uc7hDhNjXOwZd68S1SqJZuv4hIw,4264
|
540
|
+
omlish-0.0.0.dev162.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
541
|
+
omlish-0.0.0.dev162.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
542
|
+
omlish-0.0.0.dev162.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
543
|
+
omlish-0.0.0.dev162.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|