diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000000..3fadb19095 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,21 @@ +changelog: + exclude: + authors: + - pre-commit-ci + labels: + - no-changelog-entry-needed + - skip-changelog + + categories: + - title: New Features + labels: + - enhancement + - title: Bug Fixes + labels: + - bug + - title: Documentation + labels: + - documentation + - title: Other Changes + labels: + - "*" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5290129fe0..9ee4cc6178 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,53 +1,32 @@ name: Run tests -on: [push, pull_request] +on: + push: + pull_request: jobs: tests: - name: ${{ matrix.name}} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - python-version: 3.9 - name: Python 3.9 with minimal dependencies - toxenv: py39-test - - os: ubuntu-latest - python-version: 3.8 - name: Python 3.8 with minimal dependencies - toxenv: py38-test - - os: ubuntu-latest - python-version: 3.7 - name: Python 3.7 with minimal dependencies - toxenv: py37-test - - os: ubuntu-latest - python-version: 3.9 - name: Python 3.9, all non-visualization dependencies, and dev versions of key dependencies - toxenv: py39-test-novis-dev - - os: windows-latest - python-version: 3.9 - name: Python 3.9, all dependencies, and dev versions of key dependencies on Windows - toxenv: py39-test-all-dev - - os: ubuntu-latest - python-version: 3.9 - name: Documentation - toxenv: build_docs - - 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 testing dependencies - run: python -m pip install tox codecov - - name: Run tests with ${{ matrix.name }} - if: ${{ contains(matrix.toxenv,'-cov') }} - run: tox -v -e ${{ matrix.toxenv }} - - name: Upload coverage to codecov - if: ${{ contains(matrix.toxenv,'-cov') }} - uses: codecov/codecov-action@v1.0.13 - with: - file: ./coverage.xml + uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 + with: + display: true + libraries: | + apt: + - '^libxcb.*-dev' + - libxkbcommon-x11-dev + - libegl1-mesa + envs: | + - linux: py38-test-oldestdeps + - linux: py39-test + - linux: py310-test-viz + - linux: py311-test-alldeps + - linux: py312-test-devdeps + - macos: py38-test-oldestdeps + - macos: py39-test + - macos: py310-test-viz + - macos: py311-test-alldeps + - macos: py312-test-devdeps + - windows: py38-test-oldestdeps + - windows: py39-test + - windows: py310-test-viz + - windows: py311-test-alldeps + - windows: py312-test-devdeps diff --git a/.github/workflows/update-changelog.yaml b/.github/workflows/update-changelog.yaml new file mode 100644 index 0000000000..5e4e1c474c --- /dev/null +++ b/.github/workflows/update-changelog.yaml @@ -0,0 +1,33 @@ +# This workflow takes the GitHub release notes and updates the changelog on the +# main branch with the body of the release notes, thereby keeping a log in +# the git repo of the changes. + +name: "Update Changelog" + +on: + release: + types: [released] + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: main + + - name: Update Changelog + uses: stefanzweifel/changelog-updater-action@v1 + with: + release-notes: ${{ github.event.release.body }} + latest-version: ${{ github.event.release.name }} + path-to-changelog: CHANGES.md + + - name: Commit updated Changelog + uses: stefanzweifel/git-auto-commit-action@v4 + with: + branch: main + commit_message: Update CHANGELOG + file_pattern: CHANGES.md diff --git a/.gitignore b/.gitignore index 55e2af0510..070f29bf27 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ distribute-*.tar.gz # Mac OSX .DS_Store + +.tmp diff --git a/CHANGES b/CHANGES deleted file mode 100644 index 877bab8d10..0000000000 --- a/CHANGES +++ /dev/null @@ -1,16 +0,0 @@ -v0.2 (2020-04-19) ------------------ - -- Update package infrastructure. [#93, #96] - -- Fix compatibility with the latest versions of Python and Matplotlib. [#89, #95] - -- Added ``return_area`` option for ``extract_poly_slices``. [#59] - -- Fix error that occurred when WCS did not have a PC matrix defined. [#90] - - -v0.1 (2018-01-26) ----------------- - -- First official release. diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000000..0a01c77cfb --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,23 @@ +# v0.3 (2022-03-31) + +## What's Changed + +* Plot docs and convenience tools by @keflavich in https://github.com/radio-astro-tools/pvextractor/pull/102 +* Add gh actions by @keflavich in https://github.com/radio-astro-tools/pvextractor/pull/103 +* try to fix grid by removing 'novis' by @keflavich in https://github.com/radio-astro-tools/pvextractor/pull/105 +* allow DaskSpectralCube, etc. to work by @keflavich in https://github.com/radio-astro-tools/pvextractor/pull/99 + +**Full Changelog**: https://github.com/radio-astro-tools/pvextractor/compare/v0.2...v0.3 + +# v0.2 (2020-04-19) + +* Update package infrastructure. #93, #96 +* Fix compatibility with the latest versions of Python and Matplotlib. #89, #95 +* Added `return_area` option for `extract_poly_slices`. #59 +* Fix error that occurred when WCS did not have a PC matrix defined. #90 + +# v0.1 (2018-01-26) + +* First official release. + + diff --git a/pvextractor/__init__.py b/pvextractor/__init__.py index f7835a8fdc..8ac7637a87 100644 --- a/pvextractor/__init__.py +++ b/pvextractor/__init__.py @@ -1,19 +1,7 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst -""" -This is an Astropy affiliated package. -""" - -# Affiliated packages may add whatever they like to this file, but -# should keep this content at the top. -# ---------------------------------------------------------------------------- -from ._astropy_init import * -# ---------------------------------------------------------------------------- - -if not _ASTROPY_SETUP_: - - from . import utils - from .pvextractor import extract_pv_slice - from .utils.wcs_slicing import slice_wcs - from .geometry import Path, PathFromCenter - from .pvregions import paths_from_regfile +from . import utils +from .pvextractor import extract_pv_slice +from .utils.wcs_slicing import slice_wcs +from .geometry import Path, PathFromCenter +from .pvregions import paths_from_regfile diff --git a/pvextractor/_astropy_init.py b/pvextractor/_astropy_init.py deleted file mode 100644 index 2dffe8fd04..0000000000 --- a/pvextractor/_astropy_init.py +++ /dev/null @@ -1,52 +0,0 @@ -# Licensed under a 3-clause BSD style license - see LICENSE.rst - -__all__ = ['__version__'] - -# this indicates whether or not we are in the package's setup.py -try: - _ASTROPY_SETUP_ -except NameError: - import builtins - builtins._ASTROPY_SETUP_ = False - -try: - from .version import version as __version__ -except ImportError: - __version__ = '' - - -if not _ASTROPY_SETUP_: # noqa - import os - from warnings import warn - from astropy.config.configuration import ( - update_default_config, - ConfigurationDefaultMissingError, - ConfigurationDefaultMissingWarning) - - # Create the test function for self test - from astropy.tests.runner import TestRunner - test = TestRunner.make_test_runner_in(os.path.dirname(__file__)) - test.__test__ = False - __all__ += ['test'] - - # add these here so we only need to cleanup the namespace at the end - config_dir = None - - if not os.environ.get('ASTROPY_SKIP_CONFIG_UPDATE', False): - config_dir = os.path.dirname(__file__) - config_template = os.path.join(config_dir, __package__ + ".cfg") - if os.path.isfile(config_template): - try: - update_default_config( - __package__, config_dir, version=__version__) - except TypeError as orig_error: - try: - update_default_config(__package__, config_dir) - except ConfigurationDefaultMissingError as e: - wmsg = (e.args[0] + - " Cannot install default profile. If you are " - "importing from source, this is expected.") - warn(ConfigurationDefaultMissingWarning(wmsg)) - del e - except Exception: - raise orig_error diff --git a/pvextractor/conftest.py b/pvextractor/conftest.py index b54888a041..c0576c6b2f 100644 --- a/pvextractor/conftest.py +++ b/pvextractor/conftest.py @@ -20,13 +20,6 @@ def pytest_configure(config): PYTEST_HEADER_MODULES['regions'] = 'regions' PYTEST_HEADER_MODULES['APLpy'] = 'aplpy' - -from astropy.tests.helper import enable_deprecations_as_exceptions - -## Uncomment the following line to treat all DeprecationWarnings as -## exceptions -# enable_deprecations_as_exceptions() - app = None diff --git a/pvextractor/tests/test_gui.py b/pvextractor/tests/test_gui.py index 7ac28efd0e..a50d18bd11 100644 --- a/pvextractor/tests/test_gui.py +++ b/pvextractor/tests/test_gui.py @@ -1,23 +1,47 @@ -from distutils.version import LooseVersion +from packaging.version import Version import pytest import numpy as np import matplotlib +from matplotlib.backend_bases import KeyEvent, MouseEvent from ..gui import PVSlicer -from .test_slicer import make_test_hdu +from .test_slicer import make_test_hdu, make_test_fits_file -MPL_LT_31 = LooseVersion(matplotlib.__version__) < LooseVersion('3.1') +MATPLOTLIB_GE_36 = Version(matplotlib.__version__) >= Version('3.6') + +def key_press_event(canvas, *event): + if MATPLOTLIB_GE_36: + canvas.callbacks.process('key_press_event', + KeyEvent('key_press_event', canvas, *event)) + else: + canvas.key_press_event(*event) + + +def button_press_event(canvas, *event): + if MATPLOTLIB_GE_36: + canvas.callbacks.process('button_press_event', + MouseEvent('button_press_event', canvas, *event)) + else: + canvas.button_press_event(*event) + + +def motion_notify_event(canvas, *event): + if MATPLOTLIB_GE_36: + canvas.callbacks.process('motion_notify_event', + MouseEvent('motion_notify_event', canvas, *event)) + else: + canvas.motion_notify_event(*event) def test_gui(): - # This tests currently segfaults with Matplotlib 3.1 and later + pytest.importorskip('PyQt6') hdu = make_test_hdu() - pv = PVSlicer(hdu, clim=(-0.02, 2), backend='Qt5Agg') + pv = PVSlicer(hdu, clim=(-0.02, 2), backend='QtAgg') pv.show(block=False) xy_data = np.array([[0.0, 0.1, 0.5, 1.0, 0.5], @@ -26,12 +50,12 @@ def test_gui(): x, y = pv.ax1.transData.transform(xy_data).T for i in range(len(x)): - pv.fig.canvas.motion_notify_event(x[i], y[i]) - pv.fig.canvas.button_press_event(x[i], y[i], 1) + motion_notify_event(pv.fig.canvas, x[i], y[i]) + button_press_event(pv.fig.canvas, x[i], y[i], 1) - pv.fig.canvas.key_press_event('enter') - pv.fig.canvas.motion_notify_event(x[-1] - 20, y[-1]) - pv.fig.canvas.button_press_event(x[-1] - 20, y[-1], 1) + key_press_event(pv.fig.canvas, 'enter') + motion_notify_event(pv.fig.canvas, x[-1] - 20, y[-1]) + button_press_event(pv.fig.canvas, x[-1] - 20, y[-1], 1) pv.fig.canvas.draw() @@ -40,14 +64,13 @@ def test_gui(): pv.close() -def test_gui_from_fits_filename(): +def test_gui_from_fits_filename(tmp_path): - # This tests currently segfaults with Matplotlib 3.1 and later + pytest.importorskip('PyQt6') - fits_filename = make_test_fits_file() + fits_filename = make_test_fits_file(tmp_path) - pv = PVSlicer(fits_filename, clim=(-0.02, 2), backend='Qt5Agg') + pv = PVSlicer(fits_filename, clim=(-0.02, 2), backend='QtAgg') pv.show(block=False) pv.close() - diff --git a/pvextractor/tests/test_slicer.py b/pvextractor/tests/test_slicer.py index 24f5218b4d..e4d1caf731 100644 --- a/pvextractor/tests/test_slicer.py +++ b/pvextractor/tests/test_slicer.py @@ -86,9 +86,9 @@ def make_test_hdu(): return hdu -def make_test_fits_file(): +def make_test_fits_file(tmp_path): hdu = make_test_hdu() - filename = 'example.fits' + filename = tmp_path / 'example.fits' hdu.writeto(filename) return filename diff --git a/setup.cfg b/setup.cfg index 0dc7353546..ec9c007468 100644 --- a/setup.cfg +++ b/setup.cfg @@ -14,19 +14,19 @@ github_project = radio-astro-tools/pvextractor [options] zip_safe = False packages = find: -python_requires = >=3.6 +python_requires = >=3.8 setup_requires = setuptools_scm install_requires = - astropy - matplotlib>=2.0 - scipy - qtpy - spectral-cube + numpy>=1.22 + astropy>=5.0 + matplotlib>=3.5 + scipy>=1.8 + qtpy>=2.0 + spectral-cube>=0.4 [options.extras_require] test = pytest-astropy - PyQt5==5.13.* docs = sphinx-astropy @@ -40,6 +40,9 @@ doctest_plus = enabled text_file_format = rst addopts = --doctest-rst open_files_ignore = "*.ttf" +filterwarnings = + error::DeprecationWarning + ignore:`np.float` is a deprecated alias for the builtin [coverage:run] omit = diff --git a/tox.ini b/tox.ini index 817a431b94..ed36f3c0a9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,14 @@ [tox] envlist = - py{36,37,38,39}-test{,-oldestdeps,-alldeps,-devdeps,-novis,-cov} + py{36,37,38,39}-test{,-oldestdeps,-alldeps,-devdeps,-viz,-cov} build_docs codestyle requires = setuptools >= 30.3.0 pip >= 19.3.1 isolated_build = true +indexserver = + devdeps: PIP_EXTRA_INDEX_URL = https://pypi.anaconda.org/astropy/simple https://pypi.anaconda.org/scientific-python-nightly-wheels/simple [testenv] passenv = @@ -20,9 +22,16 @@ changedir = description = run tests with pytest deps = - oldestdeps: matplotlib==2.0.* - devdeps: git+https://github.com/radio-astro-tools/spectral-cube#egg=spectral-cube - devdeps: git+https://github.com/astropy/astropy#egg=astropy + oldestdeps: numpy==1.22.* + oldestdeps: astropy==5.0.* + oldestdeps: matplotlib==3.5.* + oldestdeps: scipy==1.8.* + oldestdeps: qtpy==2.0.* + oldestdeps: spectral-cube==0.4.* + devdeps: numpy>=0.0.dev0 + devdeps: astropy>=0.0.dev0 + devdeps: spectral-cube @ git+https://github.com/radio-astro-tools/spectral-cube + viz: PyQt6 extras = test alldeps: all