omlish 0.0.0.dev112__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/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev112'
2
- __revision__ = 'b12f9a554e6b2fb475bd820af89e0860c0b46215'
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
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev112
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
1
  omlish/.manifests.json,sha256=CxGnj-UiRPlZgmgWoovDWrOnqpSEmBy_kqA7cdfSA3w,1431
2
- omlish/__about__.py,sha256=DGyL6xk-FSlgo5rE4puw2-MQAqKILCVboGjEq38_1Ek,3352
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,12 +151,12 @@ 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
158
  omlish/diag/pycharm.py,sha256=7-r_F-whXt8v-0dehxAX-MeMFPM3iZXX9IfeL0GfUtk,4643
159
- omlish/diag/pydevd.py,sha256=tHI0fc2ZaYKudUWTRuUe5B66qGeNktPC49ZKb8x0rSY,7298
159
+ omlish/diag/pydevd.py,sha256=z9cy0fdmGkQf2fYKmOdAt6oPMBNMKXbz0XxK6capldI,7178
160
160
  omlish/diag/threads.py,sha256=1-x02VCDZ407gfbtXm1pWK-ubqhqfePm9PMqkHCVoqk,3642
161
161
  omlish/diag/_pycharm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
162
162
  omlish/diag/_pycharm/runhack.py,sha256=eJlaUXIcFzAjOop_793RwNS_KF9NmhLv0i22xRVVeo0,34951
@@ -467,9 +467,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329
467
467
  omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
468
468
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
469
469
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
470
- omlish-0.0.0.dev112.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
471
- omlish-0.0.0.dev112.dist-info/METADATA,sha256=INYzO7o12uhwfL_sfYgGb5QZrhHz6hTkQq8eby0_zrY,4000
472
- omlish-0.0.0.dev112.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
473
- omlish-0.0.0.dev112.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
474
- omlish-0.0.0.dev112.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
475
- omlish-0.0.0.dev112.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,,