omdev 0.0.0.dev144__py3-none-any.whl → 0.0.0.dev146__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 omdev might be problematic. Click here for more details.

omdev/.manifests.json CHANGED
@@ -243,7 +243,7 @@
243
243
  "module": ".tools.docker",
244
244
  "attr": "_CLI_MODULE",
245
245
  "file": "omdev/tools/docker.py",
246
- "line": 236,
246
+ "line": 249,
247
247
  "value": {
248
248
  "$.cli.types.CliModule": {
249
249
  "cmd_name": "docker",
@@ -255,7 +255,7 @@
255
255
  "module": ".tools.git",
256
256
  "attr": "_CLI_MODULE",
257
257
  "file": "omdev/tools/git.py",
258
- "line": 211,
258
+ "line": 215,
259
259
  "value": {
260
260
  "$.cli.types.CliModule": {
261
261
  "cmd_name": "git",
omdev/amalg/amalg.py CHANGED
@@ -25,8 +25,10 @@ Targets:
25
25
  """
26
26
  import argparse
27
27
  import ast
28
+ import base64
28
29
  import dataclasses as dc
29
30
  import io
31
+ import itertools
30
32
  import logging
31
33
  import os.path
32
34
  import re
@@ -286,6 +288,37 @@ def is_root_level_if_type_checking_block(lts: Tokens) -> bool:
286
288
  ##
287
289
 
288
290
 
291
+ class RootLevelResourcesRead(ta.NamedTuple):
292
+ variable: str
293
+ kind: ta.Literal['binary', 'text']
294
+ resource: str
295
+
296
+
297
+ def is_root_level_resources_read(lts: Tokens) -> RootLevelResourcesRead | None:
298
+ wts = list(tks.ignore_ws(lts, keep=['INDENT']))
299
+
300
+ if not tks.match_toks(wts, [
301
+ ('NAME', None),
302
+ ('OP', '='),
303
+ ('NAME', ('read_package_resource_binary', 'read_package_resource_text')),
304
+ ('OP', '('),
305
+ ('NAME', '__package__'),
306
+ ('OP', ','),
307
+ ('STRING', None),
308
+ ('OP', ')'),
309
+ ]):
310
+ return None
311
+
312
+ return RootLevelResourcesRead(
313
+ wts[0].src,
314
+ 'binary' if wts[2].src == 'read_package_resource_binary' else 'text',
315
+ ast.literal_eval(wts[6].src),
316
+ )
317
+
318
+
319
+ ##
320
+
321
+
289
322
  @dc.dataclass(frozen=True, kw_only=True)
290
323
  class SrcFile:
291
324
  path: str
@@ -301,6 +334,8 @@ class SrcFile:
301
334
 
302
335
  ruff_noqa: ta.AbstractSet[str] = dc.field(repr=False)
303
336
 
337
+ has_binary_resources: bool = False
338
+
304
339
 
305
340
  def make_src_file(
306
341
  path: str,
@@ -322,6 +357,8 @@ def make_src_file(
322
357
  tys: list[Typing] = []
323
358
  ctls: list[Tokens] = []
324
359
 
360
+ has_binary_resources = False
361
+
325
362
  i = 0
326
363
  while i < len(cls):
327
364
  line = cls[i]
@@ -383,6 +420,57 @@ def make_src_file(
383
420
  i += 1
384
421
  skip_block()
385
422
 
423
+ elif (rsrc := is_root_level_resources_read(line)) is not None:
424
+ rf = os.path.join(os.path.dirname(path), rsrc.resource)
425
+
426
+ if rsrc.kind == 'binary':
427
+ with open(rf, 'rb') as bf:
428
+ rb = bf.read() # noqa
429
+
430
+ ctls.append([
431
+ trt.Token(name='NAME', src=rsrc.variable),
432
+ trt.Token(name='UNIMPORTANT_WS', src=' '),
433
+ trt.Token(name='OP', src='='),
434
+ trt.Token(name='UNIMPORTANT_WS', src=' '),
435
+ trt.Token(name='NAME', src='base64'),
436
+ trt.Token(name='OP', src='.'),
437
+ trt.Token(name='NAME', src='b64decode'),
438
+ trt.Token(name='OP', src='('),
439
+ trt.Token(name='NL', src='\n'),
440
+ ])
441
+
442
+ rb64 = base64.b64encode(rb).decode('ascii')
443
+ for chunk in itertools.batched(rb64, 96):
444
+ ctls.append([
445
+ trt.Token(name='UNIMPORTANT_WS', src=' '),
446
+ trt.Token(name='STRING', src=f"'{''.join(chunk)}'"),
447
+ trt.Token(name='NL', src='\n'),
448
+ ])
449
+
450
+ ctls.append([
451
+ trt.Token(name='OP', src=')'),
452
+ trt.Token(name='NEWLINE', src='\n'),
453
+ ])
454
+
455
+ has_binary_resources = True
456
+
457
+ elif rsrc.kind == 'text':
458
+ with open(rf) as tf:
459
+ rt = tf.read() # noqa
460
+ rt = rt.replace('\\', '\\\\') # Escape backslashes
461
+ rt = rt.replace('"""', r'\"\"\"')
462
+ ctls.append([
463
+ trt.Token(name='NAME', src=rsrc.variable),
464
+ trt.Token(name='UNIMPORTANT_WS', src=' '),
465
+ trt.Token(name='OP', src='='),
466
+ trt.Token(name='UNIMPORTANT_WS', src=' '),
467
+ trt.Token(name='STRING', src=f'"""\\\n{rt}"""\n'),
468
+ trt.Token(name='NEWLINE', src=''),
469
+ ])
470
+
471
+ else:
472
+ raise ValueError(rsrc.kind)
473
+
386
474
  else:
387
475
  ctls.append(line)
388
476
 
@@ -399,6 +487,8 @@ def make_src_file(
399
487
  content_lines=ctls,
400
488
 
401
489
  ruff_noqa=set(lang.flatten(tks.join_toks(l).strip().split()[3:] for l in rnls)), # noqa
490
+
491
+ has_binary_resources=has_binary_resources,
402
492
  )
403
493
 
404
494
 
@@ -488,6 +578,8 @@ def gen_amalg(
488
578
  dct: dict = {
489
579
  ('sys', None, None): ['import sys\n'],
490
580
  }
581
+ if any(sf.has_binary_resources for sf in src_files.values()):
582
+ dct[('base64', None, None)] = ['import base64\n']
491
583
  for imp in gl_imps:
492
584
  dct.setdefault((imp.mod, imp.item, imp.as_), []).append(imp)
493
585
  for _, l in sorted(dct.items()):
omdev/cli/main.py CHANGED
@@ -13,8 +13,8 @@ import typing as ta
13
13
 
14
14
  from omlish import check
15
15
  from omlish.lite.cached import cached_nullary
16
+ from omlish.manifests.load import ManifestLoader
16
17
 
17
- from ..manifests.load import ManifestLoader
18
18
  from .types import CliCmd
19
19
  from .types import CliFunc
20
20
  from .types import CliModule
omdev/interp/resolvers.py CHANGED
@@ -35,7 +35,7 @@ class InterpResolver:
35
35
  if spec.contains(si)
36
36
  ]
37
37
 
38
- slst = sorted(lst, key=lambda t: (-t[0], t[1]))
38
+ slst = sorted(lst, key=lambda t: (-t[0], t[1].version))
39
39
  if not slst:
40
40
  return None
41
41
 
@@ -1,2 +1 @@
1
1
  # @omlish-lite
2
- from .types import Manifest # noqa
omdev/manifests/build.py CHANGED
@@ -1,3 +1,4 @@
1
+ # ruff: noqa: UP006 UP007
1
2
  """
2
3
  TODO:
3
4
  - separate build from cli
@@ -10,7 +11,6 @@ See (entry_points):
10
11
  - https://packaging.python.org/en/latest/guides/creating-and-discovering-plugins/
11
12
  - [project.entry-points.omlish-manifests] \n omdev = omdev
12
13
  """
13
- # ruff: noqa: UP006 UP007
14
14
  import argparse
15
15
  import asyncio
16
16
  import collections
@@ -31,11 +31,11 @@ from omlish.lite.cached import cached_nullary
31
31
  from omlish.lite.json import json_dumps_pretty
32
32
  from omlish.lite.logs import configure_standard_logging
33
33
  from omlish.lite.logs import log
34
+ from omlish.manifests.load import ManifestLoader
35
+ from omlish.manifests.types import Manifest
36
+ from omlish.manifests.types import ManifestOrigin
34
37
 
35
38
  from .. import magic
36
- from .load import ManifestLoader
37
- from .types import Manifest
38
- from .types import ManifestOrigin
39
39
 
40
40
 
41
41
  T = ta.TypeVar('T')
@@ -1,7 +1,8 @@
1
1
  import dataclasses as dc
2
2
  import typing as ta
3
3
 
4
- from ..manifests.load import ManifestLoader
4
+ from omlish.manifests.load import ManifestLoader
5
+
5
6
  from .base import Precheck
6
7
  from .base import PrecheckContext
7
8
 
omdev/scripts/interp.py CHANGED
@@ -2530,7 +2530,7 @@ class InterpResolver:
2530
2530
  if spec.contains(si)
2531
2531
  ]
2532
2532
 
2533
- slst = sorted(lst, key=lambda t: (-t[0], t[1]))
2533
+ slst = sorted(lst, key=lambda t: (-t[0], t[1].version))
2534
2534
  if not slst:
2535
2535
  return None
2536
2536
 
@@ -3087,23 +3087,24 @@ TODO:
3087
3087
  @dc.dataclass(frozen=True)
3088
3088
  class ObjMarshalOptions:
3089
3089
  raw_bytes: bool = False
3090
+ nonstrict_dataclasses: bool = False
3090
3091
 
3091
3092
 
3092
3093
  class ObjMarshaler(abc.ABC):
3093
3094
  @abc.abstractmethod
3094
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3095
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3095
3096
  raise NotImplementedError
3096
3097
 
3097
3098
  @abc.abstractmethod
3098
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3099
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3099
3100
  raise NotImplementedError
3100
3101
 
3101
3102
 
3102
3103
  class NopObjMarshaler(ObjMarshaler):
3103
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3104
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3104
3105
  return o
3105
3106
 
3106
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3107
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3107
3108
  return o
3108
3109
 
3109
3110
 
@@ -3111,29 +3112,29 @@ class NopObjMarshaler(ObjMarshaler):
3111
3112
  class ProxyObjMarshaler(ObjMarshaler):
3112
3113
  m: ta.Optional[ObjMarshaler] = None
3113
3114
 
3114
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3115
- return check_not_none(self.m).marshal(o, opts)
3115
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3116
+ return check_not_none(self.m).marshal(o, ctx)
3116
3117
 
3117
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3118
- return check_not_none(self.m).unmarshal(o, opts)
3118
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3119
+ return check_not_none(self.m).unmarshal(o, ctx)
3119
3120
 
3120
3121
 
3121
3122
  @dc.dataclass(frozen=True)
3122
3123
  class CastObjMarshaler(ObjMarshaler):
3123
3124
  ty: type
3124
3125
 
3125
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3126
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3126
3127
  return o
3127
3128
 
3128
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3129
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3129
3130
  return self.ty(o)
3130
3131
 
3131
3132
 
3132
3133
  class DynamicObjMarshaler(ObjMarshaler):
3133
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3134
- return marshal_obj(o)
3134
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3135
+ return ctx.manager.marshal_obj(o, opts=ctx.options)
3135
3136
 
3136
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3137
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3137
3138
  return o
3138
3139
 
3139
3140
 
@@ -3141,10 +3142,10 @@ class DynamicObjMarshaler(ObjMarshaler):
3141
3142
  class Base64ObjMarshaler(ObjMarshaler):
3142
3143
  ty: type
3143
3144
 
3144
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3145
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3145
3146
  return base64.b64encode(o).decode('ascii')
3146
3147
 
3147
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3148
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3148
3149
  return self.ty(base64.b64decode(o))
3149
3150
 
3150
3151
 
@@ -3152,25 +3153,25 @@ class Base64ObjMarshaler(ObjMarshaler):
3152
3153
  class BytesSwitchedObjMarshaler(ObjMarshaler):
3153
3154
  m: ObjMarshaler
3154
3155
 
3155
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3156
- if opts.raw_bytes:
3156
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3157
+ if ctx.options.raw_bytes:
3157
3158
  return o
3158
- return self.m.marshal(o, opts)
3159
+ return self.m.marshal(o, ctx)
3159
3160
 
3160
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3161
- if opts.raw_bytes:
3161
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3162
+ if ctx.options.raw_bytes:
3162
3163
  return o
3163
- return self.m.unmarshal(o, opts)
3164
+ return self.m.unmarshal(o, ctx)
3164
3165
 
3165
3166
 
3166
3167
  @dc.dataclass(frozen=True)
3167
3168
  class EnumObjMarshaler(ObjMarshaler):
3168
3169
  ty: type
3169
3170
 
3170
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3171
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3171
3172
  return o.name
3172
3173
 
3173
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3174
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3174
3175
  return self.ty.__members__[o] # type: ignore
3175
3176
 
3176
3177
 
@@ -3178,15 +3179,15 @@ class EnumObjMarshaler(ObjMarshaler):
3178
3179
  class OptionalObjMarshaler(ObjMarshaler):
3179
3180
  item: ObjMarshaler
3180
3181
 
3181
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3182
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3182
3183
  if o is None:
3183
3184
  return None
3184
- return self.item.marshal(o, opts)
3185
+ return self.item.marshal(o, ctx)
3185
3186
 
3186
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3187
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3187
3188
  if o is None:
3188
3189
  return None
3189
- return self.item.unmarshal(o, opts)
3190
+ return self.item.unmarshal(o, ctx)
3190
3191
 
3191
3192
 
3192
3193
  @dc.dataclass(frozen=True)
@@ -3195,11 +3196,11 @@ class MappingObjMarshaler(ObjMarshaler):
3195
3196
  km: ObjMarshaler
3196
3197
  vm: ObjMarshaler
3197
3198
 
3198
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3199
- return {self.km.marshal(k, opts): self.vm.marshal(v, opts) for k, v in o.items()}
3199
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3200
+ return {self.km.marshal(k, ctx): self.vm.marshal(v, ctx) for k, v in o.items()}
3200
3201
 
3201
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3202
- return self.ty((self.km.unmarshal(k, opts), self.vm.unmarshal(v, opts)) for k, v in o.items())
3202
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3203
+ return self.ty((self.km.unmarshal(k, ctx), self.vm.unmarshal(v, ctx)) for k, v in o.items())
3203
3204
 
3204
3205
 
3205
3206
  @dc.dataclass(frozen=True)
@@ -3207,11 +3208,11 @@ class IterableObjMarshaler(ObjMarshaler):
3207
3208
  ty: type
3208
3209
  item: ObjMarshaler
3209
3210
 
3210
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3211
- return [self.item.marshal(e, opts) for e in o]
3211
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3212
+ return [self.item.marshal(e, ctx) for e in o]
3212
3213
 
3213
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3214
- return self.ty(self.item.unmarshal(e, opts) for e in o)
3214
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3215
+ return self.ty(self.item.unmarshal(e, ctx) for e in o)
3215
3216
 
3216
3217
 
3217
3218
  @dc.dataclass(frozen=True)
@@ -3220,11 +3221,18 @@ class DataclassObjMarshaler(ObjMarshaler):
3220
3221
  fs: ta.Mapping[str, ObjMarshaler]
3221
3222
  nonstrict: bool = False
3222
3223
 
3223
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3224
- return {k: m.marshal(getattr(o, k), opts) for k, m in self.fs.items()}
3224
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3225
+ return {
3226
+ k: m.marshal(getattr(o, k), ctx)
3227
+ for k, m in self.fs.items()
3228
+ }
3225
3229
 
3226
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3227
- return self.ty(**{k: self.fs[k].unmarshal(v, opts) for k, v in o.items() if not self.nonstrict or k in self.fs})
3230
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3231
+ return self.ty(**{
3232
+ k: self.fs[k].unmarshal(v, ctx)
3233
+ for k, v in o.items()
3234
+ if not (self.nonstrict or ctx.options.nonstrict_dataclasses) or k in self.fs
3235
+ })
3228
3236
 
3229
3237
 
3230
3238
  @dc.dataclass(frozen=True)
@@ -3244,50 +3252,50 @@ class PolymorphicObjMarshaler(ObjMarshaler):
3244
3252
  {i.tag: i for i in impls},
3245
3253
  )
3246
3254
 
3247
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3255
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3248
3256
  impl = self.impls_by_ty[type(o)]
3249
- return {impl.tag: impl.m.marshal(o, opts)}
3257
+ return {impl.tag: impl.m.marshal(o, ctx)}
3250
3258
 
3251
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3259
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3252
3260
  [(t, v)] = o.items()
3253
3261
  impl = self.impls_by_tag[t]
3254
- return impl.m.unmarshal(v, opts)
3262
+ return impl.m.unmarshal(v, ctx)
3255
3263
 
3256
3264
 
3257
3265
  @dc.dataclass(frozen=True)
3258
3266
  class DatetimeObjMarshaler(ObjMarshaler):
3259
3267
  ty: type
3260
3268
 
3261
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3269
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3262
3270
  return o.isoformat()
3263
3271
 
3264
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3272
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3265
3273
  return self.ty.fromisoformat(o) # type: ignore
3266
3274
 
3267
3275
 
3268
3276
  class DecimalObjMarshaler(ObjMarshaler):
3269
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3277
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3270
3278
  return str(check_isinstance(o, decimal.Decimal))
3271
3279
 
3272
- def unmarshal(self, v: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3280
+ def unmarshal(self, v: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3273
3281
  return decimal.Decimal(check_isinstance(v, str))
3274
3282
 
3275
3283
 
3276
3284
  class FractionObjMarshaler(ObjMarshaler):
3277
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3285
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3278
3286
  fr = check_isinstance(o, fractions.Fraction)
3279
3287
  return [fr.numerator, fr.denominator]
3280
3288
 
3281
- def unmarshal(self, v: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3289
+ def unmarshal(self, v: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3282
3290
  num, denom = check_isinstance(v, list)
3283
3291
  return fractions.Fraction(num, denom)
3284
3292
 
3285
3293
 
3286
3294
  class UuidObjMarshaler(ObjMarshaler):
3287
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3295
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3288
3296
  return str(o)
3289
3297
 
3290
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
3298
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
3291
3299
  return uuid.UUID(o)
3292
3300
 
3293
3301
 
@@ -3448,6 +3456,12 @@ class ObjMarshalerManager:
3448
3456
 
3449
3457
  #
3450
3458
 
3459
+ def _make_context(self, opts: ta.Optional[ObjMarshalOptions]) -> 'ObjMarshalContext':
3460
+ return ObjMarshalContext(
3461
+ options=opts or self._default_options,
3462
+ manager=self,
3463
+ )
3464
+
3451
3465
  def marshal_obj(
3452
3466
  self,
3453
3467
  o: ta.Any,
@@ -3455,7 +3469,7 @@ class ObjMarshalerManager:
3455
3469
  opts: ta.Optional[ObjMarshalOptions] = None,
3456
3470
  ) -> ta.Any:
3457
3471
  m = self.get_obj_marshaler(ty if ty is not None else type(o))
3458
- return m.marshal(o, opts or self._default_options)
3472
+ return m.marshal(o, self._make_context(opts))
3459
3473
 
3460
3474
  def unmarshal_obj(
3461
3475
  self,
@@ -3464,7 +3478,7 @@ class ObjMarshalerManager:
3464
3478
  opts: ta.Optional[ObjMarshalOptions] = None,
3465
3479
  ) -> T:
3466
3480
  m = self.get_obj_marshaler(ty)
3467
- return m.unmarshal(o, opts or self._default_options)
3481
+ return m.unmarshal(o, self._make_context(opts))
3468
3482
 
3469
3483
  def roundtrip_obj(
3470
3484
  self,
@@ -3479,6 +3493,12 @@ class ObjMarshalerManager:
3479
3493
  return u
3480
3494
 
3481
3495
 
3496
+ @dc.dataclass(frozen=True)
3497
+ class ObjMarshalContext:
3498
+ options: ObjMarshalOptions
3499
+ manager: ObjMarshalerManager
3500
+
3501
+
3482
3502
  ##
3483
3503
 
3484
3504
 
@@ -5728,7 +5748,7 @@ class InterpResolver:
5728
5748
  if spec.contains(si)
5729
5749
  ]
5730
5750
 
5731
- slst = sorted(lst, key=lambda t: (-t[0], t[1]))
5751
+ slst = sorted(lst, key=lambda t: (-t[0], t[1].version))
5732
5752
  if not slst:
5733
5753
  return None
5734
5754
 
omdev/tokens.py CHANGED
@@ -61,7 +61,7 @@ def join_lines(ls: ta.Iterable[Tokens]) -> str:
61
61
 
62
62
  def match_toks(
63
63
  ts: ta.Iterable['trt.Token'],
64
- pat: ta.Sequence[tuple[str | None, str | None]],
64
+ pat: ta.Sequence[tuple[str | None, str | tuple[str, ...] | None]],
65
65
  ) -> bool:
66
66
  it = iter(ts)
67
67
  for pn, ps in pat:
@@ -71,6 +71,13 @@ def match_toks(
71
71
  return False
72
72
  if pn is not None and t.name != pn:
73
73
  return False
74
- if ps is not None and t.src != ps:
75
- return False
74
+ if ps is not None:
75
+ if isinstance(ps, str):
76
+ if t.src != ps:
77
+ return False
78
+ elif isinstance(ps, tuple):
79
+ if t.src not in ps:
80
+ return False
81
+ else:
82
+ raise TypeError(ps)
76
83
  return True
omdev/tools/docker.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """
2
2
  TODO:
3
- - check for updates
3
+ - https://github.com/zeromake/docker-debug
4
4
  """
5
5
  import os
6
6
  import re
@@ -232,6 +232,19 @@ class Cli(ap.Cli):
232
232
 
233
233
  print(f'{svc_name}: {lt}')
234
234
 
235
+ @ap.command()
236
+ def dockly(self) -> None:
237
+ os.execl(
238
+ exe := docker_exe(),
239
+ exe,
240
+ 'run',
241
+ '-it',
242
+ '--rm',
243
+ '-v',
244
+ '/var/run/docker.sock:/var/run/docker.sock',
245
+ 'lirantal/dockly',
246
+ )
247
+
235
248
 
236
249
  # @omlish-manifest
237
250
  _CLI_MODULE = CliModule('docker', __name__)
omdev/tools/git.py CHANGED
@@ -1,3 +1,7 @@
1
+ """
2
+ TODO:
3
+ - https://github.com/vegardit/bash-funk/blob/main/docs/git.md
4
+ """
1
5
  import os
2
6
  import re
3
7
  import subprocess
omdev/tools/json/io.py CHANGED
@@ -53,7 +53,7 @@
53
53
  #
54
54
  #
55
55
  # @dc.dataclass(frozen=True)
56
- # class FdIo(Input, Output):
56
+ # class Fdio(Input, Output):
57
57
  # fd: int
58
58
  #
59
59
  # default_read_sz: int = DEFAULT_READ_SZ
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev144
3
+ Version: 0.0.0.dev146
4
4
  Summary: omdev
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Operating System :: POSIX
13
13
  Requires-Python: >=3.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omlish==0.0.0.dev144
15
+ Requires-Dist: omlish==0.0.0.dev146
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black~=24.10; extra == "all"
18
18
  Requires-Dist: pycparser~=2.22; extra == "all"
@@ -1,4 +1,4 @@
1
- omdev/.manifests.json,sha256=Uq3VB0ovogq663SM_1fuRBjqbod7kE30wNxBByQI2zo,8033
1
+ omdev/.manifests.json,sha256=ln-OyFCqhvwbtxlfrQk-6s4Ilao4ufYVmQJQI_4UtT8,8033
2
2
  omdev/__about__.py,sha256=n5x-SO70OgbDQFzQ1d7sZDVMsnkQc4PxQZPFaIQFa0E,1281
3
3
  omdev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  omdev/bracepy.py,sha256=I8EdqtDvxzAi3I8TuMEW-RBfwXfqKbwp06CfOdj3L1o,2743
@@ -10,11 +10,11 @@ omdev/imgur.py,sha256=il12R3t19tALolteYCZywvcdQUEOcgvPyUYgWtKiqt4,2993
10
10
  omdev/pip.py,sha256=7cZ_IOpekQvgPm_gKnX3Pr8xjqUid50PPScTlZCYVlM,2118
11
11
  omdev/revisions.py,sha256=7tRBeDECSOhYfwSxJDrMFypQjtghLu9P4P0oFT3NHdQ,5008
12
12
  omdev/secrets.py,sha256=bcquaBIDKqX4UIKOzUuKrX7nxVCenj67rRHIMIrd9bk,540
13
- omdev/tokens.py,sha256=eCppK7BtlgAK_AmfO-Or_B-x85tqmu0HVla8d2gvB3I,1333
13
+ omdev/tokens.py,sha256=zh2TCAfCbcq8ZnoVdQ824jrTiwNy3XJ_oCqlZpLpcCY,1574
14
14
  omdev/wheelfile.py,sha256=yfupGcGkbFlmzGzKU64k_vmOKpaKnUlDWxeGn2KdekU,10005
15
15
  omdev/amalg/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  omdev/amalg/__main__.py,sha256=h94M-VqZ3AFBU2a8zOsjeKK7RF6uINhTHl6OiGbVMgw,163
17
- omdev/amalg/amalg.py,sha256=AEhgXmc9y3zfvMpAdJUuTwlhYZ5bCAUrVf1WHsgV5PI,16084
17
+ omdev/amalg/amalg.py,sha256=_5goY2wRrP9X4nma3MzDHTbCj7_bkfNxi98bRbd6eSQ,19240
18
18
  omdev/antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  omdev/antlr/consts.py,sha256=8pR6r0m0P3hAiyiAoJZ-nptd2GYbZ98mxwPL9cpaRuw,279
20
20
  omdev/antlr/gen.py,sha256=QnPyVWUrJYqHoOc3XsXA8fJdoiwAj6pyUwdG-DVrIeA,2953
@@ -62,7 +62,7 @@ omdev/cli/__main__.py,sha256=mOJpgc07o0r5luQ1DlX4tk2PqZkgmbwPbdzJ3KmtjgQ,138
62
62
  omdev/cli/_pathhack.py,sha256=kxqb2kHap68Lkh8b211rDbcgj06hidBiAKA3f9posyc,2119
63
63
  omdev/cli/clicli.py,sha256=NhTYaCQx3K_Y8UOZZYqCa3lqxkCB41XgE2FpR_PT7Gc,3504
64
64
  omdev/cli/install.py,sha256=C-W171YlIHt4Cfok-nWSMbHwWhqF_PFqq2HixFttYx8,4460
65
- omdev/cli/main.py,sha256=p00ZoNIOlQW6GjyzryoIweQnC-a8tDx59S8EQYJ4uLY,7028
65
+ omdev/cli/main.py,sha256=OY7ir2WWuDUM1Urmh-WdEv7uEhidRRGnE4FNYHaEN3s,7033
66
66
  omdev/cli/managers.py,sha256=BV98_n30Jj63OJrFgRoVZRfICxMLXEZKoEn4rMj9LV4,1160
67
67
  omdev/cli/types.py,sha256=bqKw9SbtBtAip2vF9v4khh0CqKG6LBr6n9VzWBz7AJE,474
68
68
  omdev/clipboard/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -75,7 +75,7 @@ omdev/interp/cli.py,sha256=sh7PZQoLletUViw1Y9OXNr9ekyNZ6YyxYuOQ_n9hyqU,2072
75
75
  omdev/interp/inspect.py,sha256=55_il4ehoW6Q468YE57w5CyZxHLNsndkRIH4W80OplM,2848
76
76
  omdev/interp/providers.py,sha256=PFEjozW0c33eqg8sno-GHMKbhVUzQF9jrAx-M0uQimk,1787
77
77
  omdev/interp/pyenv.py,sha256=rHps4saqLxp-udbZp-5RpFxNhZNQc6plqIvaCQpNBHo,13837
78
- omdev/interp/resolvers.py,sha256=tpzlmqGp1C4QKdA6TfcPmtmaygu7mb6WK2RPSbyNQ6s,3022
78
+ omdev/interp/resolvers.py,sha256=O4QTqWGL7KXiJl3JN5BlbqT52FbhycrDSRd7M_jTeRs,3030
79
79
  omdev/interp/standalone.py,sha256=XcltiL7ypcfV89C82_3knQ3Kx7aW4wnnxf2056ZXC3A,7731
80
80
  omdev/interp/system.py,sha256=bI-JhX4GVJqW7wMxnIa-DGJWnCLmFcIsnl9pc1RGY2g,3513
81
81
  omdev/interp/types.py,sha256=EMN3StEMkFoQAMUIZd7JYL4uUWqzFGY-2hTL8EBznYM,2437
@@ -84,10 +84,8 @@ omdev/magic/find.py,sha256=tTmpWXAleaXG3_kNOsRF7s8D0CpYMXbdz6-HbCNBW90,7070
84
84
  omdev/magic/magic.py,sha256=h1nxoW6CV1MRCiHjDt3sO4kmG0qTtTRbkDNiPLGo2BE,224
85
85
  omdev/magic/prepare.py,sha256=V5jYT2AeFmazzPwk9sNismSouLwFXEoik6FwKcWCNUY,589
86
86
  omdev/magic/styles.py,sha256=YQ-HgwfvFWPj-o_705E7A-yehEn1G1hRNLPWpeWCK0U,605
87
- omdev/manifests/__init__.py,sha256=P2B0dpT8D7l5lJwRGPA92IcQj6oeXfd90X5-q9BJrKg,51
88
- omdev/manifests/build.py,sha256=E7BelbrJEJes-BEbAUZCVLVs79sYuC0fbthgXAoxaOk,10865
89
- omdev/manifests/load.py,sha256=LtEsluDdd8CkNGj0QGBxee3twBn095Fru0xz2mtr7uk,4788
90
- omdev/manifests/types.py,sha256=Jv6PAdVLPb9Hh4y6vDhPlWuMNBBViin1bC_u83jfsH4,234
87
+ omdev/manifests/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
88
+ omdev/manifests/build.py,sha256=yFrMf1HUMlLFSV-VfDg0IwbHAAoWNmM2rJj7ZaXwwro,10913
91
89
  omdev/mypy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
90
  omdev/mypy/debug.py,sha256=WcZw-3Z1njg_KFGqi3DB6RuqbBa3dLArJnjVCuY1Mn0,3003
93
91
  omdev/packaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -102,7 +100,7 @@ omdev/precheck/base.py,sha256=a_lGoFM-QhL8u8XDUYFhb-feEyfPbP4j8lcmNO51sHY,732
102
100
  omdev/precheck/git.py,sha256=APC5Ln7x0zDrQiGPRWPsBcVJK3vWhbU-brqR5M63JQA,849
103
101
  omdev/precheck/lite.py,sha256=z99pgTO4SAmLEqSj6qaKd4hcs0WpwixYkQZn75lZRX8,3883
104
102
  omdev/precheck/main.py,sha256=wryjWMXEa-9dmfdcvU_1uVwWw_GtCcoknXfUOyZvdw8,2872
105
- omdev/precheck/manifests.py,sha256=YfXqt6u0hlFXY0QkBMec6V_6Y9T4eCVAmrJDkQkB13U,774
103
+ omdev/precheck/manifests.py,sha256=JNWxY3e5uFsJJSjjOeZZJE9mEkV6o7Y4I89D-UIXWyg,780
106
104
  omdev/precheck/scripts.py,sha256=Xw9kkQzlDd_2V9av9qlaNpNZG9jZdy3TTo7x60MeR2I,1273
107
105
  omdev/ptk/__init__.py,sha256=QIu7cMeCKgNiXvIt7pXTESToJLuRMN0Qsxns_Z7ci0k,641
108
106
  omdev/ptk/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -122,8 +120,8 @@ omdev/scripts/bumpversion.py,sha256=Kn7fo73Hs8uJh3Hi3EIyLOlzLPWAC6dwuD_lZ3cIzuY,
122
120
  omdev/scripts/execrss.py,sha256=mR0G0wERBYtQmVIn63lCIIFb5zkCM6X_XOENDFYDBKc,651
123
121
  omdev/scripts/exectime.py,sha256=sFb376GflU6s9gNX-2-we8hgH6w5MuQNS9g6i4SqJIo,610
124
122
  omdev/scripts/importtrace.py,sha256=oa7CtcWJVMNDbyIEiRHej6ICfABfErMeo4_haIqe18Q,14041
125
- omdev/scripts/interp.py,sha256=Xzki1bTvF2uahDrK65_A-lbN29W67jE4t7v8SY__F44,74287
126
- omdev/scripts/pyproject.py,sha256=rxjEsErhrVmoOhX8RYZ0i77D13VKaE7uGFveu--bGtk,179110
123
+ omdev/scripts/interp.py,sha256=nda-QHD-do9MVfXrDlfqdaEXdNwacil48RHd3OG0DIw,74295
124
+ omdev/scripts/pyproject.py,sha256=SW4lGBmdgoXD_2ekbeIj-LIGMqSnQoTV36eXWuvyhik,179659
127
125
  omdev/scripts/slowcat.py,sha256=lssv4yrgJHiWfOiHkUut2p8E8Tq32zB-ujXESQxFFHY,2728
128
126
  omdev/scripts/tmpexec.py,sha256=WTYcf56Tj2qjYV14AWmV8SfT0u6Y8eIU6cKgQRvEK3c,1442
129
127
  omdev/toml/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
@@ -132,8 +130,8 @@ omdev/toml/writer.py,sha256=lk3on3YXVbWuLJa-xsOzOhs1bBAT1vXqw4mBbluZl_w,3040
132
130
  omdev/tools/__init__.py,sha256=iVJAOQ0viGTQOm0DLX4uZLro-9jOioYJGLg9s0kDx1A,78
133
131
  omdev/tools/cloc.py,sha256=13lUsYLyn1LoelhsCeKrRkIwwPE0x54JmdhXJ_lvWh0,3811
134
132
  omdev/tools/doc.py,sha256=mv9XfitzqXl3vFHSenv01xHCxWf8g03rUAb_sqoty98,2556
135
- omdev/tools/docker.py,sha256=k2BrVvFYwyGov064CPHd_HWo9aqR1zHc2UeEsVwPth4,6827
136
- omdev/tools/git.py,sha256=bfhYUFip7zVxtsyXk8yEFbK2y2zguhvgraLhXc7A53M,6899
133
+ omdev/tools/docker.py,sha256=jRmKn2fiDy6szeC3MA-mN34EuU_Pbc_jWtnPJG6LIac,7141
134
+ omdev/tools/git.py,sha256=WJ7iEsC5UkMnsCv8jN5FAcjj8cURF_nK4pcaZQjY6NY,6976
137
135
  omdev/tools/importscan.py,sha256=nhJIhtjDY6eFVlReP7fegvv6L5ZjN-Z2VeyhsBonev4,4639
138
136
  omdev/tools/mkrelimp.py,sha256=wsJAjTIf3nqcSfnT9TkDpS1VUOoM9W2Az5tZdWuzyLM,4054
139
137
  omdev/tools/notebook.py,sha256=M8Xi_gfZdlahnyFLtp0RBgYZPSHWQStMMDYZc71Zync,3494
@@ -145,16 +143,16 @@ omdev/tools/json/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
145
143
  omdev/tools/json/__main__.py,sha256=wqpkN_NsQyNwKW4qjVj8ADJ4_C98KhrFBtE-Z1UamfU,168
146
144
  omdev/tools/json/cli.py,sha256=EubIMT-n2XsjWBZjSy2fWXqijlwrIhLsfbkg3SZzi28,9586
147
145
  omdev/tools/json/formats.py,sha256=XHabWAQnAQ9uNS7fHu3mdgxoptWw00RVLq08uadD6kk,1753
148
- omdev/tools/json/io.py,sha256=IoJ5asjS_gUan5TcrGgS0KpJaiSE5YQgEGljFMCcDto,1427
146
+ omdev/tools/json/io.py,sha256=sfj2hJS9Hy3aUR8a_lLzOrYcmL9fSKyvOHiofdUASsI,1427
149
147
  omdev/tools/json/parsing.py,sha256=QLsdYv-fRFNIWwy8KLr19fQ5RodiQEX2hIw4jndnEXM,2180
150
148
  omdev/tools/json/processing.py,sha256=iFm5VqaxJ97WHaun2ed7NEjMxhFeJqf28bLNfoDJft0,1209
151
149
  omdev/tools/json/rendering.py,sha256=jNShMfCpFR9-Kcn6cUFuOChXHjg71diuTC4x7Ofmz-o,2240
152
150
  omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
151
  omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
154
152
  omdev/tools/pawk/pawk.py,sha256=Eckymn22GfychCQcQi96BFqRo_LmiJ-EPhC8TTUJdB4,11446
155
- omdev-0.0.0.dev144.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
156
- omdev-0.0.0.dev144.dist-info/METADATA,sha256=zSYVvh5IUY6zP4Wn5I2TAlHKzLDdlRGccLePdsDiY0A,1760
157
- omdev-0.0.0.dev144.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
158
- omdev-0.0.0.dev144.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
159
- omdev-0.0.0.dev144.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
160
- omdev-0.0.0.dev144.dist-info/RECORD,,
153
+ omdev-0.0.0.dev146.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
154
+ omdev-0.0.0.dev146.dist-info/METADATA,sha256=IOaFWNLrbiDx0sOwGaw5D3Ae874Vk2qCBZE_-B88Blo,1760
155
+ omdev-0.0.0.dev146.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
156
+ omdev-0.0.0.dev146.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
157
+ omdev-0.0.0.dev146.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
158
+ omdev-0.0.0.dev146.dist-info/RECORD,,
omdev/manifests/load.py DELETED
@@ -1,165 +0,0 @@
1
- """
2
- Should be kept somewhat lightweight - used in cli entrypoints.
3
-
4
- TODO:
5
- - persisted caching support - {pkg_name: manifests}
6
- """
7
- # ruff: noqa: UP006 UP007
8
- import dataclasses as dc
9
- import importlib.machinery
10
- import importlib.resources
11
- import json
12
- import typing as ta
13
-
14
- from .types import Manifest
15
-
16
-
17
- ##
18
-
19
-
20
- class ManifestLoader:
21
- def __init__(
22
- self,
23
- *,
24
- module_remap: ta.Optional[ta.Mapping[str, str]] = None,
25
- ) -> None:
26
- super().__init__()
27
-
28
- self._module_remap = module_remap or {}
29
- self._module_reverse_remap = {v: k for k, v in self._module_remap.items()}
30
-
31
- self._cls_cache: ta.Dict[str, type] = {}
32
- self._raw_cache: ta.Dict[str, ta.Optional[ta.Sequence[Manifest]]] = {}
33
-
34
- @classmethod
35
- def from_entry_point(
36
- cls,
37
- globals: ta.Mapping[str, ta.Any], # noqa
38
- *,
39
- module_remap: ta.Optional[ta.Mapping[str, str]] = None,
40
- **kwargs: ta.Any,
41
- ) -> 'ManifestLoader':
42
- rm: ta.Dict[str, str] = {}
43
-
44
- if module_remap:
45
- rm.update(module_remap)
46
-
47
- if '__name__' in globals and '__spec__' in globals:
48
- name: str = globals['__name__']
49
- spec: importlib.machinery.ModuleSpec = globals['__spec__']
50
- if '__main__' not in rm and name == '__main__':
51
- rm[spec.name] = '__main__'
52
-
53
- return cls(module_remap=rm, **kwargs)
54
-
55
- def load_cls(self, key: str) -> type:
56
- try:
57
- return self._cls_cache[key]
58
- except KeyError:
59
- pass
60
-
61
- if not key.startswith('$'):
62
- raise Exception(f'Bad key: {key}')
63
-
64
- parts = key[1:].split('.')
65
- pos = next(i for i, p in enumerate(parts) if p[0].isupper())
66
-
67
- mod_name = '.'.join(parts[:pos])
68
- mod_name = self._module_remap.get(mod_name, mod_name)
69
- mod = importlib.import_module(mod_name)
70
-
71
- obj: ta.Any = mod
72
- for ca in parts[pos:]:
73
- obj = getattr(obj, ca)
74
-
75
- cls = obj
76
- if not isinstance(cls, type):
77
- raise TypeError(cls)
78
-
79
- self._cls_cache[key] = cls
80
- return cls
81
-
82
- def load_contents(self, obj: ta.Any, pkg_name: str) -> ta.Sequence[Manifest]:
83
- if not isinstance(obj, (list, tuple)):
84
- raise TypeError(obj)
85
-
86
- lst: ta.List[Manifest] = []
87
- for e in obj:
88
- m = Manifest(**e)
89
-
90
- m = dc.replace(m, module=pkg_name + m.module)
91
-
92
- [(key, value_dct)] = m.value.items()
93
- if not key.startswith('$'):
94
- raise Exception(f'Bad key: {key}')
95
- if key.startswith('$.'):
96
- key = f'${pkg_name}{key[1:]}'
97
- m = dc.replace(m, value={key: value_dct})
98
-
99
- lst.append(m)
100
-
101
- return lst
102
-
103
- def load_raw(self, pkg_name: str) -> ta.Optional[ta.Sequence[Manifest]]:
104
- try:
105
- return self._raw_cache[pkg_name]
106
- except KeyError:
107
- pass
108
-
109
- t = importlib.resources.files(pkg_name).joinpath('.manifests.json')
110
- if not t.is_file():
111
- self._raw_cache[pkg_name] = None
112
- return None
113
-
114
- src = t.read_text('utf-8')
115
- obj = json.loads(src)
116
- if not isinstance(obj, (list, tuple)):
117
- raise TypeError(obj)
118
-
119
- lst = self.load_contents(obj, pkg_name)
120
-
121
- self._raw_cache[pkg_name] = lst
122
- return lst
123
-
124
- def load(
125
- self,
126
- *pkg_names: str,
127
- only: ta.Optional[ta.Iterable[type]] = None,
128
- ) -> ta.Sequence[Manifest]:
129
- only_keys: ta.Optional[ta.Set]
130
- if only is not None:
131
- only_keys = set()
132
- for cls in only:
133
- if not (isinstance(cls, type) and dc.is_dataclass(cls)):
134
- raise TypeError(cls)
135
- mod_name = cls.__module__
136
- mod_name = self._module_reverse_remap.get(mod_name, mod_name)
137
- only_keys.add(f'${mod_name}.{cls.__qualname__}')
138
- else:
139
- only_keys = None
140
-
141
- lst: ta.List[Manifest] = []
142
- for pn in pkg_names:
143
- for manifest in (self.load_raw(pn) or []):
144
- [(key, value_dct)] = manifest.value.items()
145
- if only_keys is not None and key not in only_keys:
146
- continue
147
-
148
- cls = self.load_cls(key)
149
- value = cls(**value_dct)
150
-
151
- manifest = dc.replace(manifest, value=value)
152
- lst.append(manifest)
153
-
154
- return lst
155
-
156
- ENTRY_POINT_GROUP = 'omlish.manifests'
157
-
158
- def discover(self) -> ta.Sequence[str]:
159
- # This is a fat dep so do it late.
160
- import importlib.metadata
161
-
162
- return [
163
- ep.value
164
- for ep in importlib.metadata.entry_points(group=self.ENTRY_POINT_GROUP)
165
- ]
omdev/manifests/types.py DELETED
@@ -1,16 +0,0 @@
1
- import dataclasses as dc
2
- import typing as ta
3
-
4
-
5
- @dc.dataclass(frozen=True)
6
- class ManifestOrigin:
7
- module: str
8
- attr: str
9
-
10
- file: str
11
- line: int
12
-
13
-
14
- @dc.dataclass(frozen=True)
15
- class Manifest(ManifestOrigin):
16
- value: ta.Any