ladyrick 0.5.3__py3-none-any.whl → 0.5.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.
ladyrick/cli/calc.py CHANGED
@@ -5,15 +5,15 @@ import sys
5
5
  def initialize(interactive_mode: bool):
6
6
  imports = {}
7
7
  exec("import ladyrick.patch.rich_print")
8
- exec("import math; from math import *", locals=imports)
9
- exec("import itertools; from itertools import *", locals=imports)
10
- exec("import functools; from functools import cache, lru_cache, partial, reduce", locals=imports)
11
- exec("import os, sys, time, re, random", locals=imports)
12
- exec("from pathlib import Path", locals=imports)
13
- exec("from time import sleep", locals=imports)
14
- exec("from subprocess import check_output", locals=imports)
15
- exec("from random import randint, choice, random as rand", locals=imports)
16
- exec("import ladyrick", locals=imports)
8
+ exec("import math; from math import *", None, imports)
9
+ exec("import itertools; from itertools import *", None, imports)
10
+ exec("import functools; from functools import cache, lru_cache, partial, reduce", None, imports)
11
+ exec("import os, sys, time, re, random", None, imports)
12
+ exec("from pathlib import Path", None, imports)
13
+ exec("from time import sleep", None, imports)
14
+ exec("from subprocess import check_output", None, imports)
15
+ exec("from random import randint, choice, random as rand", None, imports)
16
+ exec("import ladyrick", None, imports)
17
17
  if interactive_mode:
18
18
  imports["ladyrick"].pprint.reg_ipython_cmd()
19
19
  globals().update(imports)
ladyrick/cli/multi_ssh.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  import os
3
+ import re
3
4
  import select
4
5
  import signal
5
6
  import subprocess
@@ -21,7 +22,7 @@ def force_kill(child: subprocess.Popen, child_pgid):
21
22
  child.kill() # kill -9
22
23
 
23
24
 
24
- REMOTE_HEAD_PROG_NAME = "ladyrick-remote-head"
25
+ REMOTE_HEAD_PROG_NAME = "ladyrick/multi-ssh/remote-head"
25
26
 
26
27
 
27
28
  def remote_head():
@@ -51,14 +52,14 @@ def remote_head():
51
52
  def handle_signal(sig, frame=None):
52
53
  if sig == signal.SIGUSR2:
53
54
  # SIGUSR2 trigger force_kill manually
54
- log("SIGUSR2 received. force kill")
55
+ print("SIGUSR2 received. force kill")
55
56
  force_kill(child, child_pgid)
56
57
  else:
57
- log(f"forward signal {sig} to {child.pid}")
58
+ print(f"forward signal {sig} to {child.pid}")
58
59
  try:
59
60
  os.kill(child.pid, sig)
60
61
  except ProcessLookupError as e:
61
- log(str(e))
62
+ print(str(e))
62
63
 
63
64
  for sig in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM, signal.SIGUSR1, signal.SIGUSR2]:
64
65
  signal.signal(sig, handle_signal)
@@ -110,15 +111,20 @@ class Host:
110
111
 
111
112
 
112
113
  class RemoteExecutor:
113
- def __init__(self, host: Host, command: list[str]):
114
+ def __init__(self, host: Host, command: list[str], envs: dict | None = None):
114
115
  self.host = host
115
116
  self.command = command
116
117
  self.envs = {}
118
+ if envs:
119
+ for k, v in envs.items():
120
+ if not re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", k):
121
+ raise ValueError(f"invalid env name: {k!r}")
122
+ self.envs[k] = v
117
123
  self.process = None
118
124
 
119
125
  @classmethod
120
126
  def make_ssh_cmd(cls, host: Host, cmd: str):
121
- opts = ["/usr/bin/env", "ssh", "-qT", "-oStrictHostKeyChecking=no"]
127
+ opts = ["/usr/bin/env", "ssh", "-T", "-oStrictHostKeyChecking=no"]
122
128
  if host.config_file is not None:
123
129
  opts.append(f"-F{host.config_file}")
124
130
  if host.User is not None:
@@ -134,6 +140,7 @@ class RemoteExecutor:
134
140
  return opts
135
141
 
136
142
  def start(self):
143
+ assert self.process is None
137
144
  code = pathlib.Path(__file__).read_text().split("# ----- remote_head end ----- #")[0].strip()
138
145
  remote_cmd = shlex.join(
139
146
  [
@@ -185,15 +192,19 @@ class RemoteExecutor:
185
192
  e.envs["RANK"] = str(i)
186
193
 
187
194
  def send_signal(self, sig):
188
- if self.process:
195
+ assert self.process is not None
196
+ if self.process.poll() is None and self.process.stdin and not self.process.stdin.closed:
189
197
  sig_name = signal.Signals(sig).name
190
- if self.process.stdin and not self.process.stdin.closed:
191
- log(f"writing to stdin: SIGNAL {sig_name}")
192
- try:
193
- self.process.stdin.write(f"SIGNAL {sig_name}\n".encode())
194
- self.process.stdin.flush()
195
- except (BrokenPipeError, OSError) as e:
196
- log(e)
198
+ log(f"writing to stdin: SIGNAL {sig_name}")
199
+ try:
200
+ self.process.stdin.write(f"SIGNAL {sig_name}\n".encode())
201
+ self.process.stdin.flush()
202
+ except (BrokenPipeError, OSError) as e:
203
+ log(e)
204
+
205
+ def poll(self):
206
+ assert self.process is not None
207
+ return self.process.poll()
197
208
 
198
209
 
199
210
  def signal_repeat_checker(sig_to_check, count, duration):
@@ -223,6 +234,7 @@ def main():
223
234
  parser.add_argument("-l", type=str, help="ssh login User")
224
235
  parser.add_argument("-o", type=str, action="append", help="ssh options")
225
236
  parser.add_argument("-F", type=str, help="ssh config file")
237
+ parser.add_argument("-e", "--env", type=str, action="append", help="extra envs")
226
238
  parser.add_argument("--hosts-config", type=str, action="append", help="hosts config string. order is 2")
227
239
  parser.add_argument("--hosts-config-file", type=str, action="append", help="hosts config file. order is 3")
228
240
  parser.add_argument("--help", action="help", default=argparse.SUPPRESS, help="show this help message and exit")
@@ -263,7 +275,15 @@ def main():
263
275
  parser.print_help()
264
276
  sys.exit(1)
265
277
 
266
- executors = [RemoteExecutor(host, args.cmd) for host in hosts]
278
+ envs = {}
279
+ if args.env:
280
+ for e in args.env:
281
+ p = e.split("=", 1)
282
+ if len(p) == 1:
283
+ p.append("")
284
+ envs[p[0]] = p[1]
285
+
286
+ executors = [RemoteExecutor(host, args.cmd, envs) for host in hosts]
267
287
 
268
288
  RemoteExecutor.set_envs(executors)
269
289
 
@@ -284,7 +304,7 @@ def main():
284
304
  for sig in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM, signal.SIGUSR1, signal.SIGUSR2]:
285
305
  signal.signal(sig, handle_signal)
286
306
 
287
- while any(e.process.poll() is None for e in executors if e.process):
307
+ while any([e.poll() is None for e in executors if e.process]):
288
308
  time.sleep(0.5)
289
309
  log("finished")
290
310
 
@@ -5,8 +5,8 @@ import time
5
5
 
6
6
  def handle_signal(sig, frame):
7
7
  print(f"received signal {sig}, {signal.Signals(sig).name}", flush=True)
8
- if sig in {signal.SIGTERM, signal.SIGINT, signal.SIGHUP}:
9
- sys.exit(0)
8
+ # if sig in {signal.SIGTERM, signal.SIGINT, signal.SIGHUP}:
9
+ # sys.exit(0)
10
10
 
11
11
 
12
12
  for sig in [s for s in vars(signal).values() if isinstance(s, signal.Signals)]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ladyrick
3
- Version: 0.5.3
3
+ Version: 0.5.5
4
4
  Summary: ladyrick's tools
5
5
  Author-email: ladyrick <ladyrick@qq.com>
6
6
  License-Expression: MIT
@@ -9,21 +9,21 @@ ladyrick/torch.py,sha256=CEdHYaOZ00StZettf4MoIB3tMF0fbzSIH-3pOqOMIZM,1977
9
9
  ladyrick/typing.py,sha256=YQeApe63dk7yL4NS5ytlR6v3dLCii2-qsXNlUvjK-zw,203
10
10
  ladyrick/utils.py,sha256=jRRaqC6kNbCJPGeE0YisFgis-wiuINLik1mcUQtytow,608
11
11
  ladyrick/vars.py,sha256=VbFh2u7XybUaBuiYEXBa4sOmoS99vc2AIXdYLBh8vjk,3763
12
- ladyrick/cli/calc.py,sha256=szg4dyCOsWHNGKPcBcL3Tg4dCCZzBFiGow1O98pyxH4,1447
13
- ladyrick/cli/multi_ssh.py,sha256=faRIgradz3e6ZjwpPd77OB_u5FEJFCfVzGq3qrwJsgk,9220
12
+ ladyrick/cli/calc.py,sha256=5_UhSSaL_K9FBCHg3zuCk41CHJXy3QAh__qCabbffQY,1438
13
+ ladyrick/cli/multi_ssh.py,sha256=02DmcotlKGlaAEIgIi5KsnjBxkNnf60OiimpH20JfYU,9903
14
14
  ladyrick/cli/psf.py,sha256=JLk3gbPn7E3uuPBbzGvLgJmFQlilA6zg_Xlg7xW5jik,1146
15
15
  ladyrick/cli/tee.py,sha256=UMJxSJLOEfbV43auVKRTIJ5ZAMAkAfj8byiFLk5PUHE,3579
16
16
  ladyrick/cli/test_args.py,sha256=f5sUPDlcf6nbNf6UfLwZQI5g5LN8wlFBQZ10GLw22cg,212
17
- ladyrick/cli/test_signal.py,sha256=uvVLbHlvpmYgZcfRF9Lcte0OJJrMDDsmId3BpSxeaOA,490
17
+ ladyrick/cli/test_signal.py,sha256=zGPGMR81j1_vNyGEAcRtO2WjhDXiCj2xHMDATk-Z33M,494
18
18
  ladyrick/patch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  ladyrick/patch/print.py,sha256=Ks_ONpeLOyC9pFKLmAiNliwGPbJyt9qz-cnRUPVto34,845
20
20
  ladyrick/patch/rich_print.py,sha256=z3Ea1VCunXZvNvEDFHpoyWc8ydINmh-gOIJ1ssscs6s,841
21
21
  ladyrick/patch/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  ladyrick/patch/python/__main__.py,sha256=BAGy1phd26WWcGM9TKHbqIpeZliVofopBndtMIPtDQ0,651
23
23
  ladyrick/patch/python/usercustomize.py,sha256=8mYpcZ8p-l41fiSJue727n8cAmcEmUktObDYZDdLJfs,218
24
- ladyrick-0.5.3.dist-info/licenses/LICENSE,sha256=EeNAFxYAOYEmo2YEM7Zk5Oknq4RI0XMAbk4Rgoem6fs,1065
25
- ladyrick-0.5.3.dist-info/METADATA,sha256=JseJXyRyBHz1PrCo-kcHp_EoezLHCyt3yR6qwyQ9VDE,883
26
- ladyrick-0.5.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- ladyrick-0.5.3.dist-info/entry_points.txt,sha256=28kidI1OCOAi7S1aHBr8veak49VNZ0tWFvf-Ty8UmSU,225
28
- ladyrick-0.5.3.dist-info/top_level.txt,sha256=RIC3-Jty2qzLYXSOr7fOu1loTwlMU9cF6MFeGIROxWU,9
29
- ladyrick-0.5.3.dist-info/RECORD,,
24
+ ladyrick-0.5.5.dist-info/licenses/LICENSE,sha256=EeNAFxYAOYEmo2YEM7Zk5Oknq4RI0XMAbk4Rgoem6fs,1065
25
+ ladyrick-0.5.5.dist-info/METADATA,sha256=5F-dTbYGPoApk--A2gPS5cS_Ev4f3WRRRLKbPrYq4S8,883
26
+ ladyrick-0.5.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ ladyrick-0.5.5.dist-info/entry_points.txt,sha256=28kidI1OCOAi7S1aHBr8veak49VNZ0tWFvf-Ty8UmSU,225
28
+ ladyrick-0.5.5.dist-info/top_level.txt,sha256=RIC3-Jty2qzLYXSOr7fOu1loTwlMU9cF6MFeGIROxWU,9
29
+ ladyrick-0.5.5.dist-info/RECORD,,