@@ -119,6 +119,16 @@ def _checkpoints_class_default(self):
119
119
deleting files really deletes them.""" ,
120
120
)
121
121
122
+ always_delete_dir = Bool (
123
+ False ,
124
+ config = True ,
125
+ help = """If True, deleting non-empty directory will always be allowed.
126
+ WARNING this may result in files being definitely removed; e.g. on Windows
127
+ if the data size is too big for the trash/recycle bin they will be really
128
+ deleted. If False (default), non-empty directory will be send to trash only
129
+ if safe. And if ``delete_to_trash`` is True, they won't be deleted.""" ,
130
+ )
131
+
122
132
@default ("files_handler_class" )
123
133
def _files_handler_class_default (self ):
124
134
return AuthenticatedFileHandler
@@ -331,7 +341,10 @@ def _file_model(self, path, content=True, format=None):
331
341
if content :
332
342
content , format = self ._read_file (os_path , format )
333
343
if model ["mimetype" ] is None :
334
- default_mime = {"text" : "text/plain" , "base64" : "application/octet-stream" }[format ]
344
+ default_mime = {
345
+ "text" : "text/plain" ,
346
+ "base64" : "application/octet-stream" ,
347
+ }[format ]
335
348
model ["mimetype" ] = default_mime
336
349
337
350
model .update (
@@ -391,7 +404,9 @@ def get(self, path, content=True, type=None, format=None):
391
404
if os .path .isdir (os_path ):
392
405
if type not in (None , "directory" ):
393
406
raise web .HTTPError (
394
- 400 , u"%s is a directory, not a %s" % (path , type ), reason = "bad type"
407
+ 400 ,
408
+ u"%s is a directory, not a %s" % (path , type ),
409
+ reason = "bad type" ,
395
410
)
396
411
model = self ._dir_model (path , content = content )
397
412
elif type == "notebook" or (type is None and path .endswith (".ipynb" )):
@@ -494,7 +509,7 @@ def is_non_empty_dir(os_path):
494
509
return False
495
510
496
511
if self .delete_to_trash :
497
- if sys .platform == "win32" and is_non_empty_dir (os_path ):
512
+ if not self . always_delete_dir and sys .platform == "win32" and is_non_empty_dir (os_path ):
498
513
# send2trash can really delete files on Windows, so disallow
499
514
# deleting non-empty files. See Github issue 3631.
500
515
raise web .HTTPError (400 , u"Directory %s not empty" % os_path )
@@ -507,12 +522,13 @@ def is_non_empty_dir(os_path):
507
522
return
508
523
else :
509
524
self .log .warning (
510
- "Skipping trash for %s, on different device " "to home directory" , os_path
525
+ "Skipping trash for %s, on different device " "to home directory" ,
526
+ os_path ,
511
527
)
512
528
513
529
if os .path .isdir (os_path ):
514
530
# Don't permanently delete non-empty directories.
515
- if is_non_empty_dir (os_path ):
531
+ if not self . always_delete_dir and is_non_empty_dir (os_path ):
516
532
raise web .HTTPError (400 , u"Directory %s not empty" % os_path )
517
533
self .log .debug ("Removing directory %s" , os_path )
518
534
with self .perm_to_403 ():
@@ -649,7 +665,10 @@ async def _file_model(self, path, content=True, format=None):
649
665
if content :
650
666
content , format = await self ._read_file (os_path , format )
651
667
if model ["mimetype" ] is None :
652
- default_mime = {"text" : "text/plain" , "base64" : "application/octet-stream" }[format ]
668
+ default_mime = {
669
+ "text" : "text/plain" ,
670
+ "base64" : "application/octet-stream" ,
671
+ }[format ]
653
672
model ["mimetype" ] = default_mime
654
673
655
674
model .update (
@@ -709,7 +728,9 @@ async def get(self, path, content=True, type=None, format=None):
709
728
if os .path .isdir (os_path ):
710
729
if type not in (None , "directory" ):
711
730
raise web .HTTPError (
712
- 400 , u"%s is a directory, not a %s" % (path , type ), reason = "bad type"
731
+ 400 ,
732
+ u"%s is a directory, not a %s" % (path , type ),
733
+ reason = "bad type" ,
713
734
)
714
735
model = await self ._dir_model (path , content = content )
715
736
elif type == "notebook" or (type is None and path .endswith (".ipynb" )):
@@ -813,7 +834,11 @@ async def is_non_empty_dir(os_path):
813
834
return False
814
835
815
836
if self .delete_to_trash :
816
- if sys .platform == "win32" and await is_non_empty_dir (os_path ):
837
+ if (
838
+ not self .always_delete_dir
839
+ and sys .platform == "win32"
840
+ and await is_non_empty_dir (os_path )
841
+ ):
817
842
# send2trash can really delete files on Windows, so disallow
818
843
# deleting non-empty files. See Github issue 3631.
819
844
raise web .HTTPError (400 , u"Directory %s not empty" % os_path )
@@ -826,12 +851,13 @@ async def is_non_empty_dir(os_path):
826
851
return
827
852
else :
828
853
self .log .warning (
829
- "Skipping trash for %s, on different device " "to home directory" , os_path
854
+ "Skipping trash for %s, on different device " "to home directory" ,
855
+ os_path ,
830
856
)
831
857
832
858
if os .path .isdir (os_path ):
833
859
# Don't permanently delete non-empty directories.
834
- if await is_non_empty_dir (os_path ):
860
+ if not self . always_delete_dir and await is_non_empty_dir (os_path ):
835
861
raise web .HTTPError (400 , u"Directory %s not empty" % os_path )
836
862
self .log .debug ("Removing directory %s" , os_path )
837
863
with self .perm_to_403 ():
0 commit comments