diff --git a/.dockerignore b/.dockerignore index cfd2643..253b2ea 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,4 +4,4 @@ venv/ .buildozer/ .pytest_cache/ .tox/ -opencv* +opencv-* diff --git a/.gitignore b/.gitignore index c1fec48..7f5edc0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,7 @@ venv/ .tox/ .buildozer/ bin/ +opencv-* +build/ +dist/ +*.egg-info/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ba0054..6479d74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## [20190902] + + - Update Cython for Python3.7 support, refs #35 + - Make garden.zbarcam a package again, refs #36 + - Don't ship opencv directory to APK, refs #37 + - Migrate to new garden structure, refs #17 + - Publish documentation to readthedocs, refs #18 + - Publish to PyPI, refs #19 + ## [20190303] - Add Python3.6 support, refs #5 diff --git a/Makefile b/Makefile index 5360553..94f2390 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,9 @@ PIP=$(VENV_NAME)/bin/pip TOX=`which tox` GARDEN=$(VENV_NAME)/bin/garden PYTHON=$(VENV_NAME)/bin/python +# using full path so it can be used outside the root dir +SPHINXBUILD=$(shell realpath venv/bin/sphinx-build) +DOCS_DIR=doc SYSTEM_DEPENDENCIES= \ build-essential \ cmake \ @@ -21,13 +24,19 @@ PYTHON_WITH_VERSION=python$(PYTHON_VERSION) # python3 has a "m" suffix for both include path and library PYTHON_M=$(PYTHON_WITH_VERSION) SITE_PACKAGES_DIR=$(VENV_NAME)/lib/$(PYTHON_WITH_VERSION)/site-packages +TMPDIR ?= /tmp +DOWNLOAD_DIR = $(TMPDIR)/downloads OPENCV_VERSION=4.0.1 -OPENCV_ARCHIVE=$(OPENCV_BASENAME).tar.gz OPENCV_BASENAME=opencv-$(OPENCV_VERSION) -OPENCV_BUILD_LIB_DIR=$(OPENCV_BASENAME)/build/lib +OPENCV_ARCHIVE=$(OPENCV_BASENAME).tar.gz +OPENCV_ARCHIVE_PATH=$(DOWNLOAD_DIR)/$(OPENCV_ARCHIVE) +OPENCV_EXTRACT_PATH=$(DOWNLOAD_DIR)/$(OPENCV_BASENAME) +OPENCV_BUILD_LIB_DIR=$(OPENCV_EXTRACT_PATH)/build/lib OPENCV_BUILD=$(OPENCV_BUILD_LIB_DIR)/python$(PYTHON_MAJOR_VERSION)/cv2*.so OPENCV_DEPLOY=$(SITE_PACKAGES_DIR)/cv2*.so NPROC=`grep -c '^processor' /proc/cpuinfo` + + ifeq ($(PYTHON_MAJOR_VERSION), 3) PYTHON_M := $(PYTHON_M)m endif @@ -38,7 +47,7 @@ all: system_dependencies virtualenv opencv venv: test -d venv || virtualenv -p python$(PYTHON_MAJOR_VERSION) venv . venv/bin/activate - $(PIP) install Cython==0.26.1 + $(PIP) install Cython==0.28.6 $(PIP) install -r requirements/requirements.txt $(GARDEN) install xcamera @@ -49,14 +58,15 @@ ifeq ($(OS), Ubuntu) sudo apt install --yes --no-install-recommends $(SYSTEM_DEPENDENCIES) endif -$(OPENCV_ARCHIVE): +$(OPENCV_ARCHIVE_PATH): + mkdir -p $(DOWNLOAD_DIR) curl --location https://github.com/opencv/opencv/archive/$(OPENCV_VERSION).tar.gz \ - --progress-bar --output $(OPENCV_ARCHIVE) + --progress-bar --output $(OPENCV_ARCHIVE_PATH) # The build also relies on virtualenv, because we make references to it. # Plus numpy is required to build OpenCV Python module. -$(OPENCV_BUILD): $(OPENCV_ARCHIVE) virtualenv - tar -xf $(OPENCV_BASENAME).tar.gz +$(OPENCV_BUILD): $(OPENCV_ARCHIVE_PATH) virtualenv + tar -xf $(OPENCV_ARCHIVE_PATH) --directory $(DOWNLOAD_DIR) cmake \ -D CMAKE_SHARED_LINKER_FLAGS=-l$(PYTHON_M) \ -D BUILD_SHARED_LIBS=ON \ @@ -90,8 +100,8 @@ $(OPENCV_BUILD): $(OPENCV_ARCHIVE) virtualenv -D WITH_JASPER=OFF \ -D WITH_OPENEXR=OFF \ -D WITH_PVAPI=OFF \ - -B$(OPENCV_BASENAME)/build -H$(OPENCV_BASENAME) - cmake --build $(OPENCV_BASENAME)/build -- -j$(NPROC) + -B$(OPENCV_EXTRACT_PATH)/build -H$(OPENCV_EXTRACT_PATH) + cmake --build $(OPENCV_EXTRACT_PATH)/build -- -j$(NPROC) $(OPENCV_DEPLOY): $(OPENCV_BUILD) virtualenv cp $(OPENCV_BUILD) $(SITE_PACKAGES_DIR) @@ -99,7 +109,7 @@ $(OPENCV_DEPLOY): $(OPENCV_BUILD) virtualenv opencv: $(OPENCV_DEPLOY) clean: - rm -rf $(VENV_NAME) .tox/ $(OPENCV_BASENAME) + rm -rf $(VENV_NAME) .tox/ $(DOWNLOAD_DIR) $(DOCS_DIR)/build/ dist/ build/ test: $(TOX) @@ -107,3 +117,6 @@ test: uitest: virtualenv $(PIP) install -r requirements/test_requirements.txt $(PYTHON) -m unittest discover --top-level-directory=. --start-directory=tests/ui/ + +docs: + cd $(DOCS_DIR) && SPHINXBUILD=$(SPHINXBUILD) make html diff --git a/OpenCV.md b/OpenCV.md index d89beb7..d5795da 100644 --- a/OpenCV.md +++ b/OpenCV.md @@ -10,3 +10,17 @@ make system_dependencies make opencv ``` It would build OpenCV and deploy it to your virtualenv. + +## Troubleshooting + +### Makefile `cp: cannot stat 'opencv-4.0.1/build/lib/python3/cv2*.so': No such file or directory` +Log: +``` +make[2]: Leaving directory '/tmp/trash/zbarcam/opencv-4.0.1/build' +make[1]: Leaving directory '/tmp/trash/zbarcam/opencv-4.0.1/build' +cp opencv-4.0.1/build/lib/python3/cv2*.so venv/lib/python3.7/site-packages +cp: cannot stat 'opencv-4.0.1/build/lib/python3/cv2*.so': No such file or directory +Makefile:97: recipe for target 'venv/lib/python3.7/site-packages/cv2*.so' failed +make: *** [venv/lib/python3.7/site-packages/cv2*.so] Error 1 +``` +Most likely you need to `pip install numpy` delete your opencv build and build again. diff --git a/README.md b/README.md index 6f06049..f5d2006 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# garden.zbarcam +# zbarcam -[![Build Status](https://secure.travis-ci.org/kivy-garden/garden.zbarcam.png?branch=develop)](http://travis-ci.org/kivy-garden/garden.zbarcam) +[![Build Status](https://travis-ci.org/kivy-garden/zbarcam.svg?branch=develop)](https://travis-ci.org/kivy-garden/zbarcam) Real time Barcode and QR Code scanner using the camera. It's built on top of [Kivy](https://github.com/kivy/kivy) and [pyzbar](https://github.com/NaturalHistoryMuseum/pyzbar). @@ -10,7 +10,7 @@ It's built on top of [Kivy](https://github.com/kivy/kivy) and [pyzbar](https://g ## How to use Simply import and instanciate `ZBarCam` in your kvlang file and access its `symbols` property. ```yaml -#:import ZBarCam kivy.garden.zbarcam +#:import ZBarCam kivy_garden.zbarcam.ZBarCam #:import ZBarSymbol pyzbar.pyzbar.ZBarSymbol BoxLayout: orientation: 'vertical' @@ -23,6 +23,7 @@ BoxLayout: size: self.texture_size[0], 50 text: ', '.join([str(symbol.data) for symbol in zbarcam.symbols]) ``` +A full working demo is available in [kivy_garden/zbarcam/main.py](kivy_garden/zbarcam/main.py). ## Install @@ -34,19 +35,19 @@ sudo apt install libzbar-dev Install garden requirements: ```sh -garden install xcamera +garden install --upgrade xcamera ``` Install zbarcam: -Via `garden`: ```sh -garden install --upgrade zbarcam +pip install --upgrade https://github.com/kivy-garden/zbarcam/archive/develop.zip ``` -Via `pip`: -```sh -pip install --upgrade https://github.com/kivy-garden/garden.zbarcam/archive/develop.zip +Then import it in your Python code via: +```python +from kivy_garden.zbarcam import ZBarCam ``` + You may also need to compile/install OpenCV manually, see [OpenCV.md](OpenCV.md). ### Android @@ -66,15 +67,15 @@ make uitest ## Troubleshooting ### Install `Unable to import package 'kivy.garden.xcamera.XCamera'` -Missing the `xcamera` dependency, install it with: -```sh -garden install xcamera -``` +You're missing the `xcamera` dependency. Install it as described in the install instructions. ### Android `ValueError: Empty module name` More likely an import issue in your `.kv` file. Try to `from zbarcam import ZBarCam` in your `main.py` to see the exact error. It's common to forget `Pillow` in `buildozer.spec` `requirements` section. +### OpenCV related +See [OpenCV.md](OpenCV.md). + ## Credits I borrowed a lot of code from [tito/android-zbar-qrcode](https://github.com/tito/android-zbar-qrcode). diff --git a/buildozer.spec b/buildozer.spec index 62cb0b5..a443aea 100644 --- a/buildozer.spec +++ b/buildozer.spec @@ -10,7 +10,7 @@ package.name = zbarcamdemo package.domain = com.github.andremiras # (str) Source code where the main.py live -source.dir = . +source.dir = src # (list) Source files to include (let empty to include all the files) source.include_exts = py,png,jpg,kv,atlas @@ -22,7 +22,7 @@ source.include_exts = py,png,jpg,kv,atlas #source.exclude_exts = spec # (list) List of directory to exclude (let empty to not exclude anything) -source.exclude_dirs = tests, bin, venv, opencv-* +#source.exclude_dirs = tests, bin # (list) List of exclusions using pattern matching #source.exclude_patterns = license,images/*/*.jpg @@ -32,7 +32,7 @@ source.exclude_dirs = tests, bin, venv, opencv-* # (str) Application versioning (method 2) version.regex = __version__ = ['"](.*)['"] -version.filename = %(source.dir)s/zbarcam/version.py +version.filename = %(source.dir)s/kivy_garden/zbarcam/version.py # (list) Application requirements # comma seperated e.g. requirements = sqlite3,kivy diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..af5f460 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,48 @@ +Generating the Docs +=================== + +Basic instructions for how to generate the flower docs and upload to github. +This needs to be done in either powershell or linux shell, not windows cmd. + +The generated docs can be found at https://kivy-garden.github.io/flower/ after this +process. + +Please use these instructions with care and don't copy paste without understanding +what the commands do as they create and delete folders. Make sure the repo is +fully pushed to github before doing this because this **deletes** all local changes. + +You may want to do the following commands in a copy of the flower directory. + +Install sphinx:: + + python -m pip install sphinx + +In a shell make sure to be in the flower directory. Then:: + + cd doc + # (in powershell do ./make.bat html) + make html + cd .. + + mkdir ~/docs_temp + # copy generated docs to temp path + cp -r doc/build/html/* ~/docs_temp + # gh-pages is the branch for the docs that github will display + git checkout --orphan gh-pages + # **CAUTION** be sure the following commands is executed in the flower directory + # we take no responsibility if you delete all the files in your computer :) + git rm -rf . + # on a linux shell do + rm -fr $(ls -1 --ignore=.git .) + # in powershell instead do + Remove-Item -recurse * -exclude .git + # copy the docs back to the repo + cp -r ~/docs_temp/* . + echo "" > .nojekyll + + git add . + git commit -a -m "Docs update" + git push origin gh-pages -f + + # Finally, get back to master + git checkout master \ No newline at end of file diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 0000000..9534b01 --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/source/api.rst b/doc/source/api.rst new file mode 100644 index 0000000..c35be91 --- /dev/null +++ b/doc/source/api.rst @@ -0,0 +1,9 @@ + +################ + Zbarcam API +################ + +.. toctree:: + :maxdepth: 1 + + zbarcam.rst diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..0429ee4 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,69 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('../../')) + + +# -- Project information ----------------------------------------------------- + +project = 'Zbarcam' +copyright = '2019, Andre Miras' +author = 'Andre Miras' + + +# -- General configuration --------------------------------------------------- + +# 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.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.intersphinx', + 'm2r', +] + +intersphinx_mapping = { + 'kivy': ('https://kivy.org/docs/', None), +} + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +source_suffix = ['.rst', '.md'] + +# The master toctree document. +master_doc = 'index' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- 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' + +# 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'] diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst new file mode 100644 index 0000000..a0a9484 --- /dev/null +++ b/doc/source/contributing.rst @@ -0,0 +1,8 @@ +################# + Contributing +################# + +.. toctree:: + :maxdepth: 2 + + release.md diff --git a/doc/source/examples.md b/doc/source/examples.md new file mode 100644 index 0000000..8b2a998 --- /dev/null +++ b/doc/source/examples.md @@ -0,0 +1,21 @@ +.. _examples: + +# Examples + + +## Basic Example + +```yaml +#:import ZBarCam kivy_garden.zbarcam.ZBarCam +#:import ZBarSymbol pyzbar.pyzbar.ZBarSymbol +BoxLayout: + orientation: 'vertical' + ZBarCam: + id: zbarcam + # optional, by default checks all types + code_types: ZBarSymbol.QRCODE, ZBarSymbol.EAN13 + Label: + size_hint: None, None + size: self.texture_size[0], 50 + text: ', '.join([str(symbol.data) for symbol in zbarcam.symbols]) +``` diff --git a/doc/source/getting_started.rst b/doc/source/getting_started.rst new file mode 100644 index 0000000..3315196 --- /dev/null +++ b/doc/source/getting_started.rst @@ -0,0 +1,11 @@ +.. _started: + +#################### + Getting Started +#################### + +.. toctree:: + :maxdepth: 2 + + installation.md + examples.md diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..0639238 --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,24 @@ +.. Zbarcam documentation master file, created by + sphinx-quickstart on Wed Jun 19 14:32:58 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Zbarcam's documentation! +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + getting_started.rst + api.rst + contributing.rst + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/source/installation.md b/doc/source/installation.md new file mode 100644 index 0000000..46b0c56 --- /dev/null +++ b/doc/source/installation.md @@ -0,0 +1,37 @@ +# Installation + +## Supported versions + +* Python 3.5+ + +## Dependencies + +* [Kivy](https://kivy.org/#download) + + +## Installation + +Please see the [garden docs](https://kivy-garden.github.io/) for full installation instructions. + +Install last zbarcam release from PyPI with: +```sh +pip install --upgrade zbarcam +``` + +Or develop branch directly from github with: +```sh +pip install https://github.com/kivy-garden/zbarcam/archive/develop.zip +``` + +You can also automatically install it using garden's pypi server with: +```sh +python -m pip install zbarcam --extra-index-url https://kivy-garden.github.io/simple/ +``` + +You can permanently add our garden server to your [pip.conf](https://pip.pypa.io/en/stable/user_guide/#config-file) +so that you don't have to specify it with `--extra-index-url`: +```sh +[global] +timeout = 60 +index-url = https://kivy-garden.github.io/simple/ +``` diff --git a/doc/source/release.md b/doc/source/release.md new file mode 100644 index 0000000..ff51794 --- /dev/null +++ b/doc/source/release.md @@ -0,0 +1,54 @@ +# How to release + +This is documenting the release process. + + +## Git flow & CHANGELOG.md + +Make sure the CHANGELOG.md is up to date and follows the http://keepachangelog.com guidelines. +Start the release with git flow: +```sh +git flow release start YYYYMMDD +``` +Now update the [CHANGELOG.md](/CHANGELOG.md) `[Unreleased]` section to match the new release version. +Also update the `version` string from the +[src/kivy_garden/zbarcam/version.py](https://github.com/kivy-garden/zbarcam/blob/develop/src/kivy_garden/zbarcam/version.py) +file. +Then commit and finish release. +```sh +git commit -a -m "YYYYMMDD" +git flow release finish +``` +Push everything, make sure tags are also pushed: +```sh +git push +git push origin master:master +git push --tags +``` + +## Publish to PyPI + +Build it: +```sh +python setup.py sdist bdist_wheel +``` +Check archive content: +```sh +tar -tvf dist/kivy_garden.zbarcam-*.tar.gz +``` +Twine check and upload: +```sh +twine check dist/* +twine upload dist/* +``` +Also publish the alias meta package `setup_meta.py`. + +## Check Read the Docs + +Make sure is up to date. + +## GitHub + +Got to GitHub [Release/Tags](https://github.com/kivy-garden/zbarcam/tags), click "Add release notes" for the tag just created. +Add the tag name in the "Release title" field and the relevant CHANGELOG.md section in the "Describe this release" textarea field. +Finally, attach the generated APK release file and click "Publish release". diff --git a/doc/source/zbarcam.rst b/doc/source/zbarcam.rst new file mode 100644 index 0000000..6c7968b --- /dev/null +++ b/doc/source/zbarcam.rst @@ -0,0 +1,13 @@ +.. _zbarcam-api: + +******* +Zbarcam +******* + +:mod:`kivy_garden.zbarcam` +============================= + +.. automodule:: kivy_garden.zbarcam + :members: + :undoc-members: + :show-inheritance: diff --git a/dockerfiles/Dockerfile-linux b/dockerfiles/Dockerfile-linux index e47af54..237f39c 100644 --- a/dockerfiles/Dockerfile-linux +++ b/dockerfiles/Dockerfile-linux @@ -35,12 +35,15 @@ RUN apt install --yes --no-install-recommends \ libsdl2-mixer-dev \ libsdl2-ttf-dev \ libpython3.6-dev \ + libpython3.7-dev \ libzbar-dev \ lsb-release \ make \ pkg-config \ - python3 \ - python3-dev \ + python3.6 \ + python3.6-dev \ + python3.7 \ + python3.7-dev \ sudo \ tox \ virtualenv diff --git a/main.py b/main.py deleted file mode 100755 index bd9295a..0000000 --- a/main.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python -""" -Buildozer is only hooking with a `main.py` file. -""" -from zbarcam.zbarcam import DemoApp - - -if __name__ == '__main__': - DemoApp().run() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7d837a9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +-r requirements/requirements.txt +-r requirements/requirements-documentation.txt +-r requirements/test_requirements.txt diff --git a/requirements/requirements-documentation.txt b/requirements/requirements-documentation.txt new file mode 100644 index 0000000..b5cb07a --- /dev/null +++ b/requirements/requirements-documentation.txt @@ -0,0 +1 @@ +m2r==0.2.1 diff --git a/setup.py b/setup.py index 28b66d6..bb1ef1a 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,39 @@ -#!/usr/bin/env python - -from distutils.core import setup - -setup(name='zbarcam', - version='20171220', - description='Real time Barcode and QR Code scanner Edit', - author='Andre Miras', - url='https://github.com/AndreMiras/garden.zbarcam', - packages=['zbarcam'], - package_data={'zbarcam': ['*.kv']}, - install_requires=['pyzbar', 'kivy', 'pillow', 'numpy']) +import os + +from setuptools import find_namespace_packages, setup +from src.kivy_garden.zbarcam import version + + +def read(fname): + with open(os.path.join(os.path.dirname(__file__), fname)) as f: + return f.read() + + +# exposing the params so it can be imported +setup_params = { + 'name': 'kivy_garden.zbarcam', + 'version': version.__version__, + 'description': 'Real time Barcode and QR Code scanner Edit', + 'long_description': read('README.md'), + 'long_description_content_type': 'text/markdown', + 'author': 'Andre Miras', + 'url': 'https://github.com/kivy-garden/zbarcam', + 'packages': find_namespace_packages(where='src'), + 'package_data': {'kivy_garden.zbarcam': ['*.kv']}, + 'package_dir': {'': 'src'}, + 'install_requires': [ + 'kivy', + 'numpy', + 'pillow', + 'pyzbar', + ], +} + + +def run_setup(): + setup(**setup_params) + + +# makes sure the setup doesn't run at import time +if __name__ == '__main__': + run_setup() diff --git a/setup_meta.py b/setup_meta.py new file mode 100644 index 0000000..c55169c --- /dev/null +++ b/setup_meta.py @@ -0,0 +1,14 @@ +""" +Creates a distribution alias that just installs pyetheroll. +""" +from setuptools import setup + +from setup import setup_params + +setup_params.update({ + 'install_requires': ['kivy_garden.zbarcam'], + 'name': 'zbarcam', +}) + + +setup(**setup_params) diff --git a/src/kivy_garden/zbarcam/__init__.py b/src/kivy_garden/zbarcam/__init__.py new file mode 100644 index 0000000..f10f37a --- /dev/null +++ b/src/kivy_garden/zbarcam/__init__.py @@ -0,0 +1,16 @@ +""" +Exposes `ZBarCam` directly in `zbarcam` rather than `zbarcam.zbarcam`. +Also note this may break `pip` since all imports within `zbarcam.py` would be +required at setup time. This is because `version.py` (same directory) is used +by the `setup.py` file. +Hence we're not exposing `ZBarCam` if `pip` is detected. +""" +import os + + +project_dir = os.path.abspath( + os.path.join(__file__, os.pardir, os.pardir, os.pardir, os.pardir)) +using_pip = os.path.basename(project_dir).startswith('pip-') +# only exposes `ZBarCam` if not within `pip` ongoing install +if not using_pip: + from .zbarcam import ZBarCam # noqa diff --git a/src/kivy_garden/zbarcam/version.py b/src/kivy_garden/zbarcam/version.py new file mode 100644 index 0000000..b29cb33 --- /dev/null +++ b/src/kivy_garden/zbarcam/version.py @@ -0,0 +1 @@ +__version__ = '2019.0902' diff --git a/zbarcam/zbarcam.kv b/src/kivy_garden/zbarcam/zbarcam.kv similarity index 100% rename from zbarcam/zbarcam.kv rename to src/kivy_garden/zbarcam/zbarcam.kv diff --git a/zbarcam/zbarcam.py b/src/kivy_garden/zbarcam/zbarcam.py similarity index 79% rename from zbarcam/zbarcam.py rename to src/kivy_garden/zbarcam/zbarcam.py index cc89198..c0d175b 100644 --- a/zbarcam/zbarcam.py +++ b/src/kivy_garden/zbarcam/zbarcam.py @@ -2,7 +2,6 @@ from collections import namedtuple import PIL -from kivy.app import App from kivy.clock import Clock from kivy.lang import Builder from kivy.properties import ListProperty @@ -91,13 +90,12 @@ def _on_texture(self, instance): def _detect_qrcode_frame(cls, texture, code_types): image_data = texture.pixels size = texture.size - fmt = texture.colorfmt.upper() - # PIL doesn't support BGRA but IOS uses BGRA for the camera - # if BGRA is detected it will switch to RGBA, color will be off - # but we don't care as it's just looking for barcodes - if cls.is_ios() and fmt == 'BGRA': - fmt = 'RGBA' - pil_image = PIL.Image.frombytes(mode=fmt, size=size, data=image_data) + # Fix for mode mismatch between texture.colorfmt and data returned by + # texture.pixels. texture.pixels always returns RGBA, so that should + # be passed to PIL no matter what texture.colorfmt returns. refs: + # https://github.com/AndreMiras/garden.zbarcam/issues/41 + pil_image = PIL.Image.frombytes(mode='RGBA', size=size, + data=image_data) pil_image = cls._fix_android_image(pil_image) symbols = [] codes = pyzbar.decode(pil_image, symbols=code_types) @@ -123,27 +121,3 @@ def is_android(): @staticmethod def is_ios(): return platform == 'ios' - - -DEMO_APP_KV_LANG = """ -#:import ZBarSymbol pyzbar.pyzbar.ZBarSymbol -BoxLayout: - orientation: 'vertical' - ZBarCam: - id: zbarcam - code_types: ZBarSymbol.QRCODE, ZBarSymbol.EAN13 - Label: - size_hint: None, None - size: self.texture_size[0], 50 - text: ', '.join([str(symbol.data) for symbol in zbarcam.symbols]) -""" - - -class DemoApp(App): - - def build(self): - return Builder.load_string(DEMO_APP_KV_LANG) - - -if __name__ == '__main__': - DemoApp().run() diff --git a/src/main.py b/src/main.py new file mode 100755 index 0000000..6db2c13 --- /dev/null +++ b/src/main.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +""" +This demo can be ran from the project root directory via: +```sh +python src/main.py +``` +It can also be ran via p4a/buildozer. +""" +from kivy.app import App +from kivy.lang import Builder + +DEMO_APP_KV_LANG = """ +#:import ZBarCam kivy_garden.zbarcam.ZBarCam +#:import ZBarSymbol pyzbar.pyzbar.ZBarSymbol +BoxLayout: + orientation: 'vertical' + ZBarCam: + id: zbarcam + # optional, by default checks all types + code_types: ZBarSymbol.QRCODE, ZBarSymbol.EAN13 + Label: + size_hint: None, None + size: self.texture_size[0], 50 + text: ', '.join([str(symbol.data) for symbol in zbarcam.symbols]) +""" + + +class DemoApp(App): + + def build(self): + return Builder.load_string(DEMO_APP_KV_LANG) + + +if __name__ == '__main__': + DemoApp().run() diff --git a/tests/test_zbarcam.py b/tests/test_zbarcam.py index 62ff679..2ec73cd 100644 --- a/tests/test_zbarcam.py +++ b/tests/test_zbarcam.py @@ -5,7 +5,7 @@ from kivy.base import EventLoop from kivy.core.image import Image -from zbarcam import ZBarCam +from kivy_garden.zbarcam import ZBarCam FIXTURE_DIR = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'fixtures') @@ -49,8 +49,12 @@ def test_detect_qrcode_frame_one_qrcode_one_ean(self): texture = Image(fixture_path).texture code_types = self.zbarcam.code_types symbols = self.zbarcam._detect_qrcode_frame(texture, code_types) - # currently detects no codes, but that's a bug - self.assertEqual(symbols, []) + self.assertEqual( + symbols, [ + ZBarCam.Symbol(type='QRCODE', data=b'zbarlight test qr code'), + ZBarCam.Symbol(type='UPCA', data=b'012345678905') + ] + ) def test_detect_qrcode_frame_two_qrcodes(self): """ diff --git a/tests/ui/test_zbarcam_ui.py b/tests/ui/test_zbarcam_ui.py index ae4c349..7d45060 100644 --- a/tests/ui/test_zbarcam_ui.py +++ b/tests/ui/test_zbarcam_ui.py @@ -4,7 +4,8 @@ from functools import partial import mock from kivy.clock import Clock -from zbarcam.zbarcam import DemoApp, ZBarCam +from kivy_garden.zbarcam.main import DemoApp +from kivy_garden.zbarcam.zbarcam import ZBarCam class UITestCase(unittest.TestCase): diff --git a/tox.ini b/tox.ini index 1682167..810095d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = pep8,isort-check,py36 +envlist = pep8,isort-check,py36,py37 # no setup.py to be ran skipsdist = True # trick to enable pre-installation of Cython @@ -8,10 +8,12 @@ indexserver = preinstall = https://pypi.python.org/simple [testenv] -setenv = KIVY_UNITTEST = 1 +setenv = + KIVY_UNITTEST = 1 + PYTHONPATH = {toxinidir}/src/ passenv = DISPLAY deps = - :preinstall: Cython==0.26.1 + :preinstall: Cython==0.28.6 -r{toxinidir}/requirements/requirements.txt -r{toxinidir}/requirements/test_requirements.txt commands = pytest --ignore tests/ui/ tests/ @@ -19,10 +21,10 @@ commands = pytest --ignore tests/ui/ tests/ [testenv:pep8] deps = -r{toxinidir}/requirements/test_requirements.txt -commands = flake8 zbarcam/ tests/ +commands = flake8 kivy_garden/ tests/ setup.py setup_meta.py [testenv:isort-check] deps = -r{toxinidir}/requirements/test_requirements.txt commands = - isort --check-only --recursive --diff zbarcam/ tests/ + isort --check-only --recursive --diff kivy_garden/ tests/ setup.py setup_meta.py diff --git a/zbarcam/__init__.py b/zbarcam/__init__.py deleted file mode 100644 index 11ad3bd..0000000 --- a/zbarcam/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .zbarcam import ZBarCam # noqa diff --git a/zbarcam/version.py b/zbarcam/version.py deleted file mode 100644 index b9801a0..0000000 --- a/zbarcam/version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = '2019.0303'