Files
EricRorich-ComfyUI-face-shaper/validate_node_structure.py
T

274 lines
7.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Simple validation script to verify the node loads and renders without errors.
This script does NOT require numpy, torch, or PIL - it just validates the code structure.
"""
import sys
import ast
import re
def validate_syntax():
"""Validate Python syntax."""
print("=" * 70)
print("1. Validating Python syntax")
print("=" * 70)
try:
with open('face_shaper.py', 'r') as f:
source = f.read()
# Parse the source code
ast.parse(source)
print("✓ Python syntax is valid")
print()
return True
except SyntaxError as e:
print(f"✗ FAILED: Syntax error at line {e.lineno}: {e.msg}")
print()
return False
def validate_imports():
"""Validate required imports are present."""
print("=" * 70)
print("2. Validating imports")
print("=" * 70)
with open('face_shaper.py', 'r') as f:
content = f.read()
required_imports = [
'from typing import',
'import numpy',
'import torch',
'from PIL import Image',
]
for imp in required_imports:
if imp not in content:
print(f"✗ FAILED: Missing import: {imp}")
return False
print("✓ All required imports present")
print()
return True
def validate_class_structure():
"""Validate ComfyUIFaceShaper class structure."""
print("=" * 70)
print("3. Validating class structure")
print("=" * 70)
with open('face_shaper.py', 'r') as f:
content = f.read()
# Check class definition
if 'class ComfyUIFaceShaper:' not in content:
print("✗ FAILED: ComfyUIFaceShaper class not found")
return False
print("✓ ComfyUIFaceShaper class defined")
# Check required attributes
required_attrs = ['CATEGORY', 'RETURN_TYPES', 'FUNCTION']
for attr in required_attrs:
if f'{attr} = ' not in content:
print(f"✗ FAILED: Missing class attribute: {attr}")
return False
print("✓ All required class attributes present")
# Check required methods
required_methods = ['INPUT_TYPES', 'draw_face']
for method in required_methods:
if f'def {method}' not in content:
print(f"✗ FAILED: Missing method: {method}")
return False
print("✓ All required methods present")
# Verify CATEGORY value
if 'CATEGORY = "face"' not in content:
print("✗ FAILED: CATEGORY should be 'face'")
return False
print("✓ CATEGORY is 'face'")
# Verify RETURN_TYPES value
if 'RETURN_TYPES = ("IMAGE", "LIST")' not in content:
print("✗ FAILED: RETURN_TYPES should be ('IMAGE', 'LIST')")
return False
print("✓ RETURN_TYPES is ('IMAGE', 'LIST')")
print()
return True
def validate_node_mappings():
"""Validate NODE_CLASS_MAPPINGS and NODE_DISPLAY_NAME_MAPPINGS."""
print("=" * 70)
print("4. Validating node mappings")
print("=" * 70)
with open('face_shaper.py', 'r') as f:
content = f.read()
# Check NODE_CLASS_MAPPINGS
if 'NODE_CLASS_MAPPINGS' not in content:
print("✗ FAILED: NODE_CLASS_MAPPINGS not found")
return False
if '"RORICH-AI": ComfyUIFaceShaper' not in content:
print("✗ FAILED: NODE_CLASS_MAPPINGS should map 'RORICH-AI' to ComfyUIFaceShaper")
return False
print("✓ NODE_CLASS_MAPPINGS configured correctly")
# Check NODE_DISPLAY_NAME_MAPPINGS
if 'NODE_DISPLAY_NAME_MAPPINGS' not in content:
print("✗ FAILED: NODE_DISPLAY_NAME_MAPPINGS not found")
return False
if '"RORICH-AI": "Face Shaper"' not in content:
print("✗ FAILED: NODE_DISPLAY_NAME_MAPPINGS should map to 'Face Shaper'")
return False
print("✓ NODE_DISPLAY_NAME_MAPPINGS configured correctly")
print()
return True
def validate_parameter_count():
"""Validate the total parameter count is reasonable."""
print("=" * 70)
print("5. Validating parameter count")
print("=" * 70)
with open('face_shaper.py', 'r') as f:
source = f.read()
tree = ast.parse(source)
# Find draw_face method
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef) and node.name == 'draw_face':
params = [arg.arg for arg in node.args.args if arg.arg != 'self' and arg.arg != 'settings_list']
print(f"✓ Total parameters in draw_face: {len(params)}")
# Expected parameter count after removing 9 ear parameters:
# Original was ~62 parameters, minus 9 ear parameters = 53-54 parameters
if len(params) < 50 or len(params) > 60:
print(f" ⚠ WARNING: Unexpected parameter count (expected ~53-54)")
else:
print(f" ✓ Parameter count looks reasonable")
print()
return True
print("✗ FAILED: Could not find draw_face method")
return False
def validate_no_ear_references():
"""Final check: no ear-related code should remain."""
print("=" * 70)
print("6. Final check: No ear references")
print("=" * 70)
with open('face_shaper.py', 'r') as f:
content = f.read()
# Remove comments to avoid false positives
content_no_comments = re.sub(r'#.*', '', content)
content_no_comments = re.sub(r'""".*?"""', '', content_no_comments, flags=re.DOTALL)
content_no_comments = re.sub(r"'''.*?'''", '', content_no_comments, flags=re.DOTALL)
# Check for ear references
ear_patterns = [
'"ear_left"',
'"ear_right"',
"'ear_left'",
"'ear_right'",
'ear_left_pos',
'ear_right_pos',
'ear_left_size',
'ear_right_size',
'debug_ears',
]
found = []
for pattern in ear_patterns:
if pattern in content_no_comments:
found.append(pattern)
if found:
print(f"✗ FAILED: Found ear references: {found}")
return False
print("✓ No ear references found in code")
print()
return True
def main():
"""Run all validation checks."""
print("\n" + "=" * 70)
print("BASIC VALIDATION: Node Structure and Functionality")
print("=" * 70 + "\n")
tests = [
("Python syntax", validate_syntax),
("Required imports", validate_imports),
("Class structure", validate_class_structure),
("Node mappings", validate_node_mappings),
("Parameter count", validate_parameter_count),
("No ear references", validate_no_ear_references),
]
results = []
for name, test_func in tests:
try:
success = test_func()
results.append((name, success))
except Exception as e:
print(f"✗ EXCEPTION in {name}: {e}\n")
results.append((name, False))
# Summary
print("=" * 70)
print("VALIDATION SUMMARY")
print("=" * 70 + "\n")
passed = sum(1 for _, success in results if success)
total = len(results)
for name, success in results:
status = "✓ PASS" if success else "✗ FAIL"
print(f"{status}: {name}")
print(f"\nTotal: {passed}/{total} tests passed")
if passed == total:
print("\n" + "=" * 70)
print("✓✓✓ ALL VALIDATION TESTS PASSED ✓✓✓")
print("=" * 70)
print("\nThe node is ready to use!")
print("• No syntax errors")
print("• All required methods and attributes present")
print("• No ear-related code remains")
print("• Node name and category unchanged")
return 0
else:
print("\n" + "=" * 70)
print("✗✗✗ SOME VALIDATION TESTS FAILED ✗✗✗")
print("=" * 70)
return 1
if __name__ == "__main__":
sys.exit(main())