comfy-env 0.0.49__py3-none-any.whl → 0.0.51__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 +7 -0
- comfy_env/decorator.py +252 -1
- comfy_env/env/config.py +2 -0
- comfy_env/env/config_file.py +4 -0
- comfy_env/install.py +38 -104
- comfy_env/isolation.py +297 -0
- comfy_env/pixi.py +131 -24
- comfy_env/stub_imports.py +310 -0
- comfy_env/templates/comfy-env-instructions.txt +31 -10
- comfy_env/templates/comfy-env.toml +36 -61
- comfy_env/workers/venv.py +179 -12
- {comfy_env-0.0.49.dist-info → comfy_env-0.0.51.dist-info}/METADATA +62 -4
- {comfy_env-0.0.49.dist-info → comfy_env-0.0.51.dist-info}/RECORD +16 -14
- {comfy_env-0.0.49.dist-info → comfy_env-0.0.51.dist-info}/WHEEL +0 -0
- {comfy_env-0.0.49.dist-info → comfy_env-0.0.51.dist-info}/entry_points.txt +0 -0
- {comfy_env-0.0.49.dist-info → comfy_env-0.0.51.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Import stub system for isolated node packs.
|
|
3
|
+
|
|
4
|
+
This module provides automatic import stubbing for packages that exist only
|
|
5
|
+
in the isolated pixi environment, not in the host ComfyUI Python.
|
|
6
|
+
|
|
7
|
+
How it works:
|
|
8
|
+
1. Read package names from comfy-env.toml
|
|
9
|
+
2. Look up their import names from top_level.txt in the pixi environment
|
|
10
|
+
3. Register import hooks that provide stub modules for those imports
|
|
11
|
+
4. Stubs allow class definitions to parse without the real packages
|
|
12
|
+
5. Real packages are used when FUNCTION runs in the isolated worker
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
# In node pack's __init__.py, BEFORE importing nodes:
|
|
16
|
+
from comfy_env import setup_isolated_imports
|
|
17
|
+
setup_isolated_imports(__file__)
|
|
18
|
+
|
|
19
|
+
from .nodes import NODE_CLASS_MAPPINGS # Now works!
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import sys
|
|
23
|
+
import types
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Dict, List, Optional, Set
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class _StubModule(types.ModuleType):
|
|
29
|
+
"""
|
|
30
|
+
A stub module that accepts any attribute access or call.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, name: str):
|
|
34
|
+
super().__init__(name)
|
|
35
|
+
self.__path__ = [] # Make it a package
|
|
36
|
+
self.__file__ = f"<stub:{name}>"
|
|
37
|
+
self._stub_name = name
|
|
38
|
+
|
|
39
|
+
def __getattr__(self, name: str):
|
|
40
|
+
if name.startswith('_'):
|
|
41
|
+
raise AttributeError(name)
|
|
42
|
+
return _StubObject(f"{self._stub_name}.{name}")
|
|
43
|
+
|
|
44
|
+
def __repr__(self):
|
|
45
|
+
return f"<StubModule '{self._stub_name}'>"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class _StubObject:
|
|
49
|
+
"""
|
|
50
|
+
A stub object that accepts any operation.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self, name: str = "stub"):
|
|
54
|
+
self._stub_name = name
|
|
55
|
+
|
|
56
|
+
def __getattr__(self, name: str):
|
|
57
|
+
if name.startswith('_'):
|
|
58
|
+
raise AttributeError(name)
|
|
59
|
+
return _StubObject(f"{self._stub_name}.{name}")
|
|
60
|
+
|
|
61
|
+
def __call__(self, *args, **kwargs):
|
|
62
|
+
return _StubObject(f"{self._stub_name}()")
|
|
63
|
+
|
|
64
|
+
def __iter__(self):
|
|
65
|
+
return iter([])
|
|
66
|
+
|
|
67
|
+
def __len__(self):
|
|
68
|
+
return 0
|
|
69
|
+
|
|
70
|
+
def __bool__(self):
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
def __enter__(self):
|
|
74
|
+
return self
|
|
75
|
+
|
|
76
|
+
def __exit__(self, *args):
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
def __repr__(self):
|
|
80
|
+
return f"<Stub '{self._stub_name}'>"
|
|
81
|
+
|
|
82
|
+
def __add__(self, other): return self
|
|
83
|
+
def __radd__(self, other): return self
|
|
84
|
+
def __sub__(self, other): return self
|
|
85
|
+
def __rsub__(self, other): return self
|
|
86
|
+
def __mul__(self, other): return self
|
|
87
|
+
def __rmul__(self, other): return self
|
|
88
|
+
def __truediv__(self, other): return self
|
|
89
|
+
def __rtruediv__(self, other): return self
|
|
90
|
+
def __eq__(self, other): return False
|
|
91
|
+
def __ne__(self, other): return True
|
|
92
|
+
def __lt__(self, other): return False
|
|
93
|
+
def __le__(self, other): return False
|
|
94
|
+
def __gt__(self, other): return False
|
|
95
|
+
def __ge__(self, other): return False
|
|
96
|
+
def __hash__(self): return hash(self._stub_name)
|
|
97
|
+
def __getitem__(self, key): return _StubObject(f"{self._stub_name}[{key}]")
|
|
98
|
+
def __setitem__(self, key, value): pass
|
|
99
|
+
def __contains__(self, item): return False
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class _StubFinder:
|
|
103
|
+
"""Import hook finder that provides stub modules for specified packages."""
|
|
104
|
+
|
|
105
|
+
def __init__(self, stub_packages: Set[str]):
|
|
106
|
+
self.stub_packages = stub_packages
|
|
107
|
+
|
|
108
|
+
def find_module(self, fullname: str, path=None):
|
|
109
|
+
top_level = fullname.split('.')[0]
|
|
110
|
+
if top_level in self.stub_packages:
|
|
111
|
+
return _StubLoader(self.stub_packages)
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class _StubLoader:
|
|
116
|
+
"""Import hook loader that creates stub modules."""
|
|
117
|
+
|
|
118
|
+
def __init__(self, stub_packages: Set[str]):
|
|
119
|
+
self.stub_packages = stub_packages
|
|
120
|
+
|
|
121
|
+
def load_module(self, fullname: str):
|
|
122
|
+
if fullname in sys.modules:
|
|
123
|
+
return sys.modules[fullname]
|
|
124
|
+
|
|
125
|
+
module = _StubModule(fullname)
|
|
126
|
+
module.__loader__ = self
|
|
127
|
+
|
|
128
|
+
if '.' in fullname:
|
|
129
|
+
parent = fullname.rsplit('.', 1)[0]
|
|
130
|
+
module.__package__ = parent
|
|
131
|
+
if parent not in sys.modules:
|
|
132
|
+
self.load_module(parent)
|
|
133
|
+
else:
|
|
134
|
+
module.__package__ = fullname
|
|
135
|
+
|
|
136
|
+
sys.modules[fullname] = module
|
|
137
|
+
return module
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _normalize_package_name(name: str) -> str:
|
|
141
|
+
"""Normalize package name for comparison (PEP 503)."""
|
|
142
|
+
return name.lower().replace('-', '_').replace('.', '_')
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _get_import_names_from_pixi(node_dir: Path) -> Set[str]:
|
|
146
|
+
"""
|
|
147
|
+
Get import names by scanning the pixi environment's site-packages.
|
|
148
|
+
|
|
149
|
+
Finds all importable packages by looking for:
|
|
150
|
+
1. Directories with __init__.py (packages)
|
|
151
|
+
2. .py files (single-file modules)
|
|
152
|
+
3. .so/.pyd files (extension modules)
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Set of import names that should be stubbed.
|
|
156
|
+
"""
|
|
157
|
+
import_names = set()
|
|
158
|
+
|
|
159
|
+
# Find the pixi site-packages
|
|
160
|
+
pixi_lib = node_dir / ".pixi" / "envs" / "default" / "lib"
|
|
161
|
+
|
|
162
|
+
if not pixi_lib.exists():
|
|
163
|
+
return import_names
|
|
164
|
+
|
|
165
|
+
# Find the python version directory (e.g., python3.11)
|
|
166
|
+
python_dirs = list(pixi_lib.glob("python3.*"))
|
|
167
|
+
if not python_dirs:
|
|
168
|
+
return import_names
|
|
169
|
+
|
|
170
|
+
site_packages = python_dirs[0] / "site-packages"
|
|
171
|
+
if not site_packages.exists():
|
|
172
|
+
return import_names
|
|
173
|
+
|
|
174
|
+
# Scan for importable modules
|
|
175
|
+
for item in site_packages.iterdir():
|
|
176
|
+
name = item.name
|
|
177
|
+
|
|
178
|
+
# Skip private/internal items
|
|
179
|
+
if name.startswith('_') or name.startswith('.'):
|
|
180
|
+
continue
|
|
181
|
+
|
|
182
|
+
# Skip dist-info and egg-info directories
|
|
183
|
+
if name.endswith('.dist-info') or name.endswith('.egg-info'):
|
|
184
|
+
continue
|
|
185
|
+
|
|
186
|
+
# Skip common non-module items
|
|
187
|
+
if name in {'bin', 'share', 'include', 'etc'}:
|
|
188
|
+
continue
|
|
189
|
+
|
|
190
|
+
# Package directory (has __init__.py)
|
|
191
|
+
if item.is_dir():
|
|
192
|
+
if (item / "__init__.py").exists():
|
|
193
|
+
import_names.add(name)
|
|
194
|
+
continue
|
|
195
|
+
|
|
196
|
+
# Single-file module (.py)
|
|
197
|
+
if name.endswith('.py'):
|
|
198
|
+
import_names.add(name[:-3])
|
|
199
|
+
continue
|
|
200
|
+
|
|
201
|
+
# Extension module (.so on Linux, .pyd on Windows)
|
|
202
|
+
if '.cpython-' in name and (name.endswith('.so') or name.endswith('.pyd')):
|
|
203
|
+
# Extract module name: foo.cpython-311-x86_64-linux-gnu.so -> foo
|
|
204
|
+
module_name = name.split('.')[0]
|
|
205
|
+
import_names.add(module_name)
|
|
206
|
+
continue
|
|
207
|
+
|
|
208
|
+
return import_names
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _filter_to_missing(import_names: Set[str]) -> Set[str]:
|
|
212
|
+
"""Filter to only imports not available in host Python."""
|
|
213
|
+
missing = set()
|
|
214
|
+
|
|
215
|
+
for name in import_names:
|
|
216
|
+
# Skip if already in sys.modules
|
|
217
|
+
if name in sys.modules:
|
|
218
|
+
continue
|
|
219
|
+
|
|
220
|
+
# Try to import
|
|
221
|
+
try:
|
|
222
|
+
__import__(name)
|
|
223
|
+
except ImportError:
|
|
224
|
+
missing.add(name)
|
|
225
|
+
except Exception:
|
|
226
|
+
# Other errors - don't stub, let real error surface
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
return missing
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# Track whether we've already set up stubs
|
|
233
|
+
_stub_finder: Optional[_StubFinder] = None
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def setup_isolated_imports(init_file: str) -> List[str]:
|
|
237
|
+
"""
|
|
238
|
+
Set up import stubs for packages in the pixi environment but not in host Python.
|
|
239
|
+
|
|
240
|
+
Call this BEFORE importing your nodes module.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
init_file: The __file__ of the calling module (usually __file__ from __init__.py)
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
List of import names that were stubbed.
|
|
247
|
+
|
|
248
|
+
Example:
|
|
249
|
+
from comfy_env import setup_isolated_imports
|
|
250
|
+
setup_isolated_imports(__file__)
|
|
251
|
+
|
|
252
|
+
from .nodes import NODE_CLASS_MAPPINGS # Now works!
|
|
253
|
+
"""
|
|
254
|
+
global _stub_finder
|
|
255
|
+
|
|
256
|
+
node_dir = Path(init_file).resolve().parent
|
|
257
|
+
|
|
258
|
+
# Get all import names from pixi environment
|
|
259
|
+
pixi_imports = _get_import_names_from_pixi(node_dir)
|
|
260
|
+
|
|
261
|
+
if not pixi_imports:
|
|
262
|
+
print("[comfy-env] No pixi environment found, skipping import stubbing")
|
|
263
|
+
return []
|
|
264
|
+
|
|
265
|
+
# Filter to only those missing in host
|
|
266
|
+
missing = _filter_to_missing(pixi_imports)
|
|
267
|
+
|
|
268
|
+
if not missing:
|
|
269
|
+
print("[comfy-env] All pixi packages available in host, no stubbing needed")
|
|
270
|
+
return []
|
|
271
|
+
|
|
272
|
+
# Remove old finder if exists
|
|
273
|
+
if _stub_finder is not None:
|
|
274
|
+
try:
|
|
275
|
+
sys.meta_path.remove(_stub_finder)
|
|
276
|
+
except ValueError:
|
|
277
|
+
pass
|
|
278
|
+
|
|
279
|
+
# Register new finder
|
|
280
|
+
_stub_finder = _StubFinder(missing)
|
|
281
|
+
sys.meta_path.insert(0, _stub_finder)
|
|
282
|
+
|
|
283
|
+
stubbed = sorted(missing)
|
|
284
|
+
if len(stubbed) <= 10:
|
|
285
|
+
print(f"[comfy-env] Stubbed {len(stubbed)} imports: {', '.join(stubbed)}")
|
|
286
|
+
else:
|
|
287
|
+
print(f"[comfy-env] Stubbed {len(stubbed)} imports: {', '.join(stubbed[:10])}... and {len(stubbed)-10} more")
|
|
288
|
+
|
|
289
|
+
return stubbed
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def cleanup_stubs():
|
|
293
|
+
"""Remove the stub import hooks."""
|
|
294
|
+
global _stub_finder
|
|
295
|
+
|
|
296
|
+
if _stub_finder is not None:
|
|
297
|
+
try:
|
|
298
|
+
sys.meta_path.remove(_stub_finder)
|
|
299
|
+
except ValueError:
|
|
300
|
+
pass
|
|
301
|
+
|
|
302
|
+
# Remove stubbed modules from sys.modules
|
|
303
|
+
to_remove = [
|
|
304
|
+
name for name in sys.modules
|
|
305
|
+
if isinstance(sys.modules[name], _StubModule)
|
|
306
|
+
]
|
|
307
|
+
for name in to_remove:
|
|
308
|
+
del sys.modules[name]
|
|
309
|
+
|
|
310
|
+
_stub_finder = None
|
|
@@ -31,9 +31,10 @@ Case 1: Just need CUDA packages (nvdiffrast, pytorch3d, etc.)
|
|
|
31
31
|
- Add packages to [cuda] section
|
|
32
32
|
- Call install() in your __init__.py
|
|
33
33
|
|
|
34
|
-
Case 2: Need process isolation (conflicting dependencies)
|
|
35
|
-
- Define an isolated environment
|
|
36
|
-
- Use
|
|
34
|
+
Case 2: Need process isolation (conflicting dependencies, conda packages)
|
|
35
|
+
- Define an isolated environment with `isolated = true`
|
|
36
|
+
- Use enable_isolation(NODE_CLASS_MAPPINGS) in your __init__.py
|
|
37
|
+
- See PROCESS ISOLATION section below
|
|
37
38
|
|
|
38
39
|
Case 3: Need system packages (apt)
|
|
39
40
|
- Add to [system] linux = ["package1", "package2"]
|
|
@@ -54,22 +55,42 @@ PROCESS ISOLATION
|
|
|
54
55
|
-----------------
|
|
55
56
|
For nodes that need isolated dependencies:
|
|
56
57
|
|
|
58
|
+
RECOMMENDED: Pack-wide isolation (all nodes in same isolated env)
|
|
59
|
+
|
|
60
|
+
from comfy_env import setup_isolated_imports, enable_isolation
|
|
61
|
+
|
|
62
|
+
# Setup import stubs BEFORE importing nodes
|
|
63
|
+
setup_isolated_imports(__file__)
|
|
64
|
+
|
|
65
|
+
from .nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
|
66
|
+
|
|
67
|
+
# Enable isolation for all nodes
|
|
68
|
+
enable_isolation(NODE_CLASS_MAPPINGS)
|
|
69
|
+
|
|
70
|
+
Requires `isolated = true` in comfy-env.toml:
|
|
71
|
+
|
|
72
|
+
[mypack]
|
|
73
|
+
python = "3.11"
|
|
74
|
+
isolated = true
|
|
75
|
+
|
|
76
|
+
[mypack.packages]
|
|
77
|
+
requirements = ["trimesh", "scipy"]
|
|
78
|
+
|
|
79
|
+
ALTERNATIVE: Per-node isolation (for multiple isolated envs)
|
|
80
|
+
|
|
57
81
|
from comfy_env import isolated
|
|
58
82
|
|
|
59
83
|
@isolated(env="myenv")
|
|
60
84
|
class MyNode:
|
|
61
85
|
FUNCTION = "process"
|
|
62
|
-
RETURN_TYPES = ("IMAGE",)
|
|
63
|
-
|
|
64
86
|
def process(self, image):
|
|
65
|
-
# This runs in isolated subprocess
|
|
66
87
|
import conflicting_lib
|
|
67
88
|
return (result,)
|
|
68
89
|
|
|
69
|
-
|
|
70
|
-
- Runs
|
|
71
|
-
-
|
|
72
|
-
-
|
|
90
|
+
How it works:
|
|
91
|
+
- Runs FUNCTION methods in a separate Python process
|
|
92
|
+
- Tensors/numpy arrays passed by value (efficient)
|
|
93
|
+
- Complex objects (meshes, etc.) passed by reference
|
|
73
94
|
|
|
74
95
|
|
|
75
96
|
TROUBLESHOOTING
|
|
@@ -100,82 +100,71 @@ requirements = []
|
|
|
100
100
|
#
|
|
101
101
|
# #############################################################################
|
|
102
102
|
#
|
|
103
|
-
# For nodes that need completely isolated dependencies (different
|
|
104
|
-
# version, conflicting native libraries
|
|
103
|
+
# For nodes that need completely isolated dependencies (different Python
|
|
104
|
+
# version, conda packages, conflicting native libraries), define an isolated
|
|
105
|
+
# environment with `isolated = true`.
|
|
105
106
|
#
|
|
106
|
-
#
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
# 3. The node runs in a separate subprocess with its own venv
|
|
107
|
+
# RECOMMENDED: Pack-wide isolation (all nodes in one environment)
|
|
108
|
+
# ----------------------------------------------------------------
|
|
109
|
+
# This is the simplest approach - all your nodes run in the same isolated env.
|
|
110
110
|
#
|
|
111
|
-
#
|
|
111
|
+
# Step 1: Define environment in comfy-env.toml (this file)
|
|
112
|
+
# Step 2: In __init__.py:
|
|
112
113
|
#
|
|
113
|
-
# from comfy_env import
|
|
114
|
+
# from comfy_env import setup_isolated_imports, enable_isolation
|
|
115
|
+
#
|
|
116
|
+
# # Setup import stubs BEFORE importing nodes
|
|
117
|
+
# setup_isolated_imports(__file__)
|
|
114
118
|
#
|
|
115
|
-
#
|
|
116
|
-
# class MyIsolatedNode:
|
|
117
|
-
# FUNCTION = "process"
|
|
118
|
-
# RETURN_TYPES = ("IMAGE",)
|
|
119
|
+
# from .nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
|
119
120
|
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
# import conflicting_package
|
|
123
|
-
# return (result,)
|
|
121
|
+
# # Enable isolation for all nodes
|
|
122
|
+
# enable_isolation(NODE_CLASS_MAPPINGS)
|
|
124
123
|
#
|
|
125
124
|
# =============================================================================
|
|
126
125
|
|
|
127
126
|
|
|
128
127
|
# -----------------------------------------------------------------------------
|
|
129
|
-
# Example:
|
|
128
|
+
# Example: Full pack isolation with conda packages (RECOMMENDED)
|
|
130
129
|
# -----------------------------------------------------------------------------
|
|
131
|
-
#
|
|
132
|
-
# In your code: @isolated(env="simple", same_venv=True)
|
|
130
|
+
# Uses pixi to create an isolated environment with conda + pip packages.
|
|
133
131
|
|
|
134
|
-
# [
|
|
132
|
+
# [mypack]
|
|
135
133
|
# python = "3.11"
|
|
136
|
-
#
|
|
137
|
-
# pytorch_version = "auto"
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
# -----------------------------------------------------------------------------
|
|
141
|
-
# Example: Full venv isolation
|
|
142
|
-
# -----------------------------------------------------------------------------
|
|
143
|
-
# Use when you need completely different dependencies.
|
|
144
|
-
# Creates a separate virtual environment with its own packages.
|
|
145
|
-
|
|
146
|
-
# [myenv]
|
|
147
|
-
# python = "3.10"
|
|
148
|
-
# cuda_version = "12.8"
|
|
149
|
-
# pytorch_version = "2.8.0"
|
|
134
|
+
# isolated = true # Required for enable_isolation()
|
|
150
135
|
#
|
|
151
|
-
# [
|
|
152
|
-
#
|
|
153
|
-
#
|
|
136
|
+
# [mypack.conda]
|
|
137
|
+
# channels = ["conda-forge"]
|
|
138
|
+
# packages = ["cgal", "openmesh"]
|
|
154
139
|
#
|
|
155
|
-
# [
|
|
156
|
-
# requirements = ["trimesh", "scipy"]
|
|
140
|
+
# [mypack.packages]
|
|
141
|
+
# requirements = ["trimesh[easy]>=4.0", "numpy", "scipy"]
|
|
157
142
|
|
|
158
143
|
|
|
159
144
|
# -----------------------------------------------------------------------------
|
|
160
|
-
# Example: Multiple isolated environments
|
|
145
|
+
# Example: Multiple isolated environments (per-node control)
|
|
161
146
|
# -----------------------------------------------------------------------------
|
|
162
|
-
#
|
|
147
|
+
# Use @isolated(env="envname") decorator when different nodes need different envs.
|
|
148
|
+
#
|
|
149
|
+
# from comfy_env import isolated
|
|
150
|
+
#
|
|
151
|
+
# @isolated(env="env-preprocessing")
|
|
152
|
+
# class PreprocessNode: ...
|
|
153
|
+
#
|
|
154
|
+
# @isolated(env="env-inference")
|
|
155
|
+
# class InferenceNode: ...
|
|
163
156
|
|
|
164
157
|
# [env-preprocessing]
|
|
165
158
|
# python = "3.11"
|
|
166
|
-
# cuda_version = "12.8"
|
|
167
|
-
# pytorch_version = "2.8.0"
|
|
168
159
|
#
|
|
169
160
|
# [env-preprocessing.packages]
|
|
170
161
|
# requirements = ["opencv-python-headless", "pillow"]
|
|
171
162
|
|
|
172
163
|
# [env-inference]
|
|
173
164
|
# python = "3.10"
|
|
174
|
-
# cuda_version = "12.4"
|
|
175
|
-
# pytorch_version = "2.5.1"
|
|
176
165
|
#
|
|
177
166
|
# [env-inference.cuda]
|
|
178
|
-
# torch-scatter = "2.1.2"
|
|
167
|
+
# torch-scatter = "2.1.2"
|
|
179
168
|
|
|
180
169
|
|
|
181
170
|
# -----------------------------------------------------------------------------
|
|
@@ -185,7 +174,7 @@ requirements = []
|
|
|
185
174
|
|
|
186
175
|
# [crossplatform]
|
|
187
176
|
# python = "3.11"
|
|
188
|
-
#
|
|
177
|
+
# isolated = true
|
|
189
178
|
#
|
|
190
179
|
# [crossplatform.packages]
|
|
191
180
|
# requirements = ["numpy", "pillow"]
|
|
@@ -195,17 +184,3 @@ requirements = []
|
|
|
195
184
|
#
|
|
196
185
|
# [crossplatform.packages.linux]
|
|
197
186
|
# requirements = ["python-xlib"]
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
# -----------------------------------------------------------------------------
|
|
201
|
-
# Example: Conda packages (uses pixi backend)
|
|
202
|
-
# -----------------------------------------------------------------------------
|
|
203
|
-
# For packages that are easier to install via conda (e.g., CUDA toolkit).
|
|
204
|
-
|
|
205
|
-
# [blender-env]
|
|
206
|
-
# python = "3.11"
|
|
207
|
-
# cuda_version = "12.8"
|
|
208
|
-
#
|
|
209
|
-
# [blender-env.conda]
|
|
210
|
-
# channels = ["conda-forge", "nvidia"]
|
|
211
|
-
# packages = ["cuda-toolkit=12.8", "bpy"]
|