omlish 0.0.0.dev226__py3-none-any.whl → 0.0.0.dev228__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.
Files changed (50) hide show
  1. omlish/__about__.py +3 -3
  2. omlish/diag/lslocks.py +4 -4
  3. omlish/diag/lsof.py +3 -4
  4. omlish/diag/ps.py +9 -0
  5. omlish/lite/timeouts.py +1 -1
  6. omlish/marshal/__init__.py +39 -24
  7. omlish/marshal/composite/__init__.py +0 -0
  8. omlish/marshal/{iterables.py → composite/iterables.py} +10 -10
  9. omlish/marshal/{literals.py → composite/literals.py} +9 -9
  10. omlish/marshal/{mappings.py → composite/mappings.py} +10 -10
  11. omlish/marshal/{maybes.py → composite/maybes.py} +11 -11
  12. omlish/marshal/{newtypes.py → composite/newtypes.py} +8 -8
  13. omlish/marshal/{optionals.py → composite/optionals.py} +9 -9
  14. omlish/marshal/objects/__init__.py +7 -0
  15. omlish/marshal/{dataclasses.py → objects/dataclasses.py} +24 -24
  16. omlish/marshal/{helpers.py → objects/helpers.py} +6 -3
  17. omlish/marshal/objects/marshal.py +108 -0
  18. omlish/marshal/objects/metadata.py +124 -0
  19. omlish/marshal/{namedtuples.py → objects/namedtuples.py} +16 -16
  20. omlish/marshal/objects/unmarshal.py +141 -0
  21. omlish/marshal/polymorphism/__init__.py +7 -0
  22. omlish/marshal/polymorphism/marshal.py +66 -0
  23. omlish/marshal/polymorphism/metadata.py +140 -0
  24. omlish/marshal/{unions.py → polymorphism/unions.py} +18 -18
  25. omlish/marshal/polymorphism/unmarshal.py +73 -0
  26. omlish/marshal/singular/__init__.py +0 -0
  27. omlish/marshal/{any.py → singular/any.py} +8 -8
  28. omlish/marshal/{base64.py → singular/base64.py} +9 -9
  29. omlish/marshal/{datetimes.py → singular/datetimes.py} +9 -9
  30. omlish/marshal/{enums.py → singular/enums.py} +9 -9
  31. omlish/marshal/{numbers.py → singular/numbers.py} +8 -8
  32. omlish/marshal/{primitives.py → singular/primitives.py} +8 -8
  33. omlish/marshal/{uuids.py → singular/uuids.py} +8 -8
  34. omlish/marshal/standard.py +32 -32
  35. omlish/os/death.py +70 -4
  36. omlish/os/fcntl.py +11 -12
  37. omlish/os/files.py +18 -3
  38. omlish/os/forkhooks.py +215 -0
  39. omlish/os/pidfiles/manager.py +4 -1
  40. omlish/os/pidfiles/pidfile.py +31 -11
  41. omlish/os/pidfiles/pinning.py +250 -0
  42. omlish/sockets/bind.py +4 -4
  43. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/METADATA +3 -3
  44. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/RECORD +48 -38
  45. omlish/marshal/objects.py +0 -317
  46. omlish/marshal/polymorphism.py +0 -267
  47. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/LICENSE +0 -0
  48. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/WHEEL +0 -0
  49. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/entry_points.txt +0 -0
  50. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/top_level.txt +0 -0
omlish/marshal/objects.py DELETED
@@ -1,317 +0,0 @@
1
- """
2
- TODO:
3
- - cfg naming
4
- - adapters for dataclasses / namedtuples / user objects (as configured)
5
- - mro-merge ObjectMetadata
6
- - key ordering override - like slice, -1 means last
7
- """
8
- import collections.abc
9
- import typing as ta
10
-
11
- from .. import cached
12
- from .. import check
13
- from .. import collections as col
14
- from .. import dataclasses as dc
15
- from .. import lang
16
- from .. import reflect as rfl
17
- from .base import MarshalContext
18
- from .base import Marshaler
19
- from .base import MarshalerFactory
20
- from .base import UnmarshalContext
21
- from .base import Unmarshaler
22
- from .base import UnmarshalerFactory
23
- from .naming import Naming
24
- from .values import Value
25
-
26
-
27
- ##
28
-
29
-
30
- @dc.dataclass(frozen=True, kw_only=True)
31
- class FieldOptions:
32
- omit_if: ta.Callable[[ta.Any], bool] | None = None
33
-
34
- default: lang.Maybe[ta.Any] = dc.xfield(default=lang.empty(), check_type=lang.Maybe)
35
-
36
- embed: bool = False
37
-
38
- no_marshal: bool = False
39
- no_unmarshal: bool = False
40
-
41
-
42
- DEFAULT_FIELD_OPTIONS = FieldOptions()
43
- FIELD_OPTIONS_KWARGS: frozenset[str] = frozenset(dc.fields_dict(FieldOptions).keys())
44
-
45
-
46
- @dc.dataclass(frozen=True, kw_only=True)
47
- class FieldMetadata:
48
- name: str | None = None
49
- alts: ta.Iterable[str] | None = None
50
-
51
- options: FieldOptions = DEFAULT_FIELD_OPTIONS
52
-
53
- marshaler: Marshaler | None = dc.xfield(None, check_type=(Marshaler, None))
54
- marshaler_factory: MarshalerFactory | None = None
55
-
56
- unmarshaler: Unmarshaler | None = dc.xfield(None, check_type=(Unmarshaler, None))
57
- unmarshaler_factory: UnmarshalerFactory | None = None
58
-
59
- def update(self, **kwargs: ta.Any) -> 'FieldMetadata':
60
- okw = {k: v for k, v in kwargs.items() if k in FIELD_OPTIONS_KWARGS}
61
- mkw = {k: v for k, v in kwargs.items() if k not in FIELD_OPTIONS_KWARGS}
62
- return dc.replace(
63
- self,
64
- **(dict(options=dc.replace(self.options, **okw)) if okw else {}),
65
- **mkw,
66
- )
67
-
68
-
69
- @dc.dataclass(frozen=True, kw_only=True)
70
- class ObjectMetadata:
71
- field_naming: Naming | None = None
72
-
73
- unknown_field: str | None = None
74
- source_field: str | None = None
75
-
76
- @cached.property
77
- def specials(self) -> 'ObjectSpecials':
78
- return ObjectSpecials(
79
- unknown=self.unknown_field,
80
- source=self.source_field,
81
- )
82
-
83
- field_defaults: FieldMetadata = FieldMetadata()
84
-
85
- ignore_unknown: bool = False
86
-
87
-
88
- @dc.dataclass(frozen=True, kw_only=True)
89
- class ObjectSpecials:
90
- unknown: str | None = None
91
- source: str | None = None
92
-
93
- @cached.property
94
- def set(self) -> frozenset[str]:
95
- return frozenset(v for v in dc.asdict(self).values() if v is not None)
96
-
97
-
98
- ##
99
-
100
-
101
- @dc.dataclass(frozen=True, kw_only=True)
102
- class FieldInfo:
103
- name: str
104
- type: ta.Any
105
-
106
- marshal_name: str | None
107
- unmarshal_names: ta.Sequence[str]
108
-
109
- metadata: FieldMetadata = FieldMetadata()
110
-
111
- options: FieldOptions = FieldOptions()
112
-
113
-
114
- @dc.dataclass(frozen=True)
115
- class FieldInfos:
116
- lst: ta.Sequence[FieldInfo]
117
-
118
- def __iter__(self) -> ta.Iterator[FieldInfo]:
119
- return iter(self.lst)
120
-
121
- def __len__(self) -> int:
122
- return len(self.lst)
123
-
124
- @cached.property
125
- @dc.init
126
- def by_name(self) -> ta.Mapping[str, FieldInfo]:
127
- return col.make_map(((fi.name, fi) for fi in self), strict=True)
128
-
129
- @cached.property
130
- @dc.init
131
- def by_marshal_name(self) -> ta.Mapping[str, FieldInfo]:
132
- return col.make_map(((fi.marshal_name, fi) for fi in self if fi.marshal_name is not None), strict=True)
133
-
134
- @cached.property
135
- @dc.init
136
- def by_unmarshal_name(self) -> ta.Mapping[str, FieldInfo]:
137
- return col.make_map(((n, fi) for fi in self for n in fi.unmarshal_names), strict=True)
138
-
139
-
140
- ##
141
-
142
-
143
- @dc.dataclass(frozen=True)
144
- class ObjectMarshaler(Marshaler):
145
- fields: ta.Sequence[tuple[FieldInfo, Marshaler]]
146
-
147
- _: dc.KW_ONLY
148
-
149
- specials: ObjectSpecials = ObjectSpecials()
150
-
151
- def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
152
- ret: dict[str, ta.Any] = {}
153
- for fi, m in self.fields:
154
- v = getattr(o, fi.name)
155
-
156
- if fi.options.omit_if is not None and fi.options.omit_if(v):
157
- continue
158
-
159
- if fi.name in self.specials.set:
160
- continue
161
-
162
- mn = fi.marshal_name
163
- if mn is None:
164
- continue
165
-
166
- mv = m.marshal(ctx, v)
167
-
168
- if fi.options.embed:
169
- for ek, ev in check.isinstance(mv, collections.abc.Mapping).items():
170
- ret[mn + check.non_empty_str(ek)] = ev
171
-
172
- else:
173
- ret[mn] = mv
174
-
175
- if self.specials.unknown is not None:
176
- if (ukf := getattr(o, self.specials.unknown)):
177
- if (dks := set(ret) & set(ukf)):
178
- raise KeyError(f'Unknown field keys duplicate fields: {dks!r}')
179
-
180
- ret.update(ukf) # FIXME: marshal?
181
-
182
- return ret
183
-
184
-
185
- @dc.dataclass(frozen=True)
186
- class SimpleObjectMarshalerFactory(MarshalerFactory):
187
- dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
188
-
189
- _: dc.KW_ONLY
190
-
191
- specials: ObjectSpecials = ObjectSpecials()
192
-
193
- def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
194
- return isinstance(rty, type) and rty in self.dct
195
-
196
- def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
197
- ty = check.isinstance(rty, type)
198
-
199
- flds = FieldInfos(self.dct[ty])
200
-
201
- fields = [
202
- (fi, ctx.make(fi.type))
203
- for fi in flds
204
- ]
205
-
206
- return ObjectMarshaler(
207
- fields,
208
- specials=self.specials,
209
- )
210
-
211
-
212
- ##
213
-
214
-
215
- @dc.dataclass(frozen=True)
216
- class ObjectUnmarshaler(Unmarshaler):
217
- cls: type
218
- fields_by_unmarshal_name: ta.Mapping[str, tuple[FieldInfo, Unmarshaler]]
219
-
220
- _: dc.KW_ONLY
221
-
222
- specials: ObjectSpecials = ObjectSpecials()
223
-
224
- defaults: ta.Mapping[str, ta.Any] | None = None
225
-
226
- embeds: ta.Mapping[str, type] | None = None
227
- embeds_by_unmarshal_name: ta.Mapping[str, tuple[str, str]] | None = None
228
-
229
- ignore_unknown: bool = False
230
-
231
- def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
232
- ma = check.isinstance(v, collections.abc.Mapping)
233
-
234
- u: ta.Any
235
- kw: dict[str, ta.Any] = {}
236
- ukf: dict[str, ta.Any] | None = None
237
-
238
- ekws: dict[str, dict[str, ta.Any]] = {en: {} for en in self.embeds or ()}
239
-
240
- if self.specials.source is not None:
241
- kw[self.specials.source] = v
242
-
243
- if self.specials.unknown is not None:
244
- kw[self.specials.unknown] = ukf = {}
245
-
246
- for k, mv in ma.items():
247
- ks = check.isinstance(k, str)
248
-
249
- try:
250
- fi, u = self.fields_by_unmarshal_name[ks]
251
-
252
- except KeyError:
253
- if ukf is not None:
254
- ukf[ks] = mv # FIXME: unmarshal?
255
- continue
256
-
257
- if self.ignore_unknown:
258
- continue
259
-
260
- raise
261
-
262
- if self.embeds_by_unmarshal_name and (en := self.embeds_by_unmarshal_name.get(ks)):
263
- tkw, tk = ekws[en[0]], en[1]
264
- else:
265
- tkw, tk = kw, fi.name
266
-
267
- if tk in tkw:
268
- raise KeyError(f'Duplicate keys for field {tk!r}: {ks!r}')
269
-
270
- tkw[tk] = u.unmarshal(ctx, mv)
271
-
272
- for em, ecls in self.embeds.items() if self.embeds else ():
273
- ekw = ekws[em]
274
- ev = ecls(**ekw)
275
- kw[em] = ev
276
-
277
- if self.defaults:
278
- for dk, dv in self.defaults.items():
279
- kw.setdefault(dk, dv)
280
-
281
- return self.cls(**kw)
282
-
283
-
284
- @dc.dataclass(frozen=True)
285
- class SimpleObjectUnmarshalerFactory(UnmarshalerFactory):
286
- dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
287
-
288
- _: dc.KW_ONLY
289
-
290
- specials: ObjectSpecials = ObjectSpecials()
291
-
292
- def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
293
- return isinstance(rty, type) and rty in self.dct
294
-
295
- def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
296
- ty = check.isinstance(rty, type)
297
-
298
- flds = FieldInfos(self.dct[ty])
299
-
300
- fields_by_unmarshal_name = {
301
- n: (fi, ctx.make(fi.type))
302
- for fi in flds
303
- for n in fi.unmarshal_names
304
- }
305
-
306
- defaults = {
307
- fi.name: fi.options.default.must()
308
- for fi in flds
309
- if fi.options.default.present
310
- }
311
-
312
- return ObjectUnmarshaler(
313
- ty,
314
- fields_by_unmarshal_name,
315
- specials=self.specials,
316
- defaults=defaults,
317
- )
@@ -1,267 +0,0 @@
1
- """
2
- TODO:
3
- - auto-gen from __subclasses__ if abstract
4
- - cfg: unless prefixed with _ or abstract
5
- - iff Sealed
6
- - auto-name
7
- """
8
- import collections.abc
9
- import dataclasses as dc
10
- import typing as ta
11
-
12
- from .. import check
13
- from .. import lang
14
- from .. import reflect as rfl
15
- from .base import MarshalContext
16
- from .base import Marshaler
17
- from .base import MarshalerFactory
18
- from .base import UnmarshalContext
19
- from .base import Unmarshaler
20
- from .base import UnmarshalerFactory
21
- from .naming import Naming
22
- from .naming import translate_name
23
- from .registries import RegistryItem
24
- from .values import Value
25
-
26
-
27
- ##
28
-
29
-
30
- class TypeTagging(RegistryItem, lang.Abstract, lang.Sealed):
31
- pass
32
-
33
-
34
- class WrapperTypeTagging(TypeTagging, lang.Final):
35
- pass
36
-
37
-
38
- @dc.dataclass(frozen=True)
39
- class FieldTypeTagging(TypeTagging, lang.Final):
40
- field: str
41
-
42
-
43
- ##
44
-
45
-
46
- @dc.dataclass(frozen=True)
47
- class Impl:
48
- ty: type
49
- tag: str
50
- alts: ta.AbstractSet[str] = frozenset()
51
-
52
-
53
- class Impls(ta.Sequence[Impl]):
54
- def __init__(
55
- self,
56
- lst: ta.Iterable[Impl],
57
- ) -> None:
58
- super().__init__()
59
- self._lst = list(lst)
60
-
61
- by_ty: dict[type, Impl] = {}
62
- by_tag: dict[str, Impl] = {}
63
- for i in self._lst:
64
- if i.ty in by_ty:
65
- raise TypeError(i.ty)
66
- if i.tag in by_tag:
67
- raise NameError(i.tag)
68
- for a in i.alts:
69
- if a in by_tag:
70
- raise NameError(a)
71
- by_ty[i.ty] = i
72
- by_tag[i.tag] = i
73
- for a in i.alts:
74
- by_tag[a] = i
75
- self._by_ty = by_ty
76
- self._by_tag = by_tag
77
-
78
- def __iter__(self) -> ta.Iterator[Impl]:
79
- return iter(self._lst)
80
-
81
- def __len__(self) -> int:
82
- return len(self._lst)
83
-
84
- @ta.overload
85
- def __getitem__(self, index: int) -> Impl: ...
86
-
87
- @ta.overload
88
- def __getitem__(self, index: slice) -> ta.Sequence[Impl]: ...
89
-
90
- def __getitem__(self, index):
91
- return self._lst[index]
92
-
93
- @property
94
- def by_ty(self) -> ta.Mapping[type, Impl]:
95
- return self._by_ty
96
-
97
- @property
98
- def by_tag(self) -> ta.Mapping[str, Impl]:
99
- return self._by_tag
100
-
101
-
102
- class Polymorphism:
103
- def __init__(
104
- self,
105
- ty: type,
106
- impls: ta.Iterable[Impl],
107
- ) -> None:
108
- super().__init__()
109
- self._ty = ty
110
- self._impls = Impls(impls)
111
-
112
- for i in self._impls:
113
- if not issubclass(i.ty, ty):
114
- raise TypeError(i.ty, ty)
115
-
116
- @property
117
- def ty(self) -> type:
118
- return self._ty
119
-
120
- @property
121
- def impls(self) -> Impls:
122
- return self._impls
123
-
124
-
125
- def polymorphism_from_subclasses(
126
- ty: type,
127
- *,
128
- naming: Naming | None = None,
129
- strip_suffix: bool = False,
130
- ) -> Polymorphism:
131
- dct: dict[str, Impl] = {}
132
-
133
- seen: set[type] = set()
134
- todo: list[type] = [ty]
135
- while todo:
136
- cur = todo.pop()
137
- seen.add(cur)
138
-
139
- todo.extend(nxt for nxt in cur.__subclasses__() if nxt not in seen)
140
-
141
- if lang.is_abstract_class(cur):
142
- continue
143
-
144
- name = cur.__name__
145
- if strip_suffix:
146
- name = lang.strip_suffix(name, ty.__name__)
147
- if naming is not None:
148
- name = translate_name(name, naming)
149
- if name in dct:
150
- raise KeyError(f'Duplicate name: {name}')
151
-
152
- dct[name] = Impl(
153
- cur,
154
- name,
155
- )
156
-
157
- return Polymorphism(ty, dct.values())
158
-
159
-
160
- ##
161
-
162
-
163
- @dc.dataclass(frozen=True)
164
- class WrapperPolymorphismMarshaler(Marshaler):
165
- m: ta.Mapping[type, tuple[str, Marshaler]]
166
-
167
- def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
168
- tag, m = self.m[type(o)]
169
- return {tag: m.marshal(ctx, o)}
170
-
171
-
172
- @dc.dataclass(frozen=True)
173
- class FieldPolymorphismMarshaler(Marshaler):
174
- m: ta.Mapping[type, tuple[str, Marshaler]]
175
- tf: str
176
-
177
- def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
178
- tag, m = self.m[type(o)]
179
- return {self.tf: tag, **m.marshal(ctx, o)} # type: ignore
180
-
181
-
182
- def make_polymorphism_marshaler(
183
- impls: Impls,
184
- tt: TypeTagging,
185
- ctx: MarshalContext,
186
- ) -> Marshaler:
187
- m = {
188
- i.ty: (i.tag, ctx.make(i.ty))
189
- for i in impls
190
- }
191
- if isinstance(tt, WrapperTypeTagging):
192
- return WrapperPolymorphismMarshaler(m)
193
- elif isinstance(tt, FieldTypeTagging):
194
- return FieldPolymorphismMarshaler(m, tt.field)
195
- else:
196
- raise TypeError(tt)
197
-
198
-
199
- @dc.dataclass(frozen=True)
200
- class PolymorphismMarshalerFactory(MarshalerFactory):
201
- p: Polymorphism
202
- tt: TypeTagging = WrapperTypeTagging()
203
-
204
- def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
205
- return rty is self.p.ty
206
-
207
- def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
208
- check.is_(rty, self.p.ty)
209
- return make_polymorphism_marshaler(self.p.impls, self.tt, ctx)
210
-
211
-
212
- ##
213
-
214
-
215
- @dc.dataclass(frozen=True)
216
- class WrapperPolymorphismUnmarshaler(Unmarshaler):
217
- m: ta.Mapping[str, Unmarshaler]
218
-
219
- def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
220
- ma = check.isinstance(v, collections.abc.Mapping)
221
- [(tag, iv)] = ma.items()
222
- u = self.m[tag]
223
- return u.unmarshal(ctx, iv)
224
-
225
-
226
- @dc.dataclass(frozen=True)
227
- class FieldPolymorphismUnmarshaler(Unmarshaler):
228
- m: ta.Mapping[str, Unmarshaler]
229
- tf: str
230
-
231
- def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
232
- ma = dict(check.isinstance(v, collections.abc.Mapping))
233
- tag = ma.pop(self.tf)
234
- u = self.m[tag]
235
- return u.unmarshal(ctx, ma)
236
-
237
-
238
- def make_polymorphism_unmarshaler(
239
- impls: Impls,
240
- tt: TypeTagging,
241
- ctx: UnmarshalContext,
242
- ) -> Unmarshaler:
243
- m = {
244
- t: u
245
- for i in impls
246
- for u in [ctx.make(i.ty)]
247
- for t in [i.tag, *i.alts]
248
- }
249
- if isinstance(tt, WrapperTypeTagging):
250
- return WrapperPolymorphismUnmarshaler(m)
251
- elif isinstance(tt, FieldTypeTagging):
252
- return FieldPolymorphismUnmarshaler(m, tt.field)
253
- else:
254
- raise TypeError(tt)
255
-
256
-
257
- @dc.dataclass(frozen=True)
258
- class PolymorphismUnmarshalerFactory(UnmarshalerFactory):
259
- p: Polymorphism
260
- tt: TypeTagging = WrapperTypeTagging()
261
-
262
- def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
263
- return rty is self.p.ty
264
-
265
- def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
266
- check.is_(rty, self.p.ty)
267
- return make_polymorphism_unmarshaler(self.p.impls, self.tt, ctx)