1111logger = logging .getLogger (__name__ )
1212
1313
14- def setup_plugins (app : Optional [GliderApp ] = None ) -> list [str ]:
14+ def setup_plugins (app : Optional [" GliderApp" ] = None ) -> list [str ]:
1515 """
1616 Discover and initialize OpenGlider plugins.
1717 """
1818 plugins = []
19- potential_plugins = _discover_plugins ()
20-
21- for plugin_name in potential_plugins :
19+ seen = set ()
20+
21+ for plugin_name in _discover_plugins ():
22+ if plugin_name in seen :
23+ continue
24+ seen .add (plugin_name )
25+
2226 logger .info (f"Loading plugin: { plugin_name } " )
23-
27+
2428 if not _load_plugin (plugin_name , app ):
2529 continue
26-
30+
2731 plugins .append (plugin_name )
28-
32+
2933 if plugins :
3034 logger .info (f"Successfully loaded { len (plugins )} plugin(s): { ', ' .join (plugins )} " )
3135 else :
3236 logger .info ("No plugins loaded" )
33-
37+
3438 return plugins
3539
3640
41+ def _normalize (name : str ) -> str :
42+ return name .lower ().replace ("-" , "_" ).strip ()
43+
44+
3745def _discover_plugins () -> list [str ]:
3846 """
3947 Discover OpenGlider plugins using importlib.metadata.
@@ -45,70 +53,52 @@ def _discover_plugins() -> list[str]:
4553 Returns:
4654 List of plugin package names
4755 """
48- plugins = []
49-
56+ plugins = {}
57+
5058 try :
51- # Get all installed distributions
52- distributions = importlib .metadata .distributions ()
53-
54- for dist in distributions :
55- name = dist . metadata . get ( "Name" , "" )
56-
57- # Match openglider-* or openglider_* but not openglider itself
58- if name and name != "openglider" :
59- # Normalize name for comparison (PEP 503)
60- normalized = name . lower (). replace ( "-" , "_" )
61- if normalized . startswith ( "openglider_" ):
62- # Use the normalized form as module name
63- plugins . append ( normalized )
64-
59+ for dist in importlib . metadata . distributions ():
60+ name = dist .metadata .get ( "Name" ) or dist . name
61+ if not name :
62+ continue
63+
64+ normalized = _normalize ( name )
65+
66+ # only match plugins
67+ if not normalized . startswith ( "openglider_" ):
68+ continue
69+
70+ # deduplicate by normalized name
71+ plugins [ normalized ] = dist
72+
6573 except Exception as e :
6674 logger .error (f"Error discovering plugins: { e } " , exc_info = True )
67-
68- return plugins
6975
76+ return list (plugins .keys ())
7077
71- def _load_plugin (plugin_name : str , app : Optional [GliderApp ]) -> bool :
72- """
73- Load and initialize a single plugin.
74-
75- Args:
76- plugin_name: Name of the plugin module to load
77- app: The GliderApp instance to pass to the init function
78- fail_fast: Whether to raise exceptions or just log them
79-
80- Returns:
81- True if plugin loaded successfully, False otherwise
82-
83- Raises:
84- Exception: If fail_fast=True and loading fails
85- """
78+
79+ def _load_plugin (plugin_name : str , app : Optional ["GliderApp" ]) -> bool :
8680 try :
8781 module = importlib .import_module (plugin_name )
8882
8983 # Look for the init function
9084 init_func : Optional [Callable ] = getattr (module , "init" , None )
91-
85+
9286 if init_func is None :
93- logger .warning (f"Plugin '{ plugin_name } ' has no init() function - skipping initialization" )
94- logger .info (f"dir: { dir (module )} " )
87+ logger .warning (f"Plugin '{ plugin_name } ' has no init() function" )
9588 return False
96-
89+
9790 if not callable (init_func ):
98- logger .warning (f"Plugin '{ plugin_name } ' has non-callable init attribute - skipping " )
91+ logger .warning (f"Plugin '{ plugin_name } ' init is not callable " )
9992 return False
100-
101- # Call the plugin's init function
93+
10294 init_func (app )
103- logger .debug (f"Successfully initialized plugin: { plugin_name } " )
95+ logger .debug (f"Initialized plugin: { plugin_name } " )
10496 return True
105-
97+
10698 except ImportError as e :
107- error_msg = f"Failed to import plugin '{ plugin_name } ': { e } "
108- logger .error (error_msg , exc_info = True )
99+ logger .error (f"Failed to import plugin '{ plugin_name } ': { e } " , exc_info = True )
109100 return False
110-
101+
111102 except Exception as e :
112- error_msg = f"Error initializing plugin '{ plugin_name } ': { e } "
113- logger .error (error_msg )
114- raise
103+ logger .error (f"Error initializing plugin '{ plugin_name } ': { e } " , exc_info = True )
104+ raise
0 commit comments