diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..5365571 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,42 @@ +name: Build + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + name: Build (Python ${{ matrix.python }}) + runs-on: ubuntu-latest + strategy: + matrix: + python: ['3.9', '3.10', '3.11'] + + env: + TERM: xterm-256color + RELEASE_FILE: ${{ github.event.repository.name }}-${{ github.event.release.tag_name || github.sha }}-py${{ matrix.python }} + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + + - name: Install Dependencies + run: | + make dev-deps + + - name: Build Packages + run: | + make build + + - name: Upload Packages + uses: actions/upload-artifact@v4 + with: + name: ${{ env.RELEASE_FILE }} + path: dist/ diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml new file mode 100644 index 0000000..f3c1a2d --- /dev/null +++ b/.github/workflows/install.yml @@ -0,0 +1,40 @@ +name: Install Test + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + name: Install (Python ${{ matrix.python }}) + runs-on: ubuntu-latest + env: + TERM: xterm-256color + strategy: + matrix: + python: ['3.9', '3.10', '3.11'] + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + + - name: Stub files & Patch install.sh + run: | + mkdir -p boot/firmware + touch boot/firmware/config.txt + sed -i "s|/boot/firmware|`pwd`/boot/firmware|g" install.sh + sed -i "s|sudo raspi-config|raspi-config|g" pyproject.toml + touch raspi-config + chmod +x raspi-config + echo `pwd` >> $GITHUB_PATH + + - name: Run install.sh + run: | + ./install.sh --unstable --force diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml new file mode 100644 index 0000000..2e166c0 --- /dev/null +++ b/.github/workflows/qa.yml @@ -0,0 +1,39 @@ +name: QA + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + name: Linting & Spelling + runs-on: ubuntu-latest + env: + TERM: xterm-256color + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up Python '3,11' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install Dependencies + run: | + make dev-deps + + - name: Run Quality Assurance + run: | + make qa + + - name: Run Code Checks + run: | + make check + + - name: Run Bash Code Checks + run: | + make shellcheck diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..9e29cb9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,43 @@ +name: Tests + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + name: Test (Python ${{ matrix.python }}) + runs-on: ubuntu-latest + env: + TERM: xterm-256color + strategy: + matrix: + python: ['3.9', '3.10', '3.11'] + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + + - name: Install Dependencies + run: | + make dev-deps + + - name: Run Tests + run: | + make pytest + + - name: Coverage + if: ${{ matrix.python == '3.9' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + python -m pip install coveralls + coveralls --service=github + diff --git a/.gitignore b/.gitignore index 711cf84..fa45562 100644 --- a/.gitignore +++ b/.gitignore @@ -1,28 +1,20 @@ -__pycache__/ -sphinx/_build/ +build/ +_build/ +*.o +*.so +*.a *.py[cod] -*.swp +*.egg-info dist/ -sdist/ -env/ -build/ -develop-eggs/ -eggs/ -*.egg-info/ -.installed.cfg -*.egg +__pycache__ +.DS_Store *.deb *.dsc *.build *.changes *.orig.* -testing/ -MANIFEST -.idea -pip-log.txt -pip-delete-this-directory.txt -library/test/scrollphat/ -library/debian/ packaging/*tar.xz -.DS_Store -sphinx.virtualenv +library/debian/ +.coverage +.pytest_cache +.tox diff --git a/library/CHANGELOG.txt b/CHANGELOG.md similarity index 100% rename from library/CHANGELOG.txt rename to CHANGELOG.md diff --git a/library/LICENSE.txt b/LICENSE.txt similarity index 100% rename from library/LICENSE.txt rename to LICENSE.txt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..56cf0df --- /dev/null +++ b/Makefile @@ -0,0 +1,66 @@ +LIBRARY_NAME := $(shell hatch project metadata name 2> /dev/null) +LIBRARY_VERSION := $(shell hatch version 2> /dev/null) + +.PHONY: usage install uninstall check pytest qa build-deps check tag wheel sdist clean dist testdeploy deploy +usage: +ifdef LIBRARY_NAME + @echo "Library: ${LIBRARY_NAME}" + @echo "Version: ${LIBRARY_VERSION}\n" +else + @echo "WARNING: You should 'make dev-deps'\n" +endif + @echo "Usage: make , where target is one of:\n" + @echo "install: install the library locally from source" + @echo "uninstall: uninstall the local library" + @echo "dev-deps: install Python dev dependencies" + @echo "check: perform basic integrity checks on the codebase" + @echo "qa: run linting and package QA" + @echo "pytest: run Python test fixtures" + @echo "clean: clean Python build and dist directories" + @echo "build: build Python distribution files" + @echo "testdeploy: build and upload to test PyPi" + @echo "deploy: build and upload to PyPi" + @echo "tag: tag the repository with the current version\n" + +version: + @hatch version + +install: + ./install.sh --unstable + +uninstall: + ./uninstall.sh + +dev-deps: + python3 -m pip install -r requirements-dev.txt + sudo apt install dos2unix shellcheck + +check: + @bash check.sh + +shellcheck: + shellcheck *.sh + +qa: + tox -e qa + +pytest: + tox -e py + +nopost: + @bash check.sh --nopost + +tag: version + git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}" + +build: check + @hatch build + +clean: + -rm -r dist + +testdeploy: build + twine upload --repository testpypi dist/* + +deploy: nopost build + twine upload dist/* diff --git a/check.sh b/check.sh new file mode 100755 index 0000000..3dfe6f1 --- /dev/null +++ b/check.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +# 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))}') +TERM=${TERM:="xterm-256color"} + +success() { + echo -e "$(tput setaf 2)$1$(tput sgr0)" +} + +inform() { + echo -e "$(tput setaf 6)$1$(tput sgr0)" +} + +warning() { + echo -e "$(tput setaf 1)$1$(tput sgr0)" +} + +while [[ $# -gt 0 ]]; do + K="$1" + case $K in + -p|--nopost) + NOPOST=true + shift + ;; + *) + if [[ $1 == -* ]]; then + printf "Unrecognised option: %s\n" "$1"; + exit 1 + fi + POSITIONAL_ARGS+=("$1") + shift + esac +done + +inform "Checking $LIBRARY_NAME $LIBRARY_VERSION\n" + +inform "Checking for trailing whitespace..." +if grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist -exclude-dir=.venv --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO; then + warning "Trailing whitespace found!" + exit 1 +else + success "No trailing whitespace found." +fi +printf "\n" + +inform "Checking for DOS line-endings..." +if grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox -exclude-dir=.venv --exclude-dir=.git --exclude=Makefile; then + warning "DOS line-endings found!" + exit 1 +else + success "No DOS line-endings found." +fi +printf "\n" + +inform "Checking CHANGELOG.md..." +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 + success "Changes found for version ${LIBRARY_VERSION}." +fi +printf "\n" + +inform "Checking for git tag ${LIBRARY_VERSION}..." +if ! git tag -l | grep -E "${LIBRARY_VERSION}$"; then + warning "Missing git tag for version ${LIBRARY_VERSION}" +fi +printf "\n" + +if [[ $NOPOST ]]; then + inform "Checking for .postN on library version..." + if [[ "$POST_VERSION" != "" ]]; then + warning "Found .$POST_VERSION on library version." + inform "Please only use these for testpypi releases." + exit 1 + else + success "OK" + fi +fi diff --git a/examples/binary-clock.py b/examples/binary-clock.py index a166f3f..42c2c4e 100755 --- a/examples/binary-clock.py +++ b/examples/binary-clock.py @@ -4,11 +4,12 @@ # for the Pimoroni Scroll Bot. # Copyright (C) 2018 Freddy Spierenburg -import scrollphathd import datetime import math import random +import scrollphathd + class Time(object): def __init__(self): diff --git a/examples/cellular-automata.py b/examples/cellular-automata.py index ed2f5c3..5148d40 100755 --- a/examples/cellular-automata.py +++ b/examples/cellular-automata.py @@ -13,7 +13,6 @@ import scrollphathd - print(""" Scroll pHAT HD: Cellular Automata @@ -59,7 +58,7 @@ def mainloop(): while True: - # redraw first so that it shows the initial contitions when first run + # redraw first so that it shows the initial conditions when first run for y in range(0, 7): for x in range(0, 17): scrollphathd.pixel(x, y, matrix[y, x]) @@ -200,7 +199,7 @@ def mainloop(): # ^ # a match! - # this is equivelant to the bitwise AND operation: + # this is equivialent to the bitwise AND operation: # 3&30 # see here : @@ -209,12 +208,12 @@ def mainloop(): # corresponding bit of x AND of y is 1, otherwise it's 0. # so, after all that we now know the state of this output cell. - # fortunately the algorithm is a lot shorter than the explaination ;) + # fortunately the algorithm is a lot shorter than the explanation ;) # construct our abc by bitshift and move a 1 to that index. o = 1 << ((a << 2) + (b << 1) + c) - # set the output cell to 1 if it &s with the rule, othewise 0 + # set the output cell to 1 if it &s with the rule, otherwise 0 outputRow[x] = 1 if o & rule else 0 # incrementally fill in the rows until we fill the last row diff --git a/examples/font-gallery.py b/examples/font-gallery.py index 97cae4d..f4342a7 100755 --- a/examples/font-gallery.py +++ b/examples/font-gallery.py @@ -3,7 +3,7 @@ import time import scrollphathd -from scrollphathd.fonts import fontd3, fontgauntlet, fontorgan, fonthachicro +from scrollphathd.fonts import fontd3, fontgauntlet, fonthachicro, fontorgan print(""" Scroll pHAT HD: Simple Scrolling diff --git a/examples/forest-fire.py b/examples/forest-fire.py index ed0176b..3ec47e4 100755 --- a/examples/forest-fire.py +++ b/examples/forest-fire.py @@ -13,7 +13,6 @@ import scrollphathd - print(""" Scroll pHAT HD: Forest Fire diff --git a/examples/gameoflife.py b/examples/gameoflife.py index 5f5cfb3..54c5fd6 100755 --- a/examples/gameoflife.py +++ b/examples/gameoflife.py @@ -1,8 +1,9 @@ #!/usr/bin/env python -import scrollphathd -import time import random +import time + +import scrollphathd YSIZE = 7 XSIZE = 17 diff --git a/examples/graph.py b/examples/graph.py index c939b63..b9a5584 100755 --- a/examples/graph.py +++ b/examples/graph.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -import time import random +import time import scrollphathd diff --git a/examples/hello-pigpiod.py b/examples/hello-pigpiod.py index 0408256..99faec9 100755 --- a/examples/hello-pigpiod.py +++ b/examples/hello-pigpiod.py @@ -3,6 +3,7 @@ import time import pigpio + import scrollphathd print(""" diff --git a/examples/hello-utf8.py b/examples/hello-utf8.py index 5d267fc..3fc1b0b 100755 --- a/examples/hello-utf8.py +++ b/examples/hello-utf8.py @@ -3,9 +3,10 @@ import time +from six import unichr + import scrollphathd from scrollphathd.fonts import font5x7 -from six import unichr print(""" Scroll pHAT HD: Hello utf-8 diff --git a/examples/mini/button-splash.py b/examples/mini/button-splash.py index e5037e9..fd594a2 100755 --- a/examples/mini/button-splash.py +++ b/examples/mini/button-splash.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -import time import math +import time + from gpiozero import Button import scrollphathd - print("""Unicorn HAT Mini: buttons.py Demonstrates the use of Unicorn HAT Mini's buttons with gpiozero. diff --git a/examples/mini/buttons.py b/examples/mini/buttons.py index 04c1aec..a79d4e7 100755 --- a/examples/mini/buttons.py +++ b/examples/mini/buttons.py @@ -1,8 +1,9 @@ #!/usr/bin/env python3 -from gpiozero import Button from signal import pause +from gpiozero import Button + print("""Scroll HAT Mini: buttons.py Demonstrates the use of Scroll HAT Mini's buttons with gpiozero. diff --git a/examples/mini/rockfall.py b/examples/mini/rockfall.py index f8e281e..6a538c3 100755 --- a/examples/mini/rockfall.py +++ b/examples/mini/rockfall.py @@ -4,11 +4,12 @@ """ import math -import scrollphathd import time +from random import random, shuffle from gpiozero import Button -from random import random, shuffle + +import scrollphathd # ------------------------------------------------------------ @@ -40,7 +41,7 @@ class Rockfall(): # How much to change the wait time by each tick WAIT_DIFF = 0.001 - # The min and max population fractions, and how much the butttons change + # The min and max population fractions, and how much the buttons change # it by MIN_FRAC = 1.0 / HEIGHT MAX_FRAC = 4.0 / HEIGHT @@ -174,7 +175,7 @@ def run(self): start = now last = now - # Wait for bit befor emoving on + # Wait for a bit before moving on time.sleep(0.05) # ---------------------------------------------------------------------- diff --git a/examples/mini/simon.py b/examples/mini/simon.py index f65f5c2..3cdd9d5 100755 --- a/examples/mini/simon.py +++ b/examples/mini/simon.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 -import time +import colorsys import math import random -import colorsys +import time from gpiozero import Button + import scrollphathd print("""Scroll HAT Mini: simon.py diff --git a/examples/openweather-temp-display.py b/examples/openweather-temp-display.py index d4caaad..adb4f0c 100755 --- a/examples/openweather-temp-display.py +++ b/examples/openweather-temp-display.py @@ -33,9 +33,9 @@ # Used to parse OpenWeather JSON data import json +import os # Returns time values import time -import os # Uncomment the below if your display is upside down # (e.g. if you're using it in a Pimoroni Scroll Bot) diff --git a/examples/plasma.py b/examples/plasma.py index 5434e82..6193e6c 100755 --- a/examples/plasma.py +++ b/examples/plasma.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -import time import math +import time import scrollphathd diff --git a/examples/robot-mouth.py b/examples/robot-mouth.py index a5fcbea..50c64d4 100755 --- a/examples/robot-mouth.py +++ b/examples/robot-mouth.py @@ -10,7 +10,6 @@ import scrollphathd - print(""" Scroll pHAT HD: Robot Mouth diff --git a/examples/swirl.py b/examples/swirl.py index df0654c..95741eb 100755 --- a/examples/swirl.py +++ b/examples/swirl.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -import time import math +import time import scrollphathd diff --git a/examples/tests/check-test.py b/examples/tests/check-test.py index 5b6edfc..c124f03 100755 --- a/examples/tests/check-test.py +++ b/examples/tests/check-test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -import time import math +import time import scrollphathd diff --git a/examples/tests/gamma-test.py b/examples/tests/gamma-test.py index 10b0635..36efb2e 100755 --- a/examples/tests/gamma-test.py +++ b/examples/tests/gamma-test.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import time + import scrollphathd DELAY = 0.0001 diff --git a/examples/tests/transform-test.py b/examples/tests/transform-test.py index e0dfaae..3b3cd6c 100755 --- a/examples/tests/transform-test.py +++ b/examples/tests/transform-test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -import time import argparse +import time import scrollphathd from scrollphathd.fonts import font3x5 diff --git a/examples/twitter-hashtag.py b/examples/twitter-hashtag.py index 84012ed..b1a069d 100755 --- a/examples/twitter-hashtag.py +++ b/examples/twitter-hashtag.py @@ -4,10 +4,12 @@ import time import unicodedata + try: import queue except ImportError: import Queue as queue + from sys import exit try: @@ -18,7 +20,6 @@ import scrollphathd from scrollphathd.fonts import font5x7 - # adjust the tracked keyword below to your keyword or #hashtag keyword = '#bilgetank' diff --git a/examples/web-api.py b/examples/web-api.py index d0a4e78..c9a94e2 100755 --- a/examples/web-api.py +++ b/examples/web-api.py @@ -1,8 +1,9 @@ #!/usr/bin/env python +from flask import Flask + import scrollphathd from scrollphathd.api.http import scrollphathd_blueprint from scrollphathd.fonts import font3x5 -from flask import Flask # Set the font scrollphathd.set_font(font3x5) diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..61f1a4a --- /dev/null +++ b/install.sh @@ -0,0 +1,385 @@ +#!/bin/bash +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") +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" +USAGE="./install.sh (--unstable)" +POSITIONAL_ARGS=() +FORCE=false +UNSTABLE=false +PYTHON="python" +CMD_ERRORS=false + + +user_check() { + if [ "$(id -u)" -eq 0 ]; then + fatal "Script should not be run as root. Try './install.sh'\n" + fi +} + +confirm() { + if $FORCE; then + true + else + read -r -p "$1 [y/N] " response < /dev/tty + if [[ $response =~ ^(yes|y|Y)$ ]]; then + true + else + false + fi + fi +} + +success() { + echo -e "$(tput setaf 2)$1$(tput sgr0)" +} + +inform() { + echo -e "$(tput setaf 6)$1$(tput sgr0)" +} + +warning() { + 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 + fatal "Could not find $CONFIG_FILE!" + fi + fi + inform "Using $CONFIG_FILE in $CONFIG_DIR" +} + +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! +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 \$VENV_DIR/bin/activate +EOF + fi +} + +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 and/or use a default one?"; then + printf "\n" + 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 + venv_bash_snippet + # shellcheck disable=SC1091 + source "$VENV_DIR/bin/activate" + else + inform "Activating existing virtual Python environment in $VENV_DIR\n" + printf "source \"%s/bin/activate\"\n" "$VENV_DIR" + # shellcheck disable=SC1091 + source "$VENV_DIR/bin/activate" + fi + else + 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 "^^^ 😬 previous command did not exit cleanly!" + fi +} + +function do_config_backup { + if [ ! $CONFIG_BACKUP == true ]; then + 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" + if [ -f "$UNINSTALLER" ]; then + echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG_DIR/$CONFIG_FILE" >> "$UNINSTALLER" + fi + fi +} + +function apt_pkg_install { + 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 %s\n" "$PACKAGE" + dpkg -L "$PACKAGE" > /dev/null 2>&1 + if [ "$?" == "1" ]; then + PACKAGES_NEEDED+=("$PACKAGE") + fi + done + PACKAGES="${PACKAGES_NEEDED[*]}" + if ! [ "$PACKAGES" == "" ]; then + printf "\n" + inform "Installing missing packages: $PACKAGES" + if [ ! $APT_HAS_UPDATED ]; then + sudo apt update + APT_HAS_UPDATED=true + fi + # shellcheck disable=SC2086 + sudo apt install -y $PACKAGES + check_for_error + if [ -f "$UNINSTALLER" ]; then + echo "apt uninstall -y $PACKAGES" >> "$UNINSTALLER" + fi + fi +} + +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 +} + +function pip_requirements_install { + # A null Keyring prevents pip stalling in the background + PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring $PYTHON -m pip install -r "$@" + check_for_error +} + +while [[ $# -gt 0 ]]; do + K="$1" + case $K in + -u|--unstable) + UNSTABLE=true + shift + ;; + -f|--force) + FORCE=true + shift + ;; + -p|--python) + PYTHON=$2 + shift + shift + ;; + *) + if [[ $1 == -* ]]; then + printf "Unrecognised option: %s\n" "$1"; + printf "Usage: %s\n" "$USAGE"; + exit 1 + fi + POSITIONAL_ARGS+=("$1") + shift + esac +done + +printf "Installing %s...\n\n" "$LIBRARY_NAME" + +user_check +venv_check + +if [ ! -f "$(which "$PYTHON")" ]; then + fatal "Python path %s not found!\n" "$PYTHON" +fi + +PYTHON_VER=$($PYTHON --version) + +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" +printf "an editor and remove 'exit 1' from below.\n" +exit 1 +source $VIRTUAL_ENV/bin/activate +EOF + +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 + +# 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" +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 + if [[ ! "$CMD" == printf* ]]; then + printf "Running: \"%s\"\n" "$CMD" + 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" + sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG_DIR/$CONFIG_FILE + if ! grep -q "^$CONFIG_LINE" $CONFIG_DIR/$CONFIG_FILE; then + printf "%s \n" "$CONFIG_LINE" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE + fi + 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" + cp -r examples/ "$RESOURCES_DIR" + echo "rm -r $RESOURCES_DIR" >> "$UNINSTALLER" + success "Done!" + fi +fi + +printf "\n" + +if [ -f "requirements-examples.txt" ]; then + if confirm "Would you like to install example dependencies?"; then + inform "Installing dependencies from requirements-examples.txt..." + pip_requirements_install requirements-examples.txt + fi +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 + inform "Generating documentation.\n" + if $PYTHON -m pdoc "$LIBRARY_NAME" -o "$RESOURCES_DIR/docs" > /dev/null; then + inform "Documentation saved to $RESOURCES_DIR/docs" + success "Done!" + else + warning "Error: Failed to generate documentation." + fi +fi + +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 %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 %s\n\n" "$UNINSTALLER" + +if [ "$CMD_ERRORS" = true ]; then + exit 1 +else + exit 0 +fi diff --git a/library/MANIFEST.in b/library/MANIFEST.in deleted file mode 100644 index 75b870e..0000000 --- a/library/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include CHANGELOG.txt -include LICENSE.txt -include README.rst -include setup.py -recursive-include scrollphathd *.py diff --git a/library/README.rst b/library/README.rst deleted file mode 100644 index a868f37..0000000 --- a/library/README.rst +++ /dev/null @@ -1,107 +0,0 @@ -|Scroll pHAT HD| https://shop.pimoroni.com/products/scroll-phat-hd - -17x7 pixels of single-colour, brightness-controlled, message scrolling -goodness! - -Installing ----------- - -Full install (recommended): -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We've created an easy installation script that will install all -pre-requisites and get your Scroll pHAT HD up and running with minimal -efforts. To run it, fire up Terminal which you'll find in Menu -> -Accessories -> Terminal on your Raspberry Pi desktop, as illustrated -below: - -.. figure:: http://get.pimoroni.com/resources/github-repo-terminal.png - :alt: Finding the terminal - -In the new terminal window type the command exactly as it appears below -(check for typos) and follow the on-screen instructions: - -.. code:: bash - - curl https://get.pimoroni.com/scrollphathd | bash - -Alternatively, on Raspbian, you can download the ``pimoroni-dashboard`` -and install your product by browsing to the relevant entry: - -.. code:: bash - - sudo apt-get install pimoroni - -(you will find the Dashboard under 'Accessories' too, in the Pi menu - -or just run ``pimoroni-dashboard`` at the command line) - -If you choose to download examples you'll find them in -``/home/pi/Pimoroni/scrollphathd/``. - -Manual install: -~~~~~~~~~~~~~~~ - -Library install for Python 3: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -on Raspbian: - -.. code:: bash - - sudo apt-get install python3-scrollphathd - -other environments: - -.. code:: bash - - sudo pip3 install scrollphathd - -Library install for Python 2: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -on Raspbian: - -.. code:: bash - - sudo apt-get install python-scrollphathd - -other environments: - -.. code:: bash - - sudo pip2 install scrollphathd - -Development: -~~~~~~~~~~~~ - -If you want to contribute, or like living on the edge of your seat by -having the latest code, you should clone this repository, ``cd`` to the -library directory, and run: - -.. code:: bash - - sudo python3 setup.py install - -(or ``sudo python setup.py install`` whichever your primary Python -environment may be) - -In all cases you will have to enable the i2c bus. - -Documentation & Support ------------------------ - -- Guides and tutorials - https://learn.pimoroni.com/scroll-phat-hd -- Function reference - http://docs.pimoroni.com/scrollphathd/ -- GPIO Pinout - https://pinout.xyz/pinout/scroll\_phat\_hd -- Get help - http://forums.pimoroni.com/c/support - -Unofficial / Third-party libraries ----------------------------------- - -- Java library by Jim Darby - https://github.com/hackerjimbo/PiJava -- Rust library by Tiziano Santoro - - https://github.com/tiziano88/scroll-phat-hd-rs -- Go library by Tom Mitchell - - https://github.com/tomnz/scroll-phat-hd-go - -.. |Scroll pHAT HD| image:: https://raw.githubusercontent.com/pimoroni/scroll-phat-hd/master/scroll-phat-hd-logo.png diff --git a/library/setup.py b/library/setup.py deleted file mode 100755 index e96ec2d..0000000 --- a/library/setup.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python - -""" -Copyright (c) 2017 Pimoroni - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -""" - -try: - from setuptools import setup -except ImportError: - from distutils.core import setup - -classifiers = ['Development Status :: 5 - Production/Stable', - 'Operating System :: POSIX :: Linux', - 'License :: OSI Approved :: MIT License', - 'Intended Audience :: Developers', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Topic :: Software Development', - 'Topic :: System :: Hardware'] - -setup( - name = 'scrollphathd', - version = '1.3.0', - author = 'Philip Howard', - author_email = 'phil@pimoroni.com', - description = 'Scroll pHAT HD Driver', - long_description= open('README.rst').read() + "\n" + open('CHANGELOG.txt').read(), - license = 'MIT', - keywords = 'Raspberry Pi LED', - url = 'http://www.pimoroni.com', - classifiers = classifiers, - py_modules = [], - packages = ['scrollphathd', 'scrollphathd.fonts'], - include_package_data = True, - install_requires= ['numpy', 'smbus2'] -) diff --git a/packaging/CHANGELOG b/packaging/CHANGELOG deleted file mode 100644 index 3f7bf9a..0000000 --- a/packaging/CHANGELOG +++ /dev/null @@ -1,65 +0,0 @@ -scrollphathd (1.2.1) stable; urgency=low - - * New: Exposed set_gamma method for user gamma correction - * Improvement: Removed web API import to prevent hard dependency on Flask - * Improvement: Many improvements to the HTTP API including autoscroll - * Optimisation: write_string will calculate string size and grow buffer once to fit - * Optimisation: set_graph will grow buffer to fit the graph - * Bugfix: Fixed ASCII font to place accented characters at correct codepoints - - -- Phil Howard Wed, 21 Mar 2018 00:00:00 +0000 - -scrollphathd (1.2.0) stable; urgency=low - - * New: Added set_font to set current font for all write_string calls - * New: Added before_display argument to show to modify the display buffer - - -- Phil Howard Mon, 12 Feb 2018 00:00:00 +0000 - -scrollphathd (1.1.1) stable; urgency=low - - * Bugfix: Removed Flask HTTP API entry_point to prevent bin file conflict between Python 2 and 3 - - -- Phil Howard Tue, 16 Jan 2018 00:00:00 +0000 - -scrollphathd (1.1.0) stable; urgency=low - - * New: Added Flask HTTP API - * New: Init is deferred until the library is used - - -- Phil Howard Thu, 11 Jan 2018 00:00:00 +0000 - -scrollphathd (1.0.1) stable; urgency=low - - * New: Added gamma correction - - -- Phil Howard Fri, 12 May 2017 00:00:00 +0000 - -scrollphathd (1.0.0) stable; urgency=low - - * New: Added set_brightness to globally set maximum display brightness - * New: Added get_buffer_shape to return internal buffer shape - * New: Added get_shape to return display shape - * New: Added set_clear_on_exit, pass True/False to set/clear - * Improvement: draw_char no longer fills black pixels, which was incongruent with letter spacing - * Improvement: '1' in font3x5 is now 3 pixels wide - * Improvement: Monospacing option for fonts - * Improvement: Fonts can now be indexed by char in addition to ordinal - * Improvement: Clear now resets scroll position - * Improvement: Fill now grows buffer and fills in single operations - * Improvement: scroll(0,0) no longer enforces a default scroll - * Improvement: width/height now private, reimplemented as read-only properties - * Improvement: initialization now detects disabled i2c or missing pHAT and emits a friendly error - * Improvement: cleared display sooner to mitigate flash of lit pixels on startup - * Bugfix: Corrected default scroll direction - * Bugfix: 90 and 270 degree rotations are no longer cropped to 7 pixels wide - * Bugfix: Fixed missing version_info - * Bugfix: Graph catches IndexError and gracefully ignores missing values - - -- Phil Howard Tue, 13 Mar 2017 00:00:00 +0000 - -scrollphathd (0.0.1) stable; urgency=low - - * Initial release - - -- Phil Howard Tue, 14 Feb 2017 00:00:00 +0000 diff --git a/packaging/debian/README b/packaging/debian/README deleted file mode 100644 index 6ddff08..0000000 --- a/packaging/debian/README +++ /dev/null @@ -1,12 +0,0 @@ -README - -Scroll pHAT HD provides a matrix of 119, brightness controlled, white LED pixels. It's ideal for writing messages, showing graphs, and drawing pictures. - -Learn more: https://shop.pimoroni.com/products/scroll-phat-hd -For examples run: `curl -sS get.pimoroni.com/scrollphathd | bash` - -IMPORTANT - -Scroll pHAT HD requires i2c. -To enable run `curl get.pimoroni.com/i2c | bash` -or use raspi-config and reboot your Raspberry Pi. diff --git a/packaging/debian/changelog b/packaging/debian/changelog deleted file mode 100644 index 3f7bf9a..0000000 --- a/packaging/debian/changelog +++ /dev/null @@ -1,65 +0,0 @@ -scrollphathd (1.2.1) stable; urgency=low - - * New: Exposed set_gamma method for user gamma correction - * Improvement: Removed web API import to prevent hard dependency on Flask - * Improvement: Many improvements to the HTTP API including autoscroll - * Optimisation: write_string will calculate string size and grow buffer once to fit - * Optimisation: set_graph will grow buffer to fit the graph - * Bugfix: Fixed ASCII font to place accented characters at correct codepoints - - -- Phil Howard Wed, 21 Mar 2018 00:00:00 +0000 - -scrollphathd (1.2.0) stable; urgency=low - - * New: Added set_font to set current font for all write_string calls - * New: Added before_display argument to show to modify the display buffer - - -- Phil Howard Mon, 12 Feb 2018 00:00:00 +0000 - -scrollphathd (1.1.1) stable; urgency=low - - * Bugfix: Removed Flask HTTP API entry_point to prevent bin file conflict between Python 2 and 3 - - -- Phil Howard Tue, 16 Jan 2018 00:00:00 +0000 - -scrollphathd (1.1.0) stable; urgency=low - - * New: Added Flask HTTP API - * New: Init is deferred until the library is used - - -- Phil Howard Thu, 11 Jan 2018 00:00:00 +0000 - -scrollphathd (1.0.1) stable; urgency=low - - * New: Added gamma correction - - -- Phil Howard Fri, 12 May 2017 00:00:00 +0000 - -scrollphathd (1.0.0) stable; urgency=low - - * New: Added set_brightness to globally set maximum display brightness - * New: Added get_buffer_shape to return internal buffer shape - * New: Added get_shape to return display shape - * New: Added set_clear_on_exit, pass True/False to set/clear - * Improvement: draw_char no longer fills black pixels, which was incongruent with letter spacing - * Improvement: '1' in font3x5 is now 3 pixels wide - * Improvement: Monospacing option for fonts - * Improvement: Fonts can now be indexed by char in addition to ordinal - * Improvement: Clear now resets scroll position - * Improvement: Fill now grows buffer and fills in single operations - * Improvement: scroll(0,0) no longer enforces a default scroll - * Improvement: width/height now private, reimplemented as read-only properties - * Improvement: initialization now detects disabled i2c or missing pHAT and emits a friendly error - * Improvement: cleared display sooner to mitigate flash of lit pixels on startup - * Bugfix: Corrected default scroll direction - * Bugfix: 90 and 270 degree rotations are no longer cropped to 7 pixels wide - * Bugfix: Fixed missing version_info - * Bugfix: Graph catches IndexError and gracefully ignores missing values - - -- Phil Howard Tue, 13 Mar 2017 00:00:00 +0000 - -scrollphathd (0.0.1) stable; urgency=low - - * Initial release - - -- Phil Howard Tue, 14 Feb 2017 00:00:00 +0000 diff --git a/packaging/debian/clean b/packaging/debian/clean deleted file mode 100644 index 45149aa..0000000 --- a/packaging/debian/clean +++ /dev/null @@ -1 +0,0 @@ -*.egg-info/* diff --git a/packaging/debian/compat b/packaging/debian/compat deleted file mode 100644 index ec63514..0000000 --- a/packaging/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/packaging/debian/control b/packaging/debian/control deleted file mode 100644 index f7017c9..0000000 --- a/packaging/debian/control +++ /dev/null @@ -1,33 +0,0 @@ -Source: scrollphathd -Maintainer: Phil Howard -Homepage: https://github.com/pimoroni/scroll-phat-hd -Section: python -Priority: extra -Build-Depends: debhelper (>= 9.0.0), dh-python, python-all (>= 2.7), python-setuptools, python3-all (>= 3.4), python3-setuptools -Standards-Version: 3.9.6 -X-Python-Version: >= 2.7 -X-Python3-Version: >= 3.4 - -Package: python-scrollphathd -Architecture: all -Section: python -Depends: ${misc:Depends}, ${python:Depends}, python-smbus, python-numpy -Suggests: i2c-tools, python-psutil -Description: Python library for the Pimoroni Scroll pHAT HD. - Scroll pHAT HD provides a matrix of 119, brightness controlled, - white LED pixels. - It's ideal for writing messages, showing graphs, and drawing pictures. - . - This is the Python 2 version of the package. - -Package: python3-scrollphathd -Architecture: all -Section: python -Depends: ${misc:Depends}, ${python3:Depends}, python3-smbus, python3-numpy -Suggests: i2c-tools, python3-psutil -Description: Python library for the Pimoroni Scroll pHAT HD. - Scroll pHAT HD provides a matrix of 119, brightness controlled, - white LED pixels. - It's ideal for writing messages, showing graphs, and drawing pictures. - . - This is the Python 3 version of the package. diff --git a/packaging/debian/copyright b/packaging/debian/copyright deleted file mode 100644 index c40ece9..0000000 --- a/packaging/debian/copyright +++ /dev/null @@ -1,26 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: scrollphathd -Source: https://github.com/pimoroni/scroll-phat-hd - -Files: * -Copyright: 2017 Pimoroni Ltd -License: MIT - -License: MIT - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - . - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. diff --git a/packaging/debian/rules b/packaging/debian/rules deleted file mode 100755 index 98b408c..0000000 --- a/packaging/debian/rules +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- - -#export DH_VERBOSE=1 -export DH_OPTIONS - -%: - dh $@ --with python2,python3 --buildsystem=python_distutils - -override_dh_auto_install: - python setup.py install --root debian/python-scrollphathd --install-layout=deb - python3 setup.py install --root debian/python3-scrollphathd --install-layout=deb diff --git a/packaging/debian/source/format b/packaging/debian/source/format deleted file mode 100644 index 89ae9db..0000000 --- a/packaging/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (native) diff --git a/packaging/debian/source/options b/packaging/debian/source/options deleted file mode 100644 index 8f82c91..0000000 --- a/packaging/debian/source/options +++ /dev/null @@ -1 +0,0 @@ -extend-diff-ignore = "^[^/]+\.egg-info/" diff --git a/packaging/makeall.sh b/packaging/makeall.sh deleted file mode 100755 index abca395..0000000 --- a/packaging/makeall.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/bash - -# script control variables - -reponame="" # leave this blank for auto-detection -libname="" # leave this blank for auto-detection -packagename="" # leave this blank for auto-selection - -debianlog="debian/changelog" -debcontrol="debian/control" -debcopyright="debian/copyright" -debrules="debian/rules" -debreadme="debian/README" - -debdir="$(pwd)" -rootdir="$(dirname $debdir)" -libdir="$rootdir/library" - -FLAG=false - -# function define - -success() { - echo "$(tput setaf 2)$1$(tput sgr0)" -} - -inform() { - echo "$(tput setaf 6)$1$(tput sgr0)" -} - -warning() { - echo "$(tput setaf 1)$1$(tput sgr0)" -} - -newline() { - echo "" -} - -# assessing repo and library variables - -if [ -z "$reponame" ] || [ -z "$libname" ]; then - inform "detecting reponame and libname..." -else - inform "using reponame and libname overrides" -fi - -if [ -z "$reponame" ]; then - if [[ $rootdir == *"python"* ]]; then - repodir="$(dirname $rootdir)" - reponame="$(basename $repodir)" - else - repodir="$rootdir" - reponame="$(basename $repodir)" - fi - reponame=$(echo "$reponame" | tr "[A-Z]" "[a-z]") -fi - -if [ -z "$libname" ]; then - cd "$libdir" - libname=$(grep "name" setup.py | tr -d "[:space:]" | cut -c 7- | rev | cut -c 3- | rev) - libname=$(echo "$libname" | tr "[A-Z]" "[a-z]") && cd "$debdir" -fi - -if [ -z "$packagename" ]; then - packagename="$libname" -fi - -echo "reponame is $reponame and libname is $libname" -echo "output packages will be python-$packagename and python3-$packagename" - -# checking generating changelog file - -./makelog.sh -version=$(head -n 1 "$libdir/CHANGELOG.txt") -echo "building $libname version $version" - -# checking debian/changelog file - -inform "checking debian/changelog file..." - -if ! head -n 1 $debianlog | grep "$libname" &> /dev/null; then - warning "library not mentioned in header!" && FLAG=true -elif head -n 1 $debianlog | grep "UNRELEASED"; then - warning "this changelog is not going to generate a release!" - warning "change distribution to 'stable'" && FLAG=true -fi - -# checking debian/copyright file - -inform "checking debian/copyright file..." - -if ! grep "^Source" $debcopyright | grep "$reponame" &> /dev/null; then - warning "$(grep "^Source" $debcopyright)" && FLAG=true -fi - -if ! grep "^Upstream-Name" $debcopyright | grep "$libname" &> /dev/null; then - warning "$(grep "^Upstream-Name" $debcopyright)" && FLAG=true -fi - -# checking debian/control file - -inform "checking debian/control file..." - -if ! grep "^Source" $debcontrol | grep "$libname" &> /dev/null; then - warning "$(grep "^Source" $debcontrol)" && FLAG=true -fi - -if ! grep "^Homepage" $debcontrol | grep "$reponame" &> /dev/null; then - warning "$(grep "^Homepage" $debcontrol)" && FLAG=true -fi - -if ! grep "^Package: python-$packagename" $debcontrol &> /dev/null; then - warning "$(grep "^Package: python-" $debcontrol)" && FLAG=true -fi - -if ! grep "^Package: python3-$packagename" $debcontrol &> /dev/null; then - warning "$(grep "^Package: python3-" $debcontrol)" && FLAG=true -fi - -if ! grep "^Priority: extra" $debcontrol &> /dev/null; then - warning "$(grep "^Priority" $debcontrol)" && FLAG=true -fi - - -# checking debian/rules file - -inform "checking debian/rules file..." - -if ! grep "debian/python-$packagename" $debrules &> /dev/null; then - warning "$(grep "debian/python-" $debrules)" && FLAG=true -fi - -if ! grep "debian/python3-$packagename" $debrules &> /dev/null; then - warning "$(grep "debian/python3-" $debrules)" && FLAG=true -fi - -# checking debian/README file - -inform "checking debian/readme file..." - -if ! grep -e "$libname" -e "$reponame" $debreadme &> /dev/null; then - warning "README does not seem to mention product, repo or lib!" && FLAG=true -fi - -# summary of checks pre build - -if $FLAG; then - warning "Check all of the above and correct!" && exit 1 -else - inform "we're good to go... bulding!" -fi - -# building deb and final checks - -./makedeb.sh - -inform "running lintian..." -lintian -v $(find -name "python*$version*.deb") -lintian -v $(find -name "python3*$version*.deb") - -inform "checking signatures..." -gpg --verify $(find -name "*$version*changes") -gpg --verify $(find -name "*$version*dsc") - -exit 0 diff --git a/packaging/makedeb.sh b/packaging/makedeb.sh deleted file mode 100755 index 03ebac7..0000000 --- a/packaging/makedeb.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -gettools="no" # if set to yes downloads the tools required -setup="yes" # if set to yes populates library folder -buildeb="yes" # if set to yes builds the deb files -cleanup="yes" # if set to yes cleans up build files -pkgfiles=( "build" "changes" "deb" "dsc" "tar.xz" ) - -if [ $gettools == "yes" ]; then - sudo apt-get update && sudo apt-get install build-essential debhelper devscripts dh-make dh-python dput gnupg - sudo apt-get install python-all python-setuptools python3-all python3-setuptools - sudo apt-get install python-mock python-sphinx python-sphinx-rtd-theme - sudo pip install Sphinx --upgrade && sudo pip install sphinx_rtd_theme --upgrade -fi - -if [ $setup == "yes" ]; then - rm -R ../library/build ../library/debian &> /dev/null - cp -R ./debian ../library/ && cp -R ../sphinx ../library/doc -fi - -cd ../library - -if [ $buildeb == "yes" ]; then - debuild -aarmhf - for file in ${pkgfiles[@]}; do - rm ../packaging/*.$file &> /dev/null - mv ../*.$file ../packaging - done - rm -R ../documentation/html &> /dev/null - cp -R ./build/sphinx/html ../documentation -fi - -if [ $cleanup == "yes" ]; then - debuild clean - rm -R ./build ./debian ./doc &> /dev/null -fi - -exit 0 diff --git a/packaging/makedoc.sh b/packaging/makedoc.sh deleted file mode 100755 index 244e992..0000000 --- a/packaging/makedoc.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -gettools="no" # if set to yes downloads the tools required -setup="yes" # if set to yes populates library folder -buildoc="yes" # if set to yes builds the deb files -cleanup="yes" # if set to yes cleans up build files -pkgfiles=( "build" "changes" "deb" "dsc" "tar.xz" ) - -if [ $gettools == "yes" ]; then - sudo apt-get update && sudo apt-get install build-essential debhelper devscripts dh-make dh-python - sudo apt-get install python-all python-setuptools python3-all python3-setuptools - sudo apt-get install python-mock python-sphinx python-sphinx-rtd-theme - sudo pip install Sphinx --upgrade && sudo pip install sphinx_rtd_theme --upgrade -fi - -if [ $setup == "yes" ]; then - rm -R ../library/build ../library/debian &> /dev/null - cp -R ./debian ../library/ && cp -R ../sphinx ../library/doc -fi - -cd ../library - -if [ $buildoc == "yes" ]; then - debuild - for file in ${pkgfiles[@]}; do - rm ../*.$file &> /dev/null - done - rm -R ../documentation/html &> /dev/null - cp -R ./build/sphinx/html ../documentation -fi - -if [ $cleanup == "yes" ]; then - debuild clean - rm -R ./build ./debian ./doc &> /dev/null -fi - -exit 0 diff --git a/packaging/makelog.sh b/packaging/makelog.sh deleted file mode 100755 index 1055987..0000000 --- a/packaging/makelog.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -# script control variables - -libname="" # leave this blank for auto-detection -sibname=() # name of sibling in packages list -versionwarn="yes" # set to anything but 'yes' to turn off warning - -debdir="$(pwd)" -rootdir="$(dirname $debdir)" -libdir="$rootdir/library" - -mainlog="CHANGELOG" -debianlog="debian/changelog" -pypilog="$libdir/CHANGELOG.txt" - -# function define - -success() { - echo "$(tput setaf 2)$1$(tput sgr0)" -} - -inform() { - echo "$(tput setaf 6)$1$(tput sgr0)" -} - -warning() { - echo "$(tput setaf 1)$1$(tput sgr0)" -} - -newline() { - echo "" -} - -# generate debian changelog - -cat $mainlog > $debianlog -inform "seeded debian changelog" - -# generate pypi changelog - -sed -e "/--/d" -e "s/ \*/\*/" \ - -e "s/.*\([0-9].[0-9].[0-9]\).*/\1/" \ - -e '/[0-9].[0-9].[0-9]/ a\ ------' $mainlog | cat -s > $pypilog - -version=$(head -n 1 $pypilog) -inform "pypi changelog generated" - -# touch up version in setup.py file - -if [ -n $(grep version "$libdir/setup.py" &> /dev/null) ]; then - inform "touched up version in setup.py" - sed -i "s/'[0-9].[0-9].[0-9]'/'$version'/" "$libdir/setup.py" -else - warning "couldn't touch up version in setup, no match found" -fi - -# touch up version in lib or package siblings - -if [ -z "$libname" ]; then - cd "$libdir" - libname=$(grep "name" setup.py | tr -d "[:space:]" | cut -c 7- | rev | cut -c 3- | rev) - libname=$(echo "$libname" | tr "[A-Z]" "[a-z]") && cd "$debdir" - sibname+=( "$libname" ) -elif [ "$libname" != "package" ]; then - sibname+=( "$libname" ) -fi - -for sibling in ${sibname[@]}; do - if grep -e "__version__" "$libdir/$sibling.py" &> /dev/null; then - sed -i "s/__version__ = '[0-9].[0-9].[0-9]'/__version__ = '$version'/" "$libdir/$sibling.py" - inform "touched up version in $sibling.py" - elif grep -e "__version__" "$libdir/$sibling/__init__.py" &> /dev/null; then - sed -i "s/__version__ = '[0-9].[0-9].[0-9]'/__version__ = '$version'/" "$libdir/$sibling/__init__.py" - inform "touched up version in $sibling/__init__.py" - elif [ "$versionwarn" == "yes" ]; then - warning "couldn't touch up __version__ in $sibling, no match found" - fi -done - -exit 0 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d62bb43 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,121 @@ +[build-system] +requires = ["hatchling", "hatch-fancy-pypi-readme", "hatch-requirements-txt"] +build-backend = "hatchling.build" + +[project] +name = "scrollphathd" +dynamic = ["version", "readme", "optional-dependencies"] +description = "Scroll pHAT HD Driver" +license = {file = "LICENSE"} +requires-python = ">= 3.7" +authors = [ + { name = "Philip Howard", email = "phil@pimoroni.com" }, +] +maintainers = [ + { name = "Philip Howard", email = "phil@pimoroni.com" }, +] +keywords = [ + "Pi", + "Raspberry", +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Software Development", + "Topic :: Software Development :: Libraries", + "Topic :: System :: Hardware", +] +dependencies = [ + "numpy", + "smbus2" +] + +[tool.hatch.metadata.hooks.requirements_txt.optional-dependencies] +example-depends = ["requirements-examples.txt"] + +[project.urls] +GitHub = "https://www.github.com/pimoroni/scroll-phat-hd" +Homepage = "https://www.pimoroni.com" + +[tool.hatch.version] +path = "scrollphathd/__init__.py" + +[tool.hatch.build] +include = [ + "scrollphathd", + "README.md", + "CHANGELOG.md", + "LICENSE", + "requirements-examples.txt" +] + +[tool.hatch.build.targets.sdist] +include = [ + "*" +] +exclude = [ + ".*", + "dist" +] + +[tool.hatch.metadata.hooks.fancy-pypi-readme] +content-type = "text/markdown" +fragments = [ + { path = "README.md" }, + { text = "\n" }, + { path = "CHANGELOG.md" } +] + +[tool.ruff] +exclude = [ + '.tox', + '.egg', + '.git', + '__pycache__', + 'build', + 'dist' +] +line-length = 200 + +[tool.codespell] +skip = """ +./.tox,\ +./.egg,\ +./.git,\ +./__pycache__,\ +./build,\ +./dist.\ +""" +ignore-words-list = """Ehr""" + +[tool.isort] +line_length = 200 + +[tool.check-manifest] +ignore = [ + '.stickler.yml', + 'boilerplate.md', + 'check.sh', + 'install.sh', + 'uninstall.sh', + 'Makefile', + 'tox.ini', + 'tests/*', + 'examples/*', + '.coveragerc', + 'requirements-dev.txt' +] + +[tool.pimoroni] +apt_packages = [] +configtxt = [] +commands = [] diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..d392e8f --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,10 @@ +check-manifest +ruff +codespell +isort +twine +hatch +hatch-fancy-pypi-readme +hatch-requirements-txt +tox +pdoc diff --git a/library/scrollphathd/fonts/__init__.py b/requirements-examples.txt similarity index 100% rename from library/scrollphathd/fonts/__init__.py rename to requirements-examples.txt diff --git a/library/scrollphathd/__init__.py b/scrollphathd/__init__.py similarity index 99% rename from library/scrollphathd/__init__.py rename to scrollphathd/__init__.py index fc123a0..8755a40 100644 --- a/library/scrollphathd/__init__.py +++ b/scrollphathd/__init__.py @@ -1,8 +1,10 @@ """Python library for the Pimoroni Scroll pHAT HD 17x7 pixel LED display.""" import atexit + +import numpy + from . import is31fl3731 from .fonts import font5x7 -import numpy __version__ = '1.3.0' @@ -446,7 +448,7 @@ def write_string(string, x=0, y=0, font=None, letter_spacing=1, brightness=1.0, :param x: Offset x - distance of string from left of the buffer :param y: Offset y - distance of string from right of the buffer :param letter_spacing: Distance (in pixels) between characters - :param font: Font to use, defualt is to use the one specified with `set_font` + :param font: Font to use, default is to use the one specified with `set_font` :param brightness: Brightness of the pixels that comprise the text, from 0.0 to 1.0 :param monospaced: Whether to space characters evenly using `font.width` :param fill_background: Not used @@ -515,7 +517,7 @@ def clear_rect(x, y, width, height): :param x: Offset x - distance from left of buffer :param y: Offset y - distance from top of buffer :param width: Width of area (default is 17) - :param height: Heigh of area (default is 7) + :param height: Height of area (default is 7) """ fill(0, x, y, width, height) diff --git a/library/scrollphathd/api/__init__.py b/scrollphathd/api/__init__.py similarity index 100% rename from library/scrollphathd/api/__init__.py rename to scrollphathd/api/__init__.py diff --git a/library/scrollphathd/api/action.py b/scrollphathd/api/action.py similarity index 100% rename from library/scrollphathd/api/action.py rename to scrollphathd/api/action.py diff --git a/library/scrollphathd/api/http.py b/scrollphathd/api/http.py similarity index 97% rename from library/scrollphathd/api/http.py rename to scrollphathd/api/http.py index 0d67d6b..e45e2fd 100644 --- a/library/scrollphathd/api/http.py +++ b/scrollphathd/api/http.py @@ -1,13 +1,12 @@ -import scrollphathd - import threading - from argparse import ArgumentParser +import scrollphathd + try: - from queue import Queue, Empty + from queue import Queue except ImportError: - from Queue import Queue, Empty + from Queue import Queue from .action import Action from .stoppablethread import StoppableThread @@ -17,7 +16,7 @@ except ImportError: import httplib as http_status -from flask import Blueprint, render_template, abort, request, jsonify, Flask +from flask import Blueprint, Flask, jsonify, request scrollphathd_blueprint = Blueprint('scrollhat', __name__) api_queue = Queue() @@ -48,7 +47,7 @@ def run(self): @scrollphathd_blueprint.route('/autoscroll', methods=["POST"]) -def autoscroll(): +def autoscroll_(): response = {"result": "success"} status_code = http_status.OK diff --git a/library/scrollphathd/api/stoppablethread.py b/scrollphathd/api/stoppablethread.py similarity index 99% rename from library/scrollphathd/api/stoppablethread.py rename to scrollphathd/api/stoppablethread.py index 83bc376..2582ca5 100644 --- a/library/scrollphathd/api/stoppablethread.py +++ b/scrollphathd/api/stoppablethread.py @@ -1,5 +1,6 @@ import threading + class StoppableThread(threading.Thread): """Basic Stoppable Thread Wrapper Adds event for stopping the execution diff --git a/packaging/debian/docs b/scrollphathd/fonts/__init__.py similarity index 100% rename from packaging/debian/docs rename to scrollphathd/fonts/__init__.py diff --git a/library/scrollphathd/fonts/font3x5.py b/scrollphathd/fonts/font3x5.py similarity index 100% rename from library/scrollphathd/fonts/font3x5.py rename to scrollphathd/fonts/font3x5.py diff --git a/library/scrollphathd/fonts/font5x5.py b/scrollphathd/fonts/font5x5.py similarity index 100% rename from library/scrollphathd/fonts/font5x5.py rename to scrollphathd/fonts/font5x5.py diff --git a/library/scrollphathd/fonts/font5x7.py b/scrollphathd/fonts/font5x7.py similarity index 100% rename from library/scrollphathd/fonts/font5x7.py rename to scrollphathd/fonts/font5x7.py diff --git a/library/scrollphathd/fonts/font5x7smoothed.py b/scrollphathd/fonts/font5x7smoothed.py similarity index 100% rename from library/scrollphathd/fonts/font5x7smoothed.py rename to scrollphathd/fonts/font5x7smoothed.py diff --git a/library/scrollphathd/fonts/font5x7unicode.py b/scrollphathd/fonts/font5x7unicode.py similarity index 100% rename from library/scrollphathd/fonts/font5x7unicode.py rename to scrollphathd/fonts/font5x7unicode.py diff --git a/library/scrollphathd/fonts/fontd3.py b/scrollphathd/fonts/fontd3.py similarity index 100% rename from library/scrollphathd/fonts/fontd3.py rename to scrollphathd/fonts/fontd3.py diff --git a/library/scrollphathd/fonts/fontgauntlet.py b/scrollphathd/fonts/fontgauntlet.py similarity index 100% rename from library/scrollphathd/fonts/fontgauntlet.py rename to scrollphathd/fonts/fontgauntlet.py diff --git a/library/scrollphathd/fonts/fonthachicro.py b/scrollphathd/fonts/fonthachicro.py similarity index 100% rename from library/scrollphathd/fonts/fonthachicro.py rename to scrollphathd/fonts/fonthachicro.py diff --git a/library/scrollphathd/fonts/fontorgan.py b/scrollphathd/fonts/fontorgan.py similarity index 100% rename from library/scrollphathd/fonts/fontorgan.py rename to scrollphathd/fonts/fontorgan.py diff --git a/library/scrollphathd/is31fl3731.py b/scrollphathd/is31fl3731.py similarity index 95% rename from library/scrollphathd/is31fl3731.py rename to scrollphathd/is31fl3731.py index 246bb2a..9a5c09a 100644 --- a/library/scrollphathd/is31fl3731.py +++ b/scrollphathd/is31fl3731.py @@ -52,7 +52,7 @@ def __init__(self, i2c=None, address=0x74): import smbus2 self.i2c = smbus2.SMBus(1) except ImportError as e: - raise ImportError('You must supply an i2c device or install the smbus2 library.') + raise ImportError('You must supply an i2c device or install the smbus2 library.') from e except IOError as e: if hasattr(e, 'errno') and e.errno == 2: e.strerror += "\n\nMake sure you've enabled i2c in your Raspberry Pi configuration.\n" @@ -163,7 +163,7 @@ def _i2c_read(self, register, bank=None): self.set_bank(bank) return self.i2c.read_byte_data(self.address, register) - def _chunk(self, l, n): - """Split a list of values in to chunks of length n.""" - for i in range(0, len(l) + 1, n): - yield l[i:i + n] + def _chunk(self, data, length): + """Split a list of values into chunks of a given length.""" + for i in range(0, len(data) + 1, length): + yield data[i:i + length] diff --git a/simulator/scroll_phat_simulator.py b/simulator/scroll_phat_simulator.py index aa90084..daef1d7 100644 --- a/simulator/scroll_phat_simulator.py +++ b/simulator/scroll_phat_simulator.py @@ -1,8 +1,8 @@ -import threading -import sys import pickle -import tkinter as tk import signal +import sys +import threading +import tkinter as tk ROWS = 7 COLUMNS = 17 diff --git a/simulator/smbus2.py b/simulator/smbus2.py index 69a39a4..1735cde 100644 --- a/simulator/smbus2.py +++ b/simulator/smbus2.py @@ -1,7 +1,7 @@ -import sys -import subprocess -import pickle import os +import pickle +import subprocess +import sys class SMBus: diff --git a/sphinx/_static/custom.css b/sphinx/_static/custom.css deleted file mode 100644 index 141c20c..0000000 --- a/sphinx/_static/custom.css +++ /dev/null @@ -1,53 +0,0 @@ -.rst-content a, .rst-content a:focus { - color:#13c0d7; -} -.rst-content a:visited, .rst-content a:active { - color:#87319a; -} -.rst-content .highlighted { - background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAJElEQVQIW2P8//9/PSMjYyMDEmAEsdElwILoEnBBZAkUQZgEABMWE4Kzp1KUAAAAAElFTkSuQmCC),rgba(246,167,4,0.2); - margin:0 -6px; -} -.wy-side-nav-search { - background:#333333; -} -.wy-nav-side { - background:#444444; -} -.wy-menu-vertical a { - color:#cccccc -} -.wy-menu-vertical p.caption { - background: #333333; - color: #6d6d6d; -} -.rst-content dl:not(.docutils) dt { - background:#e7fafd; - border-top:solid 3px #13c0d7; - color:rgba(0,0,0,0.5); -} -.rst-content .viewcode-link, .rst-content .viewcode-back { - color:#00b09b; -} -code.literal { - color:#e63c2e; -} - - -.rst-content #at-a-glance { - margin-bottom:24px; -} -.rst-content #at-a-glance blockquote { - margin-left:0; -} -.rst-content #at-a-glance dl:not(.docutils) dt { - border:none; - background:#f0f0f0; -} -.rst-content #at-a-glance dl:not(.docutils) dd, -.rst-content #at-a-glance dl:not(.docutils) dd dl:not(.docutils) dd { - display:none; -} -.rst-content #at-a-glance dl:not(.docutils) { - margin-bottom:0; -} diff --git a/sphinx/_templates/breadcrumbs.html b/sphinx/_templates/breadcrumbs.html deleted file mode 100644 index e69de29..0000000 diff --git a/sphinx/_templates/layout.html b/sphinx/_templates/layout.html deleted file mode 100644 index a2bd1c5..0000000 --- a/sphinx/_templates/layout.html +++ /dev/null @@ -1,43 +0,0 @@ -{% extends "!layout.html" %} -{% block extrahead %} - -{% endblock %} -{% block footer %} - -{% endblock %} \ No newline at end of file diff --git a/sphinx/conf.py b/sphinx/conf.py deleted file mode 100644 index 425c9be..0000000 --- a/sphinx/conf.py +++ /dev/null @@ -1,416 +0,0 @@ -#-*- coding: utf-8 -*- - -import sys -import mock - -PACKAGE_NAME = u"Scroll pHAT HD" -PACKAGE_HANDLE = "ScrollpHATHD" -PACKAGE_MODULE = "scrollphathd" - -import sphinx_rtd_theme - -MOCK_MODULES = ['smbus', 'numpy'] -for module_name in MOCK_MODULES: - sys.modules[module_name] = mock.MagicMock() - -sys.path.insert(0, '../library/') - - -import scrollphathd - -from sphinx.ext import autodoc - - -class OutlineClassDocumenter(autodoc.ClassDocumenter): - objtype = 'class' - - def add_content(self, more_content, no_docstring=False): - return - - -class OutlineMethodDocumenter(autodoc.MethodDocumenter): - objtype = 'method' - - def add_content(self, more_content, no_docstring=False): - return - - def add_directive_header(self, sig): - if self.objpath[0] == u"Matrix": - self.objpath[0] = u'scrollphathd' - autodoc.MethodDocumenter.add_directive_header(self, sig) - - -class OutlineFunctionDocumenter(autodoc.FunctionDocumenter): - objtype = 'function' - - def add_content(self, more_content, no_docstring=False): - return - - def add_directive_header(self, sig): - if self.objpath[0] == u"Matrix": - self.objpath[0] = u'scrollphathd' - autodoc.FunctionDocumenter.add_directive_header(self, sig) - - -class MethodDocumenter(autodoc.MethodDocumenter): - objtype = 'method' - - def add_directive_header(self, sig): - if self.objpath[0] == u"Matrix": - self.objpath[0] = u'scrollphathd' - autodoc.MethodDocumenter.add_directive_header(self, sig) - - -class ModuleOutlineDocumenter(autodoc.ModuleDocumenter): - objtype = 'moduleoutline' - - def add_directive_header(self, sig): - pass # Squash directive header for At A Glance view - - def __init__(self, directive, name, indent=u''): - # Monkey patch the Method and Function documenters - sphinx_app.add_autodocumenter(OutlineMethodDocumenter) - # sphinx_app.add_autodocumenter(OutlineClassDocumenter) - sphinx_app.add_autodocumenter(OutlineFunctionDocumenter) - autodoc.ModuleDocumenter.__init__(self, directive, name, indent) - - def __del__(self): - # Return the Method and Function documenters to normal - # sphinx_app.add_autodocumenter(autodoc.ClassDocumenter) - sphinx_app.add_autodocumenter(MethodDocumenter) - sphinx_app.add_autodocumenter(autodoc.FunctionDocumenter) - - -def setup(app): - global sphinx_app - sphinx_app = app - app.add_autodocumenter(ModuleOutlineDocumenter) - app.add_autodocumenter(MethodDocumenter) - ModuleOutlineDocumenter.objtype = 'module' - - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.viewcode', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The encoding of source files. -# -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = PACKAGE_NAME -copyright = u'2017, Pimoroni Ltd' -author = u'Phil Howard' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = u'{}'.format(scrollphathd.__version__) -# The full version, including alpha/beta/rc tags. -release = u'{}'.format(scrollphathd.__version__) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# -# today = '' -# -# Else, today_fmt is used as the format for a strftime call. -# -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_rtd_theme' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -html_theme_options = { - 'collapse_navigation': False, - 'display_version': True -} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = [ - '_themes', - sphinx_rtd_theme.get_html_theme_path() -] - -# The name for this set of Sphinx documents. -# " v documentation" by default. -# -# html_title = PACKAGE_NAME + u' v0.1.2' - -# A shorter title for the navigation bar. Default is the same as html_title. -# -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# -html_logo = 'shop-logo.png' - -# The name of an image file (relative to this directory) to use as a favicon of -# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# -html_favicon = 'favicon.png' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# -# html_extra_path = [] - -# If not None, a 'Last updated on:' timestamp is inserted at every page -# bottom, using the given strftime format. -# The empty string is equivalent to '%b %d, %Y'. -# -# html_last_updated_fmt = None - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# -# html_additional_pages = {} - -# If false, no module index is generated. -# -# html_domain_indices = True - -# If false, no index is generated. -# -html_use_index = False - -# If true, the index is split into individual pages for each letter. -# -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# -html_show_sourcelink = False - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# -html_show_sphinx = False - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' -# -# html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# 'ja' uses this config value. -# 'zh' user can custom change `jieba` dictionary path. -# -# html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -# -# html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = PACKAGE_HANDLE + 'doc' - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, PACKAGE_HANDLE + '.tex', PACKAGE_NAME + u' Documentation', - u'Phil Howard', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# -# latex_use_parts = False - -# If true, show page references after internal links. -# -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# -# latex_appendices = [] - -# It false, will not define \strong, \code, itleref, \crossref ... but only -# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added -# packages. -# -# latex_keep_old_macro_names = True - -# If false, no module index is generated. -# -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, PACKAGE_MODULE, PACKAGE_NAME + u' Documentation', - [author], 1) -] - -# If true, show URL addresses after external links. -# -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, PACKAGE_HANDLE, PACKAGE_NAME + u' Documentation', - author, PACKAGE_HANDLE, 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# -# texinfo_appendices = [] - -# If false, no module index is generated. -# -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# -# texinfo_no_detailmenu = False diff --git a/sphinx/favicon.png b/sphinx/favicon.png deleted file mode 100644 index 5ed0316..0000000 Binary files a/sphinx/favicon.png and /dev/null differ diff --git a/sphinx/index.rst b/sphinx/index.rst deleted file mode 100644 index 1559b5d..0000000 --- a/sphinx/index.rst +++ /dev/null @@ -1,118 +0,0 @@ -.. role:: python(code) - :language: python - -Welcome -------- - -This documentation will guide you through the methods available in the Scroll pHAT HD python library. - -Scroll pHAT provides a matrix of 119 individually brightness controlled white LED pixels that is ideal for writing messages, showing graphs, and drawing pictures. Use it to output your IP address, show CPU usage, or just play pong! - -* More information - https://shop.pimoroni.com/products/scroll-phat-hd -* Get the code - https://github.com/pimoroni/scroll-phat-hd -* GPIO pinout - https://pinout.xyz/pinout/scroll_phat_hd -* Soldering - https://learn.pimoroni.com/tutorial/sandyj/soldering-phats -* Get help - http://forums.pimoroni.com/c/support - -.. currentmodule:: scrollphathd - -At A Glance ------------ - -.. automoduleoutline:: scrollphathd - :members: - -.. toctree:: - :titlesonly: - :maxdepth: 0 - -Set A Single Pixel In Buffer ----------------------------- - -Scroll pHAT HD uses white LEDs which can be brightness controlled. - -When you set a pixel it will not immediately display on Scroll pHAT HD, you must call :python:`scrollphathd.show()`. - -.. autofunction:: scrollphathd.set_pixel - :noindex: - -Write A Text String -------------------- - -.. autofunction:: scrollphathd.write_string - :noindex: - -Draw A Single Char ------------------- - -.. autofunction:: scrollphathd.draw_char - :noindex: - -Display A Graph ---------------- - -.. autofunction:: scrollphathd.set_graph - :noindex: - -Fill An Area ------------- - -.. autofunction:: scrollphathd.fill - :noindex: - -Clear An Area -------------- - -.. autofunction:: scrollphathd.clear_rect - :noindex: - -Display Buffer --------------- - -All of your changes to Scroll pHAT HD are stored in a Python buffer. To display them -on Scroll pHAT HD you must call :python:`scrollphathd.show()`. - -.. autofunction:: scrollphathd.show - :noindex: - -Clear Buffer ------------- - -.. autofunction:: scrollphathd.clear - :noindex: - -Scroll The Buffer ------------------ - -.. autofunction:: scrollphathd.scroll - :noindex: - -Scroll To A Position --------------------- - -.. autofunction:: scrollphathd.scroll_to - :noindex: - -Rotate The Display ------------------- - -.. autofunction:: scrollphathd.rotate - :noindex: - -Flip The Display ----------------- - -.. autofunction:: scrollphathd.flip - :noindex: - -Get The Display Size --------------------- - -.. autofunction:: scrollphathd.get_shape - :noindex: - -Get The Buffer Size -------------------- - -.. autofunction:: scrollphathd.get_buffer_shape - :noindex: diff --git a/sphinx/requirements.txt b/sphinx/requirements.txt deleted file mode 100644 index 50f1aff..0000000 --- a/sphinx/requirements.txt +++ /dev/null @@ -1,21 +0,0 @@ -alabaster==0.7.12 -Babel==2.9.1 -certifi==2018.11.29 -chardet==3.0.4 -colorama==0.4.1 -docutils==0.14 -funcsigs==1.0.2 -idna==2.8 -imagesize==1.1.0 -Jinja2==2.11.3 -MarkupSafe==1.1.0 -mock==2.0.0 -pbr==5.1.1 -Pygments==2.7.4 -pytz==2018.9 -requests==2.21.0 -six==1.12.0 -snowballstemmer==1.2.1 -Sphinx==1.5.3 -sphinx-rtd-theme==0.4.2 -urllib3==1.26.5 diff --git a/sphinx/shop-logo.png b/sphinx/shop-logo.png deleted file mode 100644 index 8fd0cda..0000000 Binary files a/sphinx/shop-logo.png and /dev/null differ diff --git a/tools/mkfont.py b/tools/mkfont.py index 9b9475b..34454a2 100755 --- a/tools/mkfont.py +++ b/tools/mkfont.py @@ -1,8 +1,9 @@ #!/usr/bin/env python +import argparse import os import sys -import argparse + import numpy try: diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..2b6d87b --- /dev/null +++ b/tox.ini @@ -0,0 +1,27 @@ +[tox] +envlist = py,qa +skip_missing_interpreters = True +isolated_build = true +minversion = 4.0.0 + +[testenv] +commands = + coverage run -m pytest -v -r wsx + coverage report +deps = + mock + pytest>=3.1 + pytest-cov + build + +[testenv:qa] +commands = + check-manifest + python -m build --no-isolation + python -m twine check dist/* + isort --check . + ruff check . + codespell . +deps = + -r{toxinidir}/requirements-dev.txt + diff --git a/uninstall.sh b/uninstall.sh new file mode 100755 index 0000000..3314b7f --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +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="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 './uninstall.sh'\n" + exit 1 + fi +} + +confirm() { + if $FORCE; then + true + else + read -r -p "$1 [y/N] " response < /dev/tty + if [[ $response =~ ^(yes|y|Y)$ ]]; then + true + else + false + fi + 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)" +} + +inform() { + echo -e "$(tput setaf 6)$1$(tput sgr0)" +} + +warning() { + echo -e "$(tput setaf 1)$1$(tput sgr0)" +} + +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" + +if [ -d "$RESOURCES_DIR" ]; then + if confirm "Would you like to delete $RESOURCES_DIR?"; then + rm -r "$RESOURCES_DIR" + fi +fi + +printf "Done!\n"