ominfra 0.0.0.dev445__py3-none-any.whl → 0.0.0.dev483__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 ominfra might be problematic. Click here for more details.

@@ -54,6 +54,57 @@ if sys.version_info < (3, 8):
54
54
  raise OSError(f'Requires python (3, 8), got {sys.version_info} from {sys.executable}') # noqa
55
55
 
56
56
 
57
+ def __omlish_amalg__(): # noqa
58
+ return dict(
59
+ src_files=[
60
+ dict(path='../../../../omlish/configs/types.py', sha1='f7a5584cd6eccb77d18d729796072a162e9a8790'),
61
+ dict(path='../../../../omlish/formats/ini/sections.py', sha1='731c92cce82e183d1d4bdc23fc781fad62187394'),
62
+ dict(path='../../../../omlish/formats/toml/parser.py', sha1='73dac82289350ab951c4bcdbfe61167fa221f26f'),
63
+ dict(path='../../../../omlish/formats/toml/writer.py', sha1='6ea41d7e724bb1dcf6bd84b88993ff4e8798e021'),
64
+ dict(path='../../../../omlish/io/readers.py', sha1='4b19ab4a87f2fa2a6f6c3cad7e1f3892b7cbd3a4'),
65
+ dict(path='../../../../omlish/lite/abstract.py', sha1='a2fc3f3697fa8de5247761e9d554e70176f37aac'),
66
+ dict(path='../../../../omlish/lite/attrops.py', sha1='c1ebfb8573d766d34593c452a2377208d02726dc'),
67
+ dict(path='../../../../omlish/lite/cached.py', sha1='0c33cf961ac8f0727284303c7a30c5ea98f714f2'),
68
+ dict(path='../../../../omlish/lite/check.py', sha1='bb6b6b63333699b84462951a854d99ae83195b94'),
69
+ dict(path='../../../../omlish/lite/contextmanagers.py', sha1='993f5ed96d3410f739a20363f55670d5e5267fa3'),
70
+ dict(path='../../../../omlish/lite/json.py', sha1='57eeddc4d23a17931e00284ffa5cb6e3ce089486'),
71
+ dict(path='../../../../omlish/lite/objects.py', sha1='9566bbf3530fd71fcc56321485216b592fae21e9'),
72
+ dict(path='../../../../omlish/lite/reflect.py', sha1='c4fec44bf144e9d93293c996af06f6c65fc5e63d'),
73
+ dict(path='../../../../omlish/lite/strings.py', sha1='89831ecbc34ad80e118a865eceb390ed399dc4d6'),
74
+ dict(path='../../../../omlish/logs/levels.py', sha1='91405563d082a5eba874da82aac89d83ce7b6152'),
75
+ dict(path='../../../../omlish/logs/std/filters.py', sha1='f36aab646d84d31e295b33aaaaa6f8b67ff38b3d'),
76
+ dict(path='../../../../omlish/logs/std/proxy.py', sha1='3e7301a2aa351127f9c85f61b2f85dcc3f15aafb'),
77
+ dict(path='../../../../omlish/logs/warnings.py', sha1='c4eb694b24773351107fcc058f3620f1dbfb6799'),
78
+ dict(path='../../../../omlish/os/pidfiles/pidfile.py', sha1='7c3c6d4674855bfc4f1d7fd77b8fa40f36581535'),
79
+ dict(path='../../../../omlish/subprocesses/utils.py', sha1='2210d90ab1bfc75642aa2f4caad662368900aa1c'),
80
+ dict(path='../auth.py', sha1='b1ac1a5e03d4e9e38957a54e346943c6dcc964a1'),
81
+ dict(path='../dataclasses.py', sha1='8e950d7815904588fed284889392cbb0b1002605'),
82
+ dict(path='../../../../omlish/configs/formats.py', sha1='9bc4f953b4b8700f6f109e6f49e2d70f8e48ce7c'),
83
+ dict(path='../../../../omlish/io/buffers.py', sha1='45a5f79c6d71f02ab82082a48d63ebbd10959031'),
84
+ dict(path='../../../../omlish/lite/marshal.py', sha1='96348f5f2a26dc27d842d33cc3927e9da163436b'),
85
+ dict(path='../../../../omlish/lite/runtime.py', sha1='2e752a27ae2bf89b1bb79b4a2da522a3ec360c70'),
86
+ dict(path='../../../../omlish/logs/infos.py', sha1='4dd104bd468a8c438601dd0bbda619b47d2f1620'),
87
+ dict(path='../../../../omlish/logs/std/json.py', sha1='2a75553131e4d5331bb0cedde42aa183f403fc3b'),
88
+ dict(path='../logs.py', sha1='5a4fad522508bdc1b790f1d5234a87f319c9da2d'),
89
+ dict(path='../../../../omlish/lite/configs.py', sha1='c8602e0e197ef1133e7e8e248935ac745bfd46cb'),
90
+ dict(path='../../../../omlish/logs/contexts.py', sha1='7456964ade9ac66460e9ade4e242dbdc24b39501'),
91
+ dict(path='../../../../omlish/logs/standard.py', sha1='818b674f7d15012f25b79f52f6e8e7368b633038'),
92
+ dict(path='../../../../omlish/subprocesses/wrap.py', sha1='8a9b7d2255481fae15c05f5624b0cdc0766f4b3f'),
93
+ dict(path='../../../../omlish/logs/base.py', sha1='a376460b11b9dc0555fd4ead5437af62c2109a4b'),
94
+ dict(path='../../../../omlish/logs/std/records.py', sha1='8bbf6ef9eccb3a012c6ca416ddf3969450fd8fc9'),
95
+ dict(path='../../../../omlish/logs/std/loggers.py', sha1='daa35bdc4adea5006e442688017f0de3392579b7'),
96
+ dict(path='../../../../omlish/logs/modules.py', sha1='99e73cde6872fd5eda6af3dbf0fc9322bdeb641a'),
97
+ dict(path='cursor.py', sha1='00f1c62e16e4c85b20658eaf33c0bedf22c9e18f'),
98
+ dict(path='../../../journald/messages.py', sha1='6f2d2eeedb71723b1c6631ad2e634b473b297696'),
99
+ dict(path='../../../threadworkers.py', sha1='e3413436070b66faeb3e6974dc9a75cd8a949ad7'),
100
+ dict(path='poster.py', sha1='275770a4e60ea5777053c9044e37d71397c3ed20'),
101
+ dict(path='../../../journald/tailer.py', sha1='1c37a6bbde32e8556d26b94b439f14869731ac01'),
102
+ dict(path='driver.py', sha1='a9353a417fc4e57f29e7f04038c3bf4668f36dbd'),
103
+ dict(path='main.py', sha1='e051dbef37e026f887b6084cfaa811ccfa543ee7'),
104
+ ],
105
+ )
106
+
107
+
57
108
  ########################################
58
109
 
59
110
 
@@ -68,7 +119,7 @@ TomlParseFloat = ta.Callable[[str], ta.Any] # ta.TypeAlias
68
119
  TomlKey = ta.Tuple[str, ...] # ta.TypeAlias
69
120
  TomlPos = int # ta.TypeAlias
70
121
 
71
- # ../../../../omlish/lite/attrops.py
122
+ # ../../../../omlish/lite/abstract.py
72
123
  T = ta.TypeVar('T')
73
124
 
74
125
  # ../../../../omlish/lite/cached.py
@@ -1200,6 +1251,36 @@ class TomlWriter:
1200
1251
  return out.getvalue()
1201
1252
 
1202
1253
 
1254
+ ########################################
1255
+ # ../../../../../omlish/io/readers.py
1256
+
1257
+
1258
+ ##
1259
+
1260
+
1261
+ class RawBytesReader(ta.Protocol):
1262
+ def read1(self, n: int = -1, /) -> bytes: ...
1263
+
1264
+
1265
+ class BufferedBytesReader(RawBytesReader, ta.Protocol):
1266
+ def read(self, n: int = -1, /) -> bytes: ...
1267
+
1268
+ def readall(self) -> bytes: ...
1269
+
1270
+
1271
+ #
1272
+
1273
+
1274
+ class AsyncRawBytesReader(ta.Protocol):
1275
+ def read1(self, n: int = -1, /) -> ta.Awaitable[bytes]: ...
1276
+
1277
+
1278
+ class AsyncBufferedBytesReader(AsyncRawBytesReader, ta.Protocol):
1279
+ def read(self, n: int = -1, /) -> ta.Awaitable[bytes]: ...
1280
+
1281
+ def readall(self) -> ta.Awaitable[bytes]: ...
1282
+
1283
+
1203
1284
  ########################################
1204
1285
  # ../../../../../omlish/lite/abstract.py
1205
1286
 
@@ -1215,25 +1296,49 @@ def is_abstract_method(obj: ta.Any) -> bool:
1215
1296
  return bool(getattr(obj, _IS_ABSTRACT_METHOD_ATTR, False))
1216
1297
 
1217
1298
 
1218
- def update_abstracts(cls, *, force=False):
1299
+ def compute_abstract_methods(cls: type) -> ta.FrozenSet[str]:
1300
+ # ~> https://github.com/python/cpython/blob/f3476c6507381ca860eec0989f53647b13517423/Modules/_abc.c#L358
1301
+
1302
+ # Stage 1: direct abstract methods
1303
+
1304
+ abstracts = {
1305
+ a
1306
+ # Get items as a list to avoid mutation issues during iteration
1307
+ for a, v in list(cls.__dict__.items())
1308
+ if is_abstract_method(v)
1309
+ }
1310
+
1311
+ # Stage 2: inherited abstract methods
1312
+
1313
+ for base in cls.__bases__:
1314
+ # Get __abstractmethods__ from base if it exists
1315
+ if (base_abstracts := getattr(base, _ABSTRACT_METHODS_ATTR, None)) is None:
1316
+ continue
1317
+
1318
+ # Iterate over abstract methods in base
1319
+ for key in base_abstracts:
1320
+ # Check if this class has an attribute with this name
1321
+ try:
1322
+ value = getattr(cls, key)
1323
+ except AttributeError:
1324
+ # Attribute not found in this class, skip
1325
+ continue
1326
+
1327
+ # Check if it's still abstract
1328
+ if is_abstract_method(value):
1329
+ abstracts.add(key)
1330
+
1331
+ return frozenset(abstracts)
1332
+
1333
+
1334
+ def update_abstracts(cls: ta.Type[T], *, force: bool = False) -> ta.Type[T]:
1219
1335
  if not force and not hasattr(cls, _ABSTRACT_METHODS_ATTR):
1220
1336
  # Per stdlib: We check for __abstractmethods__ here because cls might by a C implementation or a python
1221
1337
  # implementation (especially during testing), and we want to handle both cases.
1222
1338
  return cls
1223
1339
 
1224
- abstracts: ta.Set[str] = set()
1225
-
1226
- for scls in cls.__bases__:
1227
- for name in getattr(scls, _ABSTRACT_METHODS_ATTR, ()):
1228
- value = getattr(cls, name, None)
1229
- if getattr(value, _IS_ABSTRACT_METHOD_ATTR, False):
1230
- abstracts.add(name)
1231
-
1232
- for name, value in cls.__dict__.items():
1233
- if getattr(value, _IS_ABSTRACT_METHOD_ATTR, False):
1234
- abstracts.add(name)
1235
-
1236
- setattr(cls, _ABSTRACT_METHODS_ATTR, frozenset(abstracts))
1340
+ abstracts = compute_abstract_methods(cls)
1341
+ setattr(cls, _ABSTRACT_METHODS_ATTR, abstracts)
1237
1342
  return cls
1238
1343
 
1239
1344
 
@@ -1287,23 +1392,26 @@ class Abstract:
1287
1392
  super().__init_subclass__(**kwargs)
1288
1393
 
1289
1394
  if not (Abstract in cls.__bases__ or abc.ABC in cls.__bases__):
1290
- ams = {a: cls for a, o in cls.__dict__.items() if is_abstract_method(o)}
1395
+ if ams := compute_abstract_methods(cls):
1396
+ amd = {
1397
+ a: mcls
1398
+ for mcls in cls.__mro__[::-1]
1399
+ for a in ams
1400
+ if a in mcls.__dict__
1401
+ }
1291
1402
 
1292
- seen = set(cls.__dict__)
1293
- for b in cls.__bases__:
1294
- ams.update({a: b for a in set(getattr(b, _ABSTRACT_METHODS_ATTR, [])) - seen}) # noqa
1295
- seen.update(dir(b))
1296
-
1297
- if ams:
1298
1403
  raise AbstractTypeError(
1299
1404
  f'Cannot subclass abstract class {cls.__name__} with abstract methods: ' +
1300
1405
  ', '.join(sorted([
1301
1406
  '.'.join([
1302
- *([m] if (m := getattr(c, '__module__')) else []),
1303
- getattr(c, '__qualname__', getattr(c, '__name__')),
1407
+ *([
1408
+ *([m] if (m := getattr(c, '__module__')) else []),
1409
+ getattr(c, '__qualname__', getattr(c, '__name__')),
1410
+ ] if c is not None else '?'),
1304
1411
  a,
1305
1412
  ])
1306
- for a, c in ams.items()
1413
+ for a in ams
1414
+ for c in [amd.get(a)]
1307
1415
  ])),
1308
1416
  )
1309
1417
 
@@ -1328,6 +1436,8 @@ TODO:
1328
1436
  - per-attr repr transform / filter
1329
1437
  - __ne__ ? cases where it still matters
1330
1438
  - ordering ?
1439
+ - repr_filter: ta.Union[ta.Callable[[ta.Any], ta.Optional[str]], ta.Literal['not_none', 'truthy']]] ?
1440
+ - unify repr/repr_fn/repr_filter
1331
1441
  """
1332
1442
 
1333
1443
 
@@ -2382,7 +2492,7 @@ class ExitStacked:
2382
2492
  es.__enter__()
2383
2493
  try:
2384
2494
  self._enter_contexts()
2385
- except Exception: # noqa
2495
+ except BaseException: # noqa
2386
2496
  es.__exit__(*sys.exc_info())
2387
2497
  raise
2388
2498
  return self
@@ -2393,7 +2503,7 @@ class ExitStacked:
2393
2503
  return None
2394
2504
  try:
2395
2505
  self._exit_contexts()
2396
- except Exception: # noqa
2506
+ except BaseException: # noqa
2397
2507
  es.__exit__(*sys.exc_info())
2398
2508
  raise
2399
2509
  return es.__exit__(exc_type, exc_val, exc_tb)
@@ -2441,7 +2551,7 @@ class AsyncExitStacked:
2441
2551
  await es.__aenter__()
2442
2552
  try:
2443
2553
  await self._async_enter_contexts()
2444
- except Exception: # noqa
2554
+ except BaseException: # noqa
2445
2555
  await es.__aexit__(*sys.exc_info())
2446
2556
  raise
2447
2557
  return self
@@ -2452,7 +2562,7 @@ class AsyncExitStacked:
2452
2562
  return None
2453
2563
  try:
2454
2564
  await self._async_exit_contexts()
2455
- except Exception: # noqa
2565
+ except BaseException: # noqa
2456
2566
  await es.__aexit__(*sys.exc_info())
2457
2567
  raise
2458
2568
  return await es.__aexit__(exc_type, exc_val, exc_tb)
@@ -3879,6 +3989,10 @@ DEFAULT_CONFIG_RENDERER = SwitchedConfigRenderer(DEFAULT_CONFIG_RENDERERS)
3879
3989
 
3880
3990
  ########################################
3881
3991
  # ../../../../../omlish/io/buffers.py
3992
+ """
3993
+ TODO:
3994
+ - overhaul and just coro-ify pyio?
3995
+ """
3882
3996
 
3883
3997
 
3884
3998
  ##
@@ -4057,6 +4171,9 @@ class ReadableListBuffer:
4057
4171
 
4058
4172
  self._lst: list[bytes] = []
4059
4173
 
4174
+ def __bool__(self) -> ta.NoReturn:
4175
+ raise TypeError("Use 'buf is not None' or 'len(buf)'.")
4176
+
4060
4177
  def __len__(self) -> int:
4061
4178
  return sum(map(len, self._lst))
4062
4179
 
@@ -4082,6 +4199,9 @@ class ReadableListBuffer:
4082
4199
 
4083
4200
  def read(self, n: ta.Optional[int] = None) -> ta.Optional[bytes]:
4084
4201
  if n is None:
4202
+ if not self._lst:
4203
+ return b''
4204
+
4085
4205
  o = b''.join(self._lst)
4086
4206
  self._lst = []
4087
4207
  return o
@@ -4120,6 +4240,110 @@ class ReadableListBuffer:
4120
4240
  r = self.read_until_(delim)
4121
4241
  return r if isinstance(r, bytes) else None
4122
4242
 
4243
+ #
4244
+
4245
+ DEFAULT_BUFFERED_READER_CHUNK_SIZE: ta.ClassVar[int] = -1
4246
+
4247
+ @ta.final
4248
+ class _BufferedBytesReader(BufferedBytesReader):
4249
+ def __init__(
4250
+ self,
4251
+ raw: RawBytesReader,
4252
+ buf: 'ReadableListBuffer',
4253
+ *,
4254
+ chunk_size: ta.Optional[int] = None,
4255
+ ) -> None:
4256
+ self._raw = raw
4257
+ self._buf = buf
4258
+ self._chunk_size = chunk_size or ReadableListBuffer.DEFAULT_BUFFERED_READER_CHUNK_SIZE
4259
+
4260
+ def read1(self, n: int = -1, /) -> bytes:
4261
+ if n < 0:
4262
+ n = self._chunk_size
4263
+ if not n:
4264
+ return b''
4265
+ if 0 < n <= len(self._buf):
4266
+ return self._buf.read(n) or b''
4267
+ return self._raw.read1(n)
4268
+
4269
+ def read(self, /, n: int = -1) -> bytes:
4270
+ if n < 0:
4271
+ return self.readall()
4272
+ while len(self._buf) < n:
4273
+ if not (b := self._raw.read1(n)):
4274
+ break
4275
+ self._buf.feed(b)
4276
+ return self._buf.read(n) or b''
4277
+
4278
+ def readall(self) -> bytes:
4279
+ buf = io.BytesIO()
4280
+ buf.write(self._buf.read() or b'')
4281
+ while (b := self._raw.read1(self._chunk_size)):
4282
+ buf.write(b)
4283
+ return buf.getvalue()
4284
+
4285
+ def new_buffered_reader(
4286
+ self,
4287
+ raw: RawBytesReader,
4288
+ *,
4289
+ chunk_size: ta.Optional[int] = None,
4290
+ ) -> BufferedBytesReader:
4291
+ return self._BufferedBytesReader(
4292
+ raw,
4293
+ self,
4294
+ chunk_size=chunk_size,
4295
+ )
4296
+
4297
+ @ta.final
4298
+ class _AsyncBufferedBytesReader(AsyncBufferedBytesReader):
4299
+ def __init__(
4300
+ self,
4301
+ raw: AsyncRawBytesReader,
4302
+ buf: 'ReadableListBuffer',
4303
+ *,
4304
+ chunk_size: ta.Optional[int] = None,
4305
+ ) -> None:
4306
+ self._raw = raw
4307
+ self._buf = buf
4308
+ self._chunk_size = chunk_size or ReadableListBuffer.DEFAULT_BUFFERED_READER_CHUNK_SIZE
4309
+
4310
+ async def read1(self, n: int = -1, /) -> bytes:
4311
+ if n < 0:
4312
+ n = self._chunk_size
4313
+ if not n:
4314
+ return b''
4315
+ if 0 < n <= len(self._buf):
4316
+ return self._buf.read(n) or b''
4317
+ return await self._raw.read1(n)
4318
+
4319
+ async def read(self, /, n: int = -1) -> bytes:
4320
+ if n < 0:
4321
+ return await self.readall()
4322
+ while len(self._buf) < n:
4323
+ if not (b := await self._raw.read1(n)):
4324
+ break
4325
+ self._buf.feed(b)
4326
+ return self._buf.read(n) or b''
4327
+
4328
+ async def readall(self) -> bytes:
4329
+ buf = io.BytesIO()
4330
+ buf.write(self._buf.read() or b'')
4331
+ while b := await self._raw.read1(self._chunk_size):
4332
+ buf.write(b)
4333
+ return buf.getvalue()
4334
+
4335
+ def new_async_buffered_reader(
4336
+ self,
4337
+ raw: AsyncRawBytesReader,
4338
+ *,
4339
+ chunk_size: ta.Optional[int] = None,
4340
+ ) -> AsyncBufferedBytesReader:
4341
+ return self._AsyncBufferedBytesReader(
4342
+ raw,
4343
+ self,
4344
+ chunk_size=chunk_size,
4345
+ )
4346
+
4123
4347
 
4124
4348
  ##
4125
4349