diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..cb9ae760 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,94 @@ +name: Test + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.experimental }} + timeout-minutes: 15 + name: ${{ matrix.name }} (${{ matrix.os }}, ${{ matrix.python-version }}) + strategy: + fail-fast: false + matrix: + os: [ubuntu-18.04, macos-10.15, windows-2016] + python-version: [3.7, 3.8] + tox_env: [py-orange-released] + experimental: [false] + name: [Released] + include: + - os: windows-2019 + python-version: 3.8 + tox_env: py-orange-released + experimental: true + name: Windows10 + - os: macos-11.0 + python-version: 3.8 + tox_env: py-orange-released + experimental: true + name: Big Sur + + - os: windows-2016 + python-version: 3.7 + tox_env: py-orange-oldest + experimental: false + name: Oldest + - os: macos-10.15 + python-version: 3.7 + tox_env: py-orange-oldest + name: Oldest + experimental: false + - os: ubuntu-18.04 + python-version: 3.7 + tox_env: py-orange-oldest + name: Oldest + experimental: false + + - os: windows-2016 + python-version: 3.8 + tox_env: py-orange-latest + experimental: false + name: Latest + - os: macos-10.15 + python-version: 3.8 + tox_env: py-orange-latest + experimental: false + name: Latest + - os: ubuntu-18.04 + python-version: 3.8 + tox_env: py-orange-latest + experimental: false + name: Latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade tox tox-pip-version + + - name: Test with Tox + run: | + tox -e ${{ matrix.tox_env }} + env: + QT_QPA_PLATFORM: offscreen + + - name: Upload code coverage + if: | + matrix.python-version == '3.8' && + matrix.os == 'ubuntu-18.04' && + matrix.tox_env == 'py-orange-released' + run: | + pip install codecov + codecov diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ce4c3f11..00000000 --- a/.travis.yml +++ /dev/null @@ -1,58 +0,0 @@ -language: python - -sudo: false # use container-based infrastructure -dist: xenial - - -addons: - apt: - packages: - - libxkbcommon-x11-0 # for PyQt 5.12 - - libxcb-icccm4 - - libxcb-image0 - - libxcb-keysyms1 - - libxcb-randr0 - - libxcb-render-util0 - - libxcb-xinerama0 - - -matrix: - include: - - python: '3.7' - env: ORANGE="3.25.1" - - - python: '3.6' - env: ORANGE="release" - - - python: '3.7' - env: ORANGE="release" - - - python: '3.7' - env: ORANGE="master" - - -cache: - apt: true - pip: true - ccache: true - directories: - - $TRAVIS_BUILD_DIR/pyqt - -before_install: - - pip install -U pip wheel setuptools - - pip install codecov - -install: - - pip install sip pyqt5==5.11.* - - source $TRAVIS_BUILD_DIR/.travis/install_orange.sh - - pip install -e . - # todo: orange cache dir doesn't get created at installation - - mkdir -p $(python -c 'from Orange.misc.environ import cache_dir; print(cache_dir())') - -script: - # Screen must be at least 24bpp (see https://github.com/pytest-dev/pytest-qt/issues/35) - - XVFBARGS="-screen 0 1280x1024x24" - - catchsegv xvfb-run -a -s "$XVFBARGS" coverage run -m unittest discover -v - -after_success: - - codecov diff --git a/.travis/install_orange.sh b/.travis/install_orange.sh deleted file mode 100644 index 783052e2..00000000 --- a/.travis/install_orange.sh +++ /dev/null @@ -1,14 +0,0 @@ -if [ $ORANGE == "release" ]; then - echo "Orange: Skipping separate Orange install" - return 0 -fi - -if [ $ORANGE == "master" ]; then - echo "Orange: from git master" - pip install https://github.com/biolab/orange3/archive/master.zip - return $?; -fi - -PACKAGE="orange3==$ORANGE" -echo "Orange: installing version $PACKAGE" -pip install $PACKAGE diff --git a/.travis/install_pyqt.sh b/.travis/install_pyqt.sh deleted file mode 100644 index 3db5bfdd..00000000 --- a/.travis/install_pyqt.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -PYQT=$TRAVIS_BUILD_DIR/pyqt - -SIP_VERSION=4.16.9 -PYQT_VERSION=4.11.4 - -if [ ! "$(ls $PYQT)" ]; then - mkdir -p $PYQT - cd $PYQT - - wget -O sip.tar.gz http://sourceforge.net/projects/pyqt/files/sip/sip-$SIP_VERSION/sip-$SIP_VERSION.tar.gz - mkdir -p sip - tar xzf sip.tar.gz -C sip --strip-component=1 - - wget -O PyQt.tar.gz http://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-$PYQT_VERSION/PyQt-x11-gpl-$PYQT_VERSION.tar.gz - mkdir -p PyQt - tar xzf PyQt.tar.gz -C PyQt --strip-components=1 - - cd $PYQT/sip - python configure.py -e $PYQT/include - make - make install - - cd $PYQT/PyQt - pwd - python configure.py --confirm-license --no-designer-plugin --concatenate - make -fi - -cd $PYQT/sip -make install - -cd $PYQT/PyQt -make install - -cd ../.. - -pip install pyqtgraph diff --git a/MANIFEST.in b/MANIFEST.in index 8bb508aa..5c93f70d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,4 @@ +recursive-include doc Makefile *.bat *.json *.md *.png *.py *.rst recursive-include orangecontrib/imageanalytics *.svg *.png *.jpg -include requirements.txt -include README.md -include LICENSE.txt -include about.md -include *.py *.txt +include *.py *.txt *.pypi *.md *.yml *.ini .coveragerc diff --git a/orangecontrib/imageanalytics/widgets/owsaveimages.py b/orangecontrib/imageanalytics/widgets/owsaveimages.py index 5eefa605..59cf2975 100644 --- a/orangecontrib/imageanalytics/widgets/owsaveimages.py +++ b/orangecontrib/imageanalytics/widgets/owsaveimages.py @@ -7,7 +7,7 @@ from AnyQt.QtWidgets import QFileDialog, QGridLayout, QMessageBox -from AnyQt.QtCore import Qt +from AnyQt.QtCore import Qt, QSize from Orange.data.table import Table from Orange.widgets import gui, widget @@ -396,6 +396,9 @@ def onDeleteWidget(self): self.shutdown() super().onDeleteWidget() + def sizeHint(self): + return QSize(500, 450) + if __name__ == "__main__": # pragma: no cover WidgetPreview(OWSaveImages).run( diff --git a/orangecontrib/imageanalytics/widgets/tests/test_owimageembedding.py b/orangecontrib/imageanalytics/widgets/tests/test_owimageembedding.py index 1fb97146..a09fab87 100644 --- a/orangecontrib/imageanalytics/widgets/tests/test_owimageembedding.py +++ b/orangecontrib/imageanalytics/widgets/tests/test_owimageembedding.py @@ -80,7 +80,7 @@ def test_skipped_images(self): table[:, "Images"] = "http://www.none.com/image.jpg" self.send_signal(self.widget.Inputs.images, table) - skipped = self.get_output(self.widget.Outputs.skipped_images) + skipped = self.get_output(self.widget.Outputs.skipped_images, wait=10000) self.assertIsInstance(skipped, Table) self.assertEqual(len(skipped), len(table)) @@ -123,7 +123,7 @@ def test_embedder_changed(self): self.assertEqual(w.cb_embedder.currentText(), "VGG-19") - output = self.get_output(self.widget.Outputs.embeddings) + output = self.get_output(self.widget.Outputs.embeddings, wait=10000) self.assertIsInstance(output, Table) self.assertEqual(len(output), len(table)) # 4096 shows that output is really by VGG-19 diff --git a/orangecontrib/imageanalytics/widgets/tests/test_owsaveimages.py b/orangecontrib/imageanalytics/widgets/tests/test_owsaveimages.py index da11f9ad..dfae13ec 100644 --- a/orangecontrib/imageanalytics/widgets/tests/test_owsaveimages.py +++ b/orangecontrib/imageanalytics/widgets/tests/test_owsaveimages.py @@ -16,10 +16,6 @@ from orangecontrib.imageanalytics.widgets.owsaveimages import OWSaveImages, \ SUPPORTED_FILE_FORMATS -# Yay, MS Windows! -# This is not the proper general way to do it, but it's simplest and sufficient -# Short name is suitable for the function's purpose - def _raise_error(*args): raise IOError @@ -242,23 +238,24 @@ def test_scale(self): # test image size, since size not set the original image size is used image_path = os.path.join(dirname, "Day7", "D7-Series037_z06.png") - im = Image.open(image_path) - size = im.size + with Image.open(image_path) as im: + size = im.size self.assertTupleEqual((512, 512), size) # enable scale self.widget.controls.use_scale.setChecked(True) self.wait_until_finished() - im = Image.open(image_path) - size = im.size + with Image.open(image_path) as im: + size = im.size + # one of the scale is used, non of the preset scale is (512, 512) self.assertFalse((512, 512) == size) # change scale simulate.combobox_activate_index(self.widget.controls.scale_index, 1) self.wait_until_finished() - im = Image.open(image_path) - size = im.size + with Image.open(image_path) as im: + size = im.size # second option is squeezenet with scale 227x227 self.assertTupleEqual((227, 227), size) @@ -318,6 +315,9 @@ def test_format(self): "D7-0503-12-2-bone-inj-d7-3-0020-m1.{}".format(f)) self.assertTrue(os.path.isfile(image_path)) + def test_minimum_size(self): + pass + @unittest.skipUnless(sys.platform in ("darwin", "win32"), "Test for native dialog on Windows and macOS") diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..9787c3bd --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 4750b051..6684937b 100755 --- a/setup.py +++ b/setup.py @@ -68,11 +68,11 @@ def include_documentation(local_dir, install_dir): global DATA_FILES - if 'bdist_wheel' in sys.argv and not path.exists(local_dir): - print("Directory '{}' does not exist. " - "Please build documentation before running bdist_wheel." - .format(path.abspath(local_dir))) - sys.exit(0) + # if 'bdist_wheel' in sys.argv and not path.exists(local_dir): + # print("Directory '{}' does not exist. " + # "Please build documentation before running bdist_wheel." + # .format(path.abspath(local_dir))) + # sys.exit(0) doc_files = [] for dirpath, dirs, files in walk(local_dir): doc_files.append((dirpath.replace(local_dir, install_dir), @@ -98,6 +98,11 @@ def include_documentation(local_dir, install_dir): keywords=KEYWORDS, classifiers=CLASSIFIERS, install_requires=INSTALL_REQUIRES, + extras_require={ + 'test': [ + 'coverage', + ], + }, namespace_packages=['orangecontrib'], entry_points=ENTRY_POINTS, ) diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..579387db --- /dev/null +++ b/tox.ini @@ -0,0 +1,47 @@ +[tox] +envlist = + py{37,38}-orange-{oldest, latest, released} +skip_missing_interpreters = true +isolated_build = true +toxworkdir={env:TOX_WORK_DIR:.tox} + +[testenv] +# must use latest pip (version 20.3.1 enables Big Sur support - https://github.com/pypa/pip/issues/9138) +pip_version = pip +extras = test +passenv = * +# we MUST changedir to avoid installed being shadowed by working dir +# https://github.com/tox-dev/tox/issues/54 +# https://github.com/tox-dev/tox/issues/514 +changedir = + {envsitepackagesdir} +setenv = + # Raise deprecations as errors in our tests + ORANGE_DEPRECATIONS_ERROR=y + # Need this otherwise unittest installs a warning filter that overrides + # our desire to have OrangeDeprecationWarnings raised + PYTHONWARNINGS=module + # set coverage output and project config + COVERAGE_FILE = {toxinidir}/.coverage + COVERAGE_RCFILE = {toxinidir}/.coveragerc +deps = + pyqt5==5.12.* + pyqtwebengine==5.12.* + oldest: scikit-learn~=0.22.0 + oldest: orange3==3.25.0 + # Use newer canvas-core and widget-base to avoid segfaults on windows + oldest: orange-canvas-core==0.1.9 ; sys_platform != 'win32' + oldest: orange-canvas-core==0.1.15 ; sys_platform == 'win32' + oldest: orange-widget-base==4.5.0 ; sys_platform != 'win32' + oldest: orange-widget-base==4.9.0 ; sys_platform == 'win32' + latest: git+git://github.com/biolab/orange3.git#egg=orange3 + latest: git+git://github.com/biolab/orange-canvas-core.git#egg=orange-canvas-core + latest: git+git://github.com/biolab/orange-widget-base.git#egg=orange-widget-base +commands_pre = + # Verify installed packages have compatible dependencies + pip check + # freeze environment + pip freeze +commands = + coverage run -m unittest discover -v --start-directory orangecontrib/imageanalytics + coverage report