@@ -24,15 +24,20 @@ def __repr__(self):
2424 """This a default __repr__ method for the singleton."""
2525 def __getattribute__ (self , name ):
2626 """The __getattribute__ method is expanded to implement the singleton."""
27+ def delete (cls ):
28+ """The delete() method removes the singleton and invalidates any existing instances,
29+ allowing to create a new instance the next time the class is instantiated. This is
30+ useful for resetting the singleton to its default values.
31+ """
2732 def get_self (cls , ** kwargs ):
2833 """The get_self(**kwargs) method returns the singleton instance, allowing to pass
2934 any kwargs to the constructor, even if they are not attributes of the singleton.
3035 This is useful for kwargs filtering in getters or specific functions.
3136 """
32- def delete (cls ):
33- """The delete( ) method removes the singleton and invalidates any existing instances,
34- allowing to create a new instance the next time the class is instantiated. This is
35- useful for resetting the singleton to its default values .
37+ def filter_kwargs (cls , ** kwargs ):
38+ """The filter_kwargs(**kwargs ) method splits the kwargs into non-class kwargs and
39+ class kwargs. This is useful after a call to `get_self(**kwargs)` to only keep the
40+ kwargs that are not attributes of the singleton .
3641 """
3742
3843
@@ -191,21 +196,34 @@ def delete(this_cls):
191196 @classmethod
192197 @functools .wraps (Singleton .get_self )
193198 def get_self (this_cls , ** kwargs ):
199+ _ , filtered_kwargs = this_cls .filter_kwargs (** kwargs )
200+ if '_singleton_instance' not in this_cls .__dict__ :
201+ self = this_cls ()
202+ else :
203+ self = this_cls ._singleton_instance
204+ for kk , vv in filtered_kwargs .items ():
205+ setattr (self , kk , vv )
206+ return self
207+
208+ @classmethod
209+ @functools .wraps (Singleton .filter_kwargs )
210+ def filter_kwargs (this_cls , ** kwargs ):
194211 # Need to initialise in case the instance does not yet exist
195212 # (to recognise the allowed fields)
196213 if '_singleton_instance' not in this_cls .__dict__ :
197214 self = this_cls ()
198215 else :
199216 self = this_cls ._singleton_instance
200- filtered_kwargs = {key : value for key , value in kwargs .items ()
217+ cls_kwargs = {key : value for key , value in kwargs .items ()
201218 if hasattr (this_cls , key ) \
202219 or hasattr (this_cls ._singleton_instance , key )}
203220 if not allow_underscore_vars_in_init :
204- filtered_kwargs = {key : value for key , value in filtered_kwargs .items ()
221+ cls_kwargs = {key : value for key , value in cls_kwargs .items ()
205222 if not key .startswith ('_' )}
206- for kk , vv in filtered_kwargs .items ():
207- setattr (self , kk , vv )
208- return self
223+ non_cls_kwargs = kwargs .copy ()
224+ for kk in cls_kwargs .keys ():
225+ non_cls_kwargs .pop (kk )
226+ return non_cls_kwargs , cls_kwargs
209227
210228 # Rename the original class, for clarity in the __mro__ etc
211229 cls .__name__ = f"{ cls .__name__ } Original"
@@ -253,4 +271,4 @@ def _get_cls_functions(cls):
253271 else Singleton .__init_subclass__
254272 wrap_getattribute = cls .__getattribute__ if cls .__dict__ .get ('__getattribute__' ) \
255273 is not None else Singleton .__getattribute__
256- return wrap_new , wrap_init , wrap_init_subclass , wrap_getattribute
274+ return wrap_new , wrap_init , wrap_init_subclass , wrap_getattribute
0 commit comments