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
omdev/pyproject/reqs.py CHANGED
@@ -53,13 +53,14 @@ class RequirementsRewriter:
53
53
  if self.VENV_MAGIC in l:
54
54
  lp, _, rp = l.partition(self.VENV_MAGIC)
55
55
  rp = rp.partition('#')[0]
56
- for v in rp.split():
57
- if v[0] == '!':
58
- if self._venv is not None and self._venv == v[1:]:
59
- omit = True
60
- break
61
- else:
62
- raise NotImplementedError
56
+ vs = set(rp.split())
57
+ nvs = {v[1:] for v in vs if v.startswith('!')}
58
+ pvs = {v for v in vs if not v.startswith('!')}
59
+ if (
60
+ (nvs and self._venv in nvs) or
61
+ (pvs and self._venv not in pvs)
62
+ ):
63
+ omit = True
63
64
 
64
65
  if (
65
66
  not omit and
@@ -38,11 +38,16 @@ def _main() -> None:
38
38
  pkg_opt_deps = {d for ds in pkg_prj.optional_dependencies.values() for d in ds}
39
39
  for opt_dep in sorted(pkg_opt_deps):
40
40
  opt_req = parse_requirement(opt_dep)
41
+
41
42
  opt_cn = canonicalize_name(opt_req.name, validate=True)
43
+
42
44
  opt_spec = Specifier(opt_req.specifier)
43
45
  if re.fullmatch(r'~=\s*\d+(\.\d+)*', str(opt_spec)):
44
46
  opt_spec = Specifier(str(opt_spec) + '.0')
45
47
 
48
+ if opt_cn in pkgs:
49
+ continue
50
+
46
51
  opt_dist = dist_dct[opt_cn]
47
52
  opt_ver = opt_dist.version
48
53
 
omdev/scripts/ci.py CHANGED
@@ -97,6 +97,7 @@ def __omlish_amalg__(): # noqa
97
97
  dict(path='../../omlish/http/urllib.py', sha1='25431c5bdc7dd5cbecfcb8c0bdffaabf8c1691b9'),
98
98
  dict(path='../../omlish/http/versions.py', sha1='197685ffbb62a457a0e8d4047a9df26aebd7dae4'),
99
99
  dict(path='../../omlish/lite/abstract.py', sha1='a2fc3f3697fa8de5247761e9d554e70176f37aac'),
100
+ dict(path='../../omlish/lite/asyncs.py', sha1='b3f2251c56617ce548abf9c333ac996b63edb23e'),
100
101
  dict(path='../../omlish/lite/cached.py', sha1='0c33cf961ac8f0727284303c7a30c5ea98f714f2'),
101
102
  dict(path='../../omlish/lite/check.py', sha1='bb6b6b63333699b84462951a854d99ae83195b94'),
102
103
  dict(path='../../omlish/lite/contextmanagers.py', sha1='993f5ed96d3410f739a20363f55670d5e5267fa3'),
@@ -142,9 +143,9 @@ def __omlish_amalg__(): # noqa
142
143
  dict(path='../../omlish/asyncs/asyncio/timeouts.py', sha1='4d31b02b3c39b8f2fa7e94db36552fde6942e36a'),
143
144
  dict(path='../../omlish/http/handlers.py', sha1='40629060bac22ea5e94b720b57001861a4ec9031'),
144
145
  dict(path='../../omlish/lite/inject.py', sha1='6f097e3170019a34ff6834d36fcc9cbeed3a7ab4'),
145
- dict(path='../../omlish/logs/contexts.py', sha1='7456964ade9ac66460e9ade4e242dbdc24b39501'),
146
- dict(path='../../omlish/logs/standard.py', sha1='818b674f7d15012f25b79f52f6e8e7368b633038'),
147
- dict(path='../../omlish/logs/utils.py', sha1='8430cddbb7de34afb2793ab8a0cc6fbee47fef2c'),
146
+ dict(path='../../omlish/logs/contexts.py', sha1='1000a6d5ddfb642865ca532e34b1d50759781cf0'),
147
+ dict(path='../../omlish/logs/std/standard.py', sha1='5c97c1b9f7ead58d6127d047b873398f708f288d'),
148
+ dict(path='../../omlish/logs/utils.py', sha1='39599f5e9d9911a06eac6e0d7e5116fdc69b1263'),
148
149
  dict(path='../../omlish/sockets/server/handlers.py', sha1='6f9adca9fa04774a28a488a4e2a11bb4492c71d0'),
149
150
  dict(path='../../omlish/subprocesses/run.py', sha1='8200e48f0c49d164df3503cd0143038d0c4d30aa'),
150
151
  dict(path='../../omlish/subprocesses/wrap.py', sha1='8a9b7d2255481fae15c05f5624b0cdc0766f4b3f'),
@@ -153,7 +154,7 @@ def __omlish_amalg__(): # noqa
153
154
  dict(path='../oci/media.py', sha1='a20324c5b0661c9a9a7679406d019ab3ba4acd98'),
154
155
  dict(path='../oci/pack/packing.py', sha1='7585c3dea6b8a62b6ca63fe78968497db915ea57'),
155
156
  dict(path='../../omlish/http/coro/server/server.py', sha1='c0a980afa8346dbc20570acddb2b3b579bfc1ce0'),
156
- dict(path='../../omlish/logs/base.py', sha1='a376460b11b9dc0555fd4ead5437af62c2109a4b'),
157
+ dict(path='../../omlish/logs/base.py', sha1='8d06faee05fead6b1dd98c9035a5b042af4aebb1'),
157
158
  dict(path='../../omlish/logs/std/records.py', sha1='8bbf6ef9eccb3a012c6ca416ddf3969450fd8fc9'),
158
159
  dict(path='../../omlish/secrets/tempssl.py', sha1='360d4cd98483357bcf013e156dafd92fd37ed220'),
159
160
  dict(path='../../omlish/sockets/server/server.py', sha1='a93a74f6beb38d69e0fb9047c932f2a95aa37eca'),
@@ -165,7 +166,8 @@ def __omlish_amalg__(): # noqa
165
166
  dict(path='../oci/building.py', sha1='b4fea06c03ba02d3ecfc6d10d955dc76f263846a'),
166
167
  dict(path='../oci/loading.py', sha1='64d806ffad8d24087ccc29f759f672e6d795bee2'),
167
168
  dict(path='../../omlish/http/coro/server/sockets.py', sha1='40ef4aa43f94f1a1a2a431a012cb961f25905ff4'),
168
- dict(path='../../omlish/logs/std/loggers.py', sha1='daa35bdc4adea5006e442688017f0de3392579b7'),
169
+ dict(path='../../omlish/logs/asyncs.py', sha1='ab11b70033d9f2e9a4e70254185aa1c6130c6077'),
170
+ dict(path='../../omlish/logs/std/loggers.py', sha1='a569179445d6a8a942b5dcfad1d1f77702868803'),
169
171
  dict(path='../../omlish/subprocesses/asyncs.py', sha1='bba44d524c24c6ac73168aee6343488414e5bf48'),
170
172
  dict(path='../../omlish/subprocesses/sync.py', sha1='8434919eba4da67825773d56918fdc0cb2f1883b'),
171
173
  dict(path='requirements.py', sha1='c370a65958a00412e00608a0e1f12795e276aee1'),
@@ -173,7 +175,7 @@ def __omlish_amalg__(): # noqa
173
175
  dict(path='../oci/dataserver.py', sha1='dd147b56282b054cef264556a0ff3b3d1719bcee'),
174
176
  dict(path='../../omlish/asyncs/asyncio/subprocesses.py', sha1='b6b5f9ae3fd0b9c83593bad2e04a08f726e5904d'),
175
177
  dict(path='../../omlish/http/coro/server/simple.py', sha1='2332079fe29993123c68d7dbc266b47cd44cd6a6'),
176
- dict(path='../../omlish/logs/modules.py', sha1='99e73cde6872fd5eda6af3dbf0fc9322bdeb641a'),
178
+ dict(path='../../omlish/logs/modules.py', sha1='dd7d5f8e63fe8829dfb49460f3929ab64b68ee14'),
177
179
  dict(path='cache.py', sha1='9353e5c3b73bed47258680fd15ac49417113f0ca'),
178
180
  dict(path='compose.py', sha1='d2bec1385701979c7ff9913456b72d8c7b31f70b'),
179
181
  dict(path='docker/cmds.py', sha1='5528c384f68f9003732bfaf6be302e84747909dd'),
@@ -195,7 +197,7 @@ def __omlish_amalg__(): # noqa
195
197
  dict(path='github/cli.py', sha1='6d14b0eb4ca5f606ad2821b63b9707ce57f50406'),
196
198
  dict(path='github/inject.py', sha1='99c0dd7c55767e7c49f70b7edac25da67f718b2e'),
197
199
  dict(path='inject.py', sha1='e86b16d79a113a4f387e68ed0db1d067bcada93a'),
198
- dict(path='cli.py', sha1='49bcd482bd814ba436237099b4bdb62f77d6c054'),
200
+ dict(path='cli.py', sha1='92948cf3ec76fd9ceb25762aadbf497354adce6d'),
199
201
  ],
200
202
  )
201
203
 
@@ -759,6 +761,150 @@ class Abstract:
759
761
  update_abstracts(cls, force=True)
760
762
 
761
763
 
764
+ ########################################
765
+ # ../../../omlish/lite/asyncs.py
766
+
767
+
768
+ ##
769
+
770
+
771
+ async def opt_await(aw: ta.Optional[ta.Awaitable[T]]) -> ta.Optional[T]:
772
+ return (await aw if aw is not None else None)
773
+
774
+
775
+ async def async_list(ai: ta.AsyncIterable[T]) -> ta.List[T]:
776
+ return [v async for v in ai]
777
+
778
+
779
+ async def async_enumerate(ai: ta.AsyncIterable[T]) -> ta.AsyncIterable[ta.Tuple[int, T]]:
780
+ i = 0
781
+ async for e in ai:
782
+ yield (i, e)
783
+ i += 1
784
+
785
+
786
+ ##
787
+
788
+
789
+ def as_async(fn: ta.Callable[..., T], *, wrap: bool = False) -> ta.Callable[..., ta.Awaitable[T]]:
790
+ async def inner(*args, **kwargs):
791
+ return fn(*args, **kwargs)
792
+
793
+ return functools.wraps(fn)(inner) if wrap else inner
794
+
795
+
796
+ ##
797
+
798
+
799
+ class SyncAwaitCoroutineNotTerminatedError(Exception):
800
+ pass
801
+
802
+
803
+ def sync_await(aw: ta.Awaitable[T]) -> T:
804
+ """
805
+ Allows for the synchronous execution of async functions which will never actually *externally* await anything. These
806
+ functions are allowed to await any number of other functions - including contextmanagers and generators - so long as
807
+ nothing ever actually 'leaks' out of the function, presumably to an event loop.
808
+ """
809
+
810
+ ret = missing = object()
811
+
812
+ async def thunk():
813
+ nonlocal ret
814
+
815
+ ret = await aw
816
+
817
+ cr = thunk()
818
+ try:
819
+ try:
820
+ cr.send(None)
821
+ except StopIteration:
822
+ pass
823
+
824
+ if ret is missing or cr.cr_await is not None or cr.cr_running:
825
+ raise SyncAwaitCoroutineNotTerminatedError('Not terminated')
826
+
827
+ finally:
828
+ cr.close()
829
+
830
+ return ta.cast(T, ret)
831
+
832
+
833
+ #
834
+
835
+
836
+ def sync_aiter(ai: ta.AsyncIterator[T]) -> ta.Iterator[T]:
837
+ while True:
838
+ try:
839
+ o = sync_await(ai.__anext__())
840
+ except StopAsyncIteration:
841
+ break
842
+ yield o
843
+
844
+
845
+ def sync_async_list(ai: ta.AsyncIterable[T]) -> ta.List[T]:
846
+ """
847
+ Uses `sync_await` to synchronously read the full contents of a function call returning an async iterator, given that
848
+ the function never externally awaits anything.
849
+ """
850
+
851
+ lst: ta.Optional[ta.List[T]] = None
852
+
853
+ async def inner():
854
+ nonlocal lst
855
+
856
+ lst = [v async for v in ai]
857
+
858
+ sync_await(inner())
859
+
860
+ if not isinstance(lst, list):
861
+ raise TypeError(lst)
862
+
863
+ return lst
864
+
865
+
866
+ #
867
+
868
+
869
+ @ta.final
870
+ class SyncAwaitContextManager(ta.Generic[T]):
871
+ def __init__(self, acm: ta.AsyncContextManager[T]) -> None:
872
+ self._acm = acm
873
+
874
+ def __repr__(self) -> str:
875
+ return f'{self.__class__.__name__}({self._acm!r})'
876
+
877
+ def __enter__(self) -> T:
878
+ return sync_await(self._acm.__aenter__())
879
+
880
+ def __exit__(self, exc_type, exc_val, exc_tb):
881
+ return sync_await(self._acm.__aexit__(exc_type, exc_val, exc_tb))
882
+
883
+
884
+ sync_async_with = SyncAwaitContextManager
885
+
886
+
887
+ ##
888
+
889
+
890
+ @ta.final
891
+ class SyncToAsyncContextManager(ta.Generic[T]):
892
+ def __init__(self, cm: ta.ContextManager[T]) -> None:
893
+ self._cm = cm
894
+
895
+ def __repr__(self) -> str:
896
+ return f'{self.__class__.__name__}({self._cm!r})'
897
+
898
+ async def __aenter__(self) -> T:
899
+ return self._cm.__enter__()
900
+
901
+ async def __aexit__(self, exc_type, exc_value, traceback, /):
902
+ return self._cm.__exit__(exc_type, exc_value, traceback)
903
+
904
+
905
+ as_async_context_manager = SyncToAsyncContextManager
906
+
907
+
762
908
  ########################################
763
909
  # ../../../omlish/lite/cached.py
764
910
 
@@ -8081,6 +8227,9 @@ class CaptureLoggingContextImpl(CaptureLoggingContext):
8081
8227
  self._infos[type(info)] = info
8082
8228
  return self
8083
8229
 
8230
+ def get_infos(self) -> ta.Mapping[ta.Type[LoggingContextInfo], LoggingContextInfo]:
8231
+ return self._infos
8232
+
8084
8233
  def get_info(self, ty: ta.Type[LoggingContextInfoT]) -> ta.Optional[LoggingContextInfoT]:
8085
8234
  return self._infos.get(ty)
8086
8235
 
@@ -8103,7 +8252,7 @@ class CaptureLoggingContextImpl(CaptureLoggingContext):
8103
8252
  _stack_offset: int
8104
8253
  _stack_info: bool
8105
8254
 
8106
- def inc_stack_offset(self, ofs: int = 1) -> 'CaptureLoggingContext':
8255
+ def inc_stack_offset(self, ofs: int = 1) -> 'CaptureLoggingContextImpl':
8107
8256
  if hasattr(self, '_stack_offset'):
8108
8257
  self._stack_offset += ofs
8109
8258
  return self
@@ -8135,10 +8284,9 @@ class CaptureLoggingContextImpl(CaptureLoggingContext):
8135
8284
 
8136
8285
 
8137
8286
  ########################################
8138
- # ../../../omlish/logs/standard.py
8287
+ # ../../../omlish/logs/std/standard.py
8139
8288
  """
8140
8289
  TODO:
8141
- - !! move to std !!
8142
8290
  - structured
8143
8291
  - prefixed
8144
8292
  - debug
@@ -8274,7 +8422,7 @@ def exception_logging(log): # noqa
8274
8422
  def inner(*args, **kwargs):
8275
8423
  try:
8276
8424
  return fn(*args, **kwargs)
8277
- except Exception:
8425
+ except Exception as e: # noqa
8278
8426
  log.exception('Error in %r', fn)
8279
8427
  raise
8280
8428
 
@@ -8283,6 +8431,21 @@ def exception_logging(log): # noqa
8283
8431
  return outer
8284
8432
 
8285
8433
 
8434
+ def async_exception_logging(alog): # noqa
8435
+ def outer(fn):
8436
+ @functools.wraps(fn)
8437
+ async def inner(*args, **kwargs):
8438
+ try:
8439
+ return await fn(*args, **kwargs)
8440
+ except Exception as e: # noqa
8441
+ await alog.exception('Error in %r', fn)
8442
+ raise
8443
+
8444
+ return inner
8445
+
8446
+ return outer
8447
+
8448
+
8286
8449
  ##
8287
8450
 
8288
8451
 
@@ -9799,6 +9962,11 @@ class AnyLogger(Abstract, ta.Generic[T]):
9799
9962
 
9800
9963
  ##
9801
9964
 
9965
+ # This will be 1 for [Sync]Logger and 0 for AsyncLogger - in sync loggers these methods remain present on the stack,
9966
+ # in async loggers they return a coroutine to be awaited and thus aren't actually present when said coroutine is
9967
+ # awaited.
9968
+ _level_proxy_method_stack_offset: int
9969
+
9802
9970
  @ta.overload
9803
9971
  def log(self, level: LogLevel, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T:
9804
9972
  ...
@@ -9813,7 +9981,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
9813
9981
 
9814
9982
  @ta.final
9815
9983
  def log(self, level: LogLevel, *args, **kwargs):
9816
- return self._log(CaptureLoggingContextImpl(level, stack_offset=1), *args, **kwargs)
9984
+ return self._log(
9985
+ CaptureLoggingContextImpl(
9986
+ level,
9987
+ stack_offset=self._level_proxy_method_stack_offset,
9988
+ ),
9989
+ *args,
9990
+ **kwargs,
9991
+ )
9817
9992
 
9818
9993
  #
9819
9994
 
@@ -9831,7 +10006,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
9831
10006
 
9832
10007
  @ta.final
9833
10008
  def debug(self, *args, **kwargs):
9834
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.DEBUG, stack_offset=1), *args, **kwargs)
10009
+ return self._log(
10010
+ CaptureLoggingContextImpl(
10011
+ NamedLogLevel.DEBUG,
10012
+ stack_offset=self._level_proxy_method_stack_offset,
10013
+ ),
10014
+ *args,
10015
+ **kwargs,
10016
+ )
9835
10017
 
9836
10018
  #
9837
10019
 
@@ -9849,7 +10031,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
9849
10031
 
9850
10032
  @ta.final
9851
10033
  def info(self, *args, **kwargs):
9852
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.INFO, stack_offset=1), *args, **kwargs)
10034
+ return self._log(
10035
+ CaptureLoggingContextImpl(
10036
+ NamedLogLevel.INFO,
10037
+ stack_offset=self._level_proxy_method_stack_offset,
10038
+ ),
10039
+ *args,
10040
+ **kwargs,
10041
+ )
9853
10042
 
9854
10043
  #
9855
10044
 
@@ -9867,7 +10056,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
9867
10056
 
9868
10057
  @ta.final
9869
10058
  def warning(self, *args, **kwargs):
9870
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.WARNING, stack_offset=1), *args, **kwargs)
10059
+ return self._log(
10060
+ CaptureLoggingContextImpl(
10061
+ NamedLogLevel.WARNING,
10062
+ stack_offset=self._level_proxy_method_stack_offset,
10063
+ ),
10064
+ *args,
10065
+ **kwargs,
10066
+ )
9871
10067
 
9872
10068
  #
9873
10069
 
@@ -9885,7 +10081,14 @@ class AnyLogger(Abstract, ta.Generic[T]):
9885
10081
 
9886
10082
  @ta.final
9887
10083
  def error(self, *args, **kwargs):
9888
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.ERROR, stack_offset=1), *args, **kwargs)
10084
+ return self._log(
10085
+ CaptureLoggingContextImpl(
10086
+ NamedLogLevel.ERROR,
10087
+ stack_offset=self._level_proxy_method_stack_offset,
10088
+ ),
10089
+ *args,
10090
+ **kwargs,
10091
+ )
9889
10092
 
9890
10093
  #
9891
10094
 
@@ -9903,7 +10106,15 @@ class AnyLogger(Abstract, ta.Generic[T]):
9903
10106
 
9904
10107
  @ta.final
9905
10108
  def exception(self, *args, exc_info: LoggingExcInfoArg = True, **kwargs):
9906
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.ERROR, exc_info=exc_info, stack_offset=1), *args, **kwargs) # noqa
10109
+ return self._log(
10110
+ CaptureLoggingContextImpl(
10111
+ NamedLogLevel.ERROR,
10112
+ exc_info=exc_info,
10113
+ stack_offset=self._level_proxy_method_stack_offset,
10114
+ ),
10115
+ *args,
10116
+ **kwargs,
10117
+ )
9907
10118
 
9908
10119
  #
9909
10120
 
@@ -9921,24 +10132,53 @@ class AnyLogger(Abstract, ta.Generic[T]):
9921
10132
 
9922
10133
  @ta.final
9923
10134
  def critical(self, *args, **kwargs):
9924
- return self._log(CaptureLoggingContextImpl(NamedLogLevel.CRITICAL, stack_offset=1), *args, **kwargs)
10135
+ return self._log(
10136
+ CaptureLoggingContextImpl(
10137
+ NamedLogLevel.CRITICAL,
10138
+ stack_offset=self._level_proxy_method_stack_offset,
10139
+ ),
10140
+ *args,
10141
+ **kwargs,
10142
+ )
9925
10143
 
9926
10144
  ##
9927
10145
 
9928
10146
  @abc.abstractmethod
9929
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> T: # noqa
10147
+ def _log(
10148
+ self,
10149
+ ctx: CaptureLoggingContext,
10150
+ msg: ta.Union[str, tuple, LoggingMsgFn],
10151
+ *args: ta.Any,
10152
+ **kwargs: ta.Any,
10153
+ ) -> T:
9930
10154
  raise NotImplementedError
9931
10155
 
9932
10156
 
9933
10157
  class Logger(AnyLogger[None], Abstract):
10158
+ _level_proxy_method_stack_offset: int = 1
10159
+
9934
10160
  @abc.abstractmethod
9935
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> None: # noqa
10161
+ def _log(
10162
+ self,
10163
+ ctx: CaptureLoggingContext,
10164
+ msg: ta.Union[str, tuple, LoggingMsgFn],
10165
+ *args: ta.Any,
10166
+ **kwargs: ta.Any,
10167
+ ) -> None:
9936
10168
  raise NotImplementedError
9937
10169
 
9938
10170
 
9939
10171
  class AsyncLogger(AnyLogger[ta.Awaitable[None]], Abstract):
10172
+ _level_proxy_method_stack_offset: int = 0
10173
+
9940
10174
  @abc.abstractmethod
9941
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> ta.Awaitable[None]: # noqa
10175
+ def _log(
10176
+ self,
10177
+ ctx: CaptureLoggingContext,
10178
+ msg: ta.Union[str, tuple, LoggingMsgFn],
10179
+ *args: ta.Any,
10180
+ **kwargs: ta.Any,
10181
+ ) -> ta.Awaitable[None]:
9942
10182
  raise NotImplementedError
9943
10183
 
9944
10184
 
@@ -9953,13 +10193,25 @@ class AnyNopLogger(AnyLogger[T], Abstract):
9953
10193
 
9954
10194
  @ta.final
9955
10195
  class NopLogger(AnyNopLogger[None], Logger):
9956
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> None: # noqa
10196
+ def _log(
10197
+ self,
10198
+ ctx: CaptureLoggingContext,
10199
+ msg: ta.Union[str, tuple, LoggingMsgFn],
10200
+ *args: ta.Any,
10201
+ **kwargs: ta.Any,
10202
+ ) -> None:
9957
10203
  pass
9958
10204
 
9959
10205
 
9960
10206
  @ta.final
9961
10207
  class AsyncNopLogger(AnyNopLogger[ta.Awaitable[None]], AsyncLogger):
9962
- async def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> None: # noqa
10208
+ async def _log(
10209
+ self,
10210
+ ctx: CaptureLoggingContext,
10211
+ msg: ta.Union[str, tuple, LoggingMsgFn],
10212
+ *args: ta.Any,
10213
+ **kwargs: ta.Any,
10214
+ ) -> None:
9963
10215
  pass
9964
10216
 
9965
10217
 
@@ -11818,6 +12070,70 @@ class CoroHttpServerSocketHandler(SocketHandler_):
11818
12070
  return check.isinstance(e.value, CoroHttpServer.CoroHandleResult)
11819
12071
 
11820
12072
 
12073
+ ########################################
12074
+ # ../../../omlish/logs/asyncs.py
12075
+
12076
+
12077
+ ##
12078
+
12079
+
12080
+ class AsyncLoggerToLogger(Logger):
12081
+ def __init__(self, u: AsyncLogger) -> None:
12082
+ super().__init__()
12083
+
12084
+ self._u = u
12085
+
12086
+ def get_effective_level(self) -> LogLevel:
12087
+ return self._u.get_effective_level()
12088
+
12089
+ def _log(
12090
+ self,
12091
+ ctx: CaptureLoggingContext,
12092
+ msg: ta.Union[str, tuple, LoggingMsgFn],
12093
+ *args: ta.Any,
12094
+ **kwargs: ta.Any,
12095
+ ) -> None:
12096
+ # Nope out early to avoid sync_await if possible - don't bother in the LoggerToAsyncLogger.
12097
+ if not self.is_enabled_for(ctx.must_get_info(LoggingContextInfos.Level).level):
12098
+ return
12099
+
12100
+ # Note: we hardcode the stack offset of sync_await (which is 2 - sync_await + sync_await.thunk). In non-lite
12101
+ # code, lang.sync_await uses a cext if present to avoid being on the py stack, which would obviously complicate
12102
+ # this, but this is lite code so we will always have the non-c version.
12103
+ sync_await(
12104
+ self._u._log( # noqa
12105
+ check.isinstance(ctx, CaptureLoggingContextImpl).inc_stack_offset(3),
12106
+ msg,
12107
+ *args,
12108
+ **kwargs,
12109
+ ),
12110
+ )
12111
+
12112
+
12113
+ class LoggerToAsyncLogger(AsyncLogger):
12114
+ def __init__(self, u: Logger) -> None:
12115
+ super().__init__()
12116
+
12117
+ self._u = u
12118
+
12119
+ def get_effective_level(self) -> LogLevel:
12120
+ return self._u.get_effective_level()
12121
+
12122
+ async def _log(
12123
+ self,
12124
+ ctx: CaptureLoggingContext,
12125
+ msg: ta.Union[str, tuple, LoggingMsgFn],
12126
+ *args: ta.Any,
12127
+ **kwargs: ta.Any,
12128
+ ) -> None:
12129
+ return self._u._log( # noqa
12130
+ check.isinstance(ctx, CaptureLoggingContextImpl).inc_stack_offset(),
12131
+ msg,
12132
+ *args,
12133
+ **kwargs,
12134
+ )
12135
+
12136
+
11821
12137
  ########################################
11822
12138
  # ../../../omlish/logs/std/loggers.py
11823
12139
 
@@ -11841,7 +12157,12 @@ class StdLogger(Logger):
11841
12157
  def get_effective_level(self) -> LogLevel:
11842
12158
  return self._std.getEffectiveLevel()
11843
12159
 
11844
- def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any) -> None:
12160
+ def _log(
12161
+ self,
12162
+ ctx: CaptureLoggingContext,
12163
+ msg: ta.Union[str, tuple, LoggingMsgFn],
12164
+ *args: ta.Any,
12165
+ ) -> None:
11845
12166
  if not self.is_enabled_for(ctx.must_get_info(LoggingContextInfos.Level).level):
11846
12167
  return
11847
12168
 
@@ -12592,8 +12913,23 @@ def make_simple_http_server(
12592
12913
  ##
12593
12914
 
12594
12915
 
12916
+ def _get_module_std_logger(mod_globals: ta.Mapping[str, ta.Any]) -> logging.Logger:
12917
+ return logging.getLogger(mod_globals.get('__name__'))
12918
+
12919
+
12595
12920
  def get_module_logger(mod_globals: ta.Mapping[str, ta.Any]) -> Logger:
12596
- return StdLogger(logging.getLogger(mod_globals.get('__name__'))) # noqa
12921
+ return StdLogger(_get_module_std_logger(mod_globals))
12922
+
12923
+
12924
+ def get_module_async_logger(mod_globals: ta.Mapping[str, ta.Any]) -> AsyncLogger:
12925
+ return LoggerToAsyncLogger(get_module_logger(mod_globals))
12926
+
12927
+
12928
+ def get_module_loggers(mod_globals: ta.Mapping[str, ta.Any]) -> ta.Tuple[Logger, AsyncLogger]:
12929
+ return (
12930
+ log := get_module_logger(mod_globals),
12931
+ LoggerToAsyncLogger(log),
12932
+ )
12597
12933
 
12598
12934
 
12599
12935
  ########################################