From 8ebf5b306716e30cc2fe1b878486e2f06620c016 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 16 Oct 2023 14:13:25 +0100 Subject: [PATCH 01/22] Enforce use of a virtual environment. --- install.sh | 12 +++++++++++- uninstall.sh | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index b45e7c8..fd6f43c 100755 --- a/install.sh +++ b/install.sh @@ -10,9 +10,17 @@ USAGE="./install.sh (--unstable)" POSITIONAL_ARGS=() FORCE=false UNSTABLE=false -PYTHON="/usr/bin/python3" +PYTHON="python" +venv_check() { + PYTHON_BIN=`which $PYTHON` + if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then + printf "This script should be run in a virtual Python environment.\n" + exit 1 + fi +} + user_check() { if [ $(id -u) -eq 0 ]; then printf "Script should not be run as root. Try './install.sh'\n" @@ -126,6 +134,7 @@ while [[ $# -gt 0 ]]; do done user_check +venv_check if [ ! -f "$PYTHON" ]; then printf "Python path $PYTHON not found!\n" @@ -179,6 +188,7 @@ printf "It's recommended you run these steps manually.\n" printf "If you want to run the full script, open it in\n" printf "an editor and remove 'exit 1' from below.\n" exit 1 +source $VIRTUAL_ENV/bin/activate EOF if $UNSTABLE; then diff --git a/uninstall.sh b/uninstall.sh index e013945..f213fc5 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -3,7 +3,16 @@ FORCE=false LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'` RESOURCES_DIR=$HOME/Pimoroni/$LIBRARY_NAME -PYTHON="/usr/bin/python3" +PYTHON="python" + + +venv_check() { + PYTHON_BIN=`which $PYTHON` + if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then + printf "This script should be run in a virtual Python environment.\n" + exit 1 + fi +} user_check() { if [ $(id -u) -eq 0 ]; then @@ -49,6 +58,7 @@ warning() { printf "$LIBRARY_NAME Python Library: Uninstaller\n\n" user_check +venv_check printf "Uninstalling for Python 3...\n" $PYTHON -m pip uninstall $LIBRARY_NAME From fc12d7d72617f69e5419858ee64281de4ce732ee Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 16 Oct 2023 14:31:33 +0100 Subject: [PATCH 02/22] Add option to manage venv if it's not detected. --- install.sh | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/install.sh b/install.sh index fd6f43c..1562e6b 100755 --- a/install.sh +++ b/install.sh @@ -5,6 +5,7 @@ DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` CONFIG_BACKUP=false APT_HAS_UPDATED=false RESOURCES_TOP_DIR=$HOME/Pimoroni +PY_VENV_DIR=$RESOURCES_TOP_DIR/venv WD=`pwd` USAGE="./install.sh (--unstable)" POSITIONAL_ARGS=() @@ -13,14 +14,6 @@ UNSTABLE=false PYTHON="python" -venv_check() { - PYTHON_BIN=`which $PYTHON` - if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then - printf "This script should be run in a virtual Python environment.\n" - exit 1 - fi -} - user_check() { if [ $(id -u) -eq 0 ]; then printf "Script should not be run as root. Try './install.sh'\n" @@ -62,6 +55,28 @@ warning() { echo -e "$(tput setaf 1)$1$(tput sgr0)" } +venv_check() { + PYTHON_BIN=`which $PYTHON` + if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then + printf "This script should be run in a virtual Python environment.\n" + if confirm "Would you like us to create one for you?"; then + if [ ! -f $PY_VENV_DIR/bin/activate ]; then + inform "Creating virtual Python environment in $PY_VENV_DIR, please wait...\n" + mkdir -p $PY_VENV_DIR + /usr/bin/python3 -m venv $PY_VENV_DIR --system-site-packages + else + inform "Found existing virtual Python environment in $PY_VENV_DIR\n" + fi + inform "Activating virtual Python environment in $PY_VENV_DIR..." + inform "source $PY_VENV_DIR/bin/activate\n" + source $PY_VENV_DIR/bin/activate + + else + exit 1 + fi + fi +} + function do_config_backup { if [ ! $CONFIG_BACKUP == true ]; then CONFIG_BACKUP=true @@ -136,7 +151,7 @@ done user_check venv_check -if [ ! -f "$PYTHON" ]; then +if [ ! -f `which $PYTHON` ]; then printf "Python path $PYTHON not found!\n" exit 1 fi From c8b2011c1f98ce5c715ceccc60385a9f001cdab5 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 17 Oct 2023 11:54:14 +0100 Subject: [PATCH 03/22] QA: Drop --format argument from ruff. --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 090fdb0..44c8654 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ commands = python -m build --no-isolation python -m twine check dist/* isort --check . - ruff --format=github . + ruff . codespell . deps = check-manifest From d9710f7f9edba9ab9c64e13f403358c5f40aa530 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 19 Oct 2023 10:31:51 +0100 Subject: [PATCH 04/22] Drop an auto venv script into ~/Pimoroni, update venv prompt --- install.sh | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 1562e6b..8ee7343 100755 --- a/install.sh +++ b/install.sh @@ -55,6 +55,23 @@ warning() { echo -e "$(tput setaf 1)$1$(tput sgr0)" } +venv_bash_snippet() { + if [ ! -f $BASH_SNIPPET ]; then + cat << EOF > $BASH_SNIPPET +# Add `source $RESOURCES_DIR/auto_venv.sh` to your ~/.bashrc to activate +# the Pimoroni virtual environment automagically! +PY_ENV_DIR=~/Pimoroni/venv +if [ ! -f \$PY_ENV_DIR/bin/activate ]; then + printf "Creating user Python environment in \$PY_ENV_DIR, please wait...\n" + mkdir -p \$PY_ENV_DIR + python3 -m venv --system-site-packages --prompt Pimoroni \$PY_ENV_DIR +fi +printf " ↓ ↓ ↓ ↓ Hello, we've activated a Python venv for you. To exit, type \"deactivate\".\n" +source \$PY_ENV_DIR/bin/activate +EOF + fi +} + venv_check() { PYTHON_BIN=`which $PYTHON` if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then @@ -63,7 +80,8 @@ venv_check() { if [ ! -f $PY_VENV_DIR/bin/activate ]; then inform "Creating virtual Python environment in $PY_VENV_DIR, please wait...\n" mkdir -p $PY_VENV_DIR - /usr/bin/python3 -m venv $PY_VENV_DIR --system-site-packages + /usr/bin/python3 -m venv $PY_VENV_DIR --system-site-packages --prompt Pimoroni + venv_bash_snippet() else inform "Found existing virtual Python environment in $PY_VENV_DIR\n" fi @@ -188,6 +206,7 @@ eval $CONFIG_VARS RESOURCES_DIR=$RESOURCES_TOP_DIR/$LIBRARY_NAME UNINSTALLER=$RESOURCES_DIR/uninstall.sh +BASH_SNIPPET=$RESOURCES_DIR/auto_venv.sh RES_DIR_OWNER=`stat -c "%U" $RESOURCES_TOP_DIR` From 896b3b5c3b72c67c36fcebddb8e6ec33fa68c40a Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 23 Oct 2023 15:50:36 +0100 Subject: [PATCH 05/22] Switch venv location to virtualenvwrapper default. --- install.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index 8ee7343..d3c9aa9 100755 --- a/install.sh +++ b/install.sh @@ -5,7 +5,7 @@ DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` CONFIG_BACKUP=false APT_HAS_UPDATED=false RESOURCES_TOP_DIR=$HOME/Pimoroni -PY_VENV_DIR=$RESOURCES_TOP_DIR/venv +PY_VENV_DIR=$HOME/.virtualenvs/pimoroni WD=`pwd` USAGE="./install.sh (--unstable)" POSITIONAL_ARGS=() @@ -60,14 +60,14 @@ venv_bash_snippet() { cat << EOF > $BASH_SNIPPET # Add `source $RESOURCES_DIR/auto_venv.sh` to your ~/.bashrc to activate # the Pimoroni virtual environment automagically! -PY_ENV_DIR=~/Pimoroni/venv -if [ ! -f \$PY_ENV_DIR/bin/activate ]; then - printf "Creating user Python environment in \$PY_ENV_DIR, please wait...\n" - mkdir -p \$PY_ENV_DIR - python3 -m venv --system-site-packages --prompt Pimoroni \$PY_ENV_DIR +PY_VENV_DIR="$PY_VENV_DIR" +if [ ! -f \$PY_VENV_DIR/bin/activate ]; then + printf "Creating user Python environment in \$PY_VENV_DIR, please wait...\n" + mkdir -p \$PY_VENV_DIR + python3 -m venv --system-site-packages \$PY_VENV_DIR fi printf " ↓ ↓ ↓ ↓ Hello, we've activated a Python venv for you. To exit, type \"deactivate\".\n" -source \$PY_ENV_DIR/bin/activate +source \$PY_VENV_DIR/bin/activate EOF fi } @@ -80,7 +80,7 @@ venv_check() { if [ ! -f $PY_VENV_DIR/bin/activate ]; then inform "Creating virtual Python environment in $PY_VENV_DIR, please wait...\n" mkdir -p $PY_VENV_DIR - /usr/bin/python3 -m venv $PY_VENV_DIR --system-site-packages --prompt Pimoroni + /usr/bin/python3 -m venv $PY_VENV_DIR --system-site-packages Pimoroni venv_bash_snippet() else inform "Found existing virtual Python environment in $PY_VENV_DIR\n" From bd3bf8bf652705b1e81ed56c0c649f3868b1096d Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 23 Oct 2023 16:12:21 +0100 Subject: [PATCH 06/22] Tweaks to install and tool.pimoroni --- install.sh | 40 ++++++++++++++++++++-------------------- pyproject.toml | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/install.sh b/install.sh index d3c9aa9..aebc385 100755 --- a/install.sh +++ b/install.sh @@ -5,7 +5,8 @@ DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` CONFIG_BACKUP=false APT_HAS_UPDATED=false RESOURCES_TOP_DIR=$HOME/Pimoroni -PY_VENV_DIR=$HOME/.virtualenvs/pimoroni +VENV_BASH_SNIPPET=$RESOURCES_DIR/auto_venv.sh +VENV_DIR=$HOME/.virtualenvs/pimoroni WD=`pwd` USAGE="./install.sh (--unstable)" POSITIONAL_ARGS=() @@ -56,18 +57,18 @@ warning() { } venv_bash_snippet() { - if [ ! -f $BASH_SNIPPET ]; then - cat << EOF > $BASH_SNIPPET + if [ ! -f $VENV_BASH_SNIPPET ]; then + cat << EOF > $VENV_BASH_SNIPPET # Add `source $RESOURCES_DIR/auto_venv.sh` to your ~/.bashrc to activate # the Pimoroni virtual environment automagically! -PY_VENV_DIR="$PY_VENV_DIR" -if [ ! -f \$PY_VENV_DIR/bin/activate ]; then - printf "Creating user Python environment in \$PY_VENV_DIR, please wait...\n" - mkdir -p \$PY_VENV_DIR - python3 -m venv --system-site-packages \$PY_VENV_DIR +VENV_DIR="$VENV_DIR" +if [ ! -f \$VENV_DIR/bin/activate ]; then + printf "Creating user Python environment in \$VENV_DIR, please wait...\n" + mkdir -p \$VENV_DIR + python3 -m venv --system-site-packages \$VENV_DIR fi printf " ↓ ↓ ↓ ↓ Hello, we've activated a Python venv for you. To exit, type \"deactivate\".\n" -source \$PY_VENV_DIR/bin/activate +source \$VENV_DIR/bin/activate EOF fi } @@ -77,17 +78,17 @@ venv_check() { if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then printf "This script should be run in a virtual Python environment.\n" if confirm "Would you like us to create one for you?"; then - if [ ! -f $PY_VENV_DIR/bin/activate ]; then - inform "Creating virtual Python environment in $PY_VENV_DIR, please wait...\n" - mkdir -p $PY_VENV_DIR - /usr/bin/python3 -m venv $PY_VENV_DIR --system-site-packages Pimoroni - venv_bash_snippet() + if [ ! -f $VENV_DIR/bin/activate ]; then + inform "Creating virtual Python environment in $VENV_DIR, please wait...\n" + mkdir -p $VENV_DIR + /usr/bin/python3 -m venv $VENV_DIR --system-site-packages + venv_bash_snippet else - inform "Found existing virtual Python environment in $PY_VENV_DIR\n" + inform "Found existing virtual Python environment in $VENV_DIR\n" fi - inform "Activating virtual Python environment in $PY_VENV_DIR..." - inform "source $PY_VENV_DIR/bin/activate\n" - source $PY_VENV_DIR/bin/activate + inform "Activating virtual Python environment in $VENV_DIR..." + inform "source $VENV_DIR/bin/activate\n" + source $VENV_DIR/bin/activate else exit 1 @@ -185,7 +186,7 @@ pip_pkg_install toml CONFIG_VARS=`$PYTHON - < Date: Mon, 6 Nov 2023 16:43:09 +0000 Subject: [PATCH 07/22] CI: Set term in check.sh for GitHub Actions. --- check.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/check.sh b/check.sh index cbb1565..4395d89 100755 --- a/check.sh +++ b/check.sh @@ -6,6 +6,7 @@ NOPOST=$1 LIBRARY_NAME=`hatch project metadata name` LIBRARY_VERSION=`hatch version | awk -F "." '{print $1"."$2"."$3}'` POST_VERSION=`hatch version | awk -F "." '{print substr($4,0,length($4))}'` +TERM=${TERM:="xterm-256color"} success() { echo -e "$(tput setaf 2)$1$(tput sgr0)" From b74d0c6d1ca59c448c92f7c0762166dc57992532 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 15 Nov 2023 13:58:58 +0000 Subject: [PATCH 08/22] Better handling of /boot/config.txt and /boot/firmware/config.txt Using sed -i on /boot/config.txt would read the file and write it back as a real file instead of a link. Breaking assumptions about this file being a link to /boot/firmware/config.txt and leading to all sorts of confusion. --- install.sh | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/install.sh b/install.sh index aebc385..38f19e9 100755 --- a/install.sh +++ b/install.sh @@ -1,6 +1,7 @@ #!/bin/bash LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'` -CONFIG=/boot/config.txt +CONFIG_FILE=config.txt +CONFIG_DIR="/boot/firmware" DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` CONFIG_BACKUP=false APT_HAS_UPDATED=false @@ -56,6 +57,22 @@ warning() { echo -e "$(tput setaf 1)$1$(tput sgr0)" } +find_config() { + if [ ! -f "$CONFIG_DIR/$CONFIG_FILE" ]; then + CONFIG_DIR="/boot" + if [ ! -f "$CONFIG_DIR/$CONFIG_FILE"]; then + warning "Could not find $CONFIG_FILE!" + exit 1 + fi + else + if [ -f "/boot/$CONFIG_FILE" ] && [ ! -L "/boot/$CONFIG_FILE" ]; then + warning "Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR/$CONFIG_FILE" + warning "You might want to fix this!" + fi + fi + inform "Using $CONFIG_FILE in $CONFIG_DIR" +} + venv_bash_snippet() { if [ ! -f $VENV_BASH_SNIPPET ]; then cat << EOF > $VENV_BASH_SNIPPET @@ -100,12 +117,12 @@ function do_config_backup { if [ ! $CONFIG_BACKUP == true ]; then CONFIG_BACKUP=true FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt" - inform "Backing up $CONFIG to /boot/$FILENAME\n" - sudo cp $CONFIG /boot/$FILENAME + inform "Backing up $CONFIG_DIR/$CONFIG_FILE to $CONFIG_DIR/$FILENAME\n" + sudo cp $CONFIG_DIR/$CONFIG_FILE $CONFIG_DIR/$FILENAME mkdir -p $RESOURCES_TOP_DIR/config-backups/ - cp $CONFIG $RESOURCES_TOP_DIR/config-backups/$FILENAME + cp $CONFIG_DIR/$CONFIG_FILE $RESOURCES_TOP_DIR/config-backups/$FILENAME if [ -f "$UNINSTALLER" ]; then - echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG" >> $UNINSTALLER + echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG_DIR/$CONFIG_FILE" >> $UNINSTALLER fi fi } @@ -245,10 +262,12 @@ fi cd $WD +find_config + for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do CMD="${SETUP_CMDS[$i]}" - # Attempt to catch anything that touches /boot/config.txt and trigger a backup - if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG"* ]] || [[ "$CMD" == *"\$CONFIG"* ]]; then + # Attempt to catch anything that touches config.txt and trigger a backup + if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG_DIR/$CONFIG_FILE"* ]] || [[ "$CMD" == *"\$CONFIG_DIR/\$CONFIG_FILE"* ]]; then do_config_backup fi eval $CMD @@ -258,10 +277,10 @@ for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do CONFIG_LINE="${CONFIG_TXT[$i]}" if ! [ "$CONFIG_LINE" == "" ]; then do_config_backup - inform "Adding $CONFIG_LINE to $CONFIG\n" - sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG - if ! grep -q "^$CONFIG_LINE" $CONFIG; then - printf "$CONFIG_LINE\n" | sudo tee --append $CONFIG + inform "Adding $CONFIG_LINE to $CONFIG_DIR/$CONFIG_FILE\n" + sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG_DIR/$CONFIG_FILE + if ! grep -q "^$CONFIG_LINE" $CONFIG_DIR/$CONFIG_FILE; then + printf "$CONFIG_LINE\n" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE fi fi done From 66f69e3cf263e283abc1422e38b9836579380d3a Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 21 Nov 2023 15:57:04 +0000 Subject: [PATCH 09/22] Fix VENV_DIR path. --- install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 38f19e9..9f11aca 100755 --- a/install.sh +++ b/install.sh @@ -6,7 +6,7 @@ DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` CONFIG_BACKUP=false APT_HAS_UPDATED=false RESOURCES_TOP_DIR=$HOME/Pimoroni -VENV_BASH_SNIPPET=$RESOURCES_DIR/auto_venv.sh +VENV_BASH_SNIPPET=$RESOURCES_TOP_DIR/auto_venv.sh VENV_DIR=$HOME/.virtualenvs/pimoroni WD=`pwd` USAGE="./install.sh (--unstable)" @@ -76,7 +76,7 @@ find_config() { venv_bash_snippet() { if [ ! -f $VENV_BASH_SNIPPET ]; then cat << EOF > $VENV_BASH_SNIPPET -# Add `source $RESOURCES_DIR/auto_venv.sh` to your ~/.bashrc to activate +# Add `source $VENV_BASH_SNIPPET` to your ~/.bashrc to activate # the Pimoroni virtual environment automagically! VENV_DIR="$VENV_DIR" if [ ! -f \$VENV_DIR/bin/activate ]; then From a9db28c718b4093debb19e923e6b2e156d40db33 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 22 Nov 2023 10:46:02 +0000 Subject: [PATCH 10/22] Fix auto_venv.sh creation. --- install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 9f11aca..75411ae 100755 --- a/install.sh +++ b/install.sh @@ -74,9 +74,11 @@ find_config() { } venv_bash_snippet() { + inform "Checking for $VENV_BASH_SNIPPET\n" if [ ! -f $VENV_BASH_SNIPPET ]; then + inform "Creating $VENV_BASH_SNIPPET\n" cat << EOF > $VENV_BASH_SNIPPET -# Add `source $VENV_BASH_SNIPPET` to your ~/.bashrc to activate +# Add "source $VENV_BASH_SNIPPET" to your ~/.bashrc to activate # the Pimoroni virtual environment automagically! VENV_DIR="$VENV_DIR" if [ ! -f \$VENV_DIR/bin/activate ]; then From 5a2228ec41d0321c6c971cbad949b46d6e425750 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 22 Nov 2023 10:47:27 +0000 Subject: [PATCH 11/22] install.sh: normalise whitespace. --- install.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/install.sh b/install.sh index 75411ae..e00b03c 100755 --- a/install.sh +++ b/install.sh @@ -64,13 +64,13 @@ find_config() { warning "Could not find $CONFIG_FILE!" exit 1 fi - else - if [ -f "/boot/$CONFIG_FILE" ] && [ ! -L "/boot/$CONFIG_FILE" ]; then - warning "Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR/$CONFIG_FILE" - warning "You might want to fix this!" - fi + else + if [ -f "/boot/$CONFIG_FILE" ] && [ ! -L "/boot/$CONFIG_FILE" ]; then + warning "Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR/$CONFIG_FILE" + warning "You might want to fix this!" + fi fi - inform "Using $CONFIG_FILE in $CONFIG_DIR" + inform "Using $CONFIG_FILE in $CONFIG_DIR" } venv_bash_snippet() { From fceeafbbc93e60b47db82b75282092b2cd07e71e Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 23 Nov 2023 10:21:00 +0000 Subject: [PATCH 12/22] install.sh: rework for better error reporting and fix some bugs. Fix a bug where auto_venv.sh was being created in a non-existent directory. Trap exit codes for some commands and add some help text + GitHUb url at the end of the install process. Try to comment what some sections do, and insert linebreaks so they are more logically broken up in the installer output. Try to be more consistent with colours. Try to be more friendly with colours- remove full red warning text in favour of a prefix so the errors/warnings are easier to read. Return a failure exit code if bits of the script have failed. Try to re-order output so it's more logical. Re-word venv creation message. --- install.sh | 128 ++++++++++++++++++++++++++++++++++++------------- pyproject.toml | 4 +- 2 files changed, 96 insertions(+), 36 deletions(-) diff --git a/install.sh b/install.sh index e00b03c..d42c48d 100755 --- a/install.sh +++ b/install.sh @@ -5,21 +5,21 @@ CONFIG_DIR="/boot/firmware" DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` CONFIG_BACKUP=false APT_HAS_UPDATED=false -RESOURCES_TOP_DIR=$HOME/Pimoroni -VENV_BASH_SNIPPET=$RESOURCES_TOP_DIR/auto_venv.sh -VENV_DIR=$HOME/.virtualenvs/pimoroni +RESOURCES_TOP_DIR="$HOME/Pimoroni" +VENV_BASH_SNIPPET="$RESOURCES_TOP_DIR/auto_venv.sh" +VENV_DIR="$HOME/.virtualenvs/pimoroni" WD=`pwd` USAGE="./install.sh (--unstable)" POSITIONAL_ARGS=() FORCE=false UNSTABLE=false PYTHON="python" +CMD_ERRORS=false user_check() { if [ $(id -u) -eq 0 ]; then - printf "Script should not be run as root. Try './install.sh'\n" - exit 1 + fatal "Script should not be run as root. Try './install.sh'\n" fi } @@ -54,15 +54,19 @@ inform() { } warning() { - echo -e "$(tput setaf 1)$1$(tput sgr0)" + echo -e "$(tput setaf 1)⚠ WARNING:$(tput sgr0) $1" +} + +fatal() { + echo -e "$(tput setaf 1)⚠ FATAL:$(tput sgr0) $1" + exit 1 } find_config() { if [ ! -f "$CONFIG_DIR/$CONFIG_FILE" ]; then CONFIG_DIR="/boot" - if [ ! -f "$CONFIG_DIR/$CONFIG_FILE"]; then - warning "Could not find $CONFIG_FILE!" - exit 1 + if [ ! -f "$CONFIG_DIR/$CONFIG_FILE" ]; then + fatal "Could not find $CONFIG_FILE!" fi else if [ -f "/boot/$CONFIG_FILE" ] && [ ! -L "/boot/$CONFIG_FILE" ]; then @@ -77,6 +81,7 @@ venv_bash_snippet() { inform "Checking for $VENV_BASH_SNIPPET\n" if [ ! -f $VENV_BASH_SNIPPET ]; then inform "Creating $VENV_BASH_SNIPPET\n" + mkdir -p $RESOURCES_TOP_DIR cat << EOF > $VENV_BASH_SNIPPET # Add "source $VENV_BASH_SNIPPET" to your ~/.bashrc to activate # the Pimoroni virtual environment automagically! @@ -96,23 +101,32 @@ venv_check() { PYTHON_BIN=`which $PYTHON` if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then printf "This script should be run in a virtual Python environment.\n" - if confirm "Would you like us to create one for you?"; then + if confirm "Would you like us to create and/or use a default one?"; then + printf "\n" if [ ! -f $VENV_DIR/bin/activate ]; then - inform "Creating virtual Python environment in $VENV_DIR, please wait...\n" + inform "Creating a new virtual Python environment in $VENV_DIR, please wait...\n" mkdir -p $VENV_DIR /usr/bin/python3 -m venv $VENV_DIR --system-site-packages venv_bash_snippet + source $VENV_DIR/bin/activate else - inform "Found existing virtual Python environment in $VENV_DIR\n" + inform "Activating existing virtual Python environment in $VENV_DIR\n" + printf "source $VENV_DIR/bin/activate\n" + source $VENV_DIR/bin/activate fi - inform "Activating virtual Python environment in $VENV_DIR..." - inform "source $VENV_DIR/bin/activate\n" - source $VENV_DIR/bin/activate - else - exit 1 + printf "\n" + fatal "Please create and/or activate a virtual Python environment and try again!\n" fi fi + printf "\n" +} + +check_for_error() { + if [ $? -ne 0 ]; then + CMD_ERRORS=true + warning "^^^ 😬" + fi } function do_config_backup { @@ -132,6 +146,7 @@ function do_config_backup { function apt_pkg_install { PACKAGES=() PACKAGES_IN=("$@") + # Check the list of packages and only run update/install if we need to for ((i = 0; i < ${#PACKAGES_IN[@]}; i++)); do PACKAGE="${PACKAGES_IN[$i]}" if [ "$PACKAGE" == "" ]; then continue; fi @@ -143,12 +158,14 @@ function apt_pkg_install { done PACKAGES="${PACKAGES[@]}" if ! [ "$PACKAGES" == "" ]; then - echo "Installing missing packages: $PACKAGES" + printf "\n" + inform "Installing missing packages: $PACKAGES" if [ ! $APT_HAS_UPDATED ]; then sudo apt update APT_HAS_UPDATED=true fi sudo apt install -y $PACKAGES + check_for_error if [ -f "$UNINSTALLER" ]; then echo "apt uninstall -y $PACKAGES" >> $UNINSTALLER fi @@ -156,7 +173,9 @@ function apt_pkg_install { } function pip_pkg_install { + # A null Keyring prevents pip stalling in the background PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring $PYTHON -m pip install --upgrade "$@" + check_for_error } while [[ $# -gt 0 ]]; do @@ -186,30 +205,33 @@ while [[ $# -gt 0 ]]; do esac done +printf "Installing $LIBRARY_NAME...\n\n" + user_check venv_check if [ ! -f `which $PYTHON` ]; then - printf "Python path $PYTHON not found!\n" - exit 1 + fatal "Python path $PYTHON not found!\n" fi PYTHON_VER=`$PYTHON --version` -printf "$LIBRARY_NAME Python Library: Installer\n\n" - inform "Checking Dependencies. Please wait..." +# Install toml and try to read pyproject.toml into bash variables + pip_pkg_install toml CONFIG_VARS=`$PYTHON - < $UNINSTALLER printf "It's recommended you run these steps manually.\n" printf "If you want to run the full script, open it in\n" @@ -244,19 +270,23 @@ exit 1 source $VIRTUAL_ENV/bin/activate EOF -if $UNSTABLE; then - warning "Installing unstable library from source.\n\n" -else - printf "Installing stable library from pypi.\n\n" -fi +printf "\n" inform "Installing for $PYTHON_VER...\n" + +# Install apt packages from pyproject.toml / tool.pimoroni.apt_packages apt_pkg_install "${APT_PACKAGES[@]}" + +printf "\n" + if $UNSTABLE; then + warning "Installing unstable library from source.\n" pip_pkg_install . else + inform "Installing stable library from pypi.\n" pip_pkg_install $LIBRARY_NAME fi + if [ $? -eq 0 ]; then success "Done!\n" echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> $UNINSTALLER @@ -266,6 +296,8 @@ cd $WD find_config +# Run the setup commands from pyproject.toml / tool.pimoroni.commands + for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do CMD="${SETUP_CMDS[$i]}" # Attempt to catch anything that touches config.txt and trigger a backup @@ -273,13 +305,18 @@ for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do do_config_backup fi eval $CMD + check_for_error done +printf "\n" + +# Add the config.txt entries from pyproject.toml / tool.pimoroni.configtxt + for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do CONFIG_LINE="${CONFIG_TXT[$i]}" if ! [ "$CONFIG_LINE" == "" ]; then do_config_backup - inform "Adding $CONFIG_LINE to $CONFIG_DIR/$CONFIG_FILE\n" + inform "Adding $CONFIG_LINE to $CONFIG_DIR/$CONFIG_FILE" sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG_DIR/$CONFIG_FILE if ! grep -q "^$CONFIG_LINE" $CONFIG_DIR/$CONFIG_FILE; then printf "$CONFIG_LINE\n" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE @@ -287,6 +324,10 @@ for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do fi done +printf "\n" + +# Just a straight copy of the examples/ dir into ~/Pimoroni/board/examples + if [ -d "examples" ]; then if confirm "Would you like to copy examples to $RESOURCES_DIR?"; then inform "Copying examples to $RESOURCES_DIR" @@ -298,9 +339,12 @@ fi printf "\n" +# Use pdoc to generate basic documentation from the installed module + if confirm "Would you like to generate documentation?"; then + inform "Installing pdoc. Please wait..." pip_pkg_install pdoc - printf "Generating documentation.\n" + inform "Generating documentation.\n" $PYTHON -m pdoc $LIBRARY_NAME -o $RESOURCES_DIR/docs > /dev/null if [ $? -eq 0 ]; then inform "Documentation saved to $RESOURCES_DIR/docs" @@ -310,6 +354,22 @@ if confirm "Would you like to generate documentation?"; then fi fi -success "\nAll done!" -inform "If this is your first time installing you should reboot for hardware changes to take effect.\n" -inform "Find uninstall steps in $UNINSTALLER\n" +printf "\n" + +if [ "$CMD_ERRORS" = true ]; then + warning "One or more setup commands appear to have failed." + printf "This might prevent things from working properly.\n" + printf "Make sure your OS is up to date and try re-running this installer.\n" + printf "If things still don't work, report this or find help at $GITHUB_URL.\n\n" +else + success "\nAll done!" +fi + +printf "If this is your first time installing you should reboot for hardware changes to take effect.\n" +printf "Find uninstall steps in $UNINSTALLER\n\n" + +if [ "$CMD_ERRORS" = true ]; then + exit 1 +else + exit 0 +fi \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index b7dc485..c2a6186 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -108,6 +108,6 @@ ignore = [ ] [tool.pimoroni] -apt_packages = ["python3-rpi.gpio", "python3-smbus"] +apt_packages = ["git"] configtxt = [] -commands = [] +commands = ["false"] From e8f9443512820d60333fa5742d4a6d77ae4f695a Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 5 Dec 2023 12:06:41 +0000 Subject: [PATCH 13/22] README.md: Correct coveralls badge branch. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 97ec129..4459d0c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # __TITLE__ [![Build Status](https://img.shields.io/github/actions/workflow/status/pimoroni/PROJECT_NAME-python/test.yml?branch=main)](https://github.com/pimoroni/PROJECT_NAME-python/actions/workflows/test.yml) -[![Coverage Status](https://coveralls.io/repos/github/pimoroni/PROJECT_NAME-python/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/PROJECT_NAME-python?branch=master) +[![Coverage Status](https://coveralls.io/repos/github/pimoroni/PROJECT_NAME-python/badge.svg?branch=main)](https://coveralls.io/github/pimoroni/PROJECT_NAME-python?branch=main) [![PyPi Package](https://img.shields.io/pypi/v/PROJECT_NAME.svg)](https://pypi.python.org/pypi/PROJECT_NAME) [![Python Versions](https://img.shields.io/pypi/pyversions/PROJECT_NAME.svg)](https://pypi.python.org/pypi/PROJECT_NAME) From 39d73f7ed68e6ef03ed7343920f37c6e789346fd Mon Sep 17 00:00:00 2001 From: Dan Webb Date: Mon, 8 Jan 2024 14:59:00 +0000 Subject: [PATCH 14/22] CI: Update GitHub Actions versions. Signed-off-by: Dan Webb --- .github/workflows/build.yml | 6 +++--- .github/workflows/qa.yml | 5 ++--- .github/workflows/test.yml | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 87200ef..07620e3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,10 +19,10 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} @@ -35,7 +35,7 @@ jobs: make build - name: Upload Packages - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.RELEASE_FILE }} path: dist/ diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 4f85883..1bf14b4 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -10,16 +10,15 @@ jobs: test: name: linting & spelling runs-on: ubuntu-latest - env: TERM: xterm-256color steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Python '3,11' - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: '3.11' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 016a678..6f8cff7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} From 5e294af079b65f79c169023e437276794c4af59d Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 9 Jan 2024 13:20:28 +0000 Subject: [PATCH 15/22] QA: Add shellcheck and fix/ignore all issues. This was inspired by and built upon Dan's PR here: https://github.com/pimoroni/grow-python/pull/37 Co-authored-by: Dan Webb --- .github/workflows/qa.yml | 4 ++ Makefile | 5 +- check.sh | 20 +++---- install.sh | 111 ++++++++++++++++++--------------------- uninstall.sh | 14 ++--- 5 files changed, 75 insertions(+), 79 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 1bf14b4..ac672a5 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -33,3 +33,7 @@ jobs: - name: Run Code Checks run: | make check + + - name: Run Bash Code Checks + run: | + make shellcheck diff --git a/Makefile b/Makefile index 9e0c15c..34f4a7d 100644 --- a/Makefile +++ b/Makefile @@ -30,11 +30,14 @@ uninstall: dev-deps: python3 -m pip install -r requirements-dev.txt - sudo apt install dos2unix + sudo apt install dos2unix shellcheck check: @bash check.sh +shellcheck: + shellcheck *.sh + qa: tox -e qa diff --git a/check.sh b/check.sh index 4395d89..38dfc3a 100755 --- a/check.sh +++ b/check.sh @@ -3,9 +3,9 @@ # This script handles some basic QA checks on the source NOPOST=$1 -LIBRARY_NAME=`hatch project metadata name` -LIBRARY_VERSION=`hatch version | awk -F "." '{print $1"."$2"."$3}'` -POST_VERSION=`hatch version | awk -F "." '{print substr($4,0,length($4))}'` +LIBRARY_NAME=$(hatch project metadata name) +LIBRARY_VERSION=$(hatch version | awk -F "." '{print $1"."$2"."$3}') +POST_VERSION=$(hatch version | awk -F "." '{print substr($4,0,length($4))}') TERM=${TERM:="xterm-256color"} success() { @@ -29,7 +29,7 @@ while [[ $# -gt 0 ]]; do ;; *) if [[ $1 == -* ]]; then - printf "Unrecognised option: $1\n"; + printf "Unrecognised option: %s\n" "$1"; exit 1 fi POSITIONAL_ARGS+=("$1") @@ -40,8 +40,7 @@ done inform "Checking $LIBRARY_NAME $LIBRARY_VERSION\n" inform "Checking for trailing whitespace..." -grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO -if [[ $? -eq 0 ]]; then +if grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO; then warning "Trailing whitespace found!" exit 1 else @@ -50,8 +49,7 @@ fi printf "\n" inform "Checking for DOS line-endings..." -grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile -if [[ $? -eq 0 ]]; then +if grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile; then warning "DOS line-endings found!" exit 1 else @@ -60,8 +58,7 @@ fi printf "\n" inform "Checking CHANGELOG.md..." -cat CHANGELOG.md | grep ^${LIBRARY_VERSION} > /dev/null 2>&1 -if [[ $? -eq 1 ]]; then +if ! grep "^${LIBRARY_VERSION}" CHANGELOG.md > /dev/null 2>&1; then warning "Changes missing for version ${LIBRARY_VERSION}! Please update CHANGELOG.md." exit 1 else @@ -70,8 +67,7 @@ fi printf "\n" inform "Checking for git tag ${LIBRARY_VERSION}..." -git tag -l | grep -E "${LIBRARY_VERSION}$" -if [[ $? -eq 1 ]]; then +if ! git tag -l | grep -E "${LIBRARY_VERSION}$"; then warning "Missing git tag for version ${LIBRARY_VERSION}" fi printf "\n" diff --git a/install.sh b/install.sh index d42c48d..10c2439 100755 --- a/install.sh +++ b/install.sh @@ -1,14 +1,13 @@ #!/bin/bash -LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'` +LIBRARY_NAME=$(grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}') CONFIG_FILE=config.txt CONFIG_DIR="/boot/firmware" -DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` +DATESTAMP=$(date "+%Y-%m-%d-%H-%M-%S") CONFIG_BACKUP=false APT_HAS_UPDATED=false RESOURCES_TOP_DIR="$HOME/Pimoroni" VENV_BASH_SNIPPET="$RESOURCES_TOP_DIR/auto_venv.sh" VENV_DIR="$HOME/.virtualenvs/pimoroni" -WD=`pwd` USAGE="./install.sh (--unstable)" POSITIONAL_ARGS=() FORCE=false @@ -18,7 +17,7 @@ CMD_ERRORS=false user_check() { - if [ $(id -u) -eq 0 ]; then + if [ "$(id -u)" -eq 0 ]; then fatal "Script should not be run as root. Try './install.sh'\n" fi } @@ -36,15 +35,6 @@ confirm() { fi } -prompt() { - read -r -p "$1 [y/N] " response < /dev/tty - if [[ $response =~ ^(yes|y|Y)$ ]]; then - true - else - false - fi -} - success() { echo -e "$(tput setaf 2)$1$(tput sgr0)" } @@ -79,10 +69,10 @@ find_config() { venv_bash_snippet() { inform "Checking for $VENV_BASH_SNIPPET\n" - if [ ! -f $VENV_BASH_SNIPPET ]; then + if [ ! -f "$VENV_BASH_SNIPPET" ]; then inform "Creating $VENV_BASH_SNIPPET\n" - mkdir -p $RESOURCES_TOP_DIR - cat << EOF > $VENV_BASH_SNIPPET + mkdir -p "$RESOURCES_TOP_DIR" + cat << EOF > "$VENV_BASH_SNIPPET" # Add "source $VENV_BASH_SNIPPET" to your ~/.bashrc to activate # the Pimoroni virtual environment automagically! VENV_DIR="$VENV_DIR" @@ -98,21 +88,23 @@ EOF } venv_check() { - PYTHON_BIN=`which $PYTHON` + PYTHON_BIN=$(which "$PYTHON") if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then printf "This script should be run in a virtual Python environment.\n" if confirm "Would you like us to create and/or use a default one?"; then printf "\n" - if [ ! -f $VENV_DIR/bin/activate ]; then + if [ ! -f "$VENV_DIR/bin/activate" ]; then inform "Creating a new virtual Python environment in $VENV_DIR, please wait...\n" - mkdir -p $VENV_DIR - /usr/bin/python3 -m venv $VENV_DIR --system-site-packages + mkdir -p "$VENV_DIR" + /usr/bin/python3 -m venv "$VENV_DIR" --system-site-packages venv_bash_snippet - source $VENV_DIR/bin/activate + # shellcheck disable=SC1091 + source "$VENV_DIR/bin/activate" else inform "Activating existing virtual Python environment in $VENV_DIR\n" - printf "source $VENV_DIR/bin/activate\n" - source $VENV_DIR/bin/activate + printf "source \"%s/bin/activate\"\n" "$VENV_DIR" + # shellcheck disable=SC1091 + source "$VENV_DIR/bin/activate" fi else printf "\n" @@ -134,29 +126,29 @@ function do_config_backup { CONFIG_BACKUP=true FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt" inform "Backing up $CONFIG_DIR/$CONFIG_FILE to $CONFIG_DIR/$FILENAME\n" - sudo cp $CONFIG_DIR/$CONFIG_FILE $CONFIG_DIR/$FILENAME - mkdir -p $RESOURCES_TOP_DIR/config-backups/ - cp $CONFIG_DIR/$CONFIG_FILE $RESOURCES_TOP_DIR/config-backups/$FILENAME + sudo cp "$CONFIG_DIR/$CONFIG_FILE $CONFIG_DIR/$FILENAME" + mkdir -p "$RESOURCES_TOP_DIR/config-backups/" + cp $CONFIG_DIR/$CONFIG_FILE "$RESOURCES_TOP_DIR/config-backups/$FILENAME" if [ -f "$UNINSTALLER" ]; then - echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG_DIR/$CONFIG_FILE" >> $UNINSTALLER + echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG_DIR/$CONFIG_FILE" >> "$UNINSTALLER" fi fi } function apt_pkg_install { - PACKAGES=() + PACKAGES_NEEDED=() PACKAGES_IN=("$@") # Check the list of packages and only run update/install if we need to for ((i = 0; i < ${#PACKAGES_IN[@]}; i++)); do PACKAGE="${PACKAGES_IN[$i]}" if [ "$PACKAGE" == "" ]; then continue; fi - printf "Checking for $PACKAGE\n" - dpkg -L $PACKAGE > /dev/null 2>&1 + printf "Checking for %s\n" "$PACKAGE" + dpkg -L "$PACKAGE" > /dev/null 2>&1 if [ "$?" == "1" ]; then - PACKAGES+=("$PACKAGE") + PACKAGES_NEEDED+=("$PACKAGE") fi done - PACKAGES="${PACKAGES[@]}" + PACKAGES="${PACKAGES_NEEDED[*]}" if ! [ "$PACKAGES" == "" ]; then printf "\n" inform "Installing missing packages: $PACKAGES" @@ -164,10 +156,10 @@ function apt_pkg_install { sudo apt update APT_HAS_UPDATED=true fi - sudo apt install -y $PACKAGES + sudo apt install -y "$PACKAGES" check_for_error if [ -f "$UNINSTALLER" ]; then - echo "apt uninstall -y $PACKAGES" >> $UNINSTALLER + echo "apt uninstall -y $PACKAGES" >> "$UNINSTALLER" fi fi } @@ -196,8 +188,8 @@ while [[ $# -gt 0 ]]; do ;; *) if [[ $1 == -* ]]; then - printf "Unrecognised option: $1\n"; - printf "Usage: $USAGE\n"; + printf "Unrecognised option: %s\n" "$1"; + printf "Usage: %s\n" "$USAGE"; exit 1 fi POSITIONAL_ARGS+=("$1") @@ -205,16 +197,16 @@ while [[ $# -gt 0 ]]; do esac done -printf "Installing $LIBRARY_NAME...\n\n" +printf "Installing %s...\n\n" "$LIBRARY_NAME" user_check venv_check -if [ ! -f `which $PYTHON` ]; then - fatal "Python path $PYTHON not found!\n" +if [ ! -f "$(which "$PYTHON")" ]; then + fatal "Python path %s not found!\n" "$PYTHON" fi -PYTHON_VER=`$PYTHON --version` +PYTHON_VER=$($PYTHON --version) inform "Checking Dependencies. Please wait..." @@ -222,7 +214,8 @@ inform "Checking Dependencies. Please wait..." pip_pkg_install toml -CONFIG_VARS=`$PYTHON - < $UNINSTALLER +cat << EOF > "$UNINSTALLER" printf "It's recommended you run these steps manually.\n" printf "If you want to run the full script, open it in\n" printf "an editor and remove 'exit 1' from below.\n" @@ -284,16 +279,15 @@ if $UNSTABLE; then pip_pkg_install . else inform "Installing stable library from pypi.\n" - pip_pkg_install $LIBRARY_NAME + pip_pkg_install "$LIBRARY_NAME" fi +# shellcheck disable=SC2181 # One of two commands run, depending on --unstable flag if [ $? -eq 0 ]; then success "Done!\n" - echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> $UNINSTALLER + echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> "$UNINSTALLER" fi -cd $WD - find_config # Run the setup commands from pyproject.toml / tool.pimoroni.commands @@ -304,7 +298,7 @@ for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG_DIR/$CONFIG_FILE"* ]] || [[ "$CMD" == *"\$CONFIG_DIR/\$CONFIG_FILE"* ]]; then do_config_backup fi - eval $CMD + eval "$CMD" check_for_error done @@ -319,7 +313,7 @@ for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do inform "Adding $CONFIG_LINE to $CONFIG_DIR/$CONFIG_FILE" sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG_DIR/$CONFIG_FILE if ! grep -q "^$CONFIG_LINE" $CONFIG_DIR/$CONFIG_FILE; then - printf "$CONFIG_LINE\n" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE + printf "%s \n" "$CONFIG_LINE" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE fi fi done @@ -331,8 +325,8 @@ printf "\n" if [ -d "examples" ]; then if confirm "Would you like to copy examples to $RESOURCES_DIR?"; then inform "Copying examples to $RESOURCES_DIR" - cp -r examples/ $RESOURCES_DIR - echo "rm -r $RESOURCES_DIR" >> $UNINSTALLER + cp -r examples/ "$RESOURCES_DIR" + echo "rm -r $RESOURCES_DIR" >> "$UNINSTALLER" success "Done!" fi fi @@ -345,8 +339,7 @@ if confirm "Would you like to generate documentation?"; then inform "Installing pdoc. Please wait..." pip_pkg_install pdoc inform "Generating documentation.\n" - $PYTHON -m pdoc $LIBRARY_NAME -o $RESOURCES_DIR/docs > /dev/null - if [ $? -eq 0 ]; then + if $PYTHON -m pdoc "$LIBRARY_NAME" -o "$RESOURCES_DIR/docs" > /dev/null; then inform "Documentation saved to $RESOURCES_DIR/docs" success "Done!" else @@ -360,13 +353,13 @@ if [ "$CMD_ERRORS" = true ]; then warning "One or more setup commands appear to have failed." printf "This might prevent things from working properly.\n" printf "Make sure your OS is up to date and try re-running this installer.\n" - printf "If things still don't work, report this or find help at $GITHUB_URL.\n\n" + printf "If things still don't work, report this or find help at %s.\n\n" "$GITHUB_URL" else success "\nAll done!" fi printf "If this is your first time installing you should reboot for hardware changes to take effect.\n" -printf "Find uninstall steps in $UNINSTALLER\n\n" +printf "Find uninstall steps in %s\n\n" "$UNINSTALLER" if [ "$CMD_ERRORS" = true ]; then exit 1 diff --git a/uninstall.sh b/uninstall.sh index f213fc5..3314b7f 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,13 +1,13 @@ #!/bin/bash FORCE=false -LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'` +LIBRARY_NAME=$(grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}') RESOURCES_DIR=$HOME/Pimoroni/$LIBRARY_NAME PYTHON="python" venv_check() { - PYTHON_BIN=`which $PYTHON` + PYTHON_BIN=$(which $PYTHON) if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then printf "This script should be run in a virtual Python environment.\n" exit 1 @@ -15,7 +15,7 @@ venv_check() { } user_check() { - if [ $(id -u) -eq 0 ]; then + if [ "$(id -u)" -eq 0 ]; then printf "Script should not be run as root. Try './uninstall.sh'\n" exit 1 fi @@ -55,17 +55,17 @@ warning() { echo -e "$(tput setaf 1)$1$(tput sgr0)" } -printf "$LIBRARY_NAME Python Library: Uninstaller\n\n" +printf "%s Python Library: Uninstaller\n\n" "$LIBRARY_NAME" user_check venv_check printf "Uninstalling for Python 3...\n" -$PYTHON -m pip uninstall $LIBRARY_NAME +$PYTHON -m pip uninstall "$LIBRARY_NAME" -if [ -d $RESOURCES_DIR ]; then +if [ -d "$RESOURCES_DIR" ]; then if confirm "Would you like to delete $RESOURCES_DIR?"; then - rm -r $RESOURCES_DIR + rm -r "$RESOURCES_DIR" fi fi From f0e3f93bd8476f58813279f6769c31c7eb5e19d6 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 10 Jan 2024 13:54:24 +0000 Subject: [PATCH 16/22] install.sh: slightly better feedback for setup commands. --- install.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 10c2439..059d3c4 100755 --- a/install.sh +++ b/install.sh @@ -117,7 +117,7 @@ venv_check() { check_for_error() { if [ $? -ne 0 ]; then CMD_ERRORS=true - warning "^^^ 😬" + warning "^^^ 😬 previous command did not exit cleanly!" fi } @@ -290,14 +290,18 @@ fi find_config +printf "\n" + # Run the setup commands from pyproject.toml / tool.pimoroni.commands +inform "Running setup commands...\n" for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do CMD="${SETUP_CMDS[$i]}" # Attempt to catch anything that touches config.txt and trigger a backup if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG_DIR/$CONFIG_FILE"* ]] || [[ "$CMD" == *"\$CONFIG_DIR/\$CONFIG_FILE"* ]]; then do_config_backup fi + printf "\"%s\"\n" "$CMD" eval "$CMD" check_for_error done @@ -365,4 +369,4 @@ if [ "$CMD_ERRORS" = true ]; then exit 1 else exit 0 -fi \ No newline at end of file +fi From d6a2c6d201171ae5c04c13038f4c3d37e574ce41 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 10 Jan 2024 14:48:08 +0000 Subject: [PATCH 17/22] install.sh: fix quoting bug in do_config_backup. --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 059d3c4..f7b678e 100755 --- a/install.sh +++ b/install.sh @@ -126,7 +126,7 @@ function do_config_backup { CONFIG_BACKUP=true FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt" inform "Backing up $CONFIG_DIR/$CONFIG_FILE to $CONFIG_DIR/$FILENAME\n" - sudo cp "$CONFIG_DIR/$CONFIG_FILE $CONFIG_DIR/$FILENAME" + sudo cp "$CONFIG_DIR/$CONFIG_FILE" "$CONFIG_DIR/$FILENAME" mkdir -p "$RESOURCES_TOP_DIR/config-backups/" cp $CONFIG_DIR/$CONFIG_FILE "$RESOURCES_TOP_DIR/config-backups/$FILENAME" if [ -f "$UNINSTALLER" ]; then From 3c9d88ac71d2524acb54b2f414db16e89117c778 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 10 Jan 2024 14:48:40 +0000 Subject: [PATCH 18/22] install.sh: don't output printf commands. --- install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index f7b678e..bb671f2 100755 --- a/install.sh +++ b/install.sh @@ -301,7 +301,9 @@ for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG_DIR/$CONFIG_FILE"* ]] || [[ "$CMD" == *"\$CONFIG_DIR/\$CONFIG_FILE"* ]]; then do_config_backup fi - printf "\"%s\"\n" "$CMD" + if [[ ! "$CMD" == printf* ]]; then + printf "Running: \"%s\"\n" "$CMD" + fi eval "$CMD" check_for_error done From 367cd22bc72b7196af3030cff15d9ae86391a7bd Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 11 Mar 2024 11:59:55 +0000 Subject: [PATCH 19/22] install.sh: drop symlink warning for /boot/config.txt. This file was changed from a symlink to a "DO NOT EDIT" real file in: https://github.com/RPi-Distro/pi-gen/commit/a12534473182eb234a1751da7348f784b9271f42 --- install.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/install.sh b/install.sh index bb671f2..b689e23 100755 --- a/install.sh +++ b/install.sh @@ -58,11 +58,6 @@ find_config() { if [ ! -f "$CONFIG_DIR/$CONFIG_FILE" ]; then fatal "Could not find $CONFIG_FILE!" fi - else - if [ -f "/boot/$CONFIG_FILE" ] && [ ! -L "/boot/$CONFIG_FILE" ]; then - warning "Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR/$CONFIG_FILE" - warning "You might want to fix this!" - fi fi inform "Using $CONFIG_FILE in $CONFIG_DIR" } From 31b961c5084fb820870eb3d070b344c04c8b1dd1 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 17 Apr 2024 09:37:23 +0100 Subject: [PATCH 20/22] install.sh: drop quotes around apt packages. Quotes would cause a list of packages to be treated as a single package and lookup would fail. Reported-by: thirdr --- install.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index b689e23..3db90bc 100755 --- a/install.sh +++ b/install.sh @@ -151,7 +151,8 @@ function apt_pkg_install { sudo apt update APT_HAS_UPDATED=true fi - sudo apt install -y "$PACKAGES" + # shellcheck disable=SC2086 + sudo apt install -y $PACKAGES check_for_error if [ -f "$UNINSTALLER" ]; then echo "apt uninstall -y $PACKAGES" >> "$UNINSTALLER" From 6bb337c3a836f89064bf7a7d399bc982155d5041 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 29 Apr 2024 10:30:21 +0100 Subject: [PATCH 21/22] Makefile: fail make tag if dev tools not installed. --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 34f4a7d..56cf0df 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,9 @@ endif @echo "deploy: build and upload to PyPi" @echo "tag: tag the repository with the current version\n" +version: + @hatch version + install: ./install.sh --unstable @@ -47,7 +50,7 @@ pytest: nopost: @bash check.sh --nopost -tag: +tag: version git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}" build: check From c2d4193336ed38d595a1582b414d8f894c47a830 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 10 May 2024 10:23:05 +0100 Subject: [PATCH 22/22] tox.ini: update ruff invocation to avoid deprecation warning. `warning: `ruff ` is deprecated. Use `ruff check ` instead.` --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 44c8654..4726cef 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ commands = python -m build --no-isolation python -m twine check dist/* isort --check . - ruff . + ruff check . codespell . deps = check-manifest