comfy-env 0.1.14__py3-none-any.whl → 0.1.16__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 +115 -62
- comfy_env/cli.py +89 -319
- comfy_env/config/__init__.py +18 -8
- comfy_env/config/parser.py +21 -122
- comfy_env/config/types.py +37 -70
- comfy_env/detection/__init__.py +77 -0
- comfy_env/detection/cuda.py +61 -0
- comfy_env/detection/gpu.py +230 -0
- comfy_env/detection/platform.py +70 -0
- comfy_env/detection/runtime.py +103 -0
- comfy_env/environment/__init__.py +53 -0
- comfy_env/environment/cache.py +141 -0
- comfy_env/environment/libomp.py +41 -0
- comfy_env/environment/paths.py +38 -0
- comfy_env/environment/setup.py +88 -0
- comfy_env/install.py +163 -249
- comfy_env/isolation/__init__.py +33 -2
- comfy_env/isolation/tensor_utils.py +83 -0
- comfy_env/isolation/workers/__init__.py +16 -0
- comfy_env/{workers → isolation/workers}/mp.py +1 -1
- comfy_env/{workers → isolation/workers}/subprocess.py +2 -2
- comfy_env/isolation/wrap.py +149 -409
- comfy_env/packages/__init__.py +60 -0
- comfy_env/packages/apt.py +36 -0
- comfy_env/packages/cuda_wheels.py +97 -0
- comfy_env/packages/node_dependencies.py +77 -0
- comfy_env/packages/pixi.py +85 -0
- comfy_env/packages/toml_generator.py +88 -0
- comfy_env-0.1.16.dist-info/METADATA +279 -0
- comfy_env-0.1.16.dist-info/RECORD +36 -0
- comfy_env/cache.py +0 -331
- comfy_env/errors.py +0 -293
- comfy_env/nodes.py +0 -187
- comfy_env/pixi/__init__.py +0 -48
- comfy_env/pixi/core.py +0 -588
- comfy_env/pixi/cuda_detection.py +0 -303
- comfy_env/pixi/platform/__init__.py +0 -21
- comfy_env/pixi/platform/base.py +0 -96
- comfy_env/pixi/platform/darwin.py +0 -53
- comfy_env/pixi/platform/linux.py +0 -68
- comfy_env/pixi/platform/windows.py +0 -284
- comfy_env/pixi/resolver.py +0 -198
- comfy_env/prestartup.py +0 -192
- comfy_env/workers/__init__.py +0 -38
- comfy_env/workers/tensor_utils.py +0 -188
- comfy_env-0.1.14.dist-info/METADATA +0 -291
- comfy_env-0.1.14.dist-info/RECORD +0 -33
- /comfy_env/{workers → isolation/workers}/base.py +0 -0
- {comfy_env-0.1.14.dist-info → comfy_env-0.1.16.dist-info}/WHEEL +0 -0
- {comfy_env-0.1.14.dist-info → comfy_env-0.1.16.dist-info}/entry_points.txt +0 -0
- {comfy_env-0.1.14.dist-info → comfy_env-0.1.16.dist-info}/licenses/LICENSE +0 -0
comfy_env/cli.py
CHANGED
|
@@ -1,23 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
CLI for comfy-env.
|
|
3
|
-
|
|
4
|
-
Provides the `comfy-env` command with subcommands:
|
|
5
|
-
- init: Create a default comfy-env.toml
|
|
6
|
-
- generate: Generate pixi.toml from comfy-env.toml
|
|
7
|
-
- install: Install dependencies from config
|
|
8
|
-
- info: Show runtime environment information
|
|
9
|
-
- doctor: Verify installation
|
|
10
|
-
|
|
11
|
-
Usage:
|
|
12
|
-
comfy-env init ---> creates template comfy-env.toml
|
|
13
|
-
comfy-env generate nodes/cgal/comfy-env.toml ---> nodes/cgal/pixi.toml
|
|
14
|
-
comfy-env install ---> installs from comfy
|
|
15
|
-
comfy-env install --dry-run
|
|
16
|
-
|
|
17
|
-
comfy-env info
|
|
18
|
-
|
|
19
|
-
comfy-env doctor
|
|
20
|
-
"""
|
|
1
|
+
"""CLI for comfy-env."""
|
|
21
2
|
|
|
22
3
|
import argparse
|
|
23
4
|
import sys
|
|
@@ -28,136 +9,51 @@ from . import __version__
|
|
|
28
9
|
|
|
29
10
|
|
|
30
11
|
def main(args: Optional[List[str]] = None) -> int:
|
|
31
|
-
"""
|
|
32
|
-
parser =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
help="Path to comfy-env.toml",
|
|
64
|
-
)
|
|
65
|
-
generate_parser.add_argument(
|
|
66
|
-
"--force", "-f",
|
|
67
|
-
action="store_true",
|
|
68
|
-
help="Overwrite existing pixi.toml",
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
# install command
|
|
72
|
-
install_parser = subparsers.add_parser(
|
|
73
|
-
"install",
|
|
74
|
-
help="Install dependencies from config",
|
|
75
|
-
description="Install CUDA wheels and dependencies from comfy-env.toml",
|
|
76
|
-
)
|
|
77
|
-
install_parser.add_argument(
|
|
78
|
-
"--config", "-c",
|
|
79
|
-
type=str,
|
|
80
|
-
help="Path to config file (default: auto-discover)",
|
|
81
|
-
)
|
|
82
|
-
install_parser.add_argument(
|
|
83
|
-
"--dry-run",
|
|
84
|
-
action="store_true",
|
|
85
|
-
help="Show what would be installed without installing",
|
|
86
|
-
)
|
|
87
|
-
install_parser.add_argument(
|
|
88
|
-
"--dir", "-d",
|
|
89
|
-
type=str,
|
|
90
|
-
help="Directory containing the config (default: current directory)",
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
# info command
|
|
94
|
-
info_parser = subparsers.add_parser(
|
|
95
|
-
"info",
|
|
96
|
-
help="Show runtime environment information",
|
|
97
|
-
description="Display detected Python, CUDA, PyTorch, and GPU information",
|
|
98
|
-
)
|
|
99
|
-
info_parser.add_argument(
|
|
100
|
-
"--json",
|
|
101
|
-
action="store_true",
|
|
102
|
-
help="Output as JSON",
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
# doctor command
|
|
106
|
-
doctor_parser = subparsers.add_parser(
|
|
107
|
-
"doctor",
|
|
108
|
-
help="Verify installation and diagnose issues",
|
|
109
|
-
description="Check if packages are properly installed and importable",
|
|
110
|
-
)
|
|
111
|
-
doctor_parser.add_argument(
|
|
112
|
-
"--package", "-p",
|
|
113
|
-
type=str,
|
|
114
|
-
help="Check specific package",
|
|
115
|
-
)
|
|
116
|
-
doctor_parser.add_argument(
|
|
117
|
-
"--config", "-c",
|
|
118
|
-
type=str,
|
|
119
|
-
help="Path to config file",
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
# apt-install command
|
|
123
|
-
apt_parser = subparsers.add_parser(
|
|
124
|
-
"apt-install",
|
|
125
|
-
help="Install system packages from [apt] section (Linux only)",
|
|
126
|
-
description="Read [apt] packages from comfy-env.toml and install via apt-get",
|
|
127
|
-
)
|
|
128
|
-
apt_parser.add_argument(
|
|
129
|
-
"--config", "-c",
|
|
130
|
-
type=str,
|
|
131
|
-
help="Path to comfy-env.toml (default: auto-discover)",
|
|
132
|
-
)
|
|
133
|
-
apt_parser.add_argument(
|
|
134
|
-
"--dry-run",
|
|
135
|
-
action="store_true",
|
|
136
|
-
help="Show what would be installed without installing",
|
|
137
|
-
)
|
|
12
|
+
parser = argparse.ArgumentParser(prog="comfy-env", description="Environment management for ComfyUI")
|
|
13
|
+
parser.add_argument("--version", action="version", version=f"comfy-env {__version__}")
|
|
14
|
+
sub = parser.add_subparsers(dest="command", help="Commands")
|
|
15
|
+
|
|
16
|
+
# init
|
|
17
|
+
p = sub.add_parser("init", help="Create comfy-env.toml")
|
|
18
|
+
p.add_argument("--force", "-f", action="store_true", help="Overwrite existing")
|
|
19
|
+
|
|
20
|
+
# generate
|
|
21
|
+
p = sub.add_parser("generate", help="Generate pixi.toml from comfy-env.toml")
|
|
22
|
+
p.add_argument("config", type=str, help="Path to comfy-env.toml")
|
|
23
|
+
p.add_argument("--force", "-f", action="store_true", help="Overwrite existing")
|
|
24
|
+
|
|
25
|
+
# install
|
|
26
|
+
p = sub.add_parser("install", help="Install dependencies")
|
|
27
|
+
p.add_argument("--config", "-c", type=str, help="Config path")
|
|
28
|
+
p.add_argument("--dry-run", action="store_true", help="Preview only")
|
|
29
|
+
p.add_argument("--dir", "-d", type=str, help="Node directory")
|
|
30
|
+
|
|
31
|
+
# info
|
|
32
|
+
p = sub.add_parser("info", help="Show runtime info")
|
|
33
|
+
p.add_argument("--json", action="store_true", help="JSON output")
|
|
34
|
+
|
|
35
|
+
# doctor
|
|
36
|
+
p = sub.add_parser("doctor", help="Verify installation")
|
|
37
|
+
p.add_argument("--package", "-p", type=str, help="Check specific package")
|
|
38
|
+
p.add_argument("--config", "-c", type=str, help="Config path")
|
|
39
|
+
|
|
40
|
+
# apt-install
|
|
41
|
+
p = sub.add_parser("apt-install", help="Install apt packages (Linux)")
|
|
42
|
+
p.add_argument("--config", "-c", type=str, help="Config path")
|
|
43
|
+
p.add_argument("--dry-run", action="store_true", help="Preview only")
|
|
138
44
|
|
|
139
45
|
parsed = parser.parse_args(args)
|
|
140
|
-
|
|
141
|
-
if parsed.command is None:
|
|
46
|
+
if not parsed.command:
|
|
142
47
|
parser.print_help()
|
|
143
48
|
return 0
|
|
144
49
|
|
|
50
|
+
commands = {
|
|
51
|
+
"init": cmd_init, "generate": cmd_generate, "install": cmd_install,
|
|
52
|
+
"info": cmd_info, "doctor": cmd_doctor, "apt-install": cmd_apt_install,
|
|
53
|
+
}
|
|
54
|
+
|
|
145
55
|
try:
|
|
146
|
-
|
|
147
|
-
return cmd_init(parsed)
|
|
148
|
-
elif parsed.command == "generate":
|
|
149
|
-
return cmd_generate(parsed)
|
|
150
|
-
elif parsed.command == "install":
|
|
151
|
-
return cmd_install(parsed)
|
|
152
|
-
elif parsed.command == "info":
|
|
153
|
-
return cmd_info(parsed)
|
|
154
|
-
elif parsed.command == "doctor":
|
|
155
|
-
return cmd_doctor(parsed)
|
|
156
|
-
elif parsed.command == "apt-install":
|
|
157
|
-
return cmd_apt_install(parsed)
|
|
158
|
-
else:
|
|
159
|
-
parser.print_help()
|
|
160
|
-
return 1
|
|
56
|
+
return commands.get(parsed.command, lambda _: 1)(parsed)
|
|
161
57
|
except KeyboardInterrupt:
|
|
162
58
|
print("\nInterrupted")
|
|
163
59
|
return 130
|
|
@@ -167,113 +63,64 @@ def main(args: Optional[List[str]] = None) -> int:
|
|
|
167
63
|
|
|
168
64
|
|
|
169
65
|
DEFAULT_CONFIG = """\
|
|
170
|
-
# comfy-env.toml
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
[system]
|
|
174
|
-
# System packages required (apt on Linux, brew on macOS)
|
|
175
|
-
linux = []
|
|
66
|
+
# comfy-env.toml
|
|
67
|
+
[cuda]
|
|
68
|
+
packages = []
|
|
176
69
|
|
|
177
|
-
[
|
|
178
|
-
|
|
179
|
-
cuda_version = "auto"
|
|
180
|
-
pytorch_version = "auto"
|
|
181
|
-
|
|
182
|
-
[environment.cuda]
|
|
183
|
-
# CUDA packages from https://pozzettiandrea.github.io/cuda-wheels/
|
|
184
|
-
# Example: nvdiffrast = "0.4.0"
|
|
185
|
-
|
|
186
|
-
[environment.packages]
|
|
187
|
-
requirements = []
|
|
70
|
+
[pypi-dependencies]
|
|
71
|
+
# example = "*"
|
|
188
72
|
"""
|
|
189
73
|
|
|
190
74
|
|
|
191
75
|
def cmd_init(args) -> int:
|
|
192
|
-
"""Handle init command."""
|
|
193
76
|
config_path = Path.cwd() / "comfy-env.toml"
|
|
194
|
-
|
|
195
77
|
if config_path.exists() and not args.force:
|
|
196
|
-
print(f"
|
|
197
|
-
print("Use --force to overwrite", file=sys.stderr)
|
|
78
|
+
print(f"Already exists: {config_path}\nUse --force to overwrite", file=sys.stderr)
|
|
198
79
|
return 1
|
|
199
|
-
|
|
200
80
|
config_path.write_text(DEFAULT_CONFIG)
|
|
201
81
|
print(f"Created {config_path}")
|
|
202
82
|
return 0
|
|
203
83
|
|
|
204
84
|
|
|
205
85
|
def cmd_generate(args) -> int:
|
|
206
|
-
|
|
207
|
-
from .
|
|
208
|
-
from .pixi import create_pixi_toml
|
|
86
|
+
from .config import load_config
|
|
87
|
+
from .packages.toml_generator import write_pixi_toml
|
|
209
88
|
|
|
210
89
|
config_path = Path(args.config).resolve()
|
|
211
|
-
|
|
212
90
|
if not config_path.exists():
|
|
213
|
-
print(f"
|
|
91
|
+
print(f"Not found: {config_path}", file=sys.stderr)
|
|
214
92
|
return 1
|
|
215
93
|
|
|
216
|
-
if config_path.name != "comfy-env.toml":
|
|
217
|
-
print(f"Warning: Expected comfy-env.toml, got {config_path.name}", file=sys.stderr)
|
|
218
|
-
|
|
219
94
|
node_dir = config_path.parent
|
|
220
95
|
pixi_path = node_dir / "pixi.toml"
|
|
221
|
-
|
|
222
96
|
if pixi_path.exists() and not args.force:
|
|
223
|
-
print(f"
|
|
224
|
-
print("Use --force to overwrite", file=sys.stderr)
|
|
97
|
+
print(f"Already exists: {pixi_path}\nUse --force to overwrite", file=sys.stderr)
|
|
225
98
|
return 1
|
|
226
99
|
|
|
227
|
-
# Load the config
|
|
228
100
|
config = load_config(config_path)
|
|
229
|
-
if not config
|
|
230
|
-
print(f"
|
|
101
|
+
if not config:
|
|
102
|
+
print(f"Failed to load: {config_path}", file=sys.stderr)
|
|
231
103
|
return 1
|
|
232
104
|
|
|
233
|
-
# Use the first environment
|
|
234
|
-
env_name = next(iter(config.envs.keys()))
|
|
235
|
-
env_config = config.envs[env_name]
|
|
236
|
-
|
|
237
105
|
print(f"Generating pixi.toml from {config_path}")
|
|
238
|
-
|
|
239
|
-
print(f"
|
|
240
|
-
|
|
241
|
-
# Generate pixi.toml
|
|
242
|
-
result_path = create_pixi_toml(env_config, node_dir)
|
|
243
|
-
|
|
244
|
-
print(f"Created {result_path}")
|
|
245
|
-
print()
|
|
246
|
-
print("Next steps:")
|
|
247
|
-
print(f" cd {node_dir}")
|
|
248
|
-
print(" pixi install")
|
|
106
|
+
write_pixi_toml(config, node_dir)
|
|
107
|
+
print(f"Created {pixi_path}\nNext: cd {node_dir} && pixi install")
|
|
249
108
|
return 0
|
|
250
109
|
|
|
251
110
|
|
|
252
111
|
def cmd_install(args) -> int:
|
|
253
|
-
"""Handle install command."""
|
|
254
112
|
from .install import install
|
|
255
|
-
|
|
256
113
|
node_dir = Path(args.dir) if args.dir else Path.cwd()
|
|
257
|
-
|
|
258
114
|
try:
|
|
259
|
-
install(
|
|
260
|
-
config=args.config,
|
|
261
|
-
node_dir=node_dir,
|
|
262
|
-
dry_run=args.dry_run,
|
|
263
|
-
)
|
|
115
|
+
install(config=args.config, node_dir=node_dir, dry_run=args.dry_run)
|
|
264
116
|
return 0
|
|
265
|
-
except FileNotFoundError as e:
|
|
266
|
-
print(f"Error: {e}", file=sys.stderr)
|
|
267
|
-
return 1
|
|
268
117
|
except Exception as e:
|
|
269
|
-
print(f"
|
|
118
|
+
print(f"Failed: {e}", file=sys.stderr)
|
|
270
119
|
return 1
|
|
271
120
|
|
|
272
121
|
|
|
273
122
|
def cmd_info(args) -> int:
|
|
274
|
-
|
|
275
|
-
from .pixi import RuntimeEnv
|
|
276
|
-
|
|
123
|
+
from .detection import RuntimeEnv
|
|
277
124
|
env = RuntimeEnv.detect()
|
|
278
125
|
|
|
279
126
|
if args.json:
|
|
@@ -281,151 +128,74 @@ def cmd_info(args) -> int:
|
|
|
281
128
|
print(json.dumps(env.as_dict(), indent=2))
|
|
282
129
|
return 0
|
|
283
130
|
|
|
284
|
-
print("Runtime Environment")
|
|
285
|
-
print("
|
|
286
|
-
print(f"
|
|
287
|
-
print(f"
|
|
288
|
-
print(f"
|
|
289
|
-
|
|
290
|
-
if env.cuda_version:
|
|
291
|
-
print(f" CUDA: {env.cuda_version}")
|
|
292
|
-
else:
|
|
293
|
-
print(" CUDA: Not detected")
|
|
294
|
-
|
|
295
|
-
if env.torch_version:
|
|
296
|
-
print(f" PyTorch: {env.torch_version}")
|
|
297
|
-
else:
|
|
298
|
-
print(" PyTorch: Not installed")
|
|
299
|
-
|
|
131
|
+
print("Runtime Environment\n" + "=" * 40)
|
|
132
|
+
print(f" OS: {env.os_name}")
|
|
133
|
+
print(f" Platform: {env.platform_tag}")
|
|
134
|
+
print(f" Python: {env.python_version}")
|
|
135
|
+
print(f" CUDA: {env.cuda_version or 'Not detected'}")
|
|
136
|
+
print(f" PyTorch: {env.torch_version or 'Not installed'}")
|
|
300
137
|
if env.gpu_name:
|
|
301
|
-
print(f" GPU:
|
|
302
|
-
if env.gpu_compute:
|
|
303
|
-
print(f" Compute: {env.gpu_compute}")
|
|
304
|
-
|
|
138
|
+
print(f" GPU: {env.gpu_name}")
|
|
139
|
+
if env.gpu_compute: print(f" Compute: {env.gpu_compute}")
|
|
305
140
|
print()
|
|
306
141
|
return 0
|
|
307
142
|
|
|
308
143
|
|
|
309
144
|
def cmd_doctor(args) -> int:
|
|
310
|
-
"""Handle doctor command."""
|
|
311
145
|
from .install import verify_installation
|
|
312
|
-
from .config
|
|
146
|
+
from .config import load_config, discover_config
|
|
313
147
|
|
|
314
|
-
print("
|
|
315
|
-
print("=" * 40)
|
|
316
|
-
|
|
317
|
-
# Check environment
|
|
148
|
+
print("Diagnostics\n" + "=" * 40)
|
|
318
149
|
print("\n1. Environment")
|
|
319
150
|
cmd_info(argparse.Namespace(json=False))
|
|
320
151
|
|
|
321
|
-
|
|
322
|
-
print("2. Package Verification")
|
|
323
|
-
|
|
152
|
+
print("2. Packages")
|
|
324
153
|
packages = []
|
|
325
154
|
if args.package:
|
|
326
155
|
packages = [args.package]
|
|
327
|
-
elif args.config:
|
|
328
|
-
config = load_env_from_file(Path(args.config))
|
|
329
|
-
if config:
|
|
330
|
-
packages = (config.requirements or []) + (config.no_deps_requirements or [])
|
|
331
156
|
else:
|
|
332
|
-
|
|
333
|
-
if
|
|
334
|
-
packages = (
|
|
157
|
+
cfg = load_config(Path(args.config)) if args.config else discover_config(Path.cwd())
|
|
158
|
+
if cfg:
|
|
159
|
+
packages = list(cfg.pixi_passthrough.get("pypi-dependencies", {}).keys()) + cfg.cuda_packages
|
|
335
160
|
|
|
336
161
|
if packages:
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
pkg_names.append(name)
|
|
341
|
-
|
|
342
|
-
all_ok = verify_installation(pkg_names)
|
|
343
|
-
if all_ok:
|
|
344
|
-
print("\nAll packages verified!")
|
|
345
|
-
return 0
|
|
346
|
-
else:
|
|
347
|
-
print("\nSome packages failed verification.")
|
|
348
|
-
return 1
|
|
349
|
-
else:
|
|
350
|
-
print(" No packages to verify (no config found)")
|
|
351
|
-
return 0
|
|
162
|
+
return 0 if verify_installation(packages) else 1
|
|
163
|
+
print(" No packages to verify")
|
|
164
|
+
return 0
|
|
352
165
|
|
|
353
166
|
|
|
354
167
|
def cmd_apt_install(args) -> int:
|
|
355
|
-
|
|
356
|
-
import os
|
|
357
|
-
import shutil
|
|
358
|
-
import subprocess
|
|
359
|
-
import platform
|
|
360
|
-
|
|
168
|
+
import os, shutil, subprocess, platform
|
|
361
169
|
if platform.system() != "Linux":
|
|
362
|
-
print("apt-install
|
|
170
|
+
print("apt-install: Linux only", file=sys.stderr)
|
|
363
171
|
return 1
|
|
364
172
|
|
|
365
|
-
|
|
366
|
-
if args.config:
|
|
367
|
-
config_path = Path(args.config).resolve()
|
|
368
|
-
else:
|
|
369
|
-
config_path = Path.cwd() / "comfy-env.toml"
|
|
370
|
-
|
|
173
|
+
config_path = Path(args.config).resolve() if args.config else Path.cwd() / "comfy-env.toml"
|
|
371
174
|
if not config_path.exists():
|
|
372
|
-
print(f"
|
|
175
|
+
print(f"Not found: {config_path}", file=sys.stderr)
|
|
373
176
|
return 1
|
|
374
177
|
|
|
375
|
-
# Parse config to get apt packages
|
|
376
178
|
from .config.parser import load_config
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
print("No [apt] packages specified in config")
|
|
179
|
+
packages = load_config(config_path).apt_packages
|
|
180
|
+
if not packages:
|
|
181
|
+
print("No apt packages in config")
|
|
381
182
|
return 0
|
|
382
183
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
for pkg in packages:
|
|
386
|
-
print(f" - {pkg}")
|
|
387
|
-
|
|
388
|
-
# Determine if we need sudo
|
|
389
|
-
is_root = os.geteuid() == 0
|
|
390
|
-
has_sudo = shutil.which("sudo") is not None
|
|
391
|
-
use_sudo = not is_root and has_sudo
|
|
392
|
-
|
|
184
|
+
print(f"Packages: {', '.join(packages)}")
|
|
185
|
+
use_sudo = os.geteuid() != 0 and shutil.which("sudo")
|
|
393
186
|
prefix = ["sudo"] if use_sudo else []
|
|
394
187
|
|
|
395
188
|
if args.dry_run:
|
|
396
|
-
print("
|
|
397
|
-
prefix_str = "sudo " if use_sudo else ""
|
|
398
|
-
print(f" {prefix_str}apt-get update && {prefix_str}apt-get install -y {' '.join(packages)}")
|
|
189
|
+
print(f"Would run: {'sudo ' if use_sudo else ''}apt-get install -y {' '.join(packages)}")
|
|
399
190
|
return 0
|
|
400
191
|
|
|
401
|
-
if
|
|
402
|
-
print("
|
|
403
|
-
print("Run manually with:", file=sys.stderr)
|
|
404
|
-
print(f" sudo apt-get update && sudo apt-get install -y {' '.join(packages)}", file=sys.stderr)
|
|
192
|
+
if os.geteuid() != 0 and not shutil.which("sudo"):
|
|
193
|
+
print("Need root. Run: sudo apt-get install -y " + " ".join(packages), file=sys.stderr)
|
|
405
194
|
return 1
|
|
406
195
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
result
|
|
410
|
-
prefix + ["apt-get", "update"],
|
|
411
|
-
capture_output=False,
|
|
412
|
-
)
|
|
413
|
-
if result.returncode != 0:
|
|
414
|
-
print("Warning: apt-get update failed, continuing anyway...")
|
|
415
|
-
|
|
416
|
-
# Run apt-get install
|
|
417
|
-
print(f"\nInstalling: {' '.join(packages)}")
|
|
418
|
-
result = subprocess.run(
|
|
419
|
-
prefix + ["apt-get", "install", "-y"] + packages,
|
|
420
|
-
capture_output=False,
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
if result.returncode == 0:
|
|
424
|
-
print("\nSystem packages installed successfully!")
|
|
425
|
-
return 0
|
|
426
|
-
else:
|
|
427
|
-
print("\nFailed to install some packages", file=sys.stderr)
|
|
428
|
-
return result.returncode
|
|
196
|
+
subprocess.run(prefix + ["apt-get", "update"], capture_output=False)
|
|
197
|
+
result = subprocess.run(prefix + ["apt-get", "install", "-y"] + packages, capture_output=False)
|
|
198
|
+
return result.returncode
|
|
429
199
|
|
|
430
200
|
|
|
431
201
|
if __name__ == "__main__":
|
comfy_env/config/__init__.py
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Config parsing
|
|
2
|
+
Config layer - Configuration parsing and types.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
typed configuration objects.
|
|
4
|
+
Pure parsing, no side effects.
|
|
6
5
|
"""
|
|
7
6
|
|
|
8
|
-
from .types import
|
|
9
|
-
|
|
7
|
+
from .types import (
|
|
8
|
+
ComfyEnvConfig,
|
|
9
|
+
NodeDependency,
|
|
10
|
+
NodeReq, # Backwards compatibility alias
|
|
11
|
+
)
|
|
12
|
+
from .parser import (
|
|
13
|
+
CONFIG_FILE_NAME,
|
|
14
|
+
load_config,
|
|
15
|
+
discover_config,
|
|
16
|
+
parse_config,
|
|
17
|
+
)
|
|
10
18
|
|
|
11
19
|
__all__ = [
|
|
12
20
|
# Types
|
|
13
21
|
"ComfyEnvConfig",
|
|
14
|
-
"
|
|
15
|
-
#
|
|
22
|
+
"NodeDependency",
|
|
23
|
+
"NodeReq", # Backwards compatibility
|
|
24
|
+
# Parsing
|
|
25
|
+
"CONFIG_FILE_NAME",
|
|
16
26
|
"load_config",
|
|
17
27
|
"discover_config",
|
|
18
|
-
"
|
|
28
|
+
"parse_config",
|
|
19
29
|
]
|