99import logging
1010import pathlib
1111from importlib import metadata
12- from typing import Dict , Optional , Type
12+ from typing import Type , Union
1313
1414import toml
1515from pydantic import BaseModel
1616from pydantic_settings import BaseSettings , SettingsConfigDict
1717
1818
19- class _HermesSettings (BaseSettings ):
19+
20+ class HermesSettings (BaseSettings ):
2021 """Root class for HERMES configuration model."""
2122
2223 model_config = SettingsConfigDict (env_file_encoding = 'utf-8' )
2324
24- logging : Dict = {}
25+ logging : dict = {}
2526
2627
2728class HermesCommand (abc .ABC ):
@@ -31,7 +32,7 @@ class HermesCommand(abc.ABC):
3132 """
3233
3334 command_name : str = ""
34- settings_class : Type = _HermesSettings
35+ settings_class : Type = HermesSettings
3536
3637 def __init__ (self , parser : argparse .ArgumentParser ):
3738 """Initialize a new instance of any HERMES command.
@@ -45,28 +46,27 @@ def __init__(self, parser: argparse.ArgumentParser):
4546 self .log = logging .getLogger (f"hermes.{ self .command_name } " )
4647 self .errors = []
4748
48- @classmethod
49- def init_plugins (cls ):
49+ def init_plugins (self ):
5050 """Collect and initialize the plugins available for the HERMES command."""
5151
5252 # Collect all entry points for this group (i.e., all valid plug-ins for the step)
53- entry_point_group = f"hermes.{ cls .command_name } "
54- group_plugins = {
55- entry_point . name : entry_point . load ()
56- for entry_point in metadata . entry_points ( group = entry_point_group )
57- }
58-
59- # Collect the plug-in specific configurations
60- cls . derive_settings_class ({
61- plugin_name : plugin_class .settings_class
62- for plugin_name , plugin_class in group_plugins . items ()
63- if hasattr ( plugin_class , "settings_class" ) and plugin_class . settings_class is not None
64- } )
53+ entry_point_group = f"hermes.{ self .command_name } "
54+ group_plugins = {}
55+ group_settings = {}
56+
57+ for entry_point in metadata . entry_points ( group = entry_point_group ):
58+ plugin_cls = entry_point . load ()
59+
60+ group_plugins [ entry_point . name ] = plugin_cls
61+ if hasattr ( plugin_cls , 'settings_class' ) and plugin_cls .settings_class is not None :
62+ group_settings [ entry_point . name ] = plugin_cls . settings_class
63+
64+ self . derive_settings_class ( group_settings )
6565
6666 return group_plugins
6767
6868 @classmethod
69- def derive_settings_class (cls , setting_types : Dict [str , Type ]) -> None :
69+ def derive_settings_class (cls , setting_types : dict [str , Type ]) -> None :
7070 """Build a new Pydantic data model class for configuration.
7171
7272 This will create a new class that includes all settings from the plugins available.
@@ -131,13 +131,10 @@ def init_command_parser(self, command_parser: argparse.ArgumentParser) -> None:
131131
132132 def load_settings (self , args : argparse .Namespace ):
133133 """Load settings from the configuration file (passed in from command line)."""
134- try :
135- toml_data = toml .load (args .path / args .config )
136- self .root_settings = HermesCommand .settings_class .model_validate (toml_data )
137- self .settings = getattr (self .root_settings , self .command_name )
138- except FileNotFoundError as e :
139- self .log .error ("hermes.toml was not found. Try to run 'hermes init' first or create one manually." )
140- raise e # This will lead to our default error message & sys.exit
134+
135+ toml_data = toml .load (args .path / args .config )
136+ self .root_settings = HermesCommand .settings_class .model_validate (toml_data )
137+ self .settings = getattr (self .root_settings , self .command_name )
141138
142139 def patch_settings (self , args : argparse .Namespace ):
143140 """Process command line options for the settings."""
@@ -164,7 +161,9 @@ def __call__(self, args: argparse.Namespace):
164161class HermesPlugin (abc .ABC ):
165162 """Base class for all HERMES plugins."""
166163
167- settings_class : Optional [Type ] = None
164+ pluing_node = None
165+
166+ settings_class : Union [Type , None ] = None
168167
169168 @abc .abstractmethod
170169 def __call__ (self , command : HermesCommand ) -> None :
@@ -202,27 +201,3 @@ def __call__(self, args: argparse.Namespace) -> None:
202201 # Otherwise, simply show the general help and exit (cleanly).
203202 self .parser .print_help ()
204203 self .parser .exit ()
205-
206- def load_settings (self , args : argparse .Namespace ):
207- """No settings are needed for the help command."""
208- pass
209-
210-
211- class HermesVersionSettings (BaseModel ):
212- """Intentionally empty settings class for the version command."""
213- pass
214-
215-
216- class HermesVersionCommand (HermesCommand ):
217- """Show HERMES version and exit."""
218-
219- command_name = "version"
220- settings_class = HermesVersionSettings
221-
222- def load_settings (self , args : argparse .Namespace ):
223- """Pass loading settings as not necessary for this command."""
224- pass
225-
226- def __call__ (self , args : argparse .Namespace ) -> None :
227- self .log .info (metadata .version ("hermes" ))
228- self .parser .exit ()
0 commit comments