omlish 0.0.0.dev111__py3-none-any.whl → 0.0.0.dev113__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.
omlish/.manifests.json CHANGED
@@ -23,18 +23,6 @@
23
23
  }
24
24
  }
25
25
  },
26
- {
27
- "module": ".diag.pycharm.cli",
28
- "attr": "_CLI_MODULE",
29
- "file": "omlish/diag/pycharm/cli.py",
30
- "line": 38,
31
- "value": {
32
- "$omdev.cli.types.CliModule": {
33
- "cmd_name": "pycharm",
34
- "mod_name": "omlish.diag.pycharm.cli"
35
- }
36
- }
37
- },
38
26
  {
39
27
  "module": ".formats.json.cli.__main__",
40
28
  "attr": "_CLI_MODULE",
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev111'
2
- __revision__ = 'bb150a1986306450374f5184b47e2658a5b7c656'
1
+ __version__ = '0.0.0.dev113'
2
+ __revision__ = 'eafea7b4602b808e2955b7dbea769403091c6548'
3
3
 
4
4
 
5
5
  #
omlish/argparse.py CHANGED
@@ -77,14 +77,23 @@ CommandFn = ta.Callable[[], int | None]
77
77
  class Command:
78
78
  name: str
79
79
  fn: CommandFn
80
- args: ta.Sequence[Arg] = ()
80
+ args: ta.Sequence[Arg] = () # noqa
81
+
82
+ _: dc.KW_ONLY
83
+
84
+ aliases: ta.Sequence[str] | None = None
81
85
  parent: ta.Optional['Command'] = None
82
86
  accepts_unknown: bool = False
83
87
 
84
88
  def __post_init__(self) -> None:
85
- check.isinstance(self.name, str)
86
- check.not_in('_', self.name)
87
- check.not_empty(self.name)
89
+ def check_name(s: str) -> None:
90
+ check.isinstance(s, str)
91
+ check.not_in('_', s)
92
+ check.not_empty(s)
93
+ check_name(self.name)
94
+ check.not_isinstance(self.aliases, str)
95
+ for a in self.aliases or []:
96
+ check_name(a)
88
97
 
89
98
  check.callable(self.fn)
90
99
  check.arg(all(isinstance(a, Arg) for a in self.args))
@@ -105,6 +114,7 @@ class Command:
105
114
  def command(
106
115
  *args: Arg,
107
116
  name: str | None = None,
117
+ aliases: ta.Iterable[str] | None = None,
108
118
  parent: Command | None = None,
109
119
  accepts_unknown: bool = False,
110
120
  ) -> ta.Any: # ta.Callable[[CommandFn], Command]: # FIXME
@@ -112,12 +122,14 @@ def command(
112
122
  check.isinstance(arg, Arg)
113
123
  check.isinstance(name, (str, None))
114
124
  check.isinstance(parent, (Command, None))
125
+ check.not_isinstance(aliases, str)
115
126
 
116
127
  def inner(fn):
117
128
  return Command(
118
129
  (name if name is not None else fn.__name__).replace('_', '-'),
119
130
  fn,
120
131
  args,
132
+ aliases=tuple(aliases) if aliases is not None else None,
121
133
  parent=parent,
122
134
  accepts_unknown=accepts_unknown,
123
135
  )
@@ -185,18 +197,23 @@ class _CliMeta(type):
185
197
  if isinstance(obj, Command):
186
198
  if obj.parent is not None:
187
199
  raise NotImplementedError
188
- cparser = subparsers.add_parser(obj.name)
189
- for arg in (obj.args or []):
190
- if (
191
- len(arg.args) == 1 and
192
- isinstance(arg.args[0], str) and
193
- not (n := check.isinstance(arg.args[0], str)).startswith('-') and
194
- 'metavar' not in arg.kwargs
195
- ):
196
- cparser.add_argument(n.replace('-', '_'), **arg.kwargs, metavar=n)
197
- else:
198
- cparser.add_argument(*arg.args, **arg.kwargs)
199
- cparser.set_defaults(_cmd=obj)
200
+ for cn in [obj.name, *(obj.aliases or [])]:
201
+ cparser = subparsers.add_parser(cn)
202
+ for arg in (obj.args or []):
203
+ if (
204
+ len(arg.args) == 1 and
205
+ isinstance(arg.args[0], str) and
206
+ not (n := check.isinstance(arg.args[0], str)).startswith('-') and
207
+ 'metavar' not in arg.kwargs
208
+ ):
209
+ cparser.add_argument(
210
+ n.replace('-', '_'),
211
+ **arg.kwargs,
212
+ metavar=n,
213
+ )
214
+ else:
215
+ cparser.add_argument(*arg.args, **arg.kwargs)
216
+ cparser.set_defaults(_cmd=obj)
200
217
 
201
218
  elif isinstance(obj, Arg):
202
219
  if att in anns:
omlish/diag/debug.py CHANGED
@@ -2,25 +2,82 @@
2
2
  TODO:
3
3
  - select best debugger: ipdb, pudb,
4
4
  """
5
- import contextlib
6
- import sys
5
+ import dataclasses as dc
6
+ import functools
7
7
  import traceback
8
+ import types
8
9
  import typing as ta
9
10
 
11
+ from .. import check
12
+ from .. import lang
10
13
 
11
- @contextlib.contextmanager
12
- def debugging_on_exception(
13
- *,
14
- silent: bool = False,
15
- ) -> ta.Iterator[None]:
14
+
15
+ if ta.TYPE_CHECKING:
16
16
  import pdb # noqa
17
17
 
18
- try:
19
- yield
20
- except Exception:
21
- if not silent:
18
+ from . import pydevd
19
+
20
+ else:
21
+ pdb = lang.proxy_import('pdb')
22
+
23
+ pydevd = lang.proxy_import('.pydevd', __package__)
24
+
25
+
26
+ T = ta.TypeVar('T')
27
+ P = ta.ParamSpec('P')
28
+
29
+ ExceptionInfo: ta.TypeAlias = tuple[type[BaseException], BaseException, types.TracebackType]
30
+
31
+ PostMortemDebugger: ta.TypeAlias = ta.Callable[[ExceptionInfo], None]
32
+
33
+
34
+ ##
35
+
36
+
37
+ def pdb_post_mortem_debugger(ei: ExceptionInfo) -> None:
38
+ pdb.post_mortem(ei[2])
39
+
40
+
41
+ def get_post_mortem_debugger() -> PostMortemDebugger:
42
+ if pydevd.is_present():
43
+ return pydevd.debug_unhandled_exception
44
+
45
+ else:
46
+ check.not_none(pdb.post_mortem)
47
+ return pdb_post_mortem_debugger
48
+
49
+
50
+ ##
51
+
52
+
53
+ @dc.dataclass(kw_only=True)
54
+ class DebuggingOnException:
55
+ silent: bool = False
56
+
57
+ fn: PostMortemDebugger | None = None
58
+
59
+ def __call__(self, fn: ta.Callable[P, T]) -> ta.Callable[P, T]:
60
+ @functools.wraps(fn)
61
+ def inner(*args, **kwargs):
62
+ with self:
63
+ return fn(*args, **kwargs)
64
+
65
+ return inner
66
+
67
+ def __enter__(self) -> ta.Self:
68
+ if self.fn is None:
69
+ self.fn = get_post_mortem_debugger()
70
+
71
+ return self
72
+
73
+ def __exit__(self, exc_type, exc_val, exc_tb):
74
+ if exc_val is None:
75
+ return
76
+
77
+ if not self.silent:
22
78
  traceback.print_exc()
23
79
 
24
- pdb.post_mortem(sys.exc_info()[2])
80
+ check.not_none(self.fn)((exc_type, exc_val, exc_tb))
81
+
25
82
 
26
- raise
83
+ debugging_on_exception = DebuggingOnException
@@ -8,14 +8,14 @@ import subprocess
8
8
  import sys
9
9
  import typing as ta
10
10
 
11
- from ... import check
12
- from ... import lang
11
+ from .. import check
12
+ from .. import lang
13
13
 
14
14
 
15
15
  if ta.TYPE_CHECKING:
16
- docker = lang.proxy_import('...docker')
16
+ docker = lang.proxy_import('..docker')
17
17
  else:
18
- from ... import docker
18
+ from .. import docker
19
19
 
20
20
 
21
21
  ##
omlish/diag/pydevd.py CHANGED
@@ -5,7 +5,6 @@ an already-debugging PyCharm instance to debug PySpark jobs.
5
5
 
6
6
  TODO:
7
7
  - https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html#
8
- - PyCharm.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_constants.py -> USE_LOW_IMPACT_MONITORING
9
8
 
10
9
  ==
11
10
 
omlish/docker/helpers.py CHANGED
@@ -26,7 +26,7 @@ def timebomb_payload(delay_s: float, name: str = _DEFAULT_TIMEBOMB_NAME) -> str:
26
26
  DOCKER_FOR_MAC_HOSTNAME = 'docker.for.mac.localhost'
27
27
 
28
28
 
29
- _LIKELY_IN_DOCKER_PATTERN = re.compile(r'^overlay / .*/docker/')
29
+ _LIKELY_IN_DOCKER_PATTERN = re.compile(r'^overlay / .*/(docker|desktop-containerd)/')
30
30
 
31
31
 
32
32
  def is_likely_in_docker() -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev111
3
+ Version: 0.0.0.dev113
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,7 +1,7 @@
1
- omlish/.manifests.json,sha256=hTFp9tvE72BxKloIq1s1SS0LRQlIsvMtO69Sbc47rKg,1704
2
- omlish/__about__.py,sha256=gvxx_bze4mfSzt-0PMk7AqSogAZ6wFVXsyllG2meSDQ,3352
1
+ omlish/.manifests.json,sha256=CxGnj-UiRPlZgmgWoovDWrOnqpSEmBy_kqA7cdfSA3w,1431
2
+ omlish/__about__.py,sha256=UxymFoEqTP-bPtqBabCzEoJesLLJ54WQjXVoPYATbEc,3352
3
3
  omlish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- omlish/argparse.py,sha256=Dc73G8lyoQBLvXhMYUbzQUh4SJu_OTvKUXjSUxq_ang,7499
4
+ omlish/argparse.py,sha256=cqKGAqcxuxv_s62z0gq29L9KAvg_3-_rFvXKjVpRJjo,8126
5
5
  omlish/c3.py,sha256=4vogWgwPb8TbNS2KkZxpoWbwjj7MuHG2lQG-hdtkvjI,8062
6
6
  omlish/cached.py,sha256=vn3ZiKy0d3NW_kzoXCi_Fg_s5vUcH0LQ1idfKBcQhzk,489
7
7
  omlish/check.py,sha256=rZFEn6IHiMq4KGCYxlUGcUCJP12pPPUs_-AG0aouPM8,10540
@@ -151,17 +151,15 @@ omlish/dataclasses/impl/slots.py,sha256=qXRLbtFWUs_2UV1fFUdv53_6fBLKJ_8McjNiP9YQ
151
151
  omlish/dataclasses/impl/utils.py,sha256=aER2iL3UAtgS1BdLuEvTr9Tr2wC28wk1kiOeO-jIymw,6138
152
152
  omlish/diag/__init__.py,sha256=4S8v0myJM4Zld6_FV6cPe_nSv0aJb6kXftEit0HkiGE,1141
153
153
  omlish/diag/asts.py,sha256=BveUUNUcaAm4Hg55f4ZxGSI313E4L8cCZ5XjHpEkKVI,3325
154
- omlish/diag/debug.py,sha256=YPzQXiBAJMYHYpBKzx0QhlLMZokjR5kkAVLodA3yddQ,424
154
+ omlish/diag/debug.py,sha256=ClED7kKXeVMyKrjGIxcq14kXk9kvUJfytBQwK9y7c4Q,1637
155
155
  omlish/diag/procfs.py,sha256=vBovaMvAUKdl7FbtFq3TNsSmdhs8DaYfhoEsKeWYta8,9704
156
156
  omlish/diag/procstats.py,sha256=UkqxREqfd-38xPYZ9T1SIJISz5ARQCEhTtOZrxtm2dE,777
157
157
  omlish/diag/ps.py,sha256=1JWxZen3fVG-20R6ZZ8BtO_gpzw_5bhHZiKdoHkgxoU,1004
158
- omlish/diag/pydevd.py,sha256=tHI0fc2ZaYKudUWTRuUe5B66qGeNktPC49ZKb8x0rSY,7298
158
+ omlish/diag/pycharm.py,sha256=7-r_F-whXt8v-0dehxAX-MeMFPM3iZXX9IfeL0GfUtk,4643
159
+ omlish/diag/pydevd.py,sha256=z9cy0fdmGkQf2fYKmOdAt6oPMBNMKXbz0XxK6capldI,7178
159
160
  omlish/diag/threads.py,sha256=1-x02VCDZ407gfbtXm1pWK-ubqhqfePm9PMqkHCVoqk,3642
160
161
  omlish/diag/_pycharm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
161
162
  omlish/diag/_pycharm/runhack.py,sha256=eJlaUXIcFzAjOop_793RwNS_KF9NmhLv0i22xRVVeo0,34951
162
- omlish/diag/pycharm/__init__.py,sha256=-hZryZ3RfuoH4arwhBl-RmCZ6j-ybuUIEUf9C8o37iY,180
163
- omlish/diag/pycharm/cli.py,sha256=7SRh6yj8S5YGda4bq9BD4Kzwtgg4_Wa-K202ReZN2iI,1011
164
- omlish/diag/pycharm/pycharm.py,sha256=Xmh0PyOe51NSI7kYODvhjYCKIqSddyYOAqjx9v6zNlw,4647
165
163
  omlish/diag/replserver/__init__.py,sha256=uLo6V2aQ29v9z3IMELlPDSlG3_2iOT4-_X8VniF-EgE,235
166
164
  omlish/diag/replserver/__main__.py,sha256=LmU41lQ58bm1h4Mx7S8zhE_uEBSC6kPcp9mn5JRpulA,32
167
165
  omlish/diag/replserver/console.py,sha256=XzBDVhYlr8FY6ym4OwoaIHuFOHnGK3dTYlMDIOMUUlA,7410
@@ -175,7 +173,7 @@ omlish/dispatch/methods.py,sha256=XHjwwC9Gn4iDWxbyLAcbdSwRgVaq-8Bnn5cAwf5oZdA,54
175
173
  omlish/docker/__init__.py,sha256=dmda-4zBo0UM_CMws_1MOwtyObdF79LB0HF5IT3sDVk,482
176
174
  omlish/docker/cli.py,sha256=gtb9kitVfGnd4cr587NsVVk8D5Ok5y5SAsqD_SwGrSA,2565
177
175
  omlish/docker/compose.py,sha256=4drmnGQzbkOFJ9B6XSg9rnXkJeZz1ETmdcMe1PE790U,1237
178
- omlish/docker/helpers.py,sha256=j2eZIqIUpy34ZmoGyIzsYuKx9HeewwYBfrGNC99EFYk,928
176
+ omlish/docker/helpers.py,sha256=4gd82lpFh5bQFmKOkxgVU-QyuDcGR4341qW75UcFiX0,949
179
177
  omlish/docker/hub.py,sha256=7LIuJGdA-N1Y1dmo50ynKM1KUTcnQM_5XbtPbdT_QLU,3940
180
178
  omlish/docker/manifests.py,sha256=LR4FpOGNUT3bZQ-gTjB6r_-1C3YiG30QvevZjrsVUQM,7068
181
179
  omlish/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -469,9 +467,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329
469
467
  omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
470
468
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
471
469
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
472
- omlish-0.0.0.dev111.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
473
- omlish-0.0.0.dev111.dist-info/METADATA,sha256=NOhma2BjhNWfdWwTjNisoW2NP0V3sJ2Fi75u2-IF2UE,4000
474
- omlish-0.0.0.dev111.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
475
- omlish-0.0.0.dev111.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
476
- omlish-0.0.0.dev111.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
477
- omlish-0.0.0.dev111.dist-info/RECORD,,
470
+ omlish-0.0.0.dev113.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
471
+ omlish-0.0.0.dev113.dist-info/METADATA,sha256=xC9V1ccs4B4hZjho38fd41vMPlTr4W1MFcTA9tYwTEU,4000
472
+ omlish-0.0.0.dev113.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
473
+ omlish-0.0.0.dev113.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
474
+ omlish-0.0.0.dev113.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
475
+ omlish-0.0.0.dev113.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- from .pycharm import ( # noqa
2
- PycharmRemoteDebugger,
3
- get_pycharm_version,
4
- is_pycharm_hosted,
5
- pycharm_remote_debugger_attach,
6
- read_darwin_pycharm_info_plist,
7
- )
@@ -1,46 +0,0 @@
1
- import inspect
2
- import os.path
3
- import subprocess
4
- import tempfile
5
-
6
- from ... import argparse as ap
7
- from .pycharm import get_pycharm_version
8
-
9
-
10
- class Cli(ap.Cli):
11
- @ap.command()
12
- def version(self) -> None:
13
- print(get_pycharm_version())
14
-
15
- @ap.command(
16
- ap.arg('python-exe'),
17
- ap.arg('args', nargs=ap.REMAINDER),
18
- )
19
- def runhack(self) -> int:
20
- if not os.path.isfile(exe := self.args.python_exe):
21
- raise FileNotFoundError(exe)
22
-
23
- from .._pycharm import runhack
24
- src = inspect.getsource(runhack)
25
-
26
- src_file = tempfile.mktemp(__package__ + '-runhack') # noqa
27
- with open(src_file, 'w') as f:
28
- f.write(src)
29
-
30
- proc = subprocess.run([exe, src_file, *self.args.args], check=False)
31
- return proc.returncode
32
-
33
-
34
- def _main() -> None:
35
- Cli().call_and_exit()
36
-
37
-
38
- # @omlish-manifest
39
- _CLI_MODULE = {'$omdev.cli.types.CliModule': {
40
- 'cmd_name': 'pycharm',
41
- 'mod_name': __name__,
42
- }}
43
-
44
-
45
- if __name__ == '__main__':
46
- _main()