dycw-utilities 0.175.13__py3-none-any.whl → 0.175.15__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.175.13
3
+ Version: 0.175.15
4
4
  Summary: Miscellaneous Python utilities
5
5
  Author: Derek Wan
6
6
  Author-email: Derek Wan <d.wan@icloud.com>
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=rn68oFi0llJJbsq0IE3UHX95wFkFFAgE8pxnKhJghXs,61
1
+ utilities/__init__.py,sha256=uha69lq96VwVWN0nlW9IjESjk42aY0AznvoMolkyS1U,61
2
2
  utilities/altair.py,sha256=TLfRFbG9HwG7SLXoJ-v0r-t49ZaGgTQZD82cpjVi4vs,9085
3
3
  utilities/asyncio.py,sha256=aJySVxBY0gqsIYnoNmH7-1r8djKuf4vSsU69VCD08t8,16772
4
4
  utilities/atomicwrites.py,sha256=tPo6r-Rypd9u99u66B9z86YBPpnLrlHtwox_8Z7T34Y,5790
@@ -25,7 +25,7 @@ utilities/gzip.py,sha256=fkGP3KdsBfXlstodT4wtlp-PwNyUsogpbDCVVVGdsm4,781
25
25
  utilities/hashlib.py,sha256=SVTgtguur0P4elppvzOBbLEjVM3Pea0eWB61yg2ilxo,309
26
26
  utilities/http.py,sha256=TsavEfHlRtlLaeV21Z6KZh0qbPw-kvD1zsQdZ7Kep5Q,977
27
27
  utilities/hypothesis.py,sha256=NUu30pl5kjL3tzo-m8SMRwTqLAmTWK-_Sau2NemJcQo,46773
28
- utilities/importlib.py,sha256=mV1xT_O_zt_GnZZ36tl3xOmMaN_3jErDWY54fX39F6Y,429
28
+ utilities/importlib.py,sha256=SkVVtIjVC7bjJ36doXnmnmFiYe5tLbip4YAfYJj8Ycg,892
29
29
  utilities/inflect.py,sha256=v7YkOWSu8NAmVghPcf4F3YBZQoJCS47_DLf9jbfWIs0,581
30
30
  utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
31
31
  utilities/iterables.py,sha256=t2TsW-K3rVlS6y4_tqcc1fk9RwJV-bi7G_VwduMABK0,42558
@@ -80,7 +80,7 @@ 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=TZZ4C197fwsL71diaMID1sIfxxCOoR6aVq3RSsSRd-Y,41809
83
+ utilities/subprocess.py,sha256=NrBYeuIfQvsbebP0tY6jDPhK6upagI9aVfe6eLctxiY,42374
84
84
  utilities/tempfile.py,sha256=QyvIdfV4r4YZ0NeNYsg0tCijThLKa7Z32u5Kxy6ZsGo,3619
85
85
  utilities/testbook.py,sha256=j1KmaVbrX9VrbeMgtPh5gk55myAsn3dyRUn7jGbPbRk,1294
86
86
  utilities/text.py,sha256=7SvwcSR2l_5cOrm1samGnR4C-ZI6qyFLHLzSpO1zeHQ,13958
@@ -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.175.13.dist-info/WHEEL,sha256=RRVLqVugUmFOqBedBFAmA4bsgFcROUBiSUKlERi0Hcg,79
101
- dycw_utilities-0.175.13.dist-info/entry_points.txt,sha256=cOGtKeJI0KXLSV7MJ8Dhc2G8jPgDcBDm53MVNJU4ycI,136
102
- dycw_utilities-0.175.13.dist-info/METADATA,sha256=Qz05dYabUPFOjKVwOmKSJDAY4MDh0ZYT9oLnIShoaXo,1443
103
- dycw_utilities-0.175.13.dist-info/RECORD,,
100
+ dycw_utilities-0.175.15.dist-info/WHEEL,sha256=RRVLqVugUmFOqBedBFAmA4bsgFcROUBiSUKlERi0Hcg,79
101
+ dycw_utilities-0.175.15.dist-info/entry_points.txt,sha256=cOGtKeJI0KXLSV7MJ8Dhc2G8jPgDcBDm53MVNJU4ycI,136
102
+ dycw_utilities-0.175.15.dist-info/METADATA,sha256=hEKvIOQ5qtPfWiuWMr6PtGqv2OtWnvBmh1fTxpHvNtU,1443
103
+ dycw_utilities-0.175.15.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.175.13"
3
+ __version__ = "0.175.15"
utilities/importlib.py CHANGED
@@ -1,7 +1,23 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import importlib.resources
3
4
  from importlib import import_module
4
5
  from importlib.util import find_spec
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING
8
+
9
+ from utilities.errors import ImpossibleCaseError
10
+
11
+ if TYPE_CHECKING:
12
+ from importlib.resources import Anchor
13
+
14
+
15
+ def files(*, anchor: Anchor | None = None) -> Path:
16
+ """Get the path for an anchor."""
17
+ path = importlib.resources.files(anchor)
18
+ if isinstance(path, Path):
19
+ return path
20
+ raise ImpossibleCaseError(case=[f"{path=}"]) # pragma: no cover
5
21
 
6
22
 
7
23
  def is_valid_import(module: str, /, *, name: str | None = None) -> bool:
@@ -15,4 +31,4 @@ def is_valid_import(module: str, /, *, name: str | None = None) -> bool:
15
31
  return hasattr(mod, name)
16
32
 
17
33
 
18
- __all__ = ["is_valid_import"]
34
+ __all__ = ["files", "is_valid_import"]
utilities/subprocess.py CHANGED
@@ -22,13 +22,14 @@ from utilities.pathlib import PWD
22
22
  from utilities.permissions import Permissions, ensure_perms
23
23
  from utilities.tempfile import TemporaryDirectory
24
24
  from utilities.text import strip_and_dedent
25
- from utilities.whenever import to_seconds
25
+ from utilities.whenever import SECOND, to_seconds
26
26
 
27
27
  if TYPE_CHECKING:
28
28
  from collections.abc import Callable, Iterator
29
29
 
30
30
  from utilities.permissions import PermissionsLike
31
31
  from utilities.types import (
32
+ Delta,
32
33
  LoggerLike,
33
34
  MaybeIterable,
34
35
  PathLike,
@@ -1147,6 +1148,30 @@ def ssh_opts_cmd(
1147
1148
  ##
1148
1149
 
1149
1150
 
1151
+ def ssh_await(
1152
+ user: str,
1153
+ hostname: str,
1154
+ /,
1155
+ *,
1156
+ logger: LoggerLike | None = None,
1157
+ delta: Delta = SECOND,
1158
+ ) -> None:
1159
+ while True: # skipif-ci
1160
+ if logger is not None:
1161
+ to_logger(logger).info("Waiting for '%s'...", hostname)
1162
+ try:
1163
+ ssh(user, hostname, "true")
1164
+ except CalledProcessError:
1165
+ sleep(to_seconds(delta))
1166
+ else:
1167
+ if logger is not None:
1168
+ to_logger(logger).info("'%s' is up", hostname)
1169
+ return
1170
+
1171
+
1172
+ ##
1173
+
1174
+
1150
1175
  def ssh_keyscan(
1151
1176
  hostname: str, /, *, path: PathLike = KNOWN_HOSTS, port: int | None = None
1152
1177
  ) -> None:
@@ -1207,15 +1232,15 @@ def sudo_nopasswd_cmd(user: str, /) -> str:
1207
1232
  ##
1208
1233
 
1209
1234
 
1210
- def symlink(targret: PathLike, link: PathLike, /, *, sudo: bool = False) -> None:
1235
+ def symlink(target: PathLike, link: PathLike, /, *, sudo: bool = False) -> None:
1211
1236
  """Make a symbolic link."""
1212
1237
  rm(link, sudo=sudo)
1213
1238
  mkdir(link, sudo=sudo, parent=True)
1214
1239
  if sudo: # pragma: no cover
1215
- run(*sudo_cmd(*symlink_cmd(targret, link)))
1240
+ run(*sudo_cmd(*symlink_cmd(target, link)))
1216
1241
  else:
1217
- targret, link = map(Path, [targret, link])
1218
- link.symlink_to(targret)
1242
+ target, link = map(Path, [target, link])
1243
+ link.symlink_to(target)
1219
1244
 
1220
1245
 
1221
1246
  def symlink_cmd(target: PathLike, link: PathLike, /) -> list[str]:
@@ -1474,6 +1499,7 @@ __all__ = [
1474
1499
  "run",
1475
1500
  "set_hostname_cmd",
1476
1501
  "ssh",
1502
+ "ssh_await",
1477
1503
  "ssh_cmd",
1478
1504
  "ssh_keygen_remove",
1479
1505
  "ssh_keygen_remove_cmd",