11import importlib
22
3- from traitlets .config import LoggingConfigurable , Config
3+ from traitlets .config import LoggingConfigurable
44
55from traitlets import (
66 HasTraits ,
77 Dict ,
88 Unicode ,
99 Bool ,
1010 Any ,
11- validate
11+ Instance ,
12+ default ,
13+ observe ,
14+ validate ,
1215)
1316
17+ from .config import ExtensionConfigManager
1418from .utils import (
1519 ExtensionMetadataError ,
1620 ExtensionModuleNotFound ,
@@ -240,35 +244,44 @@ class ExtensionManager(LoggingConfigurable):
240244 linking, loading, and managing Jupyter Server extensions.
241245
242246 Usage:
243- m = ExtensionManager(jpserver_extensions=extensions )
247+ m = ExtensionManager(config_manager=... )
244248 """
245- def __init__ (self , config_manager = None , * args , ** kwargs ):
246- super ().__init__ (* args , ** kwargs )
247- # The `enabled_extensions` attribute provides a dictionary
248- # with extension (package) names mapped to their ExtensionPackage interface
249- # (see above). This manager simplifies the interaction between the
250- # ServerApp and the extensions being appended.
251- self ._extensions = {}
252- # The `_linked_extensions` attribute tracks when each extension
253- # has been successfully linked to a ServerApp. This helps prevent
254- # extensions from being re-linked recursively unintentionally if another
255- # extension attempts to link extensions again.
256- self ._linked_extensions = {}
257- self ._config_manager = config_manager
258- if self ._config_manager :
259- self .from_config_manager (self ._config_manager )
260249
261- @property
262- def config_manager (self ):
263- return self ._config_manager
250+ config_manager = Instance (ExtensionConfigManager , allow_none = True )
251+
252+ @default ("config_manager" )
253+ def _load_default_config_manager (self ):
254+ config_manager = ExtensionConfigManager ()
255+ self ._load_config_manager (config_manager )
256+ return config_manager
257+
258+ @observe ("config_manager" )
259+ def _config_manager_changed (self , change ):
260+ if change .new :
261+ self ._load_config_manager (change .new )
262+
263+ # The `extensions` attribute provides a dictionary
264+ # with extension (package) names mapped to their ExtensionPackage interface
265+ # (see above). This manager simplifies the interaction between the
266+ # ServerApp and the extensions being appended.
267+ extensions = Dict (
268+ help = """
269+ Dictionary with extension package names as keys
270+ and ExtensionPackage objects as values.
271+ """
272+ )
264273
265- @property
266- def extensions (self ):
267- """Dictionary with extension package names as keys
268- and an ExtensionPackage objects as values.
274+ # The `_linked_extensions` attribute tracks when each extension
275+ # has been successfully linked to a ServerApp. This helps prevent
276+ # extensions from being re-linked recursively unintentionally if another
277+ # extension attempts to link extensions again.
278+ linked_extensions = Dict (
279+ help = """
280+ Dictionary with extension names as keys
281+
282+ values are True if the extension is linked, False if not.
269283 """
270- # Sort enabled extensions before
271- return self ._extensions
284+ )
272285
273286 @property
274287 def extension_points (self ):
@@ -279,16 +292,14 @@ def extension_points(self):
279292 for name , point in value .extension_points .items ()
280293 }
281294
282- @property
283- def linked_extensions (self ):
284- """Dictionary with extension names as keys; values are
285- True if the extension is linked, False if not."""
286- return self ._linked_extensions
287-
288295 def from_config_manager (self , config_manager ):
289296 """Add extensions found by an ExtensionConfigManager"""
290- self ._config_manager = config_manager
291- jpserver_extensions = self ._config_manager .get_jpserver_extensions ()
297+ # load triggered via config_manager trait observer
298+ self .config_manager = config_manager
299+
300+ def _load_config_manager (self , config_manager ):
301+ """Actually load our config manager"""
302+ jpserver_extensions = config_manager .get_jpserver_extensions ()
292303 self .from_jpserver_extensions (jpserver_extensions )
293304
294305 def from_jpserver_extensions (self , jpserver_extensions ):
@@ -302,21 +313,21 @@ def add_extension(self, extension_name, enabled=False):
302313 """
303314 try :
304315 extpkg = ExtensionPackage (name = extension_name , enabled = enabled )
305- self ._extensions [extension_name ] = extpkg
316+ self .extensions [extension_name ] = extpkg
306317 return True
307318 # Raise a warning if the extension cannot be loaded.
308319 except Exception as e :
309320 self .log .warning (e )
310321 return False
311322
312323 def link_extension (self , name , serverapp ):
313- linked = self ._linked_extensions .get (name , False )
324+ linked = self .linked_extensions .get (name , False )
314325 extension = self .extensions [name ]
315326 if not linked and extension .enabled :
316327 try :
317328 # Link extension and store links
318329 extension .link_all_points (serverapp )
319- self ._linked_extensions [name ] = True
330+ self .linked_extensions [name ] = True
320331 self .log .info ("{name} | extension was successfully linked." .format (name = name ))
321332 except Exception as e :
322333 self .log .warning (e )
0 commit comments