From 11fb4fe5cb8fbfdc309bb637e28574b15dc85569 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 20 Nov 2023 13:22:13 +0000 Subject: [PATCH] Repackage to hatch/pyproject.toml. --- library/.coveragerc => .coveragerc | 2 +- .github/workflows/build.yml | 41 ++ .github/workflows/qa.yml | 36 ++ .github/workflows/test.yml | 25 +- .stickler.yml | 5 - library/CHANGELOG.txt => CHANGELOG.md | 0 library/MANIFEST.in => MANIFEST.in | 0 Makefile | 85 ++-- README.md | 14 +- check.sh | 88 +++++ {library/inky => inky}/__init__.py | 0 {library/inky => inky}/auto.py | 0 {library/inky => inky}/eeprom.py | 0 {library/inky => inky}/inky.py | 2 + {library/inky => inky}/inky_ac073tc1a.py | 0 {library/inky => inky}/inky_ssd1608.py | 0 {library/inky => inky}/inky_ssd1683.py | 0 {library/inky => inky}/inky_uc8159.py | 0 {library/inky => inky}/mock.py | 0 {library/inky => inky}/phat.py | 0 {library/inky => inky}/ssd1608.py | 0 {library/inky => inky}/ssd1683.py | 0 {library/inky => inky}/what.py | 0 install.sh | 316 ++++++++++++++- library/LICENSE.txt | 21 - library/README.md | 117 ------ library/setup.cfg | 11 - library/setup.py | 61 --- library/tox.ini | 26 -- pyproject.toml | 133 +++++++ requirements-dev.txt | 9 + sphinx/_static/custom.css | 53 --- sphinx/_templates/breadcrumbs.html | 0 sphinx/_templates/layout.html | 43 --- sphinx/conf.py | 365 ------------------ sphinx/favicon.png | Bin 26049 -> 0 bytes sphinx/index.rst | 25 -- sphinx/inky.rst | 5 - sphinx/phat.rst | 8 - sphinx/requirements.txt | 30 -- sphinx/shop-logo.png | Bin 19652 -> 0 bytes sphinx/what.rst | 8 - {library/tests => tests}/conftest.py | 0 {library/tests => tests}/test_auto.py | 0 {library/tests => tests}/test_eeprom.py | 0 {library/tests => tests}/test_init.py | 0 .../tests => tests}/test_install_helpers.py | 0 {library/tests => tests}/test_simulator.py | 0 {library/tests => tests}/tools.py | 0 tox.ini | 34 ++ uninstall.sh | 76 +++- 51 files changed, 769 insertions(+), 870 deletions(-) rename library/.coveragerc => .coveragerc (70%) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/qa.yml delete mode 100644 .stickler.yml rename library/CHANGELOG.txt => CHANGELOG.md (100%) rename library/MANIFEST.in => MANIFEST.in (100%) create mode 100755 check.sh rename {library/inky => inky}/__init__.py (100%) rename {library/inky => inky}/auto.py (100%) rename {library/inky => inky}/eeprom.py (100%) rename {library/inky => inky}/inky.py (99%) rename {library/inky => inky}/inky_ac073tc1a.py (100%) rename {library/inky => inky}/inky_ssd1608.py (100%) rename {library/inky => inky}/inky_ssd1683.py (100%) rename {library/inky => inky}/inky_uc8159.py (100%) rename {library/inky => inky}/mock.py (100%) rename {library/inky => inky}/phat.py (100%) rename {library/inky => inky}/ssd1608.py (100%) rename {library/inky => inky}/ssd1683.py (100%) rename {library/inky => inky}/what.py (100%) delete mode 100644 library/LICENSE.txt delete mode 100644 library/README.md delete mode 100644 library/setup.cfg delete mode 100755 library/setup.py delete mode 100644 library/tox.ini create mode 100644 pyproject.toml create mode 100644 requirements-dev.txt delete mode 100644 sphinx/_static/custom.css delete mode 100644 sphinx/_templates/breadcrumbs.html delete mode 100644 sphinx/_templates/layout.html delete mode 100644 sphinx/conf.py delete mode 100644 sphinx/favicon.png delete mode 100644 sphinx/index.rst delete mode 100644 sphinx/inky.rst delete mode 100644 sphinx/phat.rst delete mode 100644 sphinx/requirements.txt delete mode 100644 sphinx/shop-logo.png delete mode 100644 sphinx/what.rst rename {library/tests => tests}/conftest.py (100%) rename {library/tests => tests}/test_auto.py (100%) rename {library/tests => tests}/test_eeprom.py (100%) rename {library/tests => tests}/test_init.py (100%) rename {library/tests => tests}/test_install_helpers.py (100%) rename {library/tests => tests}/test_simulator.py (100%) rename {library/tests => tests}/tools.py (100%) create mode 100644 tox.ini diff --git a/library/.coveragerc b/.coveragerc similarity index 70% rename from library/.coveragerc rename to .coveragerc index bef4d942..ca9710de 100644 --- a/library/.coveragerc +++ b/.coveragerc @@ -3,4 +3,4 @@ source = inky omit = .tox/* relative_files = True -data_file = ../.coverage +data_file = .coverage diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..87200efb --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,41 @@ +name: Build + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + name: Python ${{ matrix.python }} + runs-on: ubuntu-latest + strategy: + matrix: + python: ['3.9', '3.10', '3.11'] + + env: + RELEASE_FILE: ${{ github.event.repository.name }}-${{ github.event.release.tag_name || github.sha }}-py${{ matrix.python }} + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v3 + 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@v3 + with: + name: ${{ env.RELEASE_FILE }} + path: dist/ diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml new file mode 100644 index 00000000..4f858832 --- /dev/null +++ b/.github/workflows/qa.yml @@ -0,0 +1,36 @@ +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@v2 + + - name: Set up Python '3,11' + uses: actions/setup-python@v3 + 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 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 786b7600..016a6780 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,38 +1,41 @@ -name: Python Tests +name: Tests on: pull_request: push: branches: - - master + - main jobs: test: + name: Python ${{ matrix.python }} runs-on: ubuntu-latest strategy: matrix: - python: [3.9] + python: ['3.9', '3.10', '3.11'] steps: - - uses: actions/checkout@v2 + - name: Checkout Code + uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} + - name: Install Dependencies run: | - python -m pip install tox + make dev-deps + - name: Run Tests - working-directory: library run: | - tox -e py + make pytest + - name: Coverage + if: ${{ matrix.python == '3.9' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - working-directory: library run: | python -m pip install coveralls coveralls --service=github - if: ${{ matrix.python == '3.9' }} - diff --git a/.stickler.yml b/.stickler.yml deleted file mode 100644 index 2466815b..00000000 --- a/.stickler.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -linters: - flake8: - python: 3 - max-line-length: 160 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/MANIFEST.in b/MANIFEST.in similarity index 100% rename from library/MANIFEST.in rename to MANIFEST.in diff --git a/Makefile b/Makefile index 8f176715..9e0c15c5 100644 --- a/Makefile +++ b/Makefile @@ -1,61 +1,60 @@ -LIBRARY_VERSION=`cat library/setup.py | grep version | awk -F"'" '{print $$2}'` -LIBRARY_NAME=`cat library/setup.py | grep name | awk -F"'" '{print $$2}'` +LIBRARY_NAME := $(shell hatch project metadata name 2> /dev/null) +LIBRARY_VERSION := $(shell hatch version 2> /dev/null) -.PHONY: usage install uninstall +.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 "check: peform basic integrity checks on the codebase" - @echo "python-readme: generate library/README.rst from README.md" - @echo "python-wheels: build python .whl files for distribution" - @echo "python-sdist: build python source distribution" - @echo "python-clean: clean python build and dist directories" - @echo "python-dist: build all python distribution files" - @echo "python-testdeploy: build all and deploy to test PyPi" + @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" install: - ./install.sh + ./install.sh --unstable uninstall: ./uninstall.sh -check: - @echo "Checking for trailing whitespace" - @! grep -IlUrn --color "[[:blank:]]$$" --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO - @echo "Checking for DOS line-endings" - @! grep -IlUrn --color " " --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile - @echo "Checking library/CHANGELOG.txt" - @cat library/CHANGELOG.txt | grep ^${LIBRARY_VERSION} - @echo "Checking library/${LIBRARY_NAME}/__init__.py" - @cat library/${LIBRARY_NAME}/__init__.py | grep "^__version__ = '${LIBRARY_VERSION}'" - -python-readme: library/README.md +dev-deps: + python3 -m pip install -r requirements-dev.txt + sudo apt install dos2unix -python-license: library/LICENSE.txt +check: + @bash check.sh -library/README.md: README.md - cp README.md library/README.md +qa: + tox -e qa -library/LICENSE.txt: LICENSE - cp LICENSE library/LICENSE.txt +pytest: + tox -e py -python-wheels: python-readme python-license - cd library; python3 setup.py bdist_wheel +nopost: + @bash check.sh --nopost -python-sdist: python-readme python-license - cd library; python3 setup.py sdist +tag: + git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}" -python-clean: - -rm -r library/dist - -rm -r library/build - -rm -r library/*.egg-info +build: check + @hatch build -python-dist: python-clean python-wheels python-sdist - ls library/dist +clean: + -rm -r dist -python-testdeploy: python-dist - twine upload --repository-url https://test.pypi.org/legacy/ library/dist/* +testdeploy: build + twine upload --repository testpypi dist/* -python-deploy: check python-dist - twine upload library/dist/* +deploy: nopost build + twine upload dist/* diff --git a/README.md b/README.md index 2cf1f74b..406a8e85 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # Inky -[![Build Status](https://travis-ci.com/pimoroni/inky.svg?branch=master)](https://travis-ci.com/pimoroni/inky) +[![Build Status](https://img.shields.io/github/actions/workflow/status/pimoroni/inky/test.yml?branch=main)](https://github.com/pimoroni/inky/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/pimoroni/inky/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/inky?branch=master) [![PyPi Package](https://img.shields.io/pypi/v/inky.svg)](https://pypi.python.org/pypi/inky) [![Python Versions](https://img.shields.io/pypi/pyversions/inky.svg)](https://pypi.python.org/pypi/inky) + Python library for [Inky pHAT](https://shop.pimoroni.com/products/inky-phat), [Inky wHAT](https://shop.pimoroni.com/products/inky-what) and [Inky Impression](https://shop.pimoroni.com/?q=inky+impression) e-paper displays for Raspberry Pi. ## Inky pHAT [Inky pHAT](https://shop.pimoroni.com/products/inky-phat) is a 250x122 pixel e-paper display, available in red/black/white, yellow/black/white and black/white. It's great for nametags and displaying very low frequency information such as a daily calendar or weather overview. - ## Inky wHAT [Inky wHAT](https://shop.pimoroni.com/products/inky-what) is a 400x300 pixel e-paper display available in red/black/white, yellow/black/white and black/white. It's got tons of resolution for detailed daily to-do lists, multi-day weather forecasts, bus timetables and more. @@ -27,19 +27,11 @@ First, make sure you have I2C and SPI enabled in `sudo raspi-config`. The Python pip package is named inky, on the Raspberry Pi install with: ``` -pip3 install inky[rpi,example-depends] +python3 -m pip install inky ``` This will install Inky along with dependencies for the Raspberry Pi, plus fonts used by the examples. -If you want to simulate Inky on your desktop, use: - -``` -pip3 install inky -``` - -You may need to use `sudo pip3` or `sudo pip` depending on your environment and Python version. - # Usage The library should be run with Python 3. diff --git a/check.sh b/check.sh new file mode 100755 index 00000000..4395d89c --- /dev/null +++ b/check.sh @@ -0,0 +1,88 @@ +#!/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: $1\n"; + exit 1 + fi + POSITIONAL_ARGS+=("$1") + shift + esac +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 + warning "Trailing whitespace found!" + exit 1 +else + success "No trailing whitespace found." +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 + warning "DOS line-endings found!" + exit 1 +else + success "No DOS line-endings found." +fi +printf "\n" + +inform "Checking CHANGELOG.md..." +cat CHANGELOG.md | grep ^${LIBRARY_VERSION} > /dev/null 2>&1 +if [[ $? -eq 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}..." +git tag -l | grep -E "${LIBRARY_VERSION}$" +if [[ $? -eq 1 ]]; 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/library/inky/__init__.py b/inky/__init__.py similarity index 100% rename from library/inky/__init__.py rename to inky/__init__.py diff --git a/library/inky/auto.py b/inky/auto.py similarity index 100% rename from library/inky/auto.py rename to inky/auto.py diff --git a/library/inky/eeprom.py b/inky/eeprom.py similarity index 100% rename from library/inky/eeprom.py rename to inky/eeprom.py diff --git a/library/inky/inky.py b/inky/inky.py similarity index 99% rename from library/inky/inky.py rename to inky/inky.py index 53b87ba1..4d16ee10 100644 --- a/library/inky/inky.py +++ b/inky/inky.py @@ -9,6 +9,8 @@ except ImportError: raise ImportError('This library requires the numpy module\nInstall with: sudo apt install python-numpy') +__version__ = "1.5.0" + # Display colour codes WHITE = 0 BLACK = 1 diff --git a/library/inky/inky_ac073tc1a.py b/inky/inky_ac073tc1a.py similarity index 100% rename from library/inky/inky_ac073tc1a.py rename to inky/inky_ac073tc1a.py diff --git a/library/inky/inky_ssd1608.py b/inky/inky_ssd1608.py similarity index 100% rename from library/inky/inky_ssd1608.py rename to inky/inky_ssd1608.py diff --git a/library/inky/inky_ssd1683.py b/inky/inky_ssd1683.py similarity index 100% rename from library/inky/inky_ssd1683.py rename to inky/inky_ssd1683.py diff --git a/library/inky/inky_uc8159.py b/inky/inky_uc8159.py similarity index 100% rename from library/inky/inky_uc8159.py rename to inky/inky_uc8159.py diff --git a/library/inky/mock.py b/inky/mock.py similarity index 100% rename from library/inky/mock.py rename to inky/mock.py diff --git a/library/inky/phat.py b/inky/phat.py similarity index 100% rename from library/inky/phat.py rename to inky/phat.py diff --git a/library/inky/ssd1608.py b/inky/ssd1608.py similarity index 100% rename from library/inky/ssd1608.py rename to inky/ssd1608.py diff --git a/library/inky/ssd1683.py b/inky/ssd1683.py similarity index 100% rename from library/inky/ssd1683.py rename to inky/ssd1683.py diff --git a/library/inky/what.py b/inky/what.py similarity index 100% rename from library/inky/what.py rename to inky/what.py diff --git a/install.sh b/install.sh index cbd9bf3a..38f19e9a 100755 --- a/install.sh +++ b/install.sh @@ -1,21 +1,313 @@ #!/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_DIR/auto_venv.sh +VENV_DIR=$HOME/.virtualenvs/pimoroni +WD=`pwd` +USAGE="./install.sh (--unstable)" +POSITIONAL_ARGS=() +FORCE=false +UNSTABLE=false +PYTHON="python" -printf "Inky Python Library: Installer\n\n" -if [ $(id -u) -ne 0 ]; then - printf "Script must be run as root. Try 'sudo ./install.sh'\n" - exit 1 +user_check() { + if [ $(id -u) -eq 0 ]; then + printf "Script should not be run as root. Try './install.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)" +} + +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 +# Add `source $RESOURCES_DIR/auto_venv.sh` 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 one for you?"; then + 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 $VENV_DIR\n" + fi + inform "Activating virtual Python environment in $VENV_DIR..." + inform "source $VENV_DIR/bin/activate\n" + source $VENV_DIR/bin/activate -function py_install() { - if [ -f "$1" ]; then - VERSION=`$1 --version 2>&1` - printf "Installing for $VERSION..\n" - $1 -m pip install --no-binary .[example-depends] ./library/ + else + exit 1 + fi fi } -py_install /usr/bin/python -py_install /usr/bin/python3 +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=() + PACKAGES_IN=("$@") + 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 + if [ "$?" == "1" ]; then + PACKAGES+=("$PACKAGE") + fi + done + PACKAGES="${PACKAGES[@]}" + if ! [ "$PACKAGES" == "" ]; then + echo "Installing missing packages: $PACKAGES" + if [ ! $APT_HAS_UPDATED ]; then + sudo apt update + APT_HAS_UPDATED=true + fi + sudo apt install -y $PACKAGES + if [ -f "$UNINSTALLER" ]; then + echo "apt uninstall -y $PACKAGES" >> $UNINSTALLER + fi + fi +} + +function pip_pkg_install { + PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring $PYTHON -m pip install --upgrade "$@" +} + +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: $1\n"; + printf "Usage: $USAGE\n"; + exit 1 + fi + POSITIONAL_ARGS+=("$1") + shift + esac +done + +user_check +venv_check + +if [ ! -f `which $PYTHON` ]; then + printf "Python path $PYTHON not found!\n" + exit 1 +fi + +PYTHON_VER=`$PYTHON --version` + +printf "$LIBRARY_NAME Python Library: Installer\n\n" + +inform "Checking Dependencies. Please wait..." + +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 + +if $UNSTABLE; then + warning "Installing unstable library from source.\n\n" +else + printf "Installing stable library from pypi.\n\n" +fi + +inform "Installing for $PYTHON_VER...\n" +apt_pkg_install "${APT_PACKAGES[@]}" +if $UNSTABLE; then + pip_pkg_install . +else + pip_pkg_install $LIBRARY_NAME +fi +if [ $? -eq 0 ]; then + success "Done!\n" + echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> $UNINSTALLER +fi + +cd $WD + +find_config + +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 + eval $CMD +done + +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" + 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 + +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 confirm "Would you like to generate documentation?"; then + pip_pkg_install pdoc + printf "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" + success "Done!" + else + warning "Error: Failed to generate documentation." + fi +fi -printf "Done!\n" +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" diff --git a/library/LICENSE.txt b/library/LICENSE.txt deleted file mode 100644 index aed751a0..00000000 --- a/library/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Pimoroni Ltd. - -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/library/README.md b/library/README.md deleted file mode 100644 index 2cf1f74b..00000000 --- a/library/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# Inky - -[![Build Status](https://travis-ci.com/pimoroni/inky.svg?branch=master)](https://travis-ci.com/pimoroni/inky) -[![Coverage Status](https://coveralls.io/repos/github/pimoroni/inky/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/inky?branch=master) -[![PyPi Package](https://img.shields.io/pypi/v/inky.svg)](https://pypi.python.org/pypi/inky) -[![Python Versions](https://img.shields.io/pypi/pyversions/inky.svg)](https://pypi.python.org/pypi/inky) - -Python library for [Inky pHAT](https://shop.pimoroni.com/products/inky-phat), [Inky wHAT](https://shop.pimoroni.com/products/inky-what) and [Inky Impression](https://shop.pimoroni.com/?q=inky+impression) e-paper displays for Raspberry Pi. - -## Inky pHAT - -[Inky pHAT](https://shop.pimoroni.com/products/inky-phat) is a 250x122 pixel e-paper display, available in red/black/white, yellow/black/white and black/white. It's great for nametags and displaying very low frequency information such as a daily calendar or weather overview. - - -## Inky wHAT - -[Inky wHAT](https://shop.pimoroni.com/products/inky-what) is a 400x300 pixel e-paper display available in red/black/white, yellow/black/white and black/white. It's got tons of resolution for detailed daily to-do lists, multi-day weather forecasts, bus timetables and more. - -## Inky Impression - -[Inky Impression](https://shop.pimoroni.com/?q=inky+impression) is our line of glorious 7 colour eInk displays, available in [4"](https://shop.pimoroni.com/products/inky-impression-4) (640 x 400 pixel) [5.7"](https://shop.pimoroni.com/products/inky-impression-5-7) (600 x 448 pixel) and [7.3"](https://shop.pimoroni.com/products/inky-impression-7-3) (800 x 480 pixel) flavours. They're packed with strong colours and perfect for displaying striking graphics or lots of data. - -# Installation - -First, make sure you have I2C and SPI enabled in `sudo raspi-config`. - -The Python pip package is named inky, on the Raspberry Pi install with: - -``` -pip3 install inky[rpi,example-depends] -``` - -This will install Inky along with dependencies for the Raspberry Pi, plus fonts used by the examples. - -If you want to simulate Inky on your desktop, use: - -``` -pip3 install inky -``` - -You may need to use `sudo pip3` or `sudo pip` depending on your environment and Python version. - -# Usage - -The library should be run with Python 3. - -## Auto Setup - -Inky can try to automatically identify your board (from the information stored on its EEPROM) and set up accordingly. This is the easiest way to work with recent Inky displays. - -```python -from inky.auto import auto -display = auto() -``` - -You can then get the colour and resolution from the board: - -```python -display.colour -display.resolution -``` - -## Manual Setup - -If you have an older Inky without an EEPROM, you can specify the type manually. The Inky library contains modules for both the pHAT and wHAT, load the Inky pHAT one as follows: - -```python -from inky import InkyPHAT -``` - -You'll then need to pick your colour, one of 'red', 'yellow' or 'black' and instantiate the class: - -```python -display = InkyPHAT('red') -``` - -If you're using the wHAT you'll need to load the InkyWHAT class from the Inky library like so: - -```python -from inky import InkyWHAT -display = InkyWHAT('red') -``` - -Once you've initialised Inky, there are only three methods you need to be concerned with: - -## Set Image - -Set a PIL image, numpy array or list to Inky's internal buffer. The image dimensions should match the dimensions of the pHAT or wHAT you're using. - -```python -display.set_image(image) -``` - -You should use `PIL` to create an image. `PIL` provides an `ImageDraw` module which allow you to draw text, lines and shapes over your image. See: https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html - -## Set Border - -Set the border colour of you pHAT or wHAT. - -```python -display.set_border(colour) -``` - -`colour` should be one of `inky.RED`, `inky.YELLOW`, `inky.WHITE` or `inky.BLACK` with available colours depending on your display type. - -## Update The Display - -Once you've prepared and set your image, and chosen a border colour, you can update your e-ink display with: - -```python -display.show() -``` - - -# Migrating - -If you're migrating code from the old `inkyphat` library you'll find that much of the drawing and image manipulation functions have been removed from Inky. These functions were always supplied by PIL, and the recommended approach is to use PIL to create and prepare your image before setting it to Inky with `set_image()`. diff --git a/library/setup.cfg b/library/setup.cfg deleted file mode 100644 index 5c3c3ea2..00000000 --- a/library/setup.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[flake8] -exclude = - test.py - .tox, - .eggs, - .git, - __pycache__, - build, - dist -ignore = - E501 diff --git a/library/setup.py b/library/setup.py deleted file mode 100755 index 6c442cce..00000000 --- a/library/setup.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python3 - -""" -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. -""" - -from setuptools 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='inky', - version='1.5.0', - author='Philip Howard', - author_email='phil@pimoroni.com', - description='Inky pHAT Driver', - long_description=open('README.md').read() + '\n' + open('CHANGELOG.txt').read(), - long_description_content_type="text/markdown", - license='MIT', - keywords='Raspberry Pi e-paper display driver', - url='http://www.pimoroni.com', - project_urls={'GitHub': 'https://www.github.com/pimoroni/inky'}, - classifiers=classifiers, - py_modules=[], - packages=['inky'], - include_package_data=True, - install_requires=['numpy', 'smbus2', 'spidev'], - extras_require={ - 'rpi-gpio-output': ['RPi.GPIO'], - 'rpi': ['RPi.GPIO'], - 'example-depends': ['requests', 'geocoder', 'beautifulsoup4', 'font-fredoka-one', 'font-source-serif-pro', 'font-hanken-grotesk', 'font-intuitive'] - } -) diff --git a/library/tox.ini b/library/tox.ini deleted file mode 100644 index 4e838450..00000000 --- a/library/tox.ini +++ /dev/null @@ -1,26 +0,0 @@ -[tox] -envlist = py{39},qa -skip_missing_interpreters = True - -[testenv] -commands = - python setup.py develop --no-deps - coverage run -m pytest -v -r wsx - coverage report -m -deps = - mock - pytest>=3.1 - pytest-cov - -[testenv:qa] -commands = - check-manifest --ignore tox.ini,tests/*,.coveragerc - flake8 --ignore E501,E122,E241,F401,W504,Q000 - python setup.py sdist bdist_wheel - twine check dist/* -deps = - check-manifest - flake8 - flake8-docstrings - flake8-quotes - twine diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..65488cc8 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,133 @@ +[build-system] +requires = ["hatchling", "hatch-fancy-pypi-readme"] +build-backend = "hatchling.build" + +[project] +name = "inky" +dynamic = ["version", "readme"] +description = "Inky pHAT 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 = [ + "Raspberry Pi", + "e-paper", +] +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", + "spidev" +] + +[project.optional-dependencies] +example-depends = [ + "requests", + "geocoder", + "beautifulsoup4", + "font-fredoka-one", + "font-source-serif-pro", + "font-hanken-grotesk", + "font-intuitive" +] +rpi-gpio-output = ['RPi.GPIO'] +rpi = ['RPi.GPIO'] + +[project.urls] +GitHub = "https://www.github.com/pimoroni/inky" +Homepage = "https://www.pimoroni.com" + +[tool.hatch.version] +path = "inky/__init__.py" + +[tool.hatch.build] +include = [ + "inky", + "README.md", + "CHANGELOG.md", + "LICENSE" +] + +[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.\ +""" + +[tool.isort] +line_length = 200 + +[tool.black] +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 00000000..525b0427 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,9 @@ +check-manifest +ruff +codespell +isort +twine +hatch +hatch-fancy-pypi-readme +tox +pdoc diff --git a/sphinx/_static/custom.css b/sphinx/_static/custom.css deleted file mode 100644 index 141c20cd..00000000 --- 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 e69de29b..00000000 diff --git a/sphinx/_templates/layout.html b/sphinx/_templates/layout.html deleted file mode 100644 index a2bd1c5c..00000000 --- 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 a4877486..00000000 --- a/sphinx/conf.py +++ /dev/null @@ -1,365 +0,0 @@ -#-*- coding: utf-8 -*- - -import sys -import site - -from unittest import mock -PACKAGE_NAME = u"Inky" -PACKAGE_HANDLE = "Inky" -PACKAGE_MODULE = "inky" - -# Prompte /usr/local/lib to the front of sys.path -#sys.path.insert(0,site.getsitepackages()[0]) - -import sphinx_rtd_theme - -MOCK_MODULES = ['RPi', 'RPi.GPIO', 'smbus2', 'smbus', 'numpy', 'spidev', 'PIL'] -for module_name in MOCK_MODULES: - sys.modules[module_name] = mock.MagicMock() - -sys.path.insert(0, '../library/') - - -import inky - -from sphinx.ext import autodoc - - -# -- 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', - 'sphinx.ext.intersphinx', - 'sphinx.ext.autosummary' -] - -autoclass_content = 'both' - -# Intersphinx configuration -intersphinx_mapping = { - 'numpy': ('https://docs.scipy.org/doc/numpy/', None), - 'PIL': ('https://pillow.readthedocs.io/en/stable/', None), - 'python': ('https://docs.python.org/3', None), - 'smbus2': ('https://smbus2.readthedocs.io/en/latest/', None), - } - -# 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'2019, 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(inky.__version__) -# The full version, including alpha/beta/rc tags. -release = u'{}'.format(inky.__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', 'sphinx.virtualenv'] - -# 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' -#html_theme = 'alabaster' - -# 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 5ed0316c76a3c90cc6c8844cdd3c1385ad5cf09d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26049 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 diff --git a/sphinx/index.rst b/sphinx/index.rst deleted file mode 100644 index 7e0c786a..00000000 --- a/sphinx/index.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. role:: python(code) - :language: python - -Welcome -------- - -This documentation will guide you through the methods available in the Inky python library. - -The Pimoroni website has tutorials demonstrating how to set up and use the `Inky pHAT`_ and `Inky wHAT`_. - -Further examples can be found on the `Inky Git repository`_. - -.. _`Inky pHAT`: https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-inky-phat -.. _`Inky wHAT`: https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-inky-what -.. _`Inky Git repository`: https://github.com/pimoroni/inky/tree/master/examples - -.. currentmodule:: inky - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - phat - what - inky diff --git a/sphinx/inky.rst b/sphinx/inky.rst deleted file mode 100644 index b07f07af..00000000 --- a/sphinx/inky.rst +++ /dev/null @@ -1,5 +0,0 @@ -Inky Base Class ---------------- - -.. autoclass:: inky.inky.Inky - :members: diff --git a/sphinx/phat.rst b/sphinx/phat.rst deleted file mode 100644 index 22a31f95..00000000 --- a/sphinx/phat.rst +++ /dev/null @@ -1,8 +0,0 @@ -Inky pHAT ---------- - -.. automodule:: inky.phat - -.. autoclass:: inky.InkyPHAT - :members: - :inherited-members: diff --git a/sphinx/requirements.txt b/sphinx/requirements.txt deleted file mode 100644 index fb969a5a..00000000 --- a/sphinx/requirements.txt +++ /dev/null @@ -1,30 +0,0 @@ -alabaster==0.7.12 -Babel==2.9.1 -certifi==2021.5.30 -chardet==4.0.0 -charset-normalizer==2.0.3 -docutils==0.16 -funcsigs==1.0.2 -idna==3.2 -imagesize==1.2.0 -Jinja2==3.0.1 -MarkupSafe==2.0.1 -packaging==21.0 -Pillow==8.3.1 -Pygments==2.9.0 -pyparsing==2.4.7 -pytz==2021.1 -requests==2.26.0 -six==1.16.0 -snowballstemmer==2.1.0 -Sphinx==4.1.2 -sphinx-rtd-theme==0.5.2 -sphinxcontrib-applehelp==1.0.2 -sphinxcontrib-devhelp==1.0.2 -sphinxcontrib-htmlhelp==2.0.0 -sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.5 -sphinxcontrib-websupport==1.2.4 -typing==3.7.4.3 -urllib3==1.26.6 diff --git a/sphinx/shop-logo.png b/sphinx/shop-logo.png deleted file mode 100644 index 8fd0cda225cb6add7db0f7137919d92322c89f06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19652 zcmeI4c|6qJ+sD76O(@y2Z%ML@nX%1e-x~WG#y-Yivdl1pAt6b!Wi7flqJ$LwBB=f&vQSo-}Ahle`a2o?{%*8xvuklpL3n>`RD7Tx#B5#7%!FXX2p#d1H zP*ZDks5ctsE~cT*tV)7Y0{CKxC=rscj~@X}QWIN`3#VMKHG{-N*1HhB)x@;c5{lTF zn2YG(0x%+qa!RsjFc>VN43h&Zsz4!%G9nOpup&qv1_H~=%7fuxc{oH~ljcD%m6 zzfDab>IG2{d_($MCBZrbj{#X?2)MuiG)6Coax3D$yL%$mlRZ0~^E&4g* zKjUF^QACV7Wko8RLAMlFeiP1Z39zBuhjs?T^00~)}O=rq5LMp z{$>LI73Ht-f06%lj$kj0-#=8)*C^{9{#j4Jc@Tq90T?Y$%5wO3mHjpDUxm~OR6%RI zy$|;PU=|3dp#N|V{#6nEXLIm<8~Xp8gP-dc?S=C5#JH=2zAxSH4gYT1zE0*}YwG(} z@b?;2U3>PxDfLTPP^k5~0jq-k*7h^=*Zy{Eb?6hg-d`CaPx(+zD3s4P>91~TDU!DI zS2wlvr}Cg5mZ(nI;MNC9)%=TU?E(39E4QMYii%K0RSN)nRU&^XmA_|O7yjb-Cj2^AzZ|>PEAVS88?IxgCLsJwJsR6uB(bX>IgP9}a~q4LskQ30WC(s9w|L*=F8q5?wOq~oH^hssOGMFoVmNykN-50#gWiwX#Bla7lv zA1W^$7ZniNCLI@TK2%;hE-E0jO*$^xe5ky1TvR}4n{-^X`A~W3xTt{8HtD!%^P%$6 zaZv%GZPIbk=0oMB7&4A0wX&^Bq}V*dGxCdQBQUS=@m z1oYDggkI#{gjI3+4MY00hbdz@#exz%v1W2bb#7tPcP?0}OPv ztVsiJooX%lO?Kk;j!VASmMv2o>G3@#yWA}Ir+f{@Gmd!d$A<7A-TU5=KmgyG*$2qiEzez$Qm&g-N zLP_UaNKaBg2G|d;c;ty)71m{gXaR54Y98 c29iqXq3)xp_>0_3<6H>b_N?3w_6T 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 diff --git a/sphinx/what.rst b/sphinx/what.rst deleted file mode 100644 index 69645c7c..00000000 --- a/sphinx/what.rst +++ /dev/null @@ -1,8 +0,0 @@ -Inky wHAT ---------- - -.. automodule:: inky.what - -.. autoclass:: inky.InkyWHAT - :members: - :inherited-members: diff --git a/library/tests/conftest.py b/tests/conftest.py similarity index 100% rename from library/tests/conftest.py rename to tests/conftest.py diff --git a/library/tests/test_auto.py b/tests/test_auto.py similarity index 100% rename from library/tests/test_auto.py rename to tests/test_auto.py diff --git a/library/tests/test_eeprom.py b/tests/test_eeprom.py similarity index 100% rename from library/tests/test_eeprom.py rename to tests/test_eeprom.py diff --git a/library/tests/test_init.py b/tests/test_init.py similarity index 100% rename from library/tests/test_init.py rename to tests/test_init.py diff --git a/library/tests/test_install_helpers.py b/tests/test_install_helpers.py similarity index 100% rename from library/tests/test_install_helpers.py rename to tests/test_install_helpers.py diff --git a/library/tests/test_simulator.py b/tests/test_simulator.py similarity index 100% rename from library/tests/test_simulator.py rename to tests/test_simulator.py diff --git a/library/tests/tools.py b/tests/tools.py similarity index 100% rename from library/tests/tools.py rename to tests/tools.py diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..44c86546 --- /dev/null +++ b/tox.ini @@ -0,0 +1,34 @@ +[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 . + codespell . +deps = + check-manifest + ruff + codespell + isort + twine + build + hatch + hatch-fancy-pypi-readme + diff --git a/uninstall.sh b/uninstall.sh index 0928b014..f213fc52 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,24 +1,72 @@ #!/bin/bash -PACKAGE="inky" +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" -printf "Inky Python Library: Uninstaller\n\n" -if [ $(id -u) -ne 0 ]; then - printf "Script must be run as root. Try 'sudo ./uninstall.sh'\n" - exit 1 -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" + exit 1 + fi +} -cd library +user_check() { + if [ $(id -u) -eq 0 ]; then + printf "Script should not be run as root. Try './uninstall.sh'\n" + exit 1 + fi +} -printf "Unnstalling for Python 2..\n" -pip uninstall $PACKAGE +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 +} -if [ -f "/usr/bin/pip3" ]; then - printf "Uninstalling for Python 3..\n" - pip3 uninstall $PACKAGE -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)" +} -cd .. +printf "$LIBRARY_NAME Python Library: Uninstaller\n\n" + +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"