comfy-env 0.1.14__py3-none-any.whl → 0.1.15__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.
- comfy_env/__init__.py +8 -30
- comfy_env/cache.py +11 -139
- comfy_env/cli.py +9 -11
- comfy_env/config/__init__.py +8 -10
- comfy_env/config/parser.py +28 -75
- comfy_env/install.py +141 -25
- comfy_env/isolation/__init__.py +2 -1
- comfy_env/isolation/wrap.py +136 -15
- comfy_env/nodes.py +1 -1
- comfy_env/pixi/core.py +1 -2
- comfy_env/prestartup.py +31 -15
- comfy_env/workers/subprocess.py +1 -1
- {comfy_env-0.1.14.dist-info → comfy_env-0.1.15.dist-info}/METADATA +2 -2
- comfy_env-0.1.15.dist-info/RECORD +31 -0
- comfy_env/config/types.py +0 -70
- comfy_env/errors.py +0 -293
- comfy_env-0.1.14.dist-info/RECORD +0 -33
- {comfy_env-0.1.14.dist-info → comfy_env-0.1.15.dist-info}/WHEEL +0 -0
- {comfy_env-0.1.14.dist-info → comfy_env-0.1.15.dist-info}/entry_points.txt +0 -0
- {comfy_env-0.1.14.dist-info → comfy_env-0.1.15.dist-info}/licenses/LICENSE +0 -0
comfy_env/isolation/__init__.py
CHANGED
comfy_env/isolation/wrap.py
CHANGED
|
@@ -174,12 +174,9 @@ def _find_env_paths(node_dir: Path) -> tuple[Optional[Path], Optional[Path]]:
|
|
|
174
174
|
marker_path = node_dir / ".comfy-env-marker.toml"
|
|
175
175
|
if marker_path.exists():
|
|
176
176
|
try:
|
|
177
|
-
|
|
178
|
-
import tomllib
|
|
179
|
-
else:
|
|
180
|
-
import tomli as tomllib
|
|
177
|
+
import tomli
|
|
181
178
|
with open(marker_path, "rb") as f:
|
|
182
|
-
marker =
|
|
179
|
+
marker = tomli.load(f)
|
|
183
180
|
env_path = marker.get("env", {}).get("path")
|
|
184
181
|
if env_path:
|
|
185
182
|
env_dir = Path(env_path)
|
|
@@ -234,12 +231,9 @@ def _find_env_dir(node_dir: Path) -> Optional[Path]:
|
|
|
234
231
|
marker_path = node_dir / ".comfy-env-marker.toml"
|
|
235
232
|
if marker_path.exists():
|
|
236
233
|
try:
|
|
237
|
-
|
|
238
|
-
import tomllib
|
|
239
|
-
else:
|
|
240
|
-
import tomli as tomllib
|
|
234
|
+
import tomli
|
|
241
235
|
with open(marker_path, "rb") as f:
|
|
242
|
-
marker =
|
|
236
|
+
marker = tomli.load(f)
|
|
243
237
|
env_path = marker.get("env", {}).get("path")
|
|
244
238
|
if env_path:
|
|
245
239
|
env_dir = Path(env_path)
|
|
@@ -391,6 +385,131 @@ def _wrap_node_class(
|
|
|
391
385
|
return cls
|
|
392
386
|
|
|
393
387
|
|
|
388
|
+
def _is_comfy_env_enabled() -> bool:
|
|
389
|
+
"""Check if comfy-env isolation is enabled (default: True)."""
|
|
390
|
+
val = os.environ.get("USE_COMFY_ENV", "1").lower()
|
|
391
|
+
return val not in ("0", "false", "no", "off")
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def wrap_nodes() -> None:
|
|
395
|
+
"""
|
|
396
|
+
Auto-wrap nodes for isolation. Call from your __init__.py after defining NODE_CLASS_MAPPINGS.
|
|
397
|
+
|
|
398
|
+
Usage:
|
|
399
|
+
from comfy_env import wrap_nodes
|
|
400
|
+
wrap_nodes()
|
|
401
|
+
"""
|
|
402
|
+
# Skip if isolation is disabled
|
|
403
|
+
if not _is_comfy_env_enabled():
|
|
404
|
+
print(f"[comfy-env] Isolation disabled, nodes running in main process")
|
|
405
|
+
return
|
|
406
|
+
|
|
407
|
+
# Skip if running inside worker subprocess
|
|
408
|
+
if os.environ.get("COMFYUI_ISOLATION_WORKER") == "1":
|
|
409
|
+
return
|
|
410
|
+
|
|
411
|
+
# Get caller's frame and module
|
|
412
|
+
frame = inspect.stack()[1]
|
|
413
|
+
caller_module = inspect.getmodule(frame.frame)
|
|
414
|
+
if caller_module is None:
|
|
415
|
+
print("[comfy-env] Warning: Could not determine caller module")
|
|
416
|
+
return
|
|
417
|
+
|
|
418
|
+
# Get NODE_CLASS_MAPPINGS from caller's module
|
|
419
|
+
node_class_mappings = getattr(caller_module, "NODE_CLASS_MAPPINGS", None)
|
|
420
|
+
if not node_class_mappings:
|
|
421
|
+
print("[comfy-env] Warning: No NODE_CLASS_MAPPINGS found in caller module")
|
|
422
|
+
return
|
|
423
|
+
|
|
424
|
+
# Get package root directory
|
|
425
|
+
caller_file = Path(frame.filename).resolve()
|
|
426
|
+
package_dir = caller_file.parent
|
|
427
|
+
|
|
428
|
+
# Find all comfy-env.toml files
|
|
429
|
+
config_files = list(package_dir.rglob("comfy-env.toml"))
|
|
430
|
+
if not config_files:
|
|
431
|
+
return # No configs, nothing to wrap
|
|
432
|
+
|
|
433
|
+
# Get ComfyUI base path
|
|
434
|
+
try:
|
|
435
|
+
import folder_paths
|
|
436
|
+
comfyui_base = folder_paths.base_path
|
|
437
|
+
except ImportError:
|
|
438
|
+
comfyui_base = None
|
|
439
|
+
|
|
440
|
+
# Build a map of config_dir -> env info
|
|
441
|
+
config_envs = []
|
|
442
|
+
for config_file in config_files:
|
|
443
|
+
config_dir = config_file.parent
|
|
444
|
+
env_dir = _find_env_dir(config_dir)
|
|
445
|
+
site_packages, lib_dir = _find_env_paths(config_dir)
|
|
446
|
+
|
|
447
|
+
if not env_dir or not site_packages:
|
|
448
|
+
continue
|
|
449
|
+
|
|
450
|
+
# Read env_vars from config
|
|
451
|
+
env_vars = {}
|
|
452
|
+
try:
|
|
453
|
+
import tomli
|
|
454
|
+
with open(config_file, "rb") as f:
|
|
455
|
+
config = tomli.load(f)
|
|
456
|
+
env_vars_data = config.get("env_vars", {})
|
|
457
|
+
env_vars = {str(k): str(v) for k, v in env_vars_data.items()}
|
|
458
|
+
except Exception:
|
|
459
|
+
pass
|
|
460
|
+
|
|
461
|
+
if comfyui_base:
|
|
462
|
+
env_vars["COMFYUI_BASE"] = str(comfyui_base)
|
|
463
|
+
|
|
464
|
+
config_envs.append({
|
|
465
|
+
"config_dir": config_dir,
|
|
466
|
+
"env_dir": env_dir,
|
|
467
|
+
"site_packages": site_packages,
|
|
468
|
+
"lib_dir": lib_dir,
|
|
469
|
+
"env_vars": env_vars,
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
if not config_envs:
|
|
473
|
+
return
|
|
474
|
+
|
|
475
|
+
# Match nodes to configs by checking source file location
|
|
476
|
+
wrapped_count = 0
|
|
477
|
+
for node_name, node_cls in node_class_mappings.items():
|
|
478
|
+
if not hasattr(node_cls, "FUNCTION"):
|
|
479
|
+
continue
|
|
480
|
+
|
|
481
|
+
# Get node's source file
|
|
482
|
+
try:
|
|
483
|
+
source_file = Path(inspect.getfile(node_cls)).resolve()
|
|
484
|
+
except (TypeError, OSError):
|
|
485
|
+
continue
|
|
486
|
+
|
|
487
|
+
# Find which config this node belongs to
|
|
488
|
+
for env_info in config_envs:
|
|
489
|
+
config_dir = env_info["config_dir"]
|
|
490
|
+
try:
|
|
491
|
+
source_file.relative_to(config_dir)
|
|
492
|
+
# Node is under this config dir - wrap it
|
|
493
|
+
sys_path = [str(env_info["site_packages"]), str(config_dir)]
|
|
494
|
+
lib_path = str(env_info["lib_dir"]) if env_info["lib_dir"] else None
|
|
495
|
+
|
|
496
|
+
_wrap_node_class(
|
|
497
|
+
node_cls,
|
|
498
|
+
env_info["env_dir"],
|
|
499
|
+
config_dir,
|
|
500
|
+
sys_path,
|
|
501
|
+
lib_path,
|
|
502
|
+
env_info["env_vars"],
|
|
503
|
+
)
|
|
504
|
+
wrapped_count += 1
|
|
505
|
+
break
|
|
506
|
+
except ValueError:
|
|
507
|
+
continue # Node not under this config dir
|
|
508
|
+
|
|
509
|
+
if wrapped_count > 0:
|
|
510
|
+
print(f"[comfy-env] Wrapped {wrapped_count} nodes for isolation")
|
|
511
|
+
|
|
512
|
+
|
|
394
513
|
def wrap_isolated_nodes(
|
|
395
514
|
node_class_mappings: Dict[str, type],
|
|
396
515
|
nodes_dir: Path,
|
|
@@ -425,6 +544,11 @@ def wrap_isolated_nodes(
|
|
|
425
544
|
wrap_isolated_nodes(cgal_nodes, Path(__file__).parent / "nodes/cgal")
|
|
426
545
|
)
|
|
427
546
|
"""
|
|
547
|
+
# Skip if isolation is disabled
|
|
548
|
+
if not _is_comfy_env_enabled():
|
|
549
|
+
print(f"[comfy-env] Isolation disabled, nodes running in main process")
|
|
550
|
+
return node_class_mappings
|
|
551
|
+
|
|
428
552
|
# Skip if running inside worker subprocess
|
|
429
553
|
if os.environ.get("COMFYUI_ISOLATION_WORKER") == "1":
|
|
430
554
|
return node_class_mappings
|
|
@@ -447,12 +571,9 @@ def wrap_isolated_nodes(
|
|
|
447
571
|
# Read env_vars from comfy-env.toml
|
|
448
572
|
env_vars = {}
|
|
449
573
|
try:
|
|
450
|
-
|
|
451
|
-
import tomllib
|
|
452
|
-
else:
|
|
453
|
-
import tomli as tomllib
|
|
574
|
+
import tomli
|
|
454
575
|
with open(config_file, "rb") as f:
|
|
455
|
-
config =
|
|
576
|
+
config = tomli.load(f)
|
|
456
577
|
env_vars_data = config.get("env_vars", {})
|
|
457
578
|
env_vars = {str(k): str(v) for k, v in env_vars_data.items()}
|
|
458
579
|
except Exception:
|
comfy_env/nodes.py
CHANGED
comfy_env/pixi/core.py
CHANGED
|
@@ -18,7 +18,7 @@ import urllib.request
|
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from typing import Any, Callable, Dict, List, Optional
|
|
20
20
|
|
|
21
|
-
from ..config.
|
|
21
|
+
from ..config.parser import ComfyEnvConfig
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
# Pixi download URLs by platform
|
|
@@ -37,7 +37,6 @@ CUDA_WHEELS_INDEX = "https://pozzettiandrea.github.io/cuda-wheels/"
|
|
|
37
37
|
CUDA_TORCH_MAP = {
|
|
38
38
|
"12.8": "2.8",
|
|
39
39
|
"12.4": "2.4",
|
|
40
|
-
"12.1": "2.4",
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
def find_wheel_url(
|
comfy_env/prestartup.py
CHANGED
|
@@ -20,24 +20,16 @@ def get_env_name(dir_name: str) -> str:
|
|
|
20
20
|
def _load_env_vars(config_path: str) -> Dict[str, str]:
|
|
21
21
|
"""
|
|
22
22
|
Load [env_vars] section from comfy-env.toml.
|
|
23
|
-
|
|
24
|
-
Uses tomllib (Python 3.11+) or tomli fallback.
|
|
25
23
|
Returns empty dict if file not found or parsing fails.
|
|
26
24
|
"""
|
|
27
25
|
if not os.path.exists(config_path):
|
|
28
26
|
return {}
|
|
29
27
|
|
|
30
28
|
try:
|
|
31
|
-
|
|
32
|
-
import tomllib
|
|
33
|
-
else:
|
|
34
|
-
try:
|
|
35
|
-
import tomli as tomllib
|
|
36
|
-
except ImportError:
|
|
37
|
-
return {}
|
|
29
|
+
import tomli
|
|
38
30
|
|
|
39
31
|
with open(config_path, "rb") as f:
|
|
40
|
-
data =
|
|
32
|
+
data = tomli.load(f)
|
|
41
33
|
|
|
42
34
|
env_vars_data = data.get("env_vars", {})
|
|
43
35
|
return {str(k): str(v) for k, v in env_vars_data.items()}
|
|
@@ -95,6 +87,12 @@ def _dedupe_libomp_macos():
|
|
|
95
87
|
pass # Permission denied, etc.
|
|
96
88
|
|
|
97
89
|
|
|
90
|
+
def _is_comfy_env_enabled() -> bool:
|
|
91
|
+
"""Check if comfy-env isolation is enabled (default: True)."""
|
|
92
|
+
val = os.environ.get("USE_COMFY_ENV", "1").lower()
|
|
93
|
+
return val not in ("0", "false", "no", "off")
|
|
94
|
+
|
|
95
|
+
|
|
98
96
|
def setup_env(node_dir: Optional[str] = None) -> None:
|
|
99
97
|
"""
|
|
100
98
|
Set up environment for pixi conda libraries.
|
|
@@ -112,6 +110,10 @@ def setup_env(node_dir: Optional[str] = None) -> None:
|
|
|
112
110
|
from comfy_env import setup_env
|
|
113
111
|
setup_env()
|
|
114
112
|
"""
|
|
113
|
+
# Skip if isolation is disabled
|
|
114
|
+
if not _is_comfy_env_enabled():
|
|
115
|
+
return
|
|
116
|
+
|
|
115
117
|
# macOS: Dedupe libomp to prevent OpenMP conflicts (torch vs pymeshlab, etc.)
|
|
116
118
|
_dedupe_libomp_macos()
|
|
117
119
|
|
|
@@ -137,12 +139,9 @@ def setup_env(node_dir: Optional[str] = None) -> None:
|
|
|
137
139
|
marker_path = os.path.join(node_dir, ".comfy-env-marker.toml")
|
|
138
140
|
if os.path.exists(marker_path):
|
|
139
141
|
try:
|
|
140
|
-
|
|
141
|
-
import tomllib
|
|
142
|
-
else:
|
|
143
|
-
import tomli as tomllib
|
|
142
|
+
import tomli
|
|
144
143
|
with open(marker_path, "rb") as f:
|
|
145
|
-
marker =
|
|
144
|
+
marker = tomli.load(f)
|
|
146
145
|
env_path = marker.get("env", {}).get("path")
|
|
147
146
|
if env_path and os.path.exists(env_path):
|
|
148
147
|
pixi_env = env_path
|
|
@@ -190,3 +189,20 @@ def setup_env(node_dir: Optional[str] = None) -> None:
|
|
|
190
189
|
|
|
191
190
|
if site_packages and os.path.exists(site_packages) and site_packages not in sys.path:
|
|
192
191
|
sys.path.insert(0, site_packages)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def copy_files(src, dst, pattern: str = "*") -> None:
|
|
195
|
+
"""Copy files matching pattern from src to dst (skip existing)."""
|
|
196
|
+
import shutil
|
|
197
|
+
|
|
198
|
+
src, dst = Path(src), Path(dst)
|
|
199
|
+
if not src.exists():
|
|
200
|
+
return
|
|
201
|
+
|
|
202
|
+
dst.mkdir(parents=True, exist_ok=True)
|
|
203
|
+
for f in src.glob(pattern):
|
|
204
|
+
if f.is_file():
|
|
205
|
+
target = dst / f.relative_to(src)
|
|
206
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
207
|
+
if not target.exists():
|
|
208
|
+
shutil.copy2(f, target)
|
comfy_env/workers/subprocess.py
CHANGED
|
@@ -440,7 +440,7 @@ def _watchdog():
|
|
|
440
440
|
f.flush()
|
|
441
441
|
|
|
442
442
|
# Also print
|
|
443
|
-
print(f"\\n=== WATCHDOG TICK {tick} ===", flush=True)
|
|
443
|
+
print(f"\\n=== WATCHDOG TICK {tick} (debug only, don't worry) ===", flush=True)
|
|
444
444
|
print(dump, flush=True)
|
|
445
445
|
print("=== END ===\\n", flush=True)
|
|
446
446
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comfy-env
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.15
|
|
4
4
|
Summary: Environment management for ComfyUI custom nodes - CUDA wheel resolution and process isolation
|
|
5
5
|
Project-URL: Homepage, https://github.com/PozzettiAndrea/comfy-env
|
|
6
6
|
Project-URL: Repository, https://github.com/PozzettiAndrea/comfy-env
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
19
19
|
Requires-Python: >=3.10
|
|
20
20
|
Requires-Dist: pip>=21.0
|
|
21
21
|
Requires-Dist: tomli-w>=1.0.0
|
|
22
|
-
Requires-Dist: tomli>=2.0.0
|
|
22
|
+
Requires-Dist: tomli>=2.0.0
|
|
23
23
|
Requires-Dist: uv>=0.4.0
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Requires-Dist: mypy; extra == 'dev'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
comfy_env/__init__.py,sha256=vtMEMhys8esoSXM3H5pFJGecE_ZoDwPS0foeEzlbmZA,2331
|
|
2
|
+
comfy_env/cache.py,sha256=LnOVGCheF0hM-JZcX_-HD46o_nA7U2SIptdOT1TQkBE,6293
|
|
3
|
+
comfy_env/cli.py,sha256=UJbPbCEKfAAoZ_J0JeUs4jVsWuJ8BeR6CV6XtCSuy1g,12707
|
|
4
|
+
comfy_env/install.py,sha256=nuG3z5V1PQ4IoXKknLfS9sUKAUq0RHcpZp7jvdOTgIY,14853
|
|
5
|
+
comfy_env/nodes.py,sha256=tqMBf3hTjtgbT9sdcUiNnMaiFNPsHWtw79_TgvsrU9Q,5392
|
|
6
|
+
comfy_env/prestartup.py,sha256=Aw8yvmkraP3bRXPTZKOFnhUHLNtGujAZ4aD76nKx6pA,7215
|
|
7
|
+
comfy_env/config/__init__.py,sha256=_udIO2AkntkFfktst1uKqRkLdne1cXf2b0BrErvNT_k,289
|
|
8
|
+
comfy_env/config/parser.py,sha256=B9iK3RQdErAHnmvD_jfZm87u5K5gTnEwFDMdOXil3YM,3458
|
|
9
|
+
comfy_env/isolation/__init__.py,sha256=Fy8A7_5plxcCMFOf00cJlEMbRVu8aKFkTo0Spj31YqI,206
|
|
10
|
+
comfy_env/isolation/wrap.py,sha256=vJz75TtS6NMyfxX_UlqNdZNQQYROHP9KbcghmNIPyFM,20046
|
|
11
|
+
comfy_env/pixi/__init__.py,sha256=BUrq7AQf3WDm0cHWh72B2xZbURNnDu2dCuELWiQCUiM,997
|
|
12
|
+
comfy_env/pixi/core.py,sha256=LY2wrvMNqO-cp9MOgixvpe1mJKtGK3U311-0rbURTBo,21770
|
|
13
|
+
comfy_env/pixi/cuda_detection.py,sha256=sqB3LjvGNdV4eFqiARQGfyecBM3ZiUmeh6nG0YCRYQw,9751
|
|
14
|
+
comfy_env/pixi/resolver.py,sha256=U_A8rBDxCj4gUlJt2YJQniP4cCKqxJEiVFgXOoH7vM8,6339
|
|
15
|
+
comfy_env/pixi/platform/__init__.py,sha256=Nb5MPZIEeanSMEWwqU4p4bnEKTJn1tWcwobnhq9x9IY,614
|
|
16
|
+
comfy_env/pixi/platform/base.py,sha256=iS0ptTTVjXRwPU4qWUdvHI7jteuzxGSjWr5BUQ7hGiU,2453
|
|
17
|
+
comfy_env/pixi/platform/darwin.py,sha256=HK3VkLT6DfesAnIXwx2IaUFHTBclF0xTQnC7azWY6Kc,1552
|
|
18
|
+
comfy_env/pixi/platform/linux.py,sha256=xLp8FEbFqZLQrzIZBI9z3C4g23Ab1ASTHLsXDzsdCoA,2062
|
|
19
|
+
comfy_env/pixi/platform/windows.py,sha256=FCOCgpzGzorY9-HueMlJUR8DxM2eH-cj9iZk6K026Is,10891
|
|
20
|
+
comfy_env/templates/comfy-env-instructions.txt,sha256=ve1RAthW7ouumU9h6DM7mIRX1MS8_Tyonq2U4tcrFu8,1031
|
|
21
|
+
comfy_env/templates/comfy-env.toml,sha256=ROIqi4BlPL1MEdL1VgebfTHpdwPNYGHwWeigI9Kw-1I,4831
|
|
22
|
+
comfy_env/workers/__init__.py,sha256=TMVG55d2XLP1mJ3x1d16H0SBDJZtk2kMC5P4HLk9TrA,1073
|
|
23
|
+
comfy_env/workers/base.py,sha256=4ZYTaQ4J0kBHCoO_OfZnsowm4rJCoqinZUaOtgkOPbw,2307
|
|
24
|
+
comfy_env/workers/mp.py,sha256=R0XWsiHv8gswxa_-iNHU14o_9Og0RFG0QnY9DRZzn2c,34060
|
|
25
|
+
comfy_env/workers/subprocess.py,sha256=FvhEWilFWkjYNVDm7mmbFmXiSYB7eT5Tl2uvJ_23qnc,57154
|
|
26
|
+
comfy_env/workers/tensor_utils.py,sha256=TCuOAjJymrSbkgfyvcKtQ_KbVWTqSwP9VH_bCaFLLq8,6409
|
|
27
|
+
comfy_env-0.1.15.dist-info/METADATA,sha256=HMJQ4qs9ObD6YpTGffqmUACR67_kzcWv392WpdNASzc,6946
|
|
28
|
+
comfy_env-0.1.15.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
29
|
+
comfy_env-0.1.15.dist-info/entry_points.txt,sha256=J4fXeqgxU_YenuW_Zxn_pEL7J-3R0--b6MS5t0QmAr0,49
|
|
30
|
+
comfy_env-0.1.15.dist-info/licenses/LICENSE,sha256=E68QZMMpW4P2YKstTZ3QU54HRQO8ecew09XZ4_Vn870,1093
|
|
31
|
+
comfy_env-0.1.15.dist-info/RECORD,,
|
comfy_env/config/types.py
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"""Configuration types for comfy-env."""
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass, field
|
|
4
|
-
from typing import Any, Dict, List, Optional
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@dataclass
|
|
8
|
-
class NodeReq:
|
|
9
|
-
"""A node dependency (another ComfyUI custom node)."""
|
|
10
|
-
name: str
|
|
11
|
-
repo: str # GitHub repo, e.g., "owner/repo"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@dataclass
|
|
15
|
-
class ComfyEnvConfig:
|
|
16
|
-
"""
|
|
17
|
-
Configuration from comfy-env.toml.
|
|
18
|
-
|
|
19
|
-
comfy-env.toml is a superset of pixi.toml. Custom sections we handle:
|
|
20
|
-
- python = "3.11" - Python version for isolated envs
|
|
21
|
-
- [cuda] packages = [...] - CUDA packages (triggers find-links + PyTorch detection)
|
|
22
|
-
- [node_reqs] - Other ComfyUI nodes to clone
|
|
23
|
-
|
|
24
|
-
Everything else passes through to pixi.toml directly:
|
|
25
|
-
- [dependencies] - conda packages
|
|
26
|
-
- [pypi-dependencies] - pip packages
|
|
27
|
-
- [target.linux-64.pypi-dependencies] - platform-specific deps
|
|
28
|
-
- Any other pixi.toml syntax
|
|
29
|
-
|
|
30
|
-
Example config:
|
|
31
|
-
python = "3.11"
|
|
32
|
-
|
|
33
|
-
[cuda]
|
|
34
|
-
packages = ["cumesh"]
|
|
35
|
-
|
|
36
|
-
[dependencies]
|
|
37
|
-
mesalib = "*"
|
|
38
|
-
cgal = "*"
|
|
39
|
-
|
|
40
|
-
[pypi-dependencies]
|
|
41
|
-
numpy = ">=1.21.0,<2"
|
|
42
|
-
trimesh = { version = ">=4.0.0", extras = ["easy"] }
|
|
43
|
-
|
|
44
|
-
[target.linux-64.pypi-dependencies]
|
|
45
|
-
embreex = "*"
|
|
46
|
-
|
|
47
|
-
[node_reqs]
|
|
48
|
-
SomeNode = "owner/repo"
|
|
49
|
-
"""
|
|
50
|
-
# python = "3.11" - Python version (for isolated envs)
|
|
51
|
-
python: Optional[str] = None
|
|
52
|
-
|
|
53
|
-
# [cuda] - CUDA packages (installed via find-links index)
|
|
54
|
-
cuda_packages: List[str] = field(default_factory=list)
|
|
55
|
-
|
|
56
|
-
# [apt] - System packages to install via apt (Linux only)
|
|
57
|
-
apt_packages: List[str] = field(default_factory=list)
|
|
58
|
-
|
|
59
|
-
# [env_vars] - Environment variables to set early (in prestartup)
|
|
60
|
-
env_vars: Dict[str, str] = field(default_factory=dict)
|
|
61
|
-
|
|
62
|
-
# [node_reqs] - other ComfyUI nodes to clone
|
|
63
|
-
node_reqs: List[NodeReq] = field(default_factory=list)
|
|
64
|
-
|
|
65
|
-
# Everything else from comfy-env.toml passes through to pixi.toml
|
|
66
|
-
pixi_passthrough: Dict[str, Any] = field(default_factory=dict)
|
|
67
|
-
|
|
68
|
-
@property
|
|
69
|
-
def has_cuda(self) -> bool:
|
|
70
|
-
return bool(self.cuda_packages)
|