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 ,
@@ -238,35 +242,44 @@ class ExtensionManager(LoggingConfigurable):
238242 linking, loading, and managing Jupyter Server extensions.
239243
240244 Usage:
241- m = ExtensionManager(jpserver_extensions=extensions )
245+ m = ExtensionManager(config_manager=... )
242246 """
243- def __init__ (self , config_manager = None , * args , ** kwargs ):
244- super ().__init__ (* args , ** kwargs )
245- # The `enabled_extensions` attribute provides a dictionary
246- # with extension (package) names mapped to their ExtensionPackage interface
247- # (see above). This manager simplifies the interaction between the
248- # ServerApp and the extensions being appended.
249- self ._extensions = {}
250- # The `_linked_extensions` attribute tracks when each extension
251- # has been successfully linked to a ServerApp. This helps prevent
252- # extensions from being re-linked recursively unintentionally if another
253- # extension attempts to link extensions again.
254- self ._linked_extensions = {}
255- self ._config_manager = config_manager
256- if self ._config_manager :
257- self .from_config_manager (self ._config_manager )
258247
259- @property
260- def config_manager (self ):
261- return self ._config_manager
248+ config_manager = Instance (ExtensionConfigManager , allow_none = True )
249+
250+ @default ("config_manager" )
251+ def _load_default_config_manager (self ):
252+ config_manager = ExtensionConfigManager ()
253+ self ._load_config_manager (config_manager )
254+ return config_manager
255+
256+ @observe ("config_manager" )
257+ def _config_manager_changed (self , change ):
258+ if change .new :
259+ self ._load_config_manager (change .new )
260+
261+ # The `extensions` attribute provides a dictionary
262+ # with extension (package) names mapped to their ExtensionPackage interface
263+ # (see above). This manager simplifies the interaction between the
264+ # ServerApp and the extensions being appended.
265+ extensions = Dict (
266+ help = """
267+ Dictionary with extension package names as keys
268+ and ExtensionPackage objects as values.
269+ """
270+ )
262271
263- @property
264- def extensions (self ):
265- """Dictionary with extension package names as keys
266- and an ExtensionPackage objects as values.
272+ # The `_linked_extensions` attribute tracks when each extension
273+ # has been successfully linked to a ServerApp. This helps prevent
274+ # extensions from being re-linked recursively unintentionally if another
275+ # extension attempts to link extensions again.
276+ linked_extensions = Dict (
277+ help = """
278+ Dictionary with extension names as keys
279+
280+ values are True if the extension is linked, False if not.
267281 """
268- # Sort enabled extensions before
269- return self ._extensions
282+ )
270283
271284 @property
272285 def extension_points (self ):
@@ -277,16 +290,14 @@ def extension_points(self):
277290 for name , point in value .extension_points .items ()
278291 }
279292
280- @property
281- def linked_extensions (self ):
282- """Dictionary with extension names as keys; values are
283- True if the extension is linked, False if not."""
284- return self ._linked_extensions
285-
286293 def from_config_manager (self , config_manager ):
287294 """Add extensions found by an ExtensionConfigManager"""
288- self ._config_manager = config_manager
289- jpserver_extensions = self ._config_manager .get_jpserver_extensions ()
295+ # load triggered via config_manager trait observer
296+ self .config_manager = config_manager
297+
298+ def _load_config_manager (self , config_manager ):
299+ """Actually load our config manager"""
300+ jpserver_extensions = config_manager .get_jpserver_extensions ()
290301 self .from_jpserver_extensions (jpserver_extensions )
291302
292303 def from_jpserver_extensions (self , jpserver_extensions ):
@@ -300,21 +311,21 @@ def add_extension(self, extension_name, enabled=False):
300311 """
301312 try :
302313 extpkg = ExtensionPackage (name = extension_name , enabled = enabled )
303- self ._extensions [extension_name ] = extpkg
314+ self .extensions [extension_name ] = extpkg
304315 return True
305316 # Raise a warning if the extension cannot be loaded.
306317 except Exception as e :
307318 self .log .warning (e )
308319 return False
309320
310321 def link_extension (self , name , serverapp ):
311- linked = self ._linked_extensions .get (name , False )
322+ linked = self .linked_extensions .get (name , False )
312323 extension = self .extensions [name ]
313324 if not linked and extension .enabled :
314325 try :
315326 # Link extension and store links
316327 extension .link_all_points (serverapp )
317- self ._linked_extensions [name ] = True
328+ self .linked_extensions [name ] = True
318329 self .log .info ("{name} | extension was successfully linked." .format (name = name ))
319330 except Exception as e :
320331 self .log .warning (e )
0 commit comments