Skip to content

Commit

Permalink
Merge branch 'release/2020.0613'
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreMiras committed Jun 13, 2020
2 parents d1a1fc5 + a6d8023 commit c280b7c
Show file tree
Hide file tree
Showing 19 changed files with 197 additions and 57 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ venv/
.buildozer/
.pytest_cache/
.tox/
htmlcov/
13 changes: 13 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Android
on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- run: docker pull kivy/buildozer
- run: make docker/run/buildozer
- uses: actions/upload-artifact@v2
with:
path: bin/xcamera-*-armeabi-v7a-debug.apk
24 changes: 24 additions & 0 deletions .github/workflows/pypi-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: PyPI release
on: [push]

jobs:
pypi:
runs-on: ubuntu-20.04
strategy:
matrix:
config:
- {setup_file: setup.py, secret_key: pypi_password_xcamera}
- {setup_file: setup_meta.py, secret_key: pypi_password_kivy_garden_xcamera}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.7
- run: python -m pip install --user --upgrade setuptools wheel kivy
- run: python setup.py sdist bdist_wheel
- name: Publish package
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
uses: pypa/[email protected]
with:
user: __token__
password: ${{ secrets[matrix.secret_key] }}
16 changes: 16 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Tests
on: [push, pull_request]

jobs:
tests:
runs-on: ubuntu-20.04
env:
DISPLAY: ':99.0'
steps:
- uses: actions/checkout@v2
- run: make docker/pull
- run: make docker/build
- run: |
sudo apt install xvfb libxkbcommon-x11-0
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
- run: make docker/run/test
14 changes: 3 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,11 @@ language: generic

services:
- docker

env:
- DISPLAY=:99.0

before_install:
- sudo apt update -qq > /dev/null
- sudo apt install --yes --no-install-recommends xvfb

install:
- make docker/build
- xvfb

before_script:
- sh -e /etc/init.d/xvfb start
- make docker/pull
- make docker/build

script:
- make docker/run/test
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Change Log

## [2020.0613]

- Increase test coverage to 93%
- Move PythonActivity from 'kivy' after 'renpy' drop, closes #15, refs #16
- Introduces GitHub actions, refs #18
- Also tests against Python 3.8, refs #19
- Android build CI, refs #20
- Uploads APK artifact, refs #21
- Automates PyPI releases from CI, refs #22
- Bumps to kivy post 2.0.0rc2 on Android, refs #23

## [2019.0928]

- Setup coverage testing
Expand Down
51 changes: 27 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,39 @@ SOURCES=src/ tests/ setup.py setup_meta.py
SPHINXBUILD=$(shell realpath venv/bin/sphinx-build)
DOCS_DIR=doc
SYSTEM_DEPENDENCIES= \
build-essential \
ccache \
cmake \
curl \
git \
libsdl2-dev \
libsdl2-image-dev \
libsdl2-mixer-dev \
libsdl2-ttf-dev \
libpython3.6-dev \
libpython$(PYTHON_VERSION)-dev \
libzbar-dev \
pkg-config \
python3.6 \
python3.6-dev \
python3.7 \
python3.7-dev \
python$(PYTHON_VERSION) \
tox \
virtualenv
OS=$(shell lsb_release -si)
PYTHON_MAJOR_VERSION=3
PYTHON_MINOR_VERSION=7
PYTHON_MINOR_VERSION=8
PYTHON_VERSION=$(PYTHON_MAJOR_VERSION).$(PYTHON_MINOR_VERSION)
PYTHON_MAJOR_MINOR=$(PYTHON_MAJOR_VERSION)$(PYTHON_MINOR_VERSION)
PYTHON_WITH_VERSION=python$(PYTHON_VERSION)
DOCKER_IMAGE_LINUX=kivy/xcamera-linux
DOCKER_ENV=--env-file dockerfiles/env.list
DOCKER_VOLUME=--volume /tmp/.X11-unix:/tmp/.X11-unix

ifndef CI
DOCKER_DEVICE=--device /dev/video0
DOCKER_GROUP_ADD=--group-add video
endif


all: system_dependencies virtualenv
all: virtualenv

system_dependencies:
ifeq ($(OS), Ubuntu)
sudo apt install --yes --no-install-recommends $(SYSTEM_DEPENDENCIES)
endif
apt install --yes --no-install-recommends $(SYSTEM_DEPENDENCIES)

$(VIRTUAL_ENV):
virtualenv -p $(PYTHON_WITH_VERSION) $(VIRTUAL_ENV)
$(PIP) install Cython==0.28.6
virtualenv --python $(PYTHON_WITH_VERSION) $(VIRTUAL_ENV)
$(PIP) install Cython
$(PIP) install -r requirements.txt

virtualenv: $(VIRTUAL_ENV)
Expand All @@ -60,7 +56,6 @@ run: virtualenv

test:
$(TOX)
@if test -n "$$CI"; then .tox/py$(PYTHON_MAJOR_MINOR)/bin/coveralls; fi; \

pytest: virtualenv/test
PYTHONPATH=src $(PYTEST) --cov src/ --cov-report html tests/
Expand Down Expand Up @@ -94,22 +89,30 @@ release/upload:
$(TWINE) upload dist/*

clean: release/clean docs/clean
py3clean src/
py3clean .
find . -type d -name "__pycache__" -exec rm -r {} +
find . -type d -name "*.egg-info" -exec rm -r {} +
rm -rf htmlcov/

clean/all: clean
rm -rf $(VIRTUAL_ENV) .tox/

docker/pull:
docker pull $(DOCKER_IMAGE_LINUX):latest

docker/build:
docker build --tag=xcamera-linux --file=dockerfiles/Dockerfile-linux .
docker build --cache-from=$(DOCKER_IMAGE_LINUX) --tag=$(DOCKER_IMAGE_LINUX) --file=dockerfiles/Dockerfile-linux .

docker/run/test:
docker run --env-file dockerfiles/env.list -v /tmp/.X11-unix:/tmp/.X11-unix xcamera-linux 'make test'
docker run --rm $(DOCKER_ENV) $(DOCKER_VOLUME) $(DOCKER_GROUP_ADD) $(DOCKER_DEVICE) $(DOCKER_IMAGE_LINUX) 'make test'

docker/run/app:
docker run --env-file dockerfiles/env.list -v /tmp/.X11-unix:/tmp/.X11-unix --device=/dev/video0:/dev/video0 xcamera-linux 'make run'
docker run --rm $(DOCKER_ENV) $(DOCKER_VOLUME) $(DOCKER_GROUP_ADD) $(DOCKER_DEVICE) $(DOCKER_IMAGE_LINUX) 'make run'

docker/run/shell:
docker run --env-file dockerfiles/env.list -v /tmp/.X11-unix:/tmp/.X11-unix --device=/dev/video0:/dev/video0 -it --rm xcamera-linux
docker run -it --rm $(DOCKER_ENV) $(DOCKER_VOLUME) $(DOCKER_GROUP_ADD) $(DOCKER_DEVICE) $(DOCKER_IMAGE_LINUX)

docker/run/buildozer:
mkdir -p ~/.buildozer .buildozer bin
@if test -n "$$CI"; then sudo chown -R 1000:1000 ~/.buildozer .buildozer bin; fi; \
docker run --volume "$(CURDIR)":/home/user/hostcwd kivy/buildozer android debug
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# XCamera: Android-optimized camera widget

[![Github Actions Tests](https://github.com/kivy-garden/xcamera/workflows/Tests/badge.svg)](https://github.com/kivy-garden/xcamera/actions?query=workflow%3ATests)
[![Github Actions Android](https://github.com/kivy-garden/xcamera/workflows/Android/badge.svg)](https://github.com/kivy-garden/xcamera/actions?query=workflow%3AAndroid)
[![Build Status](https://travis-ci.com/kivy-garden/xcamera.svg?branch=develop)](https://travis-ci.com/kivy-garden/xcamera)
[![Coverage Status](https://coveralls.io/repos/github/kivy-garden/xcamera/badge.svg?branch=develop)](https://coveralls.io/github/kivy-garden/xcamera?branch=develop)
[![PyPI version](https://badge.fury.io/py/xcamera.svg)](https://badge.fury.io/py/xcamera)
Expand Down Expand Up @@ -40,7 +42,7 @@ Notes:
[xcamera is available on PyPI](https://pypi.org/project/xcamera/).
Therefore it can be installed via `pip`.
```sh
pip3 install --user xcamera
pip3 install xcamera
```
Once installed, the demo should be available in your `PATH` and can be ran from the command line.
```sh
Expand Down
2 changes: 1 addition & 1 deletion buildozer.spec
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ version.filename = %(source.dir)s/kivy_garden/xcamera/version.py
# comma separated e.g. requirements = sqlite3,kivy
requirements =
android,
kivy==1.11.1,
kivy==00034a5,
python3
# (str) Custom source folders for requirements
Expand Down
17 changes: 9 additions & 8 deletions dockerfiles/Dockerfile-linux
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Docker image for installing dependencies on Linux and running tests.
# Build with:
# docker build --tag=xcamera-linux --file=dockerfiles/Dockerfile-linux .
# docker build --tag=kivy/xcamera-linux --file=dockerfiles/Dockerfile-linux .
# Run with:
# docker run xcamera-linux /bin/sh -c 'make test'
# docker run kivy/xcamera-linux /bin/sh -c 'make test'
# Or using the entry point shortcut:
# docker run xcamera-linux 'make test'
# docker run kivy/xcamera-linux 'make test'
# For running UI:
# xhost +"local:docker@"
# docker run -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --device=/dev/video0:/dev/video0 xcamera-linux 'make run'
# docker run -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --device=/dev/video0:/dev/video0 kivy/xcamera-linux 'make run'
# Or for interactive shell:
# docker run -it --rm xcamera-linux
# docker run -it --rm kivy/xcamera-linux
FROM ubuntu:18.04

ENV USER="user"
Expand All @@ -25,8 +25,7 @@ ENV LANG="en_US.UTF-8" \
LC_ALL="en_US.UTF-8"

# install system dependencies
RUN apt install --yes --no-install-recommends \
lsb-release \
RUN apt update -qq > /dev/null && apt install --yes --no-install-recommends \
make \
sudo

Expand All @@ -40,6 +39,8 @@ RUN gpasswd --add ${USER} video

USER ${USER}
WORKDIR ${WORK_DIR}
COPY Makefile requirements* ${WORK_DIR}/
RUN sudo apt update -qq > /dev/null \
&& sudo make system_dependencies && make virtualenv
COPY . ${WORK_DIR}
RUN sudo make system_dependencies && make virtualenv
ENTRYPOINT ["./dockerfiles/start.sh"]
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Kivy==1.11.1
opencv-python==4.1.1.26
Kivy==2.0.0rc2
opencv-python==4.1.2.30
2 changes: 1 addition & 1 deletion src/kivy_garden/xcamera/android_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Camera = autoclass('android.hardware.Camera')
AndroidActivityInfo = autoclass('android.content.pm.ActivityInfo')
AndroidPythonActivity = autoclass('org.renpy.android.PythonActivity')
AndroidPythonActivity = autoclass('org.kivy.android.PythonActivity')
PORTRAIT = AndroidActivityInfo.SCREEN_ORIENTATION_PORTRAIT
LANDSCAPE = AndroidActivityInfo.SCREEN_ORIENTATION_LANDSCAPE

Expand Down
2 changes: 1 addition & 1 deletion src/kivy_garden/xcamera/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '2019.0928'
__version__ = '2020.0613'
Empty file added tests/__init__.py
Empty file.
Empty file added tests/kivy_garden/__init__.py
Empty file.
Empty file.
40 changes: 40 additions & 0 deletions tests/kivy_garden/xcamera/test_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from threading import Thread
from time import sleep
from unittest import mock

from kivy.app import App
from kivy.clock import Clock

from kivy_garden.xcamera.main import CameraApp, main
from tests.test_main import camera_release_workaround, patch_core_camera


def patch_picture_taken():
return mock.patch('kivy_garden.xcamera.main.CameraApp.picture_taken')


class TestMain:
"""
Tests the `main` module.
"""

def test_picture_taken(self):
"""
Checks the `picture_taken()` listener gets called on the running app.
"""
app_thread = Thread(target=main)
app_thread.start()
app = App.get_running_app()
filename = mock.sentinel
Clock.schedule_once(
lambda dt: app.root.ids.xcamera.dispatch(
'on_picture_taken', filename))
with patch_picture_taken() as m_picture_taken, patch_core_camera():
sleep(0.5) # FIXME: nondeterministic approach
# makes sure app thread is gracefully stopped before asserting
app.stop()
app_thread.join()
camera_release_workaround(app)
assert type(app) == CameraApp
assert m_picture_taken.mock_calls == [
mock.call(app.root.ids.xcamera, filename)]
44 changes: 41 additions & 3 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,52 @@
import os
from threading import Thread
from unittest import mock

from kivy.app import App

from kivy_garden.xcamera.main import CameraApp
from main import main


def camera_release_workaround(app):
"""
Upstream bug workaround, refs:
https://github.com/kivy-garden/xcamera/issues/14
"""
app.root.ids.xcamera._camera._device.release()


def get_camera_class():
"""
Continuous integration providers don't have a camera available.
"""
if os.environ.get('CI', False):
Camera = None
else:
from kivy.core.camera import Camera
return Camera


def patch_core_camera():
Camera = get_camera_class()
return mock.patch('kivy.uix.camera.CoreCamera', wraps=Camera)


class TestMain:
"""
Tests the `main` module.
"""

def test_main(self):
with mock.patch('kivy_garden.xcamera.main.CameraApp.run') as m_play:
main()
assert m_play.mock_calls == [mock.call()]
"""
Checks the main starts the app properly.
"""
app_thread = Thread(target=main)
app_thread.start()
app = App.get_running_app()
# makes sure app thread is gracefully stopped before asserting
app.stop()
with patch_core_camera():
app_thread.join()
camera_release_workaround(app)
assert type(app) == CameraApp
Loading

0 comments on commit c280b7c

Please sign in to comment.