From da64382b3bab18776e16e24b597ce4a03edfe723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Deuchnord?= Date: Tue, 12 Nov 2019 20:34:54 +0100 Subject: [PATCH] Add JSON output --- kosmorro | 25 +++++++++++++------------ kosmorrolib/data.py | 12 ++++++++++++ kosmorrolib/dumper.py | 32 +++++++++++++++++++++++++++++--- kosmorrolib/ephemerides.py | 4 ++-- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/kosmorro b/kosmorro index f478abe..224b8cb 100644 --- a/kosmorro +++ b/kosmorro @@ -18,21 +18,13 @@ import argparse from datetime import date -import numpy from kosmorrolib import dumper from kosmorrolib.ephemerides import EphemeridesComputer, Position -# Fixes the "TypeError: Object of type int64 is not JSON serializable" -# See https://stackoverflow.com/a/50577730 -def json_default(obj): - if isinstance(obj, numpy.int64): - return int(obj) - raise TypeError('Object of type ' + str(type(obj)) + ' could not be integrated in the JSON') - - def main(): - args = get_args() + output_formats = get_dumpers() + args = get_args(list(output_formats.keys())) year = args.year month = args.month day = args.day @@ -43,11 +35,18 @@ def main(): ephemeris = EphemeridesComputer(Position(args.latitude, args.longitude, altitude=args.altitude)) ephemerides = ephemeris.compute_ephemerides(year, month, day) - dump = dumper.TextDumper(ephemerides) + dump = output_formats[args.format](ephemerides) print(dump.to_string()) -def get_args(): +def get_dumpers() -> {str: dumper.Dumper}: + return { + 'text': dumper.TextDumper, + 'json': dumper.JsonDumper + } + + +def get_args(output_formats: [str]): today = date.today() parser = argparse.ArgumentParser(description='Compute the ephemerides for a given date, at a given position' @@ -56,6 +55,8 @@ def get_args(): ' observer positioned at coordinates (0,0), with an altitude of 0.' % today.strftime('%a %b %d, %Y')) + parser.add_argument('--format', '-f', type=str, default=output_formats[0], choices=output_formats, + help='The format under which the information have to be output') parser.add_argument('--latitude', '-lat', type=float, default=0., help="The observer's latitude on Earth") parser.add_argument('--longitude', '-lon', type=float, default=0., diff --git a/kosmorrolib/data.py b/kosmorrolib/data.py index 89695a4..2ba310d 100644 --- a/kosmorrolib/data.py +++ b/kosmorrolib/data.py @@ -22,6 +22,18 @@ from typing import Union from skyfield.api import Topos from skyfield.timelib import Time +MOON_PHASES = { + 'NEW_MOON': 'New Moon', + 'FIRST_QUARTER': 'First Quarter', + 'FULL_MOON': 'Full Moon', + 'LAST_QUARTER': 'Last Quarter' +} + + +def skyfield_to_moon_phase(val: int) -> str: + phases = list(MOON_PHASES.keys()) + return phases[val] + class Position: def __init__(self, latitude: float, longitude: float, altitude: float = 0): diff --git a/kosmorrolib/dumper.py b/kosmorrolib/dumper.py index b5f039c..d2b8c9a 100644 --- a/kosmorrolib/dumper.py +++ b/kosmorrolib/dumper.py @@ -18,9 +18,11 @@ from abc import ABC, abstractmethod import datetime +import json from tabulate import tabulate -from skyfield import almanac -from .data import Object +from skyfield.timelib import Time +from numpy import int64 +from .data import Object, AsterEphemerides, MOON_PHASES class Dumper(ABC): @@ -33,6 +35,30 @@ class Dumper(ABC): pass +class JsonDumper(Dumper): + def to_string(self): + return json.dumps(self.ephemeris, + default=self._json_default, + indent=4) + + @staticmethod + def _json_default(obj): + # Fixes the "TypeError: Object of type int64 is not JSON serializable" + # See https://stackoverflow.com/a/50577730 + if isinstance(obj, int64): + return int(obj) + if isinstance(obj, Time): + return obj.utc_iso() + if isinstance(obj, Object): + obj = obj.__dict__ + obj.pop('skyfield_name') + return obj + if isinstance(obj, AsterEphemerides): + return obj.__dict__ + + raise TypeError('Object of type "%s" could not be integrated in the JSON' % str(type(obj))) + + class TextDumper(Dumper): def to_string(self): return '\n\n'.join(['Ephemerides of %s' % self.date.strftime('%A %B %d, %Y'), @@ -69,4 +95,4 @@ class TextDumper(Dumper): @staticmethod def get_moon(moon): - return 'Moon phase: %s' % almanac.MOON_PHASES[moon['phase']] + return 'Moon phase: %s' % MOON_PHASES[moon['phase']] diff --git a/kosmorrolib/ephemerides.py b/kosmorrolib/ephemerides.py index 93b5e35..0c2b42a 100644 --- a/kosmorrolib/ephemerides.py +++ b/kosmorrolib/ephemerides.py @@ -20,7 +20,7 @@ import datetime from skyfield import almanac from skyfield.timelib import Time -from .data import Object, Position, AsterEphemerides +from .data import Object, Position, AsterEphemerides, skyfield_to_moon_phase from .core import get_skf_objects, get_timescale, ASTERS, MONTHS RISEN_ANGLE = -0.8333 @@ -48,7 +48,7 @@ class EphemeridesComputer: _, moon_phase = almanac.find_discrete(time1, time2, almanac.moon_phases(get_skf_objects())) - return {'phase': moon_phase[-1]} + return {'phase': skyfield_to_moon_phase(moon_phase[-1])} @staticmethod def get_asters_ephemerides_for_aster(aster, date: datetime.date, position: Position) -> Object: