How to delete non empty folder from file pane (or what am I doing wrong!)

Problem : Unable to delete a empty folder from file manager pane.

Want: In file pane, right clik on folder, select delete, read prompt, click ok, then recursivley delete.

Main Cause: Students cloning git repositories creates hidden files and nested folders

Workaround: Opening a terminal or using cell magic rm -rf <path>

Reson unsuitible (to me):
a. Unexpected bahaviour based on modern file managers and IDE behaviours
b. Expose CLI tools (rm -rf) and concepts (hidden files) to students (important to understand, but not at the moment)

Issue seems to be fixed/configurable in JupyterHub 2, but TLJH use version 1.5. Based on research (links below), solutions include.

  1. set: c.FileContentsManager.delete_to_trash = True
  2. c.Spawner.environment = {
    ‘JUPYTERHUB_SINGLEUSER_APP’: “jupyter_server.serverapp.ServerApp”
    }

Solutions proposed (see links below) do not seem to be working for me. I have tried various combinations of both options varible, setting options using tljh_config, or creating a local config file: /opt/tljh/config/jupyterhub_config.d/local_settings.py. Also tried the CLI option suggested, but could not get jupyter.service to restart.

Any ideas on what I may be doing wrong? Can anyone suggest a solution?

Similar/Same:
JupyterHub Not allowing to delete non empty directory
Make it possible to delete a nonempty folders #835
Allow deleting non-empty directory when c.FileContentsManager.delete_to_trash = False #4916Jupyterhub-singleuser and jupyter_server
delete folder recursively in file explorer #9644

System Details:

  • TLJH on Ubuntu 18.04

  • jupyterhub --verison
    1.5.0

jupyter --version

jupyter_client   : 7.0.6
jupyter_core     : 4.11.1
jupyter_server   : 1.15.6
jupyterlab       : 3.3.4
  • jupyter labextension list
JupyterLab v3.4.4
/usr/local/share/jupyter/labextensions
        jupyterlab-drawio v0.9.0 enabled OK (python, jupyterlab-drawio)
        jupyterlab_pygments v0.2.2 enabled OK (python, jupyterlab_pygments)
        nbdime-jupyterlab v2.1.1 enabled OK
        @jupyter-server/resource-usage v0.6.1 enabled OK (python, jupyter-resource-usage)
        @jupyterlab/git v0.38.0 enabled OK (python, jupyterlab-git)
        @pyviz/jupyterlab_pyviz v2.2.0 enabled OK (python, pyviz_comms)
        @jupyter-widgets/jupyterlab-manager v3.1.1 enabled OK (python, jupyterlab_widgets)
        @bokeh/jupyter_bokeh v3.0.4 enabled OK (python, jupyter_bokeh)

Other labextensions (built into JupyterLab)
   app dir: /usr/local/share/jupyter/lab
        @g2nb/jupyterlab-theme v0.3.1 enabled OK
        @okuzen/jupyterlab-atom-one-light v0.1.0 enabled OK
        @shahinrostami/theme-purple-please v3.0.1 enabled OK
        @yeebc/jupyterlab_neon_theme v3.1.0 enabled OK
        jupyterlab-openbayes-theme v1.0.6 enabled OK
        jupyterlab-spreadsheet v0.4.1 enabled OK
        jupyterlab-tailwind-theme v3.0.3 enabled OK
        jupyterlab-theme-solarized-dark v2.1.0 enabled OK
        jupyterlab-theme-toggle v0.6.1 enabled OK

Disabled extensions:
    @jupyterlab/application-extension:logo
  • tljh-config show (reducted)
users:
  admin:
  - some-user-name
https:
  enabled: true
  letsencrypt:
    email: [email protected]
    domains:
    - example.com
auth:
  GitHubOAuthenticator:
    client_id: xxxxxxxxxxxxxxxxxxxxx
    client_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    oauth_callback_url: https://example.com/hub/oauth_callback
  type: oauthenticator.github.GitHubOAuthenticator
user_environment:
  default_app: jupyterlab
limits:
  memory: 4G
  cpu: 2
services:
  configurator:
    enabled: true
  • cat /opt/tljh/config/jupyterhub_config.d/local_settings.py
c.ResourceUseDisplay.track_cpu_percent = True
c.Spawner.environment = {
    'JUPYTERHUB_SINGLEUSER_APP': "jupyter_server.serverapp.ServerApp"
}
c.FileContentsManager.delete_to_trash = True

This setting applies to the single-user server (Jupyter server/notebook/lab), not JupyterHub, so it’ll need to be set in your user’s environment. The configuration file depends on your single-user server, for example
https://docs.jupyter.org/en/latest/use/jupyter-directories.html#configuration-files

Note there’s a comment in one of your links that

It looks like the issue can now be solved by setting a new parameter in Jupyter Server: FileContentsManager.always_delete_dir = True (see reference)

1 Like

Doh! I missed the link/reference (and reviewed the other posts multiple times). Thanks for the help.

Apologies for resurrecting this topic but it is still unclear to me how to do this from tljh.

Only way I found so far is to add self.config.FileContentsManager.always_delete_dir = True to /opt/tljh/user/lib/python3.12/site-packages/jupyterhub/singleuser/extension.py but it feels too hacky.

@manics do you know if there a better way of doing it? can I overwrite single-user server’s config from one of those .py files under /opt/tljh/config/jupyterhub_config.d/?

thank you very much,
Daniel

Your Jupyter server configuration files are independent of the JupyterHub config. See

For the possible locations

Thanks for the answer, it would be great if TLJH had something built-in to configure Jupyter server.

In a similar way “Zero to JupyterHub with Kubernetes” does it: Recursive delete directories in file browser? - #3 by cboettig

For completeness, if you are using TLJH you need to add:

{
  "FileContentsManager":
  { 
    "always_delete_dir": true
  }
}

to: /opt/tljh/user/etc/jupyter/jupyter_server_config.json

2 Likes