comfy-env 0.0.51__tar.gz → 0.0.53__tar.gz
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-0.0.51 → comfy_env-0.0.53}/PKG-INFO +1 -1
- {comfy_env-0.0.51 → comfy_env-0.0.53}/pyproject.toml +1 -1
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/pixi.py +38 -4
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/stub_imports.py +18 -11
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/workers/venv.py +77 -2
- {comfy_env-0.0.51 → comfy_env-0.0.53}/.github/workflows/publish.yml +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/.gitignore +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/LICENSE +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/README.md +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/__init__.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/cli.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/decorator.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/__init__.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/config.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/config_file.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/cuda_gpu_detection.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/manager.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/platform/__init__.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/platform/base.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/platform/darwin.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/platform/linux.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/platform/windows.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/env/security.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/errors.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/install.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/ipc/__init__.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/ipc/bridge.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/ipc/protocol.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/ipc/tensor.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/ipc/torch_bridge.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/ipc/transport.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/ipc/worker.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/isolation.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/nodes.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/registry.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/resolver.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/stubs/__init__.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/stubs/comfy/__init__.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/stubs/comfy/model_management.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/stubs/comfy/utils.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/stubs/folder_paths.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/templates/comfy-env-instructions.txt +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/templates/comfy-env.toml +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/wheel_sources.yml +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/workers/__init__.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/workers/base.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/workers/pool.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/workers/tensor_utils.py +0 -0
- {comfy_env-0.0.51 → comfy_env-0.0.53}/src/comfy_env/workers/torch_mp.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comfy-env
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.53
|
|
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
|
|
@@ -203,10 +203,12 @@ def create_pixi_toml(
|
|
|
203
203
|
Returns:
|
|
204
204
|
Path to the generated pixi.toml file.
|
|
205
205
|
"""
|
|
206
|
-
if not
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
# Conda is optional - use defaults if not present
|
|
207
|
+
if env_config.conda:
|
|
208
|
+
conda = env_config.conda
|
|
209
|
+
else:
|
|
210
|
+
from comfy_env.env.config import CondaConfig
|
|
211
|
+
conda = CondaConfig(channels=["conda-forge"], packages=[])
|
|
210
212
|
pixi_toml_path = node_dir / "pixi.toml"
|
|
211
213
|
|
|
212
214
|
# Build pixi.toml content
|
|
@@ -246,6 +248,10 @@ def create_pixi_toml(
|
|
|
246
248
|
lines.append("[dependencies]")
|
|
247
249
|
lines.append(f'python = "{env_config.python}.*"')
|
|
248
250
|
|
|
251
|
+
# On Windows, use MKL BLAS to avoid OpenBLAS crashes (numpy blas_fpe_check issue)
|
|
252
|
+
if sys.platform == "win32":
|
|
253
|
+
lines.append('libblas = { version = "*", build = "*mkl" }')
|
|
254
|
+
|
|
249
255
|
for pkg in conda.packages:
|
|
250
256
|
# Parse package spec (name=version or name>=version or just name)
|
|
251
257
|
if "=" in pkg and not pkg.startswith("="):
|
|
@@ -371,6 +377,34 @@ def create_pixi_toml(
|
|
|
371
377
|
lines.append(f'{name} = {value}')
|
|
372
378
|
|
|
373
379
|
for dep in pypi_deps:
|
|
380
|
+
# Handle git dependencies in two formats:
|
|
381
|
+
# 1. pkg @ git+https://github.com/user/repo.git@commit
|
|
382
|
+
# 2. git+https://github.com/user/repo.git@commit (extract name from URL)
|
|
383
|
+
if "git+" in dep:
|
|
384
|
+
if " @ git+" in dep:
|
|
385
|
+
# Format: pkg @ git+URL@commit
|
|
386
|
+
match = re.match(r'^([a-zA-Z0-9._-]+)\s*@\s*git\+(.+?)(?:@([a-f0-9]+))?$', dep)
|
|
387
|
+
if match:
|
|
388
|
+
pkg_name = match.group(1)
|
|
389
|
+
git_url = match.group(2)
|
|
390
|
+
rev = match.group(3)
|
|
391
|
+
else:
|
|
392
|
+
# Format: git+URL@commit (extract package name from repo name)
|
|
393
|
+
match = re.match(r'^git\+(.+?)(?:@([a-f0-9]+))?$', dep)
|
|
394
|
+
if match:
|
|
395
|
+
git_url = match.group(1)
|
|
396
|
+
rev = match.group(2)
|
|
397
|
+
# Extract package name from URL (repo name without .git)
|
|
398
|
+
repo_match = re.search(r'/([^/]+?)(?:\.git)?$', git_url)
|
|
399
|
+
pkg_name = repo_match.group(1) if repo_match else git_url.split('/')[-1].replace('.git', '')
|
|
400
|
+
|
|
401
|
+
if match:
|
|
402
|
+
if rev:
|
|
403
|
+
lines.append(f'{pkg_name} = {{ git = "{git_url}", rev = "{rev}" }}')
|
|
404
|
+
else:
|
|
405
|
+
lines.append(f'{pkg_name} = {{ git = "{git_url}" }}')
|
|
406
|
+
continue
|
|
407
|
+
|
|
374
408
|
# Parse pip requirement format to pixi format
|
|
375
409
|
# Handles extras like trimesh[easy]>=4.0.0
|
|
376
410
|
name, version_spec, extras = _parse_pypi_requirement(dep)
|
|
@@ -156,19 +156,26 @@ def _get_import_names_from_pixi(node_dir: Path) -> Set[str]:
|
|
|
156
156
|
"""
|
|
157
157
|
import_names = set()
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
pixi_lib = node_dir / ".pixi" / "envs" / "default" / "lib"
|
|
159
|
+
pixi_base = node_dir / ".pixi" / "envs" / "default"
|
|
161
160
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
python_dirs = list(pixi_lib.glob("python3.*"))
|
|
167
|
-
if not python_dirs:
|
|
168
|
-
return import_names
|
|
161
|
+
# Find site-packages (different paths on Windows vs Linux)
|
|
162
|
+
# Linux: .pixi/envs/default/lib/python3.x/site-packages
|
|
163
|
+
# Windows: .pixi/envs/default/Lib/site-packages
|
|
164
|
+
site_packages = None
|
|
169
165
|
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
# Try Windows path first (Lib/site-packages)
|
|
167
|
+
win_site = pixi_base / "Lib" / "site-packages"
|
|
168
|
+
if win_site.exists():
|
|
169
|
+
site_packages = win_site
|
|
170
|
+
else:
|
|
171
|
+
# Try Linux path (lib/python3.x/site-packages)
|
|
172
|
+
pixi_lib = pixi_base / "lib"
|
|
173
|
+
if pixi_lib.exists():
|
|
174
|
+
python_dirs = list(pixi_lib.glob("python3.*"))
|
|
175
|
+
if python_dirs:
|
|
176
|
+
site_packages = python_dirs[0] / "site-packages"
|
|
177
|
+
|
|
178
|
+
if site_packages is None or not site_packages.exists():
|
|
172
179
|
return import_names
|
|
173
180
|
|
|
174
181
|
# Scan for importable modules
|
|
@@ -252,10 +252,29 @@ def _serialize_for_ipc(obj, visited=None):
|
|
|
252
252
|
# Worker script template - minimal, runs in target venv
|
|
253
253
|
_WORKER_SCRIPT = '''
|
|
254
254
|
import sys
|
|
255
|
+
import os
|
|
255
256
|
import json
|
|
256
257
|
import traceback
|
|
257
258
|
from types import SimpleNamespace
|
|
258
259
|
|
|
260
|
+
# On Windows, add DLL directories for proper library loading
|
|
261
|
+
if sys.platform == "win32" and hasattr(os, "add_dll_directory"):
|
|
262
|
+
_host_python_dir = os.environ.get("COMFYUI_HOST_PYTHON_DIR")
|
|
263
|
+
if _host_python_dir:
|
|
264
|
+
try:
|
|
265
|
+
os.add_dll_directory(_host_python_dir)
|
|
266
|
+
_dlls_dir = os.path.join(_host_python_dir, "DLLs")
|
|
267
|
+
if os.path.isdir(_dlls_dir):
|
|
268
|
+
os.add_dll_directory(_dlls_dir)
|
|
269
|
+
except Exception:
|
|
270
|
+
pass
|
|
271
|
+
_pixi_library_bin = os.environ.get("COMFYUI_PIXI_LIBRARY_BIN")
|
|
272
|
+
if _pixi_library_bin:
|
|
273
|
+
try:
|
|
274
|
+
os.add_dll_directory(_pixi_library_bin)
|
|
275
|
+
except Exception:
|
|
276
|
+
pass
|
|
277
|
+
|
|
259
278
|
def _deserialize_isolated_objects(obj):
|
|
260
279
|
"""Reconstruct objects serialized with __isolated_object__ marker."""
|
|
261
280
|
if isinstance(obj, dict):
|
|
@@ -475,12 +494,29 @@ class VenvWorker(Worker):
|
|
|
475
494
|
env.update(self.extra_env)
|
|
476
495
|
env["COMFYUI_ISOLATION_WORKER"] = "1"
|
|
477
496
|
|
|
478
|
-
# For conda/pixi environments, add lib dir to LD_LIBRARY_PATH
|
|
497
|
+
# For conda/pixi environments, add lib dir to LD_LIBRARY_PATH (Linux)
|
|
479
498
|
lib_dir = self.python.parent.parent / "lib"
|
|
480
499
|
if lib_dir.is_dir():
|
|
481
500
|
existing = env.get("LD_LIBRARY_PATH", "")
|
|
482
501
|
env["LD_LIBRARY_PATH"] = f"{lib_dir}:{existing}" if existing else str(lib_dir)
|
|
483
502
|
|
|
503
|
+
# On Windows, pass host Python directory and pixi Library/bin for DLL loading
|
|
504
|
+
if sys.platform == "win32":
|
|
505
|
+
env["COMFYUI_HOST_PYTHON_DIR"] = str(Path(sys.executable).parent)
|
|
506
|
+
|
|
507
|
+
# For pixi environments with MKL, add Library/bin to PATH for DLL loading
|
|
508
|
+
# Pixi has python.exe directly in env dir, not in Scripts/
|
|
509
|
+
env_dir = self.python.parent
|
|
510
|
+
library_bin = env_dir / "Library" / "bin"
|
|
511
|
+
if library_bin.is_dir():
|
|
512
|
+
existing_path = env.get("PATH", "")
|
|
513
|
+
env["PATH"] = f"{env_dir};{library_bin};{existing_path}"
|
|
514
|
+
env["COMFYUI_PIXI_LIBRARY_BIN"] = str(library_bin)
|
|
515
|
+
# Allow duplicate OpenMP libraries (MKL's libiomp5md.dll + PyTorch's libomp.dll)
|
|
516
|
+
env["KMP_DUPLICATE_LIB_OK"] = "TRUE"
|
|
517
|
+
# Use UTF-8 encoding for stdout/stderr to handle Unicode symbols
|
|
518
|
+
env["PYTHONIOENCODING"] = "utf-8"
|
|
519
|
+
|
|
484
520
|
# Run subprocess
|
|
485
521
|
cmd = [
|
|
486
522
|
str(self.python),
|
|
@@ -592,6 +628,15 @@ if sys.platform == "win32":
|
|
|
592
628
|
except Exception:
|
|
593
629
|
pass
|
|
594
630
|
|
|
631
|
+
# For pixi environments with MKL, add Library/bin for MKL DLLs
|
|
632
|
+
_pixi_library_bin = os.environ.get("COMFYUI_PIXI_LIBRARY_BIN")
|
|
633
|
+
if _pixi_library_bin and hasattr(os, "add_dll_directory"):
|
|
634
|
+
try:
|
|
635
|
+
os.add_dll_directory(_pixi_library_bin)
|
|
636
|
+
print(f"[worker] Added pixi Library/bin to DLL search: {_pixi_library_bin}", flush=True)
|
|
637
|
+
except Exception as e:
|
|
638
|
+
print(f"[worker] Failed to add pixi Library/bin: {e}", flush=True)
|
|
639
|
+
|
|
595
640
|
# =============================================================================
|
|
596
641
|
# Object Reference System - keep complex objects in worker, pass refs to host
|
|
597
642
|
# =============================================================================
|
|
@@ -626,8 +671,12 @@ def _should_use_reference(obj):
|
|
|
626
671
|
# Primitives - pass by value
|
|
627
672
|
if isinstance(obj, (bool, int, float, str, bytes)):
|
|
628
673
|
return False
|
|
629
|
-
# NumPy
|
|
674
|
+
# NumPy scalars - pass by value (convert to Python primitives)
|
|
630
675
|
obj_type = type(obj).__name__
|
|
676
|
+
if obj_type in ('float16', 'float32', 'float64', 'int8', 'int16', 'int32', 'int64',
|
|
677
|
+
'uint8', 'uint16', 'uint32', 'uint64', 'bool_'):
|
|
678
|
+
return False
|
|
679
|
+
# NumPy arrays and torch tensors - pass by value (they serialize well)
|
|
631
680
|
if obj_type in ('ndarray', 'Tensor'):
|
|
632
681
|
return False
|
|
633
682
|
# Dicts, lists, tuples - recurse into contents (don't ref the container)
|
|
@@ -660,6 +709,16 @@ def _serialize_result(obj, visited=None):
|
|
|
660
709
|
return [_serialize_result(v, visited) for v in obj]
|
|
661
710
|
if isinstance(obj, tuple):
|
|
662
711
|
return tuple(_serialize_result(v, visited) for v in obj)
|
|
712
|
+
|
|
713
|
+
# Convert numpy scalars to Python primitives for JSON serialization
|
|
714
|
+
obj_type = type(obj).__name__
|
|
715
|
+
if obj_type in ('float16', 'float32', 'float64'):
|
|
716
|
+
return float(obj)
|
|
717
|
+
if obj_type in ('int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64'):
|
|
718
|
+
return int(obj)
|
|
719
|
+
if obj_type == 'bool_':
|
|
720
|
+
return bool(obj)
|
|
721
|
+
|
|
663
722
|
return obj
|
|
664
723
|
|
|
665
724
|
def _deserialize_input(obj):
|
|
@@ -977,6 +1036,22 @@ class PersistentVenvWorker(Worker):
|
|
|
977
1036
|
if sys.platform == "win32":
|
|
978
1037
|
env["COMFYUI_HOST_PYTHON_DIR"] = str(Path(sys.executable).parent)
|
|
979
1038
|
|
|
1039
|
+
# For pixi environments with MKL, add Library/bin to PATH for DLL loading
|
|
1040
|
+
# MKL DLLs are in .pixi/envs/default/Library/bin/
|
|
1041
|
+
# Pixi has python.exe directly in env dir, not in Scripts/
|
|
1042
|
+
env_dir = self.python.parent
|
|
1043
|
+
library_bin = env_dir / "Library" / "bin"
|
|
1044
|
+
if library_bin.is_dir():
|
|
1045
|
+
existing_path = env.get("PATH", "")
|
|
1046
|
+
# Add env dir and Library/bin to PATH
|
|
1047
|
+
env["PATH"] = f"{env_dir};{library_bin};{existing_path}"
|
|
1048
|
+
# Also pass as env var so worker can use os.add_dll_directory()
|
|
1049
|
+
env["COMFYUI_PIXI_LIBRARY_BIN"] = str(library_bin)
|
|
1050
|
+
# Allow duplicate OpenMP libraries (MKL's libiomp5md.dll + PyTorch's libomp.dll)
|
|
1051
|
+
env["KMP_DUPLICATE_LIB_OK"] = "TRUE"
|
|
1052
|
+
# Use UTF-8 encoding for stdout/stderr to handle Unicode symbols
|
|
1053
|
+
env["PYTHONIOENCODING"] = "utf-8"
|
|
1054
|
+
|
|
980
1055
|
# Find ComfyUI base and set env var for folder_paths stub
|
|
981
1056
|
comfyui_base = self._find_comfyui_base()
|
|
982
1057
|
if comfyui_base:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|