@@ -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,16 @@ 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
694
740
"""
695
741
696
742
examples = """
@@ -703,46 +749,84 @@ class UninstallNBExtensionApp(BaseExtensionApp):
703
749
"nbextensions" : "UninstallNBExtensionApp.nbextensions_dir" ,
704
750
"require" : "UninstallNBExtensionApp.require" ,
705
751
}
752
+ flags = BaseExtensionApp .flags .copy ()
753
+ flags ['system' ] = ({'UninstallNBExtensionApp' : {'system' : True }},
754
+ "Uninstall specifically from systemwide installation directory" )
706
755
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." )
756
+ prefix = Unicode ('' , config = True ,
757
+ help = "Installation prefix. Overrides --user, --sys-prefix and --system"
758
+ )
759
+ nbextensions_dir = Unicode ('' , config = True ,
760
+ help = "Full path to nbextensions dir (probably use prefix or user)"
761
+ )
762
+ require = Unicode ('' , config = True , help = "require.js module to disable loading" )
763
+ system = Bool (False , config = True ,
764
+ help = "Uninstall specifically from systemwide installation directory"
765
+ )
710
766
711
767
def _config_file_name_default (self ):
712
768
"""The default config file name."""
713
769
return 'jupyter_notebook_config'
714
-
715
- def uninstall_extensions (self ):
716
- """Uninstall some nbextensions """
770
+
771
+ def uninstall_extension (self ):
772
+ """Uninstall an nbextension from a specific location """
717
773
kwargs = {
718
774
'user' : self .user ,
719
775
'sys_prefix' : self .sys_prefix ,
720
776
'prefix' : self .prefix ,
721
777
'nbextensions_dir' : self .nbextensions_dir ,
722
778
'logger' : self .log
723
779
}
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
-
780
+
731
781
if self .python :
732
782
uninstall_nbextension_python (self .extra_args [0 ], ** kwargs )
733
783
else :
734
784
if self .require :
735
785
kwargs ['require' ] = self .require
736
786
uninstall_nbextension (self .extra_args [0 ], ** kwargs )
737
-
787
+
788
+ def find_uninstall_extension (self ):
789
+ """Uninstall an nbextension from an unspecified location"""
790
+ name = self .extra_args [0 ]
791
+ if self .python :
792
+ _ , nbexts = _get_nbextension_metadata (name )
793
+ changed = False
794
+ for nbext in nbexts :
795
+ if _find_uninstall_nbextension (nbext ['dest' ], logger = self .log ):
796
+ changed = True
797
+
798
+ # Also disable it in config.
799
+ for section in NBCONFIG_SECTIONS :
800
+ _find_disable_nbextension (section , nbext ['require' ],
801
+ logger = self .log )
802
+
803
+ else :
804
+ changed = _find_uninstall_nbextension (name , logger = self .log )
805
+
806
+ if not changed :
807
+ print ("No installed extension %r found." % name )
808
+
809
+ if self .require :
810
+ for section in NBCONFIG_SECTIONS :
811
+ _find_disable_nbextension (section , self .require ,
812
+ logger = self .log )
813
+
738
814
def start (self ):
739
815
if not self .extra_args :
740
816
sys .exit ('Please specify an nbextension to uninstall' )
741
- else :
817
+ elif len (self .extra_args ) > 1 :
818
+ sys .exit ("Only one nbextension allowed at a time. "
819
+ "Call multiple times to uninstall multiple extensions." )
820
+ elif (self .user or self .sys_prefix or self .system or self .prefix
821
+ or self .nbextensions_dir ):
822
+ # The user has specified a location from which to uninstall.
742
823
try :
743
- self .uninstall_extensions ()
824
+ self .uninstall_extension ()
744
825
except ArgumentConflict as e :
745
826
sys .exit (str (e ))
827
+ else :
828
+ # Uninstall wherever it is.
829
+ self .find_uninstall_extension ()
746
830
747
831
748
832
class ToggleNBExtensionApp (BaseExtensionApp ):
0 commit comments