0.1.33
Loading...
Searching...
No Matches
__main__.py
Go to the documentation of this file.
1"""
2Plugin status and discovery command-line interface for PyHelios.
3
4This module provides command-line tools for checking plugin availability,
5system compatibility, and generating configuration recommendations.
6
7Usage:
8 python -m pyhelios.plugins status
9 python -m pyhelios.plugins discover
10 python -m pyhelios.plugins info <plugin_name>
11 python -m pyhelios.plugins validate <plugin_list>
12"""
13
14import sys
15import argparse
16from pathlib import Path
17
18# Add pyhelios to path for imports
19sys.path.insert(0, str(Path(__file__).parent.parent.parent))
20
21from pyhelios.plugins import print_plugin_status
22from pyhelios.plugins.registry import get_plugin_registry
23from pyhelios.config.plugin_metadata import PLUGIN_METADATA, get_all_plugin_names, get_platform_compatible_plugins
24from pyhelios.config.dependency_resolver import PluginDependencyResolver
25
26
28 """Allow the CLI's status symbols to print on a legacy-codepage console.
29
30 Windows consoles default to a codepage such as cp1252, whose codec has no
31 mapping for the check and cross marks used below and raises
32 UnicodeEncodeError rather than substituting. Prefer UTF-8, and fall back to
33 replacing unencodable characters so output degrades to '?' instead of
34 killing the command.
35 """
36 for stream in (sys.stdout, sys.stderr):
37 reconfigure = getattr(stream, 'reconfigure', None)
38 if reconfigure is None:
39 continue
40 try:
41 reconfigure(encoding='utf-8', errors='replace')
42 except (OSError, ValueError, LookupError):
43 try:
44 reconfigure(errors='replace')
45 except (OSError, ValueError):
46 pass
47
48
49def cmd_status(args):
50 """Show comprehensive plugin status."""
53
54def cmd_discover(args):
55 """Discover and recommend optimal plugin configuration."""
56 print("PyHelios Plugin Discovery")
57 print("=" * 25)
58
59 resolver = PluginDependencyResolver()
60
61 # Check system capabilities
62 print("System Analysis:")
63 print("-" * 15)
64
65 # Platform compatibility
66 compatible_plugins = get_platform_compatible_plugins()
67 all_plugins = get_all_plugin_names()
68 platform_compatibility = len(compatible_plugins) / len(all_plugins) * 100
69 print(f"Platform compatibility: {platform_compatibility:.1f}% ({len(compatible_plugins)}/{len(all_plugins)} plugins)")
70
71 # GPU availability
72 gpu_available = resolver._check_cuda()
73 print(f"GPU/CUDA support: {'✓ Available' if gpu_available else '✗ Not available'}")
74
75 # System dependencies
76 system_deps = resolver._check_system_dependencies(compatible_plugins)
77 available_deps = sum(1 for available in system_deps.values() if available)
78 total_deps = len(system_deps)
79 if total_deps > 0:
80 dep_percentage = available_deps / total_deps * 100
81 print(f"System dependencies: {dep_percentage:.1f}% available ({available_deps}/{total_deps})")
82
83 print()
84
85 # Recommend configuration
86 print("Recommendations:")
87 print("-" * 15)
88
89 if gpu_available:
90 print("✓ GPU detected - GPU-accelerated workflows are possible")
91 print(" Recommended for: Ray tracing, radiation modeling, high-performance simulations")
92 recommended_plugins = ["weberpenntree", "canopygenerator", "solarposition", "radiation", "visualizer", "energybalance"]
93 else:
94 print("• No GPU detected - Using CPU-based workflows")
95 print(" Recommended for: General plant modeling, visualization, basic simulations")
96 recommended_plugins = ["weberpenntree", "canopygenerator", "solarposition", "visualizer", "energybalance"]
97
98 # Filter by platform compatibility
99 recommended_plugins = [p for p in recommended_plugins if p in compatible_plugins]
100 validation = resolver.validate_configuration(recommended_plugins)
101
102 print(f"\nRecommended plugins ({len(recommended_plugins)}):")
103 for plugin in recommended_plugins:
104 if plugin in validation['platform_compatible']:
105 print(f" ✓ {plugin}")
106 else:
107 print(f" ⚠ {plugin} (may have compatibility issues)")
108
109 # Show build command
110 print(f"\nSuggested build command:")
111 plugin_list = ",".join(recommended_plugins)
112 print(f" build_scripts/build_helios --plugins {plugin_list}")
113
114 # Show potential issues
115 if validation['platform_incompatible']:
116 print(f"\n⚠ Platform compatibility issues:")
117 for plugin in validation['platform_incompatible']:
118 print(f" - {plugin}")
119
120 missing_system_deps = [dep for dep, available in system_deps.items() if not available]
121 if missing_system_deps:
122 print(f"\n⚠ Missing system dependencies:")
123 for dep in missing_system_deps:
124 print(f" - {dep}")
125
126
127def cmd_info(args):
128 """Show detailed information about a specific plugin."""
129 plugin_name = args.plugin_name
131 if plugin_name not in PLUGIN_METADATA:
132 print(f"❌ Unknown plugin: {plugin_name}")
133 print(f"Available plugins: {', '.join(sorted(get_all_plugin_names()))}")
134 return 1
135
136 metadata = PLUGIN_METADATA[plugin_name]
137
138 print(f"Plugin Information: {plugin_name}")
139 print("=" * (20 + len(plugin_name)))
140
141 print(f"Description: {metadata.description}")
142 print(f"GPU Required: {'Yes' if metadata.gpu_required else 'No'}")
143 print(f"Optional: {'Yes' if metadata.optional else 'No (core plugin)'}")
144 print(f"Supported Platforms: {', '.join(metadata.platforms)}")
145
146 if metadata.system_dependencies:
147 print(f"System Dependencies: {', '.join(metadata.system_dependencies)}")
148
149 if metadata.plugin_dependencies:
150 print(f"Plugin Dependencies: {', '.join(metadata.plugin_dependencies)}")
151
152
153 # Runtime availability
154 print(f"\nRuntime Status:")
155 registry = get_plugin_registry()
156 available = registry.is_plugin_available(plugin_name)
157 print(f"Available: {'✓ Yes' if available else '✗ No'}")
158
159 if not available:
160 missing = registry.get_missing_plugins(list(metadata.plugin_dependencies or []))
161 if missing:
162 print(f" Missing plugin dependencies: {', '.join(missing)}")
163 print(f" Rebuild with: build_scripts/build_helios --plugins {plugin_name}")
164
165 return 0
166
167
168def cmd_validate(args):
169 """Validate a list of plugins."""
170 if args.plugins:
171 plugins = args.plugins
172 else:
173 # Read from stdin or prompt
174 plugins_input = input("Enter plugins (comma-separated): ").strip()
175 plugins = [p.strip() for p in plugins_input.split(',') if p.strip()]
176
177 if not plugins:
178 print("❌ No plugins specified")
179 return 1
180
181 print(f"Validating plugins: {', '.join(plugins)}")
182 print("=" * 40)
183
184 resolver = PluginDependencyResolver()
185 validation = resolver.validate_configuration(plugins)
186
187 print(f"Total requested: {len(plugins)}")
188 print(f"Valid plugins: {len(validation['valid_plugins'])}")
189 print(f"Invalid plugins: {len(validation['invalid_plugins'])}")
190 print(f"Platform compatible: {len(validation['platform_compatible'])}")
191 print(f"Platform incompatible: {len(validation['platform_incompatible'])}")
192
193 if validation['invalid_plugins']:
194 print(f"\n❌ Invalid plugins:")
195 for plugin in validation['invalid_plugins']:
196 print(f" - {plugin}")
197
198 if validation['platform_incompatible']:
199 print(f"\n⚠ Platform incompatible:")
200 for plugin in validation['platform_incompatible']:
201 print(f" - {plugin}")
202
203 if validation['system_dependencies']:
204 print(f"\nSystem Dependencies:")
205 for dep, available in validation['system_dependencies'].items():
206 status = "✓" if available else "✗"
207 print(f" {status} {dep}")
208
209 print(f"\nGPU required: {'Yes' if validation['gpu_required'] else 'No'}")
210
211 # Provide suggestions
212 if validation['invalid_plugins'] or validation['platform_incompatible']:
213 print(f"\n💡 Suggestions:")
214 print(f" - Use only valid, platform-compatible plugins")
215 print(f" - Check available plugins: python -m pyhelios.plugins status")
216 print(f" - Use specific plugin selection: build_scripts/build_helios --plugins plugin1,plugin2")
217 return 1
218 else:
219 print(f"\n✅ Configuration is valid")
220 return 0
221
222
223
224
225def main():
226 """Main entry point for plugin command-line interface."""
229 parser = argparse.ArgumentParser(
230 description="PyHelios plugin status and discovery tools",
231 formatter_class=argparse.RawDescriptionHelpFormatter,
232 epilog="""
233Commands:
234 status Show comprehensive plugin status
235 discover Analyze system and recommend optimal configuration
236 info Show detailed information about a specific plugin
237 validate Validate a list of plugins for compatibility
238
239Examples:
240 python -m pyhelios.plugins status
241 python -m pyhelios.plugins discover
242 python -m pyhelios.plugins info radiation
243 python -m pyhelios.plugins validate --plugins radiation,visualizer
244 """
245 )
246
247 subparsers = parser.add_subparsers(dest='command', help='Available commands')
248
249 # Status command
250 status_parser = subparsers.add_parser('status', help='Show plugin status')
251 status_parser.set_defaults(func=cmd_status)
252
253 # Discover command
254 discover_parser = subparsers.add_parser('discover', help='Discover optimal configuration')
255 discover_parser.set_defaults(func=cmd_discover)
256
257 # Info command
258 info_parser = subparsers.add_parser('info', help='Show plugin information')
259 info_parser.add_argument('plugin_name', help='Name of the plugin')
260 info_parser.set_defaults(func=cmd_info)
261
262 # Validate command
263 validate_parser = subparsers.add_parser('validate', help='Validate plugin configuration')
264 validate_parser.add_argument('--plugins', nargs='*', help='Plugin names to validate')
265 validate_parser.set_defaults(func=cmd_validate)
266
267
268 args = parser.parse_args()
269
270 if not args.command:
271 parser.print_help()
272 return 1
273
274 try:
275 return args.func(args)
276 except KeyboardInterrupt:
277 print("\nOperation cancelled by user")
278 return 130
279 except Exception as e:
280 print(f"❌ Error: {e}")
281 return 1
282
283
284if __name__ == '__main__':
285 sys.exit(main())
cmd_discover(args)
Discover and recommend optimal plugin configuration.
Definition __main__.py:57
_make_output_encoding_safe()
Allow the CLI's status symbols to print on a legacy-codepage console.
Definition __main__.py:37
cmd_validate(args)
Validate a list of plugins.
Definition __main__.py:171
main()
Main entry point for plugin command-line interface.
Definition __main__.py:228
cmd_info(args)
Show detailed information about a specific plugin.
Definition __main__.py:130
cmd_status(args)
Show comprehensive plugin status.
Definition __main__.py:52
print_plugin_status()
Print current plugin status for debugging.
Definition __init__.py:51