1import ephem
2import unittest
3
4METHODS = (
5    ephem.Observer.previous_rising,
6    ephem.Observer.previous_setting,
7    ephem.Observer.next_rising,
8    ephem.Observer.next_setting,
9)
10
11tle_lines = (
12    'ISS (ZARYA)',
13    '1 25544U 98067A   21339.43187394  .00003128  00000+0  65063-4 0  9994',
14    '2 25544  51.6429 215.9885 0004097 274.3592 259.8366 15.48933952315130',
15)
16
17class HourAngleTests(unittest.TestCase):
18    # Yes, maybe an odd place to put a body attribute test; but HA was
19    # added to support the new rising and setting logic, so here it is.
20
21    o = ephem.Observer()
22    o.date = '2021/12/5 13:56'
23
24    def test_fixed_ha(self):  # obj_fixed() in circum.c
25        b = ephem.star('Rigel')
26        b.compute(self.o)
27        self.assertNotEqual(b.ha, 0.0)
28
29    def test_cir_pos_ha(self):  # cir_pos() in circum.c
30        b = ephem.Mars()
31        b.compute(self.o)
32        self.assertNotEqual(b.ha, 0.0)
33
34    def test_earth_satellite_ha(self):  # earthsat.c
35        b = ephem.readtle(*tle_lines)
36        b.compute(self.o)
37        self.assertNotEqual(b.ha, 0.0)
38
39    # Ignoring "plmoon.c" case for now, as PyEphem objects like
40    # Callisto() seem to lack the new "ha" attribute anyway.
41
42class RiseSetTests(unittest.TestCase):
43    maxDiff = 10000
44
45    def test_never_up(self):
46        m = ephem.Moon()
47        o = ephem.Observer()
48        o.lon = '0'
49        o.date = '2021/11/11'
50
51        # First, two clear-cut cases.
52        o.lat = '+40'
53        self.assertEqual(str(o.next_rising(m)), '2021/11/11 13:22:31')
54
55        o.lat = '+80'
56        self.assertRaises(ephem.NeverUpError, o.next_rising, m)
57
58        # Now, an edge case: although the Moon starts the day too far
59        # south to rise, it moves north over the first few hours and
60        # winds up rising.
61        o.lat = '+70'
62        t = o.next_rising(m)
63        self.assertEqual(str(o.next_rising(m)), '2021/11/11 17:13:03')
64
65    def test_always_up(self):
66        m = ephem.Moon()
67        o = ephem.Observer()
68        o.lon = '0'
69        o.date = '2022/9/7'
70
71        o.lat = '-60'
72        self.assertEqual(str(o.next_rising(m)), '2022/9/7 12:11:26')
73
74        o.lat = '-70'
75        self.assertRaises(ephem.AlwaysUpError, o.next_rising, m)
76
77    def test_sun(self):
78        s = ephem.Sun()
79        o = ephem.Observer()
80        o.lat = '36.4072'
81        o.lon = '-105.5734'
82        o.date = '2021/11/24'
83        expected = """\
840.0 0.0 False
852021/11/23 13:51:09 previous_rising
862021/11/23 23:46:11 previous_setting
872021/11/24 13:52:08 next_rising
882021/11/24 23:45:47 next_setting
89
900.0 0.0 True
912021/11/23 13:52:38 previous_rising
922021/11/23 23:44:41 previous_setting
932021/11/24 13:53:38 next_rising
942021/11/24 23:44:17 next_setting
95
960.0 1010.0 False
972021/11/23 13:47:44 previous_rising
982021/11/23 23:49:36 previous_setting
992021/11/24 13:48:43 next_rising
1002021/11/24 23:49:12 next_setting
101
1020.0 1010.0 True
1032021/11/23 13:49:33 previous_rising
1042021/11/23 23:47:46 previous_setting
1052021/11/24 13:50:32 next_rising
1062021/11/24 23:47:22 next_setting
107
108-0.8333 0.0 False
1092021/11/23 13:46:34 previous_rising
1102021/11/23 23:50:46 previous_setting
1112021/11/24 13:47:33 next_rising
1122021/11/24 23:50:22 next_setting
113
114-0.8333 0.0 True
1152021/11/23 13:48:03 previous_rising
1162021/11/23 23:49:17 previous_setting
1172021/11/24 13:49:02 next_rising
1182021/11/24 23:48:53 next_setting
119
120-0.8333 1010.0 False
1212021/11/23 13:41:44 previous_rising
1222021/11/23 23:55:36 previous_setting
1232021/11/24 13:42:42 next_rising
1242021/11/24 23:55:13 next_setting
125
126-0.8333 1010.0 True
1272021/11/23 13:43:44 previous_rising
1282021/11/23 23:53:35 previous_setting
1292021/11/24 13:44:43 next_rising
1302021/11/24 23:53:12 next_setting
131"""
132        expected = expected.splitlines()
133        actual = self._generate_report(o, s)
134        for n, (expected, actual) in enumerate(zip(expected, actual), 1):
135            self.assertEqual(expected, actual, 'Line {}'.format(n))
136
137    def test_moon(self):
138        m = ephem.Moon()
139        o = ephem.Observer()
140        o.lat = '36.4072'
141        o.lon = '-105.5734'
142        o.date = '2021/11/24'
143        expected = """\
1440.0 0.0 False
1452021/11/23 02:21:39 previous_rising
1462021/11/23 17:34:47 previous_setting
1472021/11/24 03:15:45 next_rising
1482021/11/24 18:18:46 next_setting
149
1500.0 0.0 True
1512021/11/23 02:23:09 previous_rising
1522021/11/23 17:33:17 previous_setting
1532021/11/24 03:17:15 next_rising
1542021/11/24 18:17:18 next_setting
155
1560.0 1010.0 False
1572021/11/23 02:17:52 previous_rising
1582021/11/23 17:38:32 previous_setting
1592021/11/24 03:12:00 next_rising
1602021/11/24 18:22:25 next_setting
161
1620.0 1010.0 True
1632021/11/23 02:19:43 previous_rising
1642021/11/23 17:36:41 previous_setting
1652021/11/24 03:13:51 next_rising
1662021/11/24 18:20:36 next_setting
167
168-0.8333 0.0 False
1692021/11/23 02:16:31 previous_rising
1702021/11/23 17:39:52 previous_setting
1712021/11/24 03:10:40 next_rising
1722021/11/24 18:23:43 next_setting
173
174-0.8333 0.0 True
1752021/11/23 02:18:02 previous_rising
1762021/11/23 17:38:21 previous_setting
1772021/11/24 03:12:11 next_rising
1782021/11/24 18:22:14 next_setting
179
180-0.8333 1010.0 False
1812021/11/23 02:11:04 previous_rising
1822021/11/23 17:45:16 previous_setting
1832021/11/24 03:05:16 next_rising
1842021/11/24 18:28:58 next_setting
185
186-0.8333 1010.0 True
1872021/11/23 02:13:10 previous_rising
1882021/11/23 17:43:11 previous_setting
1892021/11/24 03:07:21 next_rising
1902021/11/24 18:26:56 next_setting
191"""
192        expected = expected.splitlines()
193        actual = self._generate_report(o, m)
194        for n, (expected, actual) in enumerate(zip(expected, actual), 1):
195            self.assertEqual(expected, actual, 'Line {}'.format(n))
196
197    def _generate_report(self, o, body):
198        for horizon in 0.0, '-0.8333':
199            for pressure in 0.0, 1010.0:
200                for use_center in False, True:
201                    o.horizon = horizon
202                    o.pressure = pressure
203                    yield '{} {} {}'.format(horizon, pressure, use_center)
204                    for method in METHODS:
205                        d = method(o, body, use_center=use_center)
206                        yield '{} {}'.format(d, method.__name__)
207                    yield ''
208