1313plugins = InstalledSigmaPlugins .autodiscover ()
1414
1515
16+ def _plugin_id_from_module (module_name : str , namespace : str ) -> str :
17+ """Extract the Sigma plugin identifier from a module name.
18+
19+ Sigma backends live in ``sigma.backends.<plugin_id>.*`` and pipelines in
20+ ``sigma.pipelines.<plugin_id>.*``. Splitting on '.' and picking the
21+ component after the namespace prefix returns the plugin identifier directly
22+ (e.g. ``sigma.backends.splunk.backend`` → ``splunk``).
23+ """
24+ parts = module_name .split ("." )
25+ # Expected layout: sigma . <namespace> . <plugin_id> [. submodule ...]
26+ try :
27+ idx = parts .index (namespace )
28+ plugin_id = parts [idx + 1 ]
29+ return plugin_id if plugin_id else "n/a"
30+ except (ValueError , IndexError ):
31+ return "n/a"
32+
33+
34+ def _get_backend_plugin_id (backend_class ) -> str :
35+ """Return the Sigma plugin identifier for a backend class."""
36+ return _plugin_id_from_module (backend_class .__module__ , "backends" )
37+
38+
39+ def _get_pipeline_plugin_id (pipeline_obj ) -> str :
40+ """Return the Sigma plugin identifier for a pipeline object or function."""
41+ # Plain function: use its own module
42+ module_name = getattr (pipeline_obj , "__module__" , None )
43+ if module_name and module_name != "sigma.pipelines.base" :
44+ return _plugin_id_from_module (module_name , "pipelines" )
45+ # Pipeline-decorator instance: retrieve the wrapped function's module
46+ func = getattr (pipeline_obj , "func" , None )
47+ if func is not None :
48+ func_module = getattr (func , "__module__" , None )
49+ if func_module :
50+ return _plugin_id_from_module (func_module , "pipelines" )
51+ return "n/a"
52+
53+
54+ # Pre-compute plugin IDs for all discovered pipelines (keyed by identifier).
55+ # This must be done before the resolver resolves pipeline callables into plain
56+ # ProcessingPipeline objects, which no longer carry module information.
57+ _pipeline_plugin_ids : dict = {
58+ name : _get_pipeline_plugin_id (pipeline )
59+ for name , pipeline in plugins .pipelines .items ()
60+ }
61+
62+
1663@click .group (name = "list" , help = "List available targets or processing pipelines." )
1764def list_group ():
1865 pass
@@ -32,13 +79,15 @@ def list_targets():
3279 "Identifier" ,
3380 "Target Query Language" ,
3481 "Processing Pipeline Required" ,
82+ "Plugin" ,
3583 )
3684 table .add_rows (
3785 [
3886 (
3987 name ,
4088 fill (backend .name , width = 60 ),
4189 "Yes" if backend .requires_pipeline else "No" ,
90+ _get_backend_plugin_id (backend ),
4291 )
4392 for name , backend in plugins .backends .items ()
4493 ]
@@ -108,6 +157,7 @@ def list_pipelines(backend):
108157 "Priority" ,
109158 "Processing Pipeline" ,
110159 "Backends" ,
160+ "Plugin" ,
111161 )
112162 for name , pipeline in pipelines :
113163 if (
@@ -120,7 +170,13 @@ def list_pipelines(backend):
120170 else :
121171 backends = "all"
122172 table .add_row (
123- (name , pipeline .priority , fill (pipeline .name , width = 60 ), backends )
173+ (
174+ name ,
175+ pipeline .priority ,
176+ fill (pipeline .name , width = 60 ),
177+ backends ,
178+ _pipeline_plugin_ids .get (name , "n/a" ),
179+ )
124180 )
125181 table .align = "l"
126182 click .echo (table .get_string ())
0 commit comments