QuLab 2.11.2__py3-none-any.whl → 2.11.4__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.
qulab/cli/commands.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import click
2
2
 
3
- from ..executor.cli import (boot, create, export, get, load, maintain,
3
+ from ..executor.cli import (boot, create, export, get, load, maintain, delete,
4
4
  reproduce, run, set)
5
5
  from ..monitor.__main__ import main as monitor
6
6
  from ..scan.server import server
@@ -35,6 +35,7 @@ cli.add_command(reproduce)
35
35
  cli.add_command(create)
36
36
  reg.add_command(set)
37
37
  reg.add_command(get)
38
+ reg.add_command(delete)
38
39
  reg.add_command(load)
39
40
  reg.add_command(export)
40
41
  cli.add_command(boot)
qulab/executor/cli.py CHANGED
@@ -11,6 +11,7 @@ from loguru import logger
11
11
 
12
12
  from ..cli.config import get_config_value, log_options
13
13
  from ..cli.decorators import async_command
14
+ from ..utils import combined_env
14
15
  from .load import (WorkflowType, find_unreferenced_workflows, get_entries,
15
16
  load_workflow, make_graph)
16
17
  from .registry import Registry, set_config_api
@@ -21,12 +22,14 @@ from .utils import workflow_template
21
22
 
22
23
 
23
24
  @logger.catch(reraise=True)
24
- def run_script(script_path):
25
- """Run a script in a new terminal."""
25
+ def run_script(script_path, extra_paths=None):
26
+ """Run a script in a new process, inheriting current PYTHONPATH plus any extra paths."""
26
27
  import subprocess
27
28
  import sys
28
29
 
29
- proc = subprocess.Popen([sys.executable, script_path])
30
+ # Launch the new process with the modified environment
31
+ proc = subprocess.Popen([sys.executable, script_path],
32
+ env=combined_env(extra_paths))
30
33
  proc.communicate()
31
34
 
32
35
 
@@ -131,7 +134,7 @@ def set(key, value, api):
131
134
  """
132
135
  Set a config.
133
136
  """
134
- logger.info(f'[CMD]: set {key} {value} --api {api}')
137
+ logger.info(f'[CMD]: reg set {key} {value} --api {api}')
135
138
  reg = Registry()
136
139
  if api is not None:
137
140
  api = importlib.import_module(api)
@@ -155,7 +158,7 @@ def get(key, api):
155
158
  """
156
159
  Get a config.
157
160
  """
158
- logger.info(f'[CMD]: get {key} --api {api}')
161
+ logger.info(f'[CMD]: reg get {key} --api {api}')
159
162
  reg = Registry()
160
163
  if api is not None:
161
164
  api = importlib.import_module(api)
@@ -164,6 +167,26 @@ def get(key, api):
164
167
  rich.print(reg.get(key))
165
168
 
166
169
 
170
+ @click.command()
171
+ @click.argument('key')
172
+ @click.option('--api',
173
+ '-a',
174
+ default=lambda: get_config_value("api", str, 'get'),
175
+ help='The modlule name of the api.')
176
+ @log_options('delete')
177
+ def delete(key, api):
178
+ """
179
+ Delete a config key.
180
+ """
181
+ logger.info(f'[CMD]: reg delete {key} --api {api}')
182
+ reg = Registry()
183
+ if api is not None:
184
+ api = importlib.import_module(api)
185
+ set_config_api(api.query_config, api.update_config, api.delete_config,
186
+ api.export_config, api.clear_config)
187
+ reg.delete(key)
188
+
189
+
167
190
  @click.command()
168
191
  @click.argument('file')
169
192
  @click.option('--api',
@@ -172,14 +195,14 @@ def get(key, api):
172
195
  help='The modlule name of the api.')
173
196
  @click.option('--format',
174
197
  '-f',
175
- default='json',
198
+ default='pickle',
176
199
  help='The format of the config.')
177
200
  @log_options('export')
178
201
  def export(file, api, format):
179
202
  """
180
203
  Export a config.
181
204
  """
182
- logger.info(f'[CMD]: export {file} --api {api}')
205
+ logger.info(f'[CMD]: reg export {file} --api {api}')
183
206
  reg = Registry()
184
207
  if api is not None:
185
208
  api = importlib.import_module(api)
@@ -210,14 +233,14 @@ def export(file, api, format):
210
233
  help='The modlule name of the api.')
211
234
  @click.option('--format',
212
235
  '-f',
213
- default='json',
236
+ default='pickle',
214
237
  help='The format of the config.')
215
238
  @log_options('load')
216
239
  def load(file, api, format):
217
240
  """
218
241
  Load a config.
219
242
  """
220
- logger.info(f'[CMD]: load {file} --api {api}')
243
+ logger.info(f'[CMD]: reg load {file} --api {api}')
221
244
  reg = Registry()
222
245
  if api is not None:
223
246
  api = importlib.import_module(api)
qulab/utils.py CHANGED
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import shlex
2
3
  import subprocess
3
4
  import sys
@@ -6,36 +7,56 @@ import time
6
7
  import click
7
8
 
8
9
 
9
- def run_detached(executable_path):
10
+ def combined_env(extra_paths=None):
11
+ env = os.environ.copy()
12
+
13
+ # Build a combined PYTHONPATH: current interpreter's sys.path entries + extra_paths
14
+ paths = [p for p in sys.path if p]
15
+ if extra_paths:
16
+ if isinstance(extra_paths, str):
17
+ extra_paths = [extra_paths]
18
+ paths.extend(extra_paths)
19
+
20
+ # Prepend to any existing PYTHONPATH in the environment
21
+ existing = env.get('PYTHONPATH', '')
22
+ combined = os.pathsep.join(paths + ([existing] if existing else []))
23
+ env['PYTHONPATH'] = combined
24
+ return env
25
+
26
+
27
+ def run_detached(executable_path, env=None):
10
28
  """
11
29
  启动可执行文件并完全分离(优先用 tmux/screen),无需额外终端窗口
12
30
  支持 Windows、Linux 和 macOS
13
31
  """
32
+ if env is None:
33
+ env = combined_env()
14
34
  try:
15
35
  if sys.platform == 'win32' or not _unix_detach_with_tmux_or_screen(
16
- executable_path):
36
+ executable_path, env):
17
37
  # 回退到带终端窗口的方案
18
- run_detached_with_terminal(executable_path)
38
+ run_detached_with_terminal(executable_path, env)
19
39
 
20
40
  except Exception as e:
21
41
  click.echo(f"启动失败: {e}")
22
42
  sys.exit(1)
23
43
 
24
44
 
25
- def _windows_start(executable_path):
45
+ def _windows_start(executable_path, env):
26
46
  """Windows 弹窗启动方案"""
27
47
  subprocess.Popen(f'start cmd /k "{executable_path}"',
28
48
  shell=True,
49
+ env=env,
29
50
  creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
30
51
 
31
52
 
32
- def _unix_detach_with_tmux_or_screen(executable_path):
53
+ def _unix_detach_with_tmux_or_screen(executable_path, env):
33
54
  """Unix 后台分离方案(无窗口)"""
34
55
  safe_path = shlex.quote(executable_path)
35
56
  session_name = f"qulab_{int(time.time())}"
36
57
 
37
58
  # 尝试 tmux
38
- if _check_command_exists("tmux"):
59
+ if _check_command_exists("tmux", env):
39
60
  command = [
40
61
  "tmux",
41
62
  "new-session",
@@ -48,15 +69,18 @@ def _unix_detach_with_tmux_or_screen(executable_path):
48
69
  "wait-for",
49
70
  "finished" # 防止进程立即退出
50
71
  ]
51
- subprocess.Popen(" ".join(command), shell=True, start_new_session=True)
72
+ subprocess.Popen(" ".join(command),
73
+ shell=True,
74
+ env=env,
75
+ start_new_session=True)
52
76
  click.echo(f"已启动 tmux 会话: {session_name}")
53
77
  click.echo(f"你可以使用 `tmux attach -t {session_name}` 来查看输出")
54
78
  return True
55
79
 
56
80
  # 尝试 screen
57
- elif _check_command_exists("screen"):
81
+ elif _check_command_exists("screen", env):
58
82
  command = ["screen", "-dmS", session_name, executable_path]
59
- subprocess.Popen(command, start_new_session=True)
83
+ subprocess.Popen(command, env=env, start_new_session=True)
60
84
  click.echo(f"已启动 screen 会话: {session_name}")
61
85
  click.echo(f"你可以使用 `screen -r {session_name}` 来查看输出")
62
86
  return True
@@ -64,27 +88,38 @@ def _unix_detach_with_tmux_or_screen(executable_path):
64
88
  return False
65
89
 
66
90
 
67
- def run_detached_with_terminal(executable_path):
91
+ def run_detached_with_terminal(executable_path, env=None):
68
92
  """回退到带终端窗口的方案"""
93
+ if env is None:
94
+ env = combined_env()
95
+
69
96
  if sys.platform == 'win32':
70
- _windows_start(executable_path)
97
+ _windows_start(executable_path, env)
71
98
  elif sys.platform == 'darwin':
99
+ # executable_path=shlex.quote(executable_path)
100
+ print(executable_path)
72
101
  script = f'tell app "Terminal" to do script "{executable_path}"'
73
- subprocess.Popen(["osascript", "-e", script], start_new_session=True)
102
+ subprocess.Popen(["osascript", "-e", script],
103
+ env=env,
104
+ start_new_session=True)
74
105
  else:
75
106
  try:
76
107
  subprocess.Popen(
77
108
  ["gnome-terminal", "--", "sh", "-c", executable_path],
109
+ env=env,
78
110
  start_new_session=True)
79
111
  except FileNotFoundError:
80
112
  subprocess.Popen(["xterm", "-e", executable_path],
113
+ env=env,
81
114
  start_new_session=True)
82
115
 
83
116
 
84
- def _check_command_exists(cmd):
117
+ def _check_command_exists(cmd, env):
85
118
  """检查命令行工具是否存在"""
86
119
  try:
87
- subprocess.check_output(["which", cmd], stderr=subprocess.DEVNULL)
120
+ subprocess.check_output(["which", cmd],
121
+ env=env,
122
+ stderr=subprocess.DEVNULL)
88
123
  return True
89
124
  except:
90
125
  return False
qulab/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "2.11.2"
1
+ __version__ = "2.11.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QuLab
3
- Version: 2.11.2
3
+ Version: 2.11.4
4
4
  Summary: contral instruments and manage data
5
5
  Author-email: feihoo87 <feihoo87@gmail.com>
6
6
  Maintainer-email: feihoo87 <feihoo87@gmail.com>
@@ -1,15 +1,15 @@
1
1
  qulab/__init__.py,sha256=hmf6R3jiM5NtJY1mSptogYnH5DMTR2dTzlXykqLxQzg,2027
2
2
  qulab/__main__.py,sha256=fjaRSL_uUjNIzBGNgjlGswb9TJ2VD5qnkZHW3hItrD4,68
3
3
  qulab/typing.py,sha256=vg62sGqxuD9CI5677ejlzAmf2fVdAESZCQjAE_xSxPg,69
4
- qulab/utils.py,sha256=BdLdlfjpe6m6gSeONYmpAKTTqxDaYHNk4exlz8kZxTg,2982
5
- qulab/version.py,sha256=etgBnhIbylzigCBcKn_1kBUszqWo0_TMwe37dcT153U,22
4
+ qulab/utils.py,sha256=w5oSw9Ypux6l0oB-MzlQvT40iX_rzQ5wXcwzr7CIVf8,4107
5
+ qulab/version.py,sha256=R23vM4RbEfPLzmIiHDPzMMGKJcHvi00MAAor3IxzcCA,22
6
6
  qulab/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- qulab/cli/commands.py,sha256=Ezop5CEOvvEMDaPmfGXF0JH-CifKuDMk9yLglpUK9Zs,781
7
+ qulab/cli/commands.py,sha256=ywKmwbGNBCVASx8OsgrRttaLz9ogwY38ZdKj7I-tdJ4,813
8
8
  qulab/cli/config.py,sha256=tZPSBLbf2x_Brb2UBuA1bsni8nC8WOPPGyWIi8m7j1I,5459
9
9
  qulab/cli/decorators.py,sha256=oImteZVnDPPWdyhJ4kzf2KYGJLON7VsKGBvZadWLQZo,621
10
10
  qulab/executor/__init__.py,sha256=LosPzOMaljSZY1thy_Fxtbrgq7uubJszMABEB7oM7tU,101
11
11
  qulab/executor/analyze.py,sha256=4Hau5LrKUdpweh7W94tcG4ahgxucHOevbM0hm57T7zE,5649
12
- qulab/executor/cli.py,sha256=md-RhHS2Wsbp9KgCMXvVAlxqIZQALtSnWllip7irD2M,17621
12
+ qulab/executor/cli.py,sha256=SDZAuEJmRRt874N2paI78xuBk88twTfk-aynutCHNAk,18476
13
13
  qulab/executor/load.py,sha256=eMlzOrrn8GpbP3J3uY5JJ8iO7tL5B1DWP1z2qiGyNhU,20385
14
14
  qulab/executor/registry.py,sha256=gym9F5FIDY5eV-cSCZsP99wC4l-6jkx9VMjJMaPOLaQ,4730
15
15
  qulab/executor/schedule.py,sha256=7gAJFwj13j1niGjVa1fSzwOS22eNFEN1hdrN3dfTY6A,21410
@@ -96,9 +96,9 @@ qulab/visualization/plot_seq.py,sha256=UWTS6p9nfX_7B8ehcYo6UnSTUCjkBsNU9jiOeW2ca
96
96
  qulab/visualization/qdat.py,sha256=ZeevBYWkzbww4xZnsjHhw7wRorJCBzbG0iEu-XQB4EA,5735
97
97
  qulab/visualization/rot3d.py,sha256=lMrEJlRLwYe6NMBlGkKYpp_V9CTipOAuDy6QW_cQK00,734
98
98
  qulab/visualization/widgets.py,sha256=6KkiTyQ8J-ei70LbPQZAK35wjktY47w2IveOa682ftA,3180
99
- qulab-2.11.2.dist-info/licenses/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
100
- qulab-2.11.2.dist-info/METADATA,sha256=3T_qx8RomqhcU-lsvwduReSXWxEU3ph2HUdZVJTucK8,3896
101
- qulab-2.11.2.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
102
- qulab-2.11.2.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
103
- qulab-2.11.2.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
104
- qulab-2.11.2.dist-info/RECORD,,
99
+ qulab-2.11.4.dist-info/licenses/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
100
+ qulab-2.11.4.dist-info/METADATA,sha256=qkJE05G3P9IwYbwoet89FssRyf_WtmEE8MJejsmKvOc,3896
101
+ qulab-2.11.4.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
102
+ qulab-2.11.4.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
103
+ qulab-2.11.4.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
104
+ qulab-2.11.4.dist-info/RECORD,,
File without changes