From 0aea32510333342f221859693ebfefe1335619af Mon Sep 17 00:00:00 2001 From: Eli Rykoff Date: Fri, 17 May 2024 08:27:38 -0700 Subject: [PATCH 1/9] Remove deprecated and removed numpy.string_. --- fitsio/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fitsio/util.py b/fitsio/util.py index 562b6099..18a6e8f6 100644 --- a/fitsio/util.py +++ b/fitsio/util.py @@ -41,7 +41,7 @@ def cfitsio_version(asfloat=False): numpy.uint64, numpy.int64) # different for py3 -_stypes += (numpy.string_, numpy.str_) +_stypes += (numpy.str_, ) # for header keywords _ftypes = (float, numpy.float32, numpy.float64) From 12b72ebf0d137d3288edf55c780c4df4baad280c Mon Sep 17 00:00:00 2001 From: Eli Rykoff Date: Fri, 17 May 2024 08:34:37 -0700 Subject: [PATCH 2/9] Use scipy-style shim to set copy=False for old and new numpy. Following the instructions in https://numpy.org/devdocs/numpy_2_0_migration_guide.html#adapting-to-changes-in-the-copy-keyword I used https://github.com/scipy/scipy/pull/20172 as a template for setting copy=False or copy=None for numpy 1.x and numpy 2.x. --- fitsio/fitslib.py | 6 +++--- fitsio/hdu/image.py | 4 ++-- fitsio/hdu/table.py | 15 ++++++++------- fitsio/util.py | 15 ++++++++++++++- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/fitsio/fitslib.py b/fitsio/fitslib.py index 7ef718ba..3d435491 100644 --- a/fitsio/fitslib.py +++ b/fitsio/fitslib.py @@ -25,7 +25,7 @@ import numpy from . import _fitsio_wrap -from .util import IS_PY3, mks, array_to_native, isstring +from .util import IS_PY3, mks, array_to_native, isstring, copy_if_needed from .header import FITSHDR from .hdu import ( ANY_HDU, IMAGE_HDU, BINARY_TBL, ASCII_TBL, @@ -957,7 +957,7 @@ def create_image_hdu(self, if IS_PY3 and img2send.dtype.char == 'U': # for python3, we convert unicode to ascii # this will error if the character is not in ascii - img2send = img2send.astype('S', copy=False) + img2send = img2send.astype('S', copy=copy_if_needed) else: self._ensure_empty_image_ok() @@ -1738,7 +1738,7 @@ def npy_obj2fits(data, name=None): else: fits_dtype = _table_npy2fits_form['S'] else: - arr0 = numpy.array(first, copy=False) + arr0 = numpy.array(first, copy=copy_if_needed) dtype0 = arr0.dtype npy_dtype = dtype0.descr[0][1][1:] if npy_dtype[0] == 'S' or npy_dtype[0] == 'U': diff --git a/fitsio/hdu/image.py b/fitsio/hdu/image.py index 8c06bcfa..a2d16c8d 100644 --- a/fitsio/hdu/image.py +++ b/fitsio/hdu/image.py @@ -27,7 +27,7 @@ from math import floor from .base import HDUBase, IMAGE_HDU -from ..util import IS_PY3, array_to_native +from ..util import IS_PY3, array_to_native, copy_if_needed # for python3 compat if IS_PY3: @@ -146,7 +146,7 @@ def write(self, img, start=0, **keys): if IS_PY3 and img_send.dtype.char == 'U': # for python3, we convert unicode to ascii # this will error if the character is not in ascii - img_send = img_send.astype('S', copy=False) + img_send = img_send.astype('S', copy=copy_if_needed) if not numpy.isscalar(start): # convert to scalar offset diff --git a/fitsio/hdu/table.py b/fitsio/hdu/table.py index f210121b..3b462b1b 100644 --- a/fitsio/hdu/table.py +++ b/fitsio/hdu/table.py @@ -36,7 +36,8 @@ array_to_native, array_to_native_c, FITSRuntimeWarning, - mks + mks, + copy_if_needed, ) from .base import HDUBase, ASCII_TBL, IMAGE_HDU, _hdu_type_map @@ -282,7 +283,7 @@ def write(self, data, firstrow=0, columns=None, names=None, slow=False, if IS_PY3 and colref.dtype.char == 'U': # for python3, we convert unicode to ascii # this will error if the character is not in ascii - colref = colref.astype('S', copy=False) + colref = colref.astype('S', copy=copy_if_needed) nonobj_arrays.append(colref) @@ -347,7 +348,7 @@ def write_column(self, column, data, firstrow=0, **keys): if IS_PY3 and data_send.dtype.char == 'U': # for python3, we convert unicode to ascii # this will error if the character is not in ascii - data_send = data_send.astype('S', copy=False) + data_send = data_send.astype('S', copy=copy_if_needed) self._verify_column_data(colnum, data_send) @@ -1420,13 +1421,13 @@ def _extract_rows(self, rows, sort=False): Extract an array of rows from an input scalar or sequence """ if rows is not None: - rows = np.array(rows, ndmin=1, copy=False, dtype='i8') + rows = np.array(rows, ndmin=1, copy=copy_if_needed, dtype='i8') if sort: rows = np.unique(rows) return rows, None # returns unique, sorted. Force i8 for 32-bit systems - sortind = np.array(rows.argsort(), dtype='i8', copy=False) + sortind = np.array(rows.argsort(), dtype='i8', copy=copy_if_needed) maxrow = self._info['nrows']-1 if rows.size > 0: @@ -1583,7 +1584,7 @@ def _maybe_decode_fits_ascii_strings_to_unicode_py3(self, array): else: new_dt.append(_dt) if do_conversion: - array = array.astype(new_dt, copy=False) + array = array.astype(new_dt, copy=copy_if_needed) return array def _convert_bool_array(self, array): @@ -1721,7 +1722,7 @@ def _read_var_column(self, colnum, rows, sortind, vstorage): descr = 'S%d' % max_size array = np.fromiter(dlist, descr) if IS_PY3: - array = array.astype('U', copy=False) + array = array.astype('U', copy=copy_if_needed) else: descr = dlist[0].dtype.str array = np.zeros((len(dlist), max_size), dtype=descr) diff --git a/fitsio/util.py b/fitsio/util.py index 18a6e8f6..23254c67 100644 --- a/fitsio/util.py +++ b/fitsio/util.py @@ -134,9 +134,22 @@ def array_to_native(array, inplace=False): return output +if numpy.lib.NumpyVersion(numpy.__version__) >= "2.0.0": + copy_if_needed = None +elif numpy.lib.NumpyVersion(numpy.__version__) < "1.28.0": + copy_if_needed = False +else: + # 2.0.0 dev versions, handle cases where copy may or may not exist + try: + numpy.array([1]).__array__(copy=None) + copy_if_needed = None + except TypeError: + copy_if_needed = False + + def array_to_native_c(array_in, inplace=False): # copy only made if not C order - arr = numpy.array(array_in, order='C', copy=False) + arr = numpy.array(array_in, order='C', copy=copy_if_needed) return array_to_native(arr, inplace=inplace) From a99e6bda4596147fe19b678fa6c4973d36542ae2 Mon Sep 17 00:00:00 2001 From: Eli Rykoff Date: Fri, 17 May 2024 09:25:00 -0700 Subject: [PATCH 3/9] Put numpy.string_ back in for numpy<2. --- fitsio/util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fitsio/util.py b/fitsio/util.py index 23254c67..24b5b403 100644 --- a/fitsio/util.py +++ b/fitsio/util.py @@ -41,7 +41,10 @@ def cfitsio_version(asfloat=False): numpy.uint64, numpy.int64) # different for py3 -_stypes += (numpy.str_, ) +if numpy.lib.NumpyVersion(numpy.__version__) >= "2.0.0": + _stypes += (numpy.str_,) +else: + _stypes += (numpy.string_, numpy.str_,) # for header keywords _ftypes = (float, numpy.float32, numpy.float64) From 18043529f445fe12bc1fa1b544e97463166b98fa Mon Sep 17 00:00:00 2001 From: Eli Rykoff Date: Fri, 17 May 2024 09:28:34 -0700 Subject: [PATCH 4/9] Add py312 and numpy2 to build matrix. --- .github/workflows/tests.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 54880ec6..1163d76f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,8 +16,8 @@ jobs: fail-fast: false matrix: os: [macos-latest, ubuntu-latest] - pyver: ["3.8", "3.9", "3.10", "3.11"] - npver: ["1.20", "1.21", "1.23"] + pyver: ["3.8", "3.9", "3.10", "3.11", "3.12"] + npver: ["1.20", "1.21", "1.23", "2.0"] exclude: - pyver: "3.11" npver: "1.20" @@ -25,6 +25,13 @@ jobs: npver: "1.21" - pyver: "3.10" npver: "1.20" + - pyver: "3.12" + npver: "1.20" + - pyver: "3.12" + npver: "1.21" + - pyver: "3.8" + npver: "2.0" + runs-on: ${{ matrix.os }} steps: @@ -38,7 +45,7 @@ jobs: - uses: conda-incubator/setup-miniconda@v2 with: python-version: ${{ matrix.pyver }} - channels: conda-forge,defaults + channels: conda-forge,conda-forge/label/numpy_rc,defaults channel-priority: strict show-channel-urls: true miniforge-version: latest From 9f97523ffddb91a349b07c5f015ee1dbe4da9a50 Mon Sep 17 00:00:00 2001 From: Eli Rykoff Date: Fri, 17 May 2024 09:31:45 -0700 Subject: [PATCH 5/9] Add numpy 1.26 for py312. --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1163d76f..51160909 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: matrix: os: [macos-latest, ubuntu-latest] pyver: ["3.8", "3.9", "3.10", "3.11", "3.12"] - npver: ["1.20", "1.21", "1.23", "2.0"] + npver: ["1.20", "1.21", "1.23", "1.26", "2.0"] exclude: - pyver: "3.11" npver: "1.20" @@ -29,6 +29,8 @@ jobs: npver: "1.20" - pyver: "3.12" npver: "1.21" + - pyver: "3.12" + npver: "1.23" - pyver: "3.8" npver: "2.0" From aa65a8ad651d11d288e71777b59d7b508b00e7d7 Mon Sep 17 00:00:00 2001 From: Eli Rykoff Date: Fri, 17 May 2024 09:43:27 -0700 Subject: [PATCH 6/9] Invert logic for numpy.string_ compatibility version checks. --- fitsio/util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fitsio/util.py b/fitsio/util.py index 24b5b403..5114d8d5 100644 --- a/fitsio/util.py +++ b/fitsio/util.py @@ -41,10 +41,10 @@ def cfitsio_version(asfloat=False): numpy.uint64, numpy.int64) # different for py3 -if numpy.lib.NumpyVersion(numpy.__version__) >= "2.0.0": - _stypes += (numpy.str_,) -else: +if numpy.lib.NumpyVersion(numpy.__version__) < "1.28.0": _stypes += (numpy.string_, numpy.str_,) +else: + _stypes += (numpy.str_,) # for header keywords _ftypes = (float, numpy.float32, numpy.float64) From 50ae22a8b164a01153241b32025738ca13fd7b07 Mon Sep 17 00:00:00 2001 From: Eli Rykoff Date: Fri, 17 May 2024 09:44:29 -0700 Subject: [PATCH 7/9] Use numpy.bytes_ for numpy2. --- fitsio/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fitsio/util.py b/fitsio/util.py index 5114d8d5..5d337be7 100644 --- a/fitsio/util.py +++ b/fitsio/util.py @@ -44,7 +44,7 @@ def cfitsio_version(asfloat=False): if numpy.lib.NumpyVersion(numpy.__version__) < "1.28.0": _stypes += (numpy.string_, numpy.str_,) else: - _stypes += (numpy.str_,) + _stypes += (numpy.bytes_, numpy.str_,) # for header keywords _ftypes = (float, numpy.float32, numpy.float64) From dc976838f5ce2f7289efeb15a5ea9321bc51ce82 Mon Sep 17 00:00:00 2001 From: Eli Rykoff Date: Fri, 17 May 2024 09:45:41 -0700 Subject: [PATCH 8/9] Reorder channels. --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 51160909..760a1bbe 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -47,7 +47,7 @@ jobs: - uses: conda-incubator/setup-miniconda@v2 with: python-version: ${{ matrix.pyver }} - channels: conda-forge,conda-forge/label/numpy_rc,defaults + channels: conda-forge/label/numpy_rc,conda-forge,defaults channel-priority: strict show-channel-urls: true miniforge-version: latest From 690afa899989b8b313940992f814ad1773ac5958 Mon Sep 17 00:00:00 2001 From: "Matthew R. Becker" Date: Fri, 17 May 2024 11:52:22 -0500 Subject: [PATCH 9/9] Update .github/workflows/tests.yml --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 760a1bbe..b7e0b4f7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,6 +33,8 @@ jobs: npver: "1.23" - pyver: "3.8" npver: "2.0" + - pyver: "3.8" + npver: "1.26" runs-on: ${{ matrix.os }}