From 7f544f1bad488dc117fe13ca2ded8112f021285a Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 16:06:39 +0000 Subject: [PATCH 01/27] Repackage and focus on Python only code. --- library/CHANGELOG.txt => CHANGELOG.md | 0 Dockerfile | 20 - Makefile | 60 + README.md | 154 +- library/blinkt.py => blinkt/__init__.py | 53 +- check.sh | 87 + documentation/REFERENCE.md | 54 +- install.sh | 294 ++ library/LICENSE.txt | 21 - library/MANIFEST.in | 5 - library/Makefile | 7 - library/README.md | 1 - library/README.rst | 120 - library/setup.cfg | 11 - library/setup.py | 53 - library/tests/test_setup.py | 17 - library/tests/tools.py | 30 - library/tox.ini | 24 - library_c/CHANGELOG.txt | 0 library_c/MANIFEST.in | 7 - library_c/Makefile | 7 - library_c/README.md | 0 library_c/README.txt | 0 library_c/blinkt | Bin 58016 -> 0 bytes library_c/blinkt.i | 22 - library_c/blinkt.py | 120 - library_c/blinkt_wrap.c | 4153 ----------------------- library_c/lib/blinkt.c | 173 - library_c/lib/blinkt.h | 9 - library_c/setup.py | 24 - packaging/CHANGELOG | 75 - packaging/debian/README | 6 - packaging/debian/changelog | 75 - packaging/debian/clean | 1 - packaging/debian/compat | 1 - packaging/debian/control | 31 - packaging/debian/copyright | 26 - packaging/debian/docs | 0 packaging/debian/rules | 12 - packaging/debian/source/format | 1 - packaging/debian/source/options | 1 - packaging/makeall.sh | 165 - packaging/makedeb.sh | 38 - packaging/makedoc.sh | 37 - packaging/makelog.sh | 82 - pyproject.toml | 115 + requirements-dev.txt | 9 + sphinx/_static/custom.css | 39 - sphinx/_templates/breadcrumbs.html | 0 sphinx/_templates/layout.html | 4 - sphinx/conf.py | 389 --- sphinx/favicon.png | Bin 26049 -> 0 bytes sphinx/index.rst | 93 - sphinx/shop-logo.png | Bin 19652 -> 0 bytes tests/conftest.py | 11 + tests/test_setup.py | 7 + tox.ini | 34 + uninstall.sh | 72 + 58 files changed, 806 insertions(+), 6044 deletions(-) rename library/CHANGELOG.txt => CHANGELOG.md (100%) delete mode 100644 Dockerfile create mode 100644 Makefile rename library/blinkt.py => blinkt/__init__.py (76%) create mode 100755 check.sh create mode 100755 install.sh delete mode 100644 library/LICENSE.txt delete mode 100644 library/MANIFEST.in delete mode 100644 library/Makefile delete mode 100644 library/README.md delete mode 100644 library/README.rst delete mode 100644 library/setup.cfg delete mode 100755 library/setup.py delete mode 100644 library/tests/test_setup.py delete mode 100644 library/tests/tools.py delete mode 100644 library/tox.ini delete mode 100644 library_c/CHANGELOG.txt delete mode 100644 library_c/MANIFEST.in delete mode 100644 library_c/Makefile delete mode 100644 library_c/README.md delete mode 100644 library_c/README.txt delete mode 100755 library_c/blinkt delete mode 100644 library_c/blinkt.i delete mode 100644 library_c/blinkt.py delete mode 100644 library_c/blinkt_wrap.c delete mode 100644 library_c/lib/blinkt.c delete mode 100644 library_c/lib/blinkt.h delete mode 100755 library_c/setup.py delete mode 100644 packaging/CHANGELOG delete mode 100644 packaging/debian/README delete mode 100644 packaging/debian/changelog delete mode 100644 packaging/debian/clean delete mode 100644 packaging/debian/compat delete mode 100644 packaging/debian/control delete mode 100644 packaging/debian/copyright delete mode 100644 packaging/debian/docs delete mode 100755 packaging/debian/rules delete mode 100644 packaging/debian/source/format delete mode 100644 packaging/debian/source/options delete mode 100755 packaging/makeall.sh delete mode 100755 packaging/makedeb.sh delete mode 100755 packaging/makedoc.sh delete mode 100755 packaging/makelog.sh 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/shop-logo.png create mode 100644 tests/conftest.py create mode 100644 tests/test_setup.py create mode 100644 tox.ini create mode 100755 uninstall.sh diff --git a/library/CHANGELOG.txt b/CHANGELOG.md similarity index 100% rename from library/CHANGELOG.txt rename to CHANGELOG.md diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 87e1336..0000000 --- a/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM resin/rpi-raspbian:jessie - -RUN apt-get update -qy && apt-get install -qy \ - python \ - python-rpi.gpio - -# Cancel out any Entrypoint already set in the base image. -ENTRYPOINT [] - -WORKDIR /root/ - -COPY library library -WORKDIR /root/library -RUN python setup.py install - -WORKDIR /root/ -COPY examples examples -WORKDIR /root/examples/ - -CMD ["python", "larson.py"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9e0c15c --- /dev/null +++ b/Makefile @@ -0,0 +1,60 @@ +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" + +install: + ./install.sh --unstable + +uninstall: + ./uninstall.sh + +dev-deps: + python3 -m pip install -r requirements-dev.txt + sudo apt install dos2unix + +check: + @bash check.sh + +qa: + tox -e qa + +pytest: + tox -e py + +nopost: + @bash check.sh --nopost + +tag: + 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/README.md b/README.md index 3d729b1..ac8b416 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,65 @@ -![Blinkt!](blinkt-logo.png) - -[![Build Status](https://travis-ci.com/pimoroni/blinkt.svg?branch=master)](https://travis-ci.com/pimoroni/blinkt) -[![Coverage Status](https://coveralls.io/repos/github/pimoroni/blinkt/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/blinkt?branch=master) -[![PyPi Package](https://img.shields.io/pypi/v/blinkt.svg)](https://pypi.python.org/pypi/blinkt) -[![Python Versions](https://img.shields.io/pypi/pyversions/blinkt.svg)](https://pypi.python.org/pypi/blinkt) - -https://shop.pimoroni.com/products/blinkt - -Eight super-bright RGB LED indicators, ideal for adding visual notifications to your Raspberry Pi on their own or on a pHAT stacking header. - -## Installing - -### Full install (recommended): - -We've created an easy installation script that will install all pre-requisites and get your Blinkt! -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: - -![Finding the terminal](http://get.pimoroni.com/resources/github-repo-terminal.png) - -In the new terminal window type the command exactly as it appears below (check for typos) and follow the on-screen instructions: - -```bash -curl https://get.pimoroni.com/blinkt | bash -``` - -Alternatively, on Raspbian, you can download the `pimoroni-dashboard` and install your product by browsing to the relevant entry: - -```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/blinkt/`. - -### Manual install: - -#### Library install for Python 3: - -on Raspbian: - -```bash -sudo apt-get install python3-blinkt -``` - -other environments: - -```bash -sudo pip3 install blinkt -``` - -#### Library install for Python 2: - -on Raspbian: - -```bash -sudo apt-get install python-blinkt -``` - -other environments: - -```bash -sudo pip2 install blinkt -``` - -### 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: - -```bash -sudo python3 setup.py install -``` -(or `sudo python setup.py install` whichever your primary Python environment may be) - -## Documentation & Support - -* Guides and tutorials - https://learn.pimoroni.com/blinkt -* Function reference - http://docs.pimoroni.com/blinkt/ -* GPIO Pinout - https://pinout.xyz/pinout/blinkt -* Get help - http://forums.pimoroni.com/c/support - -## Unofficial / Third-party libraries - -* Golang library & examples by [Alex Ellis](https://www.alexellis.io) - https://github.com/alexellis/blinkt_go, https://github.com/alexellis/blinkt_go_examples -* Java library by Jim Darby - https://github.com/hackerjimbo/PiJava -* Java library by @HoldYourWaffle - https://github.com/HoldYourWaffle/blinkt4j -* Node.js library by @irrelon - https://github.com/irrelon/node-blinkt -* Rust library by @golemparts - https://github.com/golemparts/blinkt +![Blinkt!](blinkt-logo.png) + +[![Build Status](https://travis-ci.com/pimoroni/blinkt.svg?branch=master)](https://travis-ci.com/pimoroni/blinkt) +[![Coverage Status](https://coveralls.io/repos/github/pimoroni/blinkt/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/blinkt?branch=master) +[![PyPi Package](https://img.shields.io/pypi/v/blinkt.svg)](https://pypi.python.org/pypi/blinkt) +[![Python Versions](https://img.shields.io/pypi/pyversions/blinkt.svg)](https://pypi.python.org/pypi/blinkt) + +https://shop.pimoroni.com/products/blinkt + +Eight super-bright RGB LED indicators, ideal for adding visual notifications to your Raspberry Pi on their own or on a pHAT stacking header. + +## Installing + +### Full install (recommended): + +We've created an easy installation script that will install all pre-requisites and get your Blinkt! +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: + +![Finding the terminal](http://get.pimoroni.com/resources/github-repo-terminal.png) + +In the new terminal window type the command exactly as it appears below (check for typos) and follow the on-screen instructions: + +```bash +git clone https://github.com/pimoroni/blinkt +cd blinkt +./install.sh +``` + +### Manual install: + +```bash +python3 -m pip install blinkt +``` +### 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: + +```bash +make dev-deps +make build +``` + +To run QA and tests, use: + +```bash +make check +make qa +make pytest +``` + +## Documentation & Support + +* Guides and tutorials - https://learn.pimoroni.com/blinkt +* Function reference - http://docs.pimoroni.com/blinkt/ +* GPIO Pinout - https://pinout.xyz/pinout/blinkt +* Get help - http://forums.pimoroni.com/c/support + +## Unofficial / Third-party libraries + +* Golang library & examples by [Alex Ellis](https://www.alexellis.io) - https://github.com/alexellis/blinkt_go, https://github.com/alexellis/blinkt_go_examples +* Java library by Jim Darby - https://github.com/hackerjimbo/PiJava +* Java library by @HoldYourWaffle - https://github.com/HoldYourWaffle/blinkt4j +* Node.js library by @irrelon - https://github.com/irrelon/node-blinkt +* Rust library by @golemparts - https://github.com/golemparts/blinkt diff --git a/library/blinkt.py b/blinkt/__init__.py similarity index 76% rename from library/blinkt.py rename to blinkt/__init__.py index aaf5ca0..9031b85 100644 --- a/library/blinkt.py +++ b/blinkt/__init__.py @@ -2,7 +2,9 @@ import atexit import time -import RPi.GPIO as GPIO +import gpiod + +from gpiod.line import Direction, Value __version__ = '0.1.2' @@ -11,20 +13,13 @@ CLK = 24 NUM_PIXELS = 8 BRIGHTNESS = 7 +GPIOCHIP = "/dev/gpiochip4" pixels = [[0, 0, 0, BRIGHTNESS]] * NUM_PIXELS sleep_time = 0 -_gpio_setup = False -_clear_on_exit = True - - -def _exit(): - if _clear_on_exit: - clear() - show() - GPIO.cleanup() +gpio_lines = None def set_brightness(brightness): @@ -48,45 +43,47 @@ def clear(): def _write_byte(byte): for x in range(8): - GPIO.output(DAT, byte & 0b10000000) - GPIO.output(CLK, 1) + gpio_lines.set_value(DAT, Value.ACTIVE if (byte & 0b10000000) else Value.INACTIVE) + gpio_lines.set_value(CLK, Value.ACTIVE) time.sleep(sleep_time) byte <<= 1 - GPIO.output(CLK, 0) + gpio_lines.set_value(CLK, Value.INACTIVE) time.sleep(sleep_time) # Emit exactly enough clock pulses to latch the small dark die APA102s which are weird # for some reason it takes 36 clocks, the other IC takes just 4 (number of pixels/2) def _eof(): - GPIO.output(DAT, 0) + gpio_lines.set_value(DAT, Value.INACTIVE) for x in range(36): - GPIO.output(CLK, 1) + gpio_lines.set_value(CLK, Value.ACTIVE) time.sleep(sleep_time) - GPIO.output(CLK, 0) + gpio_lines.set_value(CLK, Value.INACTIVE) time.sleep(sleep_time) def _sof(): - GPIO.output(DAT, 0) + gpio_lines.set_value(DAT, Value.INACTIVE) for x in range(32): - GPIO.output(CLK, 1) + gpio_lines.set_value(CLK, Value.ACTIVE) time.sleep(sleep_time) - GPIO.output(CLK, 0) + gpio_lines.set_value(CLK, Value.INACTIVE) time.sleep(sleep_time) def show(): """Output the buffer to Blinkt!.""" - global _gpio_setup - - if not _gpio_setup: - GPIO.setmode(GPIO.BCM) - GPIO.setwarnings(False) - GPIO.setup(DAT, GPIO.OUT) - GPIO.setup(CLK, GPIO.OUT) - atexit.register(_exit) - _gpio_setup = True + global gpio_lines + + if not gpio_lines: + gpio_lines = gpiod.request_lines( + GPIOCHIP, + consumer="blinkt", + config={ + DAT: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE), + CLK: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE) + } + ) _sof() diff --git a/check.sh b/check.sh new file mode 100755 index 0000000..cbb1565 --- /dev/null +++ b/check.sh @@ -0,0 +1,87 @@ +#!/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))}'` + +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/documentation/REFERENCE.md b/documentation/REFERENCE.md index 9690a9c..9949e02 100644 --- a/documentation/REFERENCE.md +++ b/documentation/REFERENCE.md @@ -1,27 +1,27 @@ -# Blinkt Function Reference - -The two Blinkt methods you'll most commonly use are `set_pixel` and `show`. Here's a simple example: - -``` -from blinkt import set_pixel, show - -set_pixel(0,255,0,0) -show() -``` - -`set_pixel` takes an optional fifth parameter; the brightness from 0.0 to 1.0. - -`set_pixel(pixel_no, red, green, blue, brightness)` - -You can also change the brightness with `set_brightness` from 0.0 to 1.0, for example: - -``` -from blinkt import set_brightness - -set_brightness(0.5) -show() -``` - -Additionally, there exists a helper function `set_all` which allows you to set all pixels to the same color and brightness. The `brightness` parameter is just like the one in `set_pixel`: it's optional and ranges from 0.0 to 1.0. - -`set_all(red, green, blue, brightness)` +# Blinkt Function Reference + +The two Blinkt methods you'll most commonly use are `set_pixel` and `show`. Here's a simple example: + +``` +from blinkt import set_pixel, show + +set_pixel(0,255,0,0) +show() +``` + +`set_pixel` takes an optional fifth parameter; the brightness from 0.0 to 1.0. + +`set_pixel(pixel_no, red, green, blue, brightness)` + +You can also change the brightness with `set_brightness` from 0.0 to 1.0, for example: + +``` +from blinkt import set_brightness + +set_brightness(0.5) +show() +``` + +Additionally, there exists a helper function `set_all` which allows you to set all pixels to the same color and brightness. The `brightness` parameter is just like the one in `set_pixel`: it's optional and ranges from 0.0 to 1.0. + +`set_all(red, green, blue, brightness)` diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..aebc385 --- /dev/null +++ b/install.sh @@ -0,0 +1,294 @@ +#!/bin/bash +LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'` +CONFIG=/boot/config.txt +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" + + +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)" +} + +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 + + else + exit 1 + fi + fi +} + +function do_config_backup { + if [ ! $CONFIG_BACKUP == true ]; then + CONFIG_BACKUP=true + FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt" + inform "Backing up $CONFIG to /boot/$FILENAME\n" + sudo cp $CONFIG /boot/$FILENAME + mkdir -p $RESOURCES_TOP_DIR/config-backups/ + cp $CONFIG $RESOURCES_TOP_DIR/config-backups/$FILENAME + if [ -f "$UNINSTALLER" ]; then + echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG" >> $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 + +for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do + CMD="${SETUP_CMDS[$i]}" + # Attempt to catch anything that touches /boot/config.txt and trigger a backup + if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG"* ]] || [[ "$CMD" == *"\$CONFIG"* ]]; then + 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\n" + sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG + if ! grep -q "^$CONFIG_LINE" $CONFIG; then + printf "$CONFIG_LINE\n" | sudo tee --append $CONFIG + 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 + +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 843e68a..0000000 --- a/library/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 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/MANIFEST.in b/library/MANIFEST.in deleted file mode 100644 index 090a8ba..0000000 --- a/library/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include CHANGELOG.txt -include LICENSE.txt -include README.rst -include setup.py -include blinkt.py diff --git a/library/Makefile b/library/Makefile deleted file mode 100644 index 74399eb..0000000 --- a/library/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - gcc -Wall -DTEST lib/blinkt.c -l bcm2835 -o blinkt - -devel: - -rm -r build - python setup.py build - sudo python setup.py develop diff --git a/library/README.md b/library/README.md deleted file mode 100644 index 5173cde..0000000 --- a/library/README.md +++ /dev/null @@ -1 +0,0 @@ -#Blinkt Pure Python Library diff --git a/library/README.rst b/library/README.rst deleted file mode 100644 index 1096761..0000000 --- a/library/README.rst +++ /dev/null @@ -1,120 +0,0 @@ -.. figure:: blinkt-logo.png - :alt: Blinkt! - - Blinkt! - -|Build Status| |Coverage Status| |PyPi Package| |Python Versions| - -https://shop.pimoroni.com/products/blinkt - -Eight super-bright RGB LED indicators, ideal for adding visual -notifications to your Raspberry Pi on their own or on a pHAT stacking -header. - -Installing ----------- - -Full install (recommended): -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We've created an easy installation script that will install all -pre-requisites and get your Blinkt! 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 - - 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/blinkt | 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/blinkt/``. - -Manual install: -~~~~~~~~~~~~~~~ - -Library install for Python 3: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -on Raspbian: - -.. code:: bash - - sudo apt-get install python3-blinkt - -other environments: - -.. code:: bash - - sudo pip3 install blinkt - -Library install for Python 2: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -on Raspbian: - -.. code:: bash - - sudo apt-get install python-blinkt - -other environments: - -.. code:: bash - - sudo pip2 install blinkt - -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) - -Documentation & Support ------------------------ - -- Guides and tutorials - https://learn.pimoroni.com/blinkt -- Function reference - http://docs.pimoroni.com/blinkt/ -- GPIO Pinout - https://pinout.xyz/pinout/blinkt -- Get help - http://forums.pimoroni.com/c/support - -Unofficial / Third-party libraries ----------------------------------- - -- Golang library & examples by `Alex - Ellis `__ - - https://github.com/alexellis/blinkt\_go\_examples -- Java library by Jim Darby - https://github.com/hackerjimbo/PiJava - -.. |Build Status| image:: https://travis-ci.com/pimoroni/blinkt.svg?branch=master - :target: https://travis-ci.com/pimoroni/blinkt -.. |Coverage Status| image:: https://coveralls.io/repos/github/pimoroni/blinkt/badge.svg?branch=master - :target: https://coveralls.io/github/pimoroni/blinkt?branch=master -.. |PyPi Package| image:: https://img.shields.io/pypi/v/blinkt.svg - :target: https://pypi.python.org/pypi/blinkt -.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/blinkt.svg - :target: https://pypi.python.org/pypi/blinkt diff --git a/library/setup.cfg b/library/setup.cfg deleted file mode 100644 index 5c3c3ea..0000000 --- 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 c30b957..0000000 --- a/library/setup.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -""" -Copyright (c) 2016 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='blinkt', - version='0.1.2', - author='Philip Howard', - author_email='phil@pimoroni.com', - description="""Python library for driving Pimoroni Blinkt!""", - 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=['blinkt'], - install_requires=['RPi.GPIO'] -) diff --git a/library/tests/test_setup.py b/library/tests/test_setup.py deleted file mode 100644 index 21a0eaf..0000000 --- a/library/tests/test_setup.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Test Blinkt! basis initialisation.""" -import mock -import sys -from tools import GPIO - - -def test_setup(): - """Test init succeeds and GPIO pins are setup.""" - gpio = GPIO() - sys.modules['RPi'] = mock.Mock() - sys.modules['RPi'].GPIO = gpio - sys.modules['RPi.GPIO'] = gpio - import blinkt - blinkt.show() - - assert gpio.pin_modes[blinkt.DAT] == gpio.OUT - assert gpio.pin_modes[blinkt.CLK] == gpio.OUT diff --git a/library/tests/tools.py b/library/tests/tools.py deleted file mode 100644 index dd32697..0000000 --- a/library/tests/tools.py +++ /dev/null @@ -1,30 +0,0 @@ -# noqa D100 -class GPIO: - """Mock RPi.GPIO class. - - Stubs out enough of RPi.GPIO to validate pin states are set correctly. - - """ - - BCM = 1 - OUT = 1 - IN = 1 - - def __init__(self): # noqa D100 - self.pin_modes = {} - self.pin_states = {} - - def output(self, pin, value): # noqa D100 - self.pin_states[pin] = value - - def setmode(self, mode): # noqa D100 - pass - - def setwarnings(self, mode): # noqa D100 - pass - - def setup(self, pin, mode): # noqa D100 - self.pin_modes[pin] = mode - - def cleanup(self): # noqa D100 - pass diff --git a/library/tox.ini b/library/tox.ini deleted file mode 100644 index 3b58078..0000000 --- a/library/tox.ini +++ /dev/null @@ -1,24 +0,0 @@ -[tox] -envlist = py{27,35,37,39},qa -skip_missing_interpreters = True - -[testenv] -commands = - python setup.py install - coverage run -m py.test -v -r wsx - coverage report -deps = - mock - pytest>=3.1 - pytest-cov - -[testenv:qa] -commands = - flake8 - flake8 ../examples/ - rstcheck README.rst -deps = - flake8 - flake8-docstrings - flake8-quotes - rstcheck diff --git a/library_c/CHANGELOG.txt b/library_c/CHANGELOG.txt deleted file mode 100644 index e69de29..0000000 diff --git a/library_c/MANIFEST.in b/library_c/MANIFEST.in deleted file mode 100644 index 3eeee71..0000000 --- a/library_c/MANIFEST.in +++ /dev/null @@ -1,7 +0,0 @@ -include README.md -include README.txt -include CHANGELOG.txt -include setup.py -include blinkt_wrap.c -include blinkt.py -include lib/* diff --git a/library_c/Makefile b/library_c/Makefile deleted file mode 100644 index 74399eb..0000000 --- a/library_c/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - gcc -Wall -DTEST lib/blinkt.c -l bcm2835 -o blinkt - -devel: - -rm -r build - python setup.py build - sudo python setup.py develop diff --git a/library_c/README.md b/library_c/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/library_c/README.txt b/library_c/README.txt deleted file mode 100644 index e69de29..0000000 diff --git a/library_c/blinkt b/library_c/blinkt deleted file mode 100755 index e7fc42dd989f9b4fab84d7f83406b84cceb658e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58016 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 z 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⩔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 0: - raise ImportError("Blinkt requires root.") - -atexit.register(clean_exit) -%} diff --git a/library_c/blinkt.py b/library_c/blinkt.py deleted file mode 100644 index 343e104..0000000 --- a/library_c/blinkt.py +++ /dev/null @@ -1,120 +0,0 @@ -# This file was automatically generated by SWIG (http://www.swig.org). -# Version 3.0.2 -# -# Do not make changes to this file unless you know what you are doing--modify -# the SWIG interface file instead. - - - - - -from sys import version_info -if version_info >= (2,6,0): - def swig_import_helper(): - from os.path import dirname - import imp - fp = None - try: - fp, pathname, description = imp.find_module('_blinkt', [dirname(__file__)]) - except ImportError: - import _blinkt - return _blinkt - if fp is not None: - try: - _mod = imp.load_module('_blinkt', fp, pathname, description) - finally: - fp.close() - return _mod - _blinkt = swig_import_helper() - del swig_import_helper -else: - import _blinkt -del version_info -try: - _swig_property = property -except NameError: - pass # Python < 2.2 doesn't have 'property'. -def _swig_setattr_nondynamic(self,class_type,name,value,static=1): - if (name == "thisown"): return self.this.own(value) - if (name == "this"): - if type(value).__name__ == 'SwigPyObject': - self.__dict__[name] = value - return - method = class_type.__swig_setmethods__.get(name,None) - if method: return method(self,value) - if (not static): - self.__dict__[name] = value - else: - raise AttributeError("You cannot add attributes to %s" % self) - -def _swig_setattr(self,class_type,name,value): - return _swig_setattr_nondynamic(self,class_type,name,value,0) - -def _swig_getattr(self,class_type,name): - if (name == "thisown"): return self.this.own() - method = class_type.__swig_getmethods__.get(name,None) - if method: return method(self) - raise AttributeError(name) - -def _swig_repr(self): - try: strthis = "proxy of " + self.this.__repr__() - except: strthis = "" - return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) - -try: - _object = object - _newclass = 1 -except AttributeError: - class _object : pass - _newclass = 0 - - - -def clear(): - return _blinkt.clear() -clear = _blinkt.clear - -def set_pixel_uint32(*args): - return _blinkt.set_pixel_uint32(*args) -set_pixel_uint32 = _blinkt.set_pixel_uint32 - -def set_pixel(*args): - return _blinkt.set_pixel(*args) -set_pixel = _blinkt.set_pixel - -def set_pixel_brightness(*args): - return _blinkt.set_pixel_brightness(*args) -set_pixel_brightness = _blinkt.set_pixel_brightness - -def rgbb(*args): - return _blinkt.rgbb(*args) -rgbb = _blinkt.rgbb - -def rgb(*args): - return _blinkt.rgb(*args) -rgb = _blinkt.rgb - -def stop(): - return _blinkt.stop() -stop = _blinkt.stop - -def start(): - return _blinkt.start() -start = _blinkt.start - -def show(): - return _blinkt.show() -show = _blinkt.show -import atexit - -def clean_exit(): - stop() - -if start() > 0: - raise ImportError("Blinkt requires root.") - -atexit.register(clean_exit) - -# This file is compatible with both classic and new-style classes. - - diff --git a/library_c/blinkt_wrap.c b/library_c/blinkt_wrap.c deleted file mode 100644 index 45c6d78..0000000 --- a/library_c/blinkt_wrap.c +++ /dev/null @@ -1,4153 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 3.0.2 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -#define SWIGPYTHON -#define SWIG_PYTHON_DIRECTOR_NO_VTABLE - -/* ----------------------------------------------------------------------------- - * This section contains generic SWIG labels for method/variable - * declarations/attributes, and other compiler dependent labels. - * ----------------------------------------------------------------------------- */ - -/* template workaround for compilers that cannot correctly implement the C++ standard */ -#ifndef SWIGTEMPLATEDISAMBIGUATOR -# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) -# define SWIGTEMPLATEDISAMBIGUATOR template -# elif defined(__HP_aCC) -/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ -/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ -# define SWIGTEMPLATEDISAMBIGUATOR template -# else -# define SWIGTEMPLATEDISAMBIGUATOR -# endif -#endif - -/* inline attribute */ -#ifndef SWIGINLINE -# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) -# define SWIGINLINE inline -# else -# define SWIGINLINE -# endif -#endif - -/* attribute recognised by some compilers to avoid 'unused' warnings */ -#ifndef SWIGUNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -# elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -#endif - -#ifndef SWIG_MSC_UNSUPPRESS_4505 -# if defined(_MSC_VER) -# pragma warning(disable : 4505) /* unreferenced local function has been removed */ -# endif -#endif - -#ifndef SWIGUNUSEDPARM -# ifdef __cplusplus -# define SWIGUNUSEDPARM(p) -# else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED -# endif -#endif - -/* internal SWIG method */ -#ifndef SWIGINTERN -# define SWIGINTERN static SWIGUNUSED -#endif - -/* internal inline SWIG method */ -#ifndef SWIGINTERNINLINE -# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE -#endif - -/* exporting methods */ -#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# ifndef GCC_HASCLASSVISIBILITY -# define GCC_HASCLASSVISIBILITY -# endif -#endif - -#ifndef SWIGEXPORT -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if defined(STATIC_LINKED) -# define SWIGEXPORT -# else -# define SWIGEXPORT __declspec(dllexport) -# endif -# else -# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) -# define SWIGEXPORT __attribute__ ((visibility("default"))) -# else -# define SWIGEXPORT -# endif -# endif -#endif - -/* calling conventions for Windows */ -#ifndef SWIGSTDCALL -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# define SWIGSTDCALL __stdcall -# else -# define SWIGSTDCALL -# endif -#endif - -/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ -#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ -#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) -# define _SCL_SECURE_NO_DEPRECATE -#endif - - - -#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) -/* Use debug wrappers with the Python release dll */ -# undef _DEBUG -# include -# define _DEBUG -#else -# include -#endif - -/* ----------------------------------------------------------------------------- - * swigrun.swg - * - * This file contains generic C API SWIG runtime support for pointer - * type checking. - * ----------------------------------------------------------------------------- */ - -/* This should only be incremented when either the layout of swig_type_info changes, - or for whatever reason, the runtime changes incompatibly */ -#define SWIG_RUNTIME_VERSION "4" - -/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ -#ifdef SWIG_TYPE_TABLE -# define SWIG_QUOTE_STRING(x) #x -# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) -# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) -#else -# define SWIG_TYPE_TABLE_NAME -#endif - -/* - You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for - creating a static or dynamic library from the SWIG runtime code. - In 99.9% of the cases, SWIG just needs to declare them as 'static'. - - But only do this if strictly necessary, ie, if you have problems - with your compiler or suchlike. -*/ - -#ifndef SWIGRUNTIME -# define SWIGRUNTIME SWIGINTERN -#endif - -#ifndef SWIGRUNTIMEINLINE -# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE -#endif - -/* Generic buffer size */ -#ifndef SWIG_BUFFER_SIZE -# define SWIG_BUFFER_SIZE 1024 -#endif - -/* Flags for pointer conversions */ -#define SWIG_POINTER_DISOWN 0x1 -#define SWIG_CAST_NEW_MEMORY 0x2 - -/* Flags for new pointer objects */ -#define SWIG_POINTER_OWN 0x1 - - -/* - Flags/methods for returning states. - - The SWIG conversion methods, as ConvertPtr, return an integer - that tells if the conversion was successful or not. And if not, - an error code can be returned (see swigerrors.swg for the codes). - - Use the following macros/flags to set or process the returning - states. - - In old versions of SWIG, code such as the following was usually written: - - if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { - // success code - } else { - //fail code - } - - Now you can be more explicit: - - int res = SWIG_ConvertPtr(obj,vptr,ty.flags); - if (SWIG_IsOK(res)) { - // success code - } else { - // fail code - } - - which is the same really, but now you can also do - - Type *ptr; - int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); - if (SWIG_IsOK(res)) { - // success code - if (SWIG_IsNewObj(res) { - ... - delete *ptr; - } else { - ... - } - } else { - // fail code - } - - I.e., now SWIG_ConvertPtr can return new objects and you can - identify the case and take care of the deallocation. Of course that - also requires SWIG_ConvertPtr to return new result values, such as - - int SWIG_ConvertPtr(obj, ptr,...) { - if () { - if () { - *ptr = ; - return SWIG_NEWOBJ; - } else { - *ptr = ; - return SWIG_OLDOBJ; - } - } else { - return SWIG_BADOBJ; - } - } - - Of course, returning the plain '0(success)/-1(fail)' still works, but you can be - more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the - SWIG errors code. - - Finally, if the SWIG_CASTRANK_MODE is enabled, the result code - allows to return the 'cast rank', for example, if you have this - - int food(double) - int fooi(int); - - and you call - - food(1) // cast rank '1' (1 -> 1.0) - fooi(1) // cast rank '0' - - just use the SWIG_AddCast()/SWIG_CheckState() -*/ - -#define SWIG_OK (0) -#define SWIG_ERROR (-1) -#define SWIG_IsOK(r) (r >= 0) -#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) - -/* The CastRankLimit says how many bits are used for the cast rank */ -#define SWIG_CASTRANKLIMIT (1 << 8) -/* The NewMask denotes the object was created (using new/malloc) */ -#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) -/* The TmpMask is for in/out typemaps that use temporal objects */ -#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) -/* Simple returning values */ -#define SWIG_BADOBJ (SWIG_ERROR) -#define SWIG_OLDOBJ (SWIG_OK) -#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) -#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) -/* Check, add and del mask methods */ -#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) -#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) -#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) -#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) -#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) -#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) - -/* Cast-Rank Mode */ -#if defined(SWIG_CASTRANK_MODE) -# ifndef SWIG_TypeRank -# define SWIG_TypeRank unsigned long -# endif -# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ -# define SWIG_MAXCASTRANK (2) -# endif -# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) -# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) -SWIGINTERNINLINE int SWIG_AddCast(int r) { - return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; -} -SWIGINTERNINLINE int SWIG_CheckState(int r) { - return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; -} -#else /* no cast-rank mode */ -# define SWIG_AddCast(r) (r) -# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) -#endif - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void *(*swig_converter_func)(void *, int *); -typedef struct swig_type_info *(*swig_dycast_func)(void **); - -/* Structure to store information on one type */ -typedef struct swig_type_info { - const char *name; /* mangled name of this type */ - const char *str; /* human readable name of this type */ - swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ - struct swig_cast_info *cast; /* linked list of types that can cast into this type */ - void *clientdata; /* language specific type data */ - int owndata; /* flag if the structure owns the clientdata */ -} swig_type_info; - -/* Structure to store a type and conversion function used for casting */ -typedef struct swig_cast_info { - swig_type_info *type; /* pointer to type that is equivalent to this type */ - swig_converter_func converter; /* function to cast the void pointers */ - struct swig_cast_info *next; /* pointer to next cast in linked list */ - struct swig_cast_info *prev; /* pointer to the previous cast */ -} swig_cast_info; - -/* Structure used to store module information - * Each module generates one structure like this, and the runtime collects - * all of these structures and stores them in a circularly linked list.*/ -typedef struct swig_module_info { - swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ - size_t size; /* Number of types in this module */ - struct swig_module_info *next; /* Pointer to next element in circularly linked list */ - swig_type_info **type_initial; /* Array of initially generated type structures */ - swig_cast_info **cast_initial; /* Array of initially generated casting structures */ - void *clientdata; /* Language specific module data */ -} swig_module_info; - -/* - Compare two type names skipping the space characters, therefore - "char*" == "char *" and "Class" == "Class", etc. - - Return 0 when the two name types are equivalent, as in - strncmp, but skipping ' '. -*/ -SWIGRUNTIME int -SWIG_TypeNameComp(const char *f1, const char *l1, - const char *f2, const char *l2) { - for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { - while ((*f1 == ' ') && (f1 != l1)) ++f1; - while ((*f2 == ' ') && (f2 != l2)) ++f2; - if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; - } - return (int)((l1 - f1) - (l2 - f2)); -} - -/* - Check type equivalence in a name list like ||... - Return 0 if equal, -1 if nb < tb, 1 if nb > tb -*/ -SWIGRUNTIME int -SWIG_TypeCmp(const char *nb, const char *tb) { - int equiv = 1; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (equiv != 0 && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; - } - equiv = SWIG_TypeNameComp(nb, ne, tb, te); - if (*ne) ++ne; - } - return equiv; -} - -/* - Check type equivalence in a name list like ||... - Return 0 if not equal, 1 if equal -*/ -SWIGRUNTIME int -SWIG_TypeEquiv(const char *nb, const char *tb) { - return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0; -} - -/* - Check the typename -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheck(const char *c, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (strcmp(iter->type->name, c) == 0) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (iter->type == from) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Cast a pointer up an inheritance hierarchy -*/ -SWIGRUNTIMEINLINE void * -SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { - return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); -} - -/* - Dynamic pointer casting. Down an inheritance hierarchy -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { - swig_type_info *lastty = ty; - if (!ty || !ty->dcast) return ty; - while (ty && (ty->dcast)) { - ty = (*ty->dcast)(ptr); - if (ty) lastty = ty; - } - return lastty; -} - -/* - Return the name associated with this type -*/ -SWIGRUNTIMEINLINE const char * -SWIG_TypeName(const swig_type_info *ty) { - return ty->name; -} - -/* - Return the pretty name associated with this type, - that is an unmangled type name in a form presentable to the user. -*/ -SWIGRUNTIME const char * -SWIG_TypePrettyName(const swig_type_info *type) { - /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ - if (!type) return NULL; - if (type->str != NULL) { - const char *last_name = type->str; - const char *s; - for (s = type->str; *s; s++) - if (*s == '|') last_name = s+1; - return last_name; - } - else - return type->name; -} - -/* - Set the clientdata field for a type -*/ -SWIGRUNTIME void -SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { - swig_cast_info *cast = ti->cast; - /* if (ti->clientdata == clientdata) return; */ - ti->clientdata = clientdata; - - while (cast) { - if (!cast->converter) { - swig_type_info *tc = cast->type; - if (!tc->clientdata) { - SWIG_TypeClientData(tc, clientdata); - } - } - cast = cast->next; - } -} -SWIGRUNTIME void -SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { - SWIG_TypeClientData(ti, clientdata); - ti->owndata = 1; -} - -/* - Search for a swig_type_info structure only by mangled name - Search is a O(log #types) - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_MangledTypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - swig_module_info *iter = start; - do { - if (iter->size) { - size_t l = 0; - size_t r = iter->size - 1; - do { - /* since l+r >= 0, we can (>> 1) instead (/ 2) */ - size_t i = (l + r) >> 1; - const char *iname = iter->types[i]->name; - if (iname) { - int compare = strcmp(name, iname); - if (compare == 0) { - return iter->types[i]; - } else if (compare < 0) { - if (i) { - r = i - 1; - } else { - break; - } - } else if (compare > 0) { - l = i + 1; - } - } else { - break; /* should never happen */ - } - } while (l <= r); - } - iter = iter->next; - } while (iter != end); - return 0; -} - -/* - Search for a swig_type_info structure for either a mangled name or a human readable name. - It first searches the mangled names of the types, which is a O(log #types) - If a type is not found it then searches the human readable names, which is O(#types). - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - /* STEP 1: Search the name field using binary search */ - swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); - if (ret) { - return ret; - } else { - /* STEP 2: If the type hasn't been found, do a complete search - of the str field (the human readable name) */ - swig_module_info *iter = start; - do { - size_t i = 0; - for (; i < iter->size; ++i) { - if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) - return iter->types[i]; - } - iter = iter->next; - } while (iter != end); - } - - /* neither found a match */ - return 0; -} - -/* - Pack binary data into a string -*/ -SWIGRUNTIME char * -SWIG_PackData(char *c, void *ptr, size_t sz) { - static const char hex[17] = "0123456789abcdef"; - const unsigned char *u = (unsigned char *) ptr; - const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - unsigned char uu = *u; - *(c++) = hex[(uu & 0xf0) >> 4]; - *(c++) = hex[uu & 0xf]; - } - return c; -} - -/* - Unpack binary data from a string -*/ -SWIGRUNTIME const char * -SWIG_UnpackData(const char *c, void *ptr, size_t sz) { - unsigned char *u = (unsigned char *) ptr; - const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - char d = *(c++); - unsigned char uu; - if ((d >= '0') && (d <= '9')) - uu = ((d - '0') << 4); - else if ((d >= 'a') && (d <= 'f')) - uu = ((d - ('a'-10)) << 4); - else - return (char *) 0; - d = *(c++); - if ((d >= '0') && (d <= '9')) - uu |= (d - '0'); - else if ((d >= 'a') && (d <= 'f')) - uu |= (d - ('a'-10)); - else - return (char *) 0; - *u = uu; - } - return c; -} - -/* - Pack 'void *' into a string buffer. -*/ -SWIGRUNTIME char * -SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { - char *r = buff; - if ((2*sizeof(void *) + 2) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,&ptr,sizeof(void *)); - if (strlen(name) + 1 > (bsz - (r - buff))) return 0; - strcpy(r,name); - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - *ptr = (void *) 0; - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sizeof(void *)); -} - -SWIGRUNTIME char * -SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { - char *r = buff; - size_t lname = (name ? strlen(name) : 0); - if ((2*sz + 2 + lname) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,ptr,sz); - if (lname) { - strncpy(r,name,lname+1); - } else { - *r = 0; - } - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - memset(ptr,0,sz); - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sz); -} - -#ifdef __cplusplus -} -#endif - -/* Errors in SWIG */ -#define SWIG_UnknownError -1 -#define SWIG_IOError -2 -#define SWIG_RuntimeError -3 -#define SWIG_IndexError -4 -#define SWIG_TypeError -5 -#define SWIG_DivisionByZero -6 -#define SWIG_OverflowError -7 -#define SWIG_SyntaxError -8 -#define SWIG_ValueError -9 -#define SWIG_SystemError -10 -#define SWIG_AttributeError -11 -#define SWIG_MemoryError -12 -#define SWIG_NullReferenceError -13 - - - -/* Compatibility macros for Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - -#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) -#define PyInt_Check(x) PyLong_Check(x) -#define PyInt_AsLong(x) PyLong_AsLong(x) -#define PyInt_FromLong(x) PyLong_FromLong(x) -#define PyInt_FromSize_t(x) PyLong_FromSize_t(x) -#define PyString_Check(name) PyBytes_Check(name) -#define PyString_FromString(x) PyUnicode_FromString(x) -#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) -#define PyString_AsString(str) PyBytes_AsString(str) -#define PyString_Size(str) PyBytes_Size(str) -#define PyString_InternFromString(key) PyUnicode_InternFromString(key) -#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE -#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x) -#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) - -#endif - -#ifndef Py_TYPE -# define Py_TYPE(op) ((op)->ob_type) -#endif - -/* SWIG APIs for compatibility of both Python 2 & 3 */ - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_FromFormat PyUnicode_FromFormat -#else -# define SWIG_Python_str_FromFormat PyString_FromFormat -#endif - - -/* Warning: This function will allocate a new string in Python 3, - * so please call SWIG_Python_str_DelForPy3(x) to free the space. - */ -SWIGINTERN char* -SWIG_Python_str_AsChar(PyObject *str) -{ -#if PY_VERSION_HEX >= 0x03000000 - char *cstr; - char *newstr; - Py_ssize_t len; - str = PyUnicode_AsUTF8String(str); - PyBytes_AsStringAndSize(str, &cstr, &len); - newstr = (char *) malloc(len+1); - memcpy(newstr, cstr, len+1); - Py_XDECREF(str); - return newstr; -#else - return PyString_AsString(str); -#endif -} - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) -#else -# define SWIG_Python_str_DelForPy3(x) -#endif - - -SWIGINTERN PyObject* -SWIG_Python_str_FromChar(const char *c) -{ -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_FromString(c); -#else - return PyString_FromString(c); -#endif -} - -/* Add PyOS_snprintf for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# define PyOS_snprintf _snprintf -# else -# define PyOS_snprintf snprintf -# endif -#endif - -/* A crude PyString_FromFormat implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 - -#ifndef SWIG_PYBUFFER_SIZE -# define SWIG_PYBUFFER_SIZE 1024 -#endif - -static PyObject * -PyString_FromFormat(const char *fmt, ...) { - va_list ap; - char buf[SWIG_PYBUFFER_SIZE * 2]; - int res; - va_start(ap, fmt); - res = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); -} -#endif - -/* Add PyObject_Del for old Pythons */ -#if PY_VERSION_HEX < 0x01060000 -# define PyObject_Del(op) PyMem_DEL((op)) -#endif -#ifndef PyObject_DEL -# define PyObject_DEL PyObject_Del -#endif - -/* A crude PyExc_StopIteration exception for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# ifndef PyExc_StopIteration -# define PyExc_StopIteration PyExc_RuntimeError -# endif -# ifndef PyObject_GenericGetAttr -# define PyObject_GenericGetAttr 0 -# endif -#endif - -/* Py_NotImplemented is defined in 2.1 and up. */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef Py_NotImplemented -# define Py_NotImplemented PyExc_RuntimeError -# endif -#endif - -/* A crude PyString_AsStringAndSize implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef PyString_AsStringAndSize -# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} -# endif -#endif - -/* PySequence_Size for old Pythons */ -#if PY_VERSION_HEX < 0x02000000 -# ifndef PySequence_Size -# define PySequence_Size PySequence_Length -# endif -#endif - -/* PyBool_FromLong for old Pythons */ -#if PY_VERSION_HEX < 0x02030000 -static -PyObject *PyBool_FromLong(long ok) -{ - PyObject *result = ok ? Py_True : Py_False; - Py_INCREF(result); - return result; -} -#endif - -/* Py_ssize_t for old Pythons */ -/* This code is as recommended by: */ -/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -typedef inquiry lenfunc; -typedef intargfunc ssizeargfunc; -typedef intintargfunc ssizessizeargfunc; -typedef intobjargproc ssizeobjargproc; -typedef intintobjargproc ssizessizeobjargproc; -typedef getreadbufferproc readbufferproc; -typedef getwritebufferproc writebufferproc; -typedef getsegcountproc segcountproc; -typedef getcharbufferproc charbufferproc; -static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc)) -{ - long result = 0; - PyObject *i = PyNumber_Int(x); - if (i) { - result = PyInt_AsLong(i); - Py_DECREF(i); - } - return result; -} -#endif - -#if PY_VERSION_HEX < 0x02050000 -#define PyInt_FromSize_t(x) PyInt_FromLong((long)x) -#endif - -#if PY_VERSION_HEX < 0x02040000 -#define Py_VISIT(op) \ - do { \ - if (op) { \ - int vret = visit((op), arg); \ - if (vret) \ - return vret; \ - } \ - } while (0) -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef struct { - PyTypeObject type; - PyNumberMethods as_number; - PyMappingMethods as_mapping; - PySequenceMethods as_sequence; - PyBufferProcs as_buffer; - PyObject *name, *slots; -} PyHeapTypeObject; -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef destructor freefunc; -#endif - -#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \ - (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \ - (PY_MAJOR_VERSION > 3)) -# define SWIGPY_USE_CAPSULE -# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME) -#endif - -#if PY_VERSION_HEX < 0x03020000 -#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) -#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) -#endif - -/* ----------------------------------------------------------------------------- - * error manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIME PyObject* -SWIG_Python_ErrorType(int code) { - PyObject* type = 0; - switch(code) { - case SWIG_MemoryError: - type = PyExc_MemoryError; - break; - case SWIG_IOError: - type = PyExc_IOError; - break; - case SWIG_RuntimeError: - type = PyExc_RuntimeError; - break; - case SWIG_IndexError: - type = PyExc_IndexError; - break; - case SWIG_TypeError: - type = PyExc_TypeError; - break; - case SWIG_DivisionByZero: - type = PyExc_ZeroDivisionError; - break; - case SWIG_OverflowError: - type = PyExc_OverflowError; - break; - case SWIG_SyntaxError: - type = PyExc_SyntaxError; - break; - case SWIG_ValueError: - type = PyExc_ValueError; - break; - case SWIG_SystemError: - type = PyExc_SystemError; - break; - case SWIG_AttributeError: - type = PyExc_AttributeError; - break; - default: - type = PyExc_RuntimeError; - } - return type; -} - - -SWIGRUNTIME void -SWIG_Python_AddErrorMsg(const char* mesg) -{ - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - - if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - PyErr_Clear(); - Py_XINCREF(type); - - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - Py_DECREF(value); - } else { - PyErr_SetString(PyExc_RuntimeError, mesg); - } -} - -#if defined(SWIG_PYTHON_NO_THREADS) -# if defined(SWIG_PYTHON_THREADS) -# undef SWIG_PYTHON_THREADS -# endif -#endif -#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ -# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) -# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ -# define SWIG_PYTHON_USE_GIL -# endif -# endif -# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ -# ifndef SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() -# endif -# ifdef __cplusplus /* C++ code */ - class SWIG_Python_Thread_Block { - bool status; - PyGILState_STATE state; - public: - void end() { if (status) { PyGILState_Release(state); status = false;} } - SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} - ~SWIG_Python_Thread_Block() { end(); } - }; - class SWIG_Python_Thread_Allow { - bool status; - PyThreadState *save; - public: - void end() { if (status) { PyEval_RestoreThread(save); status = false; }} - SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} - ~SWIG_Python_Thread_Allow() { end(); } - }; -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block -# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow -# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() -# else /* C code */ -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() -# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() -# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) -# endif -# else /* Old thread way, not implemented, user must provide it */ -# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) -# define SWIG_PYTHON_INITIALIZE_THREADS -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) -# define SWIG_PYTHON_THREAD_END_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# endif -# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) -# define SWIG_PYTHON_THREAD_END_ALLOW -# endif -# endif -#else /* No thread support */ -# define SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# define SWIG_PYTHON_THREAD_END_BLOCK -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# define SWIG_PYTHON_THREAD_END_ALLOW -#endif - -/* ----------------------------------------------------------------------------- - * Python API portion that goes into the runtime - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* ----------------------------------------------------------------------------- - * Constant declarations - * ----------------------------------------------------------------------------- */ - -/* Constant Types */ -#define SWIG_PY_POINTER 4 -#define SWIG_PY_BINARY 5 - -/* Constant information structure */ -typedef struct swig_const_info { - int type; - char *name; - long lvalue; - double dvalue; - void *pvalue; - swig_type_info **ptype; -} swig_const_info; - - -/* ----------------------------------------------------------------------------- - * Wrapper of PyInstanceMethod_New() used in Python 3 - * It is exported to the generated module, used for -fastproxy - * ----------------------------------------------------------------------------- */ -#if PY_VERSION_HEX >= 0x03000000 -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) -{ - return PyInstanceMethod_New(func); -} -#else -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func)) -{ - return NULL; -} -#endif - -#ifdef __cplusplus -} -#endif - - -/* ----------------------------------------------------------------------------- - * pyrun.swg - * - * This file contains the runtime support for Python modules - * and includes code for managing global variables and pointer - * type checking. - * - * ----------------------------------------------------------------------------- */ - -/* Common SWIG API */ - -/* for raw pointers */ -#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) -#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) -#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) - -#ifdef SWIGPYTHON_BUILTIN -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags) -#else -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) -#endif - -#define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) - -#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) -#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) -#define swig_owntype int - -/* for raw packed data */ -#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - -/* for class or struct pointers */ -#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) -#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) - -/* for C or C++ function pointers */ -#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) -#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0) - -/* for C++ member pointers, ie, member methods */ -#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - - -/* Runtime API */ - -#define SWIG_GetModule(clientdata) SWIG_Python_GetModule(clientdata) -#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) -#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) - -#define SWIG_SetErrorObj SWIG_Python_SetErrorObj -#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg -#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) -#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) -#define SWIG_fail goto fail - - -/* Runtime API implementation */ - -/* Error manipulation */ - -SWIGINTERN void -SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetObject(errtype, obj); - Py_DECREF(obj); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -SWIGINTERN void -SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(errtype, msg); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) - -/* Set a constant value */ - -#if defined(SWIGPYTHON_BUILTIN) - -SWIGINTERN void -SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { - PyObject *s = PyString_InternFromString(key); - PyList_Append(seq, s); - Py_DECREF(s); -} - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else - PyDict_SetItemString(d, name, obj); -#endif - Py_DECREF(obj); - if (public_interface) - SwigPyBuiltin_AddPublicSymbol(public_interface, name); -} - -#else - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else - PyDict_SetItemString(d, name, obj); -#endif - Py_DECREF(obj); -} - -#endif - -/* Append a value to the result obj */ - -SWIGINTERN PyObject* -SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { -#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyList_Check(result)) { - PyObject *o2 = result; - result = PyList_New(1); - PyList_SetItem(result, 0, o2); - } - PyList_Append(result,obj); - Py_DECREF(obj); - } - return result; -#else - PyObject* o2; - PyObject* o3; - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyTuple_Check(result)) { - o2 = result; - result = PyTuple_New(1); - PyTuple_SET_ITEM(result, 0, o2); - } - o3 = PyTuple_New(1); - PyTuple_SET_ITEM(o3, 0, obj); - o2 = result; - result = PySequence_Concat(o2, o3); - Py_DECREF(o2); - Py_DECREF(o3); - } - return result; -#endif -} - -/* Unpack the argument tuple */ - -SWIGINTERN int -SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) -{ - if (!args) { - if (!min && !max) { - return 1; - } else { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", - name, (min == max ? "" : "at least "), (int)min); - return 0; - } - } - if (!PyTuple_Check(args)) { - if (min <= 1 && max >= 1) { - int i; - objs[0] = args; - for (i = 1; i < max; ++i) { - objs[i] = 0; - } - return 2; - } - PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); - return 0; - } else { - Py_ssize_t l = PyTuple_GET_SIZE(args); - if (l < min) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at least "), (int)min, (int)l); - return 0; - } else if (l > max) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at most "), (int)max, (int)l); - return 0; - } else { - int i; - for (i = 0; i < l; ++i) { - objs[i] = PyTuple_GET_ITEM(args, i); - } - for (; l < max; ++l) { - objs[l] = 0; - } - return i + 1; - } - } -} - -/* A functor is a function object with one single object argument */ -#if PY_VERSION_HEX >= 0x02020000 -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); -#else -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); -#endif - -/* - Helper for static pointer initialization for both C and C++ code, for example - static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); -*/ -#ifdef __cplusplus -#define SWIG_STATIC_POINTER(var) var -#else -#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var -#endif - -/* ----------------------------------------------------------------------------- - * Pointer declarations - * ----------------------------------------------------------------------------- */ - -/* Flags for new pointer objects */ -#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) -#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) - -#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) - -#define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2) -#define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN) - -#ifdef __cplusplus -extern "C" { -#endif - -/* How to access Py_None */ -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef SWIG_PYTHON_NO_BUILD_NONE -# ifndef SWIG_PYTHON_BUILD_NONE -# define SWIG_PYTHON_BUILD_NONE -# endif -# endif -#endif - -#ifdef SWIG_PYTHON_BUILD_NONE -# ifdef Py_None -# undef Py_None -# define Py_None SWIG_Py_None() -# endif -SWIGRUNTIMEINLINE PyObject * -_SWIG_Py_None(void) -{ - PyObject *none = Py_BuildValue((char*)""); - Py_DECREF(none); - return none; -} -SWIGRUNTIME PyObject * -SWIG_Py_None(void) -{ - static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); - return none; -} -#endif - -/* The python void return value */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Py_Void(void) -{ - PyObject *none = Py_None; - Py_INCREF(none); - return none; -} - -/* SwigPyClientData */ - -typedef struct { - PyObject *klass; - PyObject *newraw; - PyObject *newargs; - PyObject *destroy; - int delargs; - int implicitconv; - PyTypeObject *pytype; -} SwigPyClientData; - -SWIGRUNTIMEINLINE int -SWIG_Python_CheckImplicit(swig_type_info *ty) -{ - SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; - return data ? data->implicitconv : 0; -} - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_ExceptionType(swig_type_info *desc) { - SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; - PyObject *klass = data ? data->klass : 0; - return (klass ? klass : PyExc_RuntimeError); -} - - -SWIGRUNTIME SwigPyClientData * -SwigPyClientData_New(PyObject* obj) -{ - if (!obj) { - return 0; - } else { - SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); - /* the klass element */ - data->klass = obj; - Py_INCREF(data->klass); - /* the newraw method and newargs arguments used to create a new raw instance */ - if (PyClass_Check(obj)) { - data->newraw = 0; - data->newargs = obj; - Py_INCREF(obj); - } else { -#if (PY_VERSION_HEX < 0x02020000) - data->newraw = 0; -#else - data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); -#endif - if (data->newraw) { - Py_INCREF(data->newraw); - data->newargs = PyTuple_New(1); - PyTuple_SetItem(data->newargs, 0, obj); - } else { - data->newargs = obj; - } - Py_INCREF(data->newargs); - } - /* the destroy method, aka as the C++ delete method */ - data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); - if (PyErr_Occurred()) { - PyErr_Clear(); - data->destroy = 0; - } - if (data->destroy) { - int flags; - Py_INCREF(data->destroy); - flags = PyCFunction_GET_FLAGS(data->destroy); -#ifdef METH_O - data->delargs = !(flags & (METH_O)); -#else - data->delargs = 0; -#endif - } else { - data->delargs = 0; - } - data->implicitconv = 0; - data->pytype = 0; - return data; - } -} - -SWIGRUNTIME void -SwigPyClientData_Del(SwigPyClientData *data) { - Py_XDECREF(data->newraw); - Py_XDECREF(data->newargs); - Py_XDECREF(data->destroy); -} - -/* =============== SwigPyObject =====================*/ - -typedef struct { - PyObject_HEAD - void *ptr; - swig_type_info *ty; - int own; - PyObject *next; -#ifdef SWIGPYTHON_BUILTIN - PyObject *dict; -#endif -} SwigPyObject; - -SWIGRUNTIME PyObject * -SwigPyObject_long(SwigPyObject *v) -{ - return PyLong_FromVoidPtr(v->ptr); -} - -SWIGRUNTIME PyObject * -SwigPyObject_format(const char* fmt, SwigPyObject *v) -{ - PyObject *res = NULL; - PyObject *args = PyTuple_New(1); - if (args) { - if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { - PyObject *ofmt = SWIG_Python_str_FromChar(fmt); - if (ofmt) { -#if PY_VERSION_HEX >= 0x03000000 - res = PyUnicode_Format(ofmt,args); -#else - res = PyString_Format(ofmt,args); -#endif - Py_DECREF(ofmt); - } - Py_DECREF(args); - } - } - return res; -} - -SWIGRUNTIME PyObject * -SwigPyObject_oct(SwigPyObject *v) -{ - return SwigPyObject_format("%o",v); -} - -SWIGRUNTIME PyObject * -SwigPyObject_hex(SwigPyObject *v) -{ - return SwigPyObject_format("%x",v); -} - -SWIGRUNTIME PyObject * -#ifdef METH_NOARGS -SwigPyObject_repr(SwigPyObject *v) -#else -SwigPyObject_repr(SwigPyObject *v, PyObject *args) -#endif -{ - const char *name = SWIG_TypePrettyName(v->ty); - PyObject *repr = SWIG_Python_str_FromFormat("", (name ? name : "unknown"), (void *)v); - if (v->next) { -# ifdef METH_NOARGS - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); -# else - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); -# endif -# if PY_VERSION_HEX >= 0x03000000 - PyObject *joined = PyUnicode_Concat(repr, nrep); - Py_DecRef(repr); - Py_DecRef(nrep); - repr = joined; -# else - PyString_ConcatAndDel(&repr,nrep); -# endif - } - return repr; -} - -SWIGRUNTIME int -SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) -{ - void *i = v->ptr; - void *j = w->ptr; - return (i < j) ? -1 : ((i > j) ? 1 : 0); -} - -/* Added for Python 3.x, would it also be useful for Python 2.x? */ -SWIGRUNTIME PyObject* -SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) -{ - PyObject* res; - if( op != Py_EQ && op != Py_NE ) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0); - return res; -} - - -SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void); - -#ifdef SWIGPYTHON_BUILTIN -static swig_type_info *SwigPyObject_stype = 0; -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - SwigPyClientData *cd; - assert(SwigPyObject_stype); - cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; - assert(cd); - assert(cd->pytype); - return cd->pytype; -} -#else -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce(); - return type; -} -#endif - -SWIGRUNTIMEINLINE int -SwigPyObject_Check(PyObject *op) { -#ifdef SWIGPYTHON_BUILTIN - PyTypeObject *target_tp = SwigPyObject_type(); - if (PyType_IsSubtype(op->ob_type, target_tp)) - return 1; - return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0); -#else - return (Py_TYPE(op) == SwigPyObject_type()) - || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); -#endif -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own); - -SWIGRUNTIME void -SwigPyObject_dealloc(PyObject *v) -{ - SwigPyObject *sobj = (SwigPyObject *) v; - PyObject *next = sobj->next; - if (sobj->own == SWIG_POINTER_OWN) { - swig_type_info *ty = sobj->ty; - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - PyObject *destroy = data ? data->destroy : 0; - if (destroy) { - /* destroy is always a VARARGS method */ - PyObject *res; - if (data->delargs) { - /* we need to create a temporary object to carry the destroy operation */ - PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); - res = SWIG_Python_CallFunctor(destroy, tmp); - Py_DECREF(tmp); - } else { - PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); - PyObject *mself = PyCFunction_GET_SELF(destroy); - res = ((*meth)(mself, v)); - } - Py_XDECREF(res); - } -#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) - else { - const char *name = SWIG_TypePrettyName(ty); - printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); - } -#endif - } - Py_XDECREF(next); - PyObject_DEL(v); -} - -SWIGRUNTIME PyObject* -SwigPyObject_append(PyObject* v, PyObject* next) -{ - SwigPyObject *sobj = (SwigPyObject *) v; -#ifndef METH_O - PyObject *tmp = 0; - if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; - next = tmp; -#endif - if (!SwigPyObject_Check(next)) { - return NULL; - } - sobj->next = next; - Py_INCREF(next); - return SWIG_Py_Void(); -} - -SWIGRUNTIME PyObject* -#ifdef METH_NOARGS -SwigPyObject_next(PyObject* v) -#else -SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *) v; - if (sobj->next) { - Py_INCREF(sobj->next); - return sobj->next; - } else { - return SWIG_Py_Void(); - } -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_disown(PyObject *v) -#else -SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = 0; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_acquire(PyObject *v) -#else -SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = SWIG_POINTER_OWN; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -SwigPyObject_own(PyObject *v, PyObject *args) -{ - PyObject *val = 0; -#if (PY_VERSION_HEX < 0x02020000) - if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) -#elif (PY_VERSION_HEX < 0x02050000) - if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) -#else - if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) -#endif - { - return NULL; - } - else - { - SwigPyObject *sobj = (SwigPyObject *)v; - PyObject *obj = PyBool_FromLong(sobj->own); - if (val) { -#ifdef METH_NOARGS - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v); - } else { - SwigPyObject_disown(v); - } -#else - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v,args); - } else { - SwigPyObject_disown(v,args); - } -#endif - } - return obj; - } -} - -#ifdef METH_O -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#else -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"aquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#endif - -#if PY_VERSION_HEX < 0x02020000 -SWIGINTERN PyObject * -SwigPyObject_getattr(SwigPyObject *sobj,char *name) -{ - return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); -} -#endif - -SWIGRUNTIME PyTypeObject* -SwigPyObject_TypeOnce(void) { - static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; - - static PyNumberMethods SwigPyObject_as_number = { - (binaryfunc)0, /*nb_add*/ - (binaryfunc)0, /*nb_subtract*/ - (binaryfunc)0, /*nb_multiply*/ - /* nb_divide removed in Python 3 */ -#if PY_VERSION_HEX < 0x03000000 - (binaryfunc)0, /*nb_divide*/ -#endif - (binaryfunc)0, /*nb_remainder*/ - (binaryfunc)0, /*nb_divmod*/ - (ternaryfunc)0,/*nb_power*/ - (unaryfunc)0, /*nb_negative*/ - (unaryfunc)0, /*nb_positive*/ - (unaryfunc)0, /*nb_absolute*/ - (inquiry)0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ -#if PY_VERSION_HEX < 0x03000000 - 0, /*nb_coerce*/ -#endif - (unaryfunc)SwigPyObject_long, /*nb_int*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_long, /*nb_long*/ -#else - 0, /*nb_reserved*/ -#endif - (unaryfunc)0, /*nb_float*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_oct, /*nb_oct*/ - (unaryfunc)SwigPyObject_hex, /*nb_hex*/ -#endif -#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ -#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ -#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ -#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ - 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ -#endif - }; - - static PyTypeObject swigpyobject_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyObject", /* tp_name */ - sizeof(SwigPyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyObject_dealloc, /* tp_dealloc */ - 0, /* tp_print */ -#if PY_VERSION_HEX < 0x02020000 - (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ -#else - (getattrfunc)0, /* tp_getattr */ -#endif - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX >= 0x03000000 - 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ -#else - (cmpfunc)SwigPyObject_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyObject_repr, /* tp_repr */ - &SwigPyObject_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigobject_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - swigobject_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - swigpyobject_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpyobject_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&swigpyobject_type) < 0) - return NULL; -#endif - } - return &swigpyobject_type; -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own) -{ - SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); - if (sobj) { - sobj->ptr = ptr; - sobj->ty = ty; - sobj->own = own; - sobj->next = 0; - } - return (PyObject *)sobj; -} - -/* ----------------------------------------------------------------------------- - * Implements a simple Swig Packed type, and use it instead of string - * ----------------------------------------------------------------------------- */ - -typedef struct { - PyObject_HEAD - void *pack; - swig_type_info *ty; - size_t size; -} SwigPyPacked; - -SWIGRUNTIME int -SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char result[SWIG_BUFFER_SIZE]; - fputs("pack, v->size, 0, sizeof(result))) { - fputs("at ", fp); - fputs(result, fp); - } - fputs(v->ty->name,fp); - fputs(">", fp); - return 0; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_repr(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { - return SWIG_Python_str_FromFormat("", result, v->ty->name); - } else { - return SWIG_Python_str_FromFormat("", v->ty->name); - } -} - -SWIGRUNTIME PyObject * -SwigPyPacked_str(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ - return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); - } else { - return SWIG_Python_str_FromChar(v->ty->name); - } -} - -SWIGRUNTIME int -SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) -{ - size_t i = v->size; - size_t j = w->size; - int s = (i < j) ? -1 : ((i > j) ? 1 : 0); - return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); -} - -SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce(); - return type; -} - -SWIGRUNTIMEINLINE int -SwigPyPacked_Check(PyObject *op) { - return ((op)->ob_type == SwigPyPacked_TypeOnce()) - || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); -} - -SWIGRUNTIME void -SwigPyPacked_dealloc(PyObject *v) -{ - if (SwigPyPacked_Check(v)) { - SwigPyPacked *sobj = (SwigPyPacked *) v; - free(sobj->pack); - } - PyObject_DEL(v); -} - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_TypeOnce(void) { - static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; - static PyTypeObject swigpypacked_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX>=0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyPacked", /* tp_name */ - sizeof(SwigPyPacked), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ - (printfunc)SwigPyPacked_print, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX>=0x03000000 - 0, /* tp_reserved in 3.0.1 */ -#else - (cmpfunc)SwigPyPacked_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyPacked_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)SwigPyPacked_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigpacked_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - swigpypacked_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpypacked_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&swigpypacked_type) < 0) - return NULL; -#endif - } - return &swigpypacked_type; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) -{ - SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); - if (sobj) { - void *pack = malloc(size); - if (pack) { - memcpy(pack, ptr, size); - sobj->pack = pack; - sobj->ty = ty; - sobj->size = size; - } else { - PyObject_DEL((PyObject *) sobj); - sobj = 0; - } - } - return (PyObject *) sobj; -} - -SWIGRUNTIME swig_type_info * -SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) -{ - if (SwigPyPacked_Check(obj)) { - SwigPyPacked *sobj = (SwigPyPacked *)obj; - if (sobj->size != size) return 0; - memcpy(ptr, sobj->pack, size); - return sobj->ty; - } else { - return 0; - } -} - -/* ----------------------------------------------------------------------------- - * pointers/data manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIMEINLINE PyObject * -_SWIG_This(void) -{ - return SWIG_Python_str_FromChar("this"); -} - -static PyObject *swig_this = NULL; - -SWIGRUNTIME PyObject * -SWIG_This(void) -{ - if (swig_this == NULL) - swig_this = _SWIG_This(); - return swig_this; -} - -/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ - -/* TODO: I don't know how to implement the fast getset in Python 3 right now */ -#if PY_VERSION_HEX>=0x03000000 -#define SWIG_PYTHON_SLOW_GETSET_THIS -#endif - -SWIGRUNTIME SwigPyObject * -SWIG_Python_GetSwigThis(PyObject *pyobj) -{ - PyObject *obj; - - if (SwigPyObject_Check(pyobj)) - return (SwigPyObject *) pyobj; - -#ifdef SWIGPYTHON_BUILTIN - (void)obj; -# ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - pyobj = PyWeakref_GET_OBJECT(pyobj); - if (pyobj && SwigPyObject_Check(pyobj)) - return (SwigPyObject*) pyobj; - } -# endif - return NULL; -#else - - obj = 0; - -#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) - if (PyInstance_Check(pyobj)) { - obj = _PyInstance_Lookup(pyobj, SWIG_This()); - } else { - PyObject **dictptr = _PyObject_GetDictPtr(pyobj); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; - } else { -#ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); - return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; - } -#endif - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } - } - } -#else - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } -#endif - if (obj && !SwigPyObject_Check(obj)) { - /* a PyObject is called 'this', try to get the 'real this' - SwigPyObject from it */ - return SWIG_Python_GetSwigThis(obj); - } - return (SwigPyObject *)obj; -#endif -} - -/* Acquire a pointer value */ - -SWIGRUNTIME int -SWIG_Python_AcquirePtr(PyObject *obj, int own) { - if (own == SWIG_POINTER_OWN) { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (sobj) { - int oldown = sobj->own; - sobj->own = own; - return oldown; - } - } - return 0; -} - -/* Convert a pointer value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { - int res; - SwigPyObject *sobj; - int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0; - - if (!obj) - return SWIG_ERROR; - if (obj == Py_None && !implicit_conv) { - if (ptr) - *ptr = 0; - return SWIG_OK; - } - - res = SWIG_ERROR; - - sobj = SWIG_Python_GetSwigThis(obj); - if (own) - *own = 0; - while (sobj) { - void *vptr = sobj->ptr; - if (ty) { - swig_type_info *to = sobj->ty; - if (to == ty) { - /* no type cast needed */ - if (ptr) *ptr = vptr; - break; - } else { - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) { - sobj = (SwigPyObject *)sobj->next; - } else { - if (ptr) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ - if (own) - *own = *own | SWIG_CAST_NEW_MEMORY; - } - } - break; - } - } - } else { - if (ptr) *ptr = vptr; - break; - } - } - if (sobj) { - if (own) - *own = *own | sobj->own; - if (flags & SWIG_POINTER_DISOWN) { - sobj->own = 0; - } - res = SWIG_OK; - } else { - if (implicit_conv) { - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - if (data && !data->implicitconv) { - PyObject *klass = data->klass; - if (klass) { - PyObject *impconv; - data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ - impconv = SWIG_Python_CallFunctor(klass, obj); - data->implicitconv = 0; - if (PyErr_Occurred()) { - PyErr_Clear(); - impconv = 0; - } - if (impconv) { - SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); - if (iobj) { - void *vptr; - res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); - if (SWIG_IsOK(res)) { - if (ptr) { - *ptr = vptr; - /* transfer the ownership to 'ptr' */ - iobj->own = 0; - res = SWIG_AddCast(res); - res = SWIG_AddNewMask(res); - } else { - res = SWIG_AddCast(res); - } - } - } - Py_DECREF(impconv); - } - } - } - } - if (!SWIG_IsOK(res) && obj == Py_None) { - if (ptr) - *ptr = 0; - if (PyErr_Occurred()) - PyErr_Clear(); - res = SWIG_OK; - } - } - return res; -} - -/* Convert a function ptr value */ - -SWIGRUNTIME int -SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { - if (!PyCFunction_Check(obj)) { - return SWIG_ConvertPtr(obj, ptr, ty, 0); - } else { - void *vptr = 0; - - /* here we get the method pointer for callbacks */ - const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); - const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; - if (desc) - desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; - if (!desc) - return SWIG_ERROR; - if (ty) { - swig_cast_info *tc = SWIG_TypeCheck(desc,ty); - if (tc) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } else { - return SWIG_ERROR; - } - } else { - *ptr = vptr; - } - return SWIG_OK; - } -} - -/* Convert a packed value value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { - swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); - if (!to) return SWIG_ERROR; - if (ty) { - if (to != ty) { - /* check type cast? */ - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) return SWIG_ERROR; - } - } - return SWIG_OK; -} - -/* ----------------------------------------------------------------------------- - * Create a new pointer object - * ----------------------------------------------------------------------------- */ - -/* - Create a new instance object, without calling __init__, and set the - 'this' attribute. -*/ - -SWIGRUNTIME PyObject* -SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) -{ -#if (PY_VERSION_HEX >= 0x02020000) - PyObject *inst = 0; - PyObject *newraw = data->newraw; - if (newraw) { - inst = PyObject_Call(newraw, data->newargs, NULL); - if (inst) { -#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - PyDict_SetItem(dict, SWIG_This(), swig_this); - } - } -#else - PyObject *key = SWIG_This(); - PyObject_SetAttr(inst, key, swig_this); -#endif - } - } else { -#if PY_VERSION_HEX >= 0x03000000 - inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); - if (inst) { - PyObject_SetAttr(inst, SWIG_This(), swig_this); - Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; - } -#else - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } -#endif - } - return inst; -#else -#if (PY_VERSION_HEX >= 0x02010000) - PyObject *inst = 0; - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } - return (PyObject *) inst; -#else - PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); - if (inst == NULL) { - return NULL; - } - inst->in_class = (PyClassObject *)data->newargs; - Py_INCREF(inst->in_class); - inst->in_dict = PyDict_New(); - if (inst->in_dict == NULL) { - Py_DECREF(inst); - return NULL; - } -#ifdef Py_TPFLAGS_HAVE_WEAKREFS - inst->in_weakreflist = NULL; -#endif -#ifdef Py_TPFLAGS_GC - PyObject_GC_Init(inst); -#endif - PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); - return (PyObject *) inst; -#endif -#endif -} - -SWIGRUNTIME void -SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) -{ - PyObject *dict; -#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - } - PyDict_SetItem(dict, SWIG_This(), swig_this); - return; - } -#endif - dict = PyObject_GetAttrString(inst, (char*)"__dict__"); - PyDict_SetItem(dict, SWIG_This(), swig_this); - Py_DECREF(dict); -} - - -SWIGINTERN PyObject * -SWIG_Python_InitShadowInstance(PyObject *args) { - PyObject *obj[2]; - if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) { - return NULL; - } else { - SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); - if (sthis) { - SwigPyObject_append((PyObject*) sthis, obj[1]); - } else { - SWIG_Python_SetSwigThis(obj[0], obj[1]); - } - return SWIG_Py_Void(); - } -} - -/* Create a new pointer object */ - -SWIGRUNTIME PyObject * -SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) { - SwigPyClientData *clientdata; - PyObject * robj; - int own; - - if (!ptr) - return SWIG_Py_Void(); - - clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; - own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; - if (clientdata && clientdata->pytype) { - SwigPyObject *newobj; - if (flags & SWIG_BUILTIN_TP_INIT) { - newobj = (SwigPyObject*) self; - if (newobj->ptr) { - PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0); - while (newobj->next) - newobj = (SwigPyObject *) newobj->next; - newobj->next = next_self; - newobj = (SwigPyObject *)next_self; - } - } else { - newobj = PyObject_New(SwigPyObject, clientdata->pytype); - } - if (newobj) { - newobj->ptr = ptr; - newobj->ty = type; - newobj->own = own; - newobj->next = 0; -#ifdef SWIGPYTHON_BUILTIN - newobj->dict = 0; -#endif - return (PyObject*) newobj; - } - return SWIG_Py_Void(); - } - - assert(!(flags & SWIG_BUILTIN_TP_INIT)); - - robj = SwigPyObject_New(ptr, type, own); - if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { - PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); - Py_DECREF(robj); - robj = inst; - } - return robj; -} - -/* Create a new packed object */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { - return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); -} - -/* -----------------------------------------------------------------------------* - * Get type list - * -----------------------------------------------------------------------------*/ - -#ifdef SWIG_LINK_RUNTIME -void *SWIG_ReturnGlobalTypeList(void *); -#endif - -SWIGRUNTIME swig_module_info * -SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { - static void *type_pointer = (void *)0; - /* first check if module already created */ - if (!type_pointer) { -#ifdef SWIG_LINK_RUNTIME - type_pointer = SWIG_ReturnGlobalTypeList((void *)0); -#else -# ifdef SWIGPY_USE_CAPSULE - type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); -# else - type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); -# endif - if (PyErr_Occurred()) { - PyErr_Clear(); - type_pointer = (void *)0; - } -#endif - } - return (swig_module_info *) type_pointer; -} - -#if PY_MAJOR_VERSION < 2 -/* PyModule_AddObject function was introduced in Python 2.0. The following function - is copied out of Python/modsupport.c in python version 2.3.4 */ -SWIGINTERN int -PyModule_AddObject(PyObject *m, char *name, PyObject *o) -{ - PyObject *dict; - if (!PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, - "PyModule_AddObject() needs module as first arg"); - return SWIG_ERROR; - } - if (!o) { - PyErr_SetString(PyExc_TypeError, - "PyModule_AddObject() needs non-NULL value"); - return SWIG_ERROR; - } - - dict = PyModule_GetDict(m); - if (dict == NULL) { - /* Internal error -- modules must have a dict! */ - PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", - PyModule_GetName(m)); - return SWIG_ERROR; - } - if (PyDict_SetItemString(dict, name, o)) - return SWIG_ERROR; - Py_DECREF(o); - return SWIG_OK; -} -#endif - -SWIGRUNTIME void -#ifdef SWIGPY_USE_CAPSULE -SWIG_Python_DestroyModule(PyObject *obj) -#else -SWIG_Python_DestroyModule(void *vptr) -#endif -{ -#ifdef SWIGPY_USE_CAPSULE - swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); -#else - swig_module_info *swig_module = (swig_module_info *) vptr; -#endif - swig_type_info **types = swig_module->types; - size_t i; - for (i =0; i < swig_module->size; ++i) { - swig_type_info *ty = types[i]; - if (ty->owndata) { - SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; - if (data) SwigPyClientData_Del(data); - } - } - Py_DECREF(SWIG_This()); - swig_this = NULL; -} - -SWIGRUNTIME void -SWIG_Python_SetModule(swig_module_info *swig_module) { -#if PY_VERSION_HEX >= 0x03000000 - /* Add a dummy module object into sys.modules */ - PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); -#else - static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */ - PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); -#endif -#ifdef SWIGPY_USE_CAPSULE - PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#else - PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#endif -} - -/* The python cached type query */ -SWIGRUNTIME PyObject * -SWIG_Python_TypeCache(void) { - static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); - return cache; -} - -SWIGRUNTIME swig_type_info * -SWIG_Python_TypeQuery(const char *type) -{ - PyObject *cache = SWIG_Python_TypeCache(); - PyObject *key = SWIG_Python_str_FromChar(type); - PyObject *obj = PyDict_GetItem(cache, key); - swig_type_info *descriptor; - if (obj) { -#ifdef SWIGPY_USE_CAPSULE - descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL); -#else - descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); -#endif - } else { - swig_module_info *swig_module = SWIG_GetModule(0); - descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); - if (descriptor) { -#ifdef SWIGPY_USE_CAPSULE - obj = PyCapsule_New((void*) descriptor, NULL, NULL); -#else - obj = PyCObject_FromVoidPtr(descriptor, NULL); -#endif - PyDict_SetItem(cache, key, obj); - Py_DECREF(obj); - } - } - Py_DECREF(key); - return descriptor; -} - -/* - For backward compatibility only -*/ -#define SWIG_POINTER_EXCEPTION 0 -#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) -#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) - -SWIGRUNTIME int -SWIG_Python_AddErrMesg(const char* mesg, int infront) -{ - if (PyErr_Occurred()) { - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - Py_XINCREF(type); - PyErr_Clear(); - if (infront) { - PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); - } else { - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - } - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - } - return 1; - } else { - return 0; - } -} - -SWIGRUNTIME int -SWIG_Python_ArgFail(int argnum) -{ - if (PyErr_Occurred()) { - /* add information about failing argument */ - char mesg[256]; - PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); - return SWIG_Python_AddErrMesg(mesg, 1); - } else { - return 0; - } -} - -SWIGRUNTIMEINLINE const char * -SwigPyObject_GetDesc(PyObject *self) -{ - SwigPyObject *v = (SwigPyObject *)self; - swig_type_info *ty = v ? v->ty : 0; - return ty ? ty->str : ""; -} - -SWIGRUNTIME void -SWIG_Python_TypeError(const char *type, PyObject *obj) -{ - if (type) { -#if defined(SWIG_COBJECT_TYPES) - if (obj && SwigPyObject_Check(obj)) { - const char *otype = (const char *) SwigPyObject_GetDesc(obj); - if (otype) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", - type, otype); - return; - } - } else -#endif - { - const char *otype = (obj ? obj->ob_type->tp_name : 0); - if (otype) { - PyObject *str = PyObject_Str(obj); - const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; - if (cstr) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", - type, otype, cstr); - SWIG_Python_str_DelForPy3(cstr); - } else { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", - type, otype); - } - Py_XDECREF(str); - return; - } - } - PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); - } else { - PyErr_Format(PyExc_TypeError, "unexpected type is received"); - } -} - - -/* Convert a pointer value, signal an exception on a type mismatch */ -SWIGRUNTIME void * -SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) { - void *result; - if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { - PyErr_Clear(); -#if SWIG_POINTER_EXCEPTION - if (flags) { - SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); - SWIG_Python_ArgFail(argnum); - } -#endif - } - return result; -} - -#ifdef SWIGPYTHON_BUILTIN -SWIGRUNTIME int -SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { - PyTypeObject *tp = obj->ob_type; - PyObject *descr; - PyObject *encoded_name; - descrsetfunc f; - int res = -1; - -# ifdef Py_USING_UNICODE - if (PyString_Check(name)) { - name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL); - if (!name) - return -1; - } else if (!PyUnicode_Check(name)) -# else - if (!PyString_Check(name)) -# endif - { - PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); - return -1; - } else { - Py_INCREF(name); - } - - if (!tp->tp_dict) { - if (PyType_Ready(tp) < 0) - goto done; - } - - descr = _PyType_Lookup(tp, name); - f = NULL; - if (descr != NULL) - f = descr->ob_type->tp_descr_set; - if (!f) { - if (PyString_Check(name)) { - encoded_name = name; - Py_INCREF(name); - } else { - encoded_name = PyUnicode_AsUTF8String(name); - } - PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); - Py_DECREF(encoded_name); - } else { - res = f(descr, obj, value); - } - - done: - Py_DECREF(name); - return res; -} -#endif - - -#ifdef __cplusplus -} -#endif - - - -#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) - -#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else - - - -/* -------- TYPES TABLE (BEGIN) -------- */ - -#define SWIGTYPE_p_char swig_types[0] -#define SWIGTYPE_p_int swig_types[1] -#define SWIGTYPE_p_long_long swig_types[2] -#define SWIGTYPE_p_short swig_types[3] -#define SWIGTYPE_p_signed_char swig_types[4] -#define SWIGTYPE_p_unsigned_char swig_types[5] -#define SWIGTYPE_p_unsigned_int swig_types[6] -#define SWIGTYPE_p_unsigned_long_long swig_types[7] -#define SWIGTYPE_p_unsigned_short swig_types[8] -static swig_type_info *swig_types[10]; -static swig_module_info swig_module = {swig_types, 9, 0, 0, 0, 0}; -#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) -#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) - -/* -------- TYPES TABLE (END) -------- */ - -#if (PY_VERSION_HEX <= 0x02000000) -# if !defined(SWIG_PYTHON_CLASSIC) -# error "This python version requires swig to be run with the '-classic' option" -# endif -#endif - -/*----------------------------------------------- - @(target):= _blinkt.so - ------------------------------------------------*/ -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_init PyInit__blinkt - -#else -# define SWIG_init init_blinkt - -#endif -#define SWIG_name "_blinkt" - -#define SWIGVERSION 0x030002 -#define SWIG_VERSION SWIGVERSION - - -#define SWIG_as_voidptr(a) (void *)((const void *)(a)) -#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) - - -#include // Use the C99 official header - - -#include "lib/blinkt.h" - - -#include -#if !defined(SWIG_NO_LLONG_MAX) -# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) -# define LLONG_MAX __LONG_LONG_MAX__ -# define LLONG_MIN (-LLONG_MAX - 1LL) -# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) -# endif -#endif - - -SWIGINTERN int -SWIG_AsVal_double (PyObject *obj, double *val) -{ - int res = SWIG_TypeError; - if (PyFloat_Check(obj)) { - if (val) *val = PyFloat_AsDouble(obj); - return SWIG_OK; - } else if (PyInt_Check(obj)) { - if (val) *val = PyInt_AsLong(obj); - return SWIG_OK; - } else if (PyLong_Check(obj)) { - double v = PyLong_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - double d = PyFloat_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = d; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); - } else { - PyErr_Clear(); - } - } - } -#endif - return res; -} - - -#include - - -#include - - -SWIGINTERNINLINE int -SWIG_CanCastAsInteger(double *d, double min, double max) { - double x = *d; - if ((min <= x && x <= max)) { - double fx = floor(x); - double cx = ceil(x); - double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ - if ((errno == EDOM) || (errno == ERANGE)) { - errno = 0; - } else { - double summ, reps, diff; - if (rd < x) { - diff = x - rd; - } else if (rd > x) { - diff = rd - x; - } else { - return 1; - } - summ = rd + x; - reps = diff/summ; - if (reps < 8*DBL_EPSILON) { - *d = rd; - return 1; - } - } - } - return 0; -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) -{ -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(obj)) { - long v = PyInt_AsLong(obj); - if (v >= 0) { - if (val) *val = v; - return SWIG_OK; - } else { - return SWIG_OverflowError; - } - } else -#endif - if (PyLong_Check(obj)) { - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); -#if PY_VERSION_HEX >= 0x03000000 - { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (v < 0) { - return SWIG_OverflowError; - } - } else { - PyErr_Clear(); - } - } -#endif - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { - if (val) *val = (unsigned long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_char (PyObject * obj, unsigned char *val) -{ - unsigned long v; - int res = SWIG_AsVal_unsigned_SS_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v > UCHAR_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (unsigned char)(v); - } - } - return res; -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val) -{ - unsigned long v; - int res = SWIG_AsVal_unsigned_SS_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v > UINT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (unsigned int)(v); - } - } - return res; -} - - -SWIGINTERNINLINE PyObject* - SWIG_From_unsigned_SS_int (unsigned int value) -{ - return PyInt_FromSize_t((size_t) value); -} - - -SWIGINTERNINLINE PyObject* - SWIG_From_int (int value) -{ - return PyInt_FromLong((long) value); -} - -#ifdef __cplusplus -extern "C" { -#endif -SWIGINTERN PyObject *_wrap_clear(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - - if (!PyArg_ParseTuple(args,(char *)":clear")) SWIG_fail; - clear(); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_set_pixel_uint32(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t arg1 ; - uint32_t arg2 ; - unsigned char val1 ; - int ecode1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"OO:set_pixel_uint32",&obj0,&obj1)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_char(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "set_pixel_uint32" "', argument " "1"" of type '" "uint8_t""'"); - } - arg1 = (uint8_t)(val1); - ecode2 = SWIG_AsVal_unsigned_SS_int(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "set_pixel_uint32" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - set_pixel_uint32(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_set_pixel(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t arg1 ; - uint8_t arg2 ; - uint8_t arg3 ; - uint8_t arg4 ; - unsigned char val1 ; - int ecode1 = 0 ; - unsigned char val2 ; - int ecode2 = 0 ; - unsigned char val3 ; - int ecode3 = 0 ; - unsigned char val4 ; - int ecode4 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"OOOO:set_pixel",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_char(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "set_pixel" "', argument " "1"" of type '" "uint8_t""'"); - } - arg1 = (uint8_t)(val1); - ecode2 = SWIG_AsVal_unsigned_SS_char(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "set_pixel" "', argument " "2"" of type '" "uint8_t""'"); - } - arg2 = (uint8_t)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_char(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "set_pixel" "', argument " "3"" of type '" "uint8_t""'"); - } - arg3 = (uint8_t)(val3); - ecode4 = SWIG_AsVal_unsigned_SS_char(obj3, &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "set_pixel" "', argument " "4"" of type '" "uint8_t""'"); - } - arg4 = (uint8_t)(val4); - set_pixel(arg1,arg2,arg3,arg4); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_set_pixel_brightness(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t arg1 ; - uint8_t arg2 ; - unsigned char val1 ; - int ecode1 = 0 ; - unsigned char val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"OO:set_pixel_brightness",&obj0,&obj1)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_char(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "set_pixel_brightness" "', argument " "1"" of type '" "uint8_t""'"); - } - arg1 = (uint8_t)(val1); - ecode2 = SWIG_AsVal_unsigned_SS_char(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "set_pixel_brightness" "', argument " "2"" of type '" "uint8_t""'"); - } - arg2 = (uint8_t)(val2); - set_pixel_brightness(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rgbb(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t arg1 ; - uint8_t arg2 ; - uint8_t arg3 ; - uint8_t arg4 ; - unsigned char val1 ; - int ecode1 = 0 ; - unsigned char val2 ; - int ecode2 = 0 ; - unsigned char val3 ; - int ecode3 = 0 ; - unsigned char val4 ; - int ecode4 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - uint32_t result; - - if (!PyArg_ParseTuple(args,(char *)"OOOO:rgbb",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_char(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rgbb" "', argument " "1"" of type '" "uint8_t""'"); - } - arg1 = (uint8_t)(val1); - ecode2 = SWIG_AsVal_unsigned_SS_char(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rgbb" "', argument " "2"" of type '" "uint8_t""'"); - } - arg2 = (uint8_t)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_char(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rgbb" "', argument " "3"" of type '" "uint8_t""'"); - } - arg3 = (uint8_t)(val3); - ecode4 = SWIG_AsVal_unsigned_SS_char(obj3, &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "rgbb" "', argument " "4"" of type '" "uint8_t""'"); - } - arg4 = (uint8_t)(val4); - result = (uint32_t)rgbb(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rgb(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t arg1 ; - uint8_t arg2 ; - uint8_t arg3 ; - unsigned char val1 ; - int ecode1 = 0 ; - unsigned char val2 ; - int ecode2 = 0 ; - unsigned char val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - uint32_t result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:rgb",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_char(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rgb" "', argument " "1"" of type '" "uint8_t""'"); - } - arg1 = (uint8_t)(val1); - ecode2 = SWIG_AsVal_unsigned_SS_char(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rgb" "', argument " "2"" of type '" "uint8_t""'"); - } - arg2 = (uint8_t)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_char(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rgb" "', argument " "3"" of type '" "uint8_t""'"); - } - arg3 = (uint8_t)(val3); - result = (uint32_t)rgb(arg1,arg2,arg3); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_stop(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - - if (!PyArg_ParseTuple(args,(char *)":stop")) SWIG_fail; - stop(); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_start(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int result; - - if (!PyArg_ParseTuple(args,(char *)":start")) SWIG_fail; - result = (int)start(); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_show(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - - if (!PyArg_ParseTuple(args,(char *)":show")) SWIG_fail; - show(); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -static PyMethodDef SwigMethods[] = { - { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL}, - { (char *)"clear", _wrap_clear, METH_VARARGS, NULL}, - { (char *)"set_pixel_uint32", _wrap_set_pixel_uint32, METH_VARARGS, NULL}, - { (char *)"set_pixel", _wrap_set_pixel, METH_VARARGS, NULL}, - { (char *)"set_pixel_brightness", _wrap_set_pixel_brightness, METH_VARARGS, NULL}, - { (char *)"rgbb", _wrap_rgbb, METH_VARARGS, NULL}, - { (char *)"rgb", _wrap_rgb, METH_VARARGS, NULL}, - { (char *)"stop", _wrap_stop, METH_VARARGS, NULL}, - { (char *)"start", _wrap_start, METH_VARARGS, NULL}, - { (char *)"show", _wrap_show, METH_VARARGS, NULL}, - { NULL, NULL, 0, NULL } -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ - -static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0}; - -static swig_type_info *swig_type_initial[] = { - &_swigt__p_char, - &_swigt__p_int, - &_swigt__p_long_long, - &_swigt__p_short, - &_swigt__p_signed_char, - &_swigt__p_unsigned_char, - &_swigt__p_unsigned_int, - &_swigt__p_unsigned_long_long, - &_swigt__p_unsigned_short, -}; - -static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}}; - -static swig_cast_info *swig_cast_initial[] = { - _swigc__p_char, - _swigc__p_int, - _swigc__p_long_long, - _swigc__p_short, - _swigc__p_signed_char, - _swigc__p_unsigned_char, - _swigc__p_unsigned_int, - _swigc__p_unsigned_long_long, - _swigc__p_unsigned_short, -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ - -static swig_const_info swig_const_table[] = { -{0, 0, 0, 0.0, 0, 0}}; - -#ifdef __cplusplus -} -#endif -/* ----------------------------------------------------------------------------- - * Type initialization: - * This problem is tough by the requirement that no dynamic - * memory is used. Also, since swig_type_info structures store pointers to - * swig_cast_info structures and swig_cast_info structures store pointers back - * to swig_type_info structures, we need some lookup code at initialization. - * The idea is that swig generates all the structures that are needed. - * The runtime then collects these partially filled structures. - * The SWIG_InitializeModule function takes these initial arrays out of - * swig_module, and does all the lookup, filling in the swig_module.types - * array with the correct data and linking the correct swig_cast_info - * structures together. - * - * The generated swig_type_info structures are assigned statically to an initial - * array. We just loop through that array, and handle each type individually. - * First we lookup if this type has been already loaded, and if so, use the - * loaded structure instead of the generated one. Then we have to fill in the - * cast linked list. The cast data is initially stored in something like a - * two-dimensional array. Each row corresponds to a type (there are the same - * number of rows as there are in the swig_type_initial array). Each entry in - * a column is one of the swig_cast_info structures for that type. - * The cast_initial array is actually an array of arrays, because each row has - * a variable number of columns. So to actually build the cast linked list, - * we find the array of casts associated with the type, and loop through it - * adding the casts to the list. The one last trick we need to do is making - * sure the type pointer in the swig_cast_info struct is correct. - * - * First off, we lookup the cast->type name to see if it is already loaded. - * There are three cases to handle: - * 1) If the cast->type has already been loaded AND the type we are adding - * casting info to has not been loaded (it is in this module), THEN we - * replace the cast->type pointer with the type pointer that has already - * been loaded. - * 2) If BOTH types (the one we are adding casting info to, and the - * cast->type) are loaded, THEN the cast info has already been loaded by - * the previous module so we just ignore it. - * 3) Finally, if cast->type has not already been loaded, then we add that - * swig_cast_info to the linked list (because the cast->type) pointer will - * be correct. - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* c-mode */ -#endif -#endif - -#if 0 -#define SWIGRUNTIME_DEBUG -#endif - - -SWIGRUNTIME void -SWIG_InitializeModule(void *clientdata) { - size_t i; - swig_module_info *module_head, *iter; - int found, init; - - /* check to see if the circular list has been setup, if not, set it up */ - if (swig_module.next==0) { - /* Initialize the swig_module */ - swig_module.type_initial = swig_type_initial; - swig_module.cast_initial = swig_cast_initial; - swig_module.next = &swig_module; - init = 1; - } else { - init = 0; - } - - /* Try and load any already created modules */ - module_head = SWIG_GetModule(clientdata); - if (!module_head) { - /* This is the first module loaded for this interpreter */ - /* so set the swig module into the interpreter */ - SWIG_SetModule(clientdata, &swig_module); - module_head = &swig_module; - } else { - /* the interpreter has loaded a SWIG module, but has it loaded this one? */ - found=0; - iter=module_head; - do { - if (iter==&swig_module) { - found=1; - break; - } - iter=iter->next; - } while (iter!= module_head); - - /* if the is found in the list, then all is done and we may leave */ - if (found) return; - /* otherwise we must add out module into the list */ - swig_module.next = module_head->next; - module_head->next = &swig_module; - } - - /* When multiple interpreters are used, a module could have already been initialized in - a different interpreter, but not yet have a pointer in this interpreter. - In this case, we do not want to continue adding types... everything should be - set up already */ - if (init == 0) return; - - /* Now work on filling in swig_module.types */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: size %d\n", swig_module.size); -#endif - for (i = 0; i < swig_module.size; ++i) { - swig_type_info *type = 0; - swig_type_info *ret; - swig_cast_info *cast; - -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); -#endif - - /* if there is another module already loaded */ - if (swig_module.next != &swig_module) { - type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); - } - if (type) { - /* Overwrite clientdata field */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found type %s\n", type->name); -#endif - if (swig_module.type_initial[i]->clientdata) { - type->clientdata = swig_module.type_initial[i]->clientdata; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); -#endif - } - } else { - type = swig_module.type_initial[i]; - } - - /* Insert casting types */ - cast = swig_module.cast_initial[i]; - while (cast->type) { - /* Don't need to add information already in the list */ - ret = 0; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); -#endif - if (swig_module.next != &swig_module) { - ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); -#ifdef SWIGRUNTIME_DEBUG - if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); -#endif - } - if (ret) { - if (type == swig_module.type_initial[i]) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: skip old type %s\n", ret->name); -#endif - cast->type = ret; - ret = 0; - } else { - /* Check for casting already in the list */ - swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); -#ifdef SWIGRUNTIME_DEBUG - if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); -#endif - if (!ocast) ret = 0; - } - } - - if (!ret) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); -#endif - if (type->cast) { - type->cast->prev = cast; - cast->next = type->cast; - } - type->cast = cast; - } - cast++; - } - /* Set entry in modules->types array equal to the type */ - swig_module.types[i] = type; - } - swig_module.types[i] = 0; - -#ifdef SWIGRUNTIME_DEBUG - printf("**** SWIG_InitializeModule: Cast List ******\n"); - for (i = 0; i < swig_module.size; ++i) { - int j = 0; - swig_cast_info *cast = swig_module.cast_initial[i]; - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); - while (cast->type) { - printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); - cast++; - ++j; - } - printf("---- Total casts: %d\n",j); - } - printf("**** SWIG_InitializeModule: Cast List ******\n"); -#endif -} - -/* This function will propagate the clientdata field of type to -* any new swig_type_info structures that have been added into the list -* of equivalent types. It is like calling -* SWIG_TypeClientData(type, clientdata) a second time. -*/ -SWIGRUNTIME void -SWIG_PropagateClientData(void) { - size_t i; - swig_cast_info *equiv; - static int init_run = 0; - - if (init_run) return; - init_run = 1; - - for (i = 0; i < swig_module.size; i++) { - if (swig_module.types[i]->clientdata) { - equiv = swig_module.types[i]->cast; - while (equiv) { - if (!equiv->converter) { - if (equiv->type && !equiv->type->clientdata) - SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); - } - equiv = equiv->next; - } - } - } -} - -#ifdef __cplusplus -#if 0 -{ - /* c-mode */ -#endif -} -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - /* Python-specific SWIG API */ -#define SWIG_newvarlink() SWIG_Python_newvarlink() -#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) -#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) - - /* ----------------------------------------------------------------------------- - * global variable support code. - * ----------------------------------------------------------------------------- */ - - typedef struct swig_globalvar { - char *name; /* Name of global variable */ - PyObject *(*get_attr)(void); /* Return the current value */ - int (*set_attr)(PyObject *); /* Set the value */ - struct swig_globalvar *next; - } swig_globalvar; - - typedef struct swig_varlinkobject { - PyObject_HEAD - swig_globalvar *vars; - } swig_varlinkobject; - - SWIGINTERN PyObject * - swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_InternFromString(""); -#else - return PyString_FromString(""); -#endif - } - - SWIGINTERN PyObject * - swig_varlink_str(swig_varlinkobject *v) { -#if PY_VERSION_HEX >= 0x03000000 - PyObject *str = PyUnicode_InternFromString("("); - PyObject *tail; - PyObject *joined; - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - tail = PyUnicode_FromString(var->name); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - if (var->next) { - tail = PyUnicode_InternFromString(", "); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - } - } - tail = PyUnicode_InternFromString(")"); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; -#else - PyObject *str = PyString_FromString("("); - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - PyString_ConcatAndDel(&str,PyString_FromString(var->name)); - if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); - } - PyString_ConcatAndDel(&str,PyString_FromString(")")); -#endif - return str; - } - - SWIGINTERN int - swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { - char *tmp; - PyObject *str = swig_varlink_str(v); - fprintf(fp,"Swig global variables "); - fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(str); - return 0; - } - - SWIGINTERN void - swig_varlink_dealloc(swig_varlinkobject *v) { - swig_globalvar *var = v->vars; - while (var) { - swig_globalvar *n = var->next; - free(var->name); - free(var); - var = n; - } - } - - SWIGINTERN PyObject * - swig_varlink_getattr(swig_varlinkobject *v, char *n) { - PyObject *res = NULL; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->get_attr)(); - break; - } - var = var->next; - } - if (res == NULL && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; - } - - SWIGINTERN int - swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { - int res = 1; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->set_attr)(p); - break; - } - var = var->next; - } - if (res == 1 && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; - } - - SWIGINTERN PyTypeObject* - swig_varlink_type(void) { - static char varlink__doc__[] = "Swig var link object"; - static PyTypeObject varlink_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"swigvarlink", /* tp_name */ - sizeof(swig_varlinkobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) swig_varlink_dealloc, /* tp_dealloc */ - (printfunc) swig_varlink_print, /* tp_print */ - (getattrfunc) swig_varlink_getattr, /* tp_getattr */ - (setattrfunc) swig_varlink_setattr, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc) swig_varlink_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) swig_varlink_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - varlink__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - varlink_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - varlink_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&varlink_type) < 0) - return NULL; -#endif - } - return &varlink_type; - } - - /* Create a variable linking object for use later */ - SWIGINTERN PyObject * - SWIG_Python_newvarlink(void) { - swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); - if (result) { - result->vars = 0; - } - return ((PyObject*) result); - } - - SWIGINTERN void - SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { - swig_varlinkobject *v = (swig_varlinkobject *) p; - swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); - if (gv) { - size_t size = strlen(name)+1; - gv->name = (char *)malloc(size); - if (gv->name) { - strncpy(gv->name,name,size); - gv->get_attr = get_attr; - gv->set_attr = set_attr; - gv->next = v->vars; - } - } - v->vars = gv; - } - - SWIGINTERN PyObject * - SWIG_globals(void) { - static PyObject *_SWIG_globals = 0; - if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); - return _SWIG_globals; - } - - /* ----------------------------------------------------------------------------- - * constants/methods manipulation - * ----------------------------------------------------------------------------- */ - - /* Install Constants */ - SWIGINTERN void - SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { - PyObject *obj = 0; - size_t i; - for (i = 0; constants[i].type; ++i) { - switch(constants[i].type) { - case SWIG_PY_POINTER: - obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); - break; - case SWIG_PY_BINARY: - obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); - break; - default: - obj = 0; - break; - } - if (obj) { - PyDict_SetItemString(d, constants[i].name, obj); - Py_DECREF(obj); - } - } - } - - /* -----------------------------------------------------------------------------*/ - /* Fix SwigMethods to carry the callback ptrs when needed */ - /* -----------------------------------------------------------------------------*/ - - SWIGINTERN void - SWIG_Python_FixMethods(PyMethodDef *methods, - swig_const_info *const_table, - swig_type_info **types, - swig_type_info **types_initial) { - size_t i; - for (i = 0; methods[i].ml_name; ++i) { - const char *c = methods[i].ml_doc; - if (c && (c = strstr(c, "swig_ptr: "))) { - int j; - swig_const_info *ci = 0; - const char *name = c + 10; - for (j = 0; const_table[j].type; ++j) { - if (strncmp(const_table[j].name, name, - strlen(const_table[j].name)) == 0) { - ci = &(const_table[j]); - break; - } - } - if (ci) { - void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; - if (ptr) { - size_t shift = (ci->ptype) - types; - swig_type_info *ty = types_initial[shift]; - size_t ldoc = (c - methods[i].ml_doc); - size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; - char *ndoc = (char*)malloc(ldoc + lptr + 10); - if (ndoc) { - char *buff = ndoc; - strncpy(buff, methods[i].ml_doc, ldoc); - buff += ldoc; - strncpy(buff, "swig_ptr: ", 10); - buff += 10; - SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); - methods[i].ml_doc = ndoc; - } - } - } - } - } - } - -#ifdef __cplusplus -} -#endif - -/* -----------------------------------------------------------------------------* - * Partial Init method - * -----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" -#endif - -SWIGEXPORT -#if PY_VERSION_HEX >= 0x03000000 -PyObject* -#else -void -#endif -SWIG_init(void) { - PyObject *m, *d, *md; -#if PY_VERSION_HEX >= 0x03000000 - static struct PyModuleDef SWIG_module = { -# if PY_VERSION_HEX >= 0x03020000 - PyModuleDef_HEAD_INIT, -# else - { - PyObject_HEAD_INIT(NULL) - NULL, /* m_init */ - 0, /* m_index */ - NULL, /* m_copy */ - }, -# endif - (char *) SWIG_name, - NULL, - -1, - SwigMethods, - NULL, - NULL, - NULL, - NULL - }; -#endif - -#if defined(SWIGPYTHON_BUILTIN) - static SwigPyClientData SwigPyObject_clientdata = { - 0, 0, 0, 0, 0, 0, 0 - }; - static PyGetSetDef this_getset_def = { - (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL - }; - static SwigPyGetSet thisown_getset_closure = { - (PyCFunction) SwigPyObject_own, - (PyCFunction) SwigPyObject_own - }; - static PyGetSetDef thisown_getset_def = { - (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure - }; - PyObject *metatype_args; - PyTypeObject *builtin_pytype; - int builtin_base_count; - swig_type_info *builtin_basetype; - PyObject *tuple; - PyGetSetDescrObject *static_getset; - PyTypeObject *metatype; - SwigPyClientData *cd; - PyObject *public_interface, *public_symbol; - PyObject *this_descr; - PyObject *thisown_descr; - int i; - - (void)builtin_pytype; - (void)builtin_base_count; - (void)builtin_basetype; - (void)tuple; - (void)static_getset; - - /* metatype is used to implement static member variables. */ - metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type); - assert(metatype_args); - metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL); - assert(metatype); - Py_DECREF(metatype_args); - metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro; - assert(PyType_Ready(metatype) >= 0); -#endif - - /* Fix SwigMethods to carry the callback ptrs when needed */ - SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); - -#if PY_VERSION_HEX >= 0x03000000 - m = PyModule_Create(&SWIG_module); -#else - m = Py_InitModule((char *) SWIG_name, SwigMethods); -#endif - md = d = PyModule_GetDict(m); - (void)md; - - SWIG_InitializeModule(0); - -#ifdef SWIGPYTHON_BUILTIN - SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject"); - assert(SwigPyObject_stype); - cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; - if (!cd) { - SwigPyObject_stype->clientdata = &SwigPyObject_clientdata; - SwigPyObject_clientdata.pytype = SwigPyObject_TypeOnce(); - } else if (SwigPyObject_TypeOnce()->tp_basicsize != cd->pytype->tp_basicsize) { - PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules."); -# if PY_VERSION_HEX >= 0x03000000 - return NULL; -# else - return; -# endif - } - - /* All objects have a 'this' attribute */ - this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def); - (void)this_descr; - - /* All objects have a 'thisown' attribute */ - thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def); - (void)thisown_descr; - - public_interface = PyList_New(0); - public_symbol = 0; - (void)public_symbol; - - PyDict_SetItemString(md, "__all__", public_interface); - Py_DECREF(public_interface); - for (i = 0; SwigMethods[i].ml_name != NULL; ++i) - SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name); - for (i = 0; swig_const_table[i].name != 0; ++i) - SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name); -#endif - - SWIG_InstallConstants(d,swig_const_table); - -#if PY_VERSION_HEX >= 0x03000000 - return m; -#else - return; -#endif -} - diff --git a/library_c/lib/blinkt.c b/library_c/lib/blinkt.c deleted file mode 100644 index c147d28..0000000 --- a/library_c/lib/blinkt.c +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "blinkt.h" - -#define APA_SOF 0b11100000 - -#define DEFAULT_BRIGHTNESS 7 -#define NUM_LEDS 8 - -#define MOSI 23 -#define SCLK 24 - -#ifdef TEST -volatile int running = 0; -#endif - -int x; - -uint32_t leds[NUM_LEDS] = {}; - -#ifdef TEST -void sigint_handler(int dummy){ - running = 0; - return; -} -#endif - -void clear(){ - for(x = 0; x < NUM_LEDS; x++){ - leds[x] = DEFAULT_BRIGHTNESS; - } -} - -void set_pixel(uint8_t led, uint8_t r, uint8_t g, uint8_t b){ - if(led >= NUM_LEDS) return; - - leds[led] = rgbb(r,g,b,leds[led] & 0b11111); -} - -void set_pixel_brightness(uint8_t led, uint8_t brightness){ - if(led >= NUM_LEDS) return; - - leds[led] = (leds[led] & 0xFFFFFF00) | (brightness & 0b11111); -} - -void set_pixel_uint32(uint8_t led, uint32_t color){ - if(led >= NUM_LEDS) return; - - leds[led] = color; -} - -uint32_t rgbb(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness){ - uint32_t result = 0; - result = (brightness & 0b11111); - result |= ((uint32_t)r << 24); - result |= ((uint32_t)g << 16); - result |= ((uint16_t)b << 8); - return result; -} - -uint32_t rgb(uint8_t r, uint8_t g, uint8_t b){ - return rgbb(r, g, b, DEFAULT_BRIGHTNESS); -} - -inline static void write_byte(uint8_t byte){ - int n; - for(n = 0; n < 8; n++){ - bcm2835_gpio_write(MOSI, (byte & (1 << (7-n))) > 0); - bcm2835_gpio_write(SCLK, HIGH); - bcm2835_gpio_write(SCLK, LOW); - } - -} - -void show(void){ - write_byte(0); - write_byte(0); - write_byte(0); - write_byte(0); - for(x = 0; x < NUM_LEDS; x++){ - write_byte(APA_SOF | (leds[x] & 0b11111)); - write_byte((leds[x] >> 8 ) & 0xFF); - write_byte((leds[x] >> 16) & 0xFF); - write_byte((leds[x] >> 24) & 0xFF); - } - write_byte(0xff); - //write_byte(0xff); - //write_byte(0xff); - //write_byte(0xff); -} - -void stop(void){ - bcm2835_spi_end(); - - bcm2835_close(); -} - - -int start(void){ - - if(!bcm2835_init()) return 1; - -#ifdef TEST - printf("GPIO Initialized\n"); -#endif - - bcm2835_gpio_fsel(MOSI, BCM2835_GPIO_FSEL_OUTP); - bcm2835_gpio_write(MOSI, LOW); - bcm2835_gpio_fsel(SCLK, BCM2835_GPIO_FSEL_OUTP); - bcm2835_gpio_write(SCLK, LOW); - - clear(); - - return 0; - -} - -#ifdef TEST -int main(){ - - int z; - int y = 0; - - running = 1; - - signal(SIGINT, sigint_handler); - - if (start()){ - printf("Unable to start apa102\n"); - return 1; - } - - printf("Running test cycle\n"); - - int col = 0; - - while(running){ - - for(z = 0; z < NUM_LEDS; z++){ - switch(col){ - case 0: set_pixel_uint32(z, rgb(y,0,0)); break; - case 1: set_pixel_uint32(z, rgb(0,y,0)); break; - case 2: set_pixel_uint32(z, rgb(0,0,y)); break; - } - } - - show(); - - usleep(1000); - - y+=1; - if(y>254) col++; - col%=3; - y%=255; - - } - - - clear(); - - usleep(1000); - - stop(); - - return 0; - -} -#endif diff --git a/library_c/lib/blinkt.h b/library_c/lib/blinkt.h deleted file mode 100644 index 9f3656e..0000000 --- a/library_c/lib/blinkt.h +++ /dev/null @@ -1,9 +0,0 @@ -void clear(void); -void set_pixel_uint32(uint8_t led, uint32_t color); -void set_pixel(uint8_t led, uint8_t r, uint8_t g, uint8_t b); -void set_pixel_brightness(uint8_t led, uint8_t brightness); -uint32_t rgbb(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness); -uint32_t rgb(uint8_t r, uint8_t g, uint8_t b); -void stop(void); -int start(void); -void show(void); diff --git a/library_c/setup.py b/library_c/setup.py deleted file mode 100755 index 9f4107a..0000000 --- a/library_c/setup.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python - -from setuptools import setup, find_packages, Extension - -_blinkt = Extension( - '_blinkt', - include_dirs=['lib'], - libraries=['bcm2835'], - sources=['lib/blinkt.c','blinkt_wrap.c'] -) - -setup( - name = 'blinkt_c', - version = '0.0.1', - author = "Philip Howard", - author_email = "phil@pimoroni.com", - url = "", - description = "", - long_description = "", - ext_modules = [ _blinkt ], - py_modules = ["blinkt"], - install_requires = [], - headers=['lib/blinkt.h'] -) diff --git a/packaging/CHANGELOG b/packaging/CHANGELOG deleted file mode 100644 index 0cd6a8f..0000000 --- a/packaging/CHANGELOG +++ /dev/null @@ -1,75 +0,0 @@ -blinkt (0.1.2) STABLE; urgency=low - - * BugFix: Added sleep to data output, see: https://github.com/pimoroni/blinkt/issues/62 - - -- Phil Howard Wed, 23 May 2018 00:00:00 +0000 - -blinkt (0.1.1) STABLE; urgency=low - - * New: Added `get_pixel` to return colour and brightness of a single pixel - - -- Phil Howard Tue, 20 Feb 2018 00:00:00 +0000 - -blinkt (0.1.0) STABLE; urgency=low - - * Removed try/except from RPi.GPIO import, output was misleading at best - * Reverted default behaviour of clear on exit - - -- Phil Howard Tue, 06 Sep 2016 00:00:00 +0000 - -blinkt (0.0.9) UNRELEASED; urgency=low - - * Added set_all method to set all pixels - * Changed default behaviour of clear on exit to reduce module side-effects - * Move GPIO initialisation to show() to reduce module side-effects - - -- Phil Howard Tue, 06 Sep 2016 00:00:00 +0000 - -blinkt (0.0.8) UNRELEASED; urgency=low - - * Tweaked some methods to show intent as implementation detail only - * Added docstrings detailing public methods - - -- Phil Howard Tue, 06 Sep 2016 00:00:00 +0000 - -blinkt (0.0.7) UNRELEASED; urgency=low - - * Fixed bug with APA102 pixels that have a small, black die (vs the larger, paler one) - - -- Phil Howard Wed, 24 Aug 2016 00:00:00 +0000 - -blinkt (0.0.6) UNRELEASED; urgency=low - - * set_clear_on_exit now method - - -- Phil Howard Thu, 11 Aug 2016 00:00:00 +0000 - -blinkt (0.0.5) UNRELEASED; urgency=low - - * Range clamping and coercion to integers - - -- Phil Howard Wed, 22 Jun 2016 00:00:00 +0000 - -blinkt (0.0.4) UNRELEASED; urgency=low - - * Various bug fixes - - -- Phil Howard Tue, 21 Jun 2016 18:00:00 +0000 - -blinkt (0.0.3) UNRELEASED; urgency=low - - * Switch to Python - - -- Phil Howard Tue, 21 Jun 2016 12:00:00 +0000 - -blinkt (0.0.2) UNRELEASED; urgency=low - - * Bug fixes for C Library - - -- Phil Howard Tue, 21 Jun 2016 06:00:00 +0000 - -blinkt (0.0.1) UNRELEASED; urgency=low - - * Original C Library - - -- Phil Howard Tue, 21 Jun 2016 00:00:00 +0000 diff --git a/packaging/debian/README b/packaging/debian/README deleted file mode 100644 index 2b68e90..0000000 --- a/packaging/debian/README +++ /dev/null @@ -1,6 +0,0 @@ -README - -Blinkt! provides eight super-bright RGB LED indicators. Ideal for adding visual notifications to your Raspberry Pi. - -Learn more: https://shop.pimoroni.com/products/blinkt -For examples run: `curl -sS get.pimoroni.com/blinkt | bash` diff --git a/packaging/debian/changelog b/packaging/debian/changelog deleted file mode 100644 index 0cd6a8f..0000000 --- a/packaging/debian/changelog +++ /dev/null @@ -1,75 +0,0 @@ -blinkt (0.1.2) STABLE; urgency=low - - * BugFix: Added sleep to data output, see: https://github.com/pimoroni/blinkt/issues/62 - - -- Phil Howard Wed, 23 May 2018 00:00:00 +0000 - -blinkt (0.1.1) STABLE; urgency=low - - * New: Added `get_pixel` to return colour and brightness of a single pixel - - -- Phil Howard Tue, 20 Feb 2018 00:00:00 +0000 - -blinkt (0.1.0) STABLE; urgency=low - - * Removed try/except from RPi.GPIO import, output was misleading at best - * Reverted default behaviour of clear on exit - - -- Phil Howard Tue, 06 Sep 2016 00:00:00 +0000 - -blinkt (0.0.9) UNRELEASED; urgency=low - - * Added set_all method to set all pixels - * Changed default behaviour of clear on exit to reduce module side-effects - * Move GPIO initialisation to show() to reduce module side-effects - - -- Phil Howard Tue, 06 Sep 2016 00:00:00 +0000 - -blinkt (0.0.8) UNRELEASED; urgency=low - - * Tweaked some methods to show intent as implementation detail only - * Added docstrings detailing public methods - - -- Phil Howard Tue, 06 Sep 2016 00:00:00 +0000 - -blinkt (0.0.7) UNRELEASED; urgency=low - - * Fixed bug with APA102 pixels that have a small, black die (vs the larger, paler one) - - -- Phil Howard Wed, 24 Aug 2016 00:00:00 +0000 - -blinkt (0.0.6) UNRELEASED; urgency=low - - * set_clear_on_exit now method - - -- Phil Howard Thu, 11 Aug 2016 00:00:00 +0000 - -blinkt (0.0.5) UNRELEASED; urgency=low - - * Range clamping and coercion to integers - - -- Phil Howard Wed, 22 Jun 2016 00:00:00 +0000 - -blinkt (0.0.4) UNRELEASED; urgency=low - - * Various bug fixes - - -- Phil Howard Tue, 21 Jun 2016 18:00:00 +0000 - -blinkt (0.0.3) UNRELEASED; urgency=low - - * Switch to Python - - -- Phil Howard Tue, 21 Jun 2016 12:00:00 +0000 - -blinkt (0.0.2) UNRELEASED; urgency=low - - * Bug fixes for C Library - - -- Phil Howard Tue, 21 Jun 2016 06:00:00 +0000 - -blinkt (0.0.1) UNRELEASED; urgency=low - - * Original C Library - - -- Phil Howard Tue, 21 Jun 2016 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 cedbaea..0000000 --- a/packaging/debian/control +++ /dev/null @@ -1,31 +0,0 @@ -Source: blinkt -Maintainer: Phil Howard -Homepage: https://github.com/pimoroni/blinkt -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-blinkt -Architecture: all -Section: python -Depends: ${misc:Depends}, ${python:Depends}, python-rpi.gpio -Suggests: python-psutil, python-requests -Description: Python library for the Pimoroni Blinkt! - Blinkt! provides eight super-bright RGB LED indicators. - Ideal for adding visual notifications to your Raspberry Pi. - . - This is the Python 2 version of the package. - -Package: python3-blinkt -Architecture: all -Section: python -Depends: ${misc:Depends}, ${python3:Depends}, python3-rpi.gpio -Suggests: python3-psutil, python3-requests -Description: Python library for the Pimoroni Blinkt! - Blinkt! provides eight super-bright RGB LED indicators. - Ideal for adding visual notifications to your Raspberry Pi. - . - This is the Python 3 version of the package. diff --git a/packaging/debian/copyright b/packaging/debian/copyright deleted file mode 100644 index 027e08f..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: blinkt -Source: https://github.com/pimoroni/blinkt - -Files: * -Copyright: 2016 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/docs b/packaging/debian/docs deleted file mode 100644 index e69de29..0000000 diff --git a/packaging/debian/rules b/packaging/debian/rules deleted file mode 100755 index e344088..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-blinkt --install-layout=deb - python3 setup.py install --root debian/python3-blinkt --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..aa3cb3b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,115 @@ +[build-system] +requires = ["hatchling", "hatch-fancy-pypi-readme"] +build-backend = "hatchling.build" + +[project] +name = "blinkt" +dynamic = ["version", "readme"] +description = "Python library for driving Pimoroni Blinkt!" +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 = [ + "gpiod" +] + +[project.urls] +GitHub = "https://www.github.com/pimoroni/blinkt" +Homepage = "https://www.pimoroni.com" + +[tool.hatch.version] +path = "blinkt/__init__.py" + +[tool.hatch.build] +include = [ + "blinkt", + "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.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..525b042 --- /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 84bf148..0000000 --- a/sphinx/_static/custom.css +++ /dev/null @@ -1,39 +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); -} -.wy-side-nav-search { - background:#333333; -} -.wy-nav-side { - background:#444444; -} -.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 #module-blinkt { - margin-bottom:24px; -} -.rst-content #module-blinkt dl:not(.docutils) dt { - border:none; - background:#f0f0f0; -} -.rst-content #module-blinkt dl:not(.docutils) dd { - display:none; -} -.rst-content #module-blinkt dl:not(.docutils) { - margin-bottom:0; -} \ No newline at end of file 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 d89399b..0000000 --- a/sphinx/_templates/layout.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "!layout.html" %} -{% block extrahead %} - -{% endblock %} \ No newline at end of file diff --git a/sphinx/conf.py b/sphinx/conf.py deleted file mode 100644 index 6dbac79..0000000 --- a/sphinx/conf.py +++ /dev/null @@ -1,389 +0,0 @@ -#-*- coding: utf-8 -*- - -import sys -import site - -import mock - - -PACKAGE_NAME = u"Blinkt!" -PACKAGE_HANDLE = "Blinkt" -PACKAGE_MODULE = "blinkt" - -# Prompte /usr/local/lib to the front of sys.path -#sys.path.insert(0,site.getsitepackages()[0]) - -import sphinx_rtd_theme - -sys.modules['RPi'] = mock.Mock() -sys.modules['RPi.GPIO'] = mock.Mock() - -sys.path.insert(0, '../library/') - -import blinkt - - -from sphinx.ext import autodoc - - -class OutlineMethodDocumenter(autodoc.MethodDocumenter): - objtype = 'method' - - def add_content(self, more_content, no_docstring=False): - return - -class OutlineFunctionDocumenter(autodoc.FunctionDocumenter): - objtype = 'function' - - def add_content(self, more_content, no_docstring=False): - return - -class ModuleOutlineDocumenter(autodoc.ModuleDocumenter): - objtype = 'moduleoutline' - - def __init__(self, directive, name, indent=u''): - # Monkey path the Method and Function documenters - sphinx_app.add_autodocumenter(OutlineMethodDocumenter) - 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.MethodDocumenter) - sphinx_app.add_autodocumenter(autodoc.FunctionDocumenter) - - -def setup(app): - global sphinx_app - sphinx_app = app - app.add_autodocumenter(ModuleOutlineDocumenter) - - 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.autosummary', - '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(blinkt.__version__) -# The full version, including alpha/beta/rc tags. -release = u'{}'.format(blinkt.__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' -#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 0b55ffc..0000000 --- a/sphinx/index.rst +++ /dev/null @@ -1,93 +0,0 @@ -.. role:: python(code) - :language: python - -.. toctree:: - :titlesonly: - :maxdepth: 0 - -Welcome -------- - -This documentation will guide you through the methods available in the Blinkt! python library. - -Blinkt! is a tiny Raspberry Pi add-on with 8, APA102, RGB LEDs which you can drive -independently for notifications, lighting effects, animation effects and more! - -* More information - https://shop.pimoroni.com/products/blinkt -* Get the code - https://github.com/pimoroni/blinkt -* Get started - https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-blinkt -* Get help - http://forums.pimoroni.com/c/support - -At A Glance ------------ - -.. automoduleoutline:: blinkt - :members: - -Set A Single Pixel ------------------- - -The bread and butter of Blintk! is setting pixels. You can set any of the 8 pixels -on your Blinkt! to one of around 16 million colours! - -The :python:`brightness` argument is completely optional. Omit it to keep the last -brightness value set for that particular pixel. - -.. automodule:: blinkt - :noindex: - :members: set_pixel - -Set All Pixels --------------- - -Sometimes you need to set all the pixels to the same colour. This convinience method -does just that! - -.. automodule:: blinkt - :noindex: - :members: set_all - -Show ----- - -None of your pixels will appear on Blinkt! until you :python:`show()` them. This method writes -all the pixel data out to your device. - -.. automodule:: blinkt - :noindex: - :members: show - -Clear ------ - -Exactly the same as calling :python:`set_all(0,0,0)`, clear sets all the pixels to black. - -You must also call :python:`show()` if you want to turn Blinkt! off. - -.. automodule:: blinkt - :noindex: - :members: clear - -Enable/Disable Clear On Exit ----------------------------- - -Sometimes you want a script that runs and quits, leaving a pattern up on Blinkt! - -.. automodule:: blinkt - :noindex: - :members: set_clear_on_exit - -Get A Single Pixel ------------------- - -.. automodule:: blinkt - :noindex: - :members: get_pixel - -Constants ---------- - -Blinkt! has 8 pixels. Simple. Use the constant :python:`blinkt.NUM_PIXELS` when you're iterating over pixels, -so you can avoid a *magic number* in your code. - -:python:`blinkt.NUM_PIXELS = 8` 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/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..0e6f213 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,11 @@ +import pytest +import mock +import sys + +@pytest.fixture(scope='function', autouse=False) +def gpiod(): + sys.modules['gpiod'] = mock.Mock() + sys.modules['gpiod.line'] = mock.Mock() + yield sys.modules['gpiod'] + del sys.modules['gpiod.line'] + del sys.modules['gpiod'] diff --git a/tests/test_setup.py b/tests/test_setup.py new file mode 100644 index 0000000..b450b7e --- /dev/null +++ b/tests/test_setup.py @@ -0,0 +1,7 @@ +"""Test Blinkt! basic initialisation.""" + +def test_setup(gpiod): + """Test init succeeds and GPIO pins are set up.""" + import blinkt + blinkt.show() + gpiod.request_lines.assert_called_once() diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..44c8654 --- /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 new file mode 100755 index 0000000..f213fc5 --- /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 "$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" From 748299eb2f6b6cf11a683e721895fe7b69b5d2ec Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 16:10:54 +0000 Subject: [PATCH 02/27] Examples: switch from apt to pip install. --- examples/candle.py | 2 +- examples/mem_load.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/candle.py b/examples/candle.py index bf61592..a0c467b 100755 --- a/examples/candle.py +++ b/examples/candle.py @@ -7,7 +7,7 @@ try: import numpy as np except ImportError: - exit('This script requires the numpy module\nInstall with: sudo apt install python3-numpy') + exit('This script requires the numpy module\nInstall with: python3 -m pip install numpy') import blinkt diff --git a/examples/mem_load.py b/examples/mem_load.py index c1b6d83..fe0c410 100755 --- a/examples/mem_load.py +++ b/examples/mem_load.py @@ -6,7 +6,7 @@ try: import psutil except ImportError: - exit('This script requires the psutil module\nInstall with: sudo apt install python3-psutil') + exit('This script requires the psutil module\nInstall with: python3 -m pip install psutil') import blinkt From 1411204b457691b2b55b4b39c379bcfb5296ad20 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 16:14:28 +0000 Subject: [PATCH 03/27] Restore clear on exit. --- blinkt/__init__.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index 9031b85..52fb9f1 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -20,6 +20,14 @@ sleep_time = 0 gpio_lines = None +_clear_on_exit = True + + +def _exit(): + if _clear_on_exit: + clear() + show() + gpio_lines.release() def set_brightness(brightness): @@ -84,6 +92,7 @@ def show(): CLK: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE) } ) + atexit.register(_exit) _sof() From 89f346b029c57fd7611f5b4856b4c1ffd0bffc59 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 16:15:08 +0000 Subject: [PATCH 04/27] QA: Apply isort suggestions. --- blinkt/__init__.py | 2 -- examples/anvil-colour-control.py | 6 +++--- examples/binary_clock_meld.py | 1 - examples/blinkt_thermo.py | 3 +-- examples/candle.py | 1 - examples/extra_examples/drum_hits.py | 1 - examples/extra_examples/spirit_level.py | 1 - examples/eyedropper.py | 6 ++++-- examples/graph.py | 1 - examples/kitt.py | 5 +++-- examples/larson_hue.py | 2 +- examples/mqtt.py | 1 - examples/resistor_clock.py | 1 - examples/setall.py | 1 + examples/solid_colours.py | 1 - examples/solid_colours2.py | 1 - examples/solid_colours3.py | 1 - examples/twitter_monitor.py | 3 +-- examples/unionjack.py | 1 + projects/mqtt/mqtt.py | 3 +-- tests/conftest.py | 6 ++++-- 21 files changed, 20 insertions(+), 28 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index 52fb9f1..b230d01 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -3,10 +3,8 @@ import time import gpiod - from gpiod.line import Direction, Value - __version__ = '0.1.2' DAT = 23 diff --git a/examples/anvil-colour-control.py b/examples/anvil-colour-control.py index c6bc1b3..1b6a75f 100755 --- a/examples/anvil-colour-control.py +++ b/examples/anvil-colour-control.py @@ -16,11 +16,11 @@ # hit the "Run" button at the top to start remote-controlling # your Blinkt! -import blinkt +import anvil.server +from anvil.app_creator import create_app from colour import Color -from anvil.app_creator import create_app -import anvil.server +import blinkt # Create the Blinkt demo app in your Anvil account app = create_app("blinkt") diff --git a/examples/binary_clock_meld.py b/examples/binary_clock_meld.py index 9652cc4..add7f2e 100755 --- a/examples/binary_clock_meld.py +++ b/examples/binary_clock_meld.py @@ -4,7 +4,6 @@ import blinkt - print('Hour = Red, Minute = Green, Second = Blue') blinkt.set_clear_on_exit() diff --git a/examples/blinkt_thermo.py b/examples/blinkt_thermo.py index 433bf51..e056c70 100755 --- a/examples/blinkt_thermo.py +++ b/examples/blinkt_thermo.py @@ -3,8 +3,8 @@ # Data from OpenWeatherMap # show_graph function adapted from cpu_temp.py -from time import sleep from sys import exit +from time import sleep try: import requests @@ -13,7 +13,6 @@ import blinkt - # Grab your API key here: http://openweathermap.org # List of city ID city.list.json.gz can be downloaded here http://bulk.openweathermap.org/sample/ API_KEY = '' diff --git a/examples/candle.py b/examples/candle.py index a0c467b..3ef114f 100755 --- a/examples/candle.py +++ b/examples/candle.py @@ -11,7 +11,6 @@ import blinkt - blinkt.clear() start = 0 end = 60 diff --git a/examples/extra_examples/drum_hits.py b/examples/extra_examples/drum_hits.py index 7384a3d..dad43e5 100755 --- a/examples/extra_examples/drum_hits.py +++ b/examples/extra_examples/drum_hits.py @@ -17,7 +17,6 @@ import blinkt - DRUM_FOLDER = 'drums2' BANK = os.path.join(os.path.dirname(__file__), DRUM_FOLDER) diff --git a/examples/extra_examples/spirit_level.py b/examples/extra_examples/spirit_level.py index 9669682..c48dfc8 100755 --- a/examples/extra_examples/spirit_level.py +++ b/examples/extra_examples/spirit_level.py @@ -10,7 +10,6 @@ import blinkt - x_avg = [] while True: diff --git a/examples/eyedropper.py b/examples/eyedropper.py index 9957464..429a5c1 100644 --- a/examples/eyedropper.py +++ b/examples/eyedropper.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -from PIL import ImageGrab +import time + import pyautogui +from PIL import ImageGrab + import blinkt -import time print('Press Ctrl-C to quit.') diff --git a/examples/graph.py b/examples/graph.py index 4cec0ba..f319672 100755 --- a/examples/graph.py +++ b/examples/graph.py @@ -5,7 +5,6 @@ import blinkt - blinkt.set_clear_on_exit() diff --git a/examples/kitt.py b/examples/kitt.py index cc748ef..4304089 100644 --- a/examples/kitt.py +++ b/examples/kitt.py @@ -1,7 +1,8 @@ #!/usr/bin/env python -import time # so we can wait between frames -import blinkt # so we can talk to our blinkt lights! +import time # so we can wait between frames + +import blinkt # so we can talk to our blinkt lights! BRIGHTNESS = 0.2 # range is 0.0 to 1.0 MAX_COLOUR = 255 # range is 0 to 255 diff --git a/examples/larson_hue.py b/examples/larson_hue.py index 7592040..b70a8eb 100755 --- a/examples/larson_hue.py +++ b/examples/larson_hue.py @@ -1,8 +1,8 @@ #!/usr/bin/env python +import colorsys import math import time -import colorsys import blinkt diff --git a/examples/mqtt.py b/examples/mqtt.py index a05127c..896b0a4 100755 --- a/examples/mqtt.py +++ b/examples/mqtt.py @@ -8,7 +8,6 @@ import blinkt - MQTT_SERVER = 'iot.eclipse.org' MQTT_PORT = 1883 MQTT_TOPIC = 'pimoroni/blinkt' diff --git a/examples/resistor_clock.py b/examples/resistor_clock.py index 2acb78a..717d38d 100755 --- a/examples/resistor_clock.py +++ b/examples/resistor_clock.py @@ -4,7 +4,6 @@ import blinkt - colours = [ [0, 0, 0], # 0 black [139, 69, 19], # 1 brown diff --git a/examples/setall.py b/examples/setall.py index b930ac0..499af66 100755 --- a/examples/setall.py +++ b/examples/setall.py @@ -2,6 +2,7 @@ import sys from sys import argv + import blinkt if len(argv) < 4 or len(argv) > 5: diff --git a/examples/solid_colours.py b/examples/solid_colours.py index b01679a..c0539a8 100755 --- a/examples/solid_colours.py +++ b/examples/solid_colours.py @@ -4,7 +4,6 @@ import blinkt - blinkt.set_clear_on_exit() step = 0 diff --git a/examples/solid_colours2.py b/examples/solid_colours2.py index cbbcbf1..aeb6a73 100755 --- a/examples/solid_colours2.py +++ b/examples/solid_colours2.py @@ -4,7 +4,6 @@ import blinkt - blinkt.set_clear_on_exit() step = 0 diff --git a/examples/solid_colours3.py b/examples/solid_colours3.py index 986e8ec..6416757 100755 --- a/examples/solid_colours3.py +++ b/examples/solid_colours3.py @@ -4,7 +4,6 @@ import blinkt - blinkt.set_clear_on_exit() step = 0 diff --git a/examples/twitter_monitor.py b/examples/twitter_monitor.py index ff4215d..23e5b72 100755 --- a/examples/twitter_monitor.py +++ b/examples/twitter_monitor.py @@ -4,14 +4,13 @@ from sys import exit try: - from tweepy import Stream, OAuthHandler + from tweepy import OAuthHandler, Stream from tweepy.streaming import StreamListener except ImportError: exit('This script requires the tweepy module\nInstall with: sudo pip install tweepy') import blinkt - ckey = '' # Consumer key csecret = '' # Consumer secret atoken = '' # Access token diff --git a/examples/unionjack.py b/examples/unionjack.py index 69f928f..7dbd9cb 100755 --- a/examples/unionjack.py +++ b/examples/unionjack.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import time + import blinkt RED__ = (255, 0, 0) diff --git a/projects/mqtt/mqtt.py b/projects/mqtt/mqtt.py index 7cc3106..67b3f85 100755 --- a/projects/mqtt/mqtt.py +++ b/projects/mqtt/mqtt.py @@ -1,8 +1,8 @@ #!/usr/bin/env python -from sys import exit import argparse import time +from sys import exit try: import paho.mqtt.client as mqtt @@ -11,7 +11,6 @@ import blinkt - MQTT_SERVER = "localhost" MQTT_PORT = 1883 MQTT_TOPIC = "pimoroni/blinkt" diff --git a/tests/conftest.py b/tests/conftest.py index 0e6f213..afffbb0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,9 @@ -import pytest -import mock import sys +import mock +import pytest + + @pytest.fixture(scope='function', autouse=False) def gpiod(): sys.modules['gpiod'] = mock.Mock() From 68f0953938dfb6b5deb65e3e387c6950e4b95c1c Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 16:16:17 +0000 Subject: [PATCH 05/27] QA: Apply ruff suggestion. --- examples/mqtt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/mqtt.py b/examples/mqtt.py index 896b0a4..64860df 100755 --- a/examples/mqtt.py +++ b/examples/mqtt.py @@ -45,7 +45,7 @@ def on_connect(client, userdata, flags, rc): def on_message(client, userdata, msg): data = msg.payload - if type(data) is bytes: + if isinstance(data, bytes): data = data.decode('utf-8') data = data.split(',') command = data.pop(0) From 256fdcdffb7a36e520f63da8036893bdc2a0c4b1 Mon Sep 17 00:00:00 2001 From: Hugo Simoes <61560976+simoesh@users.noreply.github.com> Date: Tue, 31 Oct 2023 16:18:32 +0000 Subject: [PATCH 06/27] README.md: add link to unofficial web-based simulator for examples written in Prequel --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ac8b416..3b6eb93 100644 --- a/README.md +++ b/README.md @@ -63,3 +63,4 @@ make pytest * Java library by @HoldYourWaffle - https://github.com/HoldYourWaffle/blinkt4j * Node.js library by @irrelon - https://github.com/irrelon/node-blinkt * Rust library by @golemparts - https://github.com/golemparts/blinkt +* Web-based Prequel simulator by Hugo Simoes - https://prequel-lang.org/examples/blinkp/ \ No newline at end of file From 6610f06c7bf1bc923b9b657e48968dfc2111a607 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 16:20:39 +0000 Subject: [PATCH 07/27] CI: Update workflows, eek. --- .github/workflows/build.yml | 41 +++++++++++++++++++++++++++++++++++++ .github/workflows/qa.yml | 36 ++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 24 +++++++++++++--------- 3 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/qa.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..87200ef --- /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 0000000..4f85883 --- /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 213fdea..016a678 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,37 +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: [2.7, 3.5, 3.7, 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 --upgrade setuptools 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' }} From c8506c9d0afb3336740d255e3977a218d38a6f89 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 19:20:31 +0000 Subject: [PATCH 08/27] Remove rogue .coveragerc. --- library/.coveragerc | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 library/.coveragerc diff --git a/library/.coveragerc b/library/.coveragerc deleted file mode 100644 index 626a4c0..0000000 --- a/library/.coveragerc +++ /dev/null @@ -1,4 +0,0 @@ -[run] -source = blinkt -omit = - .tox/* From e79775a482644014e2adfd6df8507a0d2da7beaa Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 19:20:46 +0000 Subject: [PATCH 09/27] Search for common gpiochip device names. Tested so far on a Pi 4 running Bullseye and a Pi 5 running Bookworm. --- blinkt/__init__.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index b230d01..552a54c 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -1,5 +1,6 @@ """Library for the Pimoroni Blinkt! - 8-pixel APA102 LED display.""" import atexit +import glob import time import gpiod @@ -11,7 +12,10 @@ CLK = 24 NUM_PIXELS = 8 BRIGHTNESS = 7 -GPIOCHIP = "/dev/gpiochip4" +RPI_GPIO_LABELS = [ + "pinctrl-rp1", # Pi 5 - Bookworm, /dev/gpiochip4 maybe + "pinctrl-bcm2711" # Pi 4 - Bullseye, /dev/gpiochip1 maybe +] pixels = [[0, 0, 0, BRIGHTNESS]] * NUM_PIXELS @@ -28,6 +32,14 @@ def _exit(): gpio_lines.release() +def get_gpiochip(): + for path in glob.glob("/dev/gpiochip*"): + if gpiod.is_gpiochip_device(path): + if gpiod.Chip(path).get_info().label in RPI_GPIO_LABELS: + return path + raise RuntimeError("Compatible /dev/gpiochipN device not found!") + + def set_brightness(brightness): """Set the brightness of all pixels. @@ -83,7 +95,7 @@ def show(): if not gpio_lines: gpio_lines = gpiod.request_lines( - GPIOCHIP, + get_gpiochip(), consumer="blinkt", config={ DAT: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE), From bcf2a6b031bc0556d03172099e76b54d9ae95bc9 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 19:49:09 +0000 Subject: [PATCH 10/27] Friendly errors when pins are claimed. --- blinkt/__init__.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index 552a54c..66b47dd 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -14,7 +14,7 @@ BRIGHTNESS = 7 RPI_GPIO_LABELS = [ "pinctrl-rp1", # Pi 5 - Bookworm, /dev/gpiochip4 maybe - "pinctrl-bcm2711" # Pi 4 - Bullseye, /dev/gpiochip1 maybe + "pinctrl-bcm2711" # Pi 4 - Bullseye, /dev/gpiochip0 maybe ] pixels = [[0, 0, 0, BRIGHTNESS]] * NUM_PIXELS @@ -32,11 +32,25 @@ def _exit(): gpio_lines.release() -def get_gpiochip(): +def check_pins_available(chip, pins): + err = [] + for (label, pin) in pins.items(): + pin_info = chip.get_line_info(pin) + if pin_info.used: + err.append(f" ⚠️ {label} (GPIO {DAT}) is currently claimed by {pin_info.consumer}") + if len(err): + err.insert(0, "some pins we need are in use:") + raise RuntimeError("\n".join(err)) + + +def get_gpiochip(pins=None): for path in glob.glob("/dev/gpiochip*"): if gpiod.is_gpiochip_device(path): if gpiod.Chip(path).get_info().label in RPI_GPIO_LABELS: - return path + chip = gpiod.Chip(path) + if pins is not None: + check_pins_available(chip, pins) + return chip raise RuntimeError("Compatible /dev/gpiochipN device not found!") @@ -94,8 +108,8 @@ def show(): global gpio_lines if not gpio_lines: - gpio_lines = gpiod.request_lines( - get_gpiochip(), + chip = get_gpiochip({"Data": DAT, "Clock": CLK}) + gpio_lines = chip.request_lines( consumer="blinkt", config={ DAT: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE), From 7b6d50e669ad68eb0f3dcef3bd14f5dabce90a36 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 31 Oct 2023 19:50:22 +0000 Subject: [PATCH 11/27] Tests: Fix to catch runtime error due to missing gpiochip. --- tests/test_setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_setup.py b/tests/test_setup.py index b450b7e..a83a685 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -1,7 +1,9 @@ """Test Blinkt! basic initialisation.""" +import pytest + def test_setup(gpiod): """Test init succeeds and GPIO pins are set up.""" import blinkt - blinkt.show() - gpiod.request_lines.assert_called_once() + with pytest.raises(RuntimeError): + blinkt.show() From 479fd1bf0eebb010eb987455b255e02e3af883c6 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 1 Nov 2023 10:52:10 +0000 Subject: [PATCH 12/27] Handle more gpiochip error cases. --- blinkt/__init__.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index 66b47dd..65237ec 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -14,7 +14,7 @@ BRIGHTNESS = 7 RPI_GPIO_LABELS = [ "pinctrl-rp1", # Pi 5 - Bookworm, /dev/gpiochip4 maybe - "pinctrl-bcm2711" # Pi 4 - Bullseye, /dev/gpiochip0 maybe + "pinctrl-bcm2711" # Pi 4, Pi 400 - Bullseye and Ubuntu, /dev/gpiochip0 maybe ] pixels = [[0, 0, 0, BRIGHTNESS]] * NUM_PIXELS @@ -33,6 +33,11 @@ def _exit(): def check_pins_available(chip, pins): + """Check if a list of pins are in use on a given gpiochip device. + + Raise a RuntimeError with a friendly list of in-use pins and their consumer if + any are in used. + """ err = [] for (label, pin) in pins.items(): pin_info = chip.get_line_info(pin) @@ -43,15 +48,28 @@ def check_pins_available(chip, pins): raise RuntimeError("\n".join(err)) -def get_gpiochip(pins=None): +def find_gpiochip(labels, pins=None): + """Try to find a /dev/gpiochipN device matching one of a set of labels. + + Raise a RuntimeError with a friendly error digest if one is not found. + """ + err = [] for path in glob.glob("/dev/gpiochip*"): if gpiod.is_gpiochip_device(path): - if gpiod.Chip(path).get_info().label in RPI_GPIO_LABELS: + try: + label = gpiod.Chip(path).get_info().label + except PermissionError: + err.append(f" ⚠️ {path}: Permission error!") + continue + if label in labels: chip = gpiod.Chip(path) if pins is not None: check_pins_available(chip, pins) return chip - raise RuntimeError("Compatible /dev/gpiochipN device not found!") + else: + err.append(f" ⚠️ {path}: This is not the GPIO we're looking for! ({label})") + err.insert(0, "Compatible /dev/gpiochipN device not found!") + raise RuntimeError("\n".join(err)) def set_brightness(brightness): @@ -108,7 +126,7 @@ def show(): global gpio_lines if not gpio_lines: - chip = get_gpiochip({"Data": DAT, "Clock": CLK}) + chip = find_gpiochip(RPI_GPIO_LABELS, {"Data": DAT, "Clock": CLK}) gpio_lines = chip.request_lines( consumer="blinkt", config={ From 7747e431d5fe29ed88fe1295794ae1e42b1d44b4 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 1 Nov 2023 11:02:35 +0000 Subject: [PATCH 13/27] Fix error output. --- blinkt/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index 65237ec..f52e1c3 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -42,7 +42,7 @@ def check_pins_available(chip, pins): for (label, pin) in pins.items(): pin_info = chip.get_line_info(pin) if pin_info.used: - err.append(f" ⚠️ {label} (GPIO {DAT}) is currently claimed by {pin_info.consumer}") + err.append(f" ⚠️ {label} (GPIO {pin}) is currently claimed by {pin_info.consumer}") if len(err): err.insert(0, "some pins we need are in use:") raise RuntimeError("\n".join(err)) From a44e9d1972da3ecbc12831c6c913954914fff67c Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 1 Nov 2023 15:49:06 +0000 Subject: [PATCH 14/27] Use gpiodevice to find pins. --- blinkt/__init__.py | 47 ++++++---------------------------------------- pyproject.toml | 3 ++- 2 files changed, 8 insertions(+), 42 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index f52e1c3..c9be263 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -6,6 +6,9 @@ import gpiod from gpiod.line import Direction, Value +import gpiodevice + + __version__ = '0.1.2' DAT = 23 @@ -24,6 +27,8 @@ gpio_lines = None _clear_on_exit = True +gpiodevice.friendly_errors = True + def _exit(): if _clear_on_exit: @@ -32,46 +37,6 @@ def _exit(): gpio_lines.release() -def check_pins_available(chip, pins): - """Check if a list of pins are in use on a given gpiochip device. - - Raise a RuntimeError with a friendly list of in-use pins and their consumer if - any are in used. - """ - err = [] - for (label, pin) in pins.items(): - pin_info = chip.get_line_info(pin) - if pin_info.used: - err.append(f" ⚠️ {label} (GPIO {pin}) is currently claimed by {pin_info.consumer}") - if len(err): - err.insert(0, "some pins we need are in use:") - raise RuntimeError("\n".join(err)) - - -def find_gpiochip(labels, pins=None): - """Try to find a /dev/gpiochipN device matching one of a set of labels. - - Raise a RuntimeError with a friendly error digest if one is not found. - """ - err = [] - for path in glob.glob("/dev/gpiochip*"): - if gpiod.is_gpiochip_device(path): - try: - label = gpiod.Chip(path).get_info().label - except PermissionError: - err.append(f" ⚠️ {path}: Permission error!") - continue - if label in labels: - chip = gpiod.Chip(path) - if pins is not None: - check_pins_available(chip, pins) - return chip - else: - err.append(f" ⚠️ {path}: This is not the GPIO we're looking for! ({label})") - err.insert(0, "Compatible /dev/gpiochipN device not found!") - raise RuntimeError("\n".join(err)) - - def set_brightness(brightness): """Set the brightness of all pixels. @@ -126,7 +91,7 @@ def show(): global gpio_lines if not gpio_lines: - chip = find_gpiochip(RPI_GPIO_LABELS, {"Data": DAT, "Clock": CLK}) + chip = gpiodevice.find_chip_by_label(RPI_GPIO_LABELS, {"Data": DAT, "Clock": CLK}) gpio_lines = chip.request_lines( consumer="blinkt", config={ diff --git a/pyproject.toml b/pyproject.toml index aa3cb3b..7d1b607 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,8 @@ classifiers = [ "Topic :: System :: Hardware", ] dependencies = [ - "gpiod" + "gpiod", + "gpiodevice" ] [project.urls] From 2eff9bad91c2e0b32d7466b4c1bb398503ee4b98 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 1 Nov 2023 17:11:53 +0000 Subject: [PATCH 15/27] Update to latest gpiodevice lib. --- blinkt/__init__.py | 75 ++++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index c9be263..b18ae99 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -11,20 +11,23 @@ __version__ = '0.1.2' -DAT = 23 -CLK = 24 +OUTL = gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE) +PLATFORMS = { + "Radxa ROCK 5B": {"dat": ("PIN_16", OUTL), "clk": ("PIN_18", OUTL)}, + "Raspberry Pi 5": {"dat": ("PIN23", OUTL), "clk": ("PIN24", OUTL)}, + "Raspberry Pi 4": {"dat": ("GPIO23", OUTL), "clk": ("GPIO24", OUTL)} +} NUM_PIXELS = 8 BRIGHTNESS = 7 -RPI_GPIO_LABELS = [ - "pinctrl-rp1", # Pi 5 - Bookworm, /dev/gpiochip4 maybe - "pinctrl-bcm2711" # Pi 4, Pi 400 - Bullseye and Ubuntu, /dev/gpiochip0 maybe -] pixels = [[0, 0, 0, BRIGHTNESS]] * NUM_PIXELS sleep_time = 0 -gpio_lines = None +clk_lines = None +clk_line = None +dat_lines = None +dat_line = None _clear_on_exit = True gpiodevice.friendly_errors = True @@ -34,7 +37,8 @@ def _exit(): if _clear_on_exit: clear() show() - gpio_lines.release() + dat_lines.release() + clk_lines.release() def set_brightness(brightness): @@ -58,48 +62,61 @@ def clear(): def _write_byte(byte): for x in range(8): - gpio_lines.set_value(DAT, Value.ACTIVE if (byte & 0b10000000) else Value.INACTIVE) - gpio_lines.set_value(CLK, Value.ACTIVE) + dat_lines.set_value(dat_line, Value.ACTIVE if (byte & 0b10000000) else Value.INACTIVE) + clk_lines.set_value(clk_line, Value.ACTIVE) time.sleep(sleep_time) byte <<= 1 - gpio_lines.set_value(CLK, Value.INACTIVE) + clk_lines.set_value(clk_line, Value.INACTIVE) time.sleep(sleep_time) # Emit exactly enough clock pulses to latch the small dark die APA102s which are weird # for some reason it takes 36 clocks, the other IC takes just 4 (number of pixels/2) def _eof(): - gpio_lines.set_value(DAT, Value.INACTIVE) + dat_lines.set_value(dat_line, Value.INACTIVE) for x in range(36): - gpio_lines.set_value(CLK, Value.ACTIVE) + clk_lines.set_value(clk_line, Value.ACTIVE) time.sleep(sleep_time) - gpio_lines.set_value(CLK, Value.INACTIVE) + clk_lines.set_value(clk_line, Value.INACTIVE) time.sleep(sleep_time) def _sof(): - gpio_lines.set_value(DAT, Value.INACTIVE) + dat_lines.set_value(dat_line, Value.INACTIVE) for x in range(32): - gpio_lines.set_value(CLK, Value.ACTIVE) + clk_lines.set_value(clk_line, Value.ACTIVE) time.sleep(sleep_time) - gpio_lines.set_value(CLK, Value.INACTIVE) + clk_lines.set_value(clk_line, Value.INACTIVE) time.sleep(sleep_time) +def set_pins(pin_dat, pin_clk): + global clk_lines, dat_lines, dat_line, clk_line + + chip_dat = gpiodevice.find_chip_by_pins(pin_dat) + dat_line = chip_dat.line_offset_from_id(pin_dat) + dat_lines = chip_dat.request_lines(consumer="blinkt", config={dat_line: OUTL}) + + chip_clk = gpiodevice.find_chip_by_pins(pin_clk) + clk_line = chip_clk.line_offset_from_id(pin_clk) + clk_lines = chip_clk.request_lines(consumer="blinkt", config={clk_line: OUTL}) + + +def default_pins(): + global clk_lines, dat_lines, dat_line, clk_line + + dat, clk = gpiodevice.get_pins_for_platform(PLATFORMS) + dat_lines, dat_line = dat + clk_lines, clk_line = clk + + def show(): """Output the buffer to Blinkt!.""" - global gpio_lines - - if not gpio_lines: - chip = gpiodevice.find_chip_by_label(RPI_GPIO_LABELS, {"Data": DAT, "Clock": CLK}) - gpio_lines = chip.request_lines( - consumer="blinkt", - config={ - DAT: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE), - CLK: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE) - } - ) - atexit.register(_exit) + if not clk_line: + default_pins() + + atexit.unregister(_exit) + atexit.register(_exit) _sof() From 18e5eb98cafe8cf03aa415c8bca0b60c4c2f1e76 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 1 Nov 2023 17:22:26 +0000 Subject: [PATCH 16/27] Fix Pi 5 pins. --- blinkt/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index b18ae99..172a4de 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -14,7 +14,7 @@ OUTL = gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE) PLATFORMS = { "Radxa ROCK 5B": {"dat": ("PIN_16", OUTL), "clk": ("PIN_18", OUTL)}, - "Raspberry Pi 5": {"dat": ("PIN23", OUTL), "clk": ("PIN24", OUTL)}, + "Raspberry Pi 5": {"dat": ("PIN16", OUTL), "clk": ("PIN18", OUTL)}, "Raspberry Pi 4": {"dat": ("GPIO23", OUTL), "clk": ("GPIO24", OUTL)} } NUM_PIXELS = 8 From d9245a83fcf9be41f0636235e048772f95c9e79b Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 2 Nov 2023 11:03:20 +0000 Subject: [PATCH 17/27] Do not explicitly release gpio lines. Avoid a segfault on exit as detailed in pimoroni/gpiodevice-python#1 --- blinkt/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index 172a4de..ceafdc8 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -37,8 +37,6 @@ def _exit(): if _clear_on_exit: clear() show() - dat_lines.release() - clk_lines.release() def set_brightness(brightness): From bad87d10c222c878292a825f1bed15701314e32c Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 2 Nov 2023 11:04:55 +0000 Subject: [PATCH 18/27] Try to set up pins using gpiodevice before falling back. --- blinkt/__init__.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index ceafdc8..af2982e 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -91,13 +91,25 @@ def _sof(): def set_pins(pin_dat, pin_clk): global clk_lines, dat_lines, dat_line, clk_line + try: + chip = gpiodevice.find_chip_by_pins((pin_dat, pin_clk)) + dat_line = chip.line_offset_from_id(pin_dat) + clk_line = chip.line_offset_from_id(pin_clk) + dat_lines = clk_lines = chip.request_lines(consumer="blinkt", config={ + dat_line: OUTL, + clk_line: OUTL + }) + return + except SystemExit: + pass + chip_dat = gpiodevice.find_chip_by_pins(pin_dat) dat_line = chip_dat.line_offset_from_id(pin_dat) - dat_lines = chip_dat.request_lines(consumer="blinkt", config={dat_line: OUTL}) + dat_lines = chip_dat.request_lines(consumer="blinkt-dat", config={dat_line: OUTL}) chip_clk = gpiodevice.find_chip_by_pins(pin_clk) clk_line = chip_clk.line_offset_from_id(pin_clk) - clk_lines = chip_clk.request_lines(consumer="blinkt", config={clk_line: OUTL}) + clk_lines = chip_clk.request_lines(consumer="blinkt-clk", config={clk_line: OUTL}) def default_pins(): From 16d2fcd5073ae1e5b1767e14a1d7f3b12a901a5a Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 2 Nov 2023 11:16:02 +0000 Subject: [PATCH 19/27] Fix import sorting. --- blinkt/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index af2982e..7cae75e 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -4,10 +4,8 @@ import time import gpiod -from gpiod.line import Direction, Value - import gpiodevice - +from gpiod.line import Direction, Value __version__ = '0.1.2' From d234a1eb6631157e3e39f05dab657ce6f225bc48 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 2 Nov 2023 11:25:53 +0000 Subject: [PATCH 20/27] Require gpiodevice >= 0.0.2 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7d1b607..7c38d53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ classifiers = [ ] dependencies = [ "gpiod", - "gpiodevice" + "gpiodevice>=0.0.2" ] [project.urls] From c6fcf62dd67d27425b128af502f48e57191bbe1d Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 2 Nov 2023 11:29:33 +0000 Subject: [PATCH 21/27] Remove unused glob import. --- blinkt/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index 7cae75e..f9918dc 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -1,6 +1,5 @@ """Library for the Pimoroni Blinkt! - 8-pixel APA102 LED display.""" import atexit -import glob import time import gpiod From 9d2b4c87f622bc6adcf62b9865e726a704ef614b Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 2 Nov 2023 11:36:12 +0000 Subject: [PATCH 22/27] Fix test to pass locally. --- tests/test_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_setup.py b/tests/test_setup.py index a83a685..7853ccb 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -5,5 +5,5 @@ def test_setup(gpiod): """Test init succeeds and GPIO pins are set up.""" import blinkt - with pytest.raises(RuntimeError): + with pytest.raises((RuntimeError, SystemExit)): blinkt.show() From 8134ffa8d5dbe5c62d7cfdb7be8f753d310b086d Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 23 Nov 2023 10:49:33 +0000 Subject: [PATCH 23/27] install.sh: rework for better error reporting and fix some bugs. Fix a bug where auto_venv.sh was being created in a non-existent directory. Trap exit codes for some commands and add some help text + GitHUb url at the end of the install process. Try to comment what some sections do, and insert linebreaks so they are more logically broken up in the installer output. Try to be more consistent with colours. Try to be more friendly with colours- remove full red warning text in favour of a prefix so the errors/warnings are easier to read. Return a failure exit code if bits of the script have failed. Try to re-order output so it's more logical. Re-word venv creation message. --- install.sh | 165 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 123 insertions(+), 42 deletions(-) diff --git a/install.sh b/install.sh index aebc385..d42c48d 100755 --- a/install.sh +++ b/install.sh @@ -1,24 +1,25 @@ #!/bin/bash LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'` -CONFIG=/boot/config.txt +CONFIG_FILE=config.txt +CONFIG_DIR="/boot/firmware" DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` CONFIG_BACKUP=false APT_HAS_UPDATED=false -RESOURCES_TOP_DIR=$HOME/Pimoroni -VENV_BASH_SNIPPET=$RESOURCES_DIR/auto_venv.sh -VENV_DIR=$HOME/.virtualenvs/pimoroni +RESOURCES_TOP_DIR="$HOME/Pimoroni" +VENV_BASH_SNIPPET="$RESOURCES_TOP_DIR/auto_venv.sh" +VENV_DIR="$HOME/.virtualenvs/pimoroni" WD=`pwd` USAGE="./install.sh (--unstable)" POSITIONAL_ARGS=() FORCE=false UNSTABLE=false PYTHON="python" +CMD_ERRORS=false user_check() { if [ $(id -u) -eq 0 ]; then - printf "Script should not be run as root. Try './install.sh'\n" - exit 1 + fatal "Script should not be run as root. Try './install.sh'\n" fi } @@ -53,13 +54,36 @@ inform() { } warning() { - echo -e "$(tput setaf 1)$1$(tput sgr0)" + echo -e "$(tput setaf 1)⚠ WARNING:$(tput sgr0) $1" +} + +fatal() { + echo -e "$(tput setaf 1)⚠ FATAL:$(tput sgr0) $1" + exit 1 +} + +find_config() { + if [ ! -f "$CONFIG_DIR/$CONFIG_FILE" ]; then + CONFIG_DIR="/boot" + if [ ! -f "$CONFIG_DIR/$CONFIG_FILE" ]; then + fatal "Could not find $CONFIG_FILE!" + fi + else + if [ -f "/boot/$CONFIG_FILE" ] && [ ! -L "/boot/$CONFIG_FILE" ]; then + warning "Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR/$CONFIG_FILE" + warning "You might want to fix this!" + fi + fi + inform "Using $CONFIG_FILE in $CONFIG_DIR" } 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 $RESOURCES_DIR/auto_venv.sh` to your ~/.bashrc to activate +# Add "source $VENV_BASH_SNIPPET" to your ~/.bashrc to activate # the Pimoroni virtual environment automagically! VENV_DIR="$VENV_DIR" if [ ! -f \$VENV_DIR/bin/activate ]; then @@ -77,35 +101,44 @@ venv_check() { PYTHON_BIN=`which $PYTHON` if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then printf "This script should be run in a virtual Python environment.\n" - if confirm "Would you like us to create one for you?"; then + if confirm "Would you like us to create and/or use a default one?"; then + printf "\n" if [ ! -f $VENV_DIR/bin/activate ]; then - inform "Creating virtual Python environment in $VENV_DIR, please wait...\n" + inform "Creating a new virtual Python environment in $VENV_DIR, please wait...\n" mkdir -p $VENV_DIR /usr/bin/python3 -m venv $VENV_DIR --system-site-packages venv_bash_snippet + source $VENV_DIR/bin/activate else - inform "Found existing virtual Python environment in $VENV_DIR\n" + inform "Activating existing virtual Python environment in $VENV_DIR\n" + printf "source $VENV_DIR/bin/activate\n" + source $VENV_DIR/bin/activate fi - inform "Activating virtual Python environment in $VENV_DIR..." - inform "source $VENV_DIR/bin/activate\n" - source $VENV_DIR/bin/activate - else - exit 1 + printf "\n" + fatal "Please create and/or activate a virtual Python environment and try again!\n" fi fi + printf "\n" +} + +check_for_error() { + if [ $? -ne 0 ]; then + CMD_ERRORS=true + warning "^^^ 😬" + fi } function do_config_backup { if [ ! $CONFIG_BACKUP == true ]; then CONFIG_BACKUP=true FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt" - inform "Backing up $CONFIG to /boot/$FILENAME\n" - sudo cp $CONFIG /boot/$FILENAME + inform "Backing up $CONFIG_DIR/$CONFIG_FILE to $CONFIG_DIR/$FILENAME\n" + sudo cp $CONFIG_DIR/$CONFIG_FILE $CONFIG_DIR/$FILENAME mkdir -p $RESOURCES_TOP_DIR/config-backups/ - cp $CONFIG $RESOURCES_TOP_DIR/config-backups/$FILENAME + cp $CONFIG_DIR/$CONFIG_FILE $RESOURCES_TOP_DIR/config-backups/$FILENAME if [ -f "$UNINSTALLER" ]; then - echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG" >> $UNINSTALLER + echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG_DIR/$CONFIG_FILE" >> $UNINSTALLER fi fi } @@ -113,6 +146,7 @@ function do_config_backup { function apt_pkg_install { PACKAGES=() PACKAGES_IN=("$@") + # Check the list of packages and only run update/install if we need to for ((i = 0; i < ${#PACKAGES_IN[@]}; i++)); do PACKAGE="${PACKAGES_IN[$i]}" if [ "$PACKAGE" == "" ]; then continue; fi @@ -124,12 +158,14 @@ function apt_pkg_install { done PACKAGES="${PACKAGES[@]}" if ! [ "$PACKAGES" == "" ]; then - echo "Installing missing packages: $PACKAGES" + printf "\n" + inform "Installing missing packages: $PACKAGES" if [ ! $APT_HAS_UPDATED ]; then sudo apt update APT_HAS_UPDATED=true fi sudo apt install -y $PACKAGES + check_for_error if [ -f "$UNINSTALLER" ]; then echo "apt uninstall -y $PACKAGES" >> $UNINSTALLER fi @@ -137,7 +173,9 @@ function apt_pkg_install { } function pip_pkg_install { + # A null Keyring prevents pip stalling in the background PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring $PYTHON -m pip install --upgrade "$@" + check_for_error } while [[ $# -gt 0 ]]; do @@ -167,30 +205,33 @@ while [[ $# -gt 0 ]]; do esac done +printf "Installing $LIBRARY_NAME...\n\n" + user_check venv_check if [ ! -f `which $PYTHON` ]; then - printf "Python path $PYTHON not found!\n" - exit 1 + fatal "Python path $PYTHON not found!\n" fi PYTHON_VER=`$PYTHON --version` -printf "$LIBRARY_NAME Python Library: Installer\n\n" - inform "Checking Dependencies. Please wait..." +# Install toml and try to read pyproject.toml into bash variables + pip_pkg_install toml CONFIG_VARS=`$PYTHON - < $UNINSTALLER printf "It's recommended you run these steps manually.\n" printf "If you want to run the full script, open it in\n" @@ -225,19 +270,23 @@ exit 1 source $VIRTUAL_ENV/bin/activate EOF -if $UNSTABLE; then - warning "Installing unstable library from source.\n\n" -else - printf "Installing stable library from pypi.\n\n" -fi +printf "\n" inform "Installing for $PYTHON_VER...\n" + +# Install apt packages from pyproject.toml / tool.pimoroni.apt_packages apt_pkg_install "${APT_PACKAGES[@]}" + +printf "\n" + if $UNSTABLE; then + warning "Installing unstable library from source.\n" pip_pkg_install . else + inform "Installing stable library from pypi.\n" pip_pkg_install $LIBRARY_NAME fi + if [ $? -eq 0 ]; then success "Done!\n" echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> $UNINSTALLER @@ -245,27 +294,40 @@ fi cd $WD +find_config + +# Run the setup commands from pyproject.toml / tool.pimoroni.commands + for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do CMD="${SETUP_CMDS[$i]}" - # Attempt to catch anything that touches /boot/config.txt and trigger a backup - if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG"* ]] || [[ "$CMD" == *"\$CONFIG"* ]]; then + # Attempt to catch anything that touches config.txt and trigger a backup + if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG_DIR/$CONFIG_FILE"* ]] || [[ "$CMD" == *"\$CONFIG_DIR/\$CONFIG_FILE"* ]]; then do_config_backup fi eval $CMD + 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\n" - sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG - if ! grep -q "^$CONFIG_LINE" $CONFIG; then - printf "$CONFIG_LINE\n" | sudo tee --append $CONFIG + inform "Adding $CONFIG_LINE to $CONFIG_DIR/$CONFIG_FILE" + 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 +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" @@ -277,9 +339,12 @@ fi printf "\n" +# Use pdoc to generate basic documentation from the installed module + if confirm "Would you like to generate documentation?"; then + inform "Installing pdoc. Please wait..." pip_pkg_install pdoc - printf "Generating documentation.\n" + inform "Generating documentation.\n" $PYTHON -m pdoc $LIBRARY_NAME -o $RESOURCES_DIR/docs > /dev/null if [ $? -eq 0 ]; then inform "Documentation saved to $RESOURCES_DIR/docs" @@ -289,6 +354,22 @@ if confirm "Would you like to generate documentation?"; then fi fi -success "\nAll done!" -inform "If this is your first time installing you should reboot for hardware changes to take effect.\n" -inform "Find uninstall steps in $UNINSTALLER\n" +printf "\n" + +if [ "$CMD_ERRORS" = true ]; then + warning "One or more setup commands appear to have failed." + printf "This might prevent things from working properly.\n" + printf "Make sure your OS is up to date and try re-running this installer.\n" + printf "If things still don't work, report this or find help at $GITHUB_URL.\n\n" +else + success "\nAll done!" +fi + +printf "If this is your first time installing you should reboot for hardware changes to take effect.\n" +printf "Find uninstall steps in $UNINSTALLER\n\n" + +if [ "$CMD_ERRORS" = true ]; then + exit 1 +else + exit 0 +fi \ No newline at end of file From 402ff25460e85889026db13f13d15b75901949f5 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 23 Nov 2023 11:17:49 +0000 Subject: [PATCH 24/27] Shakeup examples and fix README links. --- .coveragerc | 4 + README.md | 2 +- examples/1d_tetris.py | 2 +- ...our-control.py => anvil_colour_control.py} | 4 +- examples/binary_clock.py | 10 +-- examples/binary_clock_meld.py | 4 +- examples/blinkt_thermo.py | 23 ++--- examples/candle.py | 3 +- examples/cheerlights.py | 12 +-- examples/cpu_load.py | 3 +- examples/cpu_temp.py | 4 +- examples/extra_examples/drum_hits.py | 11 ++- examples/extra_examples/pov_rainbow.py | 5 +- examples/extra_examples/spirit_level.py | 3 +- examples/eyedropper.py | 6 +- examples/kitt.py | 16 ++-- examples/larson_hue.py | 12 +-- examples/mem_load.py | 3 +- examples/morse_code.py | 8 +- examples/mqtt.py | 45 +++++----- examples/pulse.py | 5 +- examples/resistor_clock.py | 16 ++-- examples/rgb.py | 4 +- examples/setall.py | 2 +- examples/twitter_monitor.py | 47 ----------- projects/mqtt/mqtt.py | 84 ++++++++----------- pyproject.toml | 3 + requirements-examples.txt | 8 ++ tests/conftest.py | 18 ++++ tests/test_setup.py | 67 +++++++++++++++ 30 files changed, 225 insertions(+), 209 deletions(-) create mode 100644 .coveragerc rename examples/{anvil-colour-control.py => anvil_colour_control.py} (91%) delete mode 100755 examples/twitter_monitor.py create mode 100644 requirements-examples.txt diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..e16890c --- /dev/null +++ b/.coveragerc @@ -0,0 +1,4 @@ +[run] +source = blinkt +omit = + tests/ \ No newline at end of file diff --git a/README.md b/README.md index 3b6eb93..0d0e794 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Blinkt!](blinkt-logo.png) -[![Build Status](https://travis-ci.com/pimoroni/blinkt.svg?branch=master)](https://travis-ci.com/pimoroni/blinkt) +[![Build Status](https://img.shields.io/github/actions/workflow/status/pimoroni/blinkt/test.yml?branch=main)](https://github.com/pimoroni/blinkt/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/pimoroni/blinkt/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/blinkt?branch=master) [![PyPi Package](https://img.shields.io/pypi/v/blinkt.svg)](https://pypi.python.org/pypi/blinkt) [![Python Versions](https://img.shields.io/pypi/pyversions/blinkt.svg)](https://pypi.python.org/pypi/blinkt) diff --git a/examples/1d_tetris.py b/examples/1d_tetris.py index 406a13e..f9b71ea 100755 --- a/examples/1d_tetris.py +++ b/examples/1d_tetris.py @@ -90,5 +90,5 @@ def main(): update() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/examples/anvil-colour-control.py b/examples/anvil_colour_control.py similarity index 91% rename from examples/anvil-colour-control.py rename to examples/anvil_colour_control.py index 1b6a75f..3019a48 100755 --- a/examples/anvil-colour-control.py +++ b/examples/anvil_colour_control.py @@ -31,7 +31,7 @@ @anvil.server.callable def set_color(color_string): - print("Setting LEDs to {}".format(color_string)) + print(f"Setting LEDs to {color_string}") c = Color(color_string) blinkt.set_all(c.red * 255, c.green * 255, c.blue * 255, 1.0) blinkt.show() @@ -45,7 +45,7 @@ def clear(): # Display the URL where you can control the Blinkt LEDS -print("Control your Blinkt LEDs at {}".format(app.origin)) +print(f"Control your Blinkt LEDs at {app.origin}") print("Press Ctrl-C to exit") # Keep the script running until the user exits with Ctrl-C diff --git a/examples/binary_clock.py b/examples/binary_clock.py index 7e75db9..25be528 100755 --- a/examples/binary_clock.py +++ b/examples/binary_clock.py @@ -9,9 +9,7 @@ MODE_HOUR = 0 MODE_MIN = 1 MODE_SEC = 2 -MODE_NAMES = {MODE_HOUR: 'Hour mode', - MODE_MIN: 'Minute mode', - MODE_SEC: 'Seconds mode'} +MODE_NAMES = {MODE_HOUR: "Hour mode", MODE_MIN: "Minute mode", MODE_SEC: "Seconds mode"} time_to_stay_in_mode = 3 time_in_mode = 0 @@ -62,11 +60,7 @@ blinkt.set_pixel(7 - x, r, g, b) blinkt.show() - print('{h:2d}:{m:02d}:{s:02d}; mode: {mode}; time in mode: {tim}'.format(h=h, - m=m, - s=s, - mode=MODE_NAMES[mode], - tim=time_in_mode)) + print(f"{h:2d}:{m:02d}:{s:02d}; mode: {MODE_NAMES[mode]}; time in mode: {time_in_mode}") time_in_mode += 1 if time_in_mode == time_to_stay_in_mode: diff --git a/examples/binary_clock_meld.py b/examples/binary_clock_meld.py index add7f2e..116f05f 100755 --- a/examples/binary_clock_meld.py +++ b/examples/binary_clock_meld.py @@ -4,7 +4,7 @@ import blinkt -print('Hour = Red, Minute = Green, Second = Blue') +print("Hour = Red, Minute = Green, Second = Blue") blinkt.set_clear_on_exit() @@ -16,7 +16,7 @@ t = localtime() h, m, s = t.tm_hour, t.tm_min, t.tm_sec - print('{h:2d}:{m:02d}:{s:02d}'.format(h=h, m=m, s=s)) + print(f"{h:2d}:{m:02d}:{s:02d}") blinkt.clear() diff --git a/examples/blinkt_thermo.py b/examples/blinkt_thermo.py index e056c70..71e1a16 100755 --- a/examples/blinkt_thermo.py +++ b/examples/blinkt_thermo.py @@ -3,40 +3,35 @@ # Data from OpenWeatherMap # show_graph function adapted from cpu_temp.py -from sys import exit from time import sleep try: import requests except ImportError: - exit('This script requires the requests module\nInstall with: sudo pip install requests') + raise ImportError("This script requires the requests module\nInstall with: python3 -m pip install requests") import blinkt # Grab your API key here: http://openweathermap.org # List of city ID city.list.json.gz can be downloaded here http://bulk.openweathermap.org/sample/ -API_KEY = '' -CITY_ID = '' +API_KEY = "" +CITY_ID = "" -url = 'http://api.openweathermap.org/data/2.5/weather' +url = "http://api.openweathermap.org/data/2.5/weather" temp = 0 def update_weather(): global temp - payload = { - 'id': CITY_ID, - 'units': 'metric', - 'appid': API_KEY - } + payload = {"id": CITY_ID, "units": "metric", "appid": API_KEY} try: r = requests.get(url=url, params=payload) - temp = r.json().get('main').get('temp') - print('Temperture = ' + str(temp) + ' C') + temp = r.json().get("main").get("temp") + print("Temperture = " + str(temp) + " C") except requests.exceptions.ConnectionError: - print('Connection Error') + print("Connection Error") def show_graph(v, r, g, b): @@ -54,7 +49,7 @@ def show_graph(v, r, g, b): def draw_thermo(temp): v = temp v /= 40 - v += (1 / 8) + v += 1 / 8 show_graph(v, 255, 0, 0) diff --git a/examples/candle.py b/examples/candle.py index 3ef114f..b9aa5f0 100755 --- a/examples/candle.py +++ b/examples/candle.py @@ -2,12 +2,11 @@ import colorsys import time -from sys import exit try: import numpy as np except ImportError: - exit('This script requires the numpy module\nInstall with: python3 -m pip install numpy') + raise ImportError("This script requires the numpy module\nInstall with: python3 -m pip install numpy") import blinkt diff --git a/examples/cheerlights.py b/examples/cheerlights.py index 1783feb..0c53162 100755 --- a/examples/cheerlights.py +++ b/examples/cheerlights.py @@ -5,7 +5,7 @@ try: import requests except ImportError: - exit('This script requires the requests module\nInstall with: sudo pip install requests') + exit("This script requires the requests module\nInstall with: python3 -m pip install requests") import blinkt @@ -14,20 +14,20 @@ def hex_to_rgb(col_hex): """Convert a hex colour to an RGB tuple.""" - col_hex = col_hex.lstrip('#') + col_hex = col_hex.lstrip("#") return bytearray.fromhex(col_hex) while True: - r = requests.get('http://api.thingspeak.com/channels/1417/field/2/last.json', timeout=2) + r = requests.get("http://api.thingspeak.com/channels/1417/field/2/last.json", timeout=2) json = r.json() - if 'field2' not in json: - print('Error {status}: {error}'.format(status=json['status'], error=json['error'])) + if "field2" not in json: + print(f"Error {json['status']}: {json['error']}") time.sleep(5) continue - r, g, b = hex_to_rgb(json['field2']) + r, g, b = hex_to_rgb(json["field2"]) for i in range(blinkt.NUM_PIXELS): blinkt.set_pixel(i, r, g, b) diff --git a/examples/cpu_load.py b/examples/cpu_load.py index 1331229..e928820 100755 --- a/examples/cpu_load.py +++ b/examples/cpu_load.py @@ -1,11 +1,10 @@ #!/usr/bin/env python import time -from sys import exit try: import psutil except ImportError: - exit('This script requires the psutil module\nInstall with: sudo apt install python3-psutil') + raise ImportError("This script requires the psutil module\nInstall with: sudo apt install python3-psutil") import blinkt diff --git a/examples/cpu_temp.py b/examples/cpu_temp.py index 29b99e4..5f5686d 100755 --- a/examples/cpu_temp.py +++ b/examples/cpu_temp.py @@ -9,11 +9,11 @@ def get_cpu_temperature(): - process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE) + process = Popen(["vcgencmd", "measure_temp"], stdout=PIPE) output, _error = process.communicate() output = output.decode() - pos_start = output.index('=') + 1 + pos_start = output.index("=") + 1 pos_end = output.rindex("'") temp = float(output[pos_start:pos_end]) diff --git a/examples/extra_examples/drum_hits.py b/examples/extra_examples/drum_hits.py index dad43e5..8b4da7a 100755 --- a/examples/extra_examples/drum_hits.py +++ b/examples/extra_examples/drum_hits.py @@ -3,28 +3,27 @@ import glob import os import time -from sys import exit try: import drumhat except ImportError: - exit('This script requires the drumhat module\nInstall with: sudo pip install drumhat') + raise ImportError("This script requires the drumhat module\nInstall with: python3 -m pip install drumhat") try: import pygame except ImportError: - exit('This script requires the pygame module\nInstall with: sudo pip install pygame') + raise ImportError("This script requires the pygame module\nInstall with: python3 -m pip install pygame") import blinkt -DRUM_FOLDER = 'drums2' +DRUM_FOLDER = "drums2" BANK = os.path.join(os.path.dirname(__file__), DRUM_FOLDER) pygame.mixer.init(44100, -16, 1, 512) pygame.mixer.set_num_channels(16) -files = glob.glob(os.path.join(BANK, '*.wav')) +files = glob.glob(os.path.join(BANK, "*.wav")) files.sort() samples = [pygame.mixer.Sound(f) for f in files] @@ -40,7 +39,7 @@ def show_all(state): def handle_hit(event): samples[event.channel].play(loops=0) show_all(1) - print('You hit pad {}, playing: {}'.format(event.pad, files[event.channel])) + print(f"You hit pad {event.pad}, playing: {files[event.channel]}") def handle_release(): diff --git a/examples/extra_examples/pov_rainbow.py b/examples/extra_examples/pov_rainbow.py index d56bd2a..e3bd39a 100755 --- a/examples/extra_examples/pov_rainbow.py +++ b/examples/extra_examples/pov_rainbow.py @@ -2,12 +2,11 @@ import time from colorsys import hsv_to_rgb -from sys import exit try: from envirophat import motion except ImportError: - exit('This script requires the envirophat module\nInstall with: sudo pip install envirophat') + raise ImportError("This script requires the envirophat module\nInstall with: python3 -m pip install envirophat") import blinkt @@ -42,7 +41,7 @@ def millis(): if len(t) > 0: total_time = float(sum(t)) / len(t) - offset = ((millis() - t_start) / total_time) + offset = (millis() - t_start) / total_time # offset += direction * 10 diff --git a/examples/extra_examples/spirit_level.py b/examples/extra_examples/spirit_level.py index c48dfc8..784a76c 100755 --- a/examples/extra_examples/spirit_level.py +++ b/examples/extra_examples/spirit_level.py @@ -1,12 +1,11 @@ #!/usr/bin/env python import time -from sys import exit try: from envirophat import motion except ImportError: - exit('This script requires the envirophat module\nInstall with: sudo pip install envirophat') + raise ImportError("This script requires the envirophat module\nInstall with: python3 -m pip install envirophat") import blinkt diff --git a/examples/eyedropper.py b/examples/eyedropper.py index 429a5c1..d2ea621 100644 --- a/examples/eyedropper.py +++ b/examples/eyedropper.py @@ -7,7 +7,7 @@ import blinkt -print('Press Ctrl-C to quit.') +print("Press Ctrl-C to quit.") try: while True: @@ -15,10 +15,10 @@ im = ImageGrab.grab(bbox=(x - 1, y, x, y + 1)) rawrgb = list(im.getdata()) rgb = str(rawrgb)[2:-2] - r, g, b = rgb.split(', ') + r, g, b = rgb.split(", ") blinkt.set_all(r, g, b) blinkt.set_brightness(1) blinkt.show() time.sleep(0.01) except KeyboardInterrupt: - print('\n') + print("\n") diff --git a/examples/kitt.py b/examples/kitt.py index 4304089..d1f3311 100644 --- a/examples/kitt.py +++ b/examples/kitt.py @@ -4,20 +4,20 @@ import blinkt # so we can talk to our blinkt lights! -BRIGHTNESS = 0.2 # range is 0.0 to 1.0 -MAX_COLOUR = 255 # range is 0 to 255 -DECAY_FACTOR = 1.5 # how quickly should MAX_COLOUR fade? (1.5 works well) -TIME_SLEEP = 0.04 # seconds (0.04 works well) +BRIGHTNESS = 0.2 # range is 0.0 to 1.0 +MAX_COLOUR = 255 # range is 0 to 255 +DECAY_FACTOR = 1.5 # how quickly should MAX_COLOUR fade? (1.5 works well) +TIME_SLEEP = 0.04 # seconds (0.04 works well) PIXELS = blinkt.NUM_PIXELS # usually 8, can use fewer if you like! -blinkt.clear # make all pixels blank / black +blinkt.clear # make all pixels blank / black blinkt.set_brightness(BRIGHTNESS) brightpixel = -1 direction = 1 -print('Hello Michael.\nHow are you today?') +print("Hello Michael.\nHow are you today?") while True: # decay all pixels @@ -31,12 +31,12 @@ if brightpixel >= PIXELS - 1: brightpixel = PIXELS - 1 - direction = - abs(direction) + direction = -abs(direction) if brightpixel <= 0: brightpixel = 0 direction = abs(direction) blinkt.set_pixel(brightpixel, MAX_COLOUR, 0, 0) - blinkt.show() # draw the lights! + blinkt.show() # draw the lights! time.sleep(TIME_SLEEP) # wait a bit before working on next frame diff --git a/examples/larson_hue.py b/examples/larson_hue.py index b70a8eb..53ea617 100755 --- a/examples/larson_hue.py +++ b/examples/larson_hue.py @@ -14,7 +14,7 @@ start_time = time.time() while True: - delta = (time.time() - start_time) + delta = time.time() - start_time # Offset is a sine wave derived from the time delta # we use this to animate both the hue and larson scan @@ -34,13 +34,13 @@ sat = 1.0 val = max_val - (abs(offset - x) * FALLOFF) - val /= float(max_val) # Convert to 0.0 to 1.0 - val = max(val, 0.0) # Ditch negative values + val /= float(max_val) # Convert to 0.0 to 1.0 + val = max(val, 0.0) # Ditch negative values - xhue = hue # Grab hue for this pixel + xhue = hue # Grab hue for this pixel xhue += (1 - val) * 10 # Use the val offset to give a slight colour trail variation - xhue %= 360 # Clamp to 0-359 - xhue /= 360.0 # Convert to 0.0 to 1.0 + xhue %= 360 # Clamp to 0-359 + xhue /= 360.0 # Convert to 0.0 to 1.0 r, g, b = [int(c * 255) for c in colorsys.hsv_to_rgb(xhue, sat, val)] diff --git a/examples/mem_load.py b/examples/mem_load.py index fe0c410..5141a2e 100755 --- a/examples/mem_load.py +++ b/examples/mem_load.py @@ -1,12 +1,11 @@ #!/usr/bin/env python import time -from sys import exit try: import psutil except ImportError: - exit('This script requires the psutil module\nInstall with: python3 -m pip install psutil') + raise ImportError("This script requires the psutil module\nInstall with: python3 -m pip install psutil") import blinkt diff --git a/examples/morse_code.py b/examples/morse_code.py index 6f349d8..fbee738 100755 --- a/examples/morse_code.py +++ b/examples/morse_code.py @@ -37,13 +37,13 @@ def space(): # 0 is a space, 1 is a dot and 2 is a dash -MORSE = ' -... .. . -.. - -. . - . - -. -. - ' +MORSE = " -... .. . -.. - -. . - . - -. -. - " while True: for m in MORSE: - if m == ' ': + if m == " ": space() - elif m == '.': + elif m == ".": dot() - elif m == '-': + elif m == "-": dash() diff --git a/examples/mqtt.py b/examples/mqtt.py index 64860df..24f5c59 100755 --- a/examples/mqtt.py +++ b/examples/mqtt.py @@ -1,78 +1,74 @@ #!/usr/bin/env python -from sys import exit try: import paho.mqtt.client as mqtt except ImportError: - exit('This example requires the paho-mqtt module\nInstall with: sudo pip install paho-mqtt') + raise ImportError("This example requires the paho-mqtt module\nInstall with: python3 -m pip install paho-mqtt") import blinkt -MQTT_SERVER = 'iot.eclipse.org' +MQTT_SERVER = "iot.eclipse.org" MQTT_PORT = 1883 -MQTT_TOPIC = 'pimoroni/blinkt' +MQTT_TOPIC = "pimoroni/blinkt" # Set these to use authorisation MQTT_USER = None MQTT_PASS = None -print(""" +print( + f""" MQTT Blinkt! Control -This example uses public MQTT messages from {server} on port {port} to control Blinkt! +This example uses public MQTT messages from {MQTT_SERVER} on port {MQTT_PORT} to control Blinkt! -It will monitor the {topic} topic by default, and understands the following messages: +It will monitor the {MQTT_TOPIC} topic by default, and understands the following messages: rgb,,,, - Set a single pixel to an RGB colour. Example: rgb,1,255,0,255 clr - Clear Blinkt! You can use the online MQTT tester at http://www.hivemq.com/demos/websocket-client/ to send messages. -Use {server} as the host, and port 80 (Eclipse's websocket port). Set the topic to topic: {topic} -""".format( - server=MQTT_SERVER, - port=MQTT_PORT, - topic=MQTT_TOPIC -)) +Use {MQTT_SERVER} as the host, and port 80 (Eclipse's websocket port). Set the topic to topic: {MQTT_TOPIC} +""" +) def on_connect(client, userdata, flags, rc): - print('Connected with result code ' + str(rc)) + print("Connected with result code " + str(rc)) client.subscribe(MQTT_TOPIC) def on_message(client, userdata, msg): - data = msg.payload if isinstance(data, bytes): - data = data.decode('utf-8') - data = data.split(',') + data = data.decode("utf-8") + data = data.split(",") command = data.pop(0) - if command == 'clr' and len(data) == 0: + if command == "clr" and len(data) == 0: blinkt.clear() blinkt.show() return - if command == 'rgb' and len(data) == 4: + if command == "rgb" and len(data) == 4: try: pixel = data.pop(0) - if pixel == '*': + if pixel == "*": pixel = None else: pixel = int(pixel) if pixel > 7: - print('Pixel out of range: ' + str(pixel)) + print("Pixel out of range: " + str(pixel)) return - r, g, b = [int(x) & 0xff for x in data] + r, g, b = [int(x) & 0xFF for x in data] print(command, pixel, r, g, b) except ValueError: - print('Malformed command: ' + str(msg.payload)) + print("Malformed command: " + str(msg.payload)) return if pixel is None: @@ -92,7 +88,8 @@ def on_message(client, userdata, msg): client.on_message = on_message if MQTT_USER is not None and MQTT_PASS is not None: - print('Using username: {un} and password: {pw}'.format(un=MQTT_USER, pw='*' * len(MQTT_PASS))) + pw = "*" * len(MQTT_PASS) + print(f"Using username: {MQTT_USER} and password: {pw}") client.username_pw_set(username=MQTT_USER, password=MQTT_PASS) client.connect(MQTT_SERVER, MQTT_PORT, 60) diff --git a/examples/pulse.py b/examples/pulse.py index b260129..c6dd28a 100755 --- a/examples/pulse.py +++ b/examples/pulse.py @@ -2,12 +2,11 @@ import colorsys import time -from sys import exit try: import numpy as np except ImportError: - exit('This script requires the numpy module\nInstall with: sudo pip install numpy') + raise ImportError("This script requires the numpy module\nInstall with: python3 -m pip install numpy") import blinkt @@ -19,7 +18,7 @@ def make_gaussian(fwhm): y = x[:, np.newaxis] x0, y0 = 3.5, 3.5 fwhm = fwhm - gauss = np.exp(-4 * np.log(2) * ((x - x0) ** 2 + (y - y0) ** 2) / fwhm ** 2) + gauss = np.exp(-4 * np.log(2) * ((x - x0) ** 2 + (y - y0) ** 2) / fwhm**2) return gauss diff --git a/examples/resistor_clock.py b/examples/resistor_clock.py index 717d38d..1f4e983 100755 --- a/examples/resistor_clock.py +++ b/examples/resistor_clock.py @@ -5,14 +5,14 @@ import blinkt colours = [ - [0, 0, 0], # 0 black - [139, 69, 19], # 1 brown - [255, 0, 0], # 2 red - [255, 69, 0], # 3 orange - [255, 255, 0], # 4 yellow - [0, 255, 0], # 5 green - [0, 0, 255], # 6 blue - [128, 0, 128], # 7 violet + [0, 0, 0], # 0 black + [139, 69, 19], # 1 brown + [255, 0, 0], # 2 red + [255, 69, 0], # 3 orange + [255, 255, 0], # 4 yellow + [0, 255, 0], # 5 green + [0, 0, 255], # 6 blue + [128, 0, 128], # 7 violet [255, 255, 100], # 8 grey [255, 255, 255], # 9 white ] diff --git a/examples/rgb.py b/examples/rgb.py index 94f8ffc..476a69a 100755 --- a/examples/rgb.py +++ b/examples/rgb.py @@ -6,7 +6,7 @@ def usage(): - print('Usage: {} '.format(sys.argv[0])) + print(f"Usage: {sys.argv[0]} ") sys.exit(1) @@ -23,7 +23,7 @@ def usage(): if max(r, g, b) > 255: usage() -print('Setting Blinkt to {r},{g},{b}'.format(r=r, g=g, b=b)) +print(f"Setting Blinkt to {r},{g},{b}") blinkt.set_clear_on_exit(False) diff --git a/examples/setall.py b/examples/setall.py index 499af66..e12107a 100755 --- a/examples/setall.py +++ b/examples/setall.py @@ -6,7 +6,7 @@ import blinkt if len(argv) < 4 or len(argv) > 5: - sys.stderr.write("Syntax: {0} [brightness]\n".format(argv[0])) + sys.stderr.write(f"Syntax: {argv[0]} [brightness]\n") exit(1) red = int(argv[1]) diff --git a/examples/twitter_monitor.py b/examples/twitter_monitor.py deleted file mode 100755 index 23e5b72..0000000 --- a/examples/twitter_monitor.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python - -import time -from sys import exit - -try: - from tweepy import OAuthHandler, Stream - from tweepy.streaming import StreamListener -except ImportError: - exit('This script requires the tweepy module\nInstall with: sudo pip install tweepy') - -import blinkt - -ckey = '' # Consumer key -csecret = '' # Consumer secret -atoken = '' # Access token -asecret = '' # Access secret - - -class listener(StreamListener): - def on_data(self, data): - blink_blinkt() - return True - - def on_error(self, status): - print(status) - - -def blink_blinkt(): - for i in range(3): - for j in range(blinkt.NUM_PIXELS): - blinkt.set_pixel(j, 255, 0, 0) - - blinkt.show() - time.sleep(0.1) - - for j in range(blinkt.NUM_PIXELS): - blinkt.set_pixel(j, 0, 0, 0) - - blinkt.show() - time.sleep(0.2) - - -auth = OAuthHandler(ckey, csecret) -auth.set_access_token(atoken, asecret) -twitterstream = Stream(auth, listener()) -twitterstream.filter(track=['#INSERTHASHTAGHERE']) diff --git a/projects/mqtt/mqtt.py b/projects/mqtt/mqtt.py index 67b3f85..0560b17 100755 --- a/projects/mqtt/mqtt.py +++ b/projects/mqtt/mqtt.py @@ -7,7 +7,7 @@ try: import paho.mqtt.client as mqtt except ImportError: - raise ImportError("This example requires the paho-mqtt module\nInstall with: sudo pip install paho-mqtt") + raise ImportError("This example requires the paho-mqtt module\nInstall with: python3 -m pip install paho-mqtt") import blinkt @@ -19,12 +19,12 @@ MQTT_USER = None MQTT_PASS = None -description = """\ +description = f"""\ MQTT Blinkt! Control -This example uses MQTT messages from {server} on port {port} to control Blinkt! +This example uses MQTT messages from {MQTT_SERVER} on port {MQTT_PORT} to control Blinkt! -It will monitor the {topic} topic by default, and understands the following messages: +It will monitor the {MQTT_TOPIC} topic by default, and understands the following messages: rgb,,,, - Set a single pixel to an RGB colour. Example: rgb,1,255,0,255 clr - Clear Blinkt! @@ -32,47 +32,35 @@ You can use the online MQTT tester at http://www.hivemq.com/demos/websocket-client/ to send messages. -Use {server} as the host, and port 80 (Eclipse's websocket port). Set the topic to topic: {topic} -""".format( - server=MQTT_SERVER, - port=MQTT_PORT, - topic=MQTT_TOPIC -) +Use {MQTT_SERVER} as the host, and port 80 (Eclipse's websocket port). Set the topic to topic: {MQTT_TOPIC} +""" + parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawDescriptionHelpFormatter) -parser.add_argument('-H', '--host', default=MQTT_SERVER, - help='MQTT broker to connect to') -parser.add_argument('-P', '--port', default=MQTT_PORT, type=int, - help='port on MQTT broker to connect to') -parser.add_argument('-T', '--topic', action='append', - help='MQTT topic to subscribe to; can be repeated for multiple topics') -parser.add_argument('-u', '--user', - help='MQTT broker user name') -parser.add_argument('-p', '--pass', dest='pw', - help='MQTT broker password') -parser.add_argument('-q', '--quiet', default=False, action='store_true', - help='Minimal output (eg for running as a daemon)') -parser.add_argument('-g', '--green-hack', default=False, action='store_true', - help='Apply hack to green channel to improve colour saturation') -parser.add_argument('--timeout', default='0', - help='Pixel timeout(s). Pixel will blank if last update older than X seconds. May be a single number or comma-separated list. Use 0 for no timeout') -parser.add_argument('-D', '--daemon', metavar='PIDFILE', - help='Run as a daemon (implies -q)') +parser.add_argument("-H", "--host", default=MQTT_SERVER, help="MQTT broker to connect to") +parser.add_argument("-P", "--port", default=MQTT_PORT, type=int, help="port on MQTT broker to connect to") +parser.add_argument("-T", "--topic", action="append", help="MQTT topic to subscribe to; can be repeated for multiple topics") +parser.add_argument("-u", "--user", help="MQTT broker user name") +parser.add_argument("-p", "--pass", dest="pw", help="MQTT broker password") +parser.add_argument("-q", "--quiet", default=False, action="store_true", help="Minimal output (eg for running as a daemon)") +parser.add_argument("-g", "--green-hack", default=False, action="store_true", help="Apply hack to green channel to improve colour saturation") +parser.add_argument("--timeout", default="0", help="Pixel timeout(s). Pixel will blank if last update older than X seconds. May be a single number or comma-separated list. Use 0 for no timeout") +parser.add_argument("-D", "--daemon", metavar="PIDFILE", help="Run as a daemon (implies -q)") args = parser.parse_args() # Get timeout list into expected form -args.timeout = args.timeout.split(',') +args.timeout = args.timeout.split(",") if len(args.timeout) == 1: args.timeout = args.timeout * blinkt.NUM_PIXELS elif len(args.timeout) != blinkt.NUM_PIXELS: - print("--timeout list must be {} elements long".format(blinkt.NUM_PIXELS)) + print(f"--timeout list must be {blinkt.NUM_PIXELS} elements long") exit(1) try: args.timeout = [int(x) for x in args.timeout] except ValueError as e: - print("Bad timeout value: {}".format(e)) + print(f"Bad timeout value: {e}") exit(1) args.timeout = [x and x or 0 for x in args.timeout] @@ -80,14 +68,17 @@ if args.daemon: import signal + try: import daemon except ImportError: - raise ImportError("--daemon requires the daemon module. Install with: sudo pip install python-daemon") + print("--daemon requires the daemon module. Install with: python3 -m pip install python-daemon") + exit(1) try: import lockfile.pidlockfile except ImportError: - raise ImportError("--daemon requires the lockfile module. Install with: sudo pip install lockfile") + print("--daemon requires the lockfile module. Install with: python3 -m pip install lockfile") + exit(1) if not args.topic: args.topic = [MQTT_TOPIC] @@ -117,7 +108,7 @@ def cmd_brightness(self, bri): try: bri = float(bri) except ValueError: - print("Malformed command brightness, expected float, got: {}".format(str(bri))) + print(f"Malformed command brightness, expected float, got: {bri}") return blinkt.set_brightness(bri) blinkt.show() @@ -129,10 +120,10 @@ def cmd_rgb(self, pixel, data): else: pixel = int(pixel) if pixel > 7: - print("Pixel out of range: {}".format(str(pixel))) + print(f"Pixel out of range: {pixel}") return - r, g, b = [int(x) & 0xff for x in data] + r, g, b = [int(x) & 0xFF for x in data] if self.args.green_hack: # Green is about twice the luminosity for a given value # than red or blue, so apply a hackish linear compensation @@ -147,10 +138,10 @@ def cmd_rgb(self, pixel, data): b = b + 1 if not self.args.quiet: - print('rgb', pixel, r, g, b) + print("rgb", pixel, r, g, b) except ValueError: - print("Malformed RGB command: {} {}".format(str(pixel), str(data))) + print(f"Malformed RGB command: {pixel} {data}") return if pixel is None: @@ -165,20 +156,15 @@ def cmd_rgb(self, pixel, data): def on_connect(self, client, userdata, flags, rc): if not self.args.quiet: - print("Connected to {s}:{p} listening for topics {t} with result code {r}.\nSee {c} --help for options.".format( - s=self.args.host, - p=self.args.port, - t=', '.join(self.args.topic), - r=rc, - c=parser.prog - )) + print(f"Connected to {self.args.host}:{self.args.port} with result code {rc}.") + print(f"listening for topics {', '.join(self.args.topic)}.") + print(f"See {parser.prog} --help for options.") for topic in self.args.topic: client.subscribe(topic) def on_message(self, client, userdata, msg): - - data = msg.payload.decode('utf-8').strip().split(',') + data = msg.payload.decode("utf-8").strip().split(",") command = data.pop(0) print(command, data) @@ -218,9 +204,7 @@ def sigterm(signum, frame): daemon.daemon.get_maximum_file_descriptors = lambda: 32 args.quiet = True pidlf = lockfile.pidlockfile.PIDLockFile(args.daemon) - with daemon.DaemonContext( - pidfile=pidlf, - signal_map={signal.SIGTERM: sigterm}): + with daemon.DaemonContext(pidfile=pidlf, signal_map={signal.SIGTERM: sigterm}): client = PixelClient(args) client.loop_forever() else: diff --git a/pyproject.toml b/pyproject.toml index 7c38d53..25af28f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,6 +95,9 @@ skip = """ [tool.isort] line_length = 200 +[tool.black] +line-length = 200 + [tool.check-manifest] ignore = [ '.stickler.yml', diff --git a/requirements-examples.txt b/requirements-examples.txt new file mode 100644 index 0000000..499cb1d --- /dev/null +++ b/requirements-examples.txt @@ -0,0 +1,8 @@ +requests +paho-mqtt +psutil +numpy +envirophat +drumhat +pygame +numpy \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index afffbb0..db460f7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,6 +4,12 @@ import pytest +@pytest.fixture(scope='function', autouse=True) +def cleanup(): + yield + del sys.modules['blinkt'] + + @pytest.fixture(scope='function', autouse=False) def gpiod(): sys.modules['gpiod'] = mock.Mock() @@ -11,3 +17,15 @@ def gpiod(): yield sys.modules['gpiod'] del sys.modules['gpiod.line'] del sys.modules['gpiod'] + + +@pytest.fixture(scope='function', autouse=False) +def gpiodevice(): + sys.modules['gpiodevice'] = mock.Mock() + yield sys.modules['gpiodevice'] + del sys.modules['gpiodevice'] + + +@pytest.fixture(scope='function', autouse=False) +def gpiod_request(): + yield mock.MagicMock() diff --git a/tests/test_setup.py b/tests/test_setup.py index 7853ccb..0ffd7f5 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -1,4 +1,5 @@ """Test Blinkt! basic initialisation.""" +import mock import pytest @@ -7,3 +8,69 @@ def test_setup(gpiod): import blinkt with pytest.raises((RuntimeError, SystemExit)): blinkt.show() + + +def test_set_pins(gpiod): + import blinkt + + with pytest.raises((RuntimeError, SystemExit)): + blinkt.set_pins("PIN1", "PIN2") + + +def test_set_pixel(gpiod): + import blinkt + blinkt.set_brightness(1.0) + + blinkt.set_pixel(0, 255, 0, 0) + blinkt.set_pixel(1, 0, 255, 0) + blinkt.set_pixel(2, 0, 0, 255) + + assert blinkt.get_pixel(0)[0:3] == (255, 0, 0) + assert blinkt.get_pixel(1)[0:3] == (0, 255, 0) + assert blinkt.get_pixel(2)[0:3] == (0, 0, 255) + + +def test_set_all_and_clear(gpiod): + import blinkt + blinkt.set_brightness(1.0) + + blinkt.set_all(1, 2, 3, 0) + + for x in range(blinkt.NUM_PIXELS): + assert blinkt.get_pixel(0)[0:3] == (1, 2, 3) + + blinkt.clear() + + for x in range(blinkt.NUM_PIXELS): + assert blinkt.get_pixel(0)[0:3] == (0, 0, 0) + + +def test_brightness(gpiod): + import blinkt + blinkt.set_brightness(1.0) + + assert blinkt.pixels[0][3] == 0b11111 + + with pytest.raises(ValueError): + blinkt.set_brightness(1.5) + + with pytest.raises(ValueError): + blinkt.set_brightness(-1) + + +def test_show(gpiod, gpiod_request): + import blinkt + + blinkt.clk_lines = gpiod_request + blinkt.dat_lines = gpiod_request + + blinkt.dat_line = 0 + blinkt.clk_line = 1 + + blinkt.show() + + gpiod_request.set_value.assert_has_calls(( + mock.call(0, blinkt.Value.INACTIVE), # Dat line low + mock.call(1, blinkt.Value.ACTIVE), # Clock pin high + mock.call(1, blinkt.Value.INACTIVE) # Clock pin low + )) \ No newline at end of file From d957c4a9642e550138da618ddd816716fbe78e01 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 13 Feb 2024 14:04:37 +0000 Subject: [PATCH 25/27] Sync to latest boilerplate. --- .github/workflows/build.yml | 6 +- .github/workflows/qa.yml | 9 ++- .github/workflows/test.yml | 2 +- Makefile | 5 +- check.sh | 21 +++---- examples/blinkt_thermo.py | 2 +- install.sh | 121 ++++++++++++++++++------------------ uninstall.sh | 14 ++--- 8 files changed, 91 insertions(+), 89 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 87200ef..07620e3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,10 +19,10 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} @@ -35,7 +35,7 @@ jobs: make build - name: Upload Packages - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.RELEASE_FILE }} path: dist/ diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 4f85883..ac672a5 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -10,16 +10,15 @@ jobs: test: name: linting & spelling runs-on: ubuntu-latest - env: TERM: xterm-256color steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Python '3,11' - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: '3.11' @@ -34,3 +33,7 @@ jobs: - 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 index 016a678..6f8cff7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} diff --git a/Makefile b/Makefile index 9e0c15c..34f4a7d 100644 --- a/Makefile +++ b/Makefile @@ -30,11 +30,14 @@ uninstall: dev-deps: python3 -m pip install -r requirements-dev.txt - sudo apt install dos2unix + sudo apt install dos2unix shellcheck check: @bash check.sh +shellcheck: + shellcheck *.sh + qa: tox -e qa diff --git a/check.sh b/check.sh index cbb1565..38dfc3a 100755 --- a/check.sh +++ b/check.sh @@ -3,9 +3,10 @@ # This script handles some basic QA checks on the source NOPOST=$1 -LIBRARY_NAME=`hatch project metadata name` -LIBRARY_VERSION=`hatch version | awk -F "." '{print $1"."$2"."$3}'` -POST_VERSION=`hatch version | awk -F "." '{print substr($4,0,length($4))}'` +LIBRARY_NAME=$(hatch project metadata name) +LIBRARY_VERSION=$(hatch version | awk -F "." '{print $1"."$2"."$3}') +POST_VERSION=$(hatch version | awk -F "." '{print substr($4,0,length($4))}') +TERM=${TERM:="xterm-256color"} success() { echo -e "$(tput setaf 2)$1$(tput sgr0)" @@ -28,7 +29,7 @@ while [[ $# -gt 0 ]]; do ;; *) if [[ $1 == -* ]]; then - printf "Unrecognised option: $1\n"; + printf "Unrecognised option: %s\n" "$1"; exit 1 fi POSITIONAL_ARGS+=("$1") @@ -39,8 +40,7 @@ done inform "Checking $LIBRARY_NAME $LIBRARY_VERSION\n" inform "Checking for trailing whitespace..." -grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO -if [[ $? -eq 0 ]]; then +if grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO; then warning "Trailing whitespace found!" exit 1 else @@ -49,8 +49,7 @@ fi printf "\n" inform "Checking for DOS line-endings..." -grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile -if [[ $? -eq 0 ]]; then +if grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile; then warning "DOS line-endings found!" exit 1 else @@ -59,8 +58,7 @@ fi printf "\n" inform "Checking CHANGELOG.md..." -cat CHANGELOG.md | grep ^${LIBRARY_VERSION} > /dev/null 2>&1 -if [[ $? -eq 1 ]]; then +if ! grep "^${LIBRARY_VERSION}" CHANGELOG.md > /dev/null 2>&1; then warning "Changes missing for version ${LIBRARY_VERSION}! Please update CHANGELOG.md." exit 1 else @@ -69,8 +67,7 @@ fi printf "\n" inform "Checking for git tag ${LIBRARY_VERSION}..." -git tag -l | grep -E "${LIBRARY_VERSION}$" -if [[ $? -eq 1 ]]; then +if ! git tag -l | grep -E "${LIBRARY_VERSION}$"; then warning "Missing git tag for version ${LIBRARY_VERSION}" fi printf "\n" diff --git a/examples/blinkt_thermo.py b/examples/blinkt_thermo.py index 71e1a16..800b9b4 100755 --- a/examples/blinkt_thermo.py +++ b/examples/blinkt_thermo.py @@ -28,7 +28,7 @@ def update_weather(): try: r = requests.get(url=url, params=payload) temp = r.json().get("main").get("temp") - print("Temperture = " + str(temp) + " C") + print("Temperature = " + str(temp) + " C") except requests.exceptions.ConnectionError: print("Connection Error") diff --git a/install.sh b/install.sh index d42c48d..bb671f2 100755 --- a/install.sh +++ b/install.sh @@ -1,14 +1,13 @@ #!/bin/bash -LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'` +LIBRARY_NAME=$(grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}') CONFIG_FILE=config.txt CONFIG_DIR="/boot/firmware" -DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` +DATESTAMP=$(date "+%Y-%m-%d-%H-%M-%S") CONFIG_BACKUP=false APT_HAS_UPDATED=false RESOURCES_TOP_DIR="$HOME/Pimoroni" VENV_BASH_SNIPPET="$RESOURCES_TOP_DIR/auto_venv.sh" VENV_DIR="$HOME/.virtualenvs/pimoroni" -WD=`pwd` USAGE="./install.sh (--unstable)" POSITIONAL_ARGS=() FORCE=false @@ -18,7 +17,7 @@ CMD_ERRORS=false user_check() { - if [ $(id -u) -eq 0 ]; then + if [ "$(id -u)" -eq 0 ]; then fatal "Script should not be run as root. Try './install.sh'\n" fi } @@ -36,15 +35,6 @@ confirm() { fi } -prompt() { - read -r -p "$1 [y/N] " response < /dev/tty - if [[ $response =~ ^(yes|y|Y)$ ]]; then - true - else - false - fi -} - success() { echo -e "$(tput setaf 2)$1$(tput sgr0)" } @@ -79,10 +69,10 @@ find_config() { venv_bash_snippet() { inform "Checking for $VENV_BASH_SNIPPET\n" - if [ ! -f $VENV_BASH_SNIPPET ]; then + if [ ! -f "$VENV_BASH_SNIPPET" ]; then inform "Creating $VENV_BASH_SNIPPET\n" - mkdir -p $RESOURCES_TOP_DIR - cat << EOF > $VENV_BASH_SNIPPET + mkdir -p "$RESOURCES_TOP_DIR" + cat << EOF > "$VENV_BASH_SNIPPET" # Add "source $VENV_BASH_SNIPPET" to your ~/.bashrc to activate # the Pimoroni virtual environment automagically! VENV_DIR="$VENV_DIR" @@ -98,21 +88,23 @@ EOF } venv_check() { - PYTHON_BIN=`which $PYTHON` + PYTHON_BIN=$(which "$PYTHON") if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then printf "This script should be run in a virtual Python environment.\n" if confirm "Would you like us to create and/or use a default one?"; then printf "\n" - if [ ! -f $VENV_DIR/bin/activate ]; then + if [ ! -f "$VENV_DIR/bin/activate" ]; then inform "Creating a new virtual Python environment in $VENV_DIR, please wait...\n" - mkdir -p $VENV_DIR - /usr/bin/python3 -m venv $VENV_DIR --system-site-packages + mkdir -p "$VENV_DIR" + /usr/bin/python3 -m venv "$VENV_DIR" --system-site-packages venv_bash_snippet - source $VENV_DIR/bin/activate + # shellcheck disable=SC1091 + source "$VENV_DIR/bin/activate" else inform "Activating existing virtual Python environment in $VENV_DIR\n" - printf "source $VENV_DIR/bin/activate\n" - source $VENV_DIR/bin/activate + printf "source \"%s/bin/activate\"\n" "$VENV_DIR" + # shellcheck disable=SC1091 + source "$VENV_DIR/bin/activate" fi else printf "\n" @@ -125,7 +117,7 @@ venv_check() { check_for_error() { if [ $? -ne 0 ]; then CMD_ERRORS=true - warning "^^^ 😬" + warning "^^^ 😬 previous command did not exit cleanly!" fi } @@ -134,29 +126,29 @@ function do_config_backup { CONFIG_BACKUP=true FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt" inform "Backing up $CONFIG_DIR/$CONFIG_FILE to $CONFIG_DIR/$FILENAME\n" - sudo cp $CONFIG_DIR/$CONFIG_FILE $CONFIG_DIR/$FILENAME - mkdir -p $RESOURCES_TOP_DIR/config-backups/ - cp $CONFIG_DIR/$CONFIG_FILE $RESOURCES_TOP_DIR/config-backups/$FILENAME + sudo cp "$CONFIG_DIR/$CONFIG_FILE" "$CONFIG_DIR/$FILENAME" + mkdir -p "$RESOURCES_TOP_DIR/config-backups/" + cp $CONFIG_DIR/$CONFIG_FILE "$RESOURCES_TOP_DIR/config-backups/$FILENAME" if [ -f "$UNINSTALLER" ]; then - echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG_DIR/$CONFIG_FILE" >> $UNINSTALLER + echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG_DIR/$CONFIG_FILE" >> "$UNINSTALLER" fi fi } function apt_pkg_install { - PACKAGES=() + PACKAGES_NEEDED=() PACKAGES_IN=("$@") # Check the list of packages and only run update/install if we need to for ((i = 0; i < ${#PACKAGES_IN[@]}; i++)); do PACKAGE="${PACKAGES_IN[$i]}" if [ "$PACKAGE" == "" ]; then continue; fi - printf "Checking for $PACKAGE\n" - dpkg -L $PACKAGE > /dev/null 2>&1 + printf "Checking for %s\n" "$PACKAGE" + dpkg -L "$PACKAGE" > /dev/null 2>&1 if [ "$?" == "1" ]; then - PACKAGES+=("$PACKAGE") + PACKAGES_NEEDED+=("$PACKAGE") fi done - PACKAGES="${PACKAGES[@]}" + PACKAGES="${PACKAGES_NEEDED[*]}" if ! [ "$PACKAGES" == "" ]; then printf "\n" inform "Installing missing packages: $PACKAGES" @@ -164,10 +156,10 @@ function apt_pkg_install { sudo apt update APT_HAS_UPDATED=true fi - sudo apt install -y $PACKAGES + sudo apt install -y "$PACKAGES" check_for_error if [ -f "$UNINSTALLER" ]; then - echo "apt uninstall -y $PACKAGES" >> $UNINSTALLER + echo "apt uninstall -y $PACKAGES" >> "$UNINSTALLER" fi fi } @@ -196,8 +188,8 @@ while [[ $# -gt 0 ]]; do ;; *) if [[ $1 == -* ]]; then - printf "Unrecognised option: $1\n"; - printf "Usage: $USAGE\n"; + printf "Unrecognised option: %s\n" "$1"; + printf "Usage: %s\n" "$USAGE"; exit 1 fi POSITIONAL_ARGS+=("$1") @@ -205,16 +197,16 @@ while [[ $# -gt 0 ]]; do esac done -printf "Installing $LIBRARY_NAME...\n\n" +printf "Installing %s...\n\n" "$LIBRARY_NAME" user_check venv_check -if [ ! -f `which $PYTHON` ]; then - fatal "Python path $PYTHON not found!\n" +if [ ! -f "$(which "$PYTHON")" ]; then + fatal "Python path %s not found!\n" "$PYTHON" fi -PYTHON_VER=`$PYTHON --version` +PYTHON_VER=$($PYTHON --version) inform "Checking Dependencies. Please wait..." @@ -222,7 +214,8 @@ inform "Checking Dependencies. Please wait..." pip_pkg_install toml -CONFIG_VARS=`$PYTHON - < $UNINSTALLER +cat << EOF > "$UNINSTALLER" printf "It's recommended you run these steps manually.\n" printf "If you want to run the full script, open it in\n" printf "an editor and remove 'exit 1' from below.\n" @@ -284,27 +279,32 @@ if $UNSTABLE; then pip_pkg_install . else inform "Installing stable library from pypi.\n" - pip_pkg_install $LIBRARY_NAME + pip_pkg_install "$LIBRARY_NAME" fi +# shellcheck disable=SC2181 # One of two commands run, depending on --unstable flag if [ $? -eq 0 ]; then success "Done!\n" - echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> $UNINSTALLER + echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> "$UNINSTALLER" fi -cd $WD - find_config +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 - eval $CMD + if [[ ! "$CMD" == printf* ]]; then + printf "Running: \"%s\"\n" "$CMD" + fi + eval "$CMD" check_for_error done @@ -319,7 +319,7 @@ for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do inform "Adding $CONFIG_LINE to $CONFIG_DIR/$CONFIG_FILE" sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG_DIR/$CONFIG_FILE if ! grep -q "^$CONFIG_LINE" $CONFIG_DIR/$CONFIG_FILE; then - printf "$CONFIG_LINE\n" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE + printf "%s \n" "$CONFIG_LINE" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE fi fi done @@ -331,8 +331,8 @@ printf "\n" if [ -d "examples" ]; then if confirm "Would you like to copy examples to $RESOURCES_DIR?"; then inform "Copying examples to $RESOURCES_DIR" - cp -r examples/ $RESOURCES_DIR - echo "rm -r $RESOURCES_DIR" >> $UNINSTALLER + cp -r examples/ "$RESOURCES_DIR" + echo "rm -r $RESOURCES_DIR" >> "$UNINSTALLER" success "Done!" fi fi @@ -345,8 +345,7 @@ if confirm "Would you like to generate documentation?"; then inform "Installing pdoc. Please wait..." pip_pkg_install pdoc inform "Generating documentation.\n" - $PYTHON -m pdoc $LIBRARY_NAME -o $RESOURCES_DIR/docs > /dev/null - if [ $? -eq 0 ]; then + if $PYTHON -m pdoc "$LIBRARY_NAME" -o "$RESOURCES_DIR/docs" > /dev/null; then inform "Documentation saved to $RESOURCES_DIR/docs" success "Done!" else @@ -360,16 +359,16 @@ if [ "$CMD_ERRORS" = true ]; then warning "One or more setup commands appear to have failed." printf "This might prevent things from working properly.\n" printf "Make sure your OS is up to date and try re-running this installer.\n" - printf "If things still don't work, report this or find help at $GITHUB_URL.\n\n" + printf "If things still don't work, report this or find help at %s.\n\n" "$GITHUB_URL" else success "\nAll done!" fi printf "If this is your first time installing you should reboot for hardware changes to take effect.\n" -printf "Find uninstall steps in $UNINSTALLER\n\n" +printf "Find uninstall steps in %s\n\n" "$UNINSTALLER" if [ "$CMD_ERRORS" = true ]; then exit 1 else exit 0 -fi \ No newline at end of file +fi diff --git a/uninstall.sh b/uninstall.sh index f213fc5..3314b7f 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,13 +1,13 @@ #!/bin/bash FORCE=false -LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'` +LIBRARY_NAME=$(grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}') RESOURCES_DIR=$HOME/Pimoroni/$LIBRARY_NAME PYTHON="python" venv_check() { - PYTHON_BIN=`which $PYTHON` + PYTHON_BIN=$(which $PYTHON) if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then printf "This script should be run in a virtual Python environment.\n" exit 1 @@ -15,7 +15,7 @@ venv_check() { } user_check() { - if [ $(id -u) -eq 0 ]; then + if [ "$(id -u)" -eq 0 ]; then printf "Script should not be run as root. Try './uninstall.sh'\n" exit 1 fi @@ -55,17 +55,17 @@ warning() { echo -e "$(tput setaf 1)$1$(tput sgr0)" } -printf "$LIBRARY_NAME Python Library: Uninstaller\n\n" +printf "%s Python Library: Uninstaller\n\n" "$LIBRARY_NAME" user_check venv_check printf "Uninstalling for Python 3...\n" -$PYTHON -m pip uninstall $LIBRARY_NAME +$PYTHON -m pip uninstall "$LIBRARY_NAME" -if [ -d $RESOURCES_DIR ]; then +if [ -d "$RESOURCES_DIR" ]; then if confirm "Would you like to delete $RESOURCES_DIR?"; then - rm -r $RESOURCES_DIR + rm -r "$RESOURCES_DIR" fi fi From 8452998c523c7347c76561e552dbc0409e3b3459 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 3 Jun 2024 14:43:48 +0100 Subject: [PATCH 26/27] Simplify GPIO pin setup. --- blinkt/__init__.py | 32 +++----------------------------- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/blinkt/__init__.py b/blinkt/__init__.py index f9918dc..8dc737d 100644 --- a/blinkt/__init__.py +++ b/blinkt/__init__.py @@ -9,11 +9,6 @@ __version__ = '0.1.2' OUTL = gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE) -PLATFORMS = { - "Radxa ROCK 5B": {"dat": ("PIN_16", OUTL), "clk": ("PIN_18", OUTL)}, - "Raspberry Pi 5": {"dat": ("PIN16", OUTL), "clk": ("PIN18", OUTL)}, - "Raspberry Pi 4": {"dat": ("GPIO23", OUTL), "clk": ("GPIO24", OUTL)} -} NUM_PIXELS = 8 BRIGHTNESS = 7 @@ -88,33 +83,12 @@ def _sof(): def set_pins(pin_dat, pin_clk): global clk_lines, dat_lines, dat_line, clk_line - try: - chip = gpiodevice.find_chip_by_pins((pin_dat, pin_clk)) - dat_line = chip.line_offset_from_id(pin_dat) - clk_line = chip.line_offset_from_id(pin_clk) - dat_lines = clk_lines = chip.request_lines(consumer="blinkt", config={ - dat_line: OUTL, - clk_line: OUTL - }) - return - except SystemExit: - pass - - chip_dat = gpiodevice.find_chip_by_pins(pin_dat) - dat_line = chip_dat.line_offset_from_id(pin_dat) - dat_lines = chip_dat.request_lines(consumer="blinkt-dat", config={dat_line: OUTL}) - - chip_clk = gpiodevice.find_chip_by_pins(pin_clk) - clk_line = chip_clk.line_offset_from_id(pin_clk) - clk_lines = chip_clk.request_lines(consumer="blinkt-clk", config={clk_line: OUTL}) + dat_lines, dat_line = gpiodevice.get_pin(pin_dat, "blinkt-dat", OUTL) + clk_lines, clk_line = gpiodevice.get_pin(pin_clk, "blinkt-clk", OUTL) def default_pins(): - global clk_lines, dat_lines, dat_line, clk_line - - dat, clk = gpiodevice.get_pins_for_platform(PLATFORMS) - dat_lines, dat_line = dat - clk_lines, clk_line = clk + set_pins(23, 24) def show(): diff --git a/pyproject.toml b/pyproject.toml index 25af28f..adf6d62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ classifiers = [ ] dependencies = [ "gpiod", - "gpiodevice>=0.0.2" + "gpiodevice>=0.0.4" ] [project.urls] From a2dc72934ad81d7a1beac78fad440c7a129e9ae0 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 3 Jun 2024 15:18:06 +0100 Subject: [PATCH 27/27] CI: Fix tests. --- tests/conftest.py | 6 +++++- tests/test_setup.py | 21 +++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index db460f7..353ab9d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,7 +21,11 @@ def gpiod(): @pytest.fixture(scope='function', autouse=False) def gpiodevice(): - sys.modules['gpiodevice'] = mock.Mock() + gpiodevice = mock.Mock() + gpiodevice.get_pins_for_platform.return_value = [(mock.Mock(), 0), (mock.Mock(), 0)] + gpiodevice.get_pin.return_value = (mock.Mock(), 0) + + sys.modules['gpiodevice'] = gpiodevice yield sys.modules['gpiodevice'] del sys.modules['gpiodevice'] diff --git a/tests/test_setup.py b/tests/test_setup.py index 0ffd7f5..40ceeb1 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -3,21 +3,18 @@ import pytest -def test_setup(gpiod): +def test_setup(gpiod, gpiodevice): """Test init succeeds and GPIO pins are set up.""" import blinkt - with pytest.raises((RuntimeError, SystemExit)): - blinkt.show() + blinkt.show() -def test_set_pins(gpiod): +def test_set_pins(gpiod, gpiodevice): import blinkt - - with pytest.raises((RuntimeError, SystemExit)): - blinkt.set_pins("PIN1", "PIN2") + blinkt.set_pins("PIN1", "PIN2") -def test_set_pixel(gpiod): +def test_set_pixel(gpiod, gpiodevice): import blinkt blinkt.set_brightness(1.0) @@ -30,7 +27,7 @@ def test_set_pixel(gpiod): assert blinkt.get_pixel(2)[0:3] == (0, 0, 255) -def test_set_all_and_clear(gpiod): +def test_set_all_and_clear(gpiod, gpiodevice): import blinkt blinkt.set_brightness(1.0) @@ -45,7 +42,7 @@ def test_set_all_and_clear(gpiod): assert blinkt.get_pixel(0)[0:3] == (0, 0, 0) -def test_brightness(gpiod): +def test_brightness(gpiod, gpiodevice): import blinkt blinkt.set_brightness(1.0) @@ -58,7 +55,7 @@ def test_brightness(gpiod): blinkt.set_brightness(-1) -def test_show(gpiod, gpiod_request): +def test_show(gpiod, gpiodevice, gpiod_request): import blinkt blinkt.clk_lines = gpiod_request @@ -73,4 +70,4 @@ def test_show(gpiod, gpiod_request): mock.call(0, blinkt.Value.INACTIVE), # Dat line low mock.call(1, blinkt.Value.ACTIVE), # Clock pin high mock.call(1, blinkt.Value.INACTIVE) # Clock pin low - )) \ No newline at end of file + ))