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 ,
@@ -129,6 +133,8 @@ def validate(self):
129133 self ._get_loader ()
130134 except Exception :
131135 return False
136+ else :
137+ return True
132138
133139 def link (self , serverapp ):
134140 """Link the extension to a Jupyter ServerApp object.
@@ -238,35 +244,44 @@ class ExtensionManager(LoggingConfigurable):
238244 linking, loading, and managing Jupyter Server extensions.
239245
240246 Usage:
241- m = ExtensionManager(jpserver_extensions=extensions )
247+ m = ExtensionManager(config_manager=... )
242248 """
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 )
258249
259- @property
260- def config_manager (self ):
261- 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+ )
262273
263- @property
264- def extensions (self ):
265- """Dictionary with extension package names as keys
266- 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.
267283 """
268- # Sort enabled extensions before
269- return self ._extensions
284+ )
270285
271286 @property
272287 def extension_points (self ):
@@ -277,16 +292,14 @@ def extension_points(self):
277292 for name , point in value .extension_points .items ()
278293 }
279294
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-
286295 def from_config_manager (self , config_manager ):
287296 """Add extensions found by an ExtensionConfigManager"""
288- self ._config_manager = config_manager
289- 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 ()
290303 self .from_jpserver_extensions (jpserver_extensions )
291304
292305 def from_jpserver_extensions (self , jpserver_extensions ):
@@ -300,21 +313,21 @@ def add_extension(self, extension_name, enabled=False):
300313 """
301314 try :
302315 extpkg = ExtensionPackage (name = extension_name , enabled = enabled )
303- self ._extensions [extension_name ] = extpkg
316+ self .extensions [extension_name ] = extpkg
304317 return True
305318 # Raise a warning if the extension cannot be loaded.
306319 except Exception as e :
307320 self .log .warning (e )
308321 return False
309322
310323 def link_extension (self , name , serverapp ):
311- linked = self ._linked_extensions .get (name , False )
324+ linked = self .linked_extensions .get (name , False )
312325 extension = self .extensions [name ]
313326 if not linked and extension .enabled :
314327 try :
315328 # Link extension and store links
316329 extension .link_all_points (serverapp )
317- self ._linked_extensions [name ] = True
330+ self .linked_extensions [name ] = True
318331 self .log .info ("{name} | extension was successfully linked." .format (name = name ))
319332 except Exception as e :
320333 self .log .warning (e )
0 commit comments