diff --git a/Makefile b/Makefile
index 8438cb2..8654a81 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,6 @@
+black:
+ pipenv run black kosmorrolib tests
+
.PHONY: test
tests: legacy-tests
python3 tests.py
diff --git a/kosmorrolib/__version__.py b/kosmorrolib/__version__.py
index fff308b..7718736 100644
--- a/kosmorrolib/__version__.py
+++ b/kosmorrolib/__version__.py
@@ -1,9 +1,9 @@
-__title__ = 'kosmorrolib'
-__description__ = 'A library that computes your ephemerides'
-__url__ = 'http://kosmorro.space'
-__version__ = '0.9.0'
+__title__ = "kosmorrolib"
+__description__ = "A library that computes your ephemerides"
+__url__ = "http://kosmorro.space"
+__version__ = "0.9.0"
__build__ = 0x000900
-__author__ = 'Jérôme Deuchnord'
-__author_email__ = 'jerome@deuchnord.fr'
-__license__ = 'AGPL'
-__copyright__ = 'Copyright 2021 Jérôme Deuchnord'
+__author__ = "Jérôme Deuchnord"
+__author_email__ = "jerome@deuchnord.fr"
+__license__ = "AGPL"
+__copyright__ = "Copyright 2021 Jérôme Deuchnord"
diff --git a/kosmorrolib/core.py b/kosmorrolib/core.py
index 6a949a5..fa0bf7c 100644
--- a/kosmorrolib/core.py
+++ b/kosmorrolib/core.py
@@ -28,7 +28,8 @@ from skyfield.api import Loader
from skyfield.timelib import Time
from skyfield.nutationlib import iau2000b
-CACHE_FOLDER = str(Path.home()) + '/.kosmorro-cache'
+CACHE_FOLDER = str(Path.home()) + "/.kosmorro-cache"
+
class Environment:
def __init__(self):
@@ -46,18 +47,20 @@ class Environment:
def __len__(self):
return len(self._vars)
+
def get_env() -> Environment:
environment = Environment()
for var in os.environ:
- if not re.search('^KOSMORRO_', var):
+ if not re.search("^KOSMORRO_", var):
continue
- [_, env] = var.split('_', 1)
+ [_, env] = var.split("_", 1)
environment.__set__(env.lower(), os.getenv(var))
return environment
+
def get_loader():
return Loader(CACHE_FOLDER)
@@ -67,7 +70,7 @@ def get_timescale():
def get_skf_objects():
- return get_loader()('de421.bsp')
+ return get_loader()("de421.bsp")
def get_iau2000b(time: Time):
@@ -92,26 +95,32 @@ def flatten_list(the_list: list):
def get_date(date_arg: str) -> date:
- if re.match(r'^\d{4}-\d{2}-\d{2}$', date_arg):
+ if re.match(r"^\d{4}-\d{2}-\d{2}$", date_arg):
try:
return date.fromisoformat(date_arg)
except ValueError as error:
- raise ValueError(_('The date {date} is not valid: {error}').format(date=date_arg,
- error=error.args[0])) from error
- elif re.match(r'^([+-])(([0-9]+)y)?[ ]?(([0-9]+)m)?[ ]?(([0-9]+)d)?$', date_arg):
+ raise ValueError(
+ _("The date {date} is not valid: {error}").format(
+ date=date_arg, error=error.args[0]
+ )
+ ) from error
+ elif re.match(r"^([+-])(([0-9]+)y)?[ ]?(([0-9]+)m)?[ ]?(([0-9]+)d)?$", date_arg):
+
def get_offset(date_arg: str, signifier: str):
- if re.search(r'([0-9]+)' + signifier, date_arg):
- return abs(int(re.search(r'[+-]?([0-9]+)' + signifier, date_arg).group(0)[:-1]))
+ if re.search(r"([0-9]+)" + signifier, date_arg):
+ return abs(
+ int(re.search(r"[+-]?([0-9]+)" + signifier, date_arg).group(0)[:-1])
+ )
return 0
- days = get_offset(date_arg, 'd')
- months = get_offset(date_arg, 'm')
- years = get_offset(date_arg, 'y')
+ days = get_offset(date_arg, "d")
+ months = get_offset(date_arg, "m")
+ years = get_offset(date_arg, "y")
- if date_arg[0] == '+':
+ if date_arg[0] == "+":
return date.today() + relativedelta(days=days, months=months, years=years)
return date.today() - relativedelta(days=days, months=months, years=years)
else:
- error_msg = 'The date {date} does not match the required YYYY-MM-DD format or the offset format.'
+ error_msg = "The date {date} does not match the required YYYY-MM-DD format or the offset format."
raise ValueError(error_msg.format(date=date_arg))
diff --git a/kosmorrolib/data.py b/kosmorrolib/data.py
index 91e9d7b..933f7a9 100644
--- a/kosmorrolib/data.py
+++ b/kosmorrolib/data.py
@@ -36,7 +36,12 @@ class Serializable(ABC):
class MoonPhase(Serializable):
- def __init__(self, phase_type: MoonPhaseType, time: datetime = None, next_phase_date: datetime = None):
+ def __init__(
+ self,
+ phase_type: MoonPhaseType,
+ time: datetime = None,
+ next_phase_date: datetime = None,
+ ):
self.phase_type = phase_type
self.time = time
self.next_phase_date = next_phase_date
@@ -44,7 +49,10 @@ class MoonPhase(Serializable):
def get_next_phase(self):
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]:
+ 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
@@ -53,12 +61,12 @@ class MoonPhase(Serializable):
def serialize(self) -> dict:
return {
- 'phase': self.phase_type.name,
- 'time': self.time.isoformat() if self.time is not None else None,
- 'next': {
- 'phase': self.get_next_phase().name,
- 'time': self.next_phase_date.isoformat()
- }
+ "phase": self.phase_type.name,
+ "time": self.time.isoformat() if self.time is not None else None,
+ "next": {
+ "phase": self.get_next_phase().name,
+ "time": self.next_phase_date.isoformat(),
+ },
}
@@ -67,10 +75,7 @@ class Object(Serializable):
An astronomical object.
"""
- def __init__(self,
- name: str,
- skyfield_name: str,
- radius: float = None):
+ def __init__(self, name: str, skyfield_name: str, radius: float = None):
"""
Initialize an astronomical object
@@ -84,7 +89,7 @@ class Object(Serializable):
self.radius = radius
def __repr__(self):
- return '' % (self.get_type(), self.name)
+ return "" % (self.get_type(), self.name)
def get_skyfield_object(self) -> SkfPlanet:
return get_skf_objects()[self.skyfield_name]
@@ -101,41 +106,54 @@ class Object(Serializable):
:return:
"""
if self.radius is None:
- raise ValueError('Missing radius for %s object' % self.name)
+ raise ValueError("Missing radius for %s object" % self.name)
- return 360 / pi * arcsin(self.radius / from_place.at(time).observe(self.get_skyfield_object()).distance().km)
+ return (
+ 360
+ / pi
+ * arcsin(
+ self.radius
+ / from_place.at(time).observe(self.get_skyfield_object()).distance().km
+ )
+ )
def serialize(self) -> dict:
return {
- 'name': self.name,
- 'type': self.get_type(),
- 'radius': self.radius,
+ "name": self.name,
+ "type": self.get_type(),
+ "radius": self.radius,
}
class Star(Object):
def get_type(self) -> str:
- return 'star'
+ return "star"
class Planet(Object):
def get_type(self) -> str:
- return 'planet'
+ return "planet"
class DwarfPlanet(Planet):
def get_type(self) -> str:
- return 'dwarf_planet'
+ return "dwarf_planet"
class Satellite(Object):
def get_type(self) -> str:
- return 'satellite'
+ return "satellite"
class Event(Serializable):
- def __init__(self, event_type: EventType, objects: [Object], start_time: datetime,
- end_time: Union[datetime, None] = None, details: str = None):
+ def __init__(
+ self,
+ event_type: EventType,
+ objects: [Object],
+ start_time: datetime,
+ end_time: Union[datetime, None] = None,
+ details: str = None,
+ ):
self.event_type = event_type
self.objects = objects
self.start_time = start_time
@@ -143,16 +161,18 @@ class Event(Serializable):
self.details = details
def __repr__(self):
- return '' % (self.event_type.name,
- self.objects,
- self.start_time,
- self.end_time,
- self.details)
+ return "" % (
+ self.event_type.name,
+ self.objects,
+ self.start_time,
+ self.end_time,
+ self.details,
+ )
def get_description(self, show_details: bool = True) -> str:
description = self.event_type.value % self._get_objects_name()
if show_details and self.details is not None:
- description += ' ({:s})'.format(self.details)
+ description += " ({:s})".format(self.details)
return description
def _get_objects_name(self):
@@ -163,20 +183,22 @@ class Event(Serializable):
def serialize(self) -> dict:
return {
- 'objects': [object.serialize() for object in self.objects],
- 'EventType': self.event_type.name,
- 'starts_at': self.start_time.isoformat(),
- 'ends_at': self.end_time.isoformat() if self.end_time is not None else None,
- 'details': self.details
+ "objects": [object.serialize() for object in self.objects],
+ "EventType": self.event_type.name,
+ "starts_at": self.start_time.isoformat(),
+ "ends_at": self.end_time.isoformat() if self.end_time is not None else None,
+ "details": self.details,
}
class AsterEphemerides(Serializable):
- def __init__(self,
- rise_time: Union[datetime, None],
- culmination_time: Union[datetime, None],
- set_time: Union[datetime, None],
- aster: Object):
+ def __init__(
+ self,
+ rise_time: Union[datetime, None],
+ culmination_time: Union[datetime, None],
+ set_time: Union[datetime, None],
+ aster: Object,
+ ):
self.rise_time = rise_time
self.culmination_time = culmination_time
self.set_time = set_time
@@ -184,25 +206,33 @@ class AsterEphemerides(Serializable):
def serialize(self) -> dict:
return {
- 'object': self.object.serialize(),
- 'rise_time': self.rise_time.isoformat() if self.rise_time is not None else None,
- 'culmination_time': self.culmination_time.isoformat() if self.culmination_time is not None else None,
- 'set_time': self.set_time.isoformat() if self.set_time is not None else None
+ "object": self.object.serialize(),
+ "rise_time": self.rise_time.isoformat()
+ if self.rise_time is not None
+ else None,
+ "culmination_time": self.culmination_time.isoformat()
+ if self.culmination_time is not None
+ else None,
+ "set_time": self.set_time.isoformat()
+ if self.set_time is not None
+ else None,
}
-EARTH = Planet('Earth', 'EARTH')
+EARTH = Planet("Earth", "EARTH")
-ASTERS = [Star('Sun', 'SUN', radius=696342),
- Satellite('Moon', 'MOON', radius=1737.4),
- Planet('Mercury', 'MERCURY', radius=2439.7),
- Planet('Venus', 'VENUS', radius=6051.8),
- Planet('Mars', 'MARS', radius=3396.2),
- Planet('Jupiter', 'JUPITER BARYCENTER', radius=71492),
- Planet('Saturn', 'SATURN BARYCENTER', radius=60268),
- Planet('Uranus', 'URANUS BARYCENTER', radius=25559),
- Planet('Neptune', 'NEPTUNE BARYCENTER', radius=24764),
- Planet('Pluto', 'PLUTO BARYCENTER', radius=1185)]
+ASTERS = [
+ Star("Sun", "SUN", radius=696342),
+ Satellite("Moon", "MOON", radius=1737.4),
+ Planet("Mercury", "MERCURY", radius=2439.7),
+ Planet("Venus", "VENUS", radius=6051.8),
+ Planet("Mars", "MARS", radius=3396.2),
+ Planet("Jupiter", "JUPITER BARYCENTER", radius=71492),
+ Planet("Saturn", "SATURN BARYCENTER", radius=60268),
+ Planet("Uranus", "URANUS BARYCENTER", radius=25559),
+ Planet("Neptune", "NEPTUNE BARYCENTER", radius=24764),
+ Planet("Pluto", "PLUTO BARYCENTER", radius=1185),
+]
class Position:
@@ -214,10 +244,11 @@ class Position:
def get_planet_topos(self) -> Topos:
if self.aster is None:
- raise TypeError('Observation planet must be set.')
+ raise TypeError("Observation planet must be set.")
if self._topos is None:
- self._topos = self.aster.get_skyfield_object() + Topos(latitude_degrees=self.latitude,
- longitude_degrees=self.longitude)
+ self._topos = self.aster.get_skyfield_object() + Topos(
+ latitude_degrees=self.latitude, longitude_degrees=self.longitude
+ )
return self._topos
diff --git a/kosmorrolib/dateutil.py b/kosmorrolib/dateutil.py
index 6ff64d4..84dccd5 100644
--- a/kosmorrolib/dateutil.py
+++ b/kosmorrolib/dateutil.py
@@ -25,4 +25,6 @@ def translate_to_timezone(date: datetime, to_tz: int, from_tz: int = None):
else:
source_tz = timezone.utc
- return date.replace(tzinfo=source_tz).astimezone(tz=timezone(timedelta(hours=to_tz)))
+ return date.replace(tzinfo=source_tz).astimezone(
+ tz=timezone(timedelta(hours=to_tz))
+ )
diff --git a/kosmorrolib/enum.py b/kosmorrolib/enum.py
index 29b185f..699103a 100644
--- a/kosmorrolib/enum.py
+++ b/kosmorrolib/enum.py
@@ -21,6 +21,7 @@ from enum import Enum, auto
class MoonPhaseType(Enum):
"""An enumeration of moon phases."""
+
NEW_MOON = 1
WAXING_CRESCENT = 2
FIRST_QUARTER = 3
@@ -33,6 +34,7 @@ class MoonPhaseType(Enum):
class EventType(Enum):
"""An enumeration for the supported event types."""
+
OPPOSITION = 1
CONJUNCTION = 2
OCCULTATION = 3
diff --git a/kosmorrolib/ephemerides.py b/kosmorrolib/ephemerides.py
index 2ddc578..7ef3867 100644
--- a/kosmorrolib/ephemerides.py
+++ b/kosmorrolib/ephemerides.py
@@ -33,8 +33,12 @@ from .exceptions import OutOfRangeDateError
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)
+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
@@ -65,28 +69,34 @@ def _get_skyfield_to_moon_phase(times: [Time], vals: [int], now: Time) -> Union[
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)
+ 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:
- earth = get_skf_objects()['earth']
- moon = get_skf_objects()['moon']
- sun = get_skf_objects()['sun']
+ earth = get_skf_objects()["earth"]
+ moon = get_skf_objects()["moon"]
+ sun = get_skf_objects()["sun"]
def moon_phase_at(time: Time):
time._nutation_angles = get_iau2000b(time)
current_earth = earth.at(time)
- _, mlon, _ = current_earth.observe(moon).apparent().ecliptic_latlon('date')
- _, slon, _ = current_earth.observe(sun).apparent().ecliptic_latlon('date')
+ _, mlon, _ = current_earth.observe(moon).apparent().ecliptic_latlon("date")
+ _, slon, _ = current_earth.observe(sun).apparent().ecliptic_latlon("date")
return (((mlon.radians - slon.radians) // (tau / 8)) % 8).astype(int)
moon_phase_at.rough_period = 7.0 # one lunar phase per week
today = get_timescale().utc(compute_date.year, compute_date.month, compute_date.day)
- time1 = get_timescale().utc(compute_date.year, compute_date.month, compute_date.day - 10)
- time2 = get_timescale().utc(compute_date.year, compute_date.month, compute_date.day + 10)
+ time1 = get_timescale().utc(
+ compute_date.year, compute_date.month, compute_date.day - 10
+ )
+ time2 = get_timescale().utc(
+ compute_date.year, compute_date.month, compute_date.day + 10
+ )
try:
times, phase = find_discrete(time1, time2, moon_phase_at)
@@ -94,7 +104,9 @@ def get_moon_phase(compute_date: datetime.date, timezone: int = 0) -> MoonPhase:
start = translate_to_timezone(error.start_time.utc_datetime(), timezone)
end = translate_to_timezone(error.end_time.utc_datetime(), timezone)
- start = datetime.date(start.year, start.month, start.day) + datetime.timedelta(days=12)
+ start = datetime.date(start.year, start.month, start.day) + datetime.timedelta(
+ days=12
+ )
end = datetime.date(end.year, end.month, end.day) - datetime.timedelta(days=12)
raise OutOfRangeDateError(start, end) from error
@@ -102,31 +114,51 @@ def get_moon_phase(compute_date: datetime.date, timezone: int = 0) -> MoonPhase:
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]:
ephemerides = []
def get_angle(for_aster: Object):
def fun(time: Time) -> float:
- return position.get_planet_topos().at(time).observe(for_aster.get_skyfield_object()).apparent().altaz()[0]\
- .degrees
+ return (
+ position.get_planet_topos()
+ .at(time)
+ .observe(for_aster.get_skyfield_object())
+ .apparent()
+ .altaz()[0]
+ .degrees
+ )
+
fun.rough_period = 1.0
return fun
def is_risen(for_aster: Object):
def fun(time: Time) -> bool:
return get_angle(for_aster)(time) > RISEN_ANGLE
+
fun.rough_period = 0.5
return fun
start_time = get_timescale().utc(date.year, date.month, date.day, -timezone)
- end_time = get_timescale().utc(date.year, date.month, date.day, 23 - timezone, 59, 59)
+ end_time = get_timescale().utc(
+ date.year, date.month, date.day, 23 - timezone, 59, 59
+ )
try:
for aster in ASTERS:
rise_times, arr = find_discrete(start_time, end_time, is_risen(aster))
try:
- culmination_time, _ = find_maxima(start_time, end_time, f=get_angle(aster), epsilon=1./3600/24, num=12)
- culmination_time = culmination_time[0] if len(culmination_time) > 0 else None
+ culmination_time, _ = find_maxima(
+ start_time,
+ end_time,
+ f=get_angle(aster),
+ epsilon=1.0 / 3600 / 24,
+ num=12,
+ )
+ culmination_time = (
+ culmination_time[0] if len(culmination_time) > 0 else None
+ )
except ValueError:
culmination_time = None
@@ -139,18 +171,24 @@ def get_ephemerides(date: datetime.date, position: Position, timezone: int = 0)
# Convert the Time instances to Python datetime objects
if rise_time is not None:
- rise_time = translate_to_timezone(rise_time.utc_datetime().replace(microsecond=0),
- to_tz=timezone)
+ rise_time = translate_to_timezone(
+ rise_time.utc_datetime().replace(microsecond=0), to_tz=timezone
+ )
if culmination_time is not None:
- culmination_time = translate_to_timezone(culmination_time.utc_datetime().replace(microsecond=0),
- to_tz=timezone)
+ culmination_time = translate_to_timezone(
+ culmination_time.utc_datetime().replace(microsecond=0),
+ to_tz=timezone,
+ )
if set_time is not None:
- set_time = translate_to_timezone(set_time.utc_datetime().replace(microsecond=0),
- to_tz=timezone)
+ set_time = translate_to_timezone(
+ set_time.utc_datetime().replace(microsecond=0), to_tz=timezone
+ )
- ephemerides.append(AsterEphemerides(rise_time, culmination_time, set_time, aster=aster))
+ ephemerides.append(
+ AsterEphemerides(rise_time, culmination_time, set_time, aster=aster)
+ )
except EphemerisRangeError as error:
start = translate_to_timezone(error.start_time.utc_datetime(), timezone)
end = translate_to_timezone(error.end_time.utc_datetime(), timezone)
diff --git a/kosmorrolib/events.py b/kosmorrolib/events.py
index 5d4081a..1298399 100644
--- a/kosmorrolib/events.py
+++ b/kosmorrolib/events.py
@@ -31,16 +31,22 @@ from .core import get_timescale, get_skf_objects, flatten_list
def _search_conjunction(start_time: Time, end_time: Time, timezone: int) -> [Event]:
- earth = get_skf_objects()['earth']
+ earth = get_skf_objects()["earth"]
aster1 = None
aster2 = None
def is_in_conjunction(time: Time):
earth_pos = earth.at(time)
- _, aster1_lon, _ = earth_pos.observe(aster1.get_skyfield_object()).apparent().ecliptic_latlon()
- _, aster2_lon, _ = earth_pos.observe(aster2.get_skyfield_object()).apparent().ecliptic_latlon()
+ _, aster1_lon, _ = (
+ earth_pos.observe(aster1.get_skyfield_object()).apparent().ecliptic_latlon()
+ )
+ _, aster2_lon, _ = (
+ earth_pos.observe(aster2.get_skyfield_object()).apparent().ecliptic_latlon()
+ )
- return ((aster1_lon.radians - aster2_lon.radians) / pi % 2.0).astype('int8') == 0
+ return ((aster1_lon.radians - aster2_lon.radians) / pi % 2.0).astype(
+ "int8"
+ ) == 0
is_in_conjunction.rough_period = 60.0
@@ -64,16 +70,30 @@ def _search_conjunction(start_time: Time, end_time: Time, timezone: int) -> [Eve
aster2_pos = (aster2.get_skyfield_object() - earth).at(time)
distance = aster1_pos.separation_from(aster2_pos).degrees
- if distance - aster2.get_apparent_radius(time, earth) < aster1.get_apparent_radius(time, earth):
- occulting_aster = [aster1,
- aster2] if aster1_pos.distance().km < aster2_pos.distance().km else [aster2,
- aster1]
-
- conjunctions.append(Event(EventType.OCCULTATION, occulting_aster,
- translate_to_timezone(time.utc_datetime(), timezone)))
+ if distance - aster2.get_apparent_radius(
+ time, earth
+ ) < aster1.get_apparent_radius(time, earth):
+ occulting_aster = (
+ [aster1, aster2]
+ if aster1_pos.distance().km < aster2_pos.distance().km
+ else [aster2, aster1]
+ )
+
+ conjunctions.append(
+ Event(
+ EventType.OCCULTATION,
+ occulting_aster,
+ translate_to_timezone(time.utc_datetime(), timezone),
+ )
+ )
else:
- conjunctions.append(Event(EventType.CONJUNCTION, [aster1, aster2],
- translate_to_timezone(time.utc_datetime(), timezone)))
+ conjunctions.append(
+ Event(
+ EventType.CONJUNCTION,
+ [aster1, aster2],
+ translate_to_timezone(time.utc_datetime(), timezone),
+ )
+ )
computed.append(aster1)
@@ -81,13 +101,15 @@ def _search_conjunction(start_time: Time, end_time: Time, timezone: int) -> [Eve
def _search_oppositions(start_time: Time, end_time: Time, timezone: int) -> [Event]:
- earth = get_skf_objects()['earth']
- sun = get_skf_objects()['sun']
+ earth = get_skf_objects()["earth"]
+ sun = get_skf_objects()["sun"]
aster = None
def is_oppositing(time: Time) -> [bool]:
earth_pos = earth.at(time)
- sun_pos = earth_pos.observe(sun).apparent() # Never do this without eyes protection!
+ sun_pos = earth_pos.observe(
+ sun
+ ).apparent() # Never do this without eyes protection!
aster_pos = earth_pos.observe(get_skf_objects()[aster.skyfield_name]).apparent()
_, lon1, _ = sun_pos.ecliptic_latlon()
_, lon2, _ = aster_pos.ecliptic_latlon()
@@ -97,19 +119,27 @@ def _search_oppositions(start_time: Time, end_time: Time, timezone: int) -> [Eve
events = []
for aster in ASTERS:
- if not isinstance(aster, Planet) or aster.skyfield_name in ['MERCURY', 'VENUS']:
+ if not isinstance(aster, Planet) or aster.skyfield_name in ["MERCURY", "VENUS"]:
continue
times, _ = find_discrete(start_time, end_time, is_oppositing)
for time in times:
- events.append(Event(EventType.OPPOSITION, [aster], translate_to_timezone(time.utc_datetime(), timezone)))
+ events.append(
+ Event(
+ EventType.OPPOSITION,
+ [aster],
+ translate_to_timezone(time.utc_datetime(), timezone),
+ )
+ )
return events
-def _search_maximal_elongations(start_time: Time, end_time: Time, timezone: int) -> [Event]:
- earth = get_skf_objects()['earth']
- sun = get_skf_objects()['sun']
+def _search_maximal_elongations(
+ start_time: Time, end_time: Time, timezone: int
+) -> [Event]:
+ earth = get_skf_objects()["earth"]
+ sun = get_skf_objects()["sun"]
aster = None
def get_elongation(time: Time):
@@ -123,24 +153,30 @@ def _search_maximal_elongations(start_time: Time, end_time: Time, timezone: int)
events = []
for aster in ASTERS:
- if aster.skyfield_name not in ['MERCURY', 'VENUS']:
+ if aster.skyfield_name not in ["MERCURY", "VENUS"]:
continue
- times, elongations = find_maxima(start_time, end_time, f=get_elongation, epsilon=1./24/3600, num=12)
+ times, elongations = find_maxima(
+ start_time, end_time, f=get_elongation, epsilon=1.0 / 24 / 3600, num=12
+ )
for i, time in enumerate(times):
elongation = elongations[i]
- events.append(Event(EventType.MAXIMAL_ELONGATION,
- [aster],
- translate_to_timezone(time.utc_datetime(), timezone),
- details='{:.3n}°'.format(elongation)))
+ events.append(
+ Event(
+ EventType.MAXIMAL_ELONGATION,
+ [aster],
+ translate_to_timezone(time.utc_datetime(), timezone),
+ details="{:.3n}°".format(elongation),
+ )
+ )
return events
def _get_moon_distance():
- earth = get_skf_objects()['earth']
- moon = get_skf_objects()['moon']
+ earth = get_skf_objects()["earth"]
+ moon = get_skf_objects()["moon"]
def get_distance(time: Time):
earth_pos = earth.at(time)
@@ -157,10 +193,18 @@ def _search_moon_apogee(start_time: Time, end_time: Time, timezone: int) -> [Eve
moon = ASTERS[1]
events = []
- 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.0 / 24 / 60
+ )
for time in times:
- events.append(Event(EventType.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
@@ -169,10 +213,18 @@ def _search_moon_perigee(start_time: Time, end_time: Time, timezone: int) -> [Ev
moon = ASTERS[1]
events = []
- 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.0 / 24 / 60
+ )
for time in times:
- events.append(Event(EventType.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
@@ -206,11 +258,13 @@ def get_events(date: date_type, timezone: int = 0) -> [Event]:
try:
found_events = []
- for fun in [_search_oppositions,
- _search_conjunction,
- _search_maximal_elongations,
- _search_moon_apogee,
- _search_moon_perigee]:
+ for fun in [
+ _search_oppositions,
+ _search_conjunction,
+ _search_maximal_elongations,
+ _search_moon_apogee,
+ _search_moon_perigee,
+ ]:
found_events.append(fun(start_time, end_time, timezone))
return sorted(flatten_list(found_events), key=lambda event: event.start_time)
diff --git a/kosmorrolib/exceptions.py b/kosmorrolib/exceptions.py
index e6effdd..6a69046 100644
--- a/kosmorrolib/exceptions.py
+++ b/kosmorrolib/exceptions.py
@@ -30,8 +30,10 @@ class OutOfRangeDateError(RuntimeError):
super().__init__()
self.min_date = min_date
self.max_date = max_date
- self.msg = 'The date must be between %s and %s' % (min_date.strftime('%Y-%m-%d'),
- max_date.strftime('%Y-%m-%d'))
+ self.msg = "The date must be between %s and %s" % (
+ min_date.strftime("%Y-%m-%d"),
+ max_date.strftime("%Y-%m-%d"),
+ )
class CompileError(RuntimeError):
diff --git a/tests/core.py b/tests/core.py
index 34cf8e5..76802ba 100644
--- a/tests/core.py
+++ b/tests/core.py
@@ -9,31 +9,42 @@ from dateutil.relativedelta import relativedelta
class CoreTestCase(unittest.TestCase):
def test_flatten_list(self):
- self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], core.flatten_list([0, 1, 2, [3, 4, [5, 6], 7], 8, [9]]))
+ self.assertEqual(
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
+ core.flatten_list([0, 1, 2, [3, 4, [5, 6], 7], 8, [9]]),
+ )
def test_get_env(self):
self.assertEqual(0, len(core.get_env()))
- os.environ['SOME_RANDOM_VAR'] = 'an awesome value'
+ os.environ["SOME_RANDOM_VAR"] = "an awesome value"
self.assertEqual(0, len(core.get_env()))
- os.environ['KOSMORRO_GREAT_VARIABLE'] = 'value'
+ os.environ["KOSMORRO_GREAT_VARIABLE"] = "value"
env = core.get_env()
self.assertEqual(1, len(env))
- self.assertEqual('value', env.great_variable)
+ self.assertEqual("value", env.great_variable)
- os.environ['KOSMORRO_ANOTHER_VARIABLE'] = 'another value'
+ os.environ["KOSMORRO_ANOTHER_VARIABLE"] = "another value"
env = core.get_env()
self.assertEqual(2, len(env))
- self.assertEqual('value', env.great_variable)
- self.assertEqual('another value', env.another_variable)
+ self.assertEqual("value", env.great_variable)
+ self.assertEqual("another value", env.another_variable)
- self.assertEqual("{'great_variable': 'value', 'another_variable': 'another value'}", str(env))
+ self.assertEqual(
+ "{'great_variable': 'value', 'another_variable': 'another value'}", str(env)
+ )
def test_date_arg_parsing(self):
- self.assertEqual(core.get_date("+1y 2m3d"), date.today() + relativedelta(years=1, months=2, days=3))
- self.assertEqual(core.get_date("-1y2d"), date.today() - relativedelta(years=1, days=2))
+ self.assertEqual(
+ core.get_date("+1y 2m3d"),
+ date.today() + relativedelta(years=1, months=2, days=3),
+ )
+ self.assertEqual(
+ core.get_date("-1y2d"), date.today() - relativedelta(years=1, days=2)
+ )
self.assertEqual(core.get_date("1111-11-13"), date(1111, 11, 13))
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
diff --git a/tests/data.py b/tests/data.py
index d1e2103..0b68fb0 100644
--- a/tests/data.py
+++ b/tests/data.py
@@ -5,13 +5,15 @@ from kosmorrolib import data, core
class DataTestCase(unittest.TestCase):
def test_object_radius_must_be_set_to_get_apparent_radius(self):
- o = data.Planet('Saturn', 'SATURN')
+ o = data.Planet("Saturn", "SATURN")
with self.assertRaises(ValueError) as context:
- o.get_apparent_radius(core.get_timescale().now(), core.get_skf_objects()['earth'])
+ o.get_apparent_radius(
+ core.get_timescale().now(), core.get_skf_objects()["earth"]
+ )
- self.assertEqual(('Missing radius for Saturn object',), context.exception.args)
+ self.assertEqual(("Missing radius for Saturn object",), context.exception.args)
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/tests/dateutil.py b/tests/dateutil.py
index 984add3..82cf29d 100644
--- a/tests/dateutil.py
+++ b/tests/dateutil.py
@@ -12,13 +12,17 @@ class DateUtilTestCase(unittest.TestCase):
date = dateutil.translate_to_timezone(datetime(2020, 6, 9, 0), to_tz=2)
self.assertEqual(2, date.hour)
- date = dateutil.translate_to_timezone(datetime(2020, 6, 9, 8), to_tz=2, from_tz=6)
+ date = dateutil.translate_to_timezone(
+ datetime(2020, 6, 9, 8), to_tz=2, from_tz=6
+ )
self.assertEqual(4, date.hour)
- date = dateutil.translate_to_timezone(datetime(2020, 6, 9, 1), to_tz=0, from_tz=2)
+ date = dateutil.translate_to_timezone(
+ datetime(2020, 6, 9, 1), to_tz=0, from_tz=2
+ )
self.assertEqual(8, date.day)
self.assertEqual(23, date.hour)
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/tests/ephemerides.py b/tests/ephemerides.py
index 713a115..c3d876d 100644
--- a/tests/ephemerides.py
+++ b/tests/ephemerides.py
@@ -12,16 +12,17 @@ from kosmorrolib.exceptions import OutOfRangeDateError
class EphemeridesTestCase(unittest.TestCase):
def test_get_ephemerides_for_aster_returns_correct_hours(self):
position = Position(0, 0, EARTH)
- eph = ephemerides.get_ephemerides(date=date(2019, 11, 18),
- position=position)
+ eph = ephemerides.get_ephemerides(date=date(2019, 11, 18), position=position)
@expect_assertions(self.assertRegex, num=3)
def do_assertions(assert_regex):
for ephemeris in eph:
- if ephemeris.object.skyfield_name == 'SUN':
- assert_regex(ephemeris.rise_time.isoformat(), '^2019-11-18T05:41:')
- assert_regex(ephemeris.culmination_time.isoformat(), '^2019-11-18T11:45:')
- assert_regex(ephemeris.set_time.isoformat(), '^2019-11-18T17:48:')
+ if ephemeris.object.skyfield_name == "SUN":
+ assert_regex(ephemeris.rise_time.isoformat(), "^2019-11-18T05:41:")
+ assert_regex(
+ ephemeris.culmination_time.isoformat(), "^2019-11-18T11:45:"
+ )
+ assert_regex(ephemeris.set_time.isoformat(), "^2019-11-18T17:48:")
break
do_assertions()
@@ -34,61 +35,61 @@ class EphemeridesTestCase(unittest.TestCase):
phase = ephemerides.get_moon_phase(date(2019, 11, 25))
self.assertEqual(MoonPhaseType.WANING_CRESCENT, phase.phase_type)
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))
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))
self.assertEqual(MoonPhaseType.WAXING_CRESCENT, phase.phase_type)
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):
phase = ephemerides.get_moon_phase(date(2019, 11, 3))
self.assertEqual(MoonPhaseType.WAXING_CRESCENT, phase.phase_type)
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))
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))
self.assertEqual(MoonPhaseType.WAXING_GIBBOUS, phase.phase_type)
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):
phase = ephemerides.get_moon_phase(date(2019, 11, 11))
self.assertEqual(MoonPhaseType.WAXING_GIBBOUS, phase.phase_type)
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))
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))
self.assertEqual(MoonPhaseType.WANING_GIBBOUS, phase.phase_type)
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):
phase = ephemerides.get_moon_phase(date(2019, 11, 18))
self.assertEqual(MoonPhaseType.WANING_GIBBOUS, phase.phase_type)
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))
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))
self.assertEqual(MoonPhaseType.WANING_CRESCENT, phase.phase_type)
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):
phase = MoonPhase(MoonPhaseType.NEW_MOON, None, None)
@@ -120,5 +121,5 @@ class EphemeridesTestCase(unittest.TestCase):
ephemerides.get_moon_phase(date(1789, 5, 5))
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/tests/events.py b/tests/events.py
index dd92611..da6485c 100644
--- a/tests/events.py
+++ b/tests/events.py
@@ -10,43 +10,111 @@ from kosmorrolib.exceptions import OutOfRangeDateError
EXPECTED_EVENTS = [
(date(2020, 2, 7), []),
-
- (date(2020, 10, 13), [Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2020, 10, 13, 23, 25))]),
-
- (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(EventType.OPPOSITION, [ASTERS[4]], datetime(2025, 1, 16, 2, 38))]),
-
- (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(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(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(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(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(EventType.OCCULTATION, [ASTERS[1], ASTERS[5]], datetime(2005, 6, 16, 6, 31))]),
-
- (date(2020, 4, 7), [Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 4, 7, 18, 14))]),
-
- (date(2020, 1, 29), [Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 1, 29, 21, 32))])
+ (
+ date(2020, 10, 13),
+ [Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2020, 10, 13, 23, 25))],
+ ),
+ (
+ 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(EventType.OPPOSITION, [ASTERS[4]], datetime(2025, 1, 16, 2, 38))],
+ ),
+ (
+ 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(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(
+ 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(
+ 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(
+ 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(
+ EventType.OCCULTATION,
+ [ASTERS[1], ASTERS[5]],
+ datetime(2005, 6, 16, 6, 31),
+ )
+ ],
+ ),
+ (
+ date(2020, 4, 7),
+ [Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 4, 7, 18, 14))],
+ ),
+ (
+ date(2020, 1, 29),
+ [Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 1, 29, 21, 32))],
+ ),
]
@@ -57,20 +125,23 @@ class EventTestCase(unittest.TestCase):
@parameterized.expand(EXPECTED_EVENTS)
def test_search_events(self, d: date, expected_events: [Event]):
actual_events = events.get_events(d)
- self.assertEqual(len(expected_events), len(actual_events),
- 'Expected %d elements, got %d for date %s.\n%s' % (len(expected_events),
- len(actual_events),
- d.isoformat(),
- actual_events))
+ self.assertEqual(
+ len(expected_events),
+ len(actual_events),
+ "Expected %d elements, got %d for date %s.\n%s"
+ % (len(expected_events), len(actual_events), d.isoformat(), actual_events),
+ )
for i, expected_event in enumerate(expected_events):
actual_event = actual_events[i]
# Remove unnecessary precision (seconds and microseconds)
- actual_event.start_time = datetime(actual_event.start_time.year,
- actual_event.start_time.month,
- actual_event.start_time.day,
- actual_event.start_time.hour,
- actual_event.start_time.minute)
+ actual_event.start_time = datetime(
+ actual_event.start_time.year,
+ actual_event.start_time.month,
+ actual_event.start_time.day,
+ actual_event.start_time.hour,
+ actual_event.start_time.minute,
+ )
self.assertEqual(expected_event.__dict__, actual_event.__dict__)
@@ -79,5 +150,5 @@ class EventTestCase(unittest.TestCase):
events.get_events(date(1789, 5, 5))
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/tests/testutils.py b/tests/testutils.py
index 964a3e1..475aeaa 100644
--- a/tests/testutils.py
+++ b/tests/testutils.py
@@ -39,9 +39,10 @@ def expect_assertions(assert_fun, num=1):
count = assert_fun_mock.call_count
if count != num:
- raise AssertionError('Expected %d call(s) to function %s but called %d time(s).' % (num,
- assert_fun.__name__,
- count))
+ raise AssertionError(
+ "Expected %d call(s) to function %s but called %d time(s)."
+ % (num, assert_fun.__name__, count)
+ )
return sniff_function