pyship 0.4.0__py3-none-any.whl → 0.4.2__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.
- pyship/clip.py +2 -2
- pyship/create_launcher.py +64 -2
- pyship/launcher/launcher.py +21 -0
- pyship/uv_util.py +11 -4
- {pyship-0.4.0.dist-info → pyship-0.4.2.dist-info}/METADATA +1 -1
- {pyship-0.4.0.dist-info → pyship-0.4.2.dist-info}/RECORD +9 -9
- {pyship-0.4.0.dist-info → pyship-0.4.2.dist-info}/WHEEL +0 -0
- {pyship-0.4.0.dist-info → pyship-0.4.2.dist-info}/licenses/LICENSE +0 -0
- {pyship-0.4.0.dist-info → pyship-0.4.2.dist-info}/top_level.txt +0 -0
pyship/clip.py
CHANGED
|
@@ -60,8 +60,8 @@ def create_base_clip(target_app_info: AppInfo, app_dir: Path, cache_dir: Path) -
|
|
|
60
60
|
pyship_print(f'building clip {clip_dir_name} ("{clip_dir}")')
|
|
61
61
|
|
|
62
62
|
uv_path = find_or_bootstrap_uv(cache_dir)
|
|
63
|
-
uv_python_install(uv_path, python_version)
|
|
64
|
-
uv_venv_create(uv_path, clip_dir,
|
|
63
|
+
python_path = uv_python_install(uv_path, python_version)
|
|
64
|
+
uv_venv_create(uv_path, clip_dir, str(python_path))
|
|
65
65
|
|
|
66
66
|
return clip_dir
|
|
67
67
|
|
pyship/create_launcher.py
CHANGED
|
@@ -16,6 +16,63 @@ from pyship.launcher_stub import compile_launcher_stub
|
|
|
16
16
|
log = get_logger(launcher_application_name)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
@typechecked
|
|
20
|
+
def _write_diagnostic_bat(app_name: str, bat_path: Path):
|
|
21
|
+
"""
|
|
22
|
+
Write a diagnostic .bat file that runs the launcher script with python.exe (not pythonw.exe)
|
|
23
|
+
so that all console output is visible for troubleshooting.
|
|
24
|
+
:param app_name: target application name
|
|
25
|
+
:param bat_path: path where the .bat file will be written
|
|
26
|
+
"""
|
|
27
|
+
bat_content = f"""@echo off
|
|
28
|
+
REM Diagnostic launcher for {app_name}
|
|
29
|
+
REM Runs the launcher script with python.exe (console) so output is always visible.
|
|
30
|
+
|
|
31
|
+
setlocal
|
|
32
|
+
|
|
33
|
+
set "LAUNCHER_DIR=%~dp0"
|
|
34
|
+
REM Remove trailing backslash
|
|
35
|
+
if "%LAUNCHER_DIR:~-1%"=="\\" set "LAUNCHER_DIR=%LAUNCHER_DIR:~0,-1%"
|
|
36
|
+
|
|
37
|
+
REM app_dir is the parent of launcher_dir
|
|
38
|
+
for %%I in ("%LAUNCHER_DIR%") do set "APP_DIR=%%~dpI"
|
|
39
|
+
if "%APP_DIR:~-1%"=="\\" set "APP_DIR=%APP_DIR:~0,-1%"
|
|
40
|
+
|
|
41
|
+
REM Find the latest CLIP directory containing Scripts\\python.exe
|
|
42
|
+
set "PYTHON_EXE="
|
|
43
|
+
for /d %%D in ("%APP_DIR%\\{app_name}_*") do (
|
|
44
|
+
if exist "%%D\\Scripts\\python.exe" (
|
|
45
|
+
set "PYTHON_EXE=%%D\\Scripts\\python.exe"
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if not defined PYTHON_EXE (
|
|
50
|
+
echo ERROR: No Python environment found for {app_name} in %APP_DIR%
|
|
51
|
+
pause
|
|
52
|
+
exit /b 1
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
echo Using Python: %PYTHON_EXE%
|
|
56
|
+
echo Running: %PYTHON_EXE% "%LAUNCHER_DIR%\\{app_name}_launcher.py" --app-dir "%APP_DIR%" %*
|
|
57
|
+
echo.
|
|
58
|
+
|
|
59
|
+
"%PYTHON_EXE%" "%LAUNCHER_DIR%\\{app_name}_launcher.py" --app-dir "%APP_DIR%" %*
|
|
60
|
+
|
|
61
|
+
set "EXIT_CODE=%ERRORLEVEL%"
|
|
62
|
+
echo.
|
|
63
|
+
echo Exit code: %EXIT_CODE%
|
|
64
|
+
if not "%EXIT_CODE%"=="0" (
|
|
65
|
+
echo.
|
|
66
|
+
echo ERROR: {app_name} exited with code %EXIT_CODE%
|
|
67
|
+
pause
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
endlocal
|
|
71
|
+
exit /b %EXIT_CODE%
|
|
72
|
+
"""
|
|
73
|
+
bat_path.write_text(bat_content, encoding="utf-8")
|
|
74
|
+
|
|
75
|
+
|
|
19
76
|
@typechecked
|
|
20
77
|
def create_pyship_launcher(target_app_info: AppInfo, app_path_output: Path):
|
|
21
78
|
"""
|
|
@@ -69,13 +126,18 @@ def create_pyship_launcher(target_app_info: AppInfo, app_path_output: Path):
|
|
|
69
126
|
shutil.copy2(str(standalone_source), str(standalone_dest))
|
|
70
127
|
log.info(f"copied launcher script to {standalone_dest}")
|
|
71
128
|
|
|
72
|
-
# 3.
|
|
129
|
+
# 3. Generate diagnostic .bat launcher (always uses python.exe for console output)
|
|
130
|
+
bat_path = Path(launcher_dir, f"{target_app_info.name}.bat")
|
|
131
|
+
_write_diagnostic_bat(target_app_info.name, bat_path)
|
|
132
|
+
log.info(f"wrote diagnostic bat to {bat_path}")
|
|
133
|
+
|
|
134
|
+
# 4. Copy the icon alongside
|
|
73
135
|
if icon_path.exists():
|
|
74
136
|
icon_dest = Path(launcher_dir, f"{target_app_info.name}.ico")
|
|
75
137
|
shutil.copy2(str(icon_path), str(icon_dest))
|
|
76
138
|
log.info(f"copied icon to {icon_dest}")
|
|
77
139
|
|
|
78
|
-
#
|
|
140
|
+
# 5. Store metadata for cache invalidation
|
|
79
141
|
store_metadata(app_path_output, metadata_filename, metadata)
|
|
80
142
|
|
|
81
143
|
if launcher_exe_path.exists():
|
pyship/launcher/launcher.py
CHANGED
|
@@ -241,6 +241,27 @@ def launch(app_dir=None, additional_path=None):
|
|
|
241
241
|
std_out = target_process.stdout
|
|
242
242
|
std_err = target_process.stderr
|
|
243
243
|
|
|
244
|
+
# When pythonw.exe fails silently (no stderr), re-run with python.exe to capture the actual error
|
|
245
|
+
if is_gui and return_code not in (OK_RETURN_CODE, RESTART_RETURN_CODE) and not (std_err and std_err.strip()):
|
|
246
|
+
log.warning(f"pythonw.exe exited with return_code={return_code} but produced no error output, re-running with python.exe for diagnostics")
|
|
247
|
+
diag_python = Path(versions[latest_version], "Scripts", "python.exe")
|
|
248
|
+
if diag_python.exists():
|
|
249
|
+
diag_cmd = [str(diag_python), "-X", "faulthandler"] + cmd[1:]
|
|
250
|
+
log.info(f"diagnostic cmd={diag_cmd}")
|
|
251
|
+
try:
|
|
252
|
+
diag_process = subprocess.run(diag_cmd, cwd=str(python_exe_path.parent), capture_output=True, text=True)
|
|
253
|
+
diag_return_code = diag_process.returncode
|
|
254
|
+
std_out = diag_process.stdout
|
|
255
|
+
std_err = diag_process.stderr
|
|
256
|
+
if std_err and std_err.strip():
|
|
257
|
+
log.info(f"diagnostic stderr captured (return_code={diag_return_code})")
|
|
258
|
+
elif std_out and std_out.strip():
|
|
259
|
+
log.info(f"diagnostic stdout captured (return_code={diag_return_code})")
|
|
260
|
+
else:
|
|
261
|
+
log.warning(f"diagnostic re-run with python.exe also produced no output (return_code={diag_return_code})")
|
|
262
|
+
except Exception as diag_e:
|
|
263
|
+
log.error(f"diagnostic re-run failed: {diag_e}")
|
|
264
|
+
|
|
244
265
|
if (std_err and std_err.strip()) or (return_code != OK_RETURN_CODE and return_code != RESTART_RETURN_CODE):
|
|
245
266
|
if std_out and std_out.strip():
|
|
246
267
|
log.warning(std_out)
|
pyship/uv_util.py
CHANGED
|
@@ -92,17 +92,24 @@ def uv_python_install(uv_path: Path, python_version: str) -> Path:
|
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
@typechecked
|
|
95
|
-
def uv_venv_create(uv_path: Path, venv_dir: Path,
|
|
95
|
+
def uv_venv_create(uv_path: Path, venv_dir: Path, python_version_or_path: str) -> None:
|
|
96
96
|
"""
|
|
97
97
|
Create a relocatable venv using uv.
|
|
98
98
|
:param uv_path: path to uv executable
|
|
99
99
|
:param venv_dir: destination directory for the venv
|
|
100
|
-
:param
|
|
100
|
+
:param python_version_or_path: Python version string (e.g. "3.11") or path to Python executable
|
|
101
101
|
"""
|
|
102
102
|
pyship_print(f'creating relocatable venv at "{venv_dir}"')
|
|
103
|
-
cmd = [str(uv_path), "venv", "--relocatable", "--python",
|
|
103
|
+
cmd = [str(uv_path), "venv", "--relocatable", "--clear", "--python", python_version_or_path, str(venv_dir)]
|
|
104
104
|
log.info(f"uv venv cmd: {cmd}")
|
|
105
|
-
subprocess.run(cmd,
|
|
105
|
+
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
106
|
+
if result.stdout:
|
|
107
|
+
log.info(result.stdout)
|
|
108
|
+
if result.stderr:
|
|
109
|
+
log.info(result.stderr)
|
|
110
|
+
if result.returncode != 0:
|
|
111
|
+
log.error(f"uv venv failed (exit {result.returncode}): {result.stderr}")
|
|
112
|
+
result.check_returncode()
|
|
106
113
|
|
|
107
114
|
|
|
108
115
|
@typechecked
|
|
@@ -3,10 +3,10 @@ pyship/__main__.py,sha256=KtAdk7BCWhXbhywlFB8P4HbvypVkqJXbxgMW3XVD-To,84
|
|
|
3
3
|
pyship/__version__.py,sha256=y-oqerPvrMS7jU7JSdHdUyKkSxJWA0anyoCQCfQ3INQ,502
|
|
4
4
|
pyship/app_info.py,sha256=UTWD4ol226sNAAYsiByMJswIIL1lN8nx96PpD43YQG4,6866
|
|
5
5
|
pyship/arguments.py,sha256=p4cA8FwbNSZqg4XI6LsYit1QN7TpAWWZH2xrgLf-f-g,1882
|
|
6
|
-
pyship/clip.py,sha256=
|
|
6
|
+
pyship/clip.py,sha256=9RGqXSYGmR89T8ng6f9fDkhy61_aytRvMcXKp3yh6Yo,3716
|
|
7
7
|
pyship/cloud.py,sha256=k8m-254Akpp3NALeP0pJzFs21_2qZmmK0GHfSC-Z0sw,1282
|
|
8
8
|
pyship/constants.py,sha256=Y-yA_MMwL572UbZqmhILrJL6NH9xK3q5jELJR6atw7I,243
|
|
9
|
-
pyship/create_launcher.py,sha256=
|
|
9
|
+
pyship/create_launcher.py,sha256=vg2vsyeQlxsmVNVlgO1KVtbtacUTwJG8pWZkUf35jmQ,5771
|
|
10
10
|
pyship/download.py,sha256=QHbdVwxLNBToMEC0tOF2ZquDpoydRu0-cj7LOERr5Q4,2460
|
|
11
11
|
pyship/launcher_stub.py,sha256=3yC1EKk45m4GOJ_uat1OWKUFqgAWdcpfQZKh7qhflnk,6889
|
|
12
12
|
pyship/logging.py,sha256=cIB7487tN8TsKeDHwwzjA30rHRW5Ci5GA5uPbaEXaY0,966
|
|
@@ -20,15 +20,15 @@ pyship/pyship_exceptions.py,sha256=teUOh3FuRUU9hyv7L4owACQZPWNdwpYTEz6l-Ao35nw,9
|
|
|
20
20
|
pyship/pyship_get_icon.py,sha256=BQp_xYl8CXt2e7nDB0llSxr0hbP7to2fkQqPeu8WpIg,2050
|
|
21
21
|
pyship/pyship_path.py,sha256=RpU2n7pWXTr0501S7U8KxWCpBc8jOqKPuaX0X6IWPI8,262
|
|
22
22
|
pyship/pyship_subprocess.py,sha256=hH4MW_j2zLJLDmLDkkl2JWupXrvSemAeCPAEtPdSGyk,3212
|
|
23
|
-
pyship/uv_util.py,sha256=
|
|
23
|
+
pyship/uv_util.py,sha256=sAofeT4I9Xs__UW9w3sY2r9b_lLrfuZmOomxVLXdikE,5990
|
|
24
24
|
pyship/launcher/__init__.py,sha256=25vVghziYIHDBA0mCaGqhj6hWxxjQqlm4LrY0Hem0YY,245
|
|
25
25
|
pyship/launcher/__main__.py,sha256=KhFSf1RU5Cj15y0c4FlzvIvDpWWi9NKYy0gzJ-w7KQE,115
|
|
26
26
|
pyship/launcher/hash.py,sha256=THEh8G-StEJeh5tH24RnAQpYB0Zv1nnBwqOoStN6_NY,1153
|
|
27
|
-
pyship/launcher/launcher.py,sha256=
|
|
27
|
+
pyship/launcher/launcher.py,sha256=FNUNApE2L9Ol7JISwTxFi2mK_eHBBTSOcOpkPyQkwG4,12422
|
|
28
28
|
pyship/launcher/metadata.py,sha256=PnOkYLQf6NYvPiZWhf0LAUjmFWzURKWriRQJSy3T-x4,1969
|
|
29
29
|
pyship/launcher/restart_monitor.py,sha256=jfzchLxGuC_xUNdPAr849FhAdozJ6BX9M-gqLd-gGIA,952
|
|
30
|
-
pyship-0.4.
|
|
31
|
-
pyship-0.4.
|
|
32
|
-
pyship-0.4.
|
|
33
|
-
pyship-0.4.
|
|
34
|
-
pyship-0.4.
|
|
30
|
+
pyship-0.4.2.dist-info/licenses/LICENSE,sha256=vfTkV97IHvr2g_I1pGQg2bRYT05ktYYgaPwBDKNRv98,1093
|
|
31
|
+
pyship-0.4.2.dist-info/METADATA,sha256=lI2OnHEw5uFnXUBi1inlIkPtYfraEQrGC-YGhR7adNc,2513
|
|
32
|
+
pyship-0.4.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
33
|
+
pyship-0.4.2.dist-info/top_level.txt,sha256=mlozeft-UInVAceSajzNvtkn2vPa8El9j0RulsTVtlU,7
|
|
34
|
+
pyship-0.4.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|