QuLab 2.11.1__py3-none-any.whl → 2.11.3__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/executor/cli.py CHANGED
@@ -6,10 +6,12 @@ import sys
6
6
  from pathlib import Path
7
7
 
8
8
  import click
9
+ import rich
9
10
  from loguru import logger
10
11
 
11
12
  from ..cli.config import get_config_value, log_options
12
13
  from ..cli.decorators import async_command
14
+ from ..utils import combined_env
13
15
  from .load import (WorkflowType, find_unreferenced_workflows, get_entries,
14
16
  load_workflow, make_graph)
15
17
  from .registry import Registry, set_config_api
@@ -20,12 +22,14 @@ from .utils import workflow_template
20
22
 
21
23
 
22
24
  @logger.catch(reraise=True)
23
- def run_script(script_path):
24
- """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."""
25
27
  import subprocess
26
28
  import sys
27
29
 
28
- 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))
29
33
  proc.communicate()
30
34
 
31
35
 
@@ -160,7 +164,7 @@ def get(key, api):
160
164
  api = importlib.import_module(api)
161
165
  set_config_api(api.query_config, api.update_config, api.delete_config,
162
166
  api.export_config, api.clear_config)
163
- click.echo(reg.get(key))
167
+ rich.print(reg.get(key))
164
168
 
165
169
 
166
170
  @click.command()
@@ -171,7 +175,7 @@ def get(key, api):
171
175
  help='The modlule name of the api.')
172
176
  @click.option('--format',
173
177
  '-f',
174
- default='json',
178
+ default='pickle',
175
179
  help='The format of the config.')
176
180
  @log_options('export')
177
181
  def export(file, api, format):
@@ -209,7 +213,7 @@ def export(file, api, format):
209
213
  help='The modlule name of the api.')
210
214
  @click.option('--format',
211
215
  '-f',
212
- default='json',
216
+ default='pickle',
213
217
  help='The format of the config.')
214
218
  @log_options('load')
215
219
  def load(file, api, format):
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.1"
1
+ __version__ = "2.11.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QuLab
3
- Version: 2.11.1
3
+ Version: 2.11.3
4
4
  Summary: contral instruments and manage data
5
5
  Author-email: feihoo87 <feihoo87@gmail.com>
6
6
  Maintainer-email: feihoo87 <feihoo87@gmail.com>
@@ -47,6 +47,7 @@ Requires-Dist: SQLAlchemy>=2.0.19
47
47
  Requires-Dist: watchdog>=4.0.0
48
48
  Requires-Dist: wath>=1.1.6
49
49
  Requires-Dist: waveforms>=1.9.4
50
+ Requires-Dist: rich>=14.0.0
50
51
  Provides-Extra: full
51
52
  Requires-Dist: uvloop>=0.19.0; extra == "full"
52
53
  Dynamic: license-file
@@ -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=L1NLbAiqOvyeykqIP0sEpfnHOltZ_nm9qsrW3nkEmTk,22
4
+ qulab/utils.py,sha256=w5oSw9Ypux6l0oB-MzlQvT40iX_rzQ5wXcwzr7CIVf8,4107
5
+ qulab/version.py,sha256=TBqc-ot-JVCYjkMyPJlutWympLhMMuKgQ12zpTcCJvw,22
6
6
  qulab/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  qulab/cli/commands.py,sha256=Ezop5CEOvvEMDaPmfGXF0JH-CifKuDMk9yLglpUK9Zs,781
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=FZQY249VVSoMZm3lZGaVTAvgULKjMeC97YUe4hqi5Y0,17608
12
+ qulab/executor/cli.py,sha256=gBh0Qlb-2zNI_NWFZXUirQLWizSOCe4AMDsVm05nPqU,17848
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.1.dist-info/licenses/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
100
- qulab-2.11.1.dist-info/METADATA,sha256=NhaeCv-fsilTHypKCMhtX0vuBVH3nCCtE-4k4Ri8zKk,3868
101
- qulab-2.11.1.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
102
- qulab-2.11.1.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
103
- qulab-2.11.1.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
104
- qulab-2.11.1.dist-info/RECORD,,
99
+ qulab-2.11.3.dist-info/licenses/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
100
+ qulab-2.11.3.dist-info/METADATA,sha256=a4CvL-wBrnNJwrewATY748vOK5fZKie1LLfLWoVMwRw,3896
101
+ qulab-2.11.3.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
102
+ qulab-2.11.3.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
103
+ qulab-2.11.3.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
104
+ qulab-2.11.3.dist-info/RECORD,,
File without changes