Skip to content

Commit 60f735d

Browse files
Adding mac / windows specific tests for standalone command. (#169)
* Add test for install and standalone on windows. * Test in venv. * Skip Manager. * Fix activate command. * Update. * Update. * improve platform system determination * `DependencyCompiler`: add `reqs` parameter to `.Download` and `.Wheel` methods * refactored tarball creation/extraction to use `create_tarball`/`extract_tarball` * skip uv wheel when dehydrating standalone python on windows * small fixup to joining python standalone download url * improve parsing of reqs from reqFile * add `tarfile.data_filter` to all tar filters to address secruity audit * revert tar security fix, since `tarfile.data_filter` is busted in many python versions - see: python/cpython#107845 * add numpy<2 override on windows --------- Co-authored-by: telamonian <telamonian@users.noreply.github.com>
1 parent a2423ff commit 60f735d

File tree

6 files changed

+282
-94
lines changed

6 files changed

+282
-94
lines changed

.github/workflows/run-on-gpu.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ on:
77
paths:
88
- "comfy_cli/**"
99
- "!comfy_cli/test_**"
10+
- "!.github/**"
1011
pull_request:
1112
branches:
1213
- main
1314
paths:
1415
- "comfy_cli/**"
1516
- "!comfy_cli/test_**"
17+
- "!.github/**"
1618

1719
jobs:
1820
test-cli-gpu:

.github/workflows/test-mac.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: "Mac Specific Commands"
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
7+
jobs:
8+
test:
9+
runs-on: macos-latest
10+
env:
11+
PYTHONIOENCODING: "utf8"
12+
13+
steps:
14+
- name: Check out code
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: 3.12
21+
22+
- name: Install Dependencies
23+
run: |
24+
python -m venv venv
25+
source venv/bin/activate
26+
python -m pip install --upgrade pip
27+
pip install pytest
28+
pip install -e .
29+
comfy --skip-prompt --workspace ./ComfyUI install --fast-deps --m-series --skip-manager
30+
comfy --workspace ./ComfyUI standalone --platform macos
31+
comfy standalone --rehydrate
32+
./python/bin/python ComfyUI/main.py --cpu --quick-test-for-ci

.github/workflows/test-windows.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: "Windows Specific Commands"
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
7+
jobs:
8+
test:
9+
runs-on: windows-latest
10+
env:
11+
PYTHONIOENCODING: "utf8"
12+
13+
steps:
14+
- name: Check out code
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: 3.12
21+
22+
- name: Install Dependencies
23+
run: |
24+
python -m venv venv
25+
.\venv\Scripts\Activate.ps1
26+
Get-Command python
27+
python -m pip install --upgrade pip
28+
pip install pytest
29+
pip install -e .
30+
comfy --skip-prompt --workspace ./ComfyUI install --fast-deps --nvidia --cuda-version 12.1 --skip-manager
31+
comfy --workspace ./ComfyUI standalone --platform windows --proc x86_64
32+
ls
33+
comfy standalone --rehydrate --platform windows --proc x86_64
34+
./python/python.exe ComfyUI/main.py --cpu --quick-test-for-ci

comfy_cli/standalone.py

Lines changed: 16 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
1-
import platform as os_platform
21
import shutil
32
import subprocess
4-
import tarfile
53
from pathlib import Path
64
from typing import Optional
75

86
import requests
9-
from rich.live import Live
10-
from rich.progress import Progress, TextColumn
11-
from rich.table import Table
127

138
from comfy_cli.constants import OS, PROC
149
from comfy_cli.typing import PathLike
15-
from comfy_cli.utils import download_progress, get_os, get_proc
10+
from comfy_cli.utils import create_tarball, download_url, extract_tarball, get_os, get_proc
1611
from comfy_cli.uv import DependencyCompiler
1712

1813
_here = Path(__file__).expanduser().resolve().parent
@@ -37,6 +32,7 @@ def download_standalone_python(
3732
tag: str = "latest",
3833
flavor: str = "install_only",
3934
cwd: PathLike = ".",
35+
show_progress: bool = True,
4036
) -> PathLike:
4137
"""grab a pre-built distro from the python-build-standalone project. See
4238
https://gregoryszorc.com/docs/python-build-standalone/main/"""
@@ -59,9 +55,9 @@ def download_standalone_python(
5955

6056
name = f"cpython-{version}+{tag}-{target}-{flavor}"
6157
fname = f"{name}.tar.gz"
62-
url = f"{asset_url_prefix}/{fname}"
58+
url = f"{asset_url_prefix.rstrip('/')}/{fname.lstrip('/')}"
6359

64-
return download_progress(url, fname, cwd=cwd)
60+
return download_url(url, fname, cwd=cwd, show_progress=show_progress)
6561

6662

6763
class StandalonePython:
@@ -74,43 +70,32 @@ def FromDistro(
7470
flavor: str = "install_only",
7571
cwd: PathLike = ".",
7672
name: PathLike = "python",
77-
):
73+
show_progress: bool = True,
74+
) -> "StandalonePython":
7875
fpath = download_standalone_python(
7976
platform=platform,
8077
proc=proc,
8178
version=version,
8279
tag=tag,
8380
flavor=flavor,
8481
cwd=cwd,
82+
show_progress=show_progress,
8583
)
8684
return StandalonePython.FromTarball(fpath, name)
8785

8886
@staticmethod
89-
def FromTarball(fpath: PathLike, name: PathLike = "python") -> "StandalonePython":
87+
def FromTarball(fpath: PathLike, name: PathLike = "python", show_progress: bool = True) -> "StandalonePython":
9088
fpath = Path(fpath)
91-
92-
with tarfile.open(fpath) as tar:
93-
info = tar.next()
94-
old_name = info.name.split("/")[0]
95-
96-
old_rpath = fpath.parent / old_name
9789
rpath = fpath.parent / name
9890

99-
# clean the tar file expand target and the final target
100-
shutil.rmtree(old_rpath, ignore_errors=True)
101-
shutil.rmtree(rpath, ignore_errors=True)
102-
103-
with tarfile.open(fpath) as tar:
104-
tar.extractall()
105-
106-
shutil.move(old_rpath, rpath)
91+
extract_tarball(inPath=fpath, outPath=rpath, show_progress=show_progress)
10792

10893
return StandalonePython(rpath=rpath)
10994

11095
def __init__(self, rpath: PathLike):
11196
self.rpath = Path(rpath)
11297
self.name = self.rpath.name
113-
if os_platform.system() == "Windows":
98+
if get_os() == OS.WINDOWS:
11499
self.bin = self.rpath
115100
self.executable = self.bin / "python.exe"
116101
else:
@@ -170,48 +155,18 @@ def dehydrate_comfy_deps(
170155
extraSpecs=extraSpecs,
171156
)
172157
self.dep_comp.compile_deps()
173-
self.dep_comp.fetch_dep_wheels()
158+
159+
skip_uv = get_os() == OS.WINDOWS
160+
self.dep_comp.fetch_dep_wheels(skip_uv=skip_uv)
174161

175162
def rehydrate_comfy_deps(self):
176163
self.dep_comp = DependencyCompiler(
177164
executable=self.executable, outDir=self.rpath, reqFilesCore=[], reqFilesExt=[]
178165
)
179166
self.dep_comp.install_wheels_directly()
180167

181-
def to_tarball(self, outPath: Optional[PathLike] = None, progress: bool = True):
182-
outPath = self.rpath.with_suffix(".tgz") if outPath is None else Path(outPath)
183-
184-
# do a little clean up prep
185-
outPath.unlink(missing_ok=True)
168+
def to_tarball(self, outPath: Optional[PathLike] = None, show_progress: bool = True):
169+
# remove any __pycache__ before creating archive
186170
self.clean()
187171

188-
if progress:
189-
fileSize = sum(f.stat().st_size for f in self.rpath.glob("**/*"))
190-
191-
barProg = Progress()
192-
addTar = barProg.add_task("[cyan]Creating tarball...", total=fileSize)
193-
pathProg = Progress(TextColumn("{task.description}"))
194-
pathTar = pathProg.add_task("")
195-
196-
progress_table = Table.grid()
197-
progress_table.add_row(barProg)
198-
progress_table.add_row(pathProg)
199-
200-
_size = 0
201-
202-
def _filter(tinfo: tarfile.TarInfo):
203-
nonlocal _size
204-
pathProg.update(pathTar, description=tinfo.path)
205-
barProg.advance(addTar, _size)
206-
_size = Path(tinfo.path).stat().st_size
207-
return tinfo
208-
else:
209-
_filter = None
210-
211-
with Live(progress_table, refresh_per_second=10):
212-
with tarfile.open(outPath, "w:gz") as tar:
213-
tar.add(self.rpath.relative_to(Path(".").expanduser().resolve()), filter=_filter)
214-
215-
if progress:
216-
barProg.advance(addTar, _size)
217-
pathProg.update(pathTar, description="")
172+
create_tarball(inPath=self.rpath, outPath=outPath, show_progress=show_progress)

0 commit comments

Comments
 (0)