diff --git a/.github/workflows/codestyle.yaml b/.github/workflows/codestyle.yaml index 2e14de431..8dd0fa399 100644 --- a/.github/workflows/codestyle.yaml +++ b/.github/workflows/codestyle.yaml @@ -4,18 +4,22 @@ on: branches: - main - module/* + - 'v*x' + tags: + - 'v*' pull_request: branches: - main - module/* + - 'v*x' jobs: flake8: runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install Python 3.x - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.x - name: Install Dependencies diff --git a/.github/workflows/compatibility.yaml b/.github/workflows/compatibility.yaml index 426ad4152..984ac7487 100644 --- a/.github/workflows/compatibility.yaml +++ b/.github/workflows/compatibility.yaml @@ -9,12 +9,12 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - python: [3.9] - toxenv: [py39-test, py39-test-dev] + python: ['3.12'] + toxenv: [py312-test, py312-test-dev] release: [main, latest] steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - if: matrix.release != 'main' @@ -22,7 +22,7 @@ jobs: run: | git checkout tags/$(curl -s https://api.github.com/repos/skypyproject/skypy/releases/${{ matrix.release }} | python -c "import sys, json; print(json.load(sys.stdin)['tag_name'])") - name: Install Python ${{ matrix.python }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install Dependencies diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 51b2b3704..2800cb6af 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -4,10 +4,14 @@ on: branches: - main - module/* + - 'v*x' + tags: + - 'v*' pull_request: branches: - main - module/* + - 'v*x' jobs: test: name: ${{ matrix.name }} @@ -19,32 +23,32 @@ jobs: - name: latest supported versions os: ubuntu-latest - python: 3.9 - toxenv: py39-test-all-latest-cov + python: '3.12' + toxenv: py312-test-all-latest-cov toxposargs: --cov-report=xml:${GITHUB_WORKSPACE}/coverage.xml - name: oldest supported versions os: ubuntu-latest - python: 3.6 - toxenv: py36-test-oldest + python: '3.8' + toxenv: py38-test-oldest - name: macOS latest supported os: macos-latest - python: 3.9 - toxenv: py39-test-latest + python: '3.12' + toxenv: py312-test-latest - name: Windows latest supported os: windows-latest - python: 3.9 - toxenv: py39-test-latest + python: '3.12' + toxenv: py312-test-latest steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install Python ${{ matrix.python }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install Dependencies @@ -55,4 +59,4 @@ jobs: tox -e ${{ matrix.toxenv }} ${{ matrix.toxargs }} -- ${{ matrix.toxposargs }} - if: contains(matrix.toxenv, '-cov') name: Report Coverage - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 diff --git a/.readthedocs.yml b/.readthedocs.yml index 432dbdea7..d6ba8088d 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -3,7 +3,7 @@ version: 2 build: os: ubuntu-20.04 tools: - python: '3.7' + python: '3.8' apt_packages: - graphviz diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 6083b052d..fddce440d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -129,7 +129,7 @@ Before your pull request can be merged into the codebase, it will be reviewed by General Guidelines ^^^^^^^^^^^^^^^^^^ -- SkyPy is compatible with Python>=3.6 (see `setup.cfg `_). SkyPy *does not* support backwards compatibility with Python 2.x; `six`, `__future__` and `2to3` should not be used. +- SkyPy is compatible with Python>=3.8 (see `setup.cfg `_). SkyPy *does not* support backwards compatibility with Python 2.x; `six`, `__future__` and `2to3` should not be used. - All contributions should follow the `PEP8 Style Guide for Python Code `_. We recommend using `flake8 `__ to check your code for PEP8 compliance. - Importing SkyPy should only depend on having `NumPy `_, `SciPy `_ and `Astropy `__ installed. - Code is grouped into submodules based on broad science areas e.g. `galaxies `_. There is also a `utils `_ submodule for general utility functions. diff --git a/docs/install.rst b/docs/install.rst index 4a9cb3c29..7203271f1 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -40,7 +40,7 @@ can be installed directly from GitHub using a recent version of pip: Dependencies ------------ -SkyPy is compatble with Python versions 3.6 or later on Ubuntu, macOS and +SkyPy is compatble with Python versions 3.8 or later on Ubuntu, macOS and Windows operating systems. It has the following core dependencies: - `astropy `__ diff --git a/examples/galaxies/plot_schechter.py b/examples/galaxies/plot_schechter.py index 48e14f59f..88c50420d 100644 --- a/examples/galaxies/plot_schechter.py +++ b/examples/galaxies/plot_schechter.py @@ -47,6 +47,7 @@ from astropy.units import Quantity from matplotlib import pyplot as plt import numpy as np +import scipy.integrate from skypy.galaxies import schechter_lf z_range = np.linspace(0.2, 1.0, 100) @@ -81,7 +82,7 @@ # SkyPy simulated galaxies z_mask = np.logical_and(redshift >= z_min, redshift < z_max) dV_dz = (cosmology.differential_comoving_volume(z) * sky_area).to_value('Mpc3') - dV = np.trapz(dV_dz, z) + dV = scipy.integrate.trapezoid(dV_dz, z) dM = (np.max(bins)-np.min(bins)) / (np.size(bins)-1) phi_skypy = np.histogram(magnitude[z_mask], bins=bins)[0] / dV / dM diff --git a/setup.cfg b/setup.cfg index d94b452fa..0235fd846 100644 --- a/setup.cfg +++ b/setup.cfg @@ -14,7 +14,7 @@ github_project = skypyproject/skypy [options] zip_safe = False packages = find: -python_requires = >=3.6 +python_requires = >=3.8 setup_requires = setuptools_scm install_requires = astropy>=4 diff --git a/skypy/conftest.py b/skypy/conftest.py index 672b2733d..482ddb89f 100644 --- a/skypy/conftest.py +++ b/skypy/conftest.py @@ -1,27 +1,29 @@ -# This file is used to configure the behavior of pytest when using the Astropy -# test infrastructure. It needs to live inside the package in order for it to -# get picked up when running the tests inside an interpreter using -# packagename.test +"""Configure Test Suite. -import os +This file is used to configure the behavior of pytest when using the Astropy +test infrastructure. It needs to live inside the package in order for it to +get picked up when running the tests inside an interpreter using +`{{ cookiecutter.module_name }}.test()`. + +""" -from astropy.version import version as astropy_version +import os -# For Astropy 3.0 and later, we can use the standalone pytest plugin -if astropy_version < '3.0': - from astropy.tests.pytest_plugins import * # noqa - del pytest_report_header +try: + from pytest_astropy_header.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS ASTROPY_HEADER = True -else: - try: - from pytest_astropy_header.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS - ASTROPY_HEADER = True - except ImportError: - ASTROPY_HEADER = False +except ImportError: + ASTROPY_HEADER = False def pytest_configure(config): + """Configure Pytest with Astropy. + Parameters + ---------- + config : pytest configuration + + """ if ASTROPY_HEADER: config.option.astropy_header = True @@ -34,16 +36,3 @@ def pytest_configure(config): from . import __version__ packagename = os.path.basename(os.path.dirname(__file__)) TESTED_VERSIONS[packagename] = __version__ - -# Uncomment the last two lines in this block to treat all DeprecationWarnings as -# exceptions. For Astropy v2.0 or later, there are 2 additional keywords, -# as follow (although default should work for most cases). -# To ignore some packages that produce deprecation warnings on import -# (in addition to 'compiler', 'scipy', 'pygments', 'ipykernel', and -# 'setuptools'), add: -# modules_to_ignore_on_import=['module_1', 'module_2'] -# To ignore some specific deprecation warning messages for Python version -# MAJOR.MINOR or later, add: -# warnings_to_ignore_by_pyver={(MAJOR, MINOR): ['Message to ignore']} -# from astropy.tests.helper import enable_deprecations_as_exceptions # noqa -# enable_deprecations_as_exceptions() diff --git a/skypy/galaxies/redshift.py b/skypy/galaxies/redshift.py index f048a3574..3173c63db 100644 --- a/skypy/galaxies/redshift.py +++ b/skypy/galaxies/redshift.py @@ -249,7 +249,7 @@ def redshifts_from_comoving_density(redshift, density, sky_area, cosmology, nois dN_dz *= density # integrate density to get expected number of galaxies - N = np.trapz(dN_dz, redshift) + N = scipy.integrate.trapezoid(dN_dz, redshift) # Poisson sample galaxy number if requested if noise: diff --git a/skypy/galaxies/tests/test_redshift.py b/skypy/galaxies/tests/test_redshift.py index d41e92ac9..c974bab31 100644 --- a/skypy/galaxies/tests/test_redshift.py +++ b/skypy/galaxies/tests/test_redshift.py @@ -1,5 +1,6 @@ import numpy as np import pytest +import scipy.integrate from scipy.stats import kstest @@ -38,7 +39,7 @@ def test_schechter_lf_redshift(): density *= (sky_area * cosmo.differential_comoving_volume(z)).to_value('Mpc3') # integrate total number - n_gal = np.trapz(density, z, axis=-1) + n_gal = scipy.integrate.trapezoid(density, z, axis=-1) # make sure noise-free sample has right size assert np.isclose(len(z_gal), n_gal, atol=1.0) @@ -85,7 +86,7 @@ def test_schechter_smf_redshift(): density *= (sky_area * cosmo.differential_comoving_volume(z)).to_value('Mpc3') # integrate total number - n_gal = np.trapz(density, z, axis=-1) + n_gal = scipy.integrate.trapezoid(density, z, axis=-1) # make sure noise-free sample has right size assert np.isclose(len(z_gal), n_gal, atol=1.0) diff --git a/skypy/galaxies/tests/test_stellar_mass.py b/skypy/galaxies/tests/test_stellar_mass.py index cb6679892..49acde131 100644 --- a/skypy/galaxies/tests/test_stellar_mass.py +++ b/skypy/galaxies/tests/test_stellar_mass.py @@ -49,7 +49,7 @@ def calc_cdf(m): mass_min = 10 ** 7 mass_max = 10 ** 13 pdf = calc_pdf(m, alpha, mass_star, mass_min, mass_max) - cdf = scipy.integrate.cumtrapz(pdf, m, initial=0) + cdf = scipy.integrate.cumulative_trapezoid(pdf, m, initial=0) cdf = cdf / cdf[-1] return cdf diff --git a/skypy/pipeline/scripts/skypy.py b/skypy/pipeline/scripts/skypy.py index 62319de34..6d723bcc4 100644 --- a/skypy/pipeline/scripts/skypy.py +++ b/skypy/pipeline/scripts/skypy.py @@ -48,4 +48,4 @@ def main(args=None): logger.exception(e) raise SystemExit(2) from e - return(0) + return 0 diff --git a/skypy/pipeline/tests/test_skypy.py b/skypy/pipeline/tests/test_skypy.py index f84a5ea55..14a66db83 100644 --- a/skypy/pipeline/tests/test_skypy.py +++ b/skypy/pipeline/tests/test_skypy.py @@ -58,7 +58,7 @@ def test_logging(capsys, tmp_path): output_filename = str(tmp_path / 'logging.fits') skypy.main([config_filename, output_filename]) out, err = capsys.readouterr() - assert(not err) + assert not err # Run again with increased verbosity and capture log. Force an exception by # not using the "--overwrite" flag when the output file already exists. @@ -78,19 +78,19 @@ def test_logging(capsys, tmp_path): # Check all jobs appear in the log for job in list(config) + list(tables) + columns: log_string = f"[INFO] skypy.pipeline: Generating {job}" - assert(log_string in err) + assert log_string in err # Check all functions appear in the log for f in functions: log_string = f"[INFO] skypy.pipeline: Calling {f.function.__name__}" - assert(log_string in err) + assert log_string in err # Check cosmology appears in the log if cosmology: - assert("[INFO] skypy.pipeline: Setting cosmology" in err) + assert "[INFO] skypy.pipeline: Setting cosmology" in err # Check writing output file is in the log - assert(f"[INFO] skypy: Writing {output_filename}" in err) + assert f"[INFO] skypy: Writing {output_filename}" in err # Check error for existing output file is in the log try: @@ -100,10 +100,10 @@ def test_logging(capsys, tmp_path): except ImportError: # Fallback on old error message from astropy v4.x error_string = f"[ERROR] skypy: File {output_filename!r} already exists." - assert(error_string in err) + assert error_string in err # Run again with decreased verbosity and check the log is empty with pytest.raises(SystemExit): skypy.main([config_filename, output_filename, '-qq']) out, err = capsys.readouterr() - assert(not err) + assert not err diff --git a/skypy/utils/photometry.py b/skypy/utils/photometry.py index 8e978e3ea..47de59178 100644 --- a/skypy/utils/photometry.py +++ b/skypy/utils/photometry.py @@ -128,7 +128,7 @@ def mag_ab(wavelength, spectrum, filters, *, redshift=None, coefficients=None, u = u.reshape(u.shape + (1,)*(nd_s+nd_f)) m = np.ascontiguousarray(m[n]) m += u*dm[n] - del(dm, n, u) + del dm, n, u # combine spectra if asked to if coefficients is not None: diff --git a/tox.ini b/tox.ini index 6c12c746a..78766b466 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,9 @@ [tox] envlist = - py{36,37,38,39}-test{,-all}{,-dev,-latest,-oldest}{,-cov} - py{36,37,38,39}-test-numpy{116,117,118,119,120,121} - py{36,37,38,39}-test-scipy{12,13,14,15,16,17} - py{36,37,38,39}-test-astropy{40,41,42,43} + py{38,39,310,311,312}-test{,-all}{,-dev,-latest,-oldest}{,-cov} + py{38,39,310,311,312}-test-numpy{117,118,119,120,121,122,123,124,125,126,20,21} + py{38,39,310,311,312}-test-scipy{16,17,18,19,110,111,112,113,114} + py{38,39,310,311,312}-test-astropy{40,41,42,43,50,51,52,53,60,61} build_docs linkcheck codestyle @@ -36,56 +36,86 @@ description = latest: with the latest supported version of key dependencies oldest: with the oldest supported version of key dependencies cov: and test coverage - numpy116: with numpy 1.16.* numpy117: with numpy 1.17.* numpy118: with numpy 1.18.* numpy119: with numpy 1.19.* numpy120: with numpy 1.20.* numpy121: with numpy 1.21.* - scipy12: with scipy 1.2.* - scipy13: with scipy 1.3.* - scipy14: with scipy 1.4.* - scipy15: with scipy 1.5.* + numpy122: with numpy 1.22.* + numpy123: with numpy 1.23.* + numpy124: with numpy 1.24.* + numpy125: with numpy 1.25.* + numpy125: with numpy 1.26.* + numpy20: with numpy 2.0.* + numpy21: with numpy 2.1.* scipy16: with scipy 1.6.* scipy17: with scipy 1.7.* + scipy18: with scipy 1.8.* + scipy19: with scipy 1.9.* + scipy110: with scipy 1.10.* + scipy111: with scipy 1.11.* + scipy112: with scipy 1.12.* + scipy113: with scipy 1.13.* + scipy114: with scipy 1.14.* astropy40: with astropy 4.0.* astropy41: with astropy 4.1.* astropy42: with astropy 4.2.* astropy43: with astropy 4.3.* + astropy50: with astropy 5.0.* + astropy51: with astropy 5.1.* + astropy52: with astropy 5.2.* + astropy53: with astropy 5.3.* + astropy60: with astropy 6.0.* + astropy61: with astropy 6.1.* # The following provides some specific pinnings for key packages deps = - numpy116: numpy==1.16.* numpy117: numpy==1.17.* numpy118: numpy==1.18.* numpy119: numpy==1.19.* numpy120: numpy==1.20.* numpy121: numpy==1.21.* + numpy122: numpy==1.22.* + numpy123: numpy==1.23.* + numpy124: numpy==1.24.* + numpy125: numpy==1.25.* + numpy125: numpy==1.26.* + numpy20: numpy==2.0.* + numpy21: numpy==2.1.* - scipy12: scipy==1.2.* - scipy13: scipy==1.3.* - scipy14: scipy==1.4.* - scipy15: scipy==1.5.* scipy16: scipy==1.6.* scipy17: scipy==1.7.* + scipy18: scipy==1.8.* + scipy19: scipy==1.9.* + scipy110: scipy==1.10.* + scipy111: scipy==1.11.* + scipy112: scipy==1.12.* + scipy113: scipy==1.13.* + scipy114: scipy==1.14.* astropy40: astropy==4.0.* astropy41: astropy==4.1.* astropy42: astropy==4.2.* astropy43: astropy==4.3.* + astropy50: astropy==5.0.* + astropy51: astropy==5.1.* + astropy52: astropy==5.2.* + astropy53: astropy==5.3.* + astropy60: astropy==6.0.* + astropy61: astropy==6.1.* dev: numpy dev: scipy dev: git+https://github.com/astropy/astropy.git#egg=astropy - latest: astropy==4.3.* - latest: numpy==1.21.* - latest: scipy==1.7.* + latest: astropy==6.1.* + latest: numpy==2.1.* + latest: scipy==1.14.* oldest: astropy==4.0.* - oldest: numpy==1.16.* - oldest: scipy==1.2.* + oldest: numpy==1.17.* + oldest: scipy==1.6.* # The following indicates which extras_require from setup.cfg will be installed extras =