dycw-utilities 0.174.3__py3-none-any.whl → 0.174.5__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dycw-utilities
3
- Version: 0.174.3
3
+ Version: 0.174.5
4
4
  Author: Derek Wan
5
5
  Author-email: Derek Wan <d.wan@icloud.com>
6
6
  Requires-Dist: atomicwrites>=1.4.1,<1.5
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=l_p1vPbF4nOs4tHjj2e93HKXxeAoQ_-FUBDK_Tm0K0I,60
1
+ utilities/__init__.py,sha256=HSEHPwrjbITUKM0rHSI676yh7VgQMNCB5ksk8o1Hb8M,60
2
2
  utilities/aeventkit.py,sha256=OmDBhYGgbsKrB7cdC5FFpJHUatX9O76eTeKVVTksp2Y,12673
3
3
  utilities/altair.py,sha256=rUK99g9x6CYDDfiZrf-aTx5fSRbL1Q8ctgKORowzXHg,9060
4
4
  utilities/asyncio.py,sha256=aJySVxBY0gqsIYnoNmH7-1r8djKuf4vSsU69VCD08t8,16772
@@ -12,7 +12,7 @@ utilities/contextvars.py,sha256=J8OhC7jqozAGYOCe2KUWysbPXNGe5JYz3HfaY_mIs08,883
12
12
  utilities/cryptography.py,sha256=5PFrzsNUGHay91dFgYnDKwYprXxahrBqztmUqViRzBk,956
13
13
  utilities/cvxpy.py,sha256=Rv1-fD-XYerosCavRF8Pohop2DBkU3AlFaGTfD8AEAA,13776
14
14
  utilities/dataclasses.py,sha256=xbU3QN1GFy7RC6hIJRZIeUZm7YRlodrgEWmahWG6k2g,32465
15
- utilities/docker.py,sha256=bLMXK1WCCoyVg92Yc4BNfaCXMaCIHRKEvqL2DiHTX4s,7270
15
+ utilities/docker.py,sha256=DBgSz-UPBDHk_XJLPNaNMkNym1kKK8l3Os8IqMwEyW8,7866
16
16
  utilities/enum.py,sha256=5l6pwZD1cjSlVW4ss-zBPspWvrbrYrdtJWcg6f5_J5w,5781
17
17
  utilities/errors.py,sha256=mFlDGSM0LI1jZ1pbqwLAH3ttLZ2JVIxyZLojw8tGVZU,1479
18
18
  utilities/fastapi.py,sha256=TqyKvBjiMS594sXPjrz-KRTLMb3l3D3rZ1zAYV7GfOk,1454
@@ -80,14 +80,14 @@ utilities/sqlalchemy.py,sha256=HQYpd7LFxdTF5WYVWYtCJeEBI71EJm7ytvCGyAH9B-U,37163
80
80
  utilities/sqlalchemy_polars.py,sha256=JCGhB37raSR7fqeWV5dTsciRTMVzIdVT9YSqKT0piT0,13370
81
81
  utilities/statsmodels.py,sha256=koyiBHvpMcSiBfh99wFUfSggLNx7cuAw3rwyfAhoKpQ,3410
82
82
  utilities/string.py,sha256=shmBK87zZwzGyixuNuXCiUbqzfeZ9xlrFwz6JTaRvDk,582
83
- utilities/subprocess.py,sha256=FlE_SWoA6nUCTR7CregeXtjM6xtqNuuT9y6hqgnb8ZY,15407
83
+ utilities/subprocess.py,sha256=r91VteJ7I1upuiWxRT2kvm17xffS5eXMZ3CJXdmZT4s,15686
84
84
  utilities/tempfile.py,sha256=Lx6qa16lL1XVH6WdmD_G9vlN6gLI8nrIurxmsFkPKvg,3022
85
85
  utilities/testbook.py,sha256=j1KmaVbrX9VrbeMgtPh5gk55myAsn3dyRUn7jGbPbRk,1294
86
86
  utilities/text.py,sha256=7SvwcSR2l_5cOrm1samGnR4C-ZI6qyFLHLzSpO1zeHQ,13958
87
87
  utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
88
88
  utilities/timer.py,sha256=BGlwEVznx67scuLOUohyWJ4d5rTnwtk-IR4yLXFiNfo,2574
89
89
  utilities/traceback.py,sha256=B_sc0TRUv-mGDnF-ek05nbqjmBiHr3-wvxliAqIF5hI,9608
90
- utilities/types.py,sha256=IlRrCtPdLkGYVfpe-QIg2qNUgBr8OJNN7BhTKxnhh-M,18817
90
+ utilities/types.py,sha256=UwxYajRnupKTCnzReaYWYqtKdpIPeSO-d97Wu4bLEq8,18878
91
91
  utilities/typing.py,sha256=xuR8LxzjD-XlSftTM3TNvGVdQyV1mzpdwWdDMzWwCPE,25310
92
92
  utilities/tzdata.py,sha256=fgNVj66yUbCSI_-vrRVzSD3gtf-L_8IEJEPjP_Jel5Y,266
93
93
  utilities/tzlocal.py,sha256=KyCXEgCTjqGFx-389JdTuhMRUaT06U1RCMdWoED-qro,728
@@ -97,7 +97,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
97
97
  utilities/whenever.py,sha256=F4ek0-OBWxHYrZdmoZt76N2RnNyKY5KrEHt7rqO4AQE,60183
98
98
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
99
99
  utilities/zoneinfo.py,sha256=tdIScrTB2-B-LH0ukb1HUXKooLknOfJNwHk10MuMYvA,3619
100
- dycw_utilities-0.174.3.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
101
- dycw_utilities-0.174.3.dist-info/entry_points.txt,sha256=ykGI1ArwOPHqm2g5Cqh3ENdMxEej_a_FcOUov5EM5Oc,155
102
- dycw_utilities-0.174.3.dist-info/METADATA,sha256=XSqrLMadX1FSoqYHcNS8LSzYZ0eTrmXvGWWQk72wVhM,1709
103
- dycw_utilities-0.174.3.dist-info/RECORD,,
100
+ dycw_utilities-0.174.5.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
101
+ dycw_utilities-0.174.5.dist-info/entry_points.txt,sha256=ykGI1ArwOPHqm2g5Cqh3ENdMxEej_a_FcOUov5EM5Oc,155
102
+ dycw_utilities-0.174.5.dist-info/METADATA,sha256=qYrj2g20dkkvXEdb1v43eAPpIoIS2vJOu4nM5QEFG54,1709
103
+ dycw_utilities-0.174.5.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.174.3"
3
+ __version__ = "0.174.5"
utilities/docker.py CHANGED
@@ -5,6 +5,7 @@ from pathlib import Path
5
5
  from typing import TYPE_CHECKING, Literal, overload
6
6
 
7
7
  from utilities.errors import ImpossibleCaseError
8
+ from utilities.logging import to_logger
8
9
  from utilities.subprocess import (
9
10
  MKTEMP_DIR_CMD,
10
11
  maybe_sudo_cmd,
@@ -17,7 +18,7 @@ from utilities.subprocess import (
17
18
  if TYPE_CHECKING:
18
19
  from collections.abc import Iterator
19
20
 
20
- from utilities.types import LoggerLike, PathLike, StrStrMapping
21
+ from utilities.types import LoggerLike, PathLike, Retry, StrStrMapping
21
22
 
22
23
 
23
24
  @overload
@@ -106,6 +107,7 @@ def docker_exec(
106
107
  return_: Literal[True],
107
108
  return_stdout: bool = False,
108
109
  return_stderr: bool = False,
110
+ retry: Retry | None = None,
109
111
  logger: LoggerLike | None = None,
110
112
  **env_kwargs: str,
111
113
  ) -> str: ...
@@ -125,6 +127,7 @@ def docker_exec(
125
127
  return_: bool = False,
126
128
  return_stdout: Literal[True],
127
129
  return_stderr: bool = False,
130
+ retry: Retry | None = None,
128
131
  logger: LoggerLike | None = None,
129
132
  **env_kwargs: str,
130
133
  ) -> str: ...
@@ -144,6 +147,7 @@ def docker_exec(
144
147
  return_: bool = False,
145
148
  return_stdout: bool = False,
146
149
  return_stderr: Literal[True],
150
+ retry: Retry | None = None,
147
151
  logger: LoggerLike | None = None,
148
152
  **env_kwargs: str,
149
153
  ) -> str: ...
@@ -163,6 +167,7 @@ def docker_exec(
163
167
  return_: Literal[False] = False,
164
168
  return_stdout: Literal[False] = False,
165
169
  return_stderr: Literal[False] = False,
170
+ retry: Retry | None = None,
166
171
  logger: LoggerLike | None = None,
167
172
  **env_kwargs: str,
168
173
  ) -> None: ...
@@ -182,6 +187,7 @@ def docker_exec(
182
187
  return_: bool = False,
183
188
  return_stdout: bool = False,
184
189
  return_stderr: bool = False,
190
+ retry: Retry | None = None,
185
191
  logger: LoggerLike | None = None,
186
192
  **env_kwargs: str,
187
193
  ) -> str | None: ...
@@ -200,6 +206,7 @@ def docker_exec(
200
206
  return_: bool = False,
201
207
  return_stdout: bool = False,
202
208
  return_stderr: bool = False,
209
+ retry: Retry | None = None,
203
210
  logger: LoggerLike | None = None,
204
211
  **env_kwargs: str,
205
212
  ) -> str | None:
@@ -222,6 +229,7 @@ def docker_exec(
222
229
  return_=return_,
223
230
  return_stdout=return_stdout,
224
231
  return_stderr=return_stderr,
232
+ retry=retry,
225
233
  logger=logger,
226
234
  )
227
235
 
@@ -253,15 +261,32 @@ def docker_exec_cmd(
253
261
 
254
262
  @contextmanager
255
263
  def yield_docker_temp_dir(
256
- container: str, /, *, user: str | None = None, logger: LoggerLike | None = None
264
+ container: str,
265
+ /,
266
+ *,
267
+ user: str | None = None,
268
+ retry: Retry | None = None,
269
+ logger: LoggerLike | None = None,
270
+ keep: bool = False,
257
271
  ) -> Iterator[Path]:
258
272
  path = Path( # skipif-ci
259
- docker_exec(container, *MKTEMP_DIR_CMD, user=user, return_=True, logger=logger)
273
+ docker_exec(
274
+ container,
275
+ *MKTEMP_DIR_CMD,
276
+ user=user,
277
+ return_=True,
278
+ retry=retry,
279
+ logger=logger,
280
+ )
260
281
  )
261
282
  try: # skipif-ci
262
283
  yield path
263
284
  finally: # skipif-ci
264
- docker_exec(container, *rm_cmd(path), user=user, logger=logger)
285
+ if keep:
286
+ if logger is not None:
287
+ to_logger(logger).info("Keeping temporary directory '%s'...", path)
288
+ else:
289
+ docker_exec(container, *rm_cmd(path), user=user, retry=retry, logger=logger)
265
290
 
266
291
 
267
292
  __all__ = ["docker_cp_cmd", "docker_exec", "docker_exec_cmd", "yield_docker_temp_dir"]
utilities/subprocess.py CHANGED
@@ -13,22 +13,24 @@ from typing import IO, TYPE_CHECKING, Literal, assert_never, overload
13
13
  from utilities.errors import ImpossibleCaseError
14
14
  from utilities.logging import to_logger
15
15
  from utilities.text import strip_and_dedent
16
- from utilities.types import Delta
17
16
  from utilities.whenever import to_seconds
18
17
 
19
18
  if TYPE_CHECKING:
20
19
  from collections.abc import Iterator
21
20
 
22
- from utilities.types import LoggerLike, PathLike, StrMapping, StrStrMapping
21
+ from utilities.types import LoggerLike, PathLike, Retry, StrMapping, StrStrMapping
23
22
 
24
23
 
25
- type _Retry = tuple[int, Delta | None]
26
24
  _HOST_KEY_ALGORITHMS = ["ssh-ed25519"]
27
25
  BASH_LC = ["bash", "-lc"]
28
26
  BASH_LS = ["bash", "-ls"]
29
27
  MKTEMP_DIR_CMD = ["mktemp", "-d"]
30
28
 
31
29
 
30
+ def cp_cmd(src: PathLike, dest: PathLike, /) -> list[str]:
31
+ return ["cp", "-r", str(src), str(dest)]
32
+
33
+
32
34
  def echo_cmd(text: str, /) -> list[str]:
33
35
  return ["echo", text]
34
36
 
@@ -62,6 +64,10 @@ def mkdir_cmd(path: PathLike, /, *, parent: bool = False) -> list[str]:
62
64
  return ["mkdir", "-p", str(path_use)]
63
65
 
64
66
 
67
+ def mv_cmd(src: PathLike, dest: PathLike, /) -> list[str]:
68
+ return ["mv", str(src), str(dest)]
69
+
70
+
65
71
  def rm_cmd(path: PathLike, /) -> list[str]:
66
72
  return ["rm", "-rf", str(path)]
67
73
 
@@ -83,7 +89,7 @@ def run(
83
89
  return_: Literal[True],
84
90
  return_stdout: bool = False,
85
91
  return_stderr: bool = False,
86
- retry: _Retry | None = None,
92
+ retry: Retry | None = None,
87
93
  logger: LoggerLike | None = None,
88
94
  ) -> str: ...
89
95
  @overload
@@ -103,7 +109,7 @@ def run(
103
109
  return_: bool = False,
104
110
  return_stdout: Literal[True],
105
111
  return_stderr: bool = False,
106
- retry: _Retry | None = None,
112
+ retry: Retry | None = None,
107
113
  logger: LoggerLike | None = None,
108
114
  ) -> str: ...
109
115
  @overload
@@ -123,7 +129,7 @@ def run(
123
129
  return_: bool = False,
124
130
  return_stdout: bool = False,
125
131
  return_stderr: Literal[True],
126
- retry: _Retry | None = None,
132
+ retry: Retry | None = None,
127
133
  logger: LoggerLike | None = None,
128
134
  ) -> str: ...
129
135
  @overload
@@ -143,7 +149,7 @@ def run(
143
149
  return_: Literal[False] = False,
144
150
  return_stdout: Literal[False] = False,
145
151
  return_stderr: Literal[False] = False,
146
- retry: _Retry | None = None,
152
+ retry: Retry | None = None,
147
153
  logger: LoggerLike | None = None,
148
154
  ) -> None: ...
149
155
  @overload
@@ -163,7 +169,7 @@ def run(
163
169
  return_: bool = False,
164
170
  return_stdout: bool = False,
165
171
  return_stderr: bool = False,
166
- retry: _Retry | None = None,
172
+ retry: Retry | None = None,
167
173
  logger: LoggerLike | None = None,
168
174
  ) -> str | None: ...
169
175
  def run(
@@ -182,7 +188,7 @@ def run(
182
188
  return_: bool = False,
183
189
  return_stdout: bool = False,
184
190
  return_stderr: bool = False,
185
- retry: _Retry | None = None,
191
+ retry: Retry | None = None,
186
192
  logger: LoggerLike | None = None,
187
193
  ) -> str | None:
188
194
  args: list[str] = []
@@ -337,7 +343,7 @@ def ssh(
337
343
  return_: Literal[True],
338
344
  return_stdout: bool = False,
339
345
  return_stderr: bool = False,
340
- retry: _Retry | None = None,
346
+ retry: Retry | None = None,
341
347
  logger: LoggerLike | None = None,
342
348
  ) -> str: ...
343
349
  @overload
@@ -356,7 +362,7 @@ def ssh(
356
362
  return_: bool = False,
357
363
  return_stdout: Literal[True],
358
364
  return_stderr: bool = False,
359
- retry: _Retry | None = None,
365
+ retry: Retry | None = None,
360
366
  logger: LoggerLike | None = None,
361
367
  ) -> str: ...
362
368
  @overload
@@ -375,7 +381,7 @@ def ssh(
375
381
  return_: bool = False,
376
382
  return_stdout: bool = False,
377
383
  return_stderr: Literal[True],
378
- retry: _Retry | None = None,
384
+ retry: Retry | None = None,
379
385
  logger: LoggerLike | None = None,
380
386
  ) -> str: ...
381
387
  @overload
@@ -394,7 +400,7 @@ def ssh(
394
400
  return_: Literal[False] = False,
395
401
  return_stdout: Literal[False] = False,
396
402
  return_stderr: Literal[False] = False,
397
- retry: _Retry | None = None,
403
+ retry: Retry | None = None,
398
404
  logger: LoggerLike | None = None,
399
405
  ) -> None: ...
400
406
  @overload
@@ -413,7 +419,7 @@ def ssh(
413
419
  return_: bool = False,
414
420
  return_stdout: bool = False,
415
421
  return_stderr: bool = False,
416
- retry: _Retry | None = None,
422
+ retry: Retry | None = None,
417
423
  logger: LoggerLike | None = None,
418
424
  ) -> str | None: ...
419
425
  def ssh(
@@ -431,7 +437,7 @@ def ssh(
431
437
  return_: bool = False,
432
438
  return_stdout: bool = False,
433
439
  return_stderr: bool = False,
434
- retry: _Retry | None = None,
440
+ retry: Retry | None = None,
435
441
  logger: LoggerLike | None = None,
436
442
  ) -> str | None:
437
443
  cmd_and_args = ssh_cmd( # skipif-ci
@@ -484,9 +490,17 @@ def touch_cmd(path: PathLike, /) -> list[str]:
484
490
 
485
491
  @contextmanager
486
492
  def yield_ssh_temp_dir(
487
- user: str, hostname: str, /, *, keep: bool = False, logger: LoggerLike | None = None
493
+ user: str,
494
+ hostname: str,
495
+ /,
496
+ *,
497
+ retry: Retry | None = None,
498
+ logger: LoggerLike | None = None,
499
+ keep: bool = False,
488
500
  ) -> Iterator[Path]:
489
- path = Path(ssh(user, hostname, *MKTEMP_DIR_CMD, return_=True))
501
+ path = Path(
502
+ ssh(user, hostname, *MKTEMP_DIR_CMD, return_=True, retry=retry, logger=logger)
503
+ )
490
504
  try:
491
505
  yield path
492
506
  finally:
@@ -494,18 +508,20 @@ def yield_ssh_temp_dir(
494
508
  if logger is not None:
495
509
  to_logger(logger).info("Keeping temporary directory '%s'...", path)
496
510
  else:
497
- ssh(user, hostname, *rm_cmd(path))
511
+ ssh(user, hostname, *rm_cmd(path), retry=retry, logger=logger)
498
512
 
499
513
 
500
514
  __all__ = [
501
515
  "BASH_LC",
502
516
  "BASH_LS",
503
517
  "MKTEMP_DIR_CMD",
518
+ "cp_cmd",
504
519
  "echo_cmd",
505
520
  "expand_path",
506
521
  "maybe_sudo_cmd",
507
522
  "mkdir",
508
523
  "mkdir_cmd",
524
+ "mv_cmd",
509
525
  "rm_cmd",
510
526
  "run",
511
527
  "ssh",
utilities/types.py CHANGED
@@ -231,6 +231,10 @@ type Seed = int | float | str | bytes | bytearray | Random
231
231
  type PatternLike = MaybeStr[Pattern[str]]
232
232
 
233
233
 
234
+ # retry
235
+ type Retry = tuple[int, Delta | None]
236
+
237
+
234
238
  # text
235
239
  type MaybeCallableStr = MaybeCallable[str]
236
240
 
@@ -332,6 +336,7 @@ __all__ = [
332
336
  "PathLike",
333
337
  "PatternLike",
334
338
  "PlainDateTimeLike",
339
+ "Retry",
335
340
  "Seed",
336
341
  "SequenceStr",
337
342
  "SerializeObjectExtra",