omlish 0.0.0.dev226__py3-none-any.whl → 0.0.0.dev228__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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)