1"""Helpers for making Skyfield tests stable."""
2
3import datetime as dt
4import sys
5
6from skyfield import earthlib
7import skyfield.api
8import skyfield.timelib
9
10IS_32_BIT = (sys.maxsize == 0x7fffffff)
11_real_datetime_class = dt.datetime
12
13class datetime(dt.datetime):
14    _fake_now = None
15    @staticmethod
16    def now():
17        return datetime._fake_now
18
19def setup(utc=(2015, 10, 11, 10)):
20    # Importing Pandas raises a TypeError once our fake datetime is
21    # installed.  So instead of waiting, let's import it now.
22    __import__('pandas')
23
24    fake_now = dt.datetime(*utc)
25    skyfield.api.load = skyfield.iokit.Loader('.', verbose=False)
26    skyfield.timelib.Timescale._utcnow = lambda self: fake_now
27    datetime._fake_now = fake_now
28    dt.datetime = datetime
29
30def teardown():
31    skyfield.api.load = skyfield.iokit.Loader('.')
32    skyfield.timelib.Timescale._utcnow = dt.datetime.utcnow
33    dt.datetime = _real_datetime_class
34
35class low_precision_ERA(object):
36    """Compute the Earth rotation angle with only a single float for UT1.
37
38    Skyfield now uses two floats ``t.whole`` and ``t.ut1_fraction`` to
39    represent the UT1 Julian date, supplying an additional 16 digits of
40    precision.  For the Earth rotation angle, which moves very quickly
41    per unit time compared to most other astronomical quantities, this
42    knocks Skyfield out of agreement with other libraries like NOVAS and
43    SOFA that round UT1 to a single float.  Various tests use this
44    context manager to make Skyfield match the lower-precision output.
45
46    """
47    def __enter__(self):
48        self.saved = earthlib.earth_rotation_angle
49        earthlib.earth_rotation_angle = self.era
50    def __exit__(self, *args):
51        earthlib.earth_rotation_angle = self.saved
52    def era(self, whole, fraction):
53        rounded_single_float = whole + fraction
54        return self.saved(rounded_single_float)
55