Skip to content

Commit

Permalink
Fix IERS_Auto logic now that IERS-A is bundled
Browse files Browse the repository at this point in the history
  • Loading branch information
ayshih committed Mar 12, 2024
1 parent 7c61237 commit 62aea2a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 63 deletions.
28 changes: 16 additions & 12 deletions astropy/utils/iers/iers.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ class Conf(_config.ConfigNamespace):

auto_download = _config.ConfigItem(
True,
"Enable auto-downloading of the latest IERS data. If set to False "
"then the local IERS-B file will be used by default (even if the "
"full IERS file with predictions was already downloaded and cached). "
"Enable auto-downloading of the latest IERS-A data. If set to False "
"then the bundled IERS-A file will be used by default (even if a "
"newer version of the IERS-A file was already downloaded and cached). "
"This parameter also controls whether internet resources will be "
"queried to update the leap second table if the installed version is "
"out of date. Default is True.",
Expand Down Expand Up @@ -545,9 +545,9 @@ class IERS_A(IERS):
Notes
-----
The IERS A file is not part of astropy. It can be downloaded from
``iers.IERS_A_URL`` or ``iers.IERS_A_URL_MIRROR``. See ``iers.__doc__``
for instructions on use in ``Time``, etc.
If the package IERS A file (```iers.IERS_A_FILE``) is out of date, a new
version can be downloaded from ``iers.IERS_A_URL`` or ``iers.IERS_A_URL_MIRROR``.
See ``iers.__doc__`` for instructions on use in ``Time``, etc.
"""

iers_table = None
Expand Down Expand Up @@ -758,6 +758,10 @@ class IERS_Auto(IERS_A):
"""
Provide most-recent IERS data and automatically handle downloading
of updated values as necessary.
The returned table combines the IERS-A and IERS-B files, with the data
in the IERS-B file considered to be official values and thus superseding
values from th IERS-A file at the same times.
"""

iers_table = None
Expand All @@ -772,8 +776,8 @@ def open(cls):
(or non-existent) then it will be downloaded over the network and cached.
If the configuration setting ``astropy.utils.iers.conf.auto_download``
is set to False then ``astropy.utils.iers.IERS()`` is returned. This
is normally the IERS-B table that is supplied with astropy.
is set to False then the bundled IERS-A table will be used rather than
any downloaded version of the IERS-A table.
On the first call in a session, the table will be memoized (in the
``iers_table`` class attribute), and further calls to ``open`` will
Expand All @@ -786,7 +790,7 @@ def open(cls):
"""
if not conf.auto_download:
cls.iers_table = IERS_B.open()
cls.iers_table = cls.read()
return cls.iers_table

all_urls = (conf.iers_auto_url, conf.iers_auto_url_mirror)
Expand Down Expand Up @@ -817,8 +821,8 @@ def open(cls):
# Issue a warning here, perhaps user is offline. An exception
# will be raised downstream if actually trying to interpolate
# predictive values.
warn("unable to download valid IERS file, using local IERS-B", IERSWarning)
cls.iers_table = IERS_B.open()
warn("unable to download valid IERS file, using local IERS-A", IERSWarning)
cls.iers_table = cls.read()

Check warning on line 825 in astropy/utils/iers/iers.py

View check run for this annotation

Codecov / codecov/patch

astropy/utils/iers/iers.py#L824-L825

Added lines #L824 - L825 were not covered by tests

return cls.iers_table

Expand Down Expand Up @@ -932,7 +936,7 @@ def _substitute_iers_b(cls, table):
IERS-A has IERS-B values included, but for reasons unknown these
do not match the latest IERS-B values (see comments in #4436).
Here, we use the bundled astropy IERS-B table to overwrite the values
in the downloaded IERS-A table.
in the IERS-A table.
"""
iers_b = IERS_B.open()
# Substitute IERS-B values for existing B values in IERS-A table
Expand Down
77 changes: 29 additions & 48 deletions astropy/utils/iers/tests/test_iers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,9 @@

FILE_NOT_FOUND_ERROR = getattr(__builtins__, "FileNotFoundError", OSError)

try:
iers.IERS_A.open("finals2000A.all") # check if IERS_A is available
except OSError:
HAS_IERS_A = False
else:
HAS_IERS_A = True

IERS_A_EXCERPT = get_pkg_data_filename(os.path.join("data", "iers_a_excerpt"))


def setup_module():
# Need auto_download so that IERS_B won't be loaded and cause tests to
# fail. Files to be downloaded are handled appropriately in the tests.
iers.conf.auto_download = True


def teardown_module():
# This setting is to be consistent with astropy/conftest.py
iers.conf.auto_download = False


class TestBasic:
"""Basic tests that IERS_B returns correct values"""

Expand Down Expand Up @@ -216,7 +198,6 @@ def test_simple(self):
assert len(iers_tab[:2]) == 2


@pytest.mark.skipif(not HAS_IERS_A, reason="requires IERS_A")
class TestIERS_A:
@classmethod
def teardown_class(self):
Expand Down Expand Up @@ -261,6 +242,14 @@ def setup_class(self):
self.iers_a_url_2 = Path(self.iers_a_file_2).as_uri()
self.t = Time.now() + TimeDelta(10, format="jd") * np.arange(self.N)

# This group of tests requires auto downloading to be on
iers.conf.auto_download = True

# auto_download = False is tested in test_IERS_B_parameters_loading_into_IERS_Auto()

def teardown_class(self):
iers.conf.auto_download = False

def teardown_method(self, method):
"""Run this after every test."""
iers.IERS_Auto.close()
Expand Down Expand Up @@ -310,12 +299,6 @@ def test_auto_max_age_minimum(self):
iers_table = iers.IERS_Auto.open()
_ = iers_table.ut1_utc(self.t.jd1, self.t.jd2)

def test_no_auto_download(self):
with iers.conf.set_temp("auto_download", False):
t = iers.IERS_Auto.open()
assert type(t) is iers.IERS_B

@pytest.mark.remote_data
def test_simple(self):
with iers.conf.set_temp("iers_auto_url", self.iers_a_url_1):
dat = iers.IERS_Auto.open()
Expand Down Expand Up @@ -380,8 +363,10 @@ def test_simple(self):
assert dat["MJD"][-1] == (57539.0 + 60) * u.d


@pytest.mark.remote_data
def test_IERS_B_parameters_loading_into_IERS_Auto():
# Double-check that auto downloading is off
assert not iers.conf.auto_download

A = iers.IERS_Auto.open()
B = iers.IERS_B.open()

Expand Down Expand Up @@ -445,35 +430,31 @@ def test_iers_b_dl():
iers.IERS_B.close()


@pytest.mark.remote_data
def test_iers_out_of_range_handling(tmp_path):
# Make sure we don't have IERS-A data available anywhere
with set_temp_cache(tmp_path):
iers.IERS_A.close()
iers.IERS_Auto.close()
iers.IERS.close()
def test_iers_b_out_of_range_handling():
# The following error/warning applies only to IERS_B, not to the default IERS_Auto
with iers.earth_orientation_table.set(iers.IERS_B.open()):
now = Time.now()
with iers.conf.set_temp("auto_download", False):
# Should be fine with built-in IERS_B
(now - 300 * u.day).ut1

# Default is to raise an error
match = r"\(some\) times are outside of range covered by IERS table"
with pytest.raises(iers.IERSRangeError, match=match):
(now + 100 * u.day).ut1
# Should be fine with bundled IERS-B
(now - 300 * u.day).ut1

with iers.conf.set_temp("iers_degraded_accuracy", "warn"):
with pytest.warns(iers.IERSDegradedAccuracyWarning, match=match):
(now + 100 * u.day).ut1
# Default is to raise an error
match = r"\(some\) times are outside of range covered by IERS table"
with pytest.raises(iers.IERSRangeError, match=match):
(now + 100 * u.day).ut1

with iers.conf.set_temp("iers_degraded_accuracy", "ignore"):
with iers.conf.set_temp("iers_degraded_accuracy", "warn"):
with pytest.warns(iers.IERSDegradedAccuracyWarning, match=match):
(now + 100 * u.day).ut1

with iers.conf.set_temp("iers_degraded_accuracy", "ignore"):
(now + 100 * u.day).ut1


@pytest.mark.remote_data
def test_iers_download_error_handling(tmp_path):
# Make sure we don't have IERS-A data available anywhere
with set_temp_cache(tmp_path):
# Make sure an IERS-A table isn't already loaded
with set_temp_cache(tmp_path), iers.conf.set_temp("auto_download", True):
iers.IERS_A.close()
iers.IERS_Auto.close()
iers.IERS.close()
Expand All @@ -485,7 +466,7 @@ def test_iers_download_error_handling(tmp_path):
with iers.conf.set_temp("iers_auto_url_mirror", "https://google.com"):
with pytest.warns(iers.IERSWarning) as record:
with iers.conf.set_temp("iers_degraded_accuracy", "ignore"):
(now + 100 * u.day).ut1
(now + 400 * u.day).ut1

assert len(record) == 3
assert str(record[0].message).startswith(
Expand All @@ -495,7 +476,7 @@ def test_iers_download_error_handling(tmp_path):
"malformed IERS table from https://google.com"
)
assert str(record[2].message).startswith(
"unable to download valid IERS file, using local IERS-B"
"unable to download valid IERS file, using local IERS-A"
)


Expand Down
6 changes: 3 additions & 3 deletions docs/utils/iers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ that relate to automatic IERS downloading. Four of the most
important to consider are the following:

auto_download:
Enable auto-downloading of the latest IERS data. If set to ``False`` then
the local IERS-A and IERS-B files will be used by default (even if the full
IERS file with predictions was already downloaded and cached). This
Enable auto-downloading of the latest IERS-A data. If set to ``False`` then
the bundled IERS-A file will be used by default (even if a newer
versions of the IERS-A file was already downloaded and cached). This
parameter also controls whether internet resources will be queried to update
the leap second table if the installed version is out of date.

Expand Down

0 comments on commit 62aea2a

Please sign in to comment.