11from __future__ import annotations
2- from collections .abc import Sequence
2+ from collections .abc import Iterable , Iterator
33from dataclasses import dataclass
44from types import ModuleType
5- from typing import Generic , TypeVar , overload
5+ from typing import Generic , TypeVar
66import importlib
77import logging
88import pkgutil
1515 UpscalingStrategy ,
1616)
1717from .object import ObjectFileReader , ObjectFileWriter
18- from .observer import Observable
18+ from .observer import Observable , Observer
19+ from .parametric import StringParameter
1920from .patterns import DiffractionFileReader , DiffractionFileWriter
2021from .probe import FresnelZonePlate , ProbeFileReader , ProbeFileWriter
2122from .product import ProductFileReader , ProductFileWriter
3334
3435
3536@dataclass (frozen = True )
36- class PluginEntry (Generic [T ]):
37+ class Plugin (Generic [T ]):
3738 strategy : T
38- simpleName : str
39- displayName : str
39+ simple_name : str
40+ display_name : str
4041
4142
42- class PluginChooser (Sequence [ PluginEntry [T ]], Observable ):
43+ class PluginChooser (Iterable [ Plugin [T ]], Observable , Observer ):
4344 def __init__ (self ) -> None :
4445 super ().__init__ ()
45- self ._entryList : list [PluginEntry [T ]] = list ()
46- self ._currentIndex = 0
46+ self ._registered_plugins : list [Plugin [T ]] = list ()
47+ self ._current_index = 0
48+ self ._parameter : StringParameter | None = None
4749
48- def getSimpleNameList (self ) -> Sequence [str ]:
49- return [entry .simpleName for entry in self ._entryList ]
50+ def register_plugin (self , strategy : T , * , display_name : str , simple_name : str = '' ) -> None :
51+ if not simple_name :
52+ simple_name = re .sub (r'\W+' , '' , display_name )
5053
51- def getDisplayNameList (self ) -> Sequence [str ]:
52- return [entry .displayName for entry in self ._entryList ]
53-
54- def registerPlugin (self , strategy : T , * , displayName : str , simpleName : str = '' ) -> None :
55- if not simpleName :
56- simpleName = re .sub (r'\W+' , '' , displayName )
57-
58- entry = PluginEntry [T ](strategy , simpleName , displayName )
59- self ._entryList .append (entry )
54+ plugin = Plugin [T ](strategy , simple_name , display_name )
55+ self ._registered_plugins .append (plugin )
6056 self .notifyObservers ()
6157
62- @property
63- def currentPlugin (self ) -> PluginEntry [T ]:
64- return self ._entryList [self ._currentIndex ]
58+ def get_current_plugin (self ) -> Plugin [T ]:
59+ return self ._registered_plugins [self ._current_index ]
6560
66- def setCurrentPluginByName (self , name : str ) -> None :
61+ def set_current_plugin (self , name : str ) -> None :
6762 namecf = name .casefold ()
6863
69- for index , entry in enumerate (self ._entryList ):
70- if namecf == entry .simpleName .casefold () or namecf == entry .displayName .casefold ():
71- if self ._currentIndex != index :
72- self ._currentIndex = index
64+ for index , plugin in enumerate (self ._registered_plugins ):
65+ if namecf == plugin .simple_name .casefold () or namecf == plugin .display_name .casefold ():
66+ if self ._current_index != index :
67+ self ._current_index = index
68+
69+ if self ._parameter is not None :
70+ self ._parameter .setValue (self .get_current_plugin ().simple_name )
71+
7372 self .notifyObservers ()
7473
7574 return
7675
7776 logger .debug (f'Invalid plugin name "{ name } "' )
7877
79- @overload
80- def __getitem__ (self , index : int ) -> PluginEntry [T ]: ...
81-
82- @overload
83- def __getitem__ (self , index : slice ) -> Sequence [PluginEntry [T ]]: ...
84-
85- def __getitem__ (self , index : int | slice ) -> PluginEntry [T ] | Sequence [PluginEntry [T ]]:
86- return self ._entryList [index ]
78+ def synchronize_with_parameter (self , parameter : StringParameter ) -> None :
79+ self ._parameter = parameter
80+ self .set_current_plugin (parameter .getValue ())
81+ self ._parameter .addObserver (self )
8782
88- def __len__ (self ) -> int :
89- return len (self ._entryList )
83+ def __iter__ (self ) -> Iterator [Plugin [T ]]:
84+ for plugin in self ._registered_plugins :
85+ yield plugin
9086
9187 def __bool__ (self ) -> bool :
92- return bool (self ._entryList )
88+ return bool (self ._registered_plugins )
9389
94- def copy (self ) -> PluginChooser [T ]:
95- clone = PluginChooser [T ]()
96- clone ._entryList = self ._entryList .copy ()
97- clone ._currentIndex = self ._currentIndex
98- return clone
90+ def update (self , observable : Observable ) -> None :
91+ if self ._parameter is not None and observable is self ._parameter :
92+ self .set_current_plugin (self ._parameter .getValue ())
9993
10094
10195class PluginRegistry :
@@ -118,7 +112,7 @@ def __init__(self) -> None:
118112 self .deconvolutionStrategies = PluginChooser [DeconvolutionStrategy ]()
119113
120114 @classmethod
121- def loadPlugins (cls ) -> PluginRegistry :
115+ def load_plugins (cls ) -> PluginRegistry :
122116 registry = cls ()
123117
124118 import ptychodus .plugins
@@ -137,6 +131,6 @@ def loadPlugins(cls) -> PluginRegistry:
137131 logger .warning (exc )
138132 else :
139133 logger .info (f'Registering { moduleInfo .name } ' )
140- module .registerPlugins (registry )
134+ module .register_plugins (registry )
141135
142136 return registry
0 commit comments