@@ -279,6 +279,26 @@ def uninstall_nbextension(dest, require=None, user=False, sys_prefix=False, pref
279
279
cm .update (section , {"load_extensions" : {require : None }})
280
280
281
281
282
+ def _find_uninstall_nbextension (filename , logger = None ):
283
+ """Remove nbextension files from the first location they are found.
284
+
285
+ Returns True if files were removed, False otherwise.
286
+ """
287
+ filename = cast_unicode_py2 (filename )
288
+ for nbext in jupyter_path ('nbextensions' ):
289
+ path = pjoin (nbext , filename )
290
+ if os .path .lexists (path ):
291
+ if logger :
292
+ logger .info ("Removing: %s" % path )
293
+ if os .path .isdir (path ) and not os .path .islink (path ):
294
+ shutil .rmtree (path )
295
+ else :
296
+ os .remove (path )
297
+ return True
298
+
299
+ return False
300
+
301
+
282
302
def uninstall_nbextension_python (module ,
283
303
user = False , sys_prefix = False , prefix = None , nbextensions_dir = None ,
284
304
logger = None ):
@@ -420,6 +440,24 @@ def disable_nbextension(section, require, user=True, sys_prefix=False,
420
440
logger = logger )
421
441
422
442
443
+ def _find_disable_nbextension (section , require , logger = None ):
444
+ """Disable an nbextension from the first config location where it is enabled.
445
+
446
+ Returns True if it changed any config, False otherwise.
447
+ """
448
+ for config_dir in jupyter_config_path ():
449
+ cm = BaseJSONConfigManager (
450
+ config_dir = os .path .join (config_dir , 'nbconfig' ))
451
+ d = cm .get (section )
452
+ if d .get ('load_extensions' , {}).get (require , None ):
453
+ if logger :
454
+ logger .info ("Disabling %s extension in %s" , require , config_dir )
455
+ cm .update (section , {'load_extensions' : {require : None }})
456
+ return True
457
+
458
+ return False
459
+
460
+
423
461
def enable_nbextension_python (module , user = True , sys_prefix = False ,
424
462
logger = None ):
425
463
"""Enable some nbextensions associated with a Python module.
@@ -689,8 +727,20 @@ class UninstallNBExtensionApp(BaseExtensionApp):
689
727
690
728
jupyter nbextension uninstall path/url path/url/entrypoint
691
729
jupyter nbextension uninstall --py pythonPackageName
692
-
693
- This uninstalls an nbextension.
730
+
731
+ This uninstalls an nbextension. By default, it uninstalls from the
732
+ first directory on the search path where it finds the extension, but you can
733
+ uninstall from a specific location using the --user, --sys-prefix or
734
+ --system flags, or the --prefix option.
735
+
736
+ If you specify the --require option, the named extension will be disabled,
737
+ e.g.::
738
+
739
+ jupyter nbextension uninstall myext --require myext/main
740
+
741
+ If you use the --py or --python flag, the name should be a Python module.
742
+ It will uninstall nbextensions listed in that module, but not the module
743
+ itself (which you should uninstall using a package manager such as pip).
694
744
"""
695
745
696
746
examples = """
@@ -703,46 +753,84 @@ class UninstallNBExtensionApp(BaseExtensionApp):
703
753
"nbextensions" : "UninstallNBExtensionApp.nbextensions_dir" ,
704
754
"require" : "UninstallNBExtensionApp.require" ,
705
755
}
756
+ flags = BaseExtensionApp .flags .copy ()
757
+ flags ['system' ] = ({'UninstallNBExtensionApp' : {'system' : True }},
758
+ "Uninstall specifically from systemwide installation directory" )
706
759
707
- prefix = Unicode ('' , config = True , help = "Installation prefix" )
708
- nbextensions_dir = Unicode ('' , config = True , help = "Full path to nbextensions dir (probably use prefix or user)" )
709
- require = Unicode ('' , config = True , help = "require.js module to load." )
760
+ prefix = Unicode ('' , config = True ,
761
+ help = "Installation prefix. Overrides --user, --sys-prefix and --system"
762
+ )
763
+ nbextensions_dir = Unicode ('' , config = True ,
764
+ help = "Full path to nbextensions dir (probably use prefix or user)"
765
+ )
766
+ require = Unicode ('' , config = True , help = "require.js module to disable loading" )
767
+ system = Bool (False , config = True ,
768
+ help = "Uninstall specifically from systemwide installation directory"
769
+ )
710
770
711
771
def _config_file_name_default (self ):
712
772
"""The default config file name."""
713
773
return 'jupyter_notebook_config'
714
-
715
- def uninstall_extensions (self ):
716
- """Uninstall some nbextensions """
774
+
775
+ def uninstall_extension (self ):
776
+ """Uninstall an nbextension from a specific location """
717
777
kwargs = {
718
778
'user' : self .user ,
719
779
'sys_prefix' : self .sys_prefix ,
720
780
'prefix' : self .prefix ,
721
781
'nbextensions_dir' : self .nbextensions_dir ,
722
782
'logger' : self .log
723
783
}
724
-
725
- arg_count = 1
726
- if len (self .extra_args ) > arg_count :
727
- raise ValueError ("only one nbextension allowed at a time. Call multiple times to uninstall multiple extensions." )
728
- if len (self .extra_args ) < arg_count :
729
- raise ValueError ("not enough arguments" )
730
-
784
+
731
785
if self .python :
732
786
uninstall_nbextension_python (self .extra_args [0 ], ** kwargs )
733
787
else :
734
788
if self .require :
735
789
kwargs ['require' ] = self .require
736
790
uninstall_nbextension (self .extra_args [0 ], ** kwargs )
737
-
791
+
792
+ def find_uninstall_extension (self ):
793
+ """Uninstall an nbextension from an unspecified location"""
794
+ name = self .extra_args [0 ]
795
+ if self .python :
796
+ _ , nbexts = _get_nbextension_metadata (name )
797
+ changed = False
798
+ for nbext in nbexts :
799
+ if _find_uninstall_nbextension (nbext ['dest' ], logger = self .log ):
800
+ changed = True
801
+
802
+ # Also disable it in config.
803
+ for section in NBCONFIG_SECTIONS :
804
+ _find_disable_nbextension (section , nbext ['require' ],
805
+ logger = self .log )
806
+
807
+ else :
808
+ changed = _find_uninstall_nbextension (name , logger = self .log )
809
+
810
+ if not changed :
811
+ print ("No installed extension %r found." % name )
812
+
813
+ if self .require :
814
+ for section in NBCONFIG_SECTIONS :
815
+ _find_disable_nbextension (section , self .require ,
816
+ logger = self .log )
817
+
738
818
def start (self ):
739
819
if not self .extra_args :
740
820
sys .exit ('Please specify an nbextension to uninstall' )
741
- else :
821
+ elif len (self .extra_args ) > 1 :
822
+ sys .exit ("Only one nbextension allowed at a time. "
823
+ "Call multiple times to uninstall multiple extensions." )
824
+ elif (self .user or self .sys_prefix or self .system or self .prefix
825
+ or self .nbextensions_dir ):
826
+ # The user has specified a location from which to uninstall.
742
827
try :
743
- self .uninstall_extensions ()
828
+ self .uninstall_extension ()
744
829
except ArgumentConflict as e :
745
830
sys .exit (str (e ))
831
+ else :
832
+ # Uninstall wherever it is.
833
+ self .find_uninstall_extension ()
746
834
747
835
748
836
class ToggleNBExtensionApp (BaseExtensionApp ):
@@ -826,7 +914,7 @@ class DisableNBExtensionApp(ToggleNBExtensionApp):
826
914
"""An App that disables nbextensions"""
827
915
name = "jupyter nbextension disable"
828
916
description = """
829
- Enable an nbextension in frontend configuration.
917
+ Disable an nbextension in frontend configuration.
830
918
831
919
Usage
832
920
jupyter nbextension disable [--system|--sys-prefix]
0 commit comments