diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 23c9efd..0ad8383 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -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 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 - for the exact command. + for the exact command. - **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 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d8187f0..0e3432a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: [2.7, 3.4, 3.5, 3.7, 3.8] + python: [2.7, 3.6, 3.8] steps: - uses: actions/checkout@v2 @@ -32,6 +32,6 @@ jobs: working-directory: library run: | python -m pip install coveralls - coveralls + coveralls --service=github if: ${{ matrix.python == '3.8' }} diff --git a/Makefile b/Makefile index 93b0bc8..7abad19 100644 --- a/Makefile +++ b/Makefile @@ -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 usage: + @echo "Library: ${LIBRARY_NAME}" + @echo "Version: ${LIBRARY_VERSION}\n" @echo "Usage: make , where target is one of:\n" - @echo "install: install the library locally from source" - @echo "uninstall: uninstall the local library" - @echo "python-readme: generate library/README.rst from README.md" + @echo "install: install the library locally from source" + @echo "uninstall: uninstall the local library" + @echo "check: peform basic integrity checks on the codebase" + @echo "python-readme: generate library/README.md from README.md + library/CHANGELOG.txt" @echo "python-wheels: build python .whl files for distribution" @echo "python-sdist: build python source distribution" @echo "python-clean: clean python build and dist directories" - @echo "python-dist: build all python distribution files" + @echo "python-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.sh @@ -15,12 +23,27 @@ install: uninstall: ./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-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 library/LICENSE.txt: LICENSE cp LICENSE library/LICENSE.txt @@ -40,8 +63,8 @@ python-clean: python-dist: python-clean python-wheels python-sdist ls library/dist -python-deploy: python-dist - twine upload library/dist/* - -python-deploy-test: python-dist +python-testdeploy: python-dist twine upload --repository-url https://test.pypi.org/legacy/ library/dist/* + +python-deploy: check python-dist + twine upload library/dist/* diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..2606343 --- /dev/null +++ b/install.sh @@ -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 - < $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" diff --git a/library/MANIFEST.in b/library/MANIFEST.in index db398bf..0de9a87 100644 --- a/library/MANIFEST.in +++ b/library/MANIFEST.in @@ -1,5 +1,5 @@ include CHANGELOG.txt include LICENSE.txt -include README.rst +include README.md include setup.py recursive-include ST7735 *.py diff --git a/library/README.md b/library/README.md new file mode 100644 index 0000000..fb6b5a0 --- /dev/null +++ b/library/README.md @@ -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 diff --git a/library/README.rst b/library/README.rst deleted file mode 100644 index efc50cf..0000000 --- a/library/README.rst +++ /dev/null @@ -1,66 +0,0 @@ -Python ST7735 -============= - -`Build Status `__ -`Coverage -Status `__ -`PyPi Package `__ `Python -Versions `__ - -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 diff --git a/library/ST7735/__init__.py b/library/ST7735/__init__.py index b35ab3c..e547645 100644 --- a/library/ST7735/__init__.py +++ b/library/ST7735/__init__.py @@ -26,7 +26,7 @@ import spidev import RPi.GPIO as GPIO -__version__ = '0.0.3' +__version__ = '0.0.4' BG_SPI_CS_BACK = 0 BG_SPI_CS_FRONT = 1 @@ -50,15 +50,8 @@ ST7735_SLPOUT = 0x11 ST7735_PTLON = 0x12 ST7735_NORON = 0x13 -# ILI9341_RDMODE = 0x0A -# ILI9341_RDMADCTL = 0x0B -# ILI9341_RDPIXFMT = 0x0C -# ILI9341_RDIMGFMT = 0x0A -# ILI9341_RDSELFDIAG = 0x0F - ST7735_INVOFF = 0x20 ST7735_INVON = 0x21 -# ILI9341_GAMMASET = 0x26 ST7735_DISPOFF = 0x28 ST7735_DISPON = 0x29 @@ -69,14 +62,12 @@ ST7735_RAMRD = 0x2E ST7735_PTLAR = 0x30 ST7735_MADCTL = 0x36 -# ST7735_PIXFMT = 0x3A ST7735_COLMOD = 0x3A ST7735_FRMCTR1 = 0xB1 ST7735_FRMCTR2 = 0xB2 ST7735_FRMCTR3 = 0xB3 ST7735_INVCTR = 0xB4 -# ILI9341_DFUNCTR = 0xB6 ST7735_DISSET5 = 0xB6 @@ -86,7 +77,6 @@ ST7735_PWCTR3 = 0xC2 ST7735_PWCTR4 = 0xC3 ST7735_PWCTR5 = 0xC4 ST7735_VMCTR1 = 0xC5 -# ILI9341_VMCTR2 = 0xC7 ST7735_RDID1 = 0xDA ST7735_RDID2 = 0xDB diff --git a/library/setup.cfg b/library/setup.cfg index 5c3c3ea..4643395 100644 --- a/library/setup.cfg +++ b/library/setup.cfg @@ -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] exclude = - test.py .tox, .eggs, .git, @@ -9,3 +40,14 @@ exclude = dist ignore = E501 + +[pimoroni] +py3only = false +py2deps = + python-pil +py3deps = + python3-pil +configtxt = +commands = + printf "Setting up SPI...\n" + raspi-config nonint do_spi 0 \ No newline at end of file diff --git a/library/setup.py b/library/setup.py index 85d144c..ab16e72 100644 --- a/library/setup.py +++ b/library/setup.py @@ -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', - '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'] +minimum_version = parse_version('30.4.0') -setup(name='ST7735', - version='0.0.4', - description='Library to control an ST7735 168x80 TFT LCD display.', - long_description=open('README.rst').read() + '\n' + open('CHANGELOG.txt').read(), - 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']) +if parse_version(__version__) < minimum_version: + raise RuntimeError("Package setuptools must be at least version {}".format(minimum_version)) + +setup() diff --git a/library/tests/conftest.py b/library/tests/conftest.py index 7582e08..bdc5359 100644 --- a/library/tests/conftest.py +++ b/library/tests/conftest.py @@ -1,38 +1,38 @@ -"""Test configuration. -These allow the mocking of various Python modules -that might otherwise have runtime side-effects. -""" -import sys -import mock -import pytest - - -@pytest.fixture(scope='function', autouse=False) -def GPIO(): - """Mock RPi.GPIO module.""" - GPIO = mock.MagicMock() - # Fudge for Python < 37 (possibly earlier) - sys.modules['RPi'] = mock.Mock() - sys.modules['RPi'].GPIO = GPIO - sys.modules['RPi.GPIO'] = GPIO - yield GPIO - del sys.modules['RPi'] - del sys.modules['RPi.GPIO'] - - -@pytest.fixture(scope='function', autouse=False) -def spidev(): - """Mock spidev module.""" - spidev = mock.MagicMock() - sys.modules['spidev'] = spidev - yield spidev - del sys.modules['spidev'] - - -@pytest.fixture(scope='function', autouse=False) -def numpy(): - """Mock numpy module.""" - numpy = mock.MagicMock() - sys.modules['numpy'] = numpy - yield numpy - del sys.modules['numpy'] +"""Test configuration. +These allow the mocking of various Python modules +that might otherwise have runtime side-effects. +""" +import sys +import mock +import pytest + + +@pytest.fixture(scope='function', autouse=False) +def GPIO(): + """Mock RPi.GPIO module.""" + GPIO = mock.MagicMock() + # Fudge for Python < 37 (possibly earlier) + sys.modules['RPi'] = mock.Mock() + sys.modules['RPi'].GPIO = GPIO + sys.modules['RPi.GPIO'] = GPIO + yield GPIO + del sys.modules['RPi'] + del sys.modules['RPi.GPIO'] + + +@pytest.fixture(scope='function', autouse=False) +def spidev(): + """Mock spidev module.""" + spidev = mock.MagicMock() + sys.modules['spidev'] = spidev + yield spidev + del sys.modules['spidev'] + + +@pytest.fixture(scope='function', autouse=False) +def numpy(): + """Mock numpy module.""" + numpy = mock.MagicMock() + sys.modules['numpy'] = numpy + yield numpy + del sys.modules['numpy'] diff --git a/library/tests/test_features.py b/library/tests/test_features.py index f8fb7d4..8de6eb8 100644 --- a/library/tests/test_features.py +++ b/library/tests/test_features.py @@ -1,25 +1,25 @@ -import mock -from tools import force_reimport - - -def test_display(GPIO, spidev, numpy): - force_reimport('ST7735') - import ST7735 - display = ST7735.ST7735(port=0, cs=0, dc=24) - numpy.dstack().flatten().tolist.return_value = [0xff, 0x00, 0xff, 0x00] - display.display(mock.MagicMock()) - - spidev.SpiDev().xfer3.assert_called_with([0xff, 0x00, 0xff, 0x00]) - - -def test_color565(GPIO, spidev, numpy): - force_reimport('ST7735') - import ST7735 - assert ST7735.color565(255, 255, 255) == 0xFFFF - - -def test_image_to_data(GPIO, spidev, numpy): - force_reimport('ST7735') - numpy.dstack().flatten().tolist.return_value = [] - import ST7735 - assert ST7735.image_to_data(mock.MagicMock()) == [] +import mock +from tools import force_reimport + + +def test_display(GPIO, spidev, numpy): + force_reimport('ST7735') + import ST7735 + display = ST7735.ST7735(port=0, cs=0, dc=24) + numpy.dstack().flatten().tolist.return_value = [0xff, 0x00, 0xff, 0x00] + display.display(mock.MagicMock()) + + spidev.SpiDev().xfer3.assert_called_with([0xff, 0x00, 0xff, 0x00]) + + +def test_color565(GPIO, spidev, numpy): + force_reimport('ST7735') + import ST7735 + assert ST7735.color565(255, 255, 255) == 0xFFFF + + +def test_image_to_data(GPIO, spidev, numpy): + force_reimport('ST7735') + numpy.dstack().flatten().tolist.return_value = [] + import ST7735 + assert ST7735.image_to_data(mock.MagicMock()) == [] diff --git a/library/tests/tools.py b/library/tests/tools.py index ddf752d..89c3fa0 100644 --- a/library/tests/tools.py +++ b/library/tests/tools.py @@ -1,23 +1,23 @@ -import sys - - -def force_reimport(module): - """Force the module under test to be re-imported. - - 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. - - Since conftest.py already does some sys.modules mangling I see no reason not to - do the same thing here. - """ - if "." in module: - steps = module.split(".") - else: - steps = [module] - - for i in range(len(steps)): - module = ".".join(steps[0:i + 1]) - try: - del sys.modules[module] - except KeyError: - pass +import sys + + +def force_reimport(module): + """Force the module under test to be re-imported. + + 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. + + Since conftest.py already does some sys.modules mangling I see no reason not to + do the same thing here. + """ + if "." in module: + steps = module.split(".") + else: + steps = [module] + + for i in range(len(steps)): + module = ".".join(steps[0:i + 1]) + try: + del sys.modules[module] + except KeyError: + pass diff --git a/library/tox.ini b/library/tox.ini index b23507c..56501e8 100644 --- a/library/tox.ini +++ b/library/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{27,35,37},qa +envlist = py{27,36,38},qa skip_missing_interpreters = True [testenv] @@ -11,11 +11,14 @@ deps = mock pytest>=3.1 pytest-cov - + [testenv:qa] commands = + check-manifest --ignore tox.ini,tests/*,.coveragerc + python setup.py sdist bdist_wheel + twine check dist/* flake8 --ignore E501 - rstcheck README.rst deps = + check-manifest flake8 - rstcheck + twine \ No newline at end of file