omlish 0.0.0.dev95__py3-none-any.whl → 0.0.0.dev97__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev95'
2
- __revision__ = '40763ed67700ccfb9317c5f357737baadbc16159'
1
+ __version__ = '0.0.0.dev97'
2
+ __revision__ = '4adbb70454ff03be6ca98d986f768deff72e6e7f'
3
3
 
4
4
 
5
5
  #
omlish/bootstrap/diag.py CHANGED
@@ -169,17 +169,12 @@ class TimebombBootstrap(ContextBootstrap['TimebombBootstrap.Config']):
169
169
  class PycharmBootstrap(SimpleBootstrap['PycharmBootstrap.Config']):
170
170
  @dc.dataclass(frozen=True)
171
171
  class Config(Bootstrap.Config):
172
- debug_host: ta.Optional[str] = None
173
- debug_port: ta.Optional[int] = None
174
- version: ta.Optional[str] = None
172
+ debug: ta.Optional[str] = None
175
173
 
176
174
  def run(self) -> None:
177
- if self._config.debug_port is not None:
178
- diagpc.pycharm_remote_debugger_attach(
179
- self._config.debug_host,
180
- self._config.debug_port,
181
- version=self._config.version,
182
- )
175
+ if self._config.debug is not None:
176
+ prd = diagpc.PycharmRemoteDebugger.parse(self._config.debug)
177
+ diagpc.pycharm_remote_debugger_attach(prd)
183
178
 
184
179
 
185
180
  ##
@@ -1,4 +1,5 @@
1
1
  from .pycharm import ( # noqa
2
+ PycharmRemoteDebugger,
2
3
  get_pycharm_version,
3
4
  is_pycharm_hosted,
4
5
  pycharm_remote_debugger_attach,
@@ -1,5 +1,7 @@
1
+ import dataclasses as dc
1
2
  import os.path
2
3
  import plistlib
4
+ import re
3
5
  import subprocess
4
6
  import sys
5
7
  import typing as ta
@@ -106,12 +108,33 @@ def _import_pydevd_pycharm(*, version: str | None = None) -> ta.Any:
106
108
  return pydevd_pycharm
107
109
 
108
110
 
109
- def pycharm_remote_debugger_attach(
110
- host: str | None,
111
- port: int,
112
- *,
113
- version: str | None = None,
114
- ) -> None:
111
+ @dc.dataclass(frozen=True)
112
+ class PycharmRemoteDebugger:
113
+ host: str | None
114
+ port: int
115
+ version: str | None = None
116
+
117
+ def __str__(self) -> str:
118
+ return ''.join([
119
+ f'@{self.version}:' if self.version is not None else '',
120
+ f'{self.host}:' if self.host is not None else '',
121
+ str(self.port),
122
+ ])
123
+
124
+ @classmethod
125
+ def parse(cls, s: str) -> 'PycharmRemoteDebugger':
126
+ if (m := re.fullmatch(r'(@(?P<version>[^:]+):)?((?P<host>[^:]+):)?(?P<port>\d+)', s)) is None:
127
+ raise ValueError(s)
128
+ gd = m.groupdict()
129
+ return cls(
130
+ host=gd.get('host'),
131
+ port=int(gd['port']),
132
+ version=gd.get('version'),
133
+ )
134
+
135
+
136
+ def pycharm_remote_debugger_attach(prd: PycharmRemoteDebugger) -> None:
137
+ host = prd.host
115
138
  if host is None:
116
139
  if (
117
140
  sys.platform == 'linux' and
@@ -122,6 +145,7 @@ def pycharm_remote_debugger_attach(
122
145
  else:
123
146
  host = 'localhost'
124
147
 
148
+ version = prd.version
125
149
  if version is None and host in ('localhost', '127.0.0.1'):
126
150
  version = get_pycharm_version()
127
151
 
@@ -132,7 +156,7 @@ def pycharm_remote_debugger_attach(
132
156
 
133
157
  pydevd_pycharm.settrace(
134
158
  host,
135
- port=port,
159
+ port=prd.port,
136
160
  stdoutToServer=True,
137
161
  stderrToServer=True,
138
162
  )
omlish/term.py CHANGED
@@ -1,10 +1,18 @@
1
1
  import enum
2
2
  import re
3
+ import sys
4
+ import time
3
5
  import typing as ta
4
6
 
5
7
  from . import lang
6
8
 
7
9
 
10
+ T = ta.TypeVar('T')
11
+
12
+
13
+ ##
14
+
15
+
8
16
  ESC = '\x1b'
9
17
  BEL = '\x07'
10
18
 
@@ -207,6 +215,136 @@ BG24_RGB = ControlSequence(
207
215
  lambda r, g, b: CSI + '48;2;' + str(r) + ';' + str(g) + ';' + str(b) + 'm',
208
216
  '24-Bit Background Color (RGB)')
209
217
 
218
+ ##
219
+
220
+
221
+ class ProgressBar:
222
+ """
223
+ TODO:
224
+ - ProgressBarRenderer
225
+ - right-justify
226
+ - ProgressBarGroup
227
+ - animate
228
+ """
229
+
230
+ def __init__(
231
+ self,
232
+ total: int | None = None,
233
+ *,
234
+ length: int = 40,
235
+ interval: float = .2,
236
+ start_time: float | None = None,
237
+ out: ta.TextIO | None = None,
238
+ ) -> None:
239
+ super().__init__()
240
+
241
+ self._total = total
242
+ self._length = length
243
+ self._interval = interval
244
+ if start_time is None:
245
+ start_time = time.time()
246
+ self._start_time = start_time
247
+ if out is None:
248
+ out = sys.stdout
249
+ self._out = out
250
+
251
+ self._i = 0
252
+ self._elapsed = 0.
253
+ self._last_print = 0.
254
+
255
+ def render(
256
+ self,
257
+ *,
258
+ complete: bool = False,
259
+ ) -> str:
260
+ iter_per_sec = self._i / self._elapsed if self._elapsed > 0 else 0
261
+
262
+ if self._total is not None:
263
+ remaining = (self._total - self._i) / iter_per_sec if iter_per_sec > 0 else 0
264
+ done = int(self._length * self._i / self._total)
265
+
266
+ bar = f'[{"█" * done}{"." * (self._length - done)}]'
267
+ info_parts = [
268
+ f'{self._i}/{self._total}',
269
+ f'{iter_per_sec:.2f} it/s',
270
+ f'{self._elapsed:.2f}s elapsed',
271
+ f'{remaining:.2f}s left',
272
+ ]
273
+
274
+ else:
275
+ bar = f'[{("█" if complete else "?") * self._length}]'
276
+ info_parts = [
277
+ f'{self._i}',
278
+ f'{iter_per_sec:.2f} it/s',
279
+ f'{self._elapsed:.2f}s elapsed',
280
+ ]
281
+
282
+ info = ' | '.join(info_parts)
283
+ return f'{bar} {info}'
284
+
285
+ def print(
286
+ self,
287
+ *,
288
+ now: float | None = None,
289
+ **kwargs: ta.Any,
290
+ ) -> None:
291
+ if now is None:
292
+ now = time.time()
293
+
294
+ line = self.render(**kwargs)
295
+ self._out.write(f'\033[2K\033[G{line}')
296
+ self._out.flush()
297
+
298
+ self._last_print = now
299
+
300
+ def update(
301
+ self,
302
+ n: int = 1,
303
+ *,
304
+ now: float | None = None,
305
+ silent: bool = False,
306
+ ) -> None:
307
+ if now is None:
308
+ now = time.time()
309
+
310
+ self._i += n
311
+ self._elapsed = now - self._start_time
312
+
313
+ if not silent:
314
+ if now - self._last_print >= self._interval:
315
+ self.print(now=now)
316
+
317
+
318
+ def progress_bar(
319
+ seq: ta.Iterable[T],
320
+ *,
321
+ no_tty_check: bool = False,
322
+ total: int | None = None,
323
+ **kwargs: ta.Any,
324
+ ) -> ta.Generator[T, None, None]:
325
+ if not no_tty_check and not sys.stdout.isatty():
326
+ yield from seq
327
+ return
328
+
329
+ if total is None:
330
+ if isinstance(seq, ta.Sized):
331
+ total = len(seq)
332
+
333
+ pb = ProgressBar(
334
+ total=total,
335
+ **kwargs,
336
+ )
337
+
338
+ for item in seq:
339
+ pb.update()
340
+ yield item
341
+
342
+ pb.print(complete=True)
343
+ sys.stdout.write('\n')
344
+
345
+
346
+ ##
347
+
210
348
 
211
349
  def main() -> None:
212
350
  import sys
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev95
3
+ Version: 0.0.0.dev97
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=hTFp9tvE72BxKloIq1s1SS0LRQlIsvMtO69Sbc47rKg,1704
2
- omlish/__about__.py,sha256=CrlzN0XqTgVfMvKp_IYNBS-xeNlXgZLdXijAy8GS_kY,3345
2
+ omlish/__about__.py,sha256=eIwAtZZmvmulh4BBWUEeTYaDxG6LjN2S_3Q71pIDNfI,3345
3
3
  omlish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  omlish/argparse.py,sha256=Dc73G8lyoQBLvXhMYUbzQUh4SJu_OTvKUXjSUxq_ang,7499
5
5
  omlish/c3.py,sha256=4vogWgwPb8TbNS2KkZxpoWbwjj7MuHG2lQG-hdtkvjI,8062
@@ -18,7 +18,7 @@ omlish/multiprocessing.py,sha256=QZT4C7I-uThCAjaEY3xgUYb-5GagUlnE4etN01LDyU4,518
18
18
  omlish/os.py,sha256=5nJ-a9JKSMoaZVZ1eOa5BAbfL7o7CF7ue_PyJwufnwY,1460
19
19
  omlish/runmodule.py,sha256=PWvuAaJ9wQQn6bx9ftEL3_d04DyotNn8dR_twm2pgw0,700
20
20
  omlish/sync.py,sha256=AqwIfIuCMVHLwlJUa7dmaSjfA4sM5AYPCD5-nsz3XVQ,1516
21
- omlish/term.py,sha256=NEmxqAhicyInGtmFamZAizI2xdu819MzFYPEp0Fx97M,6111
21
+ omlish/term.py,sha256=pgzEZ8FigEvaaRK38N4HhPSI-M9GOYIXy3XLu_CSROc,9197
22
22
  omlish/antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  omlish/antlr/_runtime/BufferedTokenStream.py,sha256=1Rnhm62MZCWSuQeRs7lRUbdtdyo7Gyg8r4gAETjv-cE,10793
24
24
  omlish/antlr/_runtime/CommonTokenFactory.py,sha256=QrSSTH0gYhOpPeOHqrs6-2g1PGcgYvjhR6J6pynKLOc,2147
@@ -89,7 +89,7 @@ omlish/asyncs/trio_asyncio.py,sha256=oqdOHy0slj9PjVxaDf3gJkq9AAgg7wYZbB469jOftVw
89
89
  omlish/bootstrap/__init__.py,sha256=-Rtsg7uPQNhh1dIT9nqrz96XlqizwoLnWf-FwOEstJI,730
90
90
  omlish/bootstrap/__main__.py,sha256=4jCwsaogp0FrJjJZ85hzF4-WqluPeheHbfeoKynKvNs,194
91
91
  omlish/bootstrap/base.py,sha256=d8hqn4hp1XMMi5PgcJBQXPKmW47epu8CxBlqDZiRZb4,1073
92
- omlish/bootstrap/diag.py,sha256=LADLhusbJ1tKxVD8-gmia1HShX1VeszRO1OApIQhSpI,5507
92
+ omlish/bootstrap/diag.py,sha256=iemH0nQEHEDzyZztvd_ygGGVpRpgn5UG6naxeQTvXp0,5347
93
93
  omlish/bootstrap/harness.py,sha256=VW8YP-yENGyXIuJ8GL_xintArF13nafwpz-iAghPt34,1967
94
94
  omlish/bootstrap/main.py,sha256=yZhOHDDlj4xB5a89dRdT8z58FsqqnpoBg1-tvY2CJe4,5903
95
95
  omlish/bootstrap/marshal.py,sha256=ZxdAeMNd2qXRZ1HUK89HmEhz8tqlS9OduW34QBscKw0,516
@@ -159,9 +159,9 @@ omlish/diag/pydevd.py,sha256=tHI0fc2ZaYKudUWTRuUe5B66qGeNktPC49ZKb8x0rSY,7298
159
159
  omlish/diag/threads.py,sha256=1-x02VCDZ407gfbtXm1pWK-ubqhqfePm9PMqkHCVoqk,3642
160
160
  omlish/diag/_pycharm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
161
161
  omlish/diag/_pycharm/runhack.py,sha256=eJlaUXIcFzAjOop_793RwNS_KF9NmhLv0i22xRVVeo0,34951
162
- omlish/diag/pycharm/__init__.py,sha256=sT-ub7flKeCCbM_i32z9-eGV8hgGJ45hwdcqtGDkVRY,153
162
+ omlish/diag/pycharm/__init__.py,sha256=-hZryZ3RfuoH4arwhBl-RmCZ6j-ybuUIEUf9C8o37iY,180
163
163
  omlish/diag/pycharm/cli.py,sha256=7SRh6yj8S5YGda4bq9BD4Kzwtgg4_Wa-K202ReZN2iI,1011
164
- omlish/diag/pycharm/pycharm.py,sha256=g-IfF8FBH93o6k_KDrLy8kIiFSLe3n39I2URipfFy0Q,3115
164
+ omlish/diag/pycharm/pycharm.py,sha256=GFcnkNedY3bbwRM3l7_9lFiaW9BcxOB0KZl01Nk_xPs,3854
165
165
  omlish/diag/replserver/__init__.py,sha256=uLo6V2aQ29v9z3IMELlPDSlG3_2iOT4-_X8VniF-EgE,235
166
166
  omlish/diag/replserver/__main__.py,sha256=LmU41lQ58bm1h4Mx7S8zhE_uEBSC6kPcp9mn5JRpulA,32
167
167
  omlish/diag/replserver/console.py,sha256=XzBDVhYlr8FY6ym4OwoaIHuFOHnGK3dTYlMDIOMUUlA,7410
@@ -457,9 +457,9 @@ omlish/text/delimit.py,sha256=ubPXcXQmtbOVrUsNh5gH1mDq5H-n1y2R4cPL5_DQf68,4928
457
457
  omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,3296
458
458
  omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
459
459
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
460
- omlish-0.0.0.dev95.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
461
- omlish-0.0.0.dev95.dist-info/METADATA,sha256=PTGAL5lZAs2yviTLTiaEtMx1B4hL3uInPDX8T8sWDAI,3987
462
- omlish-0.0.0.dev95.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
463
- omlish-0.0.0.dev95.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
464
- omlish-0.0.0.dev95.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
465
- omlish-0.0.0.dev95.dist-info/RECORD,,
460
+ omlish-0.0.0.dev97.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
461
+ omlish-0.0.0.dev97.dist-info/METADATA,sha256=wmMErtqPFPYd69wceqTe57xiockAvRmzLhdroKiURz4,3987
462
+ omlish-0.0.0.dev97.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
463
+ omlish-0.0.0.dev97.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
464
+ omlish-0.0.0.dev97.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
465
+ omlish-0.0.0.dev97.dist-info/RECORD,,