comfy-env 0.0.67__tar.gz → 0.0.68__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.
Files changed (33) hide show
  1. {comfy_env-0.0.67 → comfy_env-0.0.68}/PKG-INFO +1 -1
  2. {comfy_env-0.0.67 → comfy_env-0.0.68}/pyproject.toml +1 -1
  3. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/core.py +21 -27
  4. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/workers/mp.py +60 -12
  5. {comfy_env-0.0.67 → comfy_env-0.0.68}/.github/workflows/publish.yml +0 -0
  6. {comfy_env-0.0.67 → comfy_env-0.0.68}/.gitignore +0 -0
  7. {comfy_env-0.0.67 → comfy_env-0.0.68}/LICENSE +0 -0
  8. {comfy_env-0.0.67 → comfy_env-0.0.68}/README.md +0 -0
  9. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/__init__.py +0 -0
  10. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/cli.py +0 -0
  11. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/config/__init__.py +0 -0
  12. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/config/parser.py +0 -0
  13. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/config/types.py +0 -0
  14. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/errors.py +0 -0
  15. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/install.py +0 -0
  16. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/isolation/__init__.py +0 -0
  17. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/isolation/wrap.py +0 -0
  18. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/nodes.py +0 -0
  19. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/__init__.py +0 -0
  20. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/cuda_detection.py +0 -0
  21. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/platform/__init__.py +0 -0
  22. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/platform/base.py +0 -0
  23. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/platform/darwin.py +0 -0
  24. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/platform/linux.py +0 -0
  25. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/platform/windows.py +0 -0
  26. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/pixi/resolver.py +0 -0
  27. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/prestartup.py +0 -0
  28. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/templates/comfy-env-instructions.txt +0 -0
  29. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/templates/comfy-env.toml +0 -0
  30. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/workers/__init__.py +0 -0
  31. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/workers/base.py +0 -0
  32. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/workers/subprocess.py +0 -0
  33. {comfy_env-0.0.67 → comfy_env-0.0.68}/src/comfy_env/workers/tensor_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comfy-env
3
- Version: 0.0.67
3
+ Version: 0.0.68
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "comfy-env"
3
- version = "0.0.67"
3
+ version = "0.0.68"
4
4
  description = "Environment management for ComfyUI custom nodes - CUDA wheel resolution and process isolation"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -252,24 +252,10 @@ def pixi_install(
252
252
  dependencies.setdefault("pip", "*") # Always include pip
253
253
  pixi_data["dependencies"] = dependencies
254
254
 
255
- # Add pypi-options for CUDA wheels
255
+ # Add pypi-options for PyTorch index (CUDA packages installed separately via pip)
256
256
  if cfg.has_cuda and cuda_version:
257
257
  pypi_options = pixi_data.get("pypi-options", {})
258
- # Merge find-links (pixi expects [{url: "..."}, ...] format)
259
- find_links = pypi_options.get("find-links", [])
260
- existing_urls = {
261
- entry.get("url") if isinstance(entry, dict) else entry
262
- for entry in find_links
263
- }
264
- if CUDA_WHEELS_INDEX not in existing_urls:
265
- find_links.append({"url": CUDA_WHEELS_INDEX})
266
- # Normalize any plain strings to {url: ...} format
267
- find_links = [
268
- {"url": entry} if isinstance(entry, str) else entry
269
- for entry in find_links
270
- ]
271
- pypi_options["find-links"] = find_links
272
- # Merge extra-index-urls
258
+ # Add PyTorch CUDA index for torch installation
273
259
  cuda_short = cuda_version.replace(".", "")[:3]
274
260
  pytorch_index = f"https://download.pytorch.org/whl/cu{cuda_short}"
275
261
  extra_urls = pypi_options.get("extra-index-urls", [])
@@ -311,23 +297,31 @@ def pixi_install(
311
297
  log(f"pixi install failed:\n{result.stderr}")
312
298
  raise RuntimeError(f"pixi install failed: {result.stderr}")
313
299
 
314
- # Install CUDA packages with --no-deps (avoids PyPI version conflicts)
300
+ # Install CUDA packages with --no-index --find-links (bypasses PyPI completely)
315
301
  if cfg.cuda_packages and cuda_version:
316
- log(f"Installing CUDA packages with --no-deps: {cfg.cuda_packages}")
302
+ log(f"Installing CUDA packages: {cfg.cuda_packages}")
317
303
  python_path = get_pixi_python(node_dir)
318
304
  if not python_path:
319
305
  raise RuntimeError("Could not find Python in pixi environment")
320
306
 
321
- pip_cmd = [
322
- str(python_path), "-m", "pip", "install",
323
- "--no-deps",
324
- "--index-url", CUDA_WHEELS_INDEX,
325
- ] + cfg.cuda_packages
307
+ for package in cfg.cuda_packages:
308
+ # Each package has its own find-links page at CUDA_WHEELS_INDEX/<package>/
309
+ find_links_url = f"{CUDA_WHEELS_INDEX}{package}/"
310
+ log(f" Installing {package} from {find_links_url}")
311
+
312
+ pip_cmd = [
313
+ str(python_path), "-m", "pip", "install",
314
+ "--no-index",
315
+ "--no-deps",
316
+ "--no-cache-dir",
317
+ "--find-links", find_links_url,
318
+ package,
319
+ ]
320
+ result = subprocess.run(pip_cmd, capture_output=True, text=True)
321
+ if result.returncode != 0:
322
+ log(f"CUDA package install failed for {package}:\n{result.stderr}")
323
+ raise RuntimeError(f"CUDA package install failed: {result.stderr}")
326
324
 
327
- result = subprocess.run(pip_cmd, capture_output=True, text=True)
328
- if result.returncode != 0:
329
- log(f"CUDA package install failed:\n{result.stderr}")
330
- raise RuntimeError(f"CUDA package install failed: {result.stderr}")
331
325
  log("CUDA packages installed")
332
326
 
333
327
  # Create symlink/junction to _env_<name> for discovery (only for isolated subdirs)
@@ -430,20 +430,68 @@ class MPWorker(Worker):
430
430
  return
431
431
 
432
432
  # Import torch here to avoid import at module level
433
+ import os
434
+ import sys
435
+
436
+ # Clear conda/pixi environment variables FIRST, before importing multiprocessing
437
+ # These can cause the child process to pick up the wrong Python interpreter
438
+ # or stdlib, leading to sys.version mismatch errors in platform module
439
+ conda_env_vars = [
440
+ 'CONDA_PREFIX',
441
+ 'CONDA_DEFAULT_ENV',
442
+ 'CONDA_PYTHON_EXE',
443
+ 'CONDA_EXE',
444
+ 'CONDA_SHLVL',
445
+ 'PYTHONHOME',
446
+ 'PYTHONPATH', # Also clear PYTHONPATH to prevent pixi paths
447
+ '_CE_CONDA',
448
+ '_CE_M',
449
+ ]
450
+ saved_env = {}
451
+ for var in conda_env_vars:
452
+ if var in os.environ:
453
+ saved_env[var] = os.environ.pop(var)
454
+
455
+ # Also remove pixi paths from LD_LIBRARY_PATH
456
+ ld_lib = os.environ.get('LD_LIBRARY_PATH', '')
457
+ if '.pixi' in ld_lib:
458
+ saved_env['LD_LIBRARY_PATH'] = ld_lib
459
+ # Filter out pixi paths
460
+ new_ld_lib = ':'.join(p for p in ld_lib.split(':') if '.pixi' not in p)
461
+ if new_ld_lib:
462
+ os.environ['LD_LIBRARY_PATH'] = new_ld_lib
463
+ else:
464
+ os.environ.pop('LD_LIBRARY_PATH', None)
465
+
433
466
  import torch.multiprocessing as mp
434
467
 
435
- # Use spawn to get clean subprocess (no inherited CUDA context)
436
- ctx = mp.get_context('spawn')
437
-
438
- self._queue_in = ctx.Queue()
439
- self._queue_out = ctx.Queue()
440
- self._process = ctx.Process(
441
- target=_worker_loop,
442
- args=(self._queue_in, self._queue_out, self._sys_path, self._lib_path),
443
- daemon=True,
444
- )
445
- self._process.start()
446
- self._started = True
468
+ try:
469
+ # Use spawn to get clean subprocess (no inherited CUDA context)
470
+ ctx = mp.get_context('spawn')
471
+
472
+ # Explicitly set the spawn executable to the current Python
473
+ # This prevents pixi/conda from hijacking the spawn process
474
+ import multiprocessing.spawn as mp_spawn
475
+ original_exe = mp_spawn.get_executable()
476
+ if original_exe != sys.executable.encode() and original_exe != sys.executable:
477
+ print(f"[comfy-env] Warning: spawn executable was {original_exe}, forcing to {sys.executable}")
478
+ mp_spawn.set_executable(sys.executable)
479
+
480
+ self._queue_in = ctx.Queue()
481
+ self._queue_out = ctx.Queue()
482
+ self._process = ctx.Process(
483
+ target=_worker_loop,
484
+ args=(self._queue_in, self._queue_out, self._sys_path, self._lib_path),
485
+ daemon=True,
486
+ )
487
+ self._process.start()
488
+ self._started = True
489
+
490
+ # Restore original executable setting
491
+ mp_spawn.set_executable(original_exe)
492
+ finally:
493
+ # Restore env vars in parent process
494
+ os.environ.update(saved_env)
447
495
 
448
496
  def call(
449
497
  self,
File without changes
File without changes
File without changes