omlish 0.0.0.dev132__py3-none-any.whl → 0.0.0.dev177__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (210) hide show
  1. omlish/.manifests.json +265 -7
  2. omlish/__about__.py +7 -5
  3. omlish/antlr/_runtime/__init__.py +0 -22
  4. omlish/antlr/_runtime/_all.py +24 -0
  5. omlish/antlr/_runtime/atn/ParserATNSimulator.py +1 -1
  6. omlish/antlr/_runtime/dfa/DFASerializer.py +1 -1
  7. omlish/antlr/_runtime/error/DiagnosticErrorListener.py +2 -1
  8. omlish/antlr/_runtime/xpath/XPath.py +7 -1
  9. omlish/antlr/_runtime/xpath/XPathLexer.py +1 -1
  10. omlish/antlr/delimit.py +106 -0
  11. omlish/antlr/dot.py +31 -0
  12. omlish/antlr/errors.py +11 -0
  13. omlish/antlr/input.py +96 -0
  14. omlish/antlr/parsing.py +19 -0
  15. omlish/antlr/runtime.py +102 -0
  16. omlish/antlr/utils.py +38 -0
  17. omlish/argparse/all.py +45 -0
  18. omlish/{argparse.py → argparse/cli.py} +112 -107
  19. omlish/asyncs/__init__.py +0 -35
  20. omlish/asyncs/all.py +35 -0
  21. omlish/asyncs/asyncio/all.py +7 -0
  22. omlish/asyncs/asyncio/channels.py +40 -0
  23. omlish/asyncs/asyncio/streams.py +45 -0
  24. omlish/asyncs/asyncio/subprocesses.py +238 -0
  25. omlish/asyncs/asyncio/timeouts.py +16 -0
  26. omlish/asyncs/bluelet/LICENSE +6 -0
  27. omlish/asyncs/bluelet/all.py +67 -0
  28. omlish/asyncs/bluelet/api.py +23 -0
  29. omlish/asyncs/bluelet/core.py +178 -0
  30. omlish/asyncs/bluelet/events.py +78 -0
  31. omlish/asyncs/bluelet/files.py +80 -0
  32. omlish/asyncs/bluelet/runner.py +416 -0
  33. omlish/asyncs/bluelet/sockets.py +214 -0
  34. omlish/bootstrap/sys.py +3 -3
  35. omlish/cached.py +2 -2
  36. omlish/check.py +49 -460
  37. omlish/codecs/__init__.py +72 -0
  38. omlish/codecs/base.py +106 -0
  39. omlish/codecs/bytes.py +119 -0
  40. omlish/codecs/chain.py +23 -0
  41. omlish/codecs/funcs.py +39 -0
  42. omlish/codecs/registry.py +139 -0
  43. omlish/codecs/standard.py +4 -0
  44. omlish/codecs/text.py +217 -0
  45. omlish/collections/cache/impl.py +50 -57
  46. omlish/collections/coerce.py +1 -0
  47. omlish/collections/mappings.py +1 -1
  48. omlish/configs/flattening.py +1 -1
  49. omlish/defs.py +1 -1
  50. omlish/diag/_pycharm/runhack.py +8 -2
  51. omlish/diag/procfs.py +8 -8
  52. omlish/docker/__init__.py +0 -36
  53. omlish/docker/all.py +31 -0
  54. omlish/docker/consts.py +4 -0
  55. omlish/{lite/docker.py → docker/detect.py} +18 -0
  56. omlish/docker/{helpers.py → timebomb.py} +0 -21
  57. omlish/formats/cbor.py +31 -0
  58. omlish/formats/cloudpickle.py +31 -0
  59. omlish/formats/codecs.py +93 -0
  60. omlish/formats/json/codecs.py +29 -0
  61. omlish/formats/json/delimted.py +4 -0
  62. omlish/formats/json/stream/errors.py +2 -0
  63. omlish/formats/json/stream/lex.py +12 -6
  64. omlish/formats/json/stream/parse.py +38 -22
  65. omlish/formats/json5.py +31 -0
  66. omlish/formats/pickle.py +31 -0
  67. omlish/formats/repr.py +25 -0
  68. omlish/formats/toml.py +17 -0
  69. omlish/formats/yaml.py +25 -0
  70. omlish/funcs/__init__.py +0 -0
  71. omlish/{genmachine.py → funcs/genmachine.py} +5 -4
  72. omlish/{matchfns.py → funcs/match.py} +1 -1
  73. omlish/funcs/pairs.py +215 -0
  74. omlish/http/__init__.py +0 -48
  75. omlish/http/all.py +48 -0
  76. omlish/http/coro/__init__.py +0 -0
  77. omlish/{lite/fdio/corohttp.py → http/coro/fdio.py} +21 -19
  78. omlish/{lite/http/coroserver.py → http/coro/server.py} +20 -21
  79. omlish/{lite/http → http}/handlers.py +3 -2
  80. omlish/{lite/http → http}/parsing.py +1 -0
  81. omlish/http/sessions.py +1 -1
  82. omlish/{lite/http → http}/versions.py +1 -0
  83. omlish/inject/managed.py +2 -2
  84. omlish/io/__init__.py +0 -3
  85. omlish/{lite/io.py → io/buffers.py} +8 -9
  86. omlish/io/compress/__init__.py +9 -0
  87. omlish/io/compress/abc.py +104 -0
  88. omlish/io/compress/adapters.py +148 -0
  89. omlish/io/compress/base.py +24 -0
  90. omlish/io/compress/brotli.py +47 -0
  91. omlish/io/compress/bz2.py +61 -0
  92. omlish/io/compress/codecs.py +78 -0
  93. omlish/io/compress/gzip.py +350 -0
  94. omlish/io/compress/lz4.py +91 -0
  95. omlish/io/compress/lzma.py +81 -0
  96. omlish/io/compress/snappy.py +34 -0
  97. omlish/io/compress/zlib.py +74 -0
  98. omlish/io/compress/zstd.py +44 -0
  99. omlish/io/fdio/__init__.py +1 -0
  100. omlish/{lite → io}/fdio/handlers.py +5 -5
  101. omlish/{lite → io}/fdio/kqueue.py +8 -8
  102. omlish/{lite → io}/fdio/manager.py +7 -7
  103. omlish/{lite → io}/fdio/pollers.py +13 -13
  104. omlish/io/generators/__init__.py +56 -0
  105. omlish/io/generators/consts.py +1 -0
  106. omlish/io/generators/direct.py +13 -0
  107. omlish/io/generators/readers.py +189 -0
  108. omlish/io/generators/stepped.py +191 -0
  109. omlish/io/pyio.py +5 -2
  110. omlish/iterators/__init__.py +24 -0
  111. omlish/iterators/iterators.py +132 -0
  112. omlish/iterators/recipes.py +18 -0
  113. omlish/iterators/tools.py +96 -0
  114. omlish/iterators/unique.py +67 -0
  115. omlish/lang/__init__.py +13 -1
  116. omlish/lang/functions.py +11 -2
  117. omlish/lang/generators.py +243 -0
  118. omlish/lang/iterables.py +46 -49
  119. omlish/lang/maybes.py +4 -4
  120. omlish/lite/cached.py +39 -6
  121. omlish/lite/check.py +438 -75
  122. omlish/lite/contextmanagers.py +17 -4
  123. omlish/lite/dataclasses.py +42 -0
  124. omlish/lite/inject.py +28 -45
  125. omlish/lite/logs.py +0 -270
  126. omlish/lite/marshal.py +309 -144
  127. omlish/lite/pycharm.py +47 -0
  128. omlish/lite/reflect.py +33 -0
  129. omlish/lite/resources.py +8 -0
  130. omlish/lite/runtime.py +4 -4
  131. omlish/lite/shlex.py +12 -0
  132. omlish/lite/socketserver.py +2 -2
  133. omlish/lite/strings.py +31 -0
  134. omlish/logs/__init__.py +0 -32
  135. omlish/logs/{_abc.py → abc.py} +0 -1
  136. omlish/logs/all.py +37 -0
  137. omlish/logs/{formatters.py → color.py} +1 -2
  138. omlish/logs/configs.py +7 -38
  139. omlish/logs/filters.py +10 -0
  140. omlish/logs/handlers.py +4 -1
  141. omlish/logs/json.py +56 -0
  142. omlish/logs/proxy.py +99 -0
  143. omlish/logs/standard.py +128 -0
  144. omlish/logs/utils.py +2 -2
  145. omlish/manifests/__init__.py +2 -0
  146. omlish/manifests/load.py +209 -0
  147. omlish/manifests/types.py +17 -0
  148. omlish/marshal/base.py +1 -1
  149. omlish/marshal/factories.py +1 -1
  150. omlish/marshal/forbidden.py +1 -1
  151. omlish/marshal/iterables.py +1 -1
  152. omlish/marshal/literals.py +50 -0
  153. omlish/marshal/mappings.py +1 -1
  154. omlish/marshal/maybes.py +1 -1
  155. omlish/marshal/standard.py +5 -1
  156. omlish/marshal/unions.py +1 -1
  157. omlish/os/__init__.py +0 -0
  158. omlish/os/atomics.py +205 -0
  159. omlish/os/deathsig.py +23 -0
  160. omlish/{os.py → os/files.py} +0 -9
  161. omlish/{lite → os}/journald.py +2 -1
  162. omlish/os/linux.py +484 -0
  163. omlish/os/paths.py +36 -0
  164. omlish/{lite → os}/pidfile.py +1 -0
  165. omlish/os/sizes.py +9 -0
  166. omlish/reflect/__init__.py +3 -0
  167. omlish/reflect/subst.py +2 -1
  168. omlish/reflect/types.py +126 -44
  169. omlish/secrets/pwhash.py +1 -1
  170. omlish/secrets/subprocesses.py +3 -1
  171. omlish/specs/jsonrpc/marshal.py +1 -1
  172. omlish/specs/openapi/marshal.py +1 -1
  173. omlish/sql/alchemy/asyncs.py +1 -1
  174. omlish/sql/queries/__init__.py +9 -1
  175. omlish/sql/queries/building.py +3 -0
  176. omlish/sql/queries/exprs.py +10 -27
  177. omlish/sql/queries/idents.py +48 -10
  178. omlish/sql/queries/names.py +80 -13
  179. omlish/sql/queries/params.py +64 -0
  180. omlish/sql/queries/rendering.py +1 -1
  181. omlish/subprocesses.py +340 -0
  182. omlish/term.py +29 -14
  183. omlish/testing/pytest/marks.py +2 -2
  184. omlish/testing/pytest/plugins/asyncs.py +6 -1
  185. omlish/testing/pytest/plugins/logging.py +1 -1
  186. omlish/testing/pytest/plugins/switches.py +1 -1
  187. {omlish-0.0.0.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/METADATA +13 -11
  188. {omlish-0.0.0.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/RECORD +200 -117
  189. omlish/fnpairs.py +0 -496
  190. omlish/formats/json/cli/__main__.py +0 -11
  191. omlish/formats/json/cli/cli.py +0 -298
  192. omlish/formats/json/cli/formats.py +0 -71
  193. omlish/formats/json/cli/io.py +0 -74
  194. omlish/formats/json/cli/parsing.py +0 -82
  195. omlish/formats/json/cli/processing.py +0 -48
  196. omlish/formats/json/cli/rendering.py +0 -92
  197. omlish/iterators.py +0 -300
  198. omlish/lite/subprocesses.py +0 -130
  199. /omlish/{formats/json/cli → argparse}/__init__.py +0 -0
  200. /omlish/{lite/fdio → asyncs/asyncio}/__init__.py +0 -0
  201. /omlish/asyncs/{asyncio.py → asyncio/asyncio.py} +0 -0
  202. /omlish/{lite/http → asyncs/bluelet}/__init__.py +0 -0
  203. /omlish/collections/{_abc.py → abc.py} +0 -0
  204. /omlish/{fnpipes.py → funcs/pipes.py} +0 -0
  205. /omlish/io/{_abc.py → abc.py} +0 -0
  206. /omlish/sql/{_abc.py → abc.py} +0 -0
  207. {omlish-0.0.0.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/LICENSE +0 -0
  208. {omlish-0.0.0.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/WHEEL +0 -0
  209. {omlish-0.0.0.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/entry_points.txt +0 -0
  210. {omlish-0.0.0.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/top_level.txt +0 -0
@@ -51,63 +51,56 @@ class CacheImpl(Cache[K, V]):
51
51
  https://google.github.io/guava/releases/16.0/api/docs/com/google/common/cache/CacheBuilder.html
52
52
  """
53
53
 
54
- try:
55
- if not ta.TYPE_CHECKING:
56
- from ..._ext.cy.collections.cache import CacheLink as Link
57
- else:
58
- raise ImportError # noqa
59
-
60
- except ImportError:
61
- class Link:
62
- __slots__ = [
63
- 'seq',
64
- 'ins_prev',
65
- 'ins_next',
66
- 'lru_prev',
67
- 'lru_next',
68
- 'lfu_prev',
69
- 'lfu_next',
70
- 'key',
71
- 'value',
72
- 'weight',
73
- 'written',
74
- 'accessed',
75
- 'hits',
76
- 'unlinked',
77
- ]
78
-
79
- seq: int
80
- ins_prev: 'CacheImpl.Link'
81
- ins_next: 'CacheImpl.Link'
82
- lru_prev: 'CacheImpl.Link'
83
- lru_next: 'CacheImpl.Link'
84
- lfu_prev: 'CacheImpl.Link'
85
- lfu_next: 'CacheImpl.Link'
86
- key: ta.Any | weakref.ref
87
- value: ta.Any | weakref.ref
88
- weight: float
89
- written: float
90
- accessed: float
91
- hits: int
92
- unlinked: bool
93
-
94
- def __repr__(self) -> str:
95
- return (
96
- f'Link@{self.seq!s}('
97
- f'ins_prev={("@" + str(self.ins_prev.seq)) if self.ins_prev is not None else None}, '
98
- f'ins_next={("@" + str(self.ins_next.seq)) if self.ins_next is not None else None}, '
99
- f'lru_prev={("@" + str(self.lru_prev.seq)) if self.lru_prev is not None else None}, '
100
- f'lru_next={("@" + str(self.lru_next.seq)) if self.lru_next is not None else None}, '
101
- f'lfu_prev={("@" + str(self.lfu_prev.seq)) if self.lfu_prev is not None else None}, '
102
- f'lfu_next={("@" + str(self.lfu_next.seq)) if self.lfu_next is not None else None}, '
103
- f'key={self.key!r}, '
104
- f'value={self.value!r}, '
105
- f'weight={self.weight}, '
106
- f'written={self.written}, '
107
- f'accessed={self.accessed}, '
108
- f'hits={self.hits}, '
109
- f'unlinked={self.unlinked})'
110
- )
54
+ class Link:
55
+ __slots__ = [
56
+ 'seq',
57
+ 'ins_prev',
58
+ 'ins_next',
59
+ 'lru_prev',
60
+ 'lru_next',
61
+ 'lfu_prev',
62
+ 'lfu_next',
63
+ 'key',
64
+ 'value',
65
+ 'weight',
66
+ 'written',
67
+ 'accessed',
68
+ 'hits',
69
+ 'unlinked',
70
+ ]
71
+
72
+ seq: int
73
+ ins_prev: 'CacheImpl.Link'
74
+ ins_next: 'CacheImpl.Link'
75
+ lru_prev: 'CacheImpl.Link'
76
+ lru_next: 'CacheImpl.Link'
77
+ lfu_prev: 'CacheImpl.Link'
78
+ lfu_next: 'CacheImpl.Link'
79
+ key: ta.Any | weakref.ref
80
+ value: ta.Any | weakref.ref
81
+ weight: float
82
+ written: float
83
+ accessed: float
84
+ hits: int
85
+ unlinked: bool
86
+
87
+ def __repr__(self) -> str:
88
+ return (
89
+ f'Link@{self.seq!s}('
90
+ f'ins_prev={("@" + str(self.ins_prev.seq)) if self.ins_prev is not None else None}, '
91
+ f'ins_next={("@" + str(self.ins_next.seq)) if self.ins_next is not None else None}, '
92
+ f'lru_prev={("@" + str(self.lru_prev.seq)) if self.lru_prev is not None else None}, '
93
+ f'lru_next={("@" + str(self.lru_next.seq)) if self.lru_next is not None else None}, '
94
+ f'lfu_prev={("@" + str(self.lfu_prev.seq)) if self.lfu_prev is not None else None}, '
95
+ f'lfu_next={("@" + str(self.lfu_next.seq)) if self.lfu_next is not None else None}, '
96
+ f'key={self.key!r}, '
97
+ f'value={self.value!r}, '
98
+ f'weight={self.weight}, '
99
+ f'written={self.written}, '
100
+ f'accessed={self.accessed}, '
101
+ f'hits={self.hits}, '
102
+ f'unlinked={self.unlinked})'
103
+ )
111
104
 
112
105
  _cache: ta.MutableMapping[ta.Any, Link]
113
106
 
@@ -334,4 +334,5 @@ def map_of_or_none(
334
334
  value_fn = _unpack_fn(value_fn)
335
335
  return inner
336
336
 
337
+
337
338
  # endregion
@@ -86,7 +86,7 @@ class DynamicTypeMap(ta.Generic[V]):
86
86
  self._items = list(items)
87
87
  self._weak = bool(weak)
88
88
 
89
- self._cache: ta.MutableMapping[type, ta.Any] = weakref.WeakKeyDictionary()
89
+ self._cache: ta.MutableMapping[type, ta.Any] = weakref.WeakKeyDictionary() if weak else {}
90
90
 
91
91
  @property
92
92
  def items(self) -> ta.Sequence[V]:
@@ -130,7 +130,7 @@ class Flattening:
130
130
  .split(self._index_close + self._index_open):
131
131
  yield int(p)
132
132
  else:
133
- check.state(')' not in part)
133
+ check.state(self._index_close not in part)
134
134
  yield part
135
135
 
136
136
  for fk, v in flattened.items():
omlish/defs.py CHANGED
@@ -199,7 +199,7 @@ def abstract_method(cls_dct, *names):
199
199
 
200
200
  @lang.cls_dct_fn()
201
201
  def abstract_property(cls_dct, *names):
202
- return not_implemented(cls_dct, *names, wrapper=abc.abstractmethod)
202
+ return not_implemented(cls_dct, *names, wrapper=lambda o: property(abc.abstractmethod(o)))
203
203
 
204
204
 
205
205
  @lang.cls_dct_fn()
@@ -3,7 +3,10 @@
3
3
  .venv/bin/python $(curl -LsSf https://raw.githubusercontent.com/wrmsr/omlish/master/omlish/diag/_pycharm/runhack.py -o $(mktemp) && echo "$_") install
4
4
 
5
5
  ==
6
+ TODO:
7
+ - check for existing files - can't run regular dep entrypoints now
6
8
 
9
+ ==
7
10
  See:
8
11
  - https://github.com/JetBrains/intellij-community/blob/6400f70dde6f743e39a257a5a78cc51b644c835e/python/helpers/pycharm/_jb_pytest_runner.py
9
12
  - https://github.com/JetBrains/intellij-community/blob/5a4e584aa59767f2e7cf4bd377adfaaf7503984b/python/helpers/pycharm/_jb_runner_tools.py
@@ -1278,7 +1281,7 @@ class HackRunner:
1278
1281
  def run(self) -> None:
1279
1282
  # breakpoint()
1280
1283
 
1281
- env = self._env()
1284
+ env = self._env() # type: RunEnv
1282
1285
  self._debug(env.as_json())
1283
1286
 
1284
1287
  if not self._is_enabled:
@@ -1292,6 +1295,10 @@ class HackRunner:
1292
1295
  self._debug('not pycharm hosted')
1293
1296
  return
1294
1297
 
1298
+ if len(env.orig_argv) < 2:
1299
+ self._debug('no enough interpreter arguments')
1300
+ return
1301
+
1295
1302
  exe = self._exe()
1296
1303
  dec = self._decider().decide(exe.target)
1297
1304
  if dec is None:
@@ -1301,7 +1308,6 @@ class HackRunner:
1301
1308
  self._debug(dec.as_json())
1302
1309
  self._apply(dec)
1303
1310
 
1304
-
1305
1311
  ##
1306
1312
 
1307
1313
 
omlish/diag/procfs.py CHANGED
@@ -13,8 +13,8 @@ import typing as ta
13
13
 
14
14
  from .. import iterators as it
15
15
  from .. import lang
16
- from .. import os as oos
17
16
  from ..formats import json
17
+ from ..os.sizes import PAGE_SIZE
18
18
  from .procstats import ProcStats
19
19
 
20
20
 
@@ -239,8 +239,8 @@ def get_process_range_pagemaps(start: int, end: int, pid: PidLike = 'self') -> t
239
239
  """https://www.kernel.org/doc/Documentation/vm/pagemap.txt"""
240
240
 
241
241
  _check_linux()
242
- offset = (start // oos.PAGE_SIZE) * 8
243
- npages = ((end - start) // oos.PAGE_SIZE)
242
+ offset = (start // PAGE_SIZE) * 8
243
+ npages = ((end - start) // PAGE_SIZE)
244
244
  size = npages * 8
245
245
  with open(f'/proc/{pid}/pagemap', 'rb') as pagemap_file:
246
246
  pagemap_file.seek(offset)
@@ -251,7 +251,7 @@ def get_process_range_pagemaps(start: int, end: int, pid: PidLike = 'self') -> t
251
251
  for pagenum in range(npages):
252
252
  [packed] = _struct_unpack('Q', pagemap_buf[pagenum * 8:(pagenum + 1) * 8])
253
253
  yield {
254
- 'address': start + (pagenum * oos.PAGE_SIZE),
254
+ 'address': start + (pagenum * PAGE_SIZE),
255
255
  'pfn': (packed & ((1 << (54 + 1)) - 1)),
256
256
  'swap_type': (packed & ((1 << (4 + 1)) - 1)),
257
257
  'swap_offset': (packed & ((1 << (54 + 1)) - 1)) >> 5,
@@ -280,7 +280,7 @@ def _dump_cmd(args: ta.Any) -> None:
280
280
  sys.stdout.write('\n')
281
281
  for pm in get_process_range_pagemaps(m['address'], m['end_address'], args.pid):
282
282
  if pm['pte_soft_dirty']:
283
- dirty_total += oos.PAGE_SIZE
283
+ dirty_total += PAGE_SIZE
284
284
  sys.stdout.write(json.dumps({'page': tuple(pm[k] for k in PAGEMAP_KEYS)}))
285
285
  sys.stdout.write('\n')
286
286
  dct = {
@@ -326,11 +326,11 @@ def _cmp_cmd(args: ta.Any) -> None:
326
326
  r_pages += c_pages
327
327
  dct = {
328
328
  'l_pages': l_pages,
329
- 'l_bytes': l_pages * oos.PAGE_SIZE,
329
+ 'l_bytes': l_pages * PAGE_SIZE,
330
330
  'r_pages': r_pages,
331
- 'r_bytes': r_pages * oos.PAGE_SIZE,
331
+ 'r_bytes': r_pages * PAGE_SIZE,
332
332
  'c_pages': c_pages,
333
- 'c_bytes': c_pages * oos.PAGE_SIZE,
333
+ 'c_bytes': c_pages * PAGE_SIZE,
334
334
  }
335
335
  sys.stdout.write(json.dumps(dct))
336
336
  sys.stdout.write('\n')
omlish/docker/__init__.py CHANGED
@@ -1,36 +0,0 @@
1
- from .cli import ( # noqa
2
- Inspect,
3
- Port,
4
- PsItem,
5
- cli_inspect,
6
- cli_ps,
7
- has_cli,
8
- parse_port,
9
- )
10
-
11
- from .compose import ( # noqa
12
- ComposeConfig,
13
- get_compose_port,
14
- )
15
-
16
- from .helpers import ( # noqa
17
- DOCKER_FOR_MAC_HOSTNAME,
18
- DOCKER_HOST_PLATFORM_KEY,
19
- get_docker_host_platform,
20
- timebomb_payload,
21
- )
22
-
23
- from .hub import ( # noqa
24
- HubRepoInfo,
25
- get_hub_repo_info,
26
- select_latest_tag,
27
- split_tag_suffix,
28
- )
29
-
30
-
31
- ##
32
-
33
-
34
- from ..lite.docker import ( # noqa
35
- is_likely_in_docker,
36
- )
omlish/docker/all.py ADDED
@@ -0,0 +1,31 @@
1
+ from .cli import ( # noqa
2
+ Inspect,
3
+ Port,
4
+ PsItem,
5
+ cli_inspect,
6
+ cli_ps,
7
+ has_cli,
8
+ parse_port,
9
+ )
10
+
11
+ from .compose import ( # noqa
12
+ ComposeConfig,
13
+ get_compose_port,
14
+ )
15
+
16
+ from .detect import ( # noqa
17
+ DOCKER_HOST_PLATFORM_KEY,
18
+ get_docker_host_platform,
19
+ is_likely_in_docker,
20
+ )
21
+
22
+ from .hub import ( # noqa
23
+ HubRepoInfo,
24
+ get_hub_repo_info,
25
+ select_latest_tag,
26
+ split_tag_suffix,
27
+ )
28
+
29
+ from .timebomb import ( # noqa
30
+ timebomb_payload,
31
+ )
@@ -0,0 +1,4 @@
1
+ # @omlish-lite
2
+
3
+
4
+ DOCKER_FOR_MAC_HOSTNAME = 'docker.for.mac.localhost'
@@ -1,5 +1,23 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ import os
1
4
  import re
2
5
  import sys
6
+ import typing as ta
7
+
8
+
9
+ ##
10
+
11
+
12
+ # Set by pyproject, docker-dev script
13
+ DOCKER_HOST_PLATFORM_KEY = 'DOCKER_HOST_PLATFORM'
14
+
15
+
16
+ def get_docker_host_platform() -> ta.Optional[str]:
17
+ return os.environ.get(DOCKER_HOST_PLATFORM_KEY)
18
+
19
+
20
+ ##
3
21
 
4
22
 
5
23
  _LIKELY_IN_DOCKER_PATTERN = re.compile(r'^overlay / .*/(docker|desktop-containerd)/')
@@ -1,10 +1,6 @@
1
- import os
2
1
  import shlex
3
2
 
4
3
 
5
- ##
6
-
7
-
8
4
  _DEFAULT_TIMEBOMB_NAME = '-'.join([*__name__.split('.'), 'timebomb'])
9
5
 
10
6
 
@@ -16,20 +12,3 @@ def timebomb_payload(delay_s: float, name: str = _DEFAULT_TIMEBOMB_NAME) -> str:
16
12
  'sh -c \'killall5 -9 -o $PPID -o $$ ; kill 1\''
17
13
  ') &'
18
14
  )
19
-
20
-
21
- ##
22
-
23
-
24
- DOCKER_FOR_MAC_HOSTNAME = 'docker.for.mac.localhost'
25
-
26
-
27
- ##
28
-
29
-
30
- # Set by pyproject, docker-dev script
31
- DOCKER_HOST_PLATFORM_KEY = 'DOCKER_HOST_PLATFORM'
32
-
33
-
34
- def get_docker_host_platform() -> str | None:
35
- return os.environ.get(DOCKER_HOST_PLATFORM_KEY)
omlish/formats/cbor.py ADDED
@@ -0,0 +1,31 @@
1
+ import typing as ta
2
+
3
+ from .. import lang
4
+ from .codecs import make_bytes_object_codec
5
+ from .codecs import make_object_lazy_loaded_codec
6
+
7
+
8
+ if ta.TYPE_CHECKING:
9
+ import cbor2
10
+ else:
11
+ cbor2 = lang.proxy_import('cbor2')
12
+
13
+
14
+ ##
15
+
16
+
17
+ def dump(obj: ta.Any) -> bytes:
18
+ return cbor2.dumps(obj)
19
+
20
+
21
+ def load(s: bytes) -> ta.Any:
22
+ return cbor2.loads(s)
23
+
24
+
25
+ ##
26
+
27
+
28
+ CBOR_CODEC = make_bytes_object_codec('cbor', dump, load)
29
+
30
+ # @omlish-manifest
31
+ _CBOR_LAZY_CODEC = make_object_lazy_loaded_codec(__name__, 'CBOR_CODEC', CBOR_CODEC)
@@ -0,0 +1,31 @@
1
+ import typing as ta
2
+
3
+ from .. import lang
4
+ from .codecs import make_bytes_object_codec
5
+ from .codecs import make_object_lazy_loaded_codec
6
+
7
+
8
+ if ta.TYPE_CHECKING:
9
+ import cloudpickle
10
+ else:
11
+ cloudpickle = lang.proxy_import('cloudpickle')
12
+
13
+
14
+ ##
15
+
16
+
17
+ def dump(obj: ta.Any) -> bytes:
18
+ return cloudpickle.dumps(obj)
19
+
20
+
21
+ def load(s: bytes) -> ta.Any:
22
+ return cloudpickle.loads(s)
23
+
24
+
25
+ ##
26
+
27
+
28
+ CLOUDPICKLE_CODEC = make_bytes_object_codec('cloudpickle', dump, load)
29
+
30
+ # @omlish-manifest
31
+ _CLOUDPICKLE_LAZY_CODEC = make_object_lazy_loaded_codec(__name__, 'CLOUDPICKLE_CODEC', CLOUDPICKLE_CODEC)
@@ -0,0 +1,93 @@
1
+ import typing as ta
2
+
3
+ from .. import codecs
4
+ from .. import reflect as rfl
5
+
6
+
7
+ ObjectCodecT = ta.TypeVar('ObjectCodecT', bound='ObjectCodec')
8
+
9
+
10
+ ##
11
+
12
+
13
+ class ObjectCodec(codecs.Codec):
14
+ pass
15
+
16
+
17
+ def make_object_codec(
18
+ cls: type[ObjectCodecT],
19
+ name: str,
20
+ dumps: ta.Callable,
21
+ loads: ta.Callable,
22
+ *,
23
+ input: rfl.Type = rfl.type_(ta.Any), # noqa
24
+ aliases: ta.Collection[str] | None = None,
25
+ ) -> ObjectCodecT:
26
+ return cls(
27
+ name=name,
28
+ aliases=aliases,
29
+
30
+ input=input,
31
+ output=bytes,
32
+
33
+ new=lambda: codecs.FnPairEagerCodec.of(dumps, loads),
34
+ )
35
+
36
+
37
+ ##
38
+
39
+
40
+ class BytesObjectCodec(ObjectCodec):
41
+ pass
42
+
43
+
44
+ def make_bytes_object_codec(
45
+ name: str,
46
+ dumps: ta.Callable[[ta.Any], bytes],
47
+ loads: ta.Callable[[bytes], ta.Any],
48
+ **kwargs: ta.Any,
49
+ ) -> BytesObjectCodec:
50
+ return make_object_codec(
51
+ BytesObjectCodec,
52
+ name,
53
+ dumps,
54
+ loads,
55
+ **kwargs,
56
+ )
57
+
58
+
59
+ ##
60
+
61
+
62
+ class StrObjectCodec(ObjectCodec):
63
+ pass
64
+
65
+
66
+ def make_str_object_codec(
67
+ name: str,
68
+ dumps: ta.Callable[[ta.Any], str],
69
+ loads: ta.Callable[[str], ta.Any],
70
+ **kwargs: ta.Any,
71
+ ) -> StrObjectCodec:
72
+ return make_object_codec(
73
+ StrObjectCodec,
74
+ name,
75
+ dumps,
76
+ loads,
77
+ **kwargs,
78
+ )
79
+
80
+
81
+ ##
82
+
83
+
84
+ def make_object_lazy_loaded_codec(
85
+ mod_name: str,
86
+ attr_name: str,
87
+ codec: ObjectCodec,
88
+ ) -> codecs.LazyLoadedCodec:
89
+ return codecs.LazyLoadedCodec.new(
90
+ mod_name,
91
+ attr_name,
92
+ codec,
93
+ )
@@ -0,0 +1,29 @@
1
+ from ..codecs import make_object_lazy_loaded_codec
2
+ from ..codecs import make_str_object_codec
3
+ from .json import dumps
4
+ from .json import dumps_compact
5
+ from .json import dumps_pretty
6
+ from .json import loads
7
+
8
+
9
+ ##
10
+
11
+
12
+ JSON_CODEC = make_str_object_codec('json', dumps, loads)
13
+
14
+ # @omlish-manifest
15
+ _JSON_LAZY_CODEC = make_object_lazy_loaded_codec(__name__, 'JSON_CODEC', JSON_CODEC)
16
+
17
+ #
18
+
19
+ JSON_COMPACT_CODEC = make_str_object_codec('json-compact', dumps_compact, loads)
20
+
21
+ # @omlish-manifest
22
+ _JSON_COMPACT_LAZY_CODEC = make_object_lazy_loaded_codec(__name__, 'JSON_COMPACT_CODEC', JSON_COMPACT_CODEC)
23
+
24
+ #
25
+
26
+ JSON_PRETTY_CODEC = make_str_object_codec('json-pretty', dumps_pretty, loads)
27
+
28
+ # @omlish-manifest
29
+ _JSON_PRETTY_LAZY_CODEC = make_object_lazy_loaded_codec(__name__, 'JSON_PRETTY_CODEC', JSON_PRETTY_CODEC)
@@ -0,0 +1,4 @@
1
+ """
2
+ TODO:
3
+ - jsonl codec
4
+ """
@@ -0,0 +1,2 @@
1
+ class JsonStreamError(Exception):
2
+ pass
@@ -3,6 +3,7 @@ TODO:
3
3
  - max buf size
4
4
  - max recursion depth
5
5
  - mark start pos of tokens, currently returning end
6
+ - _do_string inner loop optimization somehow
6
7
  """
7
8
  import dataclasses as dc
8
9
  import io
@@ -11,7 +12,8 @@ import re
11
12
  import typing as ta
12
13
 
13
14
  from .... import check
14
- from ....genmachine import GenMachine
15
+ from ....funcs.genmachine import GenMachine
16
+ from .errors import JsonStreamError
15
17
 
16
18
 
17
19
  ##
@@ -95,7 +97,7 @@ CONST_TOKENS: ta.Mapping[str, tuple[TokenKind, str | float | None]] = {
95
97
 
96
98
 
97
99
  @dc.dataclass()
98
- class JsonLexError(Exception):
100
+ class JsonStreamLexError(JsonStreamError):
99
101
  message: str
100
102
 
101
103
  pos: Position
@@ -160,8 +162,8 @@ class JsonStreamLexer(GenMachine[str, Token]):
160
162
  self._buf.truncate()
161
163
  return raw
162
164
 
163
- def _raise(self, msg: str) -> ta.NoReturn:
164
- raise JsonLexError(msg, self.pos)
165
+ def _raise(self, msg: str, src: Exception | None = None) -> ta.NoReturn:
166
+ raise JsonStreamLexError(msg, self.pos) from src
165
167
 
166
168
  def _do_main(self):
167
169
  while True:
@@ -202,7 +204,7 @@ class JsonStreamLexer(GenMachine[str, Token]):
202
204
  self._raise('Unexpected end of input')
203
205
 
204
206
  if not c:
205
- raise NotImplementedError
207
+ self._raise(f'Unterminated string literal: {self._buf.getvalue()}')
206
208
 
207
209
  self._buf.write(c)
208
210
  if c == '"' and last != '\\':
@@ -210,7 +212,11 @@ class JsonStreamLexer(GenMachine[str, Token]):
210
212
  last = c
211
213
 
212
214
  raw = self._flip_buf()
213
- sv = json.loads(raw)
215
+ try:
216
+ sv = json.loads(raw)
217
+ except json.JSONDecodeError as e:
218
+ self._raise(f'Invalid string literal: {raw!r}', e)
219
+
214
220
  yield self._make_tok('STRING', sv, raw, pos)
215
221
 
216
222
  return self._do_main()