44from collections .abc import Callable
55from contextlib import ContextDecorator
66from copy import deepcopy
7+ from datetime import datetime
78from enum import Enum
89from types import TracebackType
910from typing import Any , Final , Protocol
@@ -139,6 +140,7 @@ def __init__(
139140 self ,
140141 module_name : str ,
141142 * ,
143+ logger : logging .Logger ,
142144 category : ModuleCategory | None = None ,
143145 depends : list [str ] | None = None ,
144146 ) -> None :
@@ -151,20 +153,21 @@ def __init__(
151153 self .module_name = module_name
152154 self .category = category
153155 self .depends = depends
154- self .started = None
156+ self .started : datetime | None = None
155157 self .head_msg = f"Setup of { module_name } "
158+ self .logger = logger
156159
157160 def __enter__ (self ) -> None :
158- self .started = arrow .utcnow ()
161+ self .started = arrow .utcnow (). datetime
159162 if self .category is not None :
160- _logger .info (
163+ self . logger .info (
161164 "%s (%s, %s) started ... " ,
162165 self .head_msg ,
163166 f"{ self .category .name = } " ,
164167 f"{ self .depends } " ,
165168 )
166169 else :
167- _logger .info ("%s started ..." , self .head_msg )
170+ self . logger .info ("%s started ..." , self .head_msg )
168171
169172 def __exit__ (
170173 self ,
@@ -187,14 +190,14 @@ def is_setup_completed(module_name: str, app: web.Application) -> bool:
187190def ensure_single_setup (
188191 module_name : str ,
189192 * ,
190- logger : logging .Logger = _logger ,
193+ logger : logging .Logger ,
191194) -> Callable [[Callable [..., Any ]], Callable [..., Any ]]:
192195 """Ensures a setup function is executed only once per application and handles completion.
193196
194197 :param module_name: Name of the module being set up
195198 """
196199
197- def _skip_setup (reason : str ) -> bool :
200+ def _log_skip (reason : str ) -> bool :
198201 logger .info ("Skipping '%s' setup: %s" , module_name , reason )
199202 return False
200203
@@ -205,26 +208,34 @@ def _wrapper(app: web.Application, *args: Any, **kwargs: Any) -> bool:
205208
206209 # pre-setup init
207210 if APP_SETUP_COMPLETED_KEY not in app :
208- app [APP_SETUP_COMPLETED_KEY ] = {}
211+ app [APP_SETUP_COMPLETED_KEY ] = []
209212
210213 # check
211214 if is_setup_completed (module_name , app ):
212- return _skip_setup (
215+ _log_skip (
213216 f"'{ module_name } ' was already initialized in { app } ."
214217 " Setup can only be executed once per app."
215218 )
219+ return False
216220
217- completed = setup_func (app , * args , ** kwargs )
221+ try :
222+ completed = setup_func (app , * args , ** kwargs )
218223
219- # post-setup handling
220- if completed is None :
221- completed = True
224+ # post-setup handling
225+ if completed is None :
226+ completed = True
222227
223- if completed : # registers completed setup
224- app [APP_SETUP_COMPLETED_KEY ].add (module_name )
225- return completed
228+ if completed : # registers completed setup
229+ app [APP_SETUP_COMPLETED_KEY ].append (module_name )
230+ return completed
226231
227- return _skip_setup ("Undefined (setup function returned false)" )
232+ assert not completed # nosec
233+ _log_skip ("Undefined (setup function returned false)" )
234+ return False
235+
236+ except SkipModuleSetupError as err :
237+ _log_skip (err .reason )
238+ return False
228239
229240 return _wrapper
230241
@@ -296,7 +307,10 @@ def decorator(setup_func: _SetupFunc) -> _SetupFunc:
296307 ), f"Rename '{ setup_func .__name__ } ' start with 'setup_$(plugin-name)'"
297308
298309 @functools .wraps (setup_func )
299- @_SetupTimingContext (module_name , category = category , depends = depends )
310+ @_SetupTimingContext (
311+ module_name , category = category , depends = depends , logger = logger
312+ )
313+ @ensure_single_setup (module_name , logger = logger )
300314 def _wrapper (app : web .Application , * args , ** kargs ) -> bool :
301315 if category == ModuleCategory .ADDON :
302316 # ONLY addons can be enabled/disabled
@@ -345,9 +359,7 @@ def _wrapper(app: web.Application, *args, **kargs) -> bool:
345359 raise DependencyError (msg )
346360
347361 # execution of setup with module name
348- completed : bool = ensure_single_setup (module_name , logger = logger )(
349- setup_func
350- )(app , * args , ** kargs )
362+ completed : bool = setup_func (app , * args , ** kargs )
351363
352364 return completed
353365
0 commit comments