11#!/usr/bin/env python3
22"""
3- Plugin manager for loading parsers and generators from explicit configuration.
3+ Plugin manager for loading parser-generator pipelines from configuration.
44"""
55
66import importlib .util
77from pathlib import Path
8- from typing import Dict , Optional
8+ from typing import List
99
1010import yaml
1111
12- from .interfaces import InputParser , OutputGenerator
12+ from .interfaces import InputParser , OutputGenerator , Pipeline
1313
1414
1515class PluginManager :
16- """Loads and manages parser and generator plugins from configuration."""
16+ """Loads and manages parser- generator pipelines from configuration."""
1717
1818 def __init__ (self ):
19- self .parsers : Dict [str , InputParser ] = {}
20- self .generators : Dict [str , OutputGenerator ] = {}
21- self .parser_to_generator : Dict [str , str ] = {} # Maps parser name to generator name
19+ self .pipelines : List [Pipeline ] = []
2220
2321 def load_plugins (self , base_path : str ):
24- """Load all plugins from plugins.yaml configuration file."""
22+ """Load all pipelines from plugins.yaml configuration file."""
2523 config_path = Path (base_path ) / "plugins.yaml"
2624
2725 if not config_path .exists ():
@@ -32,65 +30,55 @@ def load_plugins(self, base_path: str):
3230 with open (config_path ) as f :
3331 config = yaml .safe_load (f )
3432
35- # Load parsers
36- for parser_config in config .get ("parsers" , []):
37- self ._load_parser (base_path , parser_config )
38- # Store parser -> generator mapping
39- if "generator" in parser_config :
40- self .parser_to_generator [parser_config ["name" ]] = parser_config ["generator" ]
41-
42- # Load generators
43- for generator_config in config .get ("generators" , []):
44- self ._load_generator (base_path , generator_config )
33+ # Load pipelines
34+ for pipeline_config in config .get ("pipelines" , []):
35+ pipeline = self ._load_pipeline (base_path , pipeline_config )
36+ if pipeline :
37+ self .pipelines .append (pipeline )
38+ print (f"✓ Loaded pipeline: { pipeline .name } - { pipeline .description } " )
4539
4640 except Exception as e :
4741 print (f"✗ Failed to load plugin configuration: { e } " )
4842
49- def _load_parser (self , base_path : str , config : dict ):
50- """Load a specific parser from configuration."""
51- try :
52- module_path = Path (base_path ) / "parsers" / f"{ config ['module' ]} .py"
53- spec = importlib .util .spec_from_file_location (
54- f"parsers.{ config ['module' ]} " , module_path
55- )
56- module = importlib .util .module_from_spec (spec )
57- spec .loader .exec_module (module )
58-
59- # Get the specified class
60- parser_class = getattr (module , config ["class" ])
61- parser = parser_class ()
62- self .parsers [parser .name ] = parser
63- print (f"✓ Loaded parser: { parser .name } ({ config ['description' ]} )" )
64-
65- except Exception as e :
66- print (f"✗ Failed to load parser { config ['name' ]} : { e } " )
67-
68- def _load_generator (self , base_path : str , config : dict ):
69- """Load a specific generator from configuration."""
43+ def _load_pipeline (self , base_path : str , config : dict ) -> Pipeline :
44+ """Load a single parser-generator pipeline."""
7045 try :
71- module_path = Path (base_path ) / "generators" / f"{ config ['module' ]} .py"
72- spec = importlib .util .spec_from_file_location (
73- f"generators.{ config ['module' ]} " , module_path
46+ # Load parser
47+ parser_config = config ["parser" ]
48+ parser = self ._load_parser (base_path , parser_config )
49+
50+ # Load generator
51+ generator_config = config ["generator" ]
52+ generator = self ._load_generator (base_path , generator_config )
53+
54+ # Create pipeline
55+ return Pipeline (
56+ name = config ["name" ],
57+ description = config ["description" ],
58+ parser = parser ,
59+ generator = generator ,
7460 )
75- module = importlib .util .module_from_spec (spec )
76- spec .loader .exec_module (module )
77-
78- # Get the specified class
79- generator_class = getattr (module , config ["class" ])
80- generator = generator_class ()
81- self .generators [generator .name ] = generator
82- print (f"✓ Loaded generator: { generator .name } ({ config ['description' ]} )" )
8361
8462 except Exception as e :
85- print (f"✗ Failed to load generator { config ['name' ]} : { e } " )
86-
87- def get_parser_for_file (self , file_path : str ) -> Optional [InputParser ]:
88- """Get appropriate parser for a file."""
89- for parser in self .parsers .values ():
90- if parser .can_parse (file_path ):
91- return parser
92- return None
93-
94- def get_generator (self , name : str ) -> Optional [OutputGenerator ]:
95- """Get generator by name."""
96- return self .generators .get (name )
63+ print (f"✗ Failed to load pipeline { config .get ('name' , 'unknown' )} : { e } " )
64+ return None
65+
66+ def _load_parser (self , base_path : str , config : dict ) -> InputParser :
67+ """Load a parser from configuration."""
68+ module_path = Path (base_path ) / "parsers" / f"{ config ['module' ]} .py"
69+ spec = importlib .util .spec_from_file_location (f"parsers.{ config ['module' ]} " , module_path )
70+ module = importlib .util .module_from_spec (spec )
71+ spec .loader .exec_module (module )
72+
73+ parser_class = getattr (module , config ["class" ])
74+ return parser_class ()
75+
76+ def _load_generator (self , base_path : str , config : dict ) -> OutputGenerator :
77+ """Load a generator from configuration."""
78+ module_path = Path (base_path ) / "generators" / f"{ config ['module' ]} .py"
79+ spec = importlib .util .spec_from_file_location (f"generators.{ config ['module' ]} " , module_path )
80+ module = importlib .util .module_from_spec (spec )
81+ spec .loader .exec_module (module )
82+
83+ generator_class = getattr (module , config ["class" ])
84+ return generator_class ()
0 commit comments