comfy-env 0.1.20__py3-none-any.whl → 0.1.22__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 CHANGED
@@ -108,7 +108,6 @@ from .isolation import (
108
108
  # Workers
109
109
  Worker,
110
110
  WorkerError,
111
- MPWorker,
112
111
  SubprocessWorker,
113
112
  # Tensor utilities
114
113
  TensorKeeper,
@@ -168,7 +167,6 @@ __all__ = [
168
167
  # Workers
169
168
  "Worker",
170
169
  "WorkerError",
171
- "MPWorker",
172
170
  "SubprocessWorker",
173
171
  "TensorKeeper",
174
172
  ]
comfy_env/cli.py CHANGED
@@ -44,6 +44,9 @@ def main(args: Optional[List[str]] = None) -> int:
44
44
  p.add_argument("--config", "-c", type=str, help="Config path")
45
45
  p.add_argument("--dry-run", action="store_true", help="Preview only")
46
46
 
47
+ # cleanup
48
+ sub.add_parser("cleanup", help="Remove orphaned environments")
49
+
47
50
  parsed = parser.parse_args(args)
48
51
  if not parsed.command:
49
52
  parser.print_help()
@@ -52,6 +55,7 @@ def main(args: Optional[List[str]] = None) -> int:
52
55
  commands = {
53
56
  "init": cmd_init, "generate": cmd_generate, "install": cmd_install,
54
57
  "info": cmd_info, "doctor": cmd_doctor, "apt-install": cmd_apt_install,
58
+ "cleanup": cmd_cleanup,
55
59
  }
56
60
 
57
61
  try:
@@ -237,5 +241,16 @@ def cmd_apt_install(args) -> int:
237
241
  return result.returncode
238
242
 
239
243
 
244
+ def cmd_cleanup(args) -> int:
245
+ from .environment.cache import cleanup_orphaned_envs
246
+ print("Cleaning orphaned environments...")
247
+ cleaned = cleanup_orphaned_envs()
248
+ if cleaned:
249
+ print(f"Removed {cleaned} orphaned environment(s)")
250
+ else:
251
+ print("No orphaned environments found")
252
+ return 0
253
+
254
+
240
255
  if __name__ == "__main__":
241
256
  sys.exit(main())
comfy_env/install.py CHANGED
@@ -116,9 +116,12 @@ def _install_via_pixi(cfg: ComfyEnvConfig, node_dir: Path, log: Callable[[str],
116
116
  from .packages.toml_generator import write_pixi_toml
117
117
  from .packages.cuda_wheels import get_wheel_url, CUDA_TORCH_MAP
118
118
  from .detection import get_recommended_cuda_version
119
- from .environment.cache import get_central_env_path, write_marker, write_env_metadata, MARKER_FILE, get_cache_dir
119
+ from .environment.cache import get_central_env_path, write_marker, write_env_metadata, MARKER_FILE, get_cache_dir, cleanup_orphaned_envs
120
120
  import shutil, subprocess, sys
121
121
 
122
+ # Clean up orphaned environments before installing
123
+ cleanup_orphaned_envs(log)
124
+
122
125
  deps = cfg.pixi_passthrough.get("dependencies", {})
123
126
  pypi_deps = cfg.pixi_passthrough.get("pypi-dependencies", {})
124
127
  if not cfg.cuda_packages and not deps and not pypi_deps:
@@ -11,7 +11,6 @@ from .wrap import (
11
11
  from .workers import (
12
12
  Worker,
13
13
  WorkerError,
14
- MPWorker,
15
14
  SubprocessWorker,
16
15
  )
17
16
  from .tensor_utils import (
@@ -29,7 +28,6 @@ __all__ = [
29
28
  # Workers
30
29
  "Worker",
31
30
  "WorkerError",
32
- "MPWorker",
33
31
  "SubprocessWorker",
34
32
  # Tensor utilities
35
33
  "TensorKeeper",
@@ -1,16 +1,14 @@
1
1
  """
2
2
  Workers - Process isolation implementations.
3
3
 
4
- Provides multiprocessing and subprocess-based workers for isolated execution.
4
+ Provides subprocess-based workers for isolated execution.
5
5
  """
6
6
 
7
7
  from .base import Worker, WorkerError
8
- from .mp import MPWorker
9
8
  from .subprocess import SubprocessWorker
10
9
 
11
10
  __all__ = [
12
11
  "Worker",
13
12
  "WorkerError",
14
- "MPWorker",
15
13
  "SubprocessWorker",
16
14
  ]
@@ -16,7 +16,7 @@ class Worker(ABC):
16
16
 
17
17
  Workers should be used as context managers when possible:
18
18
 
19
- with MPWorker() as worker:
19
+ with SubprocessWorker(python="/path/to/venv/bin/python") as worker:
20
20
  result = worker.call(my_func, arg1, arg2)
21
21
  """
22
22
 
@@ -297,6 +297,45 @@ def _to_shm(obj, registry, visited=None):
297
297
  return obj
298
298
 
299
299
 
300
+ def _deserialize_tensor_ref(data):
301
+ """Deserialize tensor from PyTorch shared memory (TensorRef format)."""
302
+ import torch
303
+ import torch.multiprocessing.reductions as reductions
304
+
305
+ dtype_str = data["dtype"]
306
+ dtype = getattr(torch, dtype_str.split(".")[-1])
307
+
308
+ manager_path = data["manager_path"]
309
+ storage_key = data["storage_key"]
310
+ storage_size = data["storage_size"]
311
+
312
+ # Encode to bytes if needed
313
+ if isinstance(manager_path, str):
314
+ manager_path = manager_path.encode("utf-8")
315
+ if isinstance(storage_key, str):
316
+ storage_key = storage_key.encode("utf-8")
317
+
318
+ # Rebuild storage from shared memory file
319
+ rebuilt_storage = reductions.rebuild_storage_filename(
320
+ torch.UntypedStorage, manager_path, storage_key, storage_size
321
+ )
322
+
323
+ # Wrap in TypedStorage
324
+ typed_storage = torch.storage.TypedStorage(
325
+ wrap_storage=rebuilt_storage, dtype=dtype, _internal=True
326
+ )
327
+
328
+ # Rebuild tensor
329
+ metadata = (
330
+ data["tensor_offset"],
331
+ tuple(data["tensor_size"]),
332
+ tuple(data["tensor_stride"]),
333
+ data["requires_grad"],
334
+ )
335
+ tensor = reductions.rebuild_tensor(torch.Tensor, typed_storage, metadata)
336
+ return tensor
337
+
338
+
300
339
  def _from_shm(obj, unlink=True):
301
340
  """Reconstruct object from shared memory metadata."""
302
341
  if not isinstance(obj, dict):
@@ -304,7 +343,15 @@ def _from_shm(obj, unlink=True):
304
343
  return [_from_shm(v, unlink) for v in obj]
305
344
  return obj
306
345
 
307
- # numpy array (or tensor that was converted to numpy)
346
+ # TensorRef -> use PyTorch's native deserialization (new format)
347
+ if obj.get("__type__") == "TensorRef":
348
+ tensor = _deserialize_tensor_ref(obj)
349
+ # Convert back to numpy if it was originally numpy
350
+ if obj.get("__was_numpy__"):
351
+ return tensor.numpy()
352
+ return tensor
353
+
354
+ # numpy array (or tensor that was converted to numpy) - legacy format
308
355
  if "__shm_np__" in obj:
309
356
  block = shm.SharedMemory(name=obj["__shm_np__"])
310
357
  arr = np.ndarray(tuple(obj["shape"]), dtype=np.dtype(obj["dtype"]), buffer=block.buf).copy()
@@ -362,10 +409,10 @@ def _serialize_for_ipc(obj, visited=None):
362
409
  if obj_id in visited:
363
410
  return visited[obj_id] # Return cached serialized result
364
411
 
365
- # Handle Path objects - convert to string for JSON serialization
412
+ # Handle Path objects - mark for reconstruction
366
413
  from pathlib import PurePath
367
414
  if isinstance(obj, PurePath):
368
- return str(obj)
415
+ return {"__path__": str(obj)}
369
416
 
370
417
  # Check if this is a custom object with broken module path
371
418
  if (hasattr(obj, '__dict__') and
@@ -434,6 +481,8 @@ import socket
434
481
  import struct
435
482
  import traceback
436
483
  import faulthandler
484
+ import collections
485
+ import time
437
486
  from types import SimpleNamespace
438
487
 
439
488
  # Enable faulthandler to dump traceback on SIGSEGV/SIGABRT/etc
@@ -533,6 +582,34 @@ if sys.platform == "win32":
533
582
  from multiprocessing import shared_memory as shm
534
583
  import numpy as np
535
584
 
585
+ # Set PyTorch to use file_system sharing (uses /dev/shm, no resource_tracker)
586
+ try:
587
+ import torch
588
+ import torch.multiprocessing as mp
589
+ mp.set_sharing_strategy("file_system")
590
+ wlog("[worker] PyTorch sharing strategy set to file_system")
591
+ except ImportError:
592
+ wlog("[worker] PyTorch not available")
593
+
594
+
595
+ # Tensor keeper - holds tensor references to prevent GC before parent reads shared memory
596
+ class TensorKeeper:
597
+ """Keep tensors alive for a retention period to prevent shared memory deletion."""
598
+ def __init__(self, retention_seconds=30.0):
599
+ self.retention_seconds = retention_seconds
600
+ self._keeper = collections.deque()
601
+ self._lock = threading.Lock()
602
+
603
+ def keep(self, t):
604
+ now = time.time()
605
+ with self._lock:
606
+ self._keeper.append((now, t))
607
+ # Cleanup old entries
608
+ while self._keeper and now - self._keeper[0][0] > self.retention_seconds:
609
+ self._keeper.popleft()
610
+
611
+ _tensor_keeper = TensorKeeper()
612
+
536
613
 
537
614
  def _prepare_trimesh_for_pickle(mesh):
538
615
  """
@@ -548,6 +625,43 @@ def _prepare_trimesh_for_pickle(mesh):
548
625
  return mesh
549
626
 
550
627
 
628
+ def _serialize_tensor_native(t, registry):
629
+ """Serialize tensor using PyTorch's native shared memory (no resource_tracker)."""
630
+ import torch
631
+ import torch.multiprocessing.reductions as reductions
632
+
633
+ # Keep tensor alive until parent reads it
634
+ _tensor_keeper.keep(t)
635
+
636
+ # Put tensor in shared memory via PyTorch's manager
637
+ if not t.is_shared():
638
+ t.share_memory_()
639
+
640
+ storage = t.untyped_storage()
641
+ sfunc, sargs = reductions.reduce_storage(storage)
642
+
643
+ if sfunc.__name__ == "rebuild_storage_filename":
644
+ # sargs: (cls, manager_path, storage_key, size)
645
+ return {
646
+ "__type__": "TensorRef",
647
+ "strategy": "file_system",
648
+ "manager_path": sargs[1].decode("utf-8") if isinstance(sargs[1], bytes) else sargs[1],
649
+ "storage_key": sargs[2].decode("utf-8") if isinstance(sargs[2], bytes) else sargs[2],
650
+ "storage_size": sargs[3],
651
+ "dtype": str(t.dtype),
652
+ "tensor_size": list(t.size()),
653
+ "tensor_stride": list(t.stride()),
654
+ "tensor_offset": t.storage_offset(),
655
+ "requires_grad": t.requires_grad,
656
+ }
657
+ else:
658
+ # Fallback: force file_system strategy
659
+ import torch.multiprocessing as mp
660
+ mp.set_sharing_strategy("file_system")
661
+ t.share_memory_()
662
+ return _serialize_tensor_native(t, registry)
663
+
664
+
551
665
  def _to_shm(obj, registry, visited=None):
552
666
  """Serialize to shared memory. Returns JSON-safe metadata."""
553
667
  if visited is None:
@@ -557,22 +671,26 @@ def _to_shm(obj, registry, visited=None):
557
671
  return visited[obj_id]
558
672
  t = type(obj).__name__
559
673
 
560
- if t == 'ndarray':
561
- arr = np.ascontiguousarray(obj)
562
- block = shm.SharedMemory(create=True, size=arr.nbytes)
563
- np.ndarray(arr.shape, arr.dtype, buffer=block.buf)[:] = arr
564
- registry.append(block)
565
- result = {"__shm_np__": block.name, "shape": list(arr.shape), "dtype": str(arr.dtype)}
674
+ # Tensor -> use PyTorch's native shared memory (bypasses resource_tracker)
675
+ if t == 'Tensor':
676
+ import torch
677
+ tensor = obj.detach().cpu().contiguous()
678
+ result = _serialize_tensor_native(tensor, registry)
566
679
  visited[obj_id] = result
567
680
  return result
568
681
 
569
- if t == 'Tensor':
570
- arr = obj.detach().cpu().numpy()
571
- result = _to_shm(arr, registry, visited)
572
- result["__was_tensor__"] = True
682
+ # ndarray -> convert to tensor, use PyTorch's native shared memory
683
+ if t == 'ndarray':
684
+ import torch
685
+ arr = np.ascontiguousarray(obj)
686
+ tensor = torch.from_numpy(arr)
687
+ result = _serialize_tensor_native(tensor, registry)
688
+ result["__was_numpy__"] = True
689
+ result["numpy_dtype"] = str(arr.dtype)
690
+ visited[obj_id] = result
573
691
  return result
574
692
 
575
- # trimesh.Trimesh -> pickle -> shared memory (preserves visual, metadata, normals)
693
+ # trimesh.Trimesh -> pickle -> shared memory
576
694
  if t == 'Trimesh':
577
695
  import pickle
578
696
  obj = _prepare_trimesh_for_pickle(obj)
@@ -601,12 +719,62 @@ def _to_shm(obj, registry, visited=None):
601
719
 
602
720
  return obj
603
721
 
722
+
723
+ def _deserialize_tensor_native(data):
724
+ """Deserialize tensor from PyTorch shared memory."""
725
+ import torch
726
+ import torch.multiprocessing.reductions as reductions
727
+
728
+ dtype_str = data["dtype"]
729
+ dtype = getattr(torch, dtype_str.split(".")[-1])
730
+
731
+ manager_path = data["manager_path"]
732
+ storage_key = data["storage_key"]
733
+ storage_size = data["storage_size"]
734
+
735
+ # Encode to bytes if needed
736
+ if isinstance(manager_path, str):
737
+ manager_path = manager_path.encode("utf-8")
738
+ if isinstance(storage_key, str):
739
+ storage_key = storage_key.encode("utf-8")
740
+
741
+ # Rebuild storage from shared memory file
742
+ rebuilt_storage = reductions.rebuild_storage_filename(
743
+ torch.UntypedStorage, manager_path, storage_key, storage_size
744
+ )
745
+
746
+ # Wrap in TypedStorage
747
+ typed_storage = torch.storage.TypedStorage(
748
+ wrap_storage=rebuilt_storage, dtype=dtype, _internal=True
749
+ )
750
+
751
+ # Rebuild tensor
752
+ metadata = (
753
+ data["tensor_offset"],
754
+ tuple(data["tensor_size"]),
755
+ tuple(data["tensor_stride"]),
756
+ data["requires_grad"],
757
+ )
758
+ tensor = reductions.rebuild_tensor(torch.Tensor, typed_storage, metadata)
759
+ return tensor
760
+
761
+
604
762
  def _from_shm(obj):
605
763
  """Reconstruct from shared memory metadata. Does NOT unlink - caller handles that."""
606
764
  if not isinstance(obj, dict):
607
765
  if isinstance(obj, list):
608
766
  return [_from_shm(v) for v in obj]
609
767
  return obj
768
+
769
+ # TensorRef -> use PyTorch's native deserialization (new format, worker->parent)
770
+ if obj.get("__type__") == "TensorRef":
771
+ tensor = _deserialize_tensor_native(obj)
772
+ # Convert back to numpy if it was originally numpy
773
+ if obj.get("__was_numpy__"):
774
+ return tensor.numpy()
775
+ return tensor
776
+
777
+ # __shm_np__ -> legacy format (parent->worker, uses Python SharedMemory)
610
778
  if "__shm_np__" in obj:
611
779
  block = shm.SharedMemory(name=obj["__shm_np__"])
612
780
  arr = np.ndarray(tuple(obj["shape"]), dtype=np.dtype(obj["dtype"]), buffer=block.buf).copy()
@@ -616,13 +784,16 @@ def _from_shm(obj):
616
784
  import torch
617
785
  return torch.from_numpy(arr)
618
786
  return arr
619
- # trimesh (pickled to preserve visual, metadata, normals)
787
+
788
+ # trimesh (pickled)
620
789
  if "__shm_trimesh__" in obj:
621
790
  import pickle
622
791
  block = shm.SharedMemory(name=obj["name"])
623
792
  mesh_bytes = bytes(block.buf[:obj["size"]])
624
793
  block.close()
794
+ block.unlink()
625
795
  return pickle.loads(mesh_bytes)
796
+
626
797
  return {k: _from_shm(v) for k, v in obj.items()}
627
798
 
628
799
  def _cleanup_shm(registry):
@@ -634,6 +805,25 @@ def _cleanup_shm(registry):
634
805
  pass
635
806
  registry.clear()
636
807
 
808
+ # Shared memory keeper - holds references to prevent premature GC
809
+ class ShmKeeper:
810
+ """Keep shm blocks alive for a retention period to prevent race conditions."""
811
+ def __init__(self, retention_seconds=30.0):
812
+ self.retention_seconds = retention_seconds
813
+ self._keeper = collections.deque()
814
+ self._lock = threading.Lock()
815
+
816
+ def keep(self, blocks):
817
+ now = time.time()
818
+ with self._lock:
819
+ self._keeper.append((now, list(blocks))) # Copy the list
820
+ # Cleanup old entries
821
+ while self._keeper and now - self._keeper[0][0] > self.retention_seconds:
822
+ old_time, old_blocks = self._keeper.popleft()
823
+ _cleanup_shm(old_blocks)
824
+
825
+ _shm_keeper = ShmKeeper()
826
+
637
827
  # =============================================================================
638
828
  # Object Reference System - keep complex objects in worker, pass refs to host
639
829
  # =============================================================================
@@ -796,6 +986,9 @@ def _connect(addr):
796
986
  def _deserialize_isolated_objects(obj):
797
987
  """Reconstruct objects serialized with __isolated_object__ marker."""
798
988
  if isinstance(obj, dict):
989
+ if obj.get("__path__"):
990
+ from pathlib import Path
991
+ return Path(obj["__path__"])
799
992
  if obj.get("__isolated_object__"):
800
993
  attrs = {k: _deserialize_isolated_objects(v) for k, v in obj.get("__attrs__", {}).items()}
801
994
  ns = SimpleNamespace(**attrs)
@@ -941,6 +1134,7 @@ def main():
941
1134
  wlog(f"[worker] Creating instance...")
942
1135
  instance = object.__new__(cls)
943
1136
  if self_state:
1137
+ self_state = _deserialize_isolated_objects(self_state)
944
1138
  instance.__dict__.update(self_state)
945
1139
  wlog(f"[worker] Calling {method_name}...")
946
1140
  method = getattr(instance, method_name)
@@ -957,7 +1151,7 @@ def main():
957
1151
  wlog(f"[worker] Created {len(shm_registry)} shm blocks for result")
958
1152
 
959
1153
  transport.send({"status": "ok", "result": result_meta})
960
- # Note: don't cleanup shm_registry here - host needs to read it
1154
+ _shm_keeper.keep(shm_registry) # Keep alive for 30s until host reads
961
1155
 
962
1156
  except Exception as e:
963
1157
  # Cleanup shm on error since host won't read it
@@ -1134,7 +1328,9 @@ class SubprocessWorker(Worker):
1134
1328
  lib_dir = self.python.parent.parent / "lib"
1135
1329
  if lib_dir.is_dir():
1136
1330
  existing = env.get("LD_LIBRARY_PATH", "")
1137
- env["LD_LIBRARY_PATH"] = f"{lib_dir}:{existing}" if existing else str(lib_dir)
1331
+ # Also include system library paths so apt-installed libs (OpenGL, etc.) are found
1332
+ system_libs = "/usr/lib/x86_64-linux-gnu:/usr/lib:/lib/x86_64-linux-gnu"
1333
+ env["LD_LIBRARY_PATH"] = f"{lib_dir}:{system_libs}:{existing}" if existing else f"{lib_dir}:{system_libs}"
1138
1334
 
1139
1335
  # On Windows, pass host Python directory so worker can add it via os.add_dll_directory()
1140
1336
  # This fixes "DLL load failed" errors for packages like opencv-python-headless
@@ -72,22 +72,14 @@ def _get_worker(env_dir: Path, working_dir: Path, sys_path: list[str],
72
72
  if cache_key in _workers and _workers[cache_key].is_alive():
73
73
  return _workers[cache_key]
74
74
 
75
- host_ver = f"{sys.version_info.major}.{sys.version_info.minor}"
76
- iso_ver = _get_python_version(env_dir)
77
75
  python = env_dir / ("python.exe" if sys.platform == "win32" else "bin/python")
78
76
 
79
- if iso_ver and iso_ver != host_ver:
80
- # Different Python version - must use SubprocessWorker
81
- from .workers.subprocess import SubprocessWorker
82
- print(f"[comfy-env] SubprocessWorker: {python} ({iso_ver} vs {host_ver})")
83
- worker = SubprocessWorker(python=str(python), working_dir=working_dir, sys_path=sys_path, name=working_dir.name)
84
- else:
85
- # Same version - use MPWorker with venv Python for true isolation (like pyisolate)
86
- # This fixes Windows where spawn would otherwise re-import main.py
87
- from .workers.mp import MPWorker
88
- print(f"[comfy-env] MPWorker: {python}")
89
- worker = MPWorker(name=working_dir.name, sys_path=sys_path, lib_path=lib_path,
90
- env_vars=env_vars, python=str(python))
77
+ # Always use SubprocessWorker - MPWorker's spawn mechanism tries to re-import
78
+ # the parent's __main__ (ComfyUI's main.py), which fails with import errors.
79
+ # SubprocessWorker uses a clean entry script that avoids this issue.
80
+ from .workers.subprocess import SubprocessWorker
81
+ print(f"[comfy-env] SubprocessWorker: {python}")
82
+ worker = SubprocessWorker(python=str(python), working_dir=working_dir, sys_path=sys_path, name=working_dir.name)
91
83
 
92
84
  _workers[cache_key] = worker
93
85
  return worker
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comfy-env
3
- Version: 0.1.20
3
+ Version: 0.1.22
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
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
19
  Requires-Python: >=3.10
20
+ Requires-Dist: numpy
20
21
  Requires-Dist: pip>=21.0
21
22
  Requires-Dist: tomli-w>=1.0.0
22
23
  Requires-Dist: tomli>=2.0.0
@@ -1,6 +1,6 @@
1
- comfy_env/__init__.py,sha256=7R1WnVv6Rmq97bbK2Fvp1A50jkFwxIgcmfiILit9k8E,4666
2
- comfy_env/cli.py,sha256=SWErVa3lB2ZHc7aNJJgWElWCRMsCzVLP_CrupuOk_zw,7684
3
- comfy_env/install.py,sha256=CT3A3kIVQqXGA5nfp7jxTU_gHdsood4NsjW0tbXv7_8,10781
1
+ comfy_env/__init__.py,sha256=xm2aZVHfUct136_yGkO-Z0IHH5g8-MMMzJPvgWZxSYg,4634
2
+ comfy_env/cli.py,sha256=yO5BvNhZgRy59QVv6b0a0kzxG44BCcg9GYh0qMRbuvc,8134
3
+ comfy_env/install.py,sha256=jSfUH3f55MwUwIItkQnLRWqhd-Dk4xH2GNJB8X9SBu0,10894
4
4
  comfy_env/config/__init__.py,sha256=QlxIc5Hdghje6cm4FutReMO6fQK5rBu-zr36V2fjcLE,474
5
5
  comfy_env/config/parser.py,sha256=bNSy8Jn4VZg3xw8pldlkEyGaaI_BmNsUEYQz-hKiXgE,2221
6
6
  comfy_env/config/types.py,sha256=vFgWeEl_p26OmcoUv0wAOlHe9GBio2isjIWl7kACKFY,1096
@@ -14,13 +14,12 @@ comfy_env/environment/cache.py,sha256=RGfVW2caMO0Dd1nX2otUQP0xW3pVS7iSOP4vIUAMdE
14
14
  comfy_env/environment/libomp.py,sha256=nzr3kDnRLgcf9CZ_WF4ItWskqEDS2S0geqZS43XoKig,1319
15
15
  comfy_env/environment/paths.py,sha256=5TFFAkOZXa8R3cHfVHDEFnwy6_JcHilVBOHJuy-yqR0,1129
16
16
  comfy_env/environment/setup.py,sha256=KQgeqlEaqB_tOVhsR2RQF76-LuPud2EPtkQWUM3AJ5Y,3231
17
- comfy_env/isolation/__init__.py,sha256=XfMLEiBIcEzHG_k2vk9fT9GvFfmOsfbpM26czuxbdRI,800
17
+ comfy_env/isolation/__init__.py,sha256=6VtzWaY0B_Cpk6TQP2Lr4QUrDjBfguuhVpwCi_GByhs,768
18
18
  comfy_env/isolation/tensor_utils.py,sha256=2_f4jjylqCPaPldD1Jw-es5CyOtuF5I1ROdyEIxsg-U,2951
19
- comfy_env/isolation/wrap.py,sha256=UO5tVK-Bzp-8AVxkRd9WNU8m9lOfy_oZFkA6trHOcbM,8876
20
- comfy_env/isolation/workers/__init__.py,sha256=Zp6sZSRBcb5Negqgzqs3jPjfO9T1u3nNrQhp6WqTAuc,325
21
- comfy_env/isolation/workers/base.py,sha256=4ZYTaQ4J0kBHCoO_OfZnsowm4rJCoqinZUaOtgkOPbw,2307
22
- comfy_env/isolation/workers/mp.py,sha256=0zGDo5RxbuiSGTbTxf5qYE0tD-Sistzl48CsIOkYCdg,34777
23
- comfy_env/isolation/workers/subprocess.py,sha256=15G4rQA7bO-mmVkkeeR3we9ytHIw6kHLNdjc9XWXCu8,57650
19
+ comfy_env/isolation/wrap.py,sha256=d-JLGHHBfb6NerAtETMZouqqCSmQD3CsPpgsN8FVCac,8412
20
+ comfy_env/isolation/workers/__init__.py,sha256=rmfSuH03_BbFFy0TSBTBL9UthhzP69o3Ou8p5R0WBrw,264
21
+ comfy_env/isolation/workers/base.py,sha256=feRCKtjVtTVh1r3efZJ1cJ3rH9D1xKBCbbwLlckcBJk,2348
22
+ comfy_env/isolation/workers/subprocess.py,sha256=mvhuc2kvt3g3FP_moLHJ407IkOoZrGn-pmyk7PL95FU,64609
24
23
  comfy_env/packages/__init__.py,sha256=4pRCUnfcVFVgy7hkbPz9BPVXELtSFHha6L7n-hqNuZA,1155
25
24
  comfy_env/packages/apt.py,sha256=pxy3A5ZHv3X8ExCVyohODY8Fcy9ji4izIVPfYoxhqT4,1027
26
25
  comfy_env/packages/cuda_wheels.py,sha256=G_CnlwNcfeWlEU24aCVBpeqQQ05y8_02dDLBwBFNwII,3980
@@ -29,8 +28,8 @@ comfy_env/packages/pixi.py,sha256=RPu8x5sSOLE1CYAhWMMjoQrbFGGt00fdsbqtRcTz7LQ,38
29
28
  comfy_env/packages/toml_generator.py,sha256=Vhc8F9euHhMTwH1TV6t96-D9Pjrn9jIN4e9WXrCIFE8,3414
30
29
  comfy_env/templates/comfy-env-instructions.txt,sha256=ve1RAthW7ouumU9h6DM7mIRX1MS8_Tyonq2U4tcrFu8,1031
31
30
  comfy_env/templates/comfy-env.toml,sha256=ROIqi4BlPL1MEdL1VgebfTHpdwPNYGHwWeigI9Kw-1I,4831
32
- comfy_env-0.1.20.dist-info/METADATA,sha256=TnybPs-8qbU-3NjJxnAadtdp2mj7Pj6fjTfMA2e7PqQ,4808
33
- comfy_env-0.1.20.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
34
- comfy_env-0.1.20.dist-info/entry_points.txt,sha256=J4fXeqgxU_YenuW_Zxn_pEL7J-3R0--b6MS5t0QmAr0,49
35
- comfy_env-0.1.20.dist-info/licenses/LICENSE,sha256=E68QZMMpW4P2YKstTZ3QU54HRQO8ecew09XZ4_Vn870,1093
36
- comfy_env-0.1.20.dist-info/RECORD,,
31
+ comfy_env-0.1.22.dist-info/METADATA,sha256=0WOa_D45kdxrIhNe8cdZLGIH3_9ZrCWyRxS5Zmz9MNA,4829
32
+ comfy_env-0.1.22.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
33
+ comfy_env-0.1.22.dist-info/entry_points.txt,sha256=J4fXeqgxU_YenuW_Zxn_pEL7J-3R0--b6MS5t0QmAr0,49
34
+ comfy_env-0.1.22.dist-info/licenses/LICENSE,sha256=E68QZMMpW4P2YKstTZ3QU54HRQO8ecew09XZ4_Vn870,1093
35
+ comfy_env-0.1.22.dist-info/RECORD,,