- Introduced `__init__.py` for package initialization, dependency checking, and node management. - Added `image_nodes.py` with nodes for model name extraction and image saving with metadata. - Created `install.py` for dependency installation and ComfyUI Manager integration setup. - Included configuration files: `node_config.json`, `.manager_info.json`, and `CHANGELOG.md`. - Established `.gitignore` to exclude auto-generated files and unnecessary directories. - Added `README.md` for comprehensive project documentation and usage instructions. - Implemented `DependencyChecker` and `NodeManager` classes for enhanced functionality. - Updated `FILETREE.md` to reflect project structure and organization.
220 lines
8.1 KiB
Python
220 lines
8.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
ComfyUI-TechsToolz Installation Script
|
|
|
|
This script handles:
|
|
- Dependency installation and verification
|
|
- ComfyUI Manager integration setup
|
|
- Configuration file creation
|
|
- Runtime environment validation
|
|
"""
|
|
|
|
import sys
|
|
import subprocess
|
|
import json
|
|
import importlib
|
|
from pathlib import Path
|
|
|
|
|
|
class TechsToolzInstaller:
|
|
"""Handles installation and setup of ComfyUI-TechsToolz."""
|
|
|
|
def __init__(self):
|
|
self.install_dir = Path(__file__).parent
|
|
self.requirements = ["piexif", "numpy", "Pillow"]
|
|
self.optional_requirements = []
|
|
self.config_file = self.install_dir / "node_config.json"
|
|
self.success = True
|
|
|
|
def log(self, message: str, level: str = "INFO"):
|
|
"""Log installation messages."""
|
|
prefix = "🖥️🛠TechsToolz"
|
|
print(f"[{prefix}] {level}: {message}")
|
|
|
|
def check_python_version(self) -> bool:
|
|
"""Check if Python version is compatible."""
|
|
min_version = (3, 8)
|
|
current_version = sys.version_info[:2]
|
|
|
|
if current_version < min_version:
|
|
self.log(f"Python {min_version[0]}.{min_version[1]}+ required, got {current_version[0]}.{current_version[1]}", "ERROR")
|
|
return False
|
|
|
|
self.log(f"Python version {current_version[0]}.{current_version[1]} is compatible", "INFO")
|
|
return True
|
|
|
|
def install_dependencies(self) -> bool:
|
|
"""Install required Python packages."""
|
|
self.log("Installing dependencies...")
|
|
|
|
for package in self.requirements:
|
|
try:
|
|
# Try to import first
|
|
importlib.import_module(package)
|
|
self.log(f"✓ {package} already installed", "INFO")
|
|
except ImportError:
|
|
self.log(f"Installing {package}...", "INFO")
|
|
try:
|
|
result = subprocess.run([sys.executable, "-m", "pip", "install", package], capture_output=True, text=True, check=True)
|
|
|
|
if result.returncode == 0:
|
|
self.log(f"✓ Successfully installed {package}", "INFO")
|
|
else:
|
|
self.log(f"✗ Failed to install {package}: {result.stderr}", "ERROR")
|
|
self.success = False
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
self.log(f"✗ Failed to install {package}: {e}", "ERROR")
|
|
self.success = False
|
|
except Exception as e:
|
|
self.log(f"✗ Unexpected error installing {package}: {e}", "ERROR")
|
|
self.success = False
|
|
|
|
return self.success
|
|
|
|
def create_default_config(self) -> bool:
|
|
"""Create default configuration file."""
|
|
self.log("Creating default configuration...")
|
|
|
|
default_config = {
|
|
"enabled_modules": ["image_nodes"],
|
|
"disabled_modules": [],
|
|
"package_info": {
|
|
"name": "ComfyUI-TechsToolz",
|
|
"version": "0.0.1",
|
|
"author": "Robin Collins",
|
|
"description": "A collection of image processing and utility nodes for ComfyUI",
|
|
"supports_manager": True,
|
|
"configurable_nodes": True,
|
|
},
|
|
"installation": {
|
|
"install_date": str(Path(__file__).stat().st_mtime),
|
|
"python_version": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
|
"dependencies_installed": self.requirements,
|
|
},
|
|
}
|
|
|
|
try:
|
|
with open(self.config_file, "w") as f:
|
|
json.dump(default_config, f, indent=2)
|
|
self.log(f"✓ Configuration created at {self.config_file}", "INFO")
|
|
return True
|
|
except Exception as e:
|
|
self.log(f"✗ Failed to create configuration: {e}", "ERROR")
|
|
return False
|
|
|
|
def verify_comfyui_environment(self) -> bool:
|
|
"""Verify ComfyUI environment is available."""
|
|
self.log("Verifying ComfyUI environment...")
|
|
|
|
try:
|
|
# Check for ComfyUI modules using importlib to avoid unused import warnings
|
|
importlib.import_module("folder_paths")
|
|
importlib.import_module("comfy")
|
|
importlib.import_module("nodes")
|
|
self.log("✓ ComfyUI environment detected", "INFO")
|
|
return True
|
|
except ImportError as e:
|
|
self.log(f"⚠ ComfyUI environment not fully available: {e}", "WARNING")
|
|
self.log("This is normal if installing outside of ComfyUI", "INFO")
|
|
return True # Don't fail installation for this
|
|
|
|
def setup_manager_integration(self) -> bool:
|
|
"""Set up ComfyUI Manager integration files."""
|
|
self.log("Setting up ComfyUI Manager integration...")
|
|
|
|
# Verify node_list.json exists
|
|
node_list_file = self.install_dir / "node_list.json"
|
|
if not node_list_file.exists():
|
|
self.log("⚠ node_list.json not found, ComfyUI Manager integration may be limited", "WARNING")
|
|
else:
|
|
self.log("✓ node_list.json found", "INFO")
|
|
|
|
# Create manager metadata
|
|
manager_info = {
|
|
"install_type": "git-clone",
|
|
"supports_manager": True,
|
|
"configurable_nodes": True,
|
|
"api_functions": ["get_node_list", "get_package_info", "enable_node_module", "disable_node_module", "get_dependency_report"],
|
|
}
|
|
|
|
manager_file = self.install_dir / ".manager_info.json"
|
|
try:
|
|
with open(manager_file, "w") as f:
|
|
json.dump(manager_info, f, indent=2)
|
|
self.log("✓ ComfyUI Manager integration configured", "INFO")
|
|
return True
|
|
except Exception as e:
|
|
self.log(f"⚠ Could not create manager info: {e}", "WARNING")
|
|
return True # Don't fail installation for this
|
|
|
|
def run_dependency_check(self) -> bool:
|
|
"""Run the dependency checker to validate installation."""
|
|
self.log("Running dependency validation...")
|
|
|
|
try:
|
|
# Import our own dependency checker
|
|
sys.path.insert(0, str(self.install_dir))
|
|
from __init__ import DependencyChecker
|
|
|
|
checker = DependencyChecker(self.install_dir)
|
|
info = checker.scan_all_dependencies()
|
|
|
|
if info["missing_dependencies"]:
|
|
self.log(f"⚠ Missing dependencies: {', '.join(info['missing_dependencies'])}", "WARNING")
|
|
self.log("These may be optional or ComfyUI-specific dependencies", "INFO")
|
|
else:
|
|
self.log("✓ All dependencies are available", "INFO")
|
|
|
|
return True
|
|
except Exception as e:
|
|
self.log(f"⚠ Could not run dependency check: {e}", "WARNING")
|
|
return True # Don't fail installation for this
|
|
|
|
def install(self) -> bool:
|
|
"""Run the complete installation process."""
|
|
self.log("Starting ComfyUI-TechsToolz installation...")
|
|
|
|
# Check Python version
|
|
if not self.check_python_version():
|
|
return False
|
|
|
|
# Install dependencies
|
|
if not self.install_dependencies():
|
|
self.log("Dependency installation failed", "ERROR")
|
|
return False
|
|
|
|
# Create configuration
|
|
if not self.create_default_config():
|
|
self.log("Configuration creation failed", "ERROR")
|
|
return False
|
|
|
|
# Verify ComfyUI environment
|
|
self.verify_comfyui_environment()
|
|
|
|
# Setup manager integration
|
|
self.setup_manager_integration()
|
|
|
|
# Run dependency check
|
|
self.run_dependency_check()
|
|
|
|
if self.success:
|
|
self.log("🎉 Installation completed successfully!", "SUCCESS")
|
|
self.log("ComfyUI-TechsToolz is ready to use!", "INFO")
|
|
self.log("Restart ComfyUI to see the new nodes", "INFO")
|
|
else:
|
|
self.log("Installation completed with some issues", "WARNING")
|
|
|
|
return self.success
|
|
|
|
|
|
def main():
|
|
"""Main installation entry point."""
|
|
installer = TechsToolzInstaller()
|
|
success = installer.install()
|
|
sys.exit(0 if success else 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|