omlish 0.0.0.dev245__py3-none-any.whl → 0.0.0.dev246__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.dev245'
2
- __revision__ = 'c3979ac75a1b25b3c679bc0310afb6364c124c4c'
1
+ __version__ = '0.0.0.dev246'
2
+ __revision__ = '796628c78050f0ca988bfa17c2f5a5cad5ee9056'
3
3
 
4
4
 
5
5
  #
@@ -63,7 +63,6 @@ from .mappings import ( # noqa
63
63
  DynamicTypeMap,
64
64
  guarded_map_update,
65
65
  multikey_dict,
66
- yield_dict_init,
67
66
  )
68
67
 
69
68
  from .ordered import ( # noqa
@@ -3,7 +3,7 @@ import collections.abc
3
3
  import itertools
4
4
  import typing as ta
5
5
 
6
- from .mappings import yield_dict_init
6
+ from .. import lang
7
7
 
8
8
 
9
9
  T = ta.TypeVar('T')
@@ -27,7 +27,7 @@ class FrozenDict(ta.Mapping[K, V], Frozen):
27
27
  if len(args) > 1:
28
28
  raise TypeError(args)
29
29
  self._dct: dict[K, V] = {}
30
- self._dct.update(yield_dict_init(*args, **kwargs))
30
+ self._dct.update(lang.yield_dict_init(*args, **kwargs))
31
31
 
32
32
  @property
33
33
  def debug(self) -> ta.Mapping[K, V]:
@@ -8,7 +8,6 @@ import dataclasses as dc
8
8
  import typing as ta
9
9
 
10
10
  from .. import lang
11
- from .mappings import yield_dict_init
12
11
 
13
12
 
14
13
  K = ta.TypeVar('K')
@@ -64,7 +63,7 @@ class HashEqMap(ta.MutableMapping[K, V]):
64
63
  self._dct: dict[int, list[HashEqMap._Node[K, V]]] = {}
65
64
  self._len = 0
66
65
 
67
- for k, v in yield_dict_init(*args, **kwargs):
66
+ for k, v in lang.yield_dict_init(*args, **kwargs):
68
67
  self[k] = v
69
68
 
70
69
  def __len__(self) -> int:
@@ -4,7 +4,6 @@ import typing as ta
4
4
  import weakref
5
5
 
6
6
  from .. import lang
7
- from .mappings import yield_dict_init
8
7
 
9
8
 
10
9
  T = ta.TypeVar('T')
@@ -38,7 +37,7 @@ class IdentityKeyDict(ta.MutableMapping[K, V]):
38
37
  def __init__(self, *args, **kwargs) -> None:
39
38
  super().__init__()
40
39
  self._dict: dict[int, tuple[K, V]] = {}
41
- for k, v in yield_dict_init(*args, **kwargs):
40
+ for k, v in lang.yield_dict_init(*args, **kwargs):
42
41
  self[k] = v
43
42
 
44
43
  @property
@@ -1,4 +1,3 @@
1
- import collections.abc
2
1
  import typing as ta
3
2
  import weakref
4
3
 
@@ -33,21 +32,6 @@ def guarded_map_update(
33
32
  return dst
34
33
 
35
34
 
36
- def yield_dict_init(*args, **kwargs) -> ta.Iterable[tuple[ta.Any, ta.Any]]:
37
- if len(args) > 1:
38
- raise TypeError
39
- if args:
40
- [src] = args
41
- if isinstance(src, collections.abc.Mapping):
42
- for k in src:
43
- yield (k, src[k])
44
- else:
45
- for k, v in src:
46
- yield (k, v)
47
- for k, v in kwargs.items():
48
- yield (k, v)
49
-
50
-
51
35
  class TypeMap(ta.Generic[T]):
52
36
  def __init__(self, items: ta.Iterable[T] = ()) -> None:
53
37
  super().__init__()
@@ -2,7 +2,6 @@ import abc
2
2
  import typing as ta
3
3
 
4
4
  from ... import lang
5
- from ..mappings import yield_dict_init
6
5
 
7
6
 
8
7
  T = ta.TypeVar('T')
@@ -83,7 +82,7 @@ class SortedListDict(SortedMutableMapping[K, V]):
83
82
  def __init__(self, impl: SortedCollection, *args, **kwargs) -> None:
84
83
  super().__init__()
85
84
  self._impl = impl
86
- for k, v in yield_dict_init(*args, **kwargs):
85
+ for k, v in lang.yield_dict_init(*args, **kwargs):
87
86
  self[k] = v
88
87
 
89
88
  @property
@@ -1,3 +1,10 @@
1
+ """
2
+ TODO:
3
+ - jsonl pidfile
4
+ - time started
5
+ - code version / revision
6
+ - venv?
7
+ """
1
8
  import abc
2
9
  import threading
3
10
  import typing as ta
@@ -108,6 +108,9 @@ from .utils import ( # noqa
108
108
  update_fields,
109
109
  update_fields_metadata,
110
110
 
111
+ shallow_astuple,
112
+ shallow_asdict,
113
+
111
114
  deep_replace,
112
115
 
113
116
  iter_items,
@@ -32,6 +32,9 @@ def fields_dict(cls_or_instance: ta.Any) -> dict[str, dc.Field]:
32
32
  return {f.name: f for f in dc.fields(cls_or_instance)}
33
33
 
34
34
 
35
+ ##
36
+
37
+
35
38
  class field_modifier: # noqa
36
39
  def __init__(self, fn: ta.Callable[[dc.Field], dc.Field]) -> None:
37
40
  super().__init__()
@@ -112,6 +115,17 @@ def update_fields_metadata(
112
115
  ##
113
116
 
114
117
 
118
+ def shallow_astuple(o: ta.Any) -> tuple[ta.Any, ...]:
119
+ return tuple(getattr(o, f.name) for f in dc.fields(o))
120
+
121
+
122
+ def shallow_asdict(o: ta.Any) -> dict[str, ta.Any]:
123
+ return {f.name: getattr(o, f.name) for f in dc.fields(o)}
124
+
125
+
126
+ ##
127
+
128
+
115
129
  def deep_replace(o: T, *args: str | ta.Callable[[ta.Any], ta.Mapping[str, ta.Any]]) -> T:
116
130
  if not args:
117
131
  return o
omlish/http/handlers.py CHANGED
@@ -79,6 +79,22 @@ class LoggingHttpHandler(HttpHandler_):
79
79
  return resp
80
80
 
81
81
 
82
+ @dc.dataclass(frozen=True)
83
+ class ExceptionLoggingHttpHandler(HttpHandler_):
84
+ handler: HttpHandler
85
+ log: logging.Logger
86
+ message: ta.Union[str, ta.Callable[[HttpHandlerRequest, BaseException], str]] = 'Error in http handler'
87
+
88
+ def __call__(self, req: HttpHandlerRequest) -> HttpHandlerResponse:
89
+ try:
90
+ return self.handler(req)
91
+ except Exception as e: # noqa
92
+ if callable(msg := self.message):
93
+ msg = msg(req, e)
94
+ self.log.exception(msg)
95
+ raise
96
+
97
+
82
98
  ##
83
99
 
84
100
 
omlish/lang/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from .attrs import ( # noqa
2
2
  AttrOps,
3
+ DictAttrOps,
3
4
  STD_ATTR_OPS,
4
5
  StdAttrOps,
5
6
  TRANSIENT_ATTR_OPS,
@@ -76,6 +77,11 @@ from .cmp import ( # noqa
76
77
  cmp,
77
78
  )
78
79
 
80
+ from .collections import ( # noqa
81
+ merge_dicts,
82
+ yield_dict_init,
83
+ )
84
+
79
85
  from .contextmanagers import ( # noqa
80
86
  AsyncContextManager,
81
87
  ContextManaged,
omlish/lang/attrs.py CHANGED
@@ -47,6 +47,35 @@ STD_ATTR_OPS = StdAttrOps()
47
47
  ##
48
48
 
49
49
 
50
+ class DictAttrOps(AttrOps):
51
+ def __init__(self, dct: ta.MutableMapping[str, ta.Any] | None = None) -> None:
52
+ super().__init__()
53
+
54
+ if dct is None:
55
+ dct = {}
56
+ self._dct = dct
57
+
58
+ def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
59
+ try:
60
+ return self._dct[name]
61
+ except KeyError:
62
+ if default is not AttrOps.NOT_SET:
63
+ return default
64
+ raise AttributeError(name) from None
65
+
66
+ def setattr(self, obj: ta.Any, name: str, value: ta.Any) -> None:
67
+ self._dct[name] = value
68
+
69
+ def delattr(self, obj: ta.Any, name: str) -> None:
70
+ try:
71
+ del self._dct[name]
72
+ except KeyError:
73
+ raise AttributeError(name) from None
74
+
75
+
76
+ ##
77
+
78
+
50
79
  class TransientDict(collections.abc.MutableMapping):
51
80
  def __init__(self) -> None:
52
81
  super().__init__()
@@ -6,6 +6,7 @@ TODO:
6
6
  - must support free functions (which have no instance nor owner)
7
7
  - 'staticmethod' or effective equiv - which must resolve to the shared instance
8
8
  - and must be transient?
9
+ - use __transient_dict__ to support common state nuking
9
10
  """
10
11
  import dataclasses as dc
11
12
  import functools
@@ -0,0 +1,50 @@
1
+ import collections.abc
2
+ import typing as ta
3
+
4
+
5
+ K = ta.TypeVar('K')
6
+ V = ta.TypeVar('V')
7
+
8
+
9
+ ##
10
+
11
+
12
+ def yield_dict_init(*args: ta.Any, **kwargs: ta.Any) -> ta.Iterable[tuple[ta.Any, ta.Any]]:
13
+ if len(args) > 1:
14
+ raise TypeError
15
+ if args:
16
+ [src] = args
17
+ if isinstance(src, collections.abc.Mapping):
18
+ for k in src:
19
+ yield (k, src[k])
20
+ else:
21
+ for k, v in src:
22
+ yield (k, v)
23
+ for k, v in kwargs.items():
24
+ yield (k, v)
25
+
26
+
27
+ def merge_dicts(
28
+ *dcts: ta.Mapping[K, V],
29
+ pair_fn: ta.Callable[[K, V], tuple[K, V] | None] | None = None,
30
+ conflict_fn: ta.Callable[[K, V, V], tuple[K, V] | None] | None = None,
31
+ ) -> dict[K, V]:
32
+ out: dict[K, V] = {}
33
+
34
+ for d in dcts:
35
+ for k_v in d.items():
36
+ if pair_fn is not None and (k_v := pair_fn(*k_v)) is None: # type: ignore[assignment]
37
+ continue
38
+
39
+ k, v = k_v
40
+ if k in out:
41
+ if conflict_fn is None:
42
+ raise KeyError(k)
43
+
44
+ if (k_v := conflict_fn(k, out[k], v)) is None: # type: ignore[assignment]
45
+ continue
46
+ k, v = k_v
47
+
48
+ out[k] = v
49
+
50
+ return out
@@ -28,6 +28,16 @@ from .base import ( # noqa
28
28
  ReflectOverride,
29
29
  )
30
30
 
31
+ from .composite.iterables import ( # noqa
32
+ IterableMarshaler,
33
+ IterableUnmarshaler,
34
+ )
35
+
36
+ from .composite.wrapped import ( # noqa
37
+ WrappedMarshaler,
38
+ WrappedUnmarshaler,
39
+ )
40
+
31
41
  from .exceptions import ( # noqa
32
42
  ForbiddenTypeError,
33
43
  MarshalError,
@@ -49,6 +59,14 @@ from .naming import ( # noqa
49
59
  translate_name,
50
60
  )
51
61
 
62
+ from .objects.dataclasses import ( # noqa
63
+ AbstractDataclassFactory,
64
+ DataclassMarshalerFactory,
65
+ DataclassUnmarshalerFactory,
66
+ get_dataclass_field_infos,
67
+ get_dataclass_metadata,
68
+ )
69
+
52
70
  from .objects.helpers import ( # noqa
53
71
  update_field_metadata,
54
72
  update_fields_metadata,
@@ -75,14 +93,18 @@ from .objects.unmarshal import ( # noqa
75
93
  )
76
94
 
77
95
  from .polymorphism.marshal import ( # noqa
96
+ PolymorphismMarshaler,
78
97
  PolymorphismMarshalerFactory,
79
98
  make_polymorphism_marshaler,
80
99
  )
81
100
 
82
101
  from .polymorphism.metadata import ( # noqa
102
+ FieldTypeTagging,
83
103
  Impl,
84
104
  Impls,
85
105
  Polymorphism,
106
+ TypeTagging,
107
+ WrapperTypeTagging,
86
108
  polymorphism_from_subclasses,
87
109
  )
88
110
 
@@ -97,6 +119,7 @@ from .polymorphism.unions import ( # noqa
97
119
  )
98
120
 
99
121
  from .polymorphism.unmarshal import ( # noqa
122
+ PolymorphismUnmarshaler,
100
123
  PolymorphismUnmarshalerFactory,
101
124
  make_polymorphism_unmarshaler,
102
125
  )
@@ -0,0 +1,26 @@
1
+ import dataclasses as dc
2
+ import typing as ta
3
+
4
+ from ..base import MarshalContext
5
+ from ..base import Marshaler
6
+ from ..base import UnmarshalContext
7
+ from ..base import Unmarshaler
8
+ from ..values import Value
9
+
10
+
11
+ @dc.dataclass(frozen=True)
12
+ class WrappedMarshaler(Marshaler):
13
+ wrapper: ta.Callable[[MarshalContext, ta.Any], ta.Any]
14
+ m: Marshaler
15
+
16
+ def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
17
+ return self.m.marshal(ctx, self.wrapper(ctx, o))
18
+
19
+
20
+ @dc.dataclass(frozen=True)
21
+ class WrappedUnmarshaler(Unmarshaler):
22
+ unwrapper: ta.Callable[[UnmarshalContext, ta.Any], ta.Any]
23
+ u: Unmarshaler
24
+
25
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
26
+ return self.unwrapper(ctx, self.u.unmarshal(ctx, v))
@@ -41,12 +41,16 @@ def get_dataclass_metadata(ty: type) -> ObjectMetadata:
41
41
  ) or ObjectMetadata()
42
42
 
43
43
 
44
- def get_field_infos(
44
+ def get_dataclass_field_infos(
45
45
  ty: type,
46
- opts: col.TypeMap[Option] = col.TypeMap(),
46
+ opts: col.TypeMap[Option] | None = None,
47
47
  ) -> FieldInfos:
48
+ if opts is None:
49
+ opts = col.TypeMap()
50
+
48
51
  dc_md = get_dataclass_metadata(ty)
49
52
  dc_naming = dc_md.field_naming or opts.get(Naming)
53
+ dc_rf = dc.reflect(ty)
50
54
 
51
55
  fi_defaults = {
52
56
  k: v
@@ -62,18 +66,24 @@ def get_field_infos(
62
66
  type_hints = ta.get_type_hints(ty)
63
67
 
64
68
  ret: list[FieldInfo] = []
65
- for field in dc.fields(ty):
69
+ for field in dc_rf.fields.values():
66
70
  if (f_naming := field.metadata.get(Naming, dc_naming)) is not None:
67
71
  um_name = translate_name(field.name, f_naming)
68
72
  else:
69
73
  um_name = field.name
70
74
 
75
+ f_ty: ta.Any
76
+ if (cpx := dc_rf.cls_params_extras) is not None and cpx.generic_init:
77
+ f_ty = dc_rf.generic_replaced_field_annotations[field.name]
78
+ else:
79
+ f_ty = type_hints[field.name]
80
+
71
81
  fi_kw = dict(fi_defaults)
72
82
  fo_kw = dict(fo_defaults)
73
83
 
74
84
  fi_kw.update(
75
85
  name=field.name,
76
- type=type_hints[field.name],
86
+ type=f_ty,
77
87
  metadata=FieldMetadata(),
78
88
 
79
89
  marshal_name=um_name,
@@ -158,7 +168,22 @@ def _make_field_obj(ctx, ty, obj, fac):
158
168
  ##
159
169
 
160
170
 
161
- class DataclassMarshalerFactory(MarshalerFactory):
171
+ class AbstractDataclassFactory(lang.Abstract):
172
+ def _get_metadata(self, ty: type) -> ObjectMetadata:
173
+ return get_dataclass_metadata(ty)
174
+
175
+ def _get_field_infos(
176
+ self,
177
+ ty: type,
178
+ opts: col.TypeMap[Option] | None = None,
179
+ ) -> FieldInfos:
180
+ return get_dataclass_field_infos(ty, opts)
181
+
182
+
183
+ ##
184
+
185
+
186
+ class DataclassMarshalerFactory(AbstractDataclassFactory, MarshalerFactory):
162
187
  def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
163
188
  return isinstance(rty, type) and dc.is_dataclass(rty) and not lang.is_abstract_class(rty)
164
189
 
@@ -167,8 +192,8 @@ class DataclassMarshalerFactory(MarshalerFactory):
167
192
  check.state(dc.is_dataclass(ty))
168
193
  check.state(not lang.is_abstract_class(ty))
169
194
 
170
- dc_md = get_dataclass_metadata(ty)
171
- fis = get_field_infos(ty, ctx.options)
195
+ dc_md = self._get_metadata(ty)
196
+ fis = self._get_field_infos(ty, ctx.options)
172
197
 
173
198
  fields = [
174
199
  (fi, _make_field_obj(ctx, fi.type, fi.metadata.marshaler, fi.metadata.marshaler_factory))
@@ -185,7 +210,7 @@ class DataclassMarshalerFactory(MarshalerFactory):
185
210
  ##
186
211
 
187
212
 
188
- class DataclassUnmarshalerFactory(UnmarshalerFactory):
213
+ class DataclassUnmarshalerFactory(AbstractDataclassFactory, UnmarshalerFactory):
189
214
  def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
190
215
  return isinstance(rty, type) and dc.is_dataclass(rty) and not lang.is_abstract_class(rty)
191
216
 
@@ -194,8 +219,8 @@ class DataclassUnmarshalerFactory(UnmarshalerFactory):
194
219
  check.state(dc.is_dataclass(ty))
195
220
  check.state(not lang.is_abstract_class(ty))
196
221
 
197
- dc_md = get_dataclass_metadata(ty)
198
- fis = get_field_infos(ty, ctx.options)
222
+ dc_md = self._get_metadata(ty)
223
+ fis = self._get_field_infos(ty, ctx.options)
199
224
 
200
225
  d: dict[str, tuple[FieldInfo, Unmarshaler]] = {}
201
226
  defaults: dict[str, ta.Any] = {}
@@ -213,7 +238,7 @@ class DataclassUnmarshalerFactory(UnmarshalerFactory):
213
238
  raise Exception(f'Embedded fields cannot have specials: {e_ty}')
214
239
 
215
240
  embeds[fi.name] = e_ty
216
- for e_fi in get_field_infos(e_ty, ctx.options):
241
+ for e_fi in self._get_field_infos(e_ty, ctx.options):
217
242
  e_ns = add_field(e_fi, prefixes=[p + ep for p in prefixes for ep in fi.unmarshal_names])
218
243
  embeds_by_unmarshal_name.update({e_f: (fi.name, e_fi.name) for e_f in e_ns})
219
244
  ret.extend(e_ns)
@@ -22,7 +22,7 @@ from .unmarshal import ObjectUnmarshaler
22
22
  ##
23
23
 
24
24
 
25
- def _is_named_tuple(rty: rfl.Type) -> bool:
25
+ def _is_namedtuple(rty: rfl.Type) -> bool:
26
26
  return (
27
27
  isinstance(rty, type) and
28
28
  issubclass(rty, tuple) and
@@ -30,11 +30,11 @@ def _is_named_tuple(rty: rfl.Type) -> bool:
30
30
  )
31
31
 
32
32
 
33
- def get_field_infos(
33
+ def get_namedtuple_field_infos(
34
34
  ty: type,
35
35
  opts: col.TypeMap[Option] = col.TypeMap(),
36
36
  ) -> FieldInfos:
37
- check.arg(_is_named_tuple(ty), ty)
37
+ check.arg(_is_namedtuple(ty), ty)
38
38
 
39
39
  sig = inspect.signature(ty)
40
40
 
@@ -57,14 +57,14 @@ def get_field_infos(
57
57
 
58
58
  class NamedtupleMarshalerFactory(MarshalerFactory):
59
59
  def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
60
- return _is_named_tuple(rty)
60
+ return _is_namedtuple(rty)
61
61
 
62
62
  def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
63
- check.state(_is_named_tuple(rty))
63
+ check.state(_is_namedtuple(rty))
64
64
  ty = check.isinstance(rty, type)
65
65
  check.state(not lang.is_abstract_class(ty))
66
66
 
67
- fis = get_field_infos(ty, ctx.options)
67
+ fis = get_namedtuple_field_infos(ty, ctx.options)
68
68
 
69
69
  fields = [
70
70
  (fi, ctx.make(fi.type))
@@ -81,14 +81,14 @@ class NamedtupleMarshalerFactory(MarshalerFactory):
81
81
 
82
82
  class NamedtupleUnmarshalerFactory(UnmarshalerFactory):
83
83
  def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
84
- return _is_named_tuple(rty)
84
+ return _is_namedtuple(rty)
85
85
 
86
86
  def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
87
- check.state(_is_named_tuple(rty))
87
+ check.state(_is_namedtuple(rty))
88
88
  ty = check.isinstance(rty, type)
89
89
  check.state(not lang.is_abstract_class(ty))
90
90
 
91
- fis = get_field_infos(ty, ctx.options)
91
+ fis = get_namedtuple_field_infos(ty, ctx.options)
92
92
 
93
93
  d: dict[str, tuple[FieldInfo, Unmarshaler]] = {}
94
94
  defaults: dict[str, ta.Any] = {}
@@ -1,7 +1,9 @@
1
+ import abc
1
2
  import dataclasses as dc
2
3
  import typing as ta
3
4
 
4
5
  from ... import check
6
+ from ... import lang
5
7
  from ... import reflect as rfl
6
8
  from ..base import MarshalContext
7
9
  from ..base import Marshaler
@@ -17,20 +19,32 @@ from .metadata import WrapperTypeTagging
17
19
  ##
18
20
 
19
21
 
22
+ class PolymorphismMarshaler(Marshaler, lang.Abstract):
23
+ @abc.abstractmethod
24
+ def get_impls(self) -> ta.Mapping[type, tuple[str, Marshaler]]:
25
+ raise NotImplementedError
26
+
27
+
20
28
  @dc.dataclass(frozen=True)
21
- class WrapperPolymorphismMarshaler(Marshaler):
29
+ class WrapperPolymorphismMarshaler(PolymorphismMarshaler):
22
30
  m: ta.Mapping[type, tuple[str, Marshaler]]
23
31
 
32
+ def get_impls(self) -> ta.Mapping[type, tuple[str, Marshaler]]:
33
+ return self.m
34
+
24
35
  def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
25
36
  tag, m = self.m[type(o)]
26
37
  return {tag: m.marshal(ctx, o)}
27
38
 
28
39
 
29
40
  @dc.dataclass(frozen=True)
30
- class FieldPolymorphismMarshaler(Marshaler):
41
+ class FieldPolymorphismMarshaler(PolymorphismMarshaler):
31
42
  m: ta.Mapping[type, tuple[str, Marshaler]]
32
43
  tf: str
33
44
 
45
+ def get_impls(self) -> ta.Mapping[type, tuple[str, Marshaler]]:
46
+ return self.m
47
+
34
48
  def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
35
49
  tag, m = self.m[type(o)]
36
50
  return {self.tf: tag, **m.marshal(ctx, o)} # type: ignore
@@ -1,8 +1,10 @@
1
+ import abc
1
2
  import collections.abc
2
3
  import dataclasses as dc
3
4
  import typing as ta
4
5
 
5
6
  from ... import check
7
+ from ... import lang
6
8
  from ... import reflect as rfl
7
9
  from ..base import UnmarshalContext
8
10
  from ..base import Unmarshaler
@@ -18,10 +20,19 @@ from .metadata import WrapperTypeTagging
18
20
  ##
19
21
 
20
22
 
23
+ class PolymorphismUnmarshaler(Unmarshaler, lang.Abstract):
24
+ @abc.abstractmethod
25
+ def get_impls(self) -> ta.Mapping[str, Unmarshaler]:
26
+ raise NotImplementedError
27
+
28
+
21
29
  @dc.dataclass(frozen=True)
22
- class WrapperPolymorphismUnmarshaler(Unmarshaler):
30
+ class WrapperPolymorphismUnmarshaler(PolymorphismUnmarshaler):
23
31
  m: ta.Mapping[str, Unmarshaler]
24
32
 
33
+ def get_impls(self) -> ta.Mapping[str, Unmarshaler]:
34
+ return self.m
35
+
25
36
  def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
26
37
  ma = check.isinstance(v, collections.abc.Mapping)
27
38
  [(tag, iv)] = ma.items()
@@ -30,10 +41,13 @@ class WrapperPolymorphismUnmarshaler(Unmarshaler):
30
41
 
31
42
 
32
43
  @dc.dataclass(frozen=True)
33
- class FieldPolymorphismUnmarshaler(Unmarshaler):
44
+ class FieldPolymorphismUnmarshaler(PolymorphismUnmarshaler):
34
45
  m: ta.Mapping[str, Unmarshaler]
35
46
  tf: str
36
47
 
48
+ def get_impls(self) -> ta.Mapping[str, Unmarshaler]:
49
+ return self.m
50
+
37
51
  def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
38
52
  ma = dict(check.isinstance(v, collections.abc.Mapping))
39
53
  tag = ma.pop(self.tf)
@@ -3,6 +3,7 @@
3
3
  """
4
4
  TODO:
5
5
  - 'json pids', with code version? '.json.pid'? '.jpid'?
6
+ - json*L* pidfiles - first line is bare int, following may be json - now `head -n1 foo.pid` not cat
6
7
  """
7
8
  import fcntl
8
9
  import os
@@ -152,7 +153,12 @@ class Pidfile:
152
153
 
153
154
  #
154
155
 
155
- def write(self, pid: ta.Optional[int] = None) -> None:
156
+ def write(
157
+ self,
158
+ pid: ta.Optional[int] = None,
159
+ *,
160
+ suffix: ta.Optional[str] = None,
161
+ ) -> None:
156
162
  self.acquire_lock()
157
163
 
158
164
  if pid is None:
@@ -160,7 +166,11 @@ class Pidfile:
160
166
 
161
167
  self._f.seek(0)
162
168
  self._f.truncate()
163
- self._f.write(f'{pid}\n')
169
+ self._f.write('\n'.join([
170
+ str(pid),
171
+ *([suffix] if suffix is not None else []),
172
+ '',
173
+ ]))
164
174
  self._f.flush()
165
175
 
166
176
  def clear(self) -> None:
@@ -171,14 +181,20 @@ class Pidfile:
171
181
 
172
182
  #
173
183
 
174
- def read(self) -> ta.Optional[int]:
184
+ def read_raw(self) -> ta.Optional[str]:
175
185
  self.ensure_cannot_lock()
176
186
 
177
187
  self._f.seek(0)
178
188
  buf = self._f.read()
179
189
  if not buf:
180
190
  return None
181
- return int(buf)
191
+ return buf
192
+
193
+ def read(self) -> ta.Optional[int]:
194
+ buf = self.read_raw()
195
+ if not buf:
196
+ return None
197
+ return int(buf.splitlines()[0].strip())
182
198
 
183
199
  def kill(self, sig: int = signal.SIGTERM) -> None:
184
200
  if (pid := self.read()) is None:
omlish/os/signals.py CHANGED
@@ -1,9 +1,13 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  # @omlish-lite
3
3
  import signal
4
+ import typing as ta
4
5
 
5
6
 
6
- def parse_signal(s: str) -> int:
7
+ def parse_signal(s: ta.Union[int, str]) -> int:
8
+ if isinstance(s, int):
9
+ return s
10
+
7
11
  try:
8
12
  return int(s)
9
13
  except ValueError:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: omlish
3
- Version: 0.0.0.dev245
3
+ Version: 0.0.0.dev246
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=vQTAIvR8OblSq-uP2GUfnbei0RnmAnM5j0T1-OToh9E,8253
2
- omlish/__about__.py,sha256=igneh_Z18EcRdtPlDRmK5tHmRK3NpxQPFoUopKrrNtw,3380
2
+ omlish/__about__.py,sha256=FBmEuLfID7wGs4KGaP2kpxM0kLF3oWiG6kw4s45Nwk8,3380
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
5
5
  omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
@@ -136,14 +136,14 @@ omlish/codecs/funcs.py,sha256=p4imNt7TobyZVXWC-WhntHVu9KfJrO4QwdtPRh-cVOk,850
136
136
  omlish/codecs/registry.py,sha256=2FnO5YP7ui1LzkguwESY0MP3WIdwgPTIJTM_4RyTOEg,3896
137
137
  omlish/codecs/standard.py,sha256=eiZ4u9ep0XrA4Z_D1zJI0vmWyuN8HLrX4Se_r_Cq_ZM,60
138
138
  omlish/codecs/text.py,sha256=JzrdwMpQPo2NBBg3K1EZszzQy5vEWmd82SIerJd4yeQ,5723
139
- omlish/collections/__init__.py,sha256=umpclbTE3wsSflMrKmYEiGmWFhiukfJxvBWgtYMZ8mk,2161
139
+ omlish/collections/__init__.py,sha256=fAGCii4OttPRee9q4AD-IfQpdsmoCdgPwYUMPgnJwCs,2140
140
140
  omlish/collections/abc.py,sha256=sP7BpTVhx6s6C59mTFeosBi4rHOWC6tbFBYbxdZmvh0,2365
141
141
  omlish/collections/coerce.py,sha256=g68ROb_-5HgH-vI8612mU2S0FZ8-wp2ZHK5_Zy_kVC0,7037
142
142
  omlish/collections/exceptions.py,sha256=shcS-NCnEUudF8qC_SmO2TQyjivKlS4TDjaz_faqQ0c,44
143
- omlish/collections/frozen.py,sha256=mxhd8pw5zIXUiRHiBVZWYCYT7wYDVG3tAY5PNU-WH-I,4150
144
- omlish/collections/hasheq.py,sha256=XcOCE6f2lXizDCOXxSX6vJv-rLcpDo2OWCYIKGSWuic,3697
145
- omlish/collections/identity.py,sha256=SwnUE5D3v9RBjATDE1LUr_vO3Rb2NHcmTK64GZIcsO8,2720
146
- omlish/collections/mappings.py,sha256=YunNPyADrpitZGTJcXV0k4bmJddj1avDvEavz0coJWU,3203
143
+ omlish/collections/frozen.py,sha256=jQppK1pyQ3e_aAvw8OEKfnr7b0OB4RI5Qr1g9xXTZaQ,4137
144
+ omlish/collections/hasheq.py,sha256=SQdVICLZWKkYu4vUXrfmWBXO3i-jx01iM9IInDWkKfU,3664
145
+ omlish/collections/identity.py,sha256=BTXn3r3ZprHluIl1DIXC9BYCmjak0BWhN7L6SxXo9ws,2687
146
+ omlish/collections/mappings.py,sha256=fCHQatlAstiZkWZiyIlOw637Yep7ce79EPPbJcWHHUA,2784
147
147
  omlish/collections/ordered.py,sha256=tUAl99XHbSbzn7Hdh99jUBl27NcC2J7ZTI67slTMe5M,2333
148
148
  omlish/collections/ranked.py,sha256=rg6DL36oOUiG5JQEAkGnT8b6f9mSndQlIovtt8GQj_w,2229
149
149
  omlish/collections/unmodifiable.py,sha256=-zys__n6L7liWzhmHAIvfxprq7cUE5HoR3foGvXc_7I,4748
@@ -158,7 +158,7 @@ omlish/collections/persistent/treap.py,sha256=A09ZPacGyJlyRB-Wi4TNj3tE0w-RpFNliP
158
158
  omlish/collections/persistent/treapmap.py,sha256=TxOM-ZRF5PK2xe5wRIhESNt7DGh9b_MeZfE7HLkCOs4,5804
159
159
  omlish/collections/sorted/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
160
  omlish/collections/sorted/skiplist.py,sha256=eU_cYQVnT-EZxv_dN9PYQZdOP0km5usEcOQRiJKL7Rw,5986
161
- omlish/collections/sorted/sorted.py,sha256=3dl3MD3soVP9j2m4lnDZFYA9fho6Ic1MpMpYePZTW-0,3353
161
+ omlish/collections/sorted/sorted.py,sha256=euHJan3FqTYSCJGsVcYYRV-yhAAQ5_htnjymnNoVHRE,3319
162
162
  omlish/concurrent/__init__.py,sha256=9p-s8MvBEYDqHIoYU3OYoe-Nni22QdkW7nhZGEukJTM,197
163
163
  omlish/concurrent/executors.py,sha256=FYKCDYYuj-OgMa8quLsA47SfFNX3KDJvRENVk8NDsrA,1292
164
164
  omlish/concurrent/futures.py,sha256=J2s9wYURUskqRJiBbAR0PNEAp1pXbIMYldOVBTQduQY,4239
@@ -183,13 +183,13 @@ omlish/daemons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
183
  omlish/daemons/daemon.py,sha256=3Wkvu8M_EaCKSpKI5UN5OayRXV0oVdF62tBss9_hlr0,3479
184
184
  omlish/daemons/launching.py,sha256=sNOYW939IGI4ZlLQ0bKxzXj6EyeOiwV7Upqhd5XfoHc,3747
185
185
  omlish/daemons/reparent.py,sha256=7uJ9oPGt9Ud7uA8bDl_SHcuqjcsmXa3kkjp9jf29wOw,585
186
- omlish/daemons/services.py,sha256=jIlGWhiWoqQlm_OFeffkSs9jjr-icDF1-I-SNMEgg9Y,3406
186
+ omlish/daemons/services.py,sha256=YYp2SMkJ71WgzOcYSXjWHeAyKKxu3j1dfuJvWkl0Dgw,3492
187
187
  omlish/daemons/spawning.py,sha256=psR73zOYjMKTqNpx1bMib8uU9wAZz62tw5TaWHrTdyY,5337
188
188
  omlish/daemons/targets.py,sha256=00KmtlknMhQ5PyyVAhWl3rpeTMPym0GxvHHq6mYPZ7c,3051
189
189
  omlish/daemons/waiting.py,sha256=RfgD1L33QQVbD2431dkKZGE4w6DUcGvYeRXXi8puAP4,1676
190
- omlish/dataclasses/__init__.py,sha256=b7EZCIfHnEHCHWwgD3YXxkdsU-uYd9iD4hM36RgpI1g,1598
190
+ omlish/dataclasses/__init__.py,sha256=9YNCTSCKvNxy0rwxrlh-Sx0qCdn69ROxdDOnmNuKrH0,1640
191
191
  omlish/dataclasses/static.py,sha256=6pZG2iTR9NN8pKm-5ukDABnaVlTKFOzMwkg-rbxURoo,7691
192
- omlish/dataclasses/utils.py,sha256=QWsHxVisS-MUCqh89JQsRdCLgdBVeC6EYK6jRwO9akU,3631
192
+ omlish/dataclasses/utils.py,sha256=BTXYyH0enSEP5kWxMnPTJ8_UPd7h4wF2RVPITNC8H4M,3872
193
193
  omlish/dataclasses/impl/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936
194
194
  omlish/dataclasses/impl/__init__.py,sha256=zqGBC5gSbjJxaqG_zS1LL1PX-zAfhIua8UqOE4IwO2k,789
195
195
  omlish/dataclasses/impl/api.py,sha256=RhU4f50GVdn-dxilia8NA3F7VIm2R5z78pFfpIVXPRQ,6635
@@ -320,7 +320,7 @@ omlish/http/consts.py,sha256=7BJ4D1MdIvqBcepkgCfBFHolgTwbOlqsOEiee_IjxOA,2289
320
320
  omlish/http/cookies.py,sha256=uuOYlHR6e2SC3GM41V0aozK10nef9tYg83Scqpn5-HM,6351
321
321
  omlish/http/dates.py,sha256=Otgp8wRxPgNGyzx8LFowu1vC4EKJYARCiAwLFncpfHM,2875
322
322
  omlish/http/encodings.py,sha256=w2WoKajpaZnQH8j-IBvk5ZFL2O2pAU_iBvZnkocaTlw,164
323
- omlish/http/handlers.py,sha256=l6JLDuK9XhYvF1IudnPz5hWTZW1dXRjUBSO4Uyck0LE,3365
323
+ omlish/http/handlers.py,sha256=ub0TiDCjFIVCUQZZZuDEB3tzJx6T6l_AMRl4s0ZrNy4,3896
324
324
  omlish/http/headers.py,sha256=ZMmjrEiYjzo0YTGyK0YsvjdwUazktGqzVVYorY4fd44,5081
325
325
  omlish/http/json.py,sha256=9XwAsl4966Mxrv-1ytyCqhcE6lbBJw-0_tFZzGszgHE,7440
326
326
  omlish/http/jwt.py,sha256=6Rigk1WrJ059DY4jDIKnxjnChWb7aFdermj2AI2DSvk,4346
@@ -399,10 +399,11 @@ omlish/iterators/iterators.py,sha256=ghI4dO6WPyyFOLTIIMaHQ_IOy2xXaFpGPqveZ5YGIBU
399
399
  omlish/iterators/recipes.py,sha256=53mkexitMhkwXQZbL6DrhpT0WePQ_56uXd5Jaw3DfzI,467
400
400
  omlish/iterators/tools.py,sha256=Pi4ybXytUXVZ3xwK89xpPImQfYYId9p1vIFQvVqVLqA,2551
401
401
  omlish/iterators/unique.py,sha256=0jAX3kwzVfRNhe0Tmh7kVP_Q2WBIn8POo_O-rgFV0rQ,1390
402
- omlish/lang/__init__.py,sha256=0LNdzzVTKiDEmjCzT9wUPbimcAu21KYe-EwD4xDgtRM,4592
403
- omlish/lang/attrs.py,sha256=vGYdGnS7ZAbSz0ZSZkkZKHCK1tKoNjZY0JdzFraHiUw,3105
402
+ omlish/lang/__init__.py,sha256=7QEQKrw1ojkB3kwFQrh-p7EH-UQI7sMemtxNX2OTTJI,4685
403
+ omlish/lang/attrs.py,sha256=fofCKN0X8TMu1yGqHpLpNLih9r9HWl3D3Vn3b6O791w,3891
404
404
  omlish/lang/clsdct.py,sha256=sJYadm-fwzti-gsi98knR5qQUxriBmOqQE_qz3RopNk,1743
405
405
  omlish/lang/cmp.py,sha256=5vbzWWbqdzDmNKAGL19z6ZfUKe5Ci49e-Oegf9f4BsE,1346
406
+ omlish/lang/collections.py,sha256=I0x5BI_cjTbL-uunoKFWA_RfNEz3gyuPkYIajdTH1CA,1236
406
407
  omlish/lang/contextmanagers.py,sha256=UPH6daYwSP9cH5AfSVsJyEHk1UURMGhVPM5ZRhp_Hvw,7576
407
408
  omlish/lang/datetimes.py,sha256=ehI_DhQRM-bDxAavnp470XcekbbXc4Gdw9y1KpHDJT0,223
408
409
  omlish/lang/descriptors.py,sha256=mZ2h9zJ__MMpw8hByjRbAiONcwfVb6GD0btNnVi8C5w,6573
@@ -419,7 +420,7 @@ omlish/lang/strings.py,sha256=egdv8PxLNG40-5V93agP5j2rBUDIsahCx048zV7uEbU,4690
419
420
  omlish/lang/sys.py,sha256=UoZz_PJYVKLQAKqYxxn-LHz1okK_38I__maZgnXMcxU,406
420
421
  omlish/lang/typing.py,sha256=Zdad9Zv0sa-hIaUXPrzPidT7sDVpRcussAI7D-j-I1c,3296
421
422
  omlish/lang/cached/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
422
- omlish/lang/cached/function.py,sha256=k3jRNuDtFh9Mk97oonC7nq5XRros2qmRJVWviMFrx74,8728
423
+ omlish/lang/cached/function.py,sha256=5pS3FCTxOradeMsrKg7JbXHsWhqdaa2C34apkXkwqqU,8785
423
424
  omlish/lang/cached/property.py,sha256=kzbao_35PlszdK_9oJBWrMmFFlVK_Xhx7YczHhTJ6cc,2764
424
425
  omlish/lang/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
425
426
  omlish/lang/classes/abstract.py,sha256=bIcuAetV_aChhpSURypmjjcqP07xi20uVYPKh1kvQNU,3710
@@ -476,7 +477,7 @@ omlish/manifests/base.py,sha256=D1WvJYcBR_njkc0gpALpFCWh1h3agb9qgqphnbbPlm4,935
476
477
  omlish/manifests/load.py,sha256=9mdsS3egmSX9pymO-m-y2Fhs4p6ruOdbsYaKT1-1Hwg,6655
477
478
  omlish/manifests/static.py,sha256=7YwOVh_Ek9_aTrWsWNO8kWS10_j4K7yv3TpXZSHsvDY,501
478
479
  omlish/manifests/types.py,sha256=IOt9dOe0r8okCHSL82ryi3sn4VZ6AT80g_QQR6oZtCE,306
479
- omlish/marshal/__init__.py,sha256=00D3S6qwUld1TUWd67hVHuNcrj3c_FAFSkCVXgGWT-s,2607
480
+ omlish/marshal/__init__.py,sha256=8jKG43_yJzX6MP0RMUJeLUn-BnWiMXDjpKH5-DnAIT4,3109
480
481
  omlish/marshal/base.py,sha256=s1wQRPG2Y6kH0qQXoL3d60ldYaVTqLuFs0NdbYXwAGg,6842
481
482
  omlish/marshal/exceptions.py,sha256=jwQWn4LcPnadT2KRI_1JJCOSkwWh0yHnYK9BmSkNN4U,302
482
483
  omlish/marshal/factories.py,sha256=Q926jSVjaQLEmStnHLhm_c_vqEysN1LnDCwAsFLIzXw,2970
@@ -493,18 +494,19 @@ omlish/marshal/composite/mappings.py,sha256=92oAqYzzTdRNhFDtmukpJd8anoi3pt2nX5Xh
493
494
  omlish/marshal/composite/maybes.py,sha256=4rxTv769Uk4gQGAnE6urVnMscF1vhcnwqP_lm5QzSoM,2211
494
495
  omlish/marshal/composite/newtypes.py,sha256=lYCacdR2BlLWMT1kc8o08UjsmJ6aYlAHkrzG8BozWCM,849
495
496
  omlish/marshal/composite/optionals.py,sha256=iQgSrb9Xyb_IP81YREAZ0xKYXImLgMILGLBnYL2lFWw,1508
497
+ omlish/marshal/composite/wrapped.py,sha256=F0pMC2WtJaPnOmzLT1FKFo9Tkzy1XbdBm9iROyp-myw,745
496
498
  omlish/marshal/objects/__init__.py,sha256=F4wej8L_tedC8ETYxAnmKfdPR9TjsqIus9Z3nZofYuc,182
497
- omlish/marshal/objects/dataclasses.py,sha256=Fo15maLrWICq4H3YlZpa0PjnJTC4eqG1IF0C-88qCKs,7780
499
+ omlish/marshal/objects/dataclasses.py,sha256=sz2GhOEL0wPQj1sNrH0dRN7MefiI72iaDPXIrdtgA64,8491
498
500
  omlish/marshal/objects/helpers.py,sha256=85GZp4h3Yo0GYGmnZpKgNxkWnSk8h2R21nfDLU2DtM0,1110
499
501
  omlish/marshal/objects/marshal.py,sha256=rdZsDWKgLBZxV0ZQlwHTJv9iUg0lC57trJHBOFKvuLo,2636
500
502
  omlish/marshal/objects/metadata.py,sha256=QVD7DRhXbLda_Edgpc3OD1xT9fthmeaaj6l_nTE1PMM,3307
501
- omlish/marshal/objects/namedtuples.py,sha256=ENWyiYZhTwDRqUkkWrHeNcoHGEo5GW634jMuBUc3654,2815
503
+ omlish/marshal/objects/namedtuples.py,sha256=nW3IA21PJ7D62_orr2qxnRt794N1TcFqwOO2rPOglmw,2842
502
504
  omlish/marshal/objects/unmarshal.py,sha256=-83sSgL6WX6C3JfXZr64ZLYi3SsJC9kyiGAbEQbVHQI,3620
503
505
  omlish/marshal/polymorphism/__init__.py,sha256=e2UTrSL0qp7w_1vkdxDWd7sXlWhep2KPV49-BB64ma8,130
504
- omlish/marshal/polymorphism/marshal.py,sha256=Lraih0Dhkcwu6Bb6QkrYOWoMIubh46VQkXxJQWisA8Y,1827
506
+ omlish/marshal/polymorphism/marshal.py,sha256=A-fhr4adRDbis3GwGp2fefwT68YT3A4HyogQbMCH69E,2248
505
507
  omlish/marshal/polymorphism/metadata.py,sha256=hbXqkYKXhfJeMllzI0Ubeeqbq201khVN8uprgVhMpHM,3046
506
508
  omlish/marshal/polymorphism/unions.py,sha256=YwsK9T3okGiHj88LTFNdUvuH7VkCsD-aTnZseKzhpdA,4350
507
- omlish/marshal/polymorphism/unmarshal.py,sha256=gdWTgpl4hXBqac1gHmg_23VMb7x42CE2x-3oRpCaLwU,2047
509
+ omlish/marshal/polymorphism/unmarshal.py,sha256=NnNQrJv85tQGkhC4MfvCTOBw7SXRbNNQOlTBXLiup4A,2439
508
510
  omlish/marshal/singular/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
509
511
  omlish/marshal/singular/base64.py,sha256=gQIkFN60lNEuSiu3MDQFoHwMZTtzDbrBRtNpFZ2HXew,1098
510
512
  omlish/marshal/singular/datetimes.py,sha256=1PDVFF6TGkGxGUno8TaFGRof0DQUookYf_X2Nl8T4V0,3723
@@ -534,7 +536,7 @@ omlish/os/journald.py,sha256=2nI8Res1poXkbLc31--MPUlzYMESnCcPUkIxDOCjZW0,3903
534
536
  omlish/os/linux.py,sha256=whJ6scwMKSFBdXiVhJW0BCpJV4jOGMr-a_a3Bhwz6Ls,18938
535
537
  omlish/os/mangle.py,sha256=M0v-SDt4TMnL68I45GekQrUaXkTIILXIlPdqRxKBTKM,524
536
538
  omlish/os/paths.py,sha256=hqPiyg_eYaRoIVPdAeX4oeLEV4Kpln_XsH0tHvbOf8Q,844
537
- omlish/os/signals.py,sha256=FtzkovLb58N3vNdfxflUeXWFCqqKzseCjk5kBdWT-ds,267
539
+ omlish/os/signals.py,sha256=_ycu36jyOAfm1YnEOoEql6w3R5sJ-3pk94NEOvXeGHo,347
538
540
  omlish/os/sizes.py,sha256=ohkALLvqSqBX4iR-7DMKJ4pfOCRdZXV8htH4QywUNM0,152
539
541
  omlish/os/temp.py,sha256=P97KiVeNB7rfGn4tlgU5ro86JUxAsiphLMlxsjQgfB0,1198
540
542
  omlish/os/deathpacts/__init__.py,sha256=IFJkHVWff-VhBbQX38th1RlmjUF2ptKh5TPIzP9Ei2M,229
@@ -545,7 +547,7 @@ omlish/os/pidfiles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
545
547
  omlish/os/pidfiles/__main__.py,sha256=AF8TwjK4xgHVnoLAP9dIWgKvT0vGhHJlfDW0tKZ7tx4,200
546
548
  omlish/os/pidfiles/cli.py,sha256=2SSsP4O3VdpsDIMAkWgWSjh_YNIPzCD9l5LNN2qrIjo,2074
547
549
  omlish/os/pidfiles/manager.py,sha256=qSEwNaWT1KOAnU0KxliwvU_uowme5jyf1FyIPsGwnTY,2391
548
- omlish/os/pidfiles/pidfile.py,sha256=nU3ONJydi3dPfmLl56DOXR7viJ4TAI8eL-iwR2XoB6s,3899
550
+ omlish/os/pidfiles/pidfile.py,sha256=v0p5NTW8tFv1frCBzgjRkXnljsw8PQ1exfc7kjZJ5L8,4359
549
551
  omlish/os/pidfiles/pinning.py,sha256=v9RlJ4BnJZcaZZXiiRqbmzLluaSOkeeEb_WrbKEClBQ,6643
550
552
  omlish/reflect/__init__.py,sha256=Er2yBHibVO16hFNA1szQF2_f43Y3HRCBWtS-fjsOIYc,798
551
553
  omlish/reflect/inspect.py,sha256=WCo2YpBYauKw6k758FLlZ_H4Q05rgVPs96fEv9w6zHQ,1538
@@ -732,9 +734,9 @@ omlish/text/mangle.py,sha256=kfzFLfvepH-chl1P89_mdc5vC4FSqyPA2aVtgzuB8IY,1133
732
734
  omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
733
735
  omlish/text/parts.py,sha256=JkNZpyR2tv2CNcTaWJJhpQ9E4F0yPR8P_YfDbZfMtwQ,6182
734
736
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
735
- omlish-0.0.0.dev245.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
736
- omlish-0.0.0.dev245.dist-info/METADATA,sha256=JjIb3VY1vdwMkndkHrbTmD72X00OMiCJVwBpn07rc88,4176
737
- omlish-0.0.0.dev245.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
738
- omlish-0.0.0.dev245.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
739
- omlish-0.0.0.dev245.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
740
- omlish-0.0.0.dev245.dist-info/RECORD,,
737
+ omlish-0.0.0.dev246.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
738
+ omlish-0.0.0.dev246.dist-info/METADATA,sha256=da_rz6vvTRxwUkKvXh0ZlBAklAosQv_ZvmsnuiTE_E8,4176
739
+ omlish-0.0.0.dev246.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
740
+ omlish-0.0.0.dev246.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
741
+ omlish-0.0.0.dev246.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
742
+ omlish-0.0.0.dev246.dist-info/RECORD,,