omdev 0.0.0.dev486__py3-none-any.whl → 0.0.0.dev500__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.

Files changed (43) hide show
  1. omdev/.omlish-manifests.json +1 -1
  2. omdev/README.md +51 -0
  3. omdev/__about__.py +4 -2
  4. omdev/ci/cli.py +1 -1
  5. omdev/cli/clicli.py +37 -7
  6. omdev/dataclasses/cli.py +1 -1
  7. omdev/interp/cli.py +1 -1
  8. omdev/interp/types.py +3 -2
  9. omdev/interp/uv/provider.py +36 -0
  10. omdev/manifests/main.py +1 -1
  11. omdev/packaging/revisions.py +1 -1
  12. omdev/py/tools/pipdepup.py +150 -93
  13. omdev/pyproject/cli.py +1 -1
  14. omdev/pyproject/pkg.py +1 -1
  15. omdev/pyproject/reqs.py +8 -7
  16. omdev/pyproject/tools/aboutdeps.py +5 -0
  17. omdev/scripts/ci.py +361 -25
  18. omdev/scripts/interp.py +43 -8
  19. omdev/scripts/lib/logs.py +117 -21
  20. omdev/scripts/pyproject.py +415 -39
  21. omdev/tools/git/cli.py +43 -13
  22. omdev/tools/json/formats.py +2 -0
  23. omdev/tools/jsonview/cli.py +19 -61
  24. omdev/tools/jsonview/resources/jsonview.html.j2 +43 -0
  25. omdev/tools/pawk/README.md +195 -0
  26. omdev/tui/apps/edit/main.py +5 -1
  27. omdev/tui/apps/irc/app.py +28 -20
  28. omdev/tui/apps/irc/commands.py +1 -1
  29. omdev/tui/rich/__init__.py +12 -0
  30. omdev/tui/textual/__init__.py +41 -2
  31. omdev/tui/textual/app2.py +6 -1
  32. omdev/tui/textual/debug/__init__.py +10 -0
  33. omdev/tui/textual/debug/dominfo.py +151 -0
  34. omdev/tui/textual/debug/screen.py +24 -0
  35. omdev/tui/textual/devtools.py +187 -0
  36. omdev/tui/textual/logging2.py +20 -0
  37. omdev/tui/textual/types.py +45 -0
  38. {omdev-0.0.0.dev486.dist-info → omdev-0.0.0.dev500.dist-info}/METADATA +10 -6
  39. {omdev-0.0.0.dev486.dist-info → omdev-0.0.0.dev500.dist-info}/RECORD +43 -34
  40. {omdev-0.0.0.dev486.dist-info → omdev-0.0.0.dev500.dist-info}/WHEEL +0 -0
  41. {omdev-0.0.0.dev486.dist-info → omdev-0.0.0.dev500.dist-info}/entry_points.txt +0 -0
  42. {omdev-0.0.0.dev486.dist-info → omdev-0.0.0.dev500.dist-info}/licenses/LICENSE +0 -0
  43. {omdev-0.0.0.dev486.dist-info → omdev-0.0.0.dev500.dist-info}/top_level.txt +0 -0
@@ -94,13 +94,14 @@ def __omlish_amalg__(): # noqa
94
94
  dict(path='../../omlish/formats/toml/parser.py', sha1='73dac82289350ab951c4bcdbfe61167fa221f26f'),
95
95
  dict(path='../../omlish/formats/toml/writer.py', sha1='6ea41d7e724bb1dcf6bd84b88993ff4e8798e021'),
96
96
  dict(path='../../omlish/lite/abstract.py', sha1='a2fc3f3697fa8de5247761e9d554e70176f37aac'),
97
+ dict(path='../../omlish/lite/asyncs.py', sha1='b3f2251c56617ce548abf9c333ac996b63edb23e'),
97
98
  dict(path='../../omlish/lite/cached.py', sha1='0c33cf961ac8f0727284303c7a30c5ea98f714f2'),
98
99
  dict(path='../../omlish/lite/check.py', sha1='bb6b6b63333699b84462951a854d99ae83195b94'),
99
100
  dict(path='../../omlish/lite/json.py', sha1='57eeddc4d23a17931e00284ffa5cb6e3ce089486'),
100
101
  dict(path='../../omlish/lite/objects.py', sha1='9566bbf3530fd71fcc56321485216b592fae21e9'),
101
102
  dict(path='../../omlish/lite/reflect.py', sha1='c4fec44bf144e9d93293c996af06f6c65fc5e63d'),
102
103
  dict(path='../../omlish/lite/strings.py', sha1='89831ecbc34ad80e118a865eceb390ed399dc4d6'),
103
- dict(path='../../omlish/lite/typing.py', sha1='deaaa560b63d9a0e40991ec0006451f5f0df04c1'),
104
+ dict(path='../../omlish/lite/typing.py', sha1='c501ff8f9ed08202e8016eaa098526d4deede834'),
104
105
  dict(path='../../omlish/logs/levels.py', sha1='91405563d082a5eba874da82aac89d83ce7b6152'),
105
106
  dict(path='../../omlish/logs/std/filters.py', sha1='f36aab646d84d31e295b33aaaaa6f8b67ff38b3d'),
106
107
  dict(path='../../omlish/logs/std/proxy.py', sha1='3e7301a2aa351127f9c85f61b2f85dcc3f15aafb'),
@@ -116,35 +117,36 @@ def __omlish_amalg__(): # noqa
116
117
  dict(path='../../omlish/logs/infos.py', sha1='4dd104bd468a8c438601dd0bbda619b47d2f1620'),
117
118
  dict(path='../../omlish/logs/protocols.py', sha1='05ca4d1d7feb50c4e3b9f22ee371aa7bf4b3dbd1'),
118
119
  dict(path='../../omlish/logs/std/json.py', sha1='2a75553131e4d5331bb0cedde42aa183f403fc3b'),
119
- dict(path='../interp/types.py', sha1='cfc14929777fb19f723c875bcafc8f7c66593d6d'),
120
+ dict(path='../interp/types.py', sha1='caf068a6e81fb6e221d777b341ac5777d92b8091'),
120
121
  dict(path='../packaging/requires.py', sha1='5818353abd45135e0e638e28fa6247b24122231b'),
121
122
  dict(path='../../omlish/asyncs/asyncio/timeouts.py', sha1='4d31b02b3c39b8f2fa7e94db36552fde6942e36a'),
122
123
  dict(path='../../omlish/lite/inject.py', sha1='6f097e3170019a34ff6834d36fcc9cbeed3a7ab4'),
123
- dict(path='../../omlish/logs/contexts.py', sha1='7456964ade9ac66460e9ade4e242dbdc24b39501'),
124
- dict(path='../../omlish/logs/standard.py', sha1='818b674f7d15012f25b79f52f6e8e7368b633038'),
124
+ dict(path='../../omlish/logs/contexts.py', sha1='1000a6d5ddfb642865ca532e34b1d50759781cf0'),
125
+ dict(path='../../omlish/logs/std/standard.py', sha1='5c97c1b9f7ead58d6127d047b873398f708f288d'),
125
126
  dict(path='../../omlish/subprocesses/run.py', sha1='8200e48f0c49d164df3503cd0143038d0c4d30aa'),
126
127
  dict(path='../../omlish/subprocesses/wrap.py', sha1='8a9b7d2255481fae15c05f5624b0cdc0766f4b3f'),
127
128
  dict(path='../interp/providers/base.py', sha1='f5d068c21f230d742e9015b033cd6320f4c68898'),
128
- dict(path='../../omlish/logs/base.py', sha1='a376460b11b9dc0555fd4ead5437af62c2109a4b'),
129
+ dict(path='../../omlish/logs/base.py', sha1='8d06faee05fead6b1dd98c9035a5b042af4aebb1'),
129
130
  dict(path='../../omlish/logs/std/records.py', sha1='8bbf6ef9eccb3a012c6ca416ddf3969450fd8fc9'),
130
131
  dict(path='../../omlish/subprocesses/base.py', sha1='cb9f668be5422fecb27222caabb67daac6c1bab9'),
131
132
  dict(path='../interp/resolvers.py', sha1='817b8e76401cd7a19eb43ca54d65272e4c8a4b0e'),
132
- dict(path='../../omlish/logs/std/loggers.py', sha1='daa35bdc4adea5006e442688017f0de3392579b7'),
133
+ dict(path='../../omlish/logs/asyncs.py', sha1='ab11b70033d9f2e9a4e70254185aa1c6130c6077'),
134
+ dict(path='../../omlish/logs/std/loggers.py', sha1='a569179445d6a8a942b5dcfad1d1f77702868803'),
133
135
  dict(path='../../omlish/subprocesses/asyncs.py', sha1='bba44d524c24c6ac73168aee6343488414e5bf48'),
134
136
  dict(path='../../omlish/subprocesses/sync.py', sha1='8434919eba4da67825773d56918fdc0cb2f1883b'),
135
137
  dict(path='../git/revisions.py', sha1='a26b5afa568313e034b6b2d3a5d2dd0b065979d4'),
136
138
  dict(path='../../omlish/asyncs/asyncio/subprocesses.py', sha1='b6b5f9ae3fd0b9c83593bad2e04a08f726e5904d'),
137
- dict(path='../../omlish/logs/modules.py', sha1='99e73cde6872fd5eda6af3dbf0fc9322bdeb641a'),
139
+ dict(path='../../omlish/logs/modules.py', sha1='dd7d5f8e63fe8829dfb49460f3929ab64b68ee14'),
138
140
  dict(path='../interp/inspect.py', sha1='736287b4ec8d14a8c30afa0ba23996fdc0662caa'),
139
141
  dict(path='../interp/pyenv/pyenv.py', sha1='d1f6e657c671c1b1a5b0e627284df656fe2d10d3'),
140
142
  dict(path='../interp/uv/uv.py', sha1='8c6515cd6755efab3972da92a285e94ccb255515'),
141
- dict(path='../packaging/revisions.py', sha1='4ea4ac3006ae5b0bdc0c5a6c587cfed8fbad87b3'),
142
- dict(path='reqs.py', sha1='822e265b0d2e6d9548ee24d3ac60c81066e40ee8'),
143
+ dict(path='../packaging/revisions.py', sha1='9ba90e4a93b1bfcc93f6ca65dbaaf38f79929677'),
144
+ dict(path='reqs.py', sha1='65ac743653c455a5015a1a0ce2317ee5372a0c7c'),
143
145
  dict(path='../interp/providers/running.py', sha1='85c9cc69ff6fbd6c8cf78ed6262619a30856c2f1'),
144
146
  dict(path='../interp/providers/system.py', sha1='9638a154475ca98775159d27739563ac7fb2eb16'),
145
147
  dict(path='../interp/pyenv/install.py', sha1='4a10a19717364b4ba9f3b8bf1d12621cf21ba8b8'),
146
- dict(path='../interp/uv/provider.py', sha1='997dc9453589a4cee0658d2fa0893c4ec60b5a0d'),
147
- dict(path='pkg.py', sha1='a7b64fcf267ba385442393b90c9711af08ba9ac3'),
148
+ dict(path='../interp/uv/provider.py', sha1='3c3980878ad2b9fd2cd02172f9424954759c7f06'),
149
+ dict(path='pkg.py', sha1='e2acb40b17d75b6deb78056e6726d114a7aef2e4'),
148
150
  dict(path='../interp/providers/inject.py', sha1='7cc9ebf58cf2ec09545321456bd9da9f9a3a79fb'),
149
151
  dict(path='../interp/pyenv/provider.py', sha1='377542ce01a35849e2a5b4a4dbafedc26882f983'),
150
152
  dict(path='../interp/uv/inject.py', sha1='e95d058c2340baa5a3155ec3440f311d1daa10a8'),
@@ -154,7 +156,7 @@ def __omlish_amalg__(): # noqa
154
156
  dict(path='../interp/venvs.py', sha1='9ba8f2c3131d7d519d5cf36ca69b75f9c6fe2b27'),
155
157
  dict(path='configs.py', sha1='7b1c1ed034ecb728d67ff15e3bb2b21a218773c9'),
156
158
  dict(path='venvs.py', sha1='9f1935171017aeb802da56e14d7f41d632a7aa25'),
157
- dict(path='cli.py', sha1='e2f06505bb59793af3a2779bfa2c15aefb308539'),
159
+ dict(path='cli.py', sha1='77efd5e792baa941a79adef6b363751dbd6a0d3e'),
158
160
  ],
159
161
  )
160
162
 
@@ -2179,6 +2181,150 @@ class Abstract:
2179
2181
  update_abstracts(cls, force=True)
2180
2182
 
2181
2183
 
2184
+ ########################################
2185
+ # ../../../omlish/lite/asyncs.py
2186
+
2187
+
2188
+ ##
2189
+
2190
+
2191
+ async def opt_await(aw: ta.Optional[ta.Awaitable[T]]) -> ta.Optional[T]:
2192
+ return (await aw if aw is not None else None)
2193
+
2194
+
2195
+ async def async_list(ai: ta.AsyncIterable[T]) -> ta.List[T]:
2196
+ return [v async for v in ai]
2197
+
2198
+
2199
+ async def async_enumerate(ai: ta.AsyncIterable[T]) -> ta.AsyncIterable[ta.Tuple[int, T]]:
2200
+ i = 0
2201
+ async for e in ai:
2202
+ yield (i, e)
2203
+ i += 1
2204
+
2205
+
2206
+ ##
2207
+
2208
+
2209
+ def as_async(fn: ta.Callable[..., T], *, wrap: bool = False) -> ta.Callable[..., ta.Awaitable[T]]:
2210
+ async def inner(*args, **kwargs):
2211
+ return fn(*args, **kwargs)
2212
+
2213
+ return functools.wraps(fn)(inner) if wrap else inner
2214
+
2215
+
2216
+ ##
2217
+
2218
+
2219
+ class SyncAwaitCoroutineNotTerminatedError(Exception):
2220
+ pass
2221
+
2222
+
2223
+ def sync_await(aw: ta.Awaitable[T]) -> T:
2224
+ """
2225
+ Allows for the synchronous execution of async functions which will never actually *externally* await anything. These
2226
+ functions are allowed to await any number of other functions - including contextmanagers and generators - so long as
2227
+ nothing ever actually 'leaks' out of the function, presumably to an event loop.
2228
+ """
2229
+
2230
+ ret = missing = object()
2231
+
2232
+ async def thunk():
2233
+ nonlocal ret
2234
+
2235
+ ret = await aw
2236
+
2237
+ cr = thunk()
2238
+ try:
2239
+ try:
2240
+ cr.send(None)
2241
+ except StopIteration:
2242
+ pass
2243
+
2244
+ if ret is missing or cr.cr_await is not None or cr.cr_running:
2245
+ raise SyncAwaitCoroutineNotTerminatedError('Not terminated')
2246
+
2247
+ finally:
2248
+ cr.close()
2249
+
2250
+ return ta.cast(T, ret)
2251
+
2252
+
2253
+ #
2254
+
2255
+
2256
+ def sync_aiter(ai: ta.AsyncIterator[T]) -> ta.Iterator[T]:
2257
+ while True:
2258
+ try:
2259
+ o = sync_await(ai.__anext__())
2260
+ except StopAsyncIteration:
2261
+ break
2262
+ yield o
2263
+
2264
+
2265
+ def sync_async_list(ai: ta.AsyncIterable[T]) -> ta.List[T]:
2266
+ """
2267
+ Uses `sync_await` to synchronously read the full contents of a function call returning an async iterator, given that
2268
+ the function never externally awaits anything.
2269
+ """
2270
+
2271
+ lst: ta.Optional[ta.List[T]] = None
2272
+
2273
+ async def inner():
2274
+ nonlocal lst
2275
+
2276
+ lst = [v async for v in ai]
2277
+
2278
+ sync_await(inner())
2279
+
2280
+ if not isinstance(lst, list):
2281
+ raise TypeError(lst)
2282
+
2283
+ return lst
2284
+
2285
+
2286
+ #
2287
+
2288
+
2289
+ @ta.final
2290
+ class SyncAwaitContextManager(ta.Generic[T]):
2291
+ def __init__(self, acm: ta.AsyncContextManager[T]) -> None:
2292
+ self._acm = acm
2293
+
2294
+ def __repr__(self) -> str:
2295
+ return f'{self.__class__.__name__}({self._acm!r})'
2296
+
2297
+ def __enter__(self) -> T:
2298
+ return sync_await(self._acm.__aenter__())
2299
+
2300
+ def __exit__(self, exc_type, exc_val, exc_tb):
2301
+ return sync_await(self._acm.__aexit__(exc_type, exc_val, exc_tb))
2302
+
2303
+
2304
+ sync_async_with = SyncAwaitContextManager
2305
+
2306
+
2307
+ ##
2308
+
2309
+
2310
+ @ta.final
2311
+ class SyncToAsyncContextManager(ta.Generic[T]):
2312
+ def __init__(self, cm: ta.ContextManager[T]) -> None:
2313
+ self._cm = cm
2314
+
2315
+ def __repr__(self) -> str:
2316
+ return f'{self.__class__.__name__}({self._cm!r})'
2317
+
2318
+ async def __aenter__(self) -> T:
2319
+ return self._cm.__enter__()
2320
+
2321
+ async def __aexit__(self, exc_type, exc_value, traceback, /):
2322
+ return self._cm.__exit__(exc_type, exc_value, traceback)
2323
+
2324
+
2325
+ as_async_context_manager = SyncToAsyncContextManager
2326
+
2327
+
2182
2328
  ########################################
2183
2329
  # ../../../omlish/lite/cached.py
2184
2330
 
@@ -3131,6 +3277,24 @@ class Func3(ta.Generic[A0, A1, A2, T]):
3131
3277
  ##
3132
3278
 
3133
3279
 
3280
+ @dc.dataclass(frozen=True)
3281
+ class CachedFunc0(ta.Generic[T]):
3282
+ fn: ta.Callable[[], T]
3283
+
3284
+ def __call__(self) -> T:
3285
+ try:
3286
+ return object.__getattribute__(self, '_value')
3287
+ except AttributeError:
3288
+ pass
3289
+
3290
+ value = self.fn()
3291
+ object.__setattr__(self, '_value', value)
3292
+ return value
3293
+
3294
+
3295
+ ##
3296
+
3297
+
3134
3298
  _TYPING_ANNOTATIONS_ATTR = '__annotate__' if sys.version_info >= (3, 14) else '__annotations__'
3135
3299
 
3136
3300
 
@@ -6166,9 +6330,10 @@ class InterpSpecifier:
6166
6330
  def parse(cls, s: str) -> 'InterpSpecifier':
6167
6331
  s, o = InterpOpts.parse_suffix(s)
6168
6332
  if not any(s.startswith(o) for o in Specifier.OPERATORS):
6169
- s = '~=' + s
6170
6333
  if s.count('.') < 2:
6171
- s += '.0'
6334
+ s = '~=' + s + '.0'
6335
+ else:
6336
+ s = '==' + s
6172
6337
  return cls(
6173
6338
  specifier=Specifier(s),
6174
6339
  opts=o,
@@ -7879,6 +8044,9 @@ class CaptureLoggingContextImpl(CaptureLoggingContext):
7879
8044
  self._infos[type(info)] = info
7880
8045
  return self
7881
8046
 
8047
+ def get_infos(self) -> ta.Mapping[ta.Type[LoggingContextInfo], LoggingContextInfo]:
8048
+ return self._infos
8049
+
7882
8050
  def get_info(self, ty: ta.Type[LoggingContextInfoT]) -> ta.Optional[LoggingContextInfoT]:
7883
8051
  return self._infos.get(ty)
7884
8052
 
@@ -7901,7 +8069,7 @@ class CaptureLoggingContextImpl(CaptureLoggingContext):
7901
8069
  _stack_offset: int
7902
8070
  _stack_info: bool
7903
8071
 
7904
- def inc_stack_offset(self, ofs: int = 1) -> 'CaptureLoggingContext':
8072
+ def inc_stack_offset(self, ofs: int = 1) -> 'CaptureLoggingContextImpl':
7905
8073
  if hasattr(self, '_stack_offset'):
7906
8074
  self._stack_offset += ofs
7907
8075
  return self
@@ -7933,10 +8101,9 @@ class CaptureLoggingContextImpl(CaptureLoggingContext):
7933
8101
 
7934
8102
 
7935
8103
  ########################################
7936
- # ../../../omlish/logs/standard.py
8104
+ # ../../../omlish/logs/std/standard.py
7937
8105
  """
7938
8106
  TODO:
7939
- - !! move to std !!
7940
8107
  - structured
7941
8108
  - prefixed
7942
8109
  - debug
@@ -8306,6 +8473,11 @@ class AnyLogger(Abstract, ta.Generic[T]):
8306
8473
 
8307
8474
  ##
8308
8475
 
8476
+ # This will be 1 for [Sync]Logger and 0 for AsyncLogger - in sync loggers these methods remain present on the stack,
8477
+ # in async loggers they return a coroutine to be awaited and thus aren't actually present when said coroutine is
8478
+ # awaited.
8479
+ _level_proxy_method_stack_offset: int
8480
+
8309
8481
  @ta.overload
8310
8482
  def log(self, level: LogLevel, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T:
8311
8483
  ...
@@ -8320,7 +8492,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
8320
8492
 
8321
8493
  @ta.final
8322
8494
  def log(self, level: LogLevel, *args, **kwargs):
8323
- return self._log(CaptureLoggingContextImpl(level, stack_offset=1), *args, **kwargs)
8495
+ return self._log(
8496
+ CaptureLoggingContextImpl(
8497
+ level,
8498
+ stack_offset=self._level_proxy_method_stack_offset,
8499
+ ),
8500
+ *args,
8501
+ **kwargs,
8502
+ )
8324
8503
 
8325
8504
  #
8326
8505
 
@@ -8338,7 +8517,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
8338
8517
 
8339
8518
  @ta.final
8340
8519
  def debug(self, *args, **kwargs):
8341
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.DEBUG, stack_offset=1), *args, **kwargs)
8520
+ return self._log(
8521
+ CaptureLoggingContextImpl(
8522
+ NamedLogLevel.DEBUG,
8523
+ stack_offset=self._level_proxy_method_stack_offset,
8524
+ ),
8525
+ *args,
8526
+ **kwargs,
8527
+ )
8342
8528
 
8343
8529
  #
8344
8530
 
@@ -8356,7 +8542,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
8356
8542
 
8357
8543
  @ta.final
8358
8544
  def info(self, *args, **kwargs):
8359
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.INFO, stack_offset=1), *args, **kwargs)
8545
+ return self._log(
8546
+ CaptureLoggingContextImpl(
8547
+ NamedLogLevel.INFO,
8548
+ stack_offset=self._level_proxy_method_stack_offset,
8549
+ ),
8550
+ *args,
8551
+ **kwargs,
8552
+ )
8360
8553
 
8361
8554
  #
8362
8555
 
@@ -8374,7 +8567,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
8374
8567
 
8375
8568
  @ta.final
8376
8569
  def warning(self, *args, **kwargs):
8377
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.WARNING, stack_offset=1), *args, **kwargs)
8570
+ return self._log(
8571
+ CaptureLoggingContextImpl(
8572
+ NamedLogLevel.WARNING,
8573
+ stack_offset=self._level_proxy_method_stack_offset,
8574
+ ),
8575
+ *args,
8576
+ **kwargs,
8577
+ )
8378
8578
 
8379
8579
  #
8380
8580
 
@@ -8392,7 +8592,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
8392
8592
 
8393
8593
  @ta.final
8394
8594
  def error(self, *args, **kwargs):
8395
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.ERROR, stack_offset=1), *args, **kwargs)
8595
+ return self._log(
8596
+ CaptureLoggingContextImpl(
8597
+ NamedLogLevel.ERROR,
8598
+ stack_offset=self._level_proxy_method_stack_offset,
8599
+ ),
8600
+ *args,
8601
+ **kwargs,
8602
+ )
8396
8603
 
8397
8604
  #
8398
8605
 
@@ -8410,7 +8617,15 @@ class AnyLogger(Abstract, ta.Generic[T]):
8410
8617
 
8411
8618
  @ta.final
8412
8619
  def exception(self, *args, exc_info: LoggingExcInfoArg = True, **kwargs):
8413
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.ERROR, exc_info=exc_info, stack_offset=1), *args, **kwargs) # noqa
8620
+ return self._log(
8621
+ CaptureLoggingContextImpl(
8622
+ NamedLogLevel.ERROR,
8623
+ exc_info=exc_info,
8624
+ stack_offset=self._level_proxy_method_stack_offset,
8625
+ ),
8626
+ *args,
8627
+ **kwargs,
8628
+ )
8414
8629
 
8415
8630
  #
8416
8631
 
@@ -8428,24 +8643,53 @@ class AnyLogger(Abstract, ta.Generic[T]):
8428
8643
 
8429
8644
  @ta.final
8430
8645
  def critical(self, *args, **kwargs):
8431
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.CRITICAL, stack_offset=1), *args, **kwargs)
8646
+ return self._log(
8647
+ CaptureLoggingContextImpl(
8648
+ NamedLogLevel.CRITICAL,
8649
+ stack_offset=self._level_proxy_method_stack_offset,
8650
+ ),
8651
+ *args,
8652
+ **kwargs,
8653
+ )
8432
8654
 
8433
8655
  ##
8434
8656
 
8435
8657
  @abc.abstractmethod
8436
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> T: # noqa
8658
+ def _log(
8659
+ self,
8660
+ ctx: CaptureLoggingContext,
8661
+ msg: ta.Union[str, tuple, LoggingMsgFn],
8662
+ *args: ta.Any,
8663
+ **kwargs: ta.Any,
8664
+ ) -> T:
8437
8665
  raise NotImplementedError
8438
8666
 
8439
8667
 
8440
8668
  class Logger(AnyLogger[None], Abstract):
8669
+ _level_proxy_method_stack_offset: int = 1
8670
+
8441
8671
  @abc.abstractmethod
8442
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> None: # noqa
8672
+ def _log(
8673
+ self,
8674
+ ctx: CaptureLoggingContext,
8675
+ msg: ta.Union[str, tuple, LoggingMsgFn],
8676
+ *args: ta.Any,
8677
+ **kwargs: ta.Any,
8678
+ ) -> None:
8443
8679
  raise NotImplementedError
8444
8680
 
8445
8681
 
8446
8682
  class AsyncLogger(AnyLogger[ta.Awaitable[None]], Abstract):
8683
+ _level_proxy_method_stack_offset: int = 0
8684
+
8447
8685
  @abc.abstractmethod
8448
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> ta.Awaitable[None]: # noqa
8686
+ def _log(
8687
+ self,
8688
+ ctx: CaptureLoggingContext,
8689
+ msg: ta.Union[str, tuple, LoggingMsgFn],
8690
+ *args: ta.Any,
8691
+ **kwargs: ta.Any,
8692
+ ) -> ta.Awaitable[None]:
8449
8693
  raise NotImplementedError
8450
8694
 
8451
8695
 
@@ -8460,13 +8704,25 @@ class AnyNopLogger(AnyLogger[T], Abstract):
8460
8704
 
8461
8705
  @ta.final
8462
8706
  class NopLogger(AnyNopLogger[None], Logger):
8463
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> None: # noqa
8707
+ def _log(
8708
+ self,
8709
+ ctx: CaptureLoggingContext,
8710
+ msg: ta.Union[str, tuple, LoggingMsgFn],
8711
+ *args: ta.Any,
8712
+ **kwargs: ta.Any,
8713
+ ) -> None:
8464
8714
  pass
8465
8715
 
8466
8716
 
8467
8717
  @ta.final
8468
8718
  class AsyncNopLogger(AnyNopLogger[ta.Awaitable[None]], AsyncLogger):
8469
- async def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> None: # noqa
8719
+ async def _log(
8720
+ self,
8721
+ ctx: CaptureLoggingContext,
8722
+ msg: ta.Union[str, tuple, LoggingMsgFn],
8723
+ *args: ta.Any,
8724
+ **kwargs: ta.Any,
8725
+ ) -> None:
8470
8726
  pass
8471
8727
 
8472
8728
 
@@ -9432,6 +9688,70 @@ class InterpResolver:
9432
9688
  print(f' {si}')
9433
9689
 
9434
9690
 
9691
+ ########################################
9692
+ # ../../../omlish/logs/asyncs.py
9693
+
9694
+
9695
+ ##
9696
+
9697
+
9698
+ class AsyncLoggerToLogger(Logger):
9699
+ def __init__(self, u: AsyncLogger) -> None:
9700
+ super().__init__()
9701
+
9702
+ self._u = u
9703
+
9704
+ def get_effective_level(self) -> LogLevel:
9705
+ return self._u.get_effective_level()
9706
+
9707
+ def _log(
9708
+ self,
9709
+ ctx: CaptureLoggingContext,
9710
+ msg: ta.Union[str, tuple, LoggingMsgFn],
9711
+ *args: ta.Any,
9712
+ **kwargs: ta.Any,
9713
+ ) -> None:
9714
+ # Nope out early to avoid sync_await if possible - don't bother in the LoggerToAsyncLogger.
9715
+ if not self.is_enabled_for(ctx.must_get_info(LoggingContextInfos.Level).level):
9716
+ return
9717
+
9718
+ # Note: we hardcode the stack offset of sync_await (which is 2 - sync_await + sync_await.thunk). In non-lite
9719
+ # code, lang.sync_await uses a cext if present to avoid being on the py stack, which would obviously complicate
9720
+ # this, but this is lite code so we will always have the non-c version.
9721
+ sync_await(
9722
+ self._u._log( # noqa
9723
+ check.isinstance(ctx, CaptureLoggingContextImpl).inc_stack_offset(3),
9724
+ msg,
9725
+ *args,
9726
+ **kwargs,
9727
+ ),
9728
+ )
9729
+
9730
+
9731
+ class LoggerToAsyncLogger(AsyncLogger):
9732
+ def __init__(self, u: Logger) -> None:
9733
+ super().__init__()
9734
+
9735
+ self._u = u
9736
+
9737
+ def get_effective_level(self) -> LogLevel:
9738
+ return self._u.get_effective_level()
9739
+
9740
+ async def _log(
9741
+ self,
9742
+ ctx: CaptureLoggingContext,
9743
+ msg: ta.Union[str, tuple, LoggingMsgFn],
9744
+ *args: ta.Any,
9745
+ **kwargs: ta.Any,
9746
+ ) -> None:
9747
+ return self._u._log( # noqa
9748
+ check.isinstance(ctx, CaptureLoggingContextImpl).inc_stack_offset(),
9749
+ msg,
9750
+ *args,
9751
+ **kwargs,
9752
+ )
9753
+
9754
+
9435
9755
  ########################################
9436
9756
  # ../../../omlish/logs/std/loggers.py
9437
9757
 
@@ -9455,7 +9775,12 @@ class StdLogger(Logger):
9455
9775
  def get_effective_level(self) -> LogLevel:
9456
9776
  return self._std.getEffectiveLevel()
9457
9777
 
9458
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any) -> None:
9778
+ def _log(
9779
+ self,
9780
+ ctx: CaptureLoggingContext,
9781
+ msg: ta.Union[str, tuple, LoggingMsgFn],
9782
+ *args: ta.Any,
9783
+ ) -> None:
9459
9784
  if not self.is_enabled_for(ctx.must_get_info(LoggingContextInfos.Level).level):
9460
9785
  return
9461
9786
 
@@ -9974,8 +10299,23 @@ asyncio_subprocesses = AsyncioSubprocesses()
9974
10299
  ##
9975
10300
 
9976
10301
 
10302
+ def _get_module_std_logger(mod_globals: ta.Mapping[str, ta.Any]) -> logging.Logger:
10303
+ return logging.getLogger(mod_globals.get('__name__'))
10304
+
10305
+
9977
10306
  def get_module_logger(mod_globals: ta.Mapping[str, ta.Any]) -> Logger:
9978
- return StdLogger(logging.getLogger(mod_globals.get('__name__'))) # noqa
10307
+ return StdLogger(_get_module_std_logger(mod_globals))
10308
+
10309
+
10310
+ def get_module_async_logger(mod_globals: ta.Mapping[str, ta.Any]) -> AsyncLogger:
10311
+ return LoggerToAsyncLogger(get_module_logger(mod_globals))
10312
+
10313
+
10314
+ def get_module_loggers(mod_globals: ta.Mapping[str, ta.Any]) -> ta.Tuple[Logger, AsyncLogger]:
10315
+ return (
10316
+ log := get_module_logger(mod_globals),
10317
+ LoggerToAsyncLogger(log),
10318
+ )
9979
10319
 
9980
10320
 
9981
10321
  ########################################
@@ -10395,13 +10735,14 @@ class RequirementsRewriter:
10395
10735
  if self.VENV_MAGIC in l:
10396
10736
  lp, _, rp = l.partition(self.VENV_MAGIC)
10397
10737
  rp = rp.partition('#')[0]
10398
- for v in rp.split():
10399
- if v[0] == '!':
10400
- if self._venv is not None and self._venv == v[1:]:
10401
- omit = True
10402
- break
10403
- else:
10404
- raise NotImplementedError
10738
+ vs = set(rp.split())
10739
+ nvs = {v[1:] for v in vs if v.startswith('!')}
10740
+ pvs = {v for v in vs if not v.startswith('!')}
10741
+ if (
10742
+ (nvs and self._venv in nvs) or
10743
+ (pvs and self._venv not in pvs)
10744
+ ):
10745
+ omit = True
10405
10746
 
10406
10747
  if (
10407
10748
  not omit and
@@ -10872,12 +11213,41 @@ uv run --python 3.11.6 pip
10872
11213
  uv venv --python 3.11.6 --seed barf
10873
11214
  python3 -m venv barf && barf/bin/pip install uv && barf/bin/uv venv --python 3.11.6 --seed barf2
10874
11215
  uv python find '3.13.10'
11216
+ uv python list --output-format=json
10875
11217
  """
10876
11218
 
10877
11219
 
10878
11220
  ##
10879
11221
 
10880
11222
 
11223
+ @dc.dataclass(frozen=True)
11224
+ class UvPythonListOutput:
11225
+ key: str
11226
+ version: str
11227
+
11228
+ @dc.dataclass(frozen=True)
11229
+ class VersionParts:
11230
+ major: int
11231
+ minor: int
11232
+ patch: int
11233
+
11234
+ version_parts: VersionParts
11235
+
11236
+ path: ta.Optional[str]
11237
+ symlink: ta.Optional[str]
11238
+
11239
+ url: str
11240
+
11241
+ os: str # emscripten linux macos
11242
+ variant: str # default freethreaded
11243
+ implementation: str # cpython graalpy pyodide pypy
11244
+ arch: str # aarch64 wasm32 x86_64
11245
+ libc: str # gnu musl none
11246
+
11247
+
11248
+ ##
11249
+
11250
+
10881
11251
  class UvInterpProvider(InterpProvider):
10882
11252
  def __init__(
10883
11253
  self,
@@ -10898,6 +11268,12 @@ class UvInterpProvider(InterpProvider):
10898
11268
  async def get_installed_version(self, version: InterpVersion) -> Interp:
10899
11269
  raise NotImplementedError
10900
11270
 
11271
+ # async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
11272
+ # return []
11273
+
11274
+ # async def install_version(self, version: InterpVersion) -> Interp:
11275
+ # raise TypeError
11276
+
10901
11277
 
10902
11278
  ########################################
10903
11279
  # ../pkg.py
@@ -11468,7 +11844,7 @@ class _PyprojectRsPackageGenerator(_PyprojectExtensionPackageGenerator):
11468
11844
  # `sdist.add_defaults` as an unbound function, not a bound method:
11469
11845
  # https://github.com/pypa/setuptools/blob/9c4d383631d3951fcae0afd73b5d08ff5a262976/setuptools/command/egg_info.py#L581
11470
11846
  from setuptools.command.sdist import sdist # noqa
11471
- sdist.add_defaults = (lambda old: lambda sdist: _sdist_add_defaults(old, sdist))(sdist.add_defaults) # noqa
11847
+ setattr(sdist, 'add_defaults', (lambda old: lambda sdist: _sdist_add_defaults(old, sdist))(sdist.add_defaults)) # noqa
11472
11848
 
11473
11849
  _patch_sdist()
11474
11850