#!/usr/bin/env bash set -eE -o functrace # Author: Yiannis Charalambous # Descreption: Simple script for managing IPyKernels. HELP='Usage: ipy-kernel-ctl [command] Author: Yiannis Charalambous Automatically deploy and manage IPyKernel instances. IPyKernel allows to run Python environments in Jupyter Lab and Notebook. Deploy a kernel while inside of an environment, to use that environment in Jupyter Lab and Notebook. Jupyter Lab should be installed on your user Python environment (only for data redundancy reasons). IPyKernel needs to be installed in your pipenv in order for the command to be located. Commands: Default Command: Outputs the name of the kernel associated with the working directory. If there is no match, will output an error. --list, --ls: List the kernels currently deployed. --create, -c: Create a new kernel. --delete, -d: Delete the kernel associated with the current directory. Accepts 1 parameter which can be the name of the kernel to delete, instead of assuming the one in the current directory. --list-verbose, --lsv Lists the locations of all the ipykernels installed on the system. --upgrade Downloads and installs the latest version of this script. Replaces the currently installed version. ' KERNEL_DIR="$HOME/.local/share/jupyter/kernels" # The format at which ipykernels are named is the same as for pipenv. # https://github.com/pypa/pipenv/issues/796 DIR_NAME=$(basename "$(pwd)") DIR_NAME=$(echo "${DIR_NAME// /_}" | awk '{ print tolower($0) }') DIR_HASH=$(echo -n "$(pwd)" | md5sum | awk '{print($1)}') IPYKERNEL_NAME="$DIR_NAME-$DIR_HASH" UPDATE_URL="https://raw.githubusercontent.com/Yiannis128/ipykernel-ctl/master/ipykernel-ctl" create_ipykernel() { if [ -d "$KERNEL_DIR/$IPYKERNEL_NAME" ]; then echo "There already is a kernel for $IPYKERNEL_NAME" return fi python -m ipykernel install --user --name="$IPYKERNEL_NAME" } list_kernels() { find "$KERNEL_DIR" -mindepth 1 -type d ! -name '.*' -exec basename {} \; } VALID_ARGS=$(getopt -o hcd --long help,create,delete,list,ls,list-verbose,lsv,upgrade -- "$@") if [ "$?" -ne "0" ]; then exit 1; fi eval set -- "$VALID_ARGS" while true; do case "$1" in -h | --help) echo "$HELP" exit 0 ;; -c | --create) echo "Creating ipykernel for directory $IPYKERNEL_NAME" create_ipykernel shift ;; -d | --delete) if [ -v "3" ]; then echo "Deleting ipykernel $3" rm -r "${KERNEL_DIR:?}/$3" # Shift: --, and finally the arg shift 2 elif [ -d "$KERNEL_DIR/$IPYKERNEL_NAME" ]; then # Deletes the iPyKenrel of the current directory echo "Deleting ipykernel associated with current directory: $IPYKERNEL_NAME" rm -r "${KERNEL_DIR:?}/${IPYKERNEL_NAME:?}" else echo "There is no ipykernel to delete." exit 1 fi # Shift: --delete or -d. shift ;; --list | --ls) list_kernels exit 0 ;; --list-verbose | --lsv) find "$KERNEL_DIR" -mindepth 1 -type d ! -name '.*' -exec echo {} \; exit 0 ;; --upgrade) while true; do read -rp "ipykernel-ctl: Update script to the latest version? The upgraded version will replace the current file (y/n) " RESPONSE if [ "$RESPONSE" = "y" ]; then break elif [ "$RESPONSE" = "n" ]; then exit 1 fi done echo "Updating: $0" wget "$UPDATE_URL" -O "${0:?}" exit 0 ;; :) echo "Option requires an argument." exit 1 ;; ?) echo "Invalid command option." exit 1 ;; --) shift; # Check if no extra args provided. if [ "$#" = 0 ]; then # Check if kernel is initialized for the current directory, if it is, # then output its name. Use case insensitive search since ipykernel will # save the name in lowercase. if [[ $(list_kernels | grep -i "$IPYKERNEL_NAME") ]]; then echo "$IPYKERNEL_NAME" else echo "No kernel associated with directory. Call with --help to see options." exit 1 fi else # This triggers when the command is invoked with invalid text as arguments. echo "Invalid arguments... Run command with -h to get help information." exit 1 fi break ;; *) exit 1; esac done