feat: Add multi-series configuration testing and debugging tools
- Add comprehensive test scripts for multi-series dongle configuration - Add debugging tools for deployment and flow testing - Add configuration verification and guide utilities - Fix stdout/stderr handling in deployment dialog for PyInstaller builds - Includes port ID configuration tests and multi-series config validation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
c4090b2420
commit
1781a05269
110
check_multi_series_config.py
Normal file
110
check_multi_series_config.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Check current multi-series configuration in saved .mflow files
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
|
||||||
|
def check_mflow_files():
|
||||||
|
"""Check .mflow files for multi-series configuration"""
|
||||||
|
|
||||||
|
# Look for .mflow files in common locations
|
||||||
|
search_paths = [
|
||||||
|
"*.mflow",
|
||||||
|
"flows/*.mflow",
|
||||||
|
"examples/*.mflow",
|
||||||
|
"../*.mflow"
|
||||||
|
]
|
||||||
|
|
||||||
|
mflow_files = []
|
||||||
|
for pattern in search_paths:
|
||||||
|
mflow_files.extend(glob.glob(pattern))
|
||||||
|
|
||||||
|
if not mflow_files:
|
||||||
|
print("No .mflow files found in current directory")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Found {len(mflow_files)} .mflow file(s):")
|
||||||
|
|
||||||
|
for mflow_file in mflow_files:
|
||||||
|
print(f"\n=== Checking {mflow_file} ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(mflow_file, 'r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
# Look for nodes with type "Model" or "ExactModelNode"
|
||||||
|
nodes = data.get('nodes', [])
|
||||||
|
model_nodes = [node for node in nodes if node.get('type') in ['Model', 'ExactModelNode']]
|
||||||
|
|
||||||
|
if not model_nodes:
|
||||||
|
print(" No Model nodes found")
|
||||||
|
continue
|
||||||
|
|
||||||
|
for i, node in enumerate(model_nodes):
|
||||||
|
print(f"\n Model Node {i+1}:")
|
||||||
|
print(f" Name: {node.get('name', 'Unnamed')}")
|
||||||
|
|
||||||
|
# Check both custom_properties and properties for multi-series config
|
||||||
|
custom_properties = node.get('custom_properties', {})
|
||||||
|
properties = node.get('properties', {})
|
||||||
|
|
||||||
|
# Multi-series config is typically in custom_properties
|
||||||
|
config_props = custom_properties if custom_properties else properties
|
||||||
|
|
||||||
|
# Check multi-series configuration
|
||||||
|
multi_series_mode = config_props.get('multi_series_mode', False)
|
||||||
|
enabled_series = config_props.get('enabled_series', [])
|
||||||
|
|
||||||
|
print(f" multi_series_mode: {multi_series_mode}")
|
||||||
|
print(f" enabled_series: {enabled_series}")
|
||||||
|
|
||||||
|
if multi_series_mode:
|
||||||
|
print(" Multi-series port configurations:")
|
||||||
|
for series in ['520', '720', '630', '730', '540']:
|
||||||
|
port_ids = config_props.get(f'kl{series}_port_ids', '')
|
||||||
|
if port_ids:
|
||||||
|
print(f" kl{series}_port_ids: '{port_ids}'")
|
||||||
|
|
||||||
|
assets_folder = config_props.get('assets_folder', '')
|
||||||
|
if assets_folder:
|
||||||
|
print(f" assets_folder: '{assets_folder}'")
|
||||||
|
else:
|
||||||
|
print(" assets_folder: (not set)")
|
||||||
|
else:
|
||||||
|
print(" Multi-series mode is DISABLED")
|
||||||
|
print(" Current single-series configuration:")
|
||||||
|
port_ids = properties.get('port_ids', [])
|
||||||
|
model_path = properties.get('model_path', '')
|
||||||
|
print(f" port_ids: {port_ids}")
|
||||||
|
print(f" model_path: '{model_path}'")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" Error reading file: {e}")
|
||||||
|
|
||||||
|
def print_configuration_guide():
|
||||||
|
"""Print guide for setting up multi-series configuration"""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("MULTI-SERIES CONFIGURATION GUIDE")
|
||||||
|
print("="*60)
|
||||||
|
print()
|
||||||
|
print("To enable multi-series inference, set these properties in your Model Node:")
|
||||||
|
print()
|
||||||
|
print("1. multi_series_mode = True")
|
||||||
|
print("2. enabled_series = ['520', '720']")
|
||||||
|
print("3. kl520_port_ids = '28,32'")
|
||||||
|
print("4. kl720_port_ids = '4'")
|
||||||
|
print("5. assets_folder = (optional, for auto model/firmware detection)")
|
||||||
|
print()
|
||||||
|
print("Expected devices found:")
|
||||||
|
print(" KL520 devices on ports: 28, 32")
|
||||||
|
print(" KL720 device on port: 4")
|
||||||
|
print()
|
||||||
|
print("If multi_series_mode is False or not set, the system will use")
|
||||||
|
print("single-series mode with only the first available device.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
check_mflow_files()
|
||||||
|
print_configuration_guide()
|
||||||
58
debug_deployment.py
Normal file
58
debug_deployment.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Debug deployment error
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
def simulate_deployment():
|
||||||
|
"""Simulate the deployment process to find the Optional error"""
|
||||||
|
try:
|
||||||
|
print("Testing export_pipeline_data equivalent...")
|
||||||
|
|
||||||
|
# Simulate creating a node and getting properties
|
||||||
|
from core.nodes.exact_nodes import ExactModelNode
|
||||||
|
|
||||||
|
# This would be similar to what dashboard does
|
||||||
|
node = ExactModelNode()
|
||||||
|
print("Node created")
|
||||||
|
|
||||||
|
# Check if node has get_business_properties
|
||||||
|
if hasattr(node, 'get_business_properties'):
|
||||||
|
print("Node has get_business_properties")
|
||||||
|
try:
|
||||||
|
props = node.get_business_properties()
|
||||||
|
print(f"Properties extracted: {type(props)}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in get_business_properties: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# Test the mflow converter directly
|
||||||
|
print("\nTesting MFlowConverter...")
|
||||||
|
from core.functions.mflow_converter import MFlowConverter
|
||||||
|
converter = MFlowConverter(default_fw_path='.')
|
||||||
|
print("MFlowConverter created successfully")
|
||||||
|
|
||||||
|
# Test multi-series config building
|
||||||
|
test_props = {
|
||||||
|
'multi_series_mode': True,
|
||||||
|
'enabled_series': ['520', '720'],
|
||||||
|
'kl520_port_ids': '28,32',
|
||||||
|
'kl720_port_ids': '4'
|
||||||
|
}
|
||||||
|
|
||||||
|
config = converter._build_multi_series_config_from_properties(test_props)
|
||||||
|
print(f"Multi-series config: {config}")
|
||||||
|
|
||||||
|
print("All tests passed!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
simulate_deployment()
|
||||||
90
debug_multi_series_flow.py
Normal file
90
debug_multi_series_flow.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Debug the multi-series configuration flow
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
def test_full_flow():
|
||||||
|
"""Test the complete multi-series configuration flow"""
|
||||||
|
print("=== Testing Multi-Series Configuration Flow ===")
|
||||||
|
|
||||||
|
# Simulate node properties as they would appear in the UI
|
||||||
|
mock_node_properties = {
|
||||||
|
'multi_series_mode': True,
|
||||||
|
'enabled_series': ['520', '720'],
|
||||||
|
'kl520_port_ids': '28,32',
|
||||||
|
'kl720_port_ids': '4',
|
||||||
|
'assets_folder': '',
|
||||||
|
'max_queue_size': 100
|
||||||
|
}
|
||||||
|
|
||||||
|
print(f"1. Mock node properties: {mock_node_properties}")
|
||||||
|
|
||||||
|
# Test the mflow converter building multi-series config
|
||||||
|
try:
|
||||||
|
from core.functions.mflow_converter import MFlowConverter
|
||||||
|
converter = MFlowConverter(default_fw_path='.')
|
||||||
|
|
||||||
|
config = converter._build_multi_series_config_from_properties(mock_node_properties)
|
||||||
|
print(f"2. Multi-series config built: {config}")
|
||||||
|
|
||||||
|
if config:
|
||||||
|
print(" [OK] Multi-series config successfully built")
|
||||||
|
|
||||||
|
# Test StageConfig creation
|
||||||
|
from core.functions.InferencePipeline import StageConfig
|
||||||
|
|
||||||
|
stage_config = StageConfig(
|
||||||
|
stage_id="test_stage",
|
||||||
|
port_ids=[], # Not used in multi-series
|
||||||
|
scpu_fw_path='',
|
||||||
|
ncpu_fw_path='',
|
||||||
|
model_path='',
|
||||||
|
upload_fw=False,
|
||||||
|
multi_series_mode=True,
|
||||||
|
multi_series_config=config
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"3. StageConfig created with multi_series_mode: {stage_config.multi_series_mode}")
|
||||||
|
print(f" Multi-series config: {stage_config.multi_series_config}")
|
||||||
|
|
||||||
|
# Test what would happen in PipelineStage initialization
|
||||||
|
print("4. Testing PipelineStage initialization logic:")
|
||||||
|
if stage_config.multi_series_mode and stage_config.multi_series_config:
|
||||||
|
print(" [OK] Would initialize MultiDongle with multi_series_config")
|
||||||
|
print(f" MultiDongle(multi_series_config={stage_config.multi_series_config})")
|
||||||
|
else:
|
||||||
|
print(" [ERROR] Would fall back to single-series mode")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(" [ERROR] Multi-series config is None - this is the problem!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in flow test: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def test_node_direct():
|
||||||
|
"""Test creating a node directly and getting its inference config"""
|
||||||
|
print("\n=== Testing Node Direct Configuration ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
from core.nodes.exact_nodes import ExactModelNode
|
||||||
|
|
||||||
|
# This won't work without NodeGraphQt, but let's see what happens
|
||||||
|
node = ExactModelNode()
|
||||||
|
print("Node created (mock mode)")
|
||||||
|
|
||||||
|
# Test the get_business_properties method that would be called during export
|
||||||
|
props = node.get_business_properties()
|
||||||
|
print(f"Business properties: {props}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in node test: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_full_flow()
|
||||||
|
test_node_direct()
|
||||||
37
simple_test.py
Normal file
37
simple_test.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Simple test for port ID configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
from core.nodes.exact_nodes import ExactModelNode
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Creating ExactModelNode...")
|
||||||
|
node = ExactModelNode()
|
||||||
|
|
||||||
|
print("Testing property options...")
|
||||||
|
if hasattr(node, '_property_options'):
|
||||||
|
port_props = [k for k in node._property_options.keys() if 'port_ids' in k]
|
||||||
|
print(f"Found port ID properties: {port_props}")
|
||||||
|
else:
|
||||||
|
print("No _property_options found")
|
||||||
|
|
||||||
|
print("Testing _build_multi_series_config method...")
|
||||||
|
if hasattr(node, '_build_multi_series_config'):
|
||||||
|
print("Method exists")
|
||||||
|
try:
|
||||||
|
config = node._build_multi_series_config()
|
||||||
|
print(f"Config result: {config}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error calling method: {e}")
|
||||||
|
else:
|
||||||
|
print("Method does not exist")
|
||||||
|
|
||||||
|
print("Test completed!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
134
test_multi_series_fix.py
Normal file
134
test_multi_series_fix.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script to verify multi-series configuration fix
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
# Test the mflow_converter functionality
|
||||||
|
def test_multi_series_config_building():
|
||||||
|
"""Test building multi-series config from properties"""
|
||||||
|
print("Testing multi-series config building...")
|
||||||
|
|
||||||
|
from core.functions.mflow_converter import MFlowConverter
|
||||||
|
|
||||||
|
# Create converter instance
|
||||||
|
converter = MFlowConverter(default_fw_path='.')
|
||||||
|
|
||||||
|
# Mock properties data that would come from a node
|
||||||
|
test_properties = {
|
||||||
|
'multi_series_mode': True,
|
||||||
|
'enabled_series': ['520', '720'],
|
||||||
|
'kl520_port_ids': '28,32',
|
||||||
|
'kl720_port_ids': '4',
|
||||||
|
'assets_folder': '', # Empty for this test
|
||||||
|
'max_queue_size': 100
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test building config
|
||||||
|
config = converter._build_multi_series_config_from_properties(test_properties)
|
||||||
|
|
||||||
|
print(f"Generated config: {config}")
|
||||||
|
|
||||||
|
if config:
|
||||||
|
# Verify structure
|
||||||
|
assert 'KL520' in config, "KL520 should be in config"
|
||||||
|
assert 'KL720' in config, "KL720 should be in config"
|
||||||
|
|
||||||
|
# Check KL520 config
|
||||||
|
kl520_config = config['KL520']
|
||||||
|
assert 'port_ids' in kl520_config, "KL520 should have port_ids"
|
||||||
|
assert kl520_config['port_ids'] == [28, 32], f"KL520 port_ids should be [28, 32], got {kl520_config['port_ids']}"
|
||||||
|
|
||||||
|
# Check KL720 config
|
||||||
|
kl720_config = config['KL720']
|
||||||
|
assert 'port_ids' in kl720_config, "KL720 should have port_ids"
|
||||||
|
assert kl720_config['port_ids'] == [4], f"KL720 port_ids should be [4], got {kl720_config['port_ids']}"
|
||||||
|
|
||||||
|
print("[OK] Multi-series config structure is correct")
|
||||||
|
else:
|
||||||
|
print("[ERROR] Config building returned None")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test with invalid port IDs
|
||||||
|
invalid_properties = {
|
||||||
|
'multi_series_mode': True,
|
||||||
|
'enabled_series': ['520'],
|
||||||
|
'kl520_port_ids': 'invalid,port,ids',
|
||||||
|
'assets_folder': ''
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_config = converter._build_multi_series_config_from_properties(invalid_properties)
|
||||||
|
assert invalid_config is None, "Invalid port IDs should result in None config"
|
||||||
|
print("[OK] Invalid port IDs handled correctly")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def test_stage_config():
|
||||||
|
"""Test StageConfig with multi-series support"""
|
||||||
|
print("\\nTesting StageConfig with multi-series...")
|
||||||
|
|
||||||
|
from core.functions.InferencePipeline import StageConfig
|
||||||
|
|
||||||
|
# Test creating StageConfig with multi-series
|
||||||
|
multi_series_config = {
|
||||||
|
"KL520": {"port_ids": [28, 32]},
|
||||||
|
"KL720": {"port_ids": [4]}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage_config = StageConfig(
|
||||||
|
stage_id="test_stage",
|
||||||
|
port_ids=[], # Not used in multi-series mode
|
||||||
|
scpu_fw_path='',
|
||||||
|
ncpu_fw_path='',
|
||||||
|
model_path='',
|
||||||
|
upload_fw=False,
|
||||||
|
multi_series_mode=True,
|
||||||
|
multi_series_config=multi_series_config
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Created StageConfig with multi_series_mode: {stage_config.multi_series_mode}")
|
||||||
|
print(f"Multi-series config: {stage_config.multi_series_config}")
|
||||||
|
|
||||||
|
assert stage_config.multi_series_mode == True, "multi_series_mode should be True"
|
||||||
|
assert stage_config.multi_series_config == multi_series_config, "multi_series_config should match"
|
||||||
|
|
||||||
|
print("[OK] StageConfig supports multi-series configuration")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run all tests"""
|
||||||
|
print("Testing Multi-Series Configuration Fix")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Test config building
|
||||||
|
if not test_multi_series_config_building():
|
||||||
|
print("[ERROR] Config building test failed")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test StageConfig
|
||||||
|
if not test_stage_config():
|
||||||
|
print("[ERROR] StageConfig test failed")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("\\n" + "=" * 50)
|
||||||
|
print("[SUCCESS] All tests passed!")
|
||||||
|
print("\\nThe fix should now properly:")
|
||||||
|
print("1. Detect multi_series_mode from node properties")
|
||||||
|
print("2. Build multi_series_config from series-specific port IDs")
|
||||||
|
print("3. Pass the config to MultiDongle for true multi-series operation")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Test failed with exception: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
success = main()
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
46
test_multidongle_start.py
Normal file
46
test_multidongle_start.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test MultiDongle start/stop functionality
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
def test_multidongle_start():
|
||||||
|
"""Test MultiDongle start method"""
|
||||||
|
try:
|
||||||
|
from core.functions.Multidongle import MultiDongle
|
||||||
|
|
||||||
|
# Test multi-series configuration
|
||||||
|
multi_series_config = {
|
||||||
|
"KL520": {"port_ids": [28, 32]},
|
||||||
|
"KL720": {"port_ids": [4]}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Creating MultiDongle with multi-series config...")
|
||||||
|
multidongle = MultiDongle(multi_series_config=multi_series_config)
|
||||||
|
|
||||||
|
print(f"Multi-series mode: {multidongle.multi_series_mode}")
|
||||||
|
print(f"Has _start_multi_series method: {hasattr(multidongle, '_start_multi_series')}")
|
||||||
|
print(f"Has _stop_multi_series method: {hasattr(multidongle, '_stop_multi_series')}")
|
||||||
|
|
||||||
|
print("MultiDongle created successfully!")
|
||||||
|
|
||||||
|
# Test that the required attributes exist
|
||||||
|
expected_attrs = ['send_threads', 'receive_threads', 'dispatcher_thread', 'result_ordering_thread']
|
||||||
|
for attr in expected_attrs:
|
||||||
|
if hasattr(multidongle, attr):
|
||||||
|
print(f"[OK] Has attribute: {attr}")
|
||||||
|
else:
|
||||||
|
print(f"[ERROR] Missing attribute: {attr}")
|
||||||
|
|
||||||
|
print("Test completed successfully!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_multidongle_start()
|
||||||
201
test_port_id_config.py
Normal file
201
test_port_id_config.py
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script for new series-specific port ID configuration functionality
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Add the project root to Python path
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
try:
|
||||||
|
from core.nodes.exact_nodes import ExactModelNode
|
||||||
|
print("[OK] Successfully imported ExactModelNode")
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"[ERROR] Failed to import ExactModelNode: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def test_port_id_properties():
|
||||||
|
"""Test that new port ID properties are created correctly"""
|
||||||
|
print("\n=== Testing Port ID Properties Creation ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
node = ExactModelNode()
|
||||||
|
|
||||||
|
# Test that all series port ID properties exist
|
||||||
|
series_properties = ['kl520_port_ids', 'kl720_port_ids', 'kl630_port_ids', 'kl730_port_ids', 'kl540_port_ids']
|
||||||
|
|
||||||
|
for prop in series_properties:
|
||||||
|
if hasattr(node, 'get_property'):
|
||||||
|
try:
|
||||||
|
value = node.get_property(prop)
|
||||||
|
print(f"[OK] Property {prop} exists with value: '{value}'")
|
||||||
|
except:
|
||||||
|
print(f"[ERROR] Property {prop} does not exist or cannot be accessed")
|
||||||
|
else:
|
||||||
|
print(f"[WARN] Node does not have get_property method (NodeGraphQt not available)")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Test property options
|
||||||
|
if hasattr(node, '_property_options'):
|
||||||
|
for prop in series_properties:
|
||||||
|
if prop in node._property_options:
|
||||||
|
options = node._property_options[prop]
|
||||||
|
print(f"[OK] Property options for {prop}: {options}")
|
||||||
|
else:
|
||||||
|
print(f"[ERROR] No property options found for {prop}")
|
||||||
|
else:
|
||||||
|
print("[WARN] Node does not have _property_options")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Error testing port ID properties: {e}")
|
||||||
|
|
||||||
|
def test_display_properties():
|
||||||
|
"""Test that display properties work correctly"""
|
||||||
|
print("\n=== Testing Display Properties ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
node = ExactModelNode()
|
||||||
|
|
||||||
|
if not hasattr(node, 'get_display_properties'):
|
||||||
|
print("[WARN] Node does not have get_display_properties method (NodeGraphQt not available)")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Test single-series mode
|
||||||
|
if hasattr(node, 'set_property'):
|
||||||
|
node.set_property('multi_series_mode', False)
|
||||||
|
single_props = node.get_display_properties()
|
||||||
|
print(f"[OK] Single-series display properties: {single_props}")
|
||||||
|
|
||||||
|
# Test multi-series mode
|
||||||
|
node.set_property('multi_series_mode', True)
|
||||||
|
node.set_property('enabled_series', ['520', '720'])
|
||||||
|
multi_props = node.get_display_properties()
|
||||||
|
print(f"[OK] Multi-series display properties: {multi_props}")
|
||||||
|
|
||||||
|
# Check if port ID properties are included
|
||||||
|
expected_port_props = ['kl520_port_ids', 'kl720_port_ids']
|
||||||
|
found_port_props = [prop for prop in multi_props if prop in expected_port_props]
|
||||||
|
print(f"[OK] Found port ID properties in display: {found_port_props}")
|
||||||
|
|
||||||
|
# Test with different enabled series
|
||||||
|
node.set_property('enabled_series', ['630', '730'])
|
||||||
|
multi_props_2 = node.get_display_properties()
|
||||||
|
print(f"[OK] Display properties with KL630/730: {multi_props_2}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("[WARN] Node does not have set_property method (NodeGraphQt not available)")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Error testing display properties: {e}")
|
||||||
|
|
||||||
|
def test_multi_series_config():
|
||||||
|
"""Test multi-series configuration building"""
|
||||||
|
print("\n=== Testing Multi-Series Config Building ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
node = ExactModelNode()
|
||||||
|
|
||||||
|
if not hasattr(node, '_build_multi_series_config'):
|
||||||
|
print("[ERROR] Node does not have _build_multi_series_config method")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not hasattr(node, 'set_property'):
|
||||||
|
print("[WARN] Node does not have set_property method (NodeGraphQt not available)")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Test with sample configuration
|
||||||
|
node.set_property('enabled_series', ['520', '720'])
|
||||||
|
node.set_property('kl520_port_ids', '28,32')
|
||||||
|
node.set_property('kl720_port_ids', '30,34')
|
||||||
|
node.set_property('assets_folder', '/fake/assets/path')
|
||||||
|
|
||||||
|
# Build multi-series config
|
||||||
|
config = node._build_multi_series_config()
|
||||||
|
print(f"[OK] Generated multi-series config: {config}")
|
||||||
|
|
||||||
|
# Verify structure
|
||||||
|
if config:
|
||||||
|
expected_keys = ['KL520', 'KL720']
|
||||||
|
for key in expected_keys:
|
||||||
|
if key in config:
|
||||||
|
series_config = config[key]
|
||||||
|
print(f"[OK] {key} config: {series_config}")
|
||||||
|
|
||||||
|
if 'port_ids' in series_config:
|
||||||
|
print(f" - Port IDs: {series_config['port_ids']}")
|
||||||
|
else:
|
||||||
|
print(f" [ERROR] Missing port_ids in {key} config")
|
||||||
|
else:
|
||||||
|
print(f"[ERROR] Missing {key} in config")
|
||||||
|
else:
|
||||||
|
print("[ERROR] Generated config is None or empty")
|
||||||
|
|
||||||
|
# Test with invalid port IDs
|
||||||
|
node.set_property('kl520_port_ids', 'invalid,port,ids')
|
||||||
|
config_invalid = node._build_multi_series_config()
|
||||||
|
print(f"[OK] Config with invalid port IDs: {config_invalid}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Error testing multi-series config: {e}")
|
||||||
|
|
||||||
|
def test_inference_config():
|
||||||
|
"""Test inference configuration"""
|
||||||
|
print("\n=== Testing Inference Config ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
node = ExactModelNode()
|
||||||
|
|
||||||
|
if not hasattr(node, 'get_inference_config'):
|
||||||
|
print("[ERROR] Node does not have get_inference_config method")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not hasattr(node, 'set_property'):
|
||||||
|
print("[WARN] Node does not have set_property method (NodeGraphQt not available)")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Test multi-series inference config
|
||||||
|
node.set_property('multi_series_mode', True)
|
||||||
|
node.set_property('enabled_series', ['520', '720'])
|
||||||
|
node.set_property('kl520_port_ids', '28,32')
|
||||||
|
node.set_property('kl720_port_ids', '30,34')
|
||||||
|
node.set_property('assets_folder', '/fake/assets')
|
||||||
|
node.set_property('max_queue_size', 50)
|
||||||
|
|
||||||
|
inference_config = node.get_inference_config()
|
||||||
|
print(f"[OK] Inference config: {inference_config}")
|
||||||
|
|
||||||
|
# Check if multi_series_config is included
|
||||||
|
if 'multi_series_config' in inference_config:
|
||||||
|
ms_config = inference_config['multi_series_config']
|
||||||
|
print(f"[OK] Multi-series config included: {ms_config}")
|
||||||
|
else:
|
||||||
|
print("[WARN] Multi-series config not found in inference config")
|
||||||
|
|
||||||
|
# Test single-series mode
|
||||||
|
node.set_property('multi_series_mode', False)
|
||||||
|
node.set_property('model_path', '/fake/model.nef')
|
||||||
|
node.set_property('port_id', '28')
|
||||||
|
|
||||||
|
single_config = node.get_inference_config()
|
||||||
|
print(f"[OK] Single-series config: {single_config}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Error testing inference config: {e}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run all tests"""
|
||||||
|
print("Testing Series-Specific Port ID Configuration")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
test_port_id_properties()
|
||||||
|
test_display_properties()
|
||||||
|
test_multi_series_config()
|
||||||
|
test_inference_config()
|
||||||
|
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("Test completed!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@ -79,8 +79,10 @@ class StdoutCapture:
|
|||||||
|
|
||||||
def write(self, text):
|
def write(self, text):
|
||||||
# Write to original stdout/stderr (so it still appears in terminal)
|
# Write to original stdout/stderr (so it still appears in terminal)
|
||||||
self.original.write(text)
|
# Check if original exists (it might be None in PyInstaller builds)
|
||||||
self.original.flush()
|
if self.original is not None:
|
||||||
|
self.original.write(text)
|
||||||
|
self.original.flush()
|
||||||
|
|
||||||
# Capture for GUI if it's a substantial message and not already emitting
|
# Capture for GUI if it's a substantial message and not already emitting
|
||||||
if text.strip() and not self._emitting:
|
if text.strip() and not self._emitting:
|
||||||
@ -91,7 +93,9 @@ class StdoutCapture:
|
|||||||
self._emitting = False
|
self._emitting = False
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
self.original.flush()
|
# Check if original exists before calling flush
|
||||||
|
if self.original is not None:
|
||||||
|
self.original.flush()
|
||||||
|
|
||||||
# Replace stdout and stderr with our tee writers
|
# Replace stdout and stderr with our tee writers
|
||||||
sys.stdout = TeeWriter(self.original_stdout, self.captured_output, self.signal_emitter)
|
sys.stdout = TeeWriter(self.original_stdout, self.captured_output, self.signal_emitter)
|
||||||
|
|||||||
41
verify_properties.py
Normal file
41
verify_properties.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Verify that properties are correctly set for multi-series
|
||||||
|
"""
|
||||||
|
|
||||||
|
def verify_properties():
|
||||||
|
"""Check the expected multi-series properties"""
|
||||||
|
|
||||||
|
print("Multi-Series Configuration Checklist:")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
print("\n1. In your Dashboard, Model Node properties should have:")
|
||||||
|
print(" ✓ multi_series_mode = True")
|
||||||
|
print(" ✓ enabled_series = ['520', '720']")
|
||||||
|
print(" ✓ kl520_port_ids = '28,32'")
|
||||||
|
print(" ✓ kl720_port_ids = '4'")
|
||||||
|
print(" ✓ assets_folder = (optional, for auto model/firmware detection)")
|
||||||
|
|
||||||
|
print("\n2. After setting these properties, when you deploy:")
|
||||||
|
print(" Expected output should show:")
|
||||||
|
print(" '[stage_1_Model_Node] Using multi-series mode with config: ...'")
|
||||||
|
print(" NOT: 'Single-series config converted to multi-series format'")
|
||||||
|
|
||||||
|
print("\n3. If you still see single-series behavior:")
|
||||||
|
print(" a) Double-check property names (they should be lowercase)")
|
||||||
|
print(" b) Make sure multi_series_mode is checked/enabled")
|
||||||
|
print(" c) Verify port IDs are comma-separated strings")
|
||||||
|
print(" d) Save the .mflow file and re-deploy")
|
||||||
|
|
||||||
|
print("\n4. Property format reference:")
|
||||||
|
print(" - kl520_port_ids: '28,32' (string, comma-separated)")
|
||||||
|
print(" - kl720_port_ids: '4' (string)")
|
||||||
|
print(" - enabled_series: ['520', '720'] (list)")
|
||||||
|
print(" - multi_series_mode: True (boolean)")
|
||||||
|
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("If properties are set correctly, your deployment should use")
|
||||||
|
print("true multi-series load balancing across KL520 and KL720 dongles!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
verify_properties()
|
||||||
Loading…
x
Reference in New Issue
Block a user