Update packaging

This commit is contained in:
Phil Howard
2021-04-12 16:21:36 +01:00
parent 9731c4257d
commit f4c3190ba6
14 changed files with 530 additions and 203 deletions

View File

@@ -19,7 +19,7 @@ common troubleshooting steps below before creating the issue:
library the code depends on is not installed. Check the tutorial/guide or library the code depends on is not installed. Check the tutorial/guide or
README to ensure you have installed the necessary libraries. Usually the README to ensure you have installed the necessary libraries. Usually the
missing library can be installed with the `pip` tool, but check the tutorial/guide missing library can be installed with the `pip` tool, but check the tutorial/guide
for the exact command. for the exact command.
- **Be sure you are supplying adequate power to the board.** Check the specs of - **Be sure you are supplying adequate power to the board.** Check the specs of
your board and power in an external power supply. In many cases just your board and power in an external power supply. In many cases just

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python: [2.7, 3.4, 3.5, 3.7, 3.8] python: [2.7, 3.6, 3.8]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -32,6 +32,6 @@ jobs:
working-directory: library working-directory: library
run: | run: |
python -m pip install coveralls python -m pip install coveralls
coveralls coveralls --service=github
if: ${{ matrix.python == '3.8' }} if: ${{ matrix.python == '3.8' }}

View File

@@ -1,13 +1,21 @@
LIBRARY_VERSION=$(shell grep version library/setup.cfg | awk -F" = " '{print $$2}')
LIBRARY_NAME=$(shell grep name library/setup.cfg | awk -F" = " '{print $$2}')
.PHONY: usage install uninstall .PHONY: usage install uninstall
usage: usage:
@echo "Library: ${LIBRARY_NAME}"
@echo "Version: ${LIBRARY_VERSION}\n"
@echo "Usage: make <target>, where target is one of:\n" @echo "Usage: make <target>, where target is one of:\n"
@echo "install: install the library locally from source" @echo "install: install the library locally from source"
@echo "uninstall: uninstall the local library" @echo "uninstall: uninstall the local library"
@echo "python-readme: generate library/README.rst from README.md" @echo "check: peform basic integrity checks on the codebase"
@echo "python-readme: generate library/README.md from README.md + library/CHANGELOG.txt"
@echo "python-wheels: build python .whl files for distribution" @echo "python-wheels: build python .whl files for distribution"
@echo "python-sdist: build python source distribution" @echo "python-sdist: build python source distribution"
@echo "python-clean: clean python build and dist directories" @echo "python-clean: clean python build and dist directories"
@echo "python-dist: build all python distribution files" @echo "python-dist: build all python distribution files"
@echo "python-testdeploy: build all and deploy to test PyPi"
@echo "tag: tag the repository with the current version"
install: install:
./install.sh ./install.sh
@@ -15,12 +23,27 @@ install:
uninstall: uninstall:
./uninstall.sh ./uninstall.sh
python-readme: library/README.rst check:
@echo "Checking for trailing whitespace"
@! grep -IUrn --color "[[:blank:]]$$" --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO
@echo "Checking for DOS line-endings"
@! grep -IlUrn --color "
" --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile
@echo "Checking library/CHANGELOG.txt"
@cat library/CHANGELOG.txt | grep ^${LIBRARY_VERSION}
@echo "Checking library/${LIBRARY_NAME}/__init__.py"
@cat library/${LIBRARY_NAME}/__init__.py | grep "^__version__ = '${LIBRARY_VERSION}'"
tag:
git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}"
python-readme: library/README.md python-readme: library/README.md
python-license: library/LICENSE.txt python-license: library/LICENSE.txt
library/README.rst: README.md
pandoc --from=markdown --to=rst -o library/README.rst README.md library/README.md: README.md library/CHANGELOG.txt
cp README.md library/README.md
printf "\n# Changelog\n" >> library/README.md
cat library/CHANGELOG.txt >> library/README.md cat library/CHANGELOG.txt >> library/README.md
library/LICENSE.txt: LICENSE library/LICENSE.txt: LICENSE
@@ -40,8 +63,8 @@ python-clean:
python-dist: python-clean python-wheels python-sdist python-dist: python-clean python-wheels python-sdist
ls library/dist ls library/dist
python-deploy: python-dist
twine upload library/dist/*
python-deploy-test: python-dist
python-testdeploy: python-dist python-testdeploy: python-dist
twine upload --repository-url https://test.pypi.org/legacy/ library/dist/*
python-deploy: check python-dist

254
install.sh Executable file
View File

@@ -0,0 +1,254 @@
#!/bin/bash
CONFIG=/boot/config.txt
DATESTAMP=`date "+%Y-%M-%d-%H-%M-%S"`
CONFIG_BACKUP=false
APT_HAS_UPDATED=false
USER_HOME=/home/$SUDO_USER
RESOURCES_TOP_DIR=$USER_HOME/Pimoroni
WD=`pwd`
USAGE="sudo ./install.sh (--unstable)"
POSITIONAL_ARGS=()
UNSTABLE=false
PYTHON3=`which python3`
user_check() {
if [ $(id -u) -ne 0 ]; then
printf "Script must be run as root. Try 'sudo ./install.sh'\n"
exit 1
fi
}
confirm() {
if [ "$FORCE" == '-y' ]; 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)"
}
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"
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
apt update
APT_HAS_UPDATED=true
fi
apt install -y $PACKAGES
if [ -f "$UNINSTALLER" ]; then
echo "apt uninstall -y $PACKAGES"
fi
fi
}
while [[ $# -gt 0 ]]; do
K="$1"
case $K in
-u|--unstable)
UNSTABLE=true
shift
;;
*)
if [[ $1 == -* ]]; then
printf "Unrecognised option: $1\n";
printf "Usage: $USAGE\n";
exit 1
fi
POSITIONAL_ARGS+=("$1")
shift
esac
done
user_check
apt_pkg_install python-configparser
CONFIG_VARS=`python - <<EOF
from configparser import ConfigParser
c = ConfigParser()
c.read('library/setup.cfg')
p = dict(c['pimoroni'])
# Convert multi-line config entries into bash arrays
for k in p.keys():
fmt = '"{}"'
if '\n' in p[k]:
p[k] = "'\n\t'".join(p[k].split('\n')[1:])
fmt = "('{}')"
p[k] = fmt.format(p[k])
print("""
LIBRARY_NAME="{name}"
LIBRARY_VERSION="{version}"
""".format(**c['metadata']))
print("""
PY3_DEPS={py3deps}
PY2_DEPS={py2deps}
SETUP_CMDS={commands}
CONFIG_TXT={configtxt}
PY3_ONLY={py3only}
""".format(**p))
EOF`
if [ $? -ne 0 ]; then
warning "Error parsing configuration...\n"
exit 1
fi
eval $CONFIG_VARS
RESOURCES_DIR=$RESOURCES_TOP_DIR/$LIBRARY_NAME
UNINSTALLER=$RESOURCES_DIR/uninstall.sh
mkdir -p $RESOURCES_DIR
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"
exit 1
EOF
printf "$LIBRARY_NAME $LIBRARY_VERSION Python Library: Installer\n\n"
if $UNSTABLE; then
warning "Installing unstable library from source.\n\n"
else
printf "Installing stable library from pypi.\n\n"
fi
cd library
if ! $PY3_ONLY; then
printf "Installing for Python 2..\n"
apt_pkg_install "${PY2_DEPS[@]}"
if $UNSTABLE; then
python setup.py install > /dev/null
else
pip install --upgrade $LIBRARY_NAME
fi
if [ $? -eq 0 ]; then
success "Done!\n"
echo "pip uninstall $LIBRARY_NAME" >> $UNINSTALLER
fi
fi
if [ -f "$PYTHON3" ]; then
printf "Installing for Python 3..\n"
apt_pkg_install "${PY3_DEPS[@]}"
if $UNSTABLE; then
python3 setup.py install > /dev/null
else
pip3 install --upgrade $LIBRARY_NAME
fi
if [ $? -eq 0 ]; then
success "Done!\n"
echo "pip3 uninstall $LIBRARY_NAME" >> $UNINSTALLER
fi
else
if $PY3_ONLY; then
warning "Python 3 is required to install this library...\n"
exit 1
fi
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"
sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG
if ! grep -q "^$CONFIG_LINE" $CONFIG; then
printf "$CONFIG_LINE\n" >> $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 [ -f "/usr/bin/pydoc" ]; then
printf "Generating documentation.\n"
pydoc -w $LIBRARY_NAME > /dev/null
if [ -f "$LIBRARY_NAME.html" ]; then
cp $LIBRARY_NAME.html $RESOURCES_DIR/docs.html
rm -f $LIBRARY_NAME.html
inform "Documentation saved to $RESOURCES_DIR/docs.html"
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"

View File

@@ -1,5 +1,5 @@
include CHANGELOG.txt include CHANGELOG.txt
include LICENSE.txt include LICENSE.txt
include README.rst include README.md
include setup.py include setup.py
recursive-include ST7735 *.py recursive-include ST7735 *.py

74
library/README.md Normal file
View File

@@ -0,0 +1,74 @@
# Python ST7735
[![Build Status](https://travis-ci.com/pimoroni/st7735-python.svg?branch=master)](https://travis-ci.com/pimoroni/st7735-python)
[![Coverage Status](https://coveralls.io/repos/github/pimoroni/st7735-python/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/st7735-python?branch=master)
[![PyPi Package](https://img.shields.io/pypi/v/st7735.svg)](https://pypi.python.org/pypi/st7735)
[![Python Versions](https://img.shields.io/pypi/pyversions/st7735.svg)](https://pypi.python.org/pypi/st7735)
Python library to control an ST7735 TFT LCD display. Allows simple drawing on the display without installing a kernel module.
Designed specifically to work with a ST7735 based 160x80 pixel TFT SPI display. (Specifically the 0.96" SPI LCD from Pimoroni).
Make sure you have the following dependencies:
````
sudo apt-get update
sudo apt-get install python-rpi.gpio python-spidev python-pip python-imaging python-numpy
````
Install this library by running:
````
sudo pip install st7735
````
See example of usage in the examples folder.
# Licensing & History
This library is a modification of a modification of code originally written by Tony DiCola for Adafruit Industries, and modified to work with the ST7735 by Clement Skau.
It has been modified by Pimoroni to include support for their 160x80 SPI LCD breakout, and hopefully also generalised enough so that it will support other ST7735-powered displays.
## Modifications include:
* PIL/Pillow has been removed from the underlying display driver to separate concerns- you should create your own PIL image and display it using `display(image)`
* `width`, `height`, `rotation`, `invert`, `offset_left` and `offset_top` parameters can be passed into `__init__` for alternate displays
* `Adafruit_GPIO` has been replaced with `RPi.GPIO` and `spidev` to closely align with our other software (IE: Raspberry Pi only)
* Test fixtures have been added to keep this library stable
Pimoroni invests time and resources forking and modifying this open source code, please support Pimoroni and open-source software by purchasing products from us, too!
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
Modified from 'Modified from 'Adafruit Python ILI9341' written by Tony DiCola for Adafruit Industries.' written by Clement Skau.
MIT license, all text above must be included in any redistribution
# Changelog
0.0.4
-----
* Depend upon spidev==3.4.0 for stability fixes
* Switch from manual data chunking to spidev.xfer3()
0.0.3
-----
* Fixed backlight pin
* Added `set_backlight`
* Added constants BG_SPI_CS_FRONT and BG_SPI_CS_BACK
* Added module __version__
0.0.2
-----
* Support for multiple display sizes/orientations
0.0.1
-----
* Initial Release

View File

@@ -1,66 +0,0 @@
Python ST7735
=============
`Build Status <https://travis-ci.com/pimoroni/st7735-python>`__
`Coverage
Status <https://coveralls.io/github/pimoroni/st7735-python?branch=master>`__
`PyPi Package <https://pypi.python.org/pypi/st7735>`__ `Python
Versions <https://pypi.python.org/pypi/st7735>`__
Python library to control an ST7735 TFT LCD display. Allows simple
drawing on the display without installing a kernel module.
Designed specifically to work with a ST7735 based 160x80 pixel TFT SPI
display. (Specifically the 0.96" SPI LCD from Pimoroni).
Make sure you have the following dependencies:
::
sudo apt-get update
sudo apt-get install python-rpi.gpio python-spidev python-pip python-imaging python-numpy
Install this library by running:
::
sudo pip install st7735
See example of usage in the examples folder.
Licensing & History
===================
This library is a modification of a modification of code originally
written by Tony DiCola for Adafruit Industries, and modified to work
with the ST7735 by Clement Skau.
It has been modified by Pimoroni to include support for their 160x80 SPI
LCD breakout, and hopefully also generalised enough so that it will
support other ST7735-powered displays.
Modifications include:
----------------------
- PIL/Pillow has been removed from the underlying display driver to
separate concerns- you should create your own PIL image and display
it using ``display(image)``
- ``width``, ``height``, ``rotation``, ``invert``, ``offset_left`` and
``offset_top`` parameters can be passed into ``__init__`` for
alternate displays
- ``Adafruit_GPIO`` has been replaced with ``RPi.GPIO`` and ``spidev``
to closely align with our other software (IE: Raspberry Pi only)
- Test fixtures have been added to keep this library stable
Pimoroni invests time and resources forking and modifying this open
source code, please support Pimoroni and open-source software by
purchasing products from us, too!
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing products
from Adafruit!
Modified from Modified from Adafruit Python ILI9341 written by Tony
DiCola for Adafruit Industries. written by Clement Skau.
MIT license, all text above must be included in any redistribution

View File

@@ -26,7 +26,7 @@ import spidev
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
__version__ = '0.0.3' __version__ = '0.0.4'
BG_SPI_CS_BACK = 0 BG_SPI_CS_BACK = 0
BG_SPI_CS_FRONT = 1 BG_SPI_CS_FRONT = 1
@@ -50,15 +50,8 @@ ST7735_SLPOUT = 0x11
ST7735_PTLON = 0x12 ST7735_PTLON = 0x12
ST7735_NORON = 0x13 ST7735_NORON = 0x13
# ILI9341_RDMODE = 0x0A
# ILI9341_RDMADCTL = 0x0B
# ILI9341_RDPIXFMT = 0x0C
# ILI9341_RDIMGFMT = 0x0A
# ILI9341_RDSELFDIAG = 0x0F
ST7735_INVOFF = 0x20 ST7735_INVOFF = 0x20
ST7735_INVON = 0x21 ST7735_INVON = 0x21
# ILI9341_GAMMASET = 0x26
ST7735_DISPOFF = 0x28 ST7735_DISPOFF = 0x28
ST7735_DISPON = 0x29 ST7735_DISPON = 0x29
@@ -69,14 +62,12 @@ ST7735_RAMRD = 0x2E
ST7735_PTLAR = 0x30 ST7735_PTLAR = 0x30
ST7735_MADCTL = 0x36 ST7735_MADCTL = 0x36
# ST7735_PIXFMT = 0x3A
ST7735_COLMOD = 0x3A ST7735_COLMOD = 0x3A
ST7735_FRMCTR1 = 0xB1 ST7735_FRMCTR1 = 0xB1
ST7735_FRMCTR2 = 0xB2 ST7735_FRMCTR2 = 0xB2
ST7735_FRMCTR3 = 0xB3 ST7735_FRMCTR3 = 0xB3
ST7735_INVCTR = 0xB4 ST7735_INVCTR = 0xB4
# ILI9341_DFUNCTR = 0xB6
ST7735_DISSET5 = 0xB6 ST7735_DISSET5 = 0xB6
@@ -86,7 +77,6 @@ ST7735_PWCTR3 = 0xC2
ST7735_PWCTR4 = 0xC3 ST7735_PWCTR4 = 0xC3
ST7735_PWCTR5 = 0xC4 ST7735_PWCTR5 = 0xC4
ST7735_VMCTR1 = 0xC5 ST7735_VMCTR1 = 0xC5
# ILI9341_VMCTR2 = 0xC7
ST7735_RDID1 = 0xDA ST7735_RDID1 = 0xDA
ST7735_RDID2 = 0xDB ST7735_RDID2 = 0xDB

View File

@@ -1,6 +1,37 @@
# -*- coding: utf-8 -*-
[metadata]
name = ST7735
version = 0.0.4
author = Philip Howard
author_email = phil@pimoroni.com
description = Library to control an ST7735 168x80 TFT LCD display.
long_description = file: README.md
long_description_content_type = text/markdown
keywords = Raspberry Pi
url = https://www.pimoroni.com
project_urls =
GitHub=https://www.github.com/pimoroni/st7735-python
license = MIT
# This includes the license file(s) in the wheel.
# https://wheel.readthedocs.io/en/stable/user_guide.html#including-license-files-in-the-generated-wheel-file
license_files = LICENSE.txt
classifiers =
Development Status :: 4 - Beta
Operating System :: POSIX :: Linux
License :: OSI Approved :: MIT License
Intended Audience :: Developers
Programming Language :: Python :: 3
Topic :: Software Development
Topic :: Software Development :: Libraries
Topic :: System :: Hardware
[options]
packages = ST7735
install_requires =
spidev >= 3.4
[flake8] [flake8]
exclude = exclude =
test.py
.tox, .tox,
.eggs, .eggs,
.git, .git,
@@ -9,3 +40,14 @@ exclude =
dist dist
ignore = ignore =
E501 E501
[pimoroni]
py3only = false
py2deps =
python-pil
py3deps =
python3-pil
configtxt =
commands =
printf "Setting up SPI...\n"
raspi-config nonint do_spi 0

View File

@@ -1,23 +1,30 @@
from setuptools import setup, find_packages #!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
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.
"""
from setuptools import setup, __version__
from pkg_resources import parse_version
classifiers = ['Development Status :: 4 - Beta', minimum_version = parse_version('30.4.0')
'Operating System :: POSIX :: Linux',
'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Topic :: Software Development',
'Topic :: System :: Hardware']
setup(name='ST7735', if parse_version(__version__) < minimum_version:
version='0.0.4', raise RuntimeError("Package setuptools must be at least version {}".format(minimum_version))
description='Library to control an ST7735 168x80 TFT LCD display.',
long_description=open('README.rst').read() + '\n' + open('CHANGELOG.txt').read(), setup()
license='MIT',
author='Philip Howard',
author_email='phil@pimoroni.com',
classifiers=classifiers,
url='https://github.com/pimoroni/st7735-160x80-python/',
packages=find_packages(),
install_requires=['spidev>=3.4'])

View File

@@ -1,38 +1,38 @@
"""Test configuration. """Test configuration.
These allow the mocking of various Python modules These allow the mocking of various Python modules
that might otherwise have runtime side-effects. that might otherwise have runtime side-effects.
""" """
import sys import sys
import mock import mock
import pytest import pytest
@pytest.fixture(scope='function', autouse=False) @pytest.fixture(scope='function', autouse=False)
def GPIO(): def GPIO():
"""Mock RPi.GPIO module.""" """Mock RPi.GPIO module."""
GPIO = mock.MagicMock() GPIO = mock.MagicMock()
# Fudge for Python < 37 (possibly earlier) # Fudge for Python < 37 (possibly earlier)
sys.modules['RPi'] = mock.Mock() sys.modules['RPi'] = mock.Mock()
sys.modules['RPi'].GPIO = GPIO sys.modules['RPi'].GPIO = GPIO
sys.modules['RPi.GPIO'] = GPIO sys.modules['RPi.GPIO'] = GPIO
yield GPIO yield GPIO
del sys.modules['RPi'] del sys.modules['RPi']
del sys.modules['RPi.GPIO'] del sys.modules['RPi.GPIO']
@pytest.fixture(scope='function', autouse=False) @pytest.fixture(scope='function', autouse=False)
def spidev(): def spidev():
"""Mock spidev module.""" """Mock spidev module."""
spidev = mock.MagicMock() spidev = mock.MagicMock()
sys.modules['spidev'] = spidev sys.modules['spidev'] = spidev
yield spidev yield spidev
del sys.modules['spidev'] del sys.modules['spidev']
@pytest.fixture(scope='function', autouse=False) @pytest.fixture(scope='function', autouse=False)
def numpy(): def numpy():
"""Mock numpy module.""" """Mock numpy module."""
numpy = mock.MagicMock() numpy = mock.MagicMock()
sys.modules['numpy'] = numpy sys.modules['numpy'] = numpy
yield numpy yield numpy
del sys.modules['numpy'] del sys.modules['numpy']

View File

@@ -1,25 +1,25 @@
import mock import mock
from tools import force_reimport from tools import force_reimport
def test_display(GPIO, spidev, numpy): def test_display(GPIO, spidev, numpy):
force_reimport('ST7735') force_reimport('ST7735')
import ST7735 import ST7735
display = ST7735.ST7735(port=0, cs=0, dc=24) display = ST7735.ST7735(port=0, cs=0, dc=24)
numpy.dstack().flatten().tolist.return_value = [0xff, 0x00, 0xff, 0x00] numpy.dstack().flatten().tolist.return_value = [0xff, 0x00, 0xff, 0x00]
display.display(mock.MagicMock()) display.display(mock.MagicMock())
spidev.SpiDev().xfer3.assert_called_with([0xff, 0x00, 0xff, 0x00]) spidev.SpiDev().xfer3.assert_called_with([0xff, 0x00, 0xff, 0x00])
def test_color565(GPIO, spidev, numpy): def test_color565(GPIO, spidev, numpy):
force_reimport('ST7735') force_reimport('ST7735')
import ST7735 import ST7735
assert ST7735.color565(255, 255, 255) == 0xFFFF assert ST7735.color565(255, 255, 255) == 0xFFFF
def test_image_to_data(GPIO, spidev, numpy): def test_image_to_data(GPIO, spidev, numpy):
force_reimport('ST7735') force_reimport('ST7735')
numpy.dstack().flatten().tolist.return_value = [] numpy.dstack().flatten().tolist.return_value = []
import ST7735 import ST7735
assert ST7735.image_to_data(mock.MagicMock()) == [] assert ST7735.image_to_data(mock.MagicMock()) == []

View File

@@ -1,23 +1,23 @@
import sys import sys
def force_reimport(module): def force_reimport(module):
"""Force the module under test to be re-imported. """Force the module under test to be re-imported.
Because pytest runs all tests within the same scope (this makes me cry) Because pytest runs all tests within the same scope (this makes me cry)
we have to do some manual housekeeping to avoid tests polluting each other. we have to do some manual housekeeping to avoid tests polluting each other.
Since conftest.py already does some sys.modules mangling I see no reason not to Since conftest.py already does some sys.modules mangling I see no reason not to
do the same thing here. do the same thing here.
""" """
if "." in module: if "." in module:
steps = module.split(".") steps = module.split(".")
else: else:
steps = [module] steps = [module]
for i in range(len(steps)): for i in range(len(steps)):
module = ".".join(steps[0:i + 1]) module = ".".join(steps[0:i + 1])
try: try:
del sys.modules[module] del sys.modules[module]
except KeyError: except KeyError:
pass pass

View File

@@ -1,5 +1,5 @@
[tox] [tox]
envlist = py{27,35,37},qa envlist = py{27,36,38},qa
skip_missing_interpreters = True skip_missing_interpreters = True
[testenv] [testenv]
@@ -11,11 +11,14 @@ deps =
mock mock
pytest>=3.1 pytest>=3.1
pytest-cov pytest-cov
[testenv:qa] [testenv:qa]
commands = commands =
check-manifest --ignore tox.ini,tests/*,.coveragerc
python setup.py sdist bdist_wheel
twine check dist/*
flake8 --ignore E501 flake8 --ignore E501
rstcheck README.rst
deps = deps =
check-manifest
flake8 flake8
rstcheck twine