Repository: astropy/astroquery

Issue:
Dropping python 3.7 support
Before I drop support, would like to see some input from the bigger teams in astroquery. Would you mind if we drop it?
(most big packages are dropping 3.8 (numpy, scipy, etc) in the upcoming releases, and dropped 3.7 a while ago already, and some of the infrastructure packages we use are dropping support, too. So while we can keep going, it's a tiny bit easier if we could do it without workarounds, or to use nice new features)

@astropy/astroquery-archive-maintainers 

Discussion:
bsipocz: > I'm onboard with these removals

There still seem to be problems with the version combinations, so the actual numbers may change, but the big picture will stay, e.g. I'm not planning on dropping the minimums to something very recent.

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 6710e9e9..d6d3ac29 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -28,6 +28,11 @@ vizier
 Infrastructure, Utility and Other Changes and Additions
 -------------------------------------------------------
 
+- Versions of astropy <5.0 and numpy <1.20 are no longer supported. [#2966]
+
+- Versions of Python <3.9 are no longer supported. [#2966]
+
+
 utils.tap
 ^^^^^^^^^
 
diff --git a/astroquery/utils/__init__.py b/astroquery/utils/__init__.py
index 4093c6bc..431a2d2a 100644
--- a/astroquery/utils/__init__.py
+++ b/astroquery/utils/__init__.py
@@ -6,7 +6,7 @@ functions that will ultimately be merged into `astropy.utils`.
 from .progressbar import chunk_report, chunk_read
 from .class_or_instance import class_or_instance
 from .commons import (parse_coordinates, TableList, suppress_vo_warnings,
-                      validate_email, ASTROPY_LT_4_3, ASTROPY_LT_5_0,
+                      validate_email,
                       ASTROPY_LT_5_1, ASTROPY_LT_6_0)
 from .process_asyncs import async_to_sync
 from .docstr_chompers import prepend_docstr_nosections
@@ -19,8 +19,6 @@ __all__ = ['chunk_report', 'chunk_read',
            'TableList',
            'suppress_vo_warnings',
            'validate_email',
-           'ASTROPY_LT_4_3',
-           'ASTROPY_LT_5_0',
            'ASTROPY_LT_5_1',
            'ASTROPY_LT_6_0',
            "async_to_sync",
diff --git a/astroquery/utils/commons.py b/astroquery/utils/commons.py
index f0e48eff..f0b2162a 100644
--- a/astroquery/utils/commons.py
+++ b/astroquery/utils/commons.py
@@ -29,14 +29,12 @@ __all__ = ['parse_coordinates',
            'TableList',
            'suppress_vo_warnings',
            'validate_email',
-           'ASTROPY_LT_4_3',
-           'ASTROPY_LT_5_0',
            'ASTROPY_LT_5_1',
+           'ASTROPY_LT_5_3',
            'ASTROPY_LT_6_0']
 
-ASTROPY_LT_4_3 = not minversion('astropy', '4.3')
-ASTROPY_LT_5_0 = not minversion('astropy', '5.0')
 ASTROPY_LT_5_1 = not minversion('astropy', '5.1')
+ASTROPY_LT_5_3 = not minversion('astropy', '5.3')
 ASTROPY_LT_6_0 = not minversion('astropy', '6.0')
 
 
@@ -74,8 +72,7 @@ def parse_coordinates(coordinates):
                           "appropriate astropy.coordinates object.", InputWarning)
             raise u.UnitsError
         except ValueError as err:
-            if ((ASTROPY_LT_5_0 and isinstance(err.args[1], u.UnitsError))
-                    or (not ASTROPY_LT_5_0 and isinstance(err.__context__, u.UnitsError))):
+            if isinstance(err.__context__, u.UnitsError):
                 try:
                     c = SkyCoord(coordinates, unit="deg", frame="icrs")
                     warnings.warn("Coordinate string is being interpreted as an "
diff --git a/setup.cfg b/setup.cfg
index a294ac42..b339f046 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -128,11 +128,11 @@ omit =
 
 [options]
 
-python_requires = >=3.7
+python_requires = >=3.9
 
 install_requires=
-   numpy>=1.18
-   astropy>=4.2.1
+   numpy>=1.20
+   astropy>=5.0
    requests>=2.19
    beautifulsoup4>=4.8
    html5lib>=0.999
@@ -157,4 +157,4 @@ all=
    mocpy>=0.9
    astropy-healpix
    boto3
-   regions
+   regions>=0.5
diff --git a/tox.ini b/tox.ini
index 56e3678a..e5a1d59f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
 [tox]
 envlist =
-    py{37,38,39,310,311,312}-test{,-alldeps,-oldestdeps,-devdeps,-predeps}{,-online}{,-cov}
+    py{39,310,311,312}-test{,-alldeps,-oldestdeps,-devdeps,-predeps}{,-online}{,-cov}
     codestyle
     linkcheck
     build_docs
@@ -34,18 +34,17 @@ deps =
 
 # mpl while not a dependency, it's required for the tests, and would pull up a newer numpy version if not pinned.
 
-    oldestdeps: astropy==4.2.1
-    oldestdeps: numpy==1.18
-    oldestdeps: matplotlib==3.3.*
+    oldestdeps: astropy==5.0.0
+    oldestdeps: numpy==1.20
+    oldestdeps: matplotlib==3.4.*
     oldestdeps: pyvo==1.1
-    oldestdeps: pytest-doctestplus==0.10.1
-    oldestdeps: requests==2.19
+    oldestdeps: pytest-doctestplus==0.13
+    oldestdeps: requests==2.25
     oldestdeps: keyring==15.0
-    oldestdeps: beautifulsoup4==4.8
+    oldestdeps: pytest==6.0
+    oldestdeps: beautifulsoup4==4.9
     oldestdeps-alldeps: mocpy==0.9
-
-    # pytest warnings issue for older versions, workaround until we drop 3.8 support
-    py38: pytest<8
+    oldestdeps-alldeps: regions==0.5
 
     online: pytest-rerunfailures
 


Test patch:
diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml
index df66d302..bb80a511 100644
--- a/.github/workflows/ci_tests.yml
+++ b/.github/workflows/ci_tests.yml
@@ -38,20 +38,20 @@ jobs:
 
           - name: oldest version for all dependencies
             os: ubuntu-latest
-            python: 3.7
-            toxenv: py37-test-oldestdeps-alldeps
+            python: "3.9"
+            toxenv: py39-test-oldestdeps-alldeps
             toxargs: -v
 
-          - name: Python 3.8 with all optional dependencies (MacOS X)
+          - name: Python 3.10 with all optional dependencies (MacOS X)
             os: macos-latest
-            python: 3.8
-            toxenv: py38-test-alldeps
+            python: "3.10"
+            toxenv: py310-test-alldeps
             toxargs: -v
 
-          - name: Python 3.9 with mandatory dependencies (Windows)
+          - name: Python 3.11 with mandatory dependencies (Windows)
             os: windows-latest
-            python: 3.9
-            toxenv: py39-test
+            python: "3.11"
+            toxenv: py311-test
             toxargs: -v
 
     steps:
@@ -74,7 +74,7 @@ jobs:
         file: ./coverage.xml
 
   egg_info:
-    name: egg_info with Python 3.7
+    name: egg_info with Python 3.9
     runs-on: ubuntu-latest
     steps:
     - name: Checkout code
@@ -84,6 +84,6 @@ jobs:
     - name: Set up Python
       uses: actions/setup-python@v5
       with:
-        python-version: 3.7
+        python-version: "3.9"
     - name: Run egg_info
       run: python setup.py egg_info
diff --git a/astroquery/casda/tests/test_casda.py b/astroquery/casda/tests/test_casda.py
index b1651438..52dd7f15 100644
--- a/astroquery/casda/tests/test_casda.py
+++ b/astroquery/casda/tests/test_casda.py
@@ -11,8 +11,11 @@ from astropy.coordinates import SkyCoord
 import astropy.units as u
 from astropy.table import Table, Column
 from astropy.io.votable import parse
-from astropy.io.votable.exceptions import W03, W50
+from astropy.io.votable.exceptions import W03, W06, W50
 from astroquery import log
+from astroquery.utils.commons import ASTROPY_LT_5_3
+from contextlib import nullcontext
+
 import numpy as np
 
 from astroquery.casda import Casda
@@ -270,8 +273,10 @@ def test_query_region_async_box(patch_get):
 
 
 def test_filter_out_unreleased():
-    with pytest.warns(W03):
-        all_records = parse(data_path('partial_unreleased.xml'), verify='warn').get_first_table().to_table()
+    # The ``W06: Invalid UCD 'meta.ref.url;meta.curation'`` warning is only raised with older astropy
+    with pytest.warns(W06) if ASTROPY_LT_5_3 else nullcontext():
+        with pytest.warns(W03):
+            all_records = parse(data_path('partial_unreleased.xml'), verify='warn').get_first_table().to_table()
     assert all_records[0]['obs_release_date'] == '2017-08-02T03:51:19.728Z'
     assert all_records[1]['obs_release_date'] == '2218-01-02T16:51:00.728Z'
     assert all_records[2]['obs_release_date'] == ''
diff --git a/astroquery/utils/tests/test_utils.py b/astroquery/utils/tests/test_utils.py
index 6228c7a0..beddfbb9 100644
--- a/astroquery/utils/tests/test_utils.py
+++ b/astroquery/utils/tests/test_utils.py
@@ -353,9 +353,8 @@ def patch_getreadablefileobj(request):
     _is_url = aud._is_url
     aud._is_url = lambda x: True
 
-    if not commons.ASTROPY_LT_4_3:
-        _try_url_open = aud._try_url_open
-        aud._try_url_open = lambda x, **kwargs: MockRemote(x, **kwargs)
+    _try_url_open = aud._try_url_open
+    aud._try_url_open = lambda x, **kwargs: MockRemote(x, **kwargs)
 
     _urlopen = urllib.request.urlopen
     _urlopener = urllib.request.build_opener
@@ -405,8 +404,7 @@ def patch_getreadablefileobj(request):
     def closing():
         aud._is_url = _is_url
 
-        if not commons.ASTROPY_LT_4_3:
-            aud._try_url_open = _try_url_open
+        aud._try_url_open = _try_url_open
 
         urllib.request.urlopen = _urlopen
         aud.urllib.request.urlopen = _urlopen
diff --git a/astroquery/vo_conesearch/validator/tests/test_inpect.py b/astroquery/vo_conesearch/validator/tests/test_inpect.py
index 506026b4..e81fcc85 100644
--- a/astroquery/vo_conesearch/validator/tests/test_inpect.py
+++ b/astroquery/vo_conesearch/validator/tests/test_inpect.py
@@ -5,16 +5,7 @@
 import os
 
 # ASTROPY
-import astropy
-from astropy.utils.data import get_pkg_data_filename
-from astropy.utils.introspection import minversion
-
-ASTROPY_LT_4_3 = not minversion(astropy, '4.3')
-
-if ASTROPY_LT_4_3:
-    from astropy.utils.data import _find_pkg_data_path as get_pkg_data_path
-else:
-    from astropy.utils.data import get_pkg_data_path
+from astropy.utils.data import get_pkg_data_filename, get_pkg_data_path
 
 # LOCAL
 from .. import inspect