Skip to content

Commit

Permalink
Update CI workflows and package requirements (#419)
Browse files Browse the repository at this point in the history
* Update testing and requirements for Python, numpy, and scipy.

* Update matplotlib to >=3.8

* Update versions in gh workflows

* Also limit python version for linkcheck

* Update type annotations following deprecations in python 3.9

* Update change log.

* py313 test should use numpy 2.1; Fix tests for numpy 2

* Remove E203 from pycodestyle

It conflicts with https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements

* Just use one pep8speaks config

* More explicit code branching based on python version.
  • Loading branch information
mkelley authored Feb 12, 2025
1 parent 9360983 commit a8415d9
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 76 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci_cron_weekly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ jobs:
- name: Link check
linux: linkcheck
- name: Python 3.11 with dev versions of key dependencies
linux: py311-test-devdeps-cov
- name: Python 3.13 with dev versions of key dependencies
linux: py313-test-devdeps-cov
posargs: --verbose
allowed_failures:
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# This file performs testing using tox and tox.ini to define and configure the test environments.

# Remove -numpy126 when we support testing with numpy 2.0
# Allow testing of optional dependencies on Python 3.12+ when pyoorb is updated.

name: CI Tests

Expand Down Expand Up @@ -45,12 +46,12 @@ jobs:
- name: Code style checks
linux: codestyle
- name: Python 3.11 with minimal dependencies, measuring coverage
linux: py311-test-numpy126-cov
- name: Python 3.13 with minimal dependencies, measuring coverage
linux: py313-test-cov
coverage: codecov
- name: Python 3.10 with all optional dependencies, measuring coverage
linux: py310-test-numpy126-alldeps-cov
- name: Python 3.11 with all optional dependencies, measuring coverage
linux: py311-test-numpy126-alldeps-cov
coverage: codecov
- name: Python 3.9 with oldest supported versions
Expand Down
11 changes: 11 additions & 0 deletions .pep8speaks.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,13 @@
pycodestyle:
max-line-length: 88

ignore:
- E741 # single-letter small-caps
- E226 # Don't force "missing whitespace around arithmetic operator"
- E402 # .conf has to be set in the __init__.py modules imports
- E501 # line too long
- E203 # whitespace before colon

exclude:
- _astropy_init.py
- version.py
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
0.6.0 (unreleased)
==================

Update supported versions [#419]:
- Python >= 3.9
- numpy >= 1.26
- scipy >= 1.10


New Features
------------

Expand Down
2 changes: 1 addition & 1 deletion docs/sbpy/time.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Or, use the ``et`` property to transform dates to ephemeris time:

.. doctest::

>>> Time("2010-11-04 13:59:47.31", scale="utc").et
>>> print(Time("2010-11-04 13:59:47.31", scale="utc").et) # doctest: +FLOAT_CMP
342151253.4925505

The conversion from UTC is thought to be good to the 0.1 ms level. See the `sbpy` tests for more information.
Expand Down
13 changes: 0 additions & 13 deletions pep8speaks.yml

This file was deleted.

6 changes: 2 additions & 4 deletions sbpy/activity/gas/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@

from abc import ABC, abstractmethod

# distutils is deprecated in python 3.10 and will be removed in 3.12 (PEP 632).
# Migration from distutils.log -> logging
from dataclasses import dataclass
from typing import Callable, Tuple
from typing import Callable

import numpy as np
import astropy.units as u
Expand Down Expand Up @@ -1354,7 +1352,7 @@ def _make_radial_logspace_grid(self) -> np.ndarray:

def _outflow_axis_sampling(
self, x: np.float64, y: np.float64, theta: np.float64
) -> Tuple[np.ndarray, np.ndarray]:
) -> tuple[np.ndarray, np.ndarray]:
"""Construct a list of points along the outflow axis, sampled to be
more dense around the minimum distance to (x, y).
Expand Down
24 changes: 12 additions & 12 deletions sbpy/dynamics/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
]

import abc
from typing import Iterable, List, Optional, Tuple, TypeVar, Union
import sys
from typing import Iterable, Optional, TypeVar, Union
from packaging.version import Version

try:
# python 3.11 feature
from typing import Self
except ImportError:
if sys.version_info[:2] < (3, 11):
Self = TypeVar("Self", bound="StateBase")
else:
from typing import Self

import numpy as np
import astropy
Expand Down Expand Up @@ -204,7 +204,7 @@ def __neg__(self) -> Self:
frame=self.frame,
)

def __abs__(self) -> Tuple[u.Quantity, u.Quantity]:
def __abs__(self) -> tuple[u.Quantity, u.Quantity]:
"""Return the magnitude of the position and velocity."""
r = np.sqrt(np.sum(self.r**2, axis=-1))
v = np.sqrt(np.sum(self.v**2, axis=-1))
Expand Down Expand Up @@ -347,11 +347,11 @@ def from_states(cls, states: Iterable[Self]) -> Self:
"""

frame: BaseCoordinateFrame = states[0].frame
states_: List[State] = [state.transform_to(frame) for state in states]
states_: list[State] = [state.transform_to(frame) for state in states]

r: List[u.Quantity] = [state.r for state in states_]
v: List[u.Quantity] = [state.v for state in states_]
t: List[Union[u.Quantity, Time]] = [state.t for state in states_]
r: list[u.Quantity] = [state.r for state in states_]
v: list[u.Quantity] = [state.v for state in states_]
t: list[Union[u.Quantity, Time]] = [state.t for state in states_]

return State(r, v, t, frame=frame)

Expand Down Expand Up @@ -399,8 +399,8 @@ def from_ephem(
"""

rectangular: Tuple[str] = ("x", "y", "z", "vx", "vy", "vz", "date")
spherical: Tuple[str] = (
rectangular: tuple[str] = ("x", "y", "z", "vx", "vy", "vz", "date")
spherical: tuple[str] = (
"ra",
"dec",
"Delta",
Expand Down
20 changes: 10 additions & 10 deletions sbpy/dynamics/syndynes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
]

import abc
import sys
import time
import logging
from typing import Iterable, List, Tuple, Union, Optional, TypeVar
from typing import Iterable, Union, Optional, TypeVar

try:
# python 3.11 feature
if sys.version_info[:2] < (3, 11):
Self = TypeVar("Self", bound="StateBase")
else:
from typing import Self
except ImportError:
Self = TypeVar("Self", bound="SynGenerator")

import numpy as np
import astropy.units as u
Expand Down Expand Up @@ -327,7 +327,7 @@ def to_ephem(self) -> Ephem:
if len(self) == 0:
return Ephem()

tables: List[Ephem] = [s.to_ephem().table for s in self]
tables: list[Ephem] = [s.to_ephem().table for s in self]

return Ephem.from_table(
vstack(tables, metadata_conflicts="error"),
Expand Down Expand Up @@ -477,7 +477,7 @@ def initialize_states(self) -> None:
"""

states: List[State] = []
states: list[State] = []
for age in self.ages:
t_i: Time = self.source.t - age
state = self.solver.solve(self.source, t_i, 0)
Expand All @@ -497,7 +497,7 @@ def solve(self) -> None:

logger: logging.Logger = logging.getLogger()

particles: List[State] = []
particles: list[State] = []
t0: float = time.monotonic()
for i in range(self.betas.size):
for j in range(self.ages.size):
Expand Down Expand Up @@ -603,7 +603,7 @@ def synchrones(self) -> Synchrones:

return Synchrones([self.synchrone(i) for i in range(len(self.ages))])

def source_orbit(self, dt: u.Quantity) -> Union[State, Tuple[State, SkyCoord]]:
def source_orbit(self, dt: u.Quantity) -> Union[State, tuple[State, SkyCoord]]:
"""Calculate and observe the orbit of the dust source.
Expand All @@ -627,7 +627,7 @@ def source_orbit(self, dt: u.Quantity) -> Union[State, Tuple[State, SkyCoord]]:
"""

states: List[State] = []
states: list[State] = []
for i in range(len(dt)):
t: Time = self.source.t + dt[i]
states.append(self.solver.solve(self.source, t, 0))
Expand Down
3 changes: 0 additions & 3 deletions sbpy/dynamics/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,6 @@ def test_GM(self):
solver = SolarGravity()
assert u.isclose(solver.GM, const.G * const.M_sun, rtol=1e-12)

@pytest.mark.skipif(
"scipy_version[0] < 2 and scipy_version[1] < 8", reason="requires scipy>=1.10"
)
def test_solverfailed(self):
r = [0, 1, 0] * u.au
v = [0, -1, 1] * u.km / u.s
Expand Down
18 changes: 9 additions & 9 deletions sbpy/imageanalysis/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ def rarray(shape, yx=None, subsample=0):
-------
>>> from sbpy.imageanalysis.utils import rarray
>>> r = rarray((5, 5))
>>> r[2, 2] # docest: +FLOAT_CMP
>>> print(r[2, 2]) # docest: +FLOAT_CMP
0.0
>>> r = rarray((5, 5), yx=(0, 0))
>>> r[2, 2] # docest: +FLOAT_CMP
>>> print(r[2, 2]) # docest: +FLOAT_CMP
2.8284271247461903
"""
Expand Down Expand Up @@ -89,10 +89,10 @@ def rebin(a, factor, flux=False, trim=False):
-------
>>> from sbpy.imageanalysis.utils import xarray, rebin
>>> x = xarray((10, 10))
>>> x[0, :2].mean() # docest: +FLOAT_CMP
>>> print(x[0, :2].mean()) # docest: +FLOAT_CMP
0.5
>>> x2 = rebin(x, -2)
>>> x2[0, 0] # docest: +FLOAT_CMP
>>> print(x2[0, 0]) # docest: +FLOAT_CMP
0.5
"""
Expand All @@ -102,7 +102,7 @@ def rebin(a, factor, flux=False, trim=False):
def mini(a, factor):
b = a[::-factor]
for i in range(-factor - 1):
b += a[(i + 1)::-factor]
b += a[(i + 1) :: -factor]
if not flux:
b = b / -factor
return b
Expand Down Expand Up @@ -176,10 +176,10 @@ def refine_pixel(func, subsample, yx_pixel, yx, **kwargs):
>>> from sbpy.imageanalysis.utils import rarray, refine_pixel
>>> yx = (2, 2) # the center of the radial array
>>> r = rarray((5, 5), yx=yx)
>>> r[2, 2] # docest: +FLOAT_CMP
>>> print(r[2, 2]) # docest: +FLOAT_CMP
0.0
>>> f = refine_pixel(rarray, 10, (2, 2), yx)
>>> np.isclose(f, 0.03826, rtol=0.01, atol=0.01)
>>> print(np.isclose(f, 0.03826, rtol=0.01, atol=0.01))
True
"""

Expand Down Expand Up @@ -212,7 +212,7 @@ def xarray(shape, yx=[0, 0], th=None):
--------
>>> from sbpy.imageanalysis.utils import xarray
>>> x = xarray((10, 10))
>>> x[0, 3]
>>> print(x[0, 3])
3
"""
Expand Down Expand Up @@ -250,7 +250,7 @@ def yarray(shape, yx=[0, 0], th=None):
>>> from sbpy.imageanalysis.utils import yarray
>>> y = yarray((10, 10))
>>> y[3, 0]
>>> print(y[3, 0])
3
"""
Expand Down
2 changes: 1 addition & 1 deletion sbpy/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class SpiceEphemerisTime(TimeFromEpoch):
>>> import sbpy.time
>>>
>>> t = Time("2023-11-21")
>>> print(t.et)
>>> print(float(t.et)) # doctest: +FLOAT_CMP
753796869.1828325
>>> t = Time(0, format="et")
Expand Down
12 changes: 6 additions & 6 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@ classifiers =
[options]
packages = find:
zip_save = False
python_requires = >=3.8
python_requires = >=3.9
setup_requires = setuptools_scm

# keep requirements in synchronization with docs/install.rst
install_requires =
numpy>=1.21.0
numpy>=1.24.0
astropy>=5.3.3
include_package_data = True

[options.extras_require]
recommended =
ads>=0.12
astroquery>=0.4.5
scipy>=1.6
scipy>=1.10
synphot>=1.1.1
all =
ads>=0.12
Expand All @@ -47,7 +47,7 @@ all =
photutils
pyoorb
pyyaml
scipy>=1.6
scipy>=1.10
synphot>=1.1.1
test =
pytest>=7.0
Expand All @@ -59,10 +59,10 @@ test =
coverage
docs =
sbpy[all,test]
matplotlib>=3.3
matplotlib>=3.8
sphinx-astropy>=1.3
astropy!=6.1.*
scipy>=1.6
scipy>=1.10
numpy<2

[options.package_data]
Expand Down
Loading

0 comments on commit a8415d9

Please sign in to comment.