Browse Source

refactor: use `enum` instead of `dict`s for the events and moon phase (#129)

BREAKING CHANGE: some methodes in Event and MoonPhase have been dropped
in favor of `enum.Enum`'s `name` and `value` properties.
tags/v0.9.0
Jérôme Deuchnord 4 years ago
committed by Jérôme Deuchnord
parent
commit
8b723bfd22
No known key found for this signature in database GPG Key ID: 72F9D1A7272D53DD
11 changed files with 282 additions and 267 deletions
  1. +15
    -2
      .github/workflows/i18n.yml
  2. +6
    -2
      Makefile
  3. +17
    -94
      kosmorrolib/data.py
  4. +5
    -7
      kosmorrolib/dumper.py
  5. +40
    -0
      kosmorrolib/enum.py
  6. +41
    -2
      kosmorrolib/ephemerides.py
  7. +9
    -6
      kosmorrolib/events.py
  8. +90
    -94
      kosmorrolib/locales/messages.pot
  9. +4
    -3
      test/dumper.py
  10. +34
    -31
      test/ephemerides.py
  11. +21
    -26
      test/events.py

+ 15
- 2
.github/workflows/i18n.yml View File

@@ -19,13 +19,26 @@ jobs:
- name: Check i18n - name: Check i18n
run: | run: |
pipenv run python setup.py extract_messages --output-file=/tmp/kosmorro-messages.pot > /dev/null pipenv run python setup.py extract_messages --output-file=/tmp/kosmorro-messages.pot > /dev/null
n=$(diff -y --suppress-common-lines kosmorrolib/locales/messages.pot /tmp/kosmorro-messages.pot | grep -v -E '^"POT-Creation-Date: ' | wc -l)
diff=$(diff kosmorrolib/locales/messages.pot /tmp/kosmorro-messages.pot | grep '^>')
n=$(echo "$diff" | grep -v '> "POT-Creation-Date: ' | wc -l)

if [ "$(echo "$diff" | grep -E '^"Generated-By: Babel' | wc -l)" -eq "1" ]; then
echo "❌ You dependencies may be out of date!"
echo " Please run the following command to fix this:"
echo
echo " pipenv sync --dev"
echo
echo " Then update the messages file:"
echo
echo " make messages"
exit 2
fi


if [ "$n" -ne "0" ]; then if [ "$n" -ne "0" ]; then
echo "❌ The messages file is not up-to-date!" echo "❌ The messages file is not up-to-date!"
echo " Please run the following command to fix this:" echo " Please run the following command to fix this:"
echo echo
echo " pipenv run python setup.py extract_messages --output-file=kosmorrolib/locales/messages.pot"
echo " make messages"
exit 1 exit 1
fi fi




+ 6
- 2
Makefile View File

@@ -6,13 +6,17 @@ test:
unset KOSMORRO_TIMEZONE; \ unset KOSMORRO_TIMEZONE; \
LANG=C pipenv run python3 -m coverage run -m unittest test LANG=C pipenv run python3 -m coverage run -m unittest test


build: i18n
build: i18n manpages
python3 setup.py sdist bdist_wheel python3 setup.py sdist bdist_wheel


i18n:
messages:
pipenv run python setup.py extract_messages --output-file=kosmorrolib/locales/messages.pot

manpages:
ronn --roff manpage/kosmorro.1.md ronn --roff manpage/kosmorro.1.md
ronn --roff manpage/kosmorro.7.md ronn --roff manpage/kosmorro.7.md


i18n:
if [ "$$POEDITOR_API_ACCESS" != "" ]; then \ if [ "$$POEDITOR_API_ACCESS" != "" ]; then \
python3 .scripts/build/getlangs.py; \ python3 .scripts/build/getlangs.py; \
python3 setup.py compile_catalog; \ python3 setup.py compile_catalog; \


+ 17
- 94
kosmorrolib/data.py View File

@@ -25,30 +25,10 @@ from numpy import pi, arcsin
from skyfield.api import Topos, Time from skyfield.api import Topos, Time
from skyfield.vectorlib import VectorSum as SkfPlanet from skyfield.vectorlib import VectorSum as SkfPlanet


from .core import get_skf_objects, get_timescale
from .core import get_skf_objects
from .enum import MoonPhaseType, EventType
from .i18n import _ from .i18n import _


MOON_PHASES = {
'NEW_MOON': _('New Moon'),
'WAXING_CRESCENT': _('Waxing crescent'),
'FIRST_QUARTER': _('First Quarter'),
'WAXING_GIBBOUS': _('Waxing gibbous'),
'FULL_MOON': _('Full Moon'),
'WANING_GIBBOUS': _('Waning gibbous'),
'LAST_QUARTER': _('Last Quarter'),
'WANING_CRESCENT': _('Waning crescent'),
'UNKNOWN': _('Unavailable')
}

EVENTS = {
'OPPOSITION': {'message': _('%s is in opposition')},
'CONJUNCTION': {'message': _('%s and %s are in conjunction')},
'OCCULTATION': {'message': _('%s occults %s')},
'MAXIMAL_ELONGATION': {'message': _("%s's largest elongation")},
'MOON_PERIGEE': {'message': _("%s is at its perigee")},
'MOON_APOGEE': {'message': _("%s is at its apogee")},
}



class Serializable(ABC): class Serializable(ABC):
@abstractmethod @abstractmethod
@@ -57,40 +37,27 @@ class Serializable(ABC):




class MoonPhase(Serializable): class MoonPhase(Serializable):
def __init__(self, identifier: str, time: datetime = None, next_phase_date: datetime = None):
if identifier not in MOON_PHASES.keys():
raise ValueError('identifier parameter must be one of %s (got %s)' % (', '.join(MOON_PHASES.keys()),
identifier))

self.identifier = identifier
def __init__(self, phase_type: MoonPhaseType, time: datetime = None, next_phase_date: datetime = None):
self.phase_type = phase_type
self.time = time self.time = time
self.next_phase_date = next_phase_date self.next_phase_date = next_phase_date


def get_phase(self):
return MOON_PHASES[self.identifier]

def get_next_phase_name(self):
next_identifier = self.get_next_phase()

return MOON_PHASES[next_identifier]

def get_next_phase(self): def get_next_phase(self):
if self.identifier == 'NEW_MOON' or self.identifier == 'WAXING_CRESCENT':
next_identifier = 'FIRST_QUARTER'
elif self.identifier == 'FIRST_QUARTER' or self.identifier == 'WAXING_GIBBOUS':
next_identifier = 'FULL_MOON'
elif self.identifier == 'FULL_MOON' or self.identifier == 'WANING_GIBBOUS':
next_identifier = 'LAST_QUARTER'
else:
next_identifier = 'NEW_MOON'
return next_identifier
if self.phase_type in [MoonPhaseType.NEW_MOON, MoonPhaseType.WAXING_CRESCENT]:
return MoonPhaseType.FIRST_QUARTER
if self.phase_type in [MoonPhaseType.FIRST_QUARTER, MoonPhaseType.WAXING_GIBBOUS]:
return MoonPhaseType.FULL_MOON
if self.phase_type in [MoonPhaseType.FULL_MOON, MoonPhaseType.WANING_GIBBOUS]:
return MoonPhaseType.LAST_QUARTER

return MoonPhaseType.NEW_MOON


def serialize(self) -> dict: def serialize(self) -> dict:
return { return {
'phase': self.identifier,
'phase': self.phase_type.name,
'time': self.time.isoformat() if self.time is not None else None, 'time': self.time.isoformat() if self.time is not None else None,
'next': { 'next': {
'phase': self.get_next_phase(),
'phase': self.get_next_phase().name,
'time': self.next_phase_date.isoformat() 'time': self.next_phase_date.isoformat()
} }
} }
@@ -168,13 +135,8 @@ class Satellite(Object):




class Event(Serializable): class Event(Serializable):
def __init__(self, event_type: str, objects: [Object], start_time: datetime,
def __init__(self, event_type: EventType, objects: [Object], start_time: datetime,
end_time: Union[datetime, None] = None, details: str = None): end_time: Union[datetime, None] = None, details: str = None):
if event_type not in EVENTS.keys():
accepted_types = ', '.join(EVENTS.keys())
raise ValueError('event_type parameter must be one of the following: %s (got %s)' % (accepted_types,
event_type))

self.event_type = event_type self.event_type = event_type
self.objects = objects self.objects = objects
self.start_time = start_time self.start_time = start_time
@@ -189,7 +151,7 @@ class Event(Serializable):
self.details) self.details)


def get_description(self, show_details: bool = True) -> str: def get_description(self, show_details: bool = True) -> str:
description = EVENTS[self.event_type]['message'] % self._get_objects_name()
description = self.event_type.value % self._get_objects_name()
if show_details and self.details is not None: if show_details and self.details is not None:
description += ' ({:s})'.format(self.details) description += ' ({:s})'.format(self.details)
return description return description
@@ -203,50 +165,13 @@ class Event(Serializable):
def serialize(self) -> dict: def serialize(self) -> dict:
return { return {
'objects': [object.serialize() for object in self.objects], 'objects': [object.serialize() for object in self.objects],
'event': self.event_type,
'event': self.event_type.name,
'starts_at': self.start_time.isoformat(), 'starts_at': self.start_time.isoformat(),
'ends_at': self.end_time.isoformat() if self.end_time is not None else None, 'ends_at': self.end_time.isoformat() if self.end_time is not None else None,
'details': self.details 'details': self.details
} }




def skyfield_to_moon_phase(times: [Time], vals: [int], now: Time) -> Union[MoonPhase, None]:
tomorrow = get_timescale().utc(now.utc_datetime().year, now.utc_datetime().month, now.utc_datetime().day + 1)

phases = list(MOON_PHASES.keys())
current_phase = None
current_phase_time = None
next_phase_time = None
i = 0

if len(times) == 0:
return None

for i, time in enumerate(times):
if now.utc_iso() <= time.utc_iso():
if vals[i] in [0, 2, 4, 6]:
if time.utc_datetime() < tomorrow.utc_datetime():
current_phase_time = time
current_phase = phases[vals[i]]
else:
i -= 1
current_phase_time = None
current_phase = phases[vals[i]]
else:
current_phase = phases[vals[i]]

break

for j in range(i + 1, len(times)):
if vals[j] in [0, 2, 4, 6]:
next_phase_time = times[j]
break

return MoonPhase(current_phase,
current_phase_time.utc_datetime() if current_phase_time is not None else None,
next_phase_time.utc_datetime() if next_phase_time is not None else None)


class AsterEphemerides(Serializable): class AsterEphemerides(Serializable):
def __init__(self, def __init__(self,
rise_time: Union[datetime, None], rise_time: Union[datetime, None],
@@ -267,8 +192,6 @@ class AsterEphemerides(Serializable):
} }




MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']

EARTH = Planet('Earth', 'EARTH') EARTH = Planet('Earth', 'EARTH')


ASTERS = [Star(_('Sun'), 'SUN', radius=696342), ASTERS = [Star(_('Sun'), 'SUN', radius=696342),


+ 5
- 7
kosmorrolib/dumper.py View File

@@ -23,6 +23,7 @@ import os
from pathlib import Path from pathlib import Path
from tabulate import tabulate from tabulate import tabulate
from termcolor import colored from termcolor import colored

from .data import ASTERS, AsterEphemerides, MoonPhase, Event from .data import ASTERS, AsterEphemerides, MoonPhase, Event
from .i18n import _, FULL_DATE_FORMAT, SHORT_DATETIME_FORMAT, TIME_FORMAT from .i18n import _, FULL_DATE_FORMAT, SHORT_DATETIME_FORMAT, TIME_FORMAT
from .version import VERSION from .version import VERSION
@@ -159,9 +160,9 @@ class TextDumper(Dumper):
if moon_phase is None: if moon_phase is None:
return _('Moon phase is unavailable for this date.') return _('Moon phase is unavailable for this date.')


current_moon_phase = ' '.join([self.style(_('Moon phase:'), 'strong'), moon_phase.get_phase()])
current_moon_phase = ' '.join([self.style(_('Moon phase:'), 'strong'), moon_phase.phase_type.value])
new_moon_phase = _('{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}').format( new_moon_phase = _('{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}').format(
next_moon_phase=moon_phase.get_next_phase_name(),
next_moon_phase=moon_phase.get_next_phase().value,
next_moon_phase_date=moon_phase.next_phase_date.strftime(FULL_DATE_FORMAT), next_moon_phase_date=moon_phase.next_phase_date.strftime(FULL_DATE_FORMAT),
next_moon_phase_time=moon_phase.next_phase_date.strftime(TIME_FORMAT) next_moon_phase_time=moon_phase.next_phase_date.strftime(TIME_FORMAT)
) )
@@ -183,12 +184,9 @@ class _LatexDumper(Dumper):
kosmorro_logo_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), kosmorro_logo_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
'assets', 'png', 'kosmorro-logo.png') 'assets', 'png', 'kosmorro-logo.png')


if self.moon_phase is None:
self.moon_phase = MoonPhase('UNKNOWN')

moon_phase_graphics = os.path.join(os.path.abspath(os.path.dirname(__file__)), moon_phase_graphics = os.path.join(os.path.abspath(os.path.dirname(__file__)),
'assets', 'moonphases', 'png', 'assets', 'moonphases', 'png',
'.'.join([self.moon_phase.identifier.lower().replace('_', '-'),
'.'.join([self.moon_phase.phase_type.name.lower().replace('_', '-'),
'png'])) 'png']))


document = template document = template
@@ -234,7 +232,7 @@ class _LatexDumper(Dumper):
.replace('+++GRAPH_LABEL_HOURS+++', _('hours')) \ .replace('+++GRAPH_LABEL_HOURS+++', _('hours')) \
.replace('+++MOON-PHASE-GRAPHICS+++', moon_phase_graphics) \ .replace('+++MOON-PHASE-GRAPHICS+++', moon_phase_graphics) \
.replace('+++CURRENT-MOON-PHASE-TITLE+++', _('Moon phase:')) \ .replace('+++CURRENT-MOON-PHASE-TITLE+++', _('Moon phase:')) \
.replace('+++CURRENT-MOON-PHASE+++', self.moon_phase.get_phase()) \
.replace('+++CURRENT-MOON-PHASE+++', self.moon_phase.phase_type.value) \
.replace('+++SECTION-EVENTS+++', _('Expected events')) \ .replace('+++SECTION-EVENTS+++', _('Expected events')) \
.replace('+++EVENTS+++', self._make_events()) .replace('+++EVENTS+++', self._make_events())




+ 40
- 0
kosmorrolib/enum.py View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python3

# Kosmorro - Compute The Next Ephemerides
# Copyright (C) 2019 Jérôme Deuchnord <jerome@deuchnord.fr>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from enum import Enum
from .i18n import _


class MoonPhaseType(Enum):
NEW_MOON = _('New Moon')
WAXING_CRESCENT = _('Waxing crescent')
FIRST_QUARTER = _('First Quarter')
WAXING_GIBBOUS = _('Waxing gibbous')
FULL_MOON = _('Full Moon')
WANING_GIBBOUS = _('Waning gibbous')
LAST_QUARTER = _('Last Quarter')
WANING_CRESCENT = _('Waning crescent')


class EventType(Enum):
OPPOSITION = _('%s is in opposition')
CONJUNCTION = _('%s and %s are in conjunction')
OCCULTATION = _('%s occults %s')
MAXIMAL_ELONGATION = _("%s's largest elongation")
MOON_PERIGEE = _("%s is at its perigee")
MOON_APOGEE = _("%s is at its apogee")

+ 41
- 2
kosmorrolib/ephemerides.py View File

@@ -17,20 +17,59 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.


import datetime import datetime
from typing import Union


from skyfield.searchlib import find_discrete, find_maxima from skyfield.searchlib import find_discrete, find_maxima
from skyfield.timelib import Time from skyfield.timelib import Time
from skyfield.constants import tau from skyfield.constants import tau
from skyfield.errors import EphemerisRangeError from skyfield.errors import EphemerisRangeError


from .data import Position, AsterEphemerides, MoonPhase, Object, ASTERS, skyfield_to_moon_phase
from .data import Position, AsterEphemerides, MoonPhase, Object, ASTERS
from .dateutil import translate_to_timezone from .dateutil import translate_to_timezone
from .core import get_skf_objects, get_timescale, get_iau2000b from .core import get_skf_objects, get_timescale, get_iau2000b
from .enum import MoonPhaseType
from .exceptions import OutOfRangeDateError from .exceptions import OutOfRangeDateError


RISEN_ANGLE = -0.8333 RISEN_ANGLE = -0.8333




def _get_skyfield_to_moon_phase(times: [Time], vals: [int], now: Time) -> Union[MoonPhase, None]:
tomorrow = get_timescale().utc(now.utc_datetime().year, now.utc_datetime().month, now.utc_datetime().day + 1)

phases = list(MoonPhaseType)
current_phase = None
current_phase_time = None
next_phase_time = None
i = 0

if len(times) == 0:
return None

for i, time in enumerate(times):
if now.utc_iso() <= time.utc_iso():
if vals[i] in [0, 2, 4, 6]:
if time.utc_datetime() < tomorrow.utc_datetime():
current_phase_time = time
current_phase = phases[vals[i]]
else:
i -= 1
current_phase_time = None
current_phase = phases[vals[i]]
else:
current_phase = phases[vals[i]]

break

for j in range(i + 1, len(times)):
if vals[j] in [0, 2, 4, 6]:
next_phase_time = times[j]
break

return MoonPhase(current_phase,
current_phase_time.utc_datetime() if current_phase_time is not None else None,
next_phase_time.utc_datetime() if next_phase_time is not None else None)


def get_moon_phase(compute_date: datetime.date, timezone: int = 0) -> MoonPhase: def get_moon_phase(compute_date: datetime.date, timezone: int = 0) -> MoonPhase:
earth = get_skf_objects()['earth'] earth = get_skf_objects()['earth']
moon = get_skf_objects()['moon'] moon = get_skf_objects()['moon']
@@ -60,7 +99,7 @@ def get_moon_phase(compute_date: datetime.date, timezone: int = 0) -> MoonPhase:


raise OutOfRangeDateError(start, end) raise OutOfRangeDateError(start, end)


return skyfield_to_moon_phase(times, phase, today)
return _get_skyfield_to_moon_phase(times, phase, today)




def get_ephemerides(date: datetime.date, position: Position, timezone: int = 0) -> [AsterEphemerides]: def get_ephemerides(date: datetime.date, position: Position, timezone: int = 0) -> [AsterEphemerides]:


+ 9
- 6
kosmorrolib/events.py View File

@@ -25,6 +25,7 @@ from numpy import pi


from .data import Event, Star, Planet, ASTERS from .data import Event, Star, Planet, ASTERS
from .dateutil import translate_to_timezone from .dateutil import translate_to_timezone
from .enum import EventType
from .exceptions import OutOfRangeDateError from .exceptions import OutOfRangeDateError
from .core import get_timescale, get_skf_objects, flatten_list from .core import get_timescale, get_skf_objects, flatten_list


@@ -68,10 +69,10 @@ def _search_conjunction(start_time: Time, end_time: Time, timezone: int) -> [Eve
aster2] if aster1_pos.distance().km < aster2_pos.distance().km else [aster2, aster2] if aster1_pos.distance().km < aster2_pos.distance().km else [aster2,
aster1] aster1]


conjunctions.append(Event('OCCULTATION', occulting_aster,
conjunctions.append(Event(EventType.OCCULTATION, occulting_aster,
translate_to_timezone(time.utc_datetime(), timezone))) translate_to_timezone(time.utc_datetime(), timezone)))
else: else:
conjunctions.append(Event('CONJUNCTION', [aster1, aster2],
conjunctions.append(Event(EventType.CONJUNCTION, [aster1, aster2],
translate_to_timezone(time.utc_datetime(), timezone))) translate_to_timezone(time.utc_datetime(), timezone)))


computed.append(aster1) computed.append(aster1)
@@ -101,7 +102,7 @@ def _search_oppositions(start_time: Time, end_time: Time, timezone: int) -> [Eve


times, _ = find_discrete(start_time, end_time, is_oppositing) times, _ = find_discrete(start_time, end_time, is_oppositing)
for time in times: for time in times:
events.append(Event('OPPOSITION', [aster], translate_to_timezone(time.utc_datetime(), timezone)))
events.append(Event(EventType.OPPOSITION, [aster], translate_to_timezone(time.utc_datetime(), timezone)))


return events return events


@@ -129,7 +130,9 @@ def _search_maximal_elongations(start_time: Time, end_time: Time, timezone: int)


for i, time in enumerate(times): for i, time in enumerate(times):
elongation = elongations[i] elongation = elongations[i]
events.append(Event('MAXIMAL_ELONGATION', [aster], translate_to_timezone(time.utc_datetime(), timezone),
events.append(Event(EventType.MAXIMAL_ELONGATION,
[aster],
translate_to_timezone(time.utc_datetime(), timezone),
details='{:.3n}°'.format(elongation))) details='{:.3n}°'.format(elongation)))


return events return events
@@ -157,7 +160,7 @@ def _search_moon_apogee(start_time: Time, end_time: Time, timezone: int) -> [Eve
times, _ = find_maxima(start_time, end_time, f=_get_moon_distance(), epsilon=1./24/60) times, _ = find_maxima(start_time, end_time, f=_get_moon_distance(), epsilon=1./24/60)


for time in times: for time in times:
events.append(Event('MOON_APOGEE', [moon], translate_to_timezone(time.utc_datetime(), timezone)))
events.append(Event(EventType.MOON_APOGEE, [moon], translate_to_timezone(time.utc_datetime(), timezone)))


return events return events


@@ -169,7 +172,7 @@ def _search_moon_perigee(start_time: Time, end_time: Time, timezone: int) -> [Ev
times, _ = find_minima(start_time, end_time, f=_get_moon_distance(), epsilon=1./24/60) times, _ = find_minima(start_time, end_time, f=_get_moon_distance(), epsilon=1./24/60)


for time in times: for time in times:
events.append(Event('MOON_PERIGEE', [moon], translate_to_timezone(time.utc_datetime(), timezone)))
events.append(Event(EventType.MOON_PERIGEE, [moon], translate_to_timezone(time.utc_datetime(), timezone)))


return events return events




+ 90
- 94
kosmorrolib/locales/messages.pot View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: kosmorro 0.8.1\n" "Project-Id-Version: kosmorro 0.8.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2020-12-01 12:01+0100\n"
"POT-Creation-Date: 2020-12-02 10:22+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -27,182 +27,116 @@ msgid ""
"offset format." "offset format."
msgstr "" msgstr ""


#: kosmorrolib/data.py:32
msgid "New Moon"
msgstr ""

#: kosmorrolib/data.py:33
msgid "Waxing crescent"
msgstr ""

#: kosmorrolib/data.py:34
msgid "First Quarter"
msgstr ""

#: kosmorrolib/data.py:35
msgid "Waxing gibbous"
msgstr ""

#: kosmorrolib/data.py:36
msgid "Full Moon"
msgstr ""

#: kosmorrolib/data.py:37
msgid "Waning gibbous"
msgstr ""

#: kosmorrolib/data.py:38
msgid "Last Quarter"
msgstr ""

#: kosmorrolib/data.py:39
msgid "Waning crescent"
msgstr ""

#: kosmorrolib/data.py:40
msgid "Unavailable"
msgstr ""

#: kosmorrolib/data.py:44
#, python-format
msgid "%s is in opposition"
msgstr ""

#: kosmorrolib/data.py:45
#, python-format
msgid "%s and %s are in conjunction"
msgstr ""

#: kosmorrolib/data.py:46
#, python-format
msgid "%s occults %s"
msgstr ""

#: kosmorrolib/data.py:47
#, python-format
msgid "%s's largest elongation"
msgstr ""

#: kosmorrolib/data.py:48
#, python-format
msgid "%s is at its perigee"
msgstr ""

#: kosmorrolib/data.py:49
#, python-format
msgid "%s is at its apogee"
msgstr ""

#: kosmorrolib/data.py:274
#: kosmorrolib/data.py:197
msgid "Sun" msgid "Sun"
msgstr "" msgstr ""


#: kosmorrolib/data.py:275
#: kosmorrolib/data.py:198
msgid "Moon" msgid "Moon"
msgstr "" msgstr ""


#: kosmorrolib/data.py:276
#: kosmorrolib/data.py:199
msgid "Mercury" msgid "Mercury"
msgstr "" msgstr ""


#: kosmorrolib/data.py:277
#: kosmorrolib/data.py:200
msgid "Venus" msgid "Venus"
msgstr "" msgstr ""


#: kosmorrolib/data.py:278
#: kosmorrolib/data.py:201
msgid "Mars" msgid "Mars"
msgstr "" msgstr ""


#: kosmorrolib/data.py:279
#: kosmorrolib/data.py:202
msgid "Jupiter" msgid "Jupiter"
msgstr "" msgstr ""


#: kosmorrolib/data.py:280
#: kosmorrolib/data.py:203
msgid "Saturn" msgid "Saturn"
msgstr "" msgstr ""


#: kosmorrolib/data.py:281
#: kosmorrolib/data.py:204
msgid "Uranus" msgid "Uranus"
msgstr "" msgstr ""


#: kosmorrolib/data.py:282
#: kosmorrolib/data.py:205
msgid "Neptune" msgid "Neptune"
msgstr "" msgstr ""


#: kosmorrolib/data.py:283
#: kosmorrolib/data.py:206
msgid "Pluto" msgid "Pluto"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:87
#: kosmorrolib/dumper.py:88
msgid "Expected events:" msgid "Expected events:"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:91
#: kosmorrolib/dumper.py:92
msgid "Note: All the hours are given in UTC." msgid "Note: All the hours are given in UTC."
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:96
#: kosmorrolib/dumper.py:97
msgid "Note: All the hours are given in the UTC{offset} timezone." msgid "Note: All the hours are given in the UTC{offset} timezone."
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:142 kosmorrolib/dumper.py:229
#: kosmorrolib/dumper.py:143 kosmorrolib/dumper.py:227
msgid "Object" msgid "Object"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:143 kosmorrolib/dumper.py:230
#: kosmorrolib/dumper.py:144 kosmorrolib/dumper.py:228
msgid "Rise time" msgid "Rise time"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:144 kosmorrolib/dumper.py:231
#: kosmorrolib/dumper.py:145 kosmorrolib/dumper.py:229
msgid "Culmination time" msgid "Culmination time"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:145 kosmorrolib/dumper.py:232
#: kosmorrolib/dumper.py:146 kosmorrolib/dumper.py:230
msgid "Set time" msgid "Set time"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:160
#: kosmorrolib/dumper.py:161
msgid "Moon phase is unavailable for this date." msgid "Moon phase is unavailable for this date."
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:162 kosmorrolib/dumper.py:236
#: kosmorrolib/dumper.py:163 kosmorrolib/dumper.py:234
msgid "Moon phase:" msgid "Moon phase:"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:163
#: kosmorrolib/dumper.py:164
msgid "{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}" msgid "{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:216
#: kosmorrolib/dumper.py:214
msgid "A Summary of your Sky" msgid "A Summary of your Sky"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:220
#: kosmorrolib/dumper.py:218
msgid "" msgid ""
"This document summarizes the ephemerides and the events of {date}. It " "This document summarizes the ephemerides and the events of {date}. It "
"aims to help you to prepare your observation session. All the hours are " "aims to help you to prepare your observation session. All the hours are "
"given in {timezone}." "given in {timezone}."
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:226
#: kosmorrolib/dumper.py:224
msgid "" msgid ""
"Don't forget to check the weather forecast before you go out with your " "Don't forget to check the weather forecast before you go out with your "
"equipment." "equipment."
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:228
#: kosmorrolib/dumper.py:226
msgid "Ephemerides of the day" msgid "Ephemerides of the day"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:234
#: kosmorrolib/dumper.py:232
msgid "hours" msgid "hours"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:238
#: kosmorrolib/dumper.py:236
msgid "Expected events" msgid "Expected events"
msgstr "" msgstr ""


#: kosmorrolib/dumper.py:352
#: kosmorrolib/dumper.py:350
msgid "" msgid ""
"Building PDFs was not possible, because some dependencies are not " "Building PDFs was not possible, because some dependencies are not "
"installed.\n" "installed.\n"
@@ -210,6 +144,68 @@ msgid ""
"information." "information."
msgstr "" msgstr ""


#: kosmorrolib/enum.py:24
msgid "New Moon"
msgstr ""

#: kosmorrolib/enum.py:25
msgid "Waxing crescent"
msgstr ""

#: kosmorrolib/enum.py:26
msgid "First Quarter"
msgstr ""

#: kosmorrolib/enum.py:27
msgid "Waxing gibbous"
msgstr ""

#: kosmorrolib/enum.py:28
msgid "Full Moon"
msgstr ""

#: kosmorrolib/enum.py:29
msgid "Waning gibbous"
msgstr ""

#: kosmorrolib/enum.py:30
msgid "Last Quarter"
msgstr ""

#: kosmorrolib/enum.py:31
msgid "Waning crescent"
msgstr ""

#: kosmorrolib/enum.py:35
#, python-format
msgid "%s is in opposition"
msgstr ""

#: kosmorrolib/enum.py:36
#, python-format
msgid "%s and %s are in conjunction"
msgstr ""

#: kosmorrolib/enum.py:37
#, python-format
msgid "%s occults %s"
msgstr ""

#: kosmorrolib/enum.py:38
#, python-format
msgid "%s's largest elongation"
msgstr ""

#: kosmorrolib/enum.py:39
#, python-format
msgid "%s is at its perigee"
msgstr ""

#: kosmorrolib/enum.py:40
#, python-format
msgid "%s is at its apogee"
msgstr ""

#: kosmorrolib/exceptions.py:34 #: kosmorrolib/exceptions.py:34
msgid "The date must be between {minimum_date} and {maximum_date}" msgid "The date must be between {minimum_date} and {maximum_date}"
msgstr "" msgstr ""


+ 4
- 3
test/dumper.py View File

@@ -3,6 +3,7 @@ from datetime import date, datetime


from kosmorrolib.data import AsterEphemerides, Planet, MoonPhase, Event from kosmorrolib.data import AsterEphemerides, Planet, MoonPhase, Event
from kosmorrolib.dumper import JsonDumper, TextDumper, _LatexDumper from kosmorrolib.dumper import JsonDumper, TextDumper, _LatexDumper
from kosmorrolib.enum import MoonPhaseType, EventType




class DumperTestCase(unittest.TestCase): class DumperTestCase(unittest.TestCase):
@@ -283,14 +284,14 @@ class DumperTestCase(unittest.TestCase):


@staticmethod @staticmethod
def _get_moon_phase(): def _get_moon_phase():
return MoonPhase('FULL_MOON', datetime(2019, 10, 14), datetime(2019, 10, 21))
return MoonPhase(MoonPhaseType.FULL_MOON, datetime(2019, 10, 14), datetime(2019, 10, 21))


@staticmethod @staticmethod
def _get_events(): def _get_events():
return [Event('OPPOSITION',
return [Event(EventType.OPPOSITION,
[Planet('Mars', 'MARS')], [Planet('Mars', 'MARS')],
datetime(2019, 10, 14, 23, 00)), datetime(2019, 10, 14, 23, 00)),
Event('MAXIMAL_ELONGATION',
Event(EventType.MAXIMAL_ELONGATION,
[Planet('Venus', 'VENUS')], [Planet('Venus', 'VENUS')],
datetime(2019, 10, 14, 12, 00), details='42.0°'), datetime(2019, 10, 14, 12, 00), details='42.0°'),
] ]


+ 34
- 31
test/ephemerides.py View File

@@ -1,7 +1,10 @@
import unittest import unittest

from .testutils import expect_assertions from .testutils import expect_assertions
from kosmorrolib import ephemerides from kosmorrolib import ephemerides
from kosmorrolib.data import EARTH, Position, MoonPhase from kosmorrolib.data import EARTH, Position, MoonPhase
from kosmorrolib.enum import MoonPhaseType

from datetime import date from datetime import date
from kosmorrolib.exceptions import OutOfRangeDateError from kosmorrolib.exceptions import OutOfRangeDateError


@@ -29,84 +32,84 @@ class EphemeridesTestCase(unittest.TestCase):


def test_moon_phase_new_moon(self): def test_moon_phase_new_moon(self):
phase = ephemerides.get_moon_phase(date(2019, 11, 25)) phase = ephemerides.get_moon_phase(date(2019, 11, 25))
self.assertEqual('WANING_CRESCENT', phase.identifier)
self.assertEqual(MoonPhaseType.WANING_CRESCENT, phase.phase_type)
self.assertIsNone(phase.time) self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T')


phase = ephemerides.get_moon_phase(date(2019, 11, 26)) phase = ephemerides.get_moon_phase(date(2019, 11, 26))
self.assertEqual('NEW_MOON', phase.identifier)
self.assertEqual(MoonPhaseType.NEW_MOON, phase.phase_type)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-12-04T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-12-04T')


phase = ephemerides.get_moon_phase(date(2019, 11, 27)) phase = ephemerides.get_moon_phase(date(2019, 11, 27))
self.assertEqual('WAXING_CRESCENT', phase.identifier)
self.assertEqual(MoonPhaseType.WAXING_CRESCENT, phase.phase_type)
self.assertIsNone(phase.time) self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-12-04T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-12-04T')


def test_moon_phase_first_crescent(self): def test_moon_phase_first_crescent(self):
phase = ephemerides.get_moon_phase(date(2019, 11, 3)) phase = ephemerides.get_moon_phase(date(2019, 11, 3))
self.assertEqual('WAXING_CRESCENT', phase.identifier)
self.assertEqual(MoonPhaseType.WAXING_CRESCENT, phase.phase_type)
self.assertIsNone(phase.time) self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-04T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-04T')


phase = ephemerides.get_moon_phase(date(2019, 11, 4)) phase = ephemerides.get_moon_phase(date(2019, 11, 4))
self.assertEqual('FIRST_QUARTER', phase.identifier)
self.assertEqual(MoonPhaseType.FIRST_QUARTER, phase.phase_type)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T')


phase = ephemerides.get_moon_phase(date(2019, 11, 5)) phase = ephemerides.get_moon_phase(date(2019, 11, 5))
self.assertEqual('WAXING_GIBBOUS', phase.identifier)
self.assertEqual(MoonPhaseType.WAXING_GIBBOUS, phase.phase_type)
self.assertIsNone(phase.time) self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T')


def test_moon_phase_full_moon(self): def test_moon_phase_full_moon(self):
phase = ephemerides.get_moon_phase(date(2019, 11, 11)) phase = ephemerides.get_moon_phase(date(2019, 11, 11))
self.assertEqual('WAXING_GIBBOUS', phase.identifier)
self.assertEqual(MoonPhaseType.WAXING_GIBBOUS, phase.phase_type)
self.assertIsNone(phase.time) self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-12T')


phase = ephemerides.get_moon_phase(date(2019, 11, 12)) phase = ephemerides.get_moon_phase(date(2019, 11, 12))
self.assertEqual('FULL_MOON', phase.identifier)
self.assertEqual(MoonPhaseType.FULL_MOON, phase.phase_type)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T')


phase = ephemerides.get_moon_phase(date(2019, 11, 13)) phase = ephemerides.get_moon_phase(date(2019, 11, 13))
self.assertEqual('WANING_GIBBOUS', phase.identifier)
self.assertEqual(MoonPhaseType.WANING_GIBBOUS, phase.phase_type)
self.assertIsNone(phase.time) self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T')


def test_moon_phase_last_quarter(self): def test_moon_phase_last_quarter(self):
phase = ephemerides.get_moon_phase(date(2019, 11, 18)) phase = ephemerides.get_moon_phase(date(2019, 11, 18))
self.assertEqual('WANING_GIBBOUS', phase.identifier)
self.assertEqual(MoonPhaseType.WANING_GIBBOUS, phase.phase_type)
self.assertIsNone(phase.time) self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-19T')


phase = ephemerides.get_moon_phase(date(2019, 11, 19)) phase = ephemerides.get_moon_phase(date(2019, 11, 19))
self.assertEqual('LAST_QUARTER', phase.identifier)
self.assertEqual(MoonPhaseType.LAST_QUARTER, phase.phase_type)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T')


phase = ephemerides.get_moon_phase(date(2019, 11, 20)) phase = ephemerides.get_moon_phase(date(2019, 11, 20))
self.assertEqual('WANING_CRESCENT', phase.identifier)
self.assertEqual(MoonPhaseType.WANING_CRESCENT, phase.phase_type)
self.assertIsNone(phase.time) self.assertIsNone(phase.time)
self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T') self.assertRegexpMatches(phase.next_phase_date.isoformat(), '^2019-11-26T')


def test_moon_phase_prediction(self): def test_moon_phase_prediction(self):
phase = MoonPhase('NEW_MOON', None, None)
self.assertEqual('First Quarter', phase.get_next_phase_name())
phase = MoonPhase('WAXING_CRESCENT', None, None)
self.assertEqual('First Quarter', phase.get_next_phase_name())
phase = MoonPhase('FIRST_QUARTER', None, None)
self.assertEqual('Full Moon', phase.get_next_phase_name())
phase = MoonPhase('WAXING_GIBBOUS', None, None)
self.assertEqual('Full Moon', phase.get_next_phase_name())
phase = MoonPhase('FULL_MOON', None, None)
self.assertEqual('Last Quarter', phase.get_next_phase_name())
phase = MoonPhase('WANING_GIBBOUS', None, None)
self.assertEqual('Last Quarter', phase.get_next_phase_name())
phase = MoonPhase('LAST_QUARTER', None, None)
self.assertEqual('New Moon', phase.get_next_phase_name())
phase = MoonPhase('WANING_CRESCENT', None, None)
self.assertEqual('New Moon', phase.get_next_phase_name())
phase = MoonPhase(MoonPhaseType.NEW_MOON, None, None)
self.assertEqual(MoonPhaseType.FIRST_QUARTER, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.WAXING_CRESCENT, None, None)
self.assertEqual(MoonPhaseType.FIRST_QUARTER, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.FIRST_QUARTER, None, None)
self.assertEqual(MoonPhaseType.FULL_MOON, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.WAXING_GIBBOUS, None, None)
self.assertEqual(MoonPhaseType.FULL_MOON, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.FULL_MOON, None, None)
self.assertEqual(MoonPhaseType.LAST_QUARTER, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.WANING_GIBBOUS, None, None)
self.assertEqual(MoonPhaseType.LAST_QUARTER, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.LAST_QUARTER, None, None)
self.assertEqual(MoonPhaseType.NEW_MOON, phase.get_next_phase())
phase = MoonPhase(MoonPhaseType.WANING_CRESCENT, None, None)
self.assertEqual(MoonPhaseType.NEW_MOON, phase.get_next_phase())


def test_get_ephemerides_raises_exception_on_out_of_date_range(self): def test_get_ephemerides_raises_exception_on_out_of_date_range(self):
with self.assertRaises(OutOfRangeDateError): with self.assertRaises(OutOfRangeDateError):


+ 21
- 26
test/events.py View File

@@ -1,12 +1,11 @@
import unittest import unittest


from datetime import date, datetime from datetime import date, datetime
from json import dumps
from unittest_data_provider import data_provider


from kosmorrolib import events from kosmorrolib import events
from kosmorrolib.data import Event, ASTERS from kosmorrolib.data import Event, ASTERS
from kosmorrolib.core import get_timescale
from unittest_data_provider import data_provider
from kosmorrolib.enum import EventType
from kosmorrolib.exceptions import OutOfRangeDateError from kosmorrolib.exceptions import OutOfRangeDateError




@@ -14,42 +13,38 @@ class EventTestCase(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.maxDiff = None self.maxDiff = None


def test_event_only_accepts_valid_values(self):
with self.assertRaises(ValueError):
Event('SUPERNOVA', None, get_timescale().now())

expected_events_provider = lambda: ( expected_events_provider = lambda: (
(date(2020, 2, 7), []), (date(2020, 2, 7), []),


(date(2020, 10, 13), [Event('OPPOSITION', [ASTERS[4]], datetime(2020, 10, 13, 23, 25))]),
(date(2020, 10, 13), [Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2020, 10, 13, 23, 25))]),


(date(2022, 12, 8), [Event('CONJUNCTION', [ASTERS[1], ASTERS[4]], datetime(2022, 12, 8, 4, 18)),
Event('OPPOSITION', [ASTERS[4]], datetime(2022, 12, 8, 5, 41))]),
(date(2022, 12, 8), [Event(EventType.CONJUNCTION, [ASTERS[1], ASTERS[4]], datetime(2022, 12, 8, 4, 18)),
Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2022, 12, 8, 5, 41))]),


(date(2025, 1, 16), [Event('OPPOSITION', [ASTERS[4]], datetime(2025, 1, 16, 2, 38))]),
(date(2025, 1, 16), [Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2025, 1, 16, 2, 38))]),


(date(2027, 2, 19), [Event('MOON_PERIGEE', [ASTERS[1]], datetime(2027, 2, 19, 7, 38)),
Event('OPPOSITION', [ASTERS[4]], datetime(2027, 2, 19, 15, 50))]),
(date(2027, 2, 19), [Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2027, 2, 19, 7, 38)),
Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2027, 2, 19, 15, 50))]),


(date(2020, 1, 2), [Event('MOON_APOGEE', [ASTERS[1]], datetime(2020, 1, 2, 1, 32)),
Event('CONJUNCTION', [ASTERS[2], ASTERS[5]], datetime(2020, 1, 2, 16, 41))]),
(date(2020, 1, 2), [Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 1, 2, 1, 32)),
Event(EventType.CONJUNCTION, [ASTERS[2], ASTERS[5]], datetime(2020, 1, 2, 16, 41))]),


(date(2020, 1, 12), [Event('CONJUNCTION', [ASTERS[2], ASTERS[6]], datetime(2020, 1, 12, 9, 51)),
Event('CONJUNCTION', [ASTERS[2], ASTERS[9]], datetime(2020, 1, 12, 10, 13)),
Event('CONJUNCTION', [ASTERS[6], ASTERS[9]], datetime(2020, 1, 12, 16, 57))]),
(date(2020, 1, 12), [Event(EventType.CONJUNCTION, [ASTERS[2], ASTERS[6]], datetime(2020, 1, 12, 9, 51)),
Event(EventType.CONJUNCTION, [ASTERS[2], ASTERS[9]], datetime(2020, 1, 12, 10, 13)),
Event(EventType.CONJUNCTION, [ASTERS[6], ASTERS[9]], datetime(2020, 1, 12, 16, 57))]),


(date(2020, 2, 10), [Event('MAXIMAL_ELONGATION', [ASTERS[2]], datetime(2020, 2, 10, 13, 46), details='18.2°'),
Event('MOON_PERIGEE', [ASTERS[1]], datetime(2020, 2, 10, 20, 34))]),
(date(2020, 2, 10), [Event(EventType.MAXIMAL_ELONGATION, [ASTERS[2]], datetime(2020, 2, 10, 13, 46), details='18.2°'),
Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 2, 10, 20, 34))]),


(date(2020, 3, 24), [Event('MAXIMAL_ELONGATION', [ASTERS[2]], datetime(2020, 3, 24, 1, 56), details='27.8°'),
Event('MOON_APOGEE', [ASTERS[1]], datetime(2020, 3, 24, 15, 39)),
Event('MAXIMAL_ELONGATION', [ASTERS[3]], datetime(2020, 3, 24, 21, 58), details='46.1°')]),
(date(2020, 3, 24), [Event(EventType.MAXIMAL_ELONGATION, [ASTERS[2]], datetime(2020, 3, 24, 1, 56), details='27.8°'),
Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 3, 24, 15, 39)),
Event(EventType.MAXIMAL_ELONGATION, [ASTERS[3]], datetime(2020, 3, 24, 21, 58), details='46.1°')]),


(date(2005, 6, 16), [Event('OCCULTATION', [ASTERS[1], ASTERS[5]], datetime(2005, 6, 16, 6, 31))]),
(date(2005, 6, 16), [Event(EventType.OCCULTATION, [ASTERS[1], ASTERS[5]], datetime(2005, 6, 16, 6, 31))]),


(date(2020, 4, 7), [Event('MOON_PERIGEE', [ASTERS[1]], datetime(2020, 4, 7, 18, 14))]),
(date(2020, 4, 7), [Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 4, 7, 18, 14))]),


(date(2020, 1, 29), [Event('MOON_APOGEE', [ASTERS[1]], datetime(2020, 1, 29, 21, 32))])
(date(2020, 1, 29), [Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 1, 29, 21, 32))])
) )


@data_provider(expected_events_provider) @data_provider(expected_events_provider)


Loading…
Cancel
Save