diff --git a/kosmorro/__main__.py b/kosmorro/__main__.py index 5660cb42..2d81a30e 100644 --- a/kosmorro/__main__.py +++ b/kosmorro/__main__.py @@ -21,8 +21,15 @@ import os.path from babel.dates import format_date -from kosmorrolib import Position, get_ephemerides, get_events, get_moon_phase -from kosmorrolib.exceptions import OutOfRangeDateError +from kosmorrolib import ( + Position, + get_ephemerides, + get_events, + get_moon_phase, + search_events, +) +from kosmorrolib.exceptions import OutOfRangeDateError, InvalidDateRangeError +from kosmorrolib.enum import EventType from datetime import date from . import dumper, environment, debug @@ -37,8 +44,10 @@ ) from .exceptions import ( InvalidOutputFormatError, + SearchDatesNotGivenError, UnavailableFeatureError, OutOfRangeDateError as DateRangeError, + InvalidEventTypeError, ) from kosmorro.i18n.utils import _ @@ -55,6 +64,8 @@ def run(): if args.special_action is not None: return 0 if args.special_action() else 1 + search_enabled = args.search is not None + try: compute_date = parse_date(args.date) except ValueError as error: @@ -105,14 +116,42 @@ def run(): try: use_colors = not environment.NO_COLOR and args.colors - output = get_information( - compute_date, - position, - timezone, - output_format, - use_colors, - args.show_graph, - ) + output = None + if search_enabled: + output = get_search_information( + args.search, + args.from_, + args.until, + timezone, + output_format, + use_colors, + args.show_graph, + ) + else: + output = get_information( + compute_date, + position, + timezone, + output_format, + use_colors, + args.show_graph, + ) + except InvalidEventTypeError as error: + print_stderr(colored(error.msg, "red")) + debug.debug_print(error) + return 7 + except InvalidDateRangeError as error: + print_stderr(colored(error, "red")) + debug.debug_print(error) + return 6 + except SearchDatesNotGivenError as error: + print_stderr(colored(error.msg, "red")) + debug.debug_print(error) + return 5 + except ValueError as error: + print_stderr(colored(error.args[0], color="red", attrs=["bold"])) + debug.debug_print(error) + return 4 except InvalidOutputFormatError as error: print_stderr(colored(error.msg, "red")) debug.debug_print(error) @@ -204,6 +243,45 @@ def get_information( timezone=timezone, with_colors=colors, show_graph=show_graph, + search_enabled=False, + ) + except KeyError as error: + raise InvalidOutputFormatError(output_format, list(get_dumpers().keys())) + except OutOfRangeDateError as error: + raise DateRangeError(error.min_date, error.max_date) + + +def get_search_information( + requested_events: [EventType], + search_from: date, + search_until: date, + timezone: int, + output_format: str, + colors: bool, + show_graph: bool, +) -> dumper.Dumper: + try: + if search_until is None: + raise SearchDatesNotGivenError + + try: + event_types = [EventType[event.upper()] for event in requested_events] + except KeyError as error: + raise InvalidEventTypeError(error.args[0]) + + from_ = parse_date(search_from) + until = parse_date(search_until) + events_list = search_events(event_types, until, from_, timezone) + + return get_dumpers()[output_format]( + ephemerides=[], + moon_phase=None, + events=events_list, + date=None, + timezone=timezone, + with_colors=colors, + show_graph=show_graph, + search_enabled=True, ) except KeyError as error: raise InvalidOutputFormatError(output_format, list(get_dumpers().keys())) @@ -308,6 +386,27 @@ def get_args(output_formats: [str]): "Can also be set in the KOSMORRO_TIMEZONE environment variable." ), ) + parser.add_argument( + "--search", + "-s", + type=str, + nargs="*", + default=None, + help=_("Search for specific event types by date."), + ) + parser.add_argument( + "--from", + dest="from_", + type=str, + default=today.strftime("%Y-%m-%d"), + help=_("The date to begin searching for events. Default is today."), + ) + parser.add_argument( + "--until", + type=str, + default=None, + help=_("The date to end searching for events."), + ) parser.add_argument( "--no-colors", dest="colors", diff --git a/kosmorro/dumper.py b/kosmorro/dumper.py index 5d5c7e39..6a697dc2 100644 --- a/kosmorro/dumper.py +++ b/kosmorro/dumper.py @@ -25,7 +25,7 @@ import shutil from pathlib import Path -from babel.dates import format_date, format_time +from babel.dates import format_date, format_time, format_datetime from tabulate import tabulate from termcolor import colored @@ -60,6 +60,7 @@ def __init__( timezone: int, with_colors: bool, show_graph: bool, + search_enabled: bool, ): self.ephemerides = ephemerides self.moon_phase = moon_phase @@ -68,6 +69,7 @@ def __init__( self.timezone = timezone self.with_colors = with_colors self.show_graph = show_graph + self.search_enabled = search_enabled def get_date_as_string(self, capitalized: bool = False) -> str: date = format_date(self.date, "full") @@ -220,9 +222,10 @@ def get_events(self, events: [Event]) -> str: if description is None: continue + date_format = "MMM dd, yyyy hh:mm a" if self.search_enabled else "hh:mm a" data.append( [ - self.style(format_time(event.start_time, "short"), "th"), + self.style(format_datetime(event.start_time, date_format), "th"), description, ] ) diff --git a/kosmorro/exceptions.py b/kosmorro/exceptions.py index c5e5ca37..e43c88f2 100644 --- a/kosmorro/exceptions.py +++ b/kosmorro/exceptions.py @@ -19,6 +19,7 @@ from datetime import date from babel.dates import format_date from kosmorro.i18n.utils import _, SHORT_DATE_FORMAT +from kosmorrolib.enum import EventType class UnavailableFeatureError(RuntimeError): @@ -53,6 +54,25 @@ def __init__(self, output_format: str, accepted_extensions: [str]): ) +class SearchDatesNotGivenError(RuntimeError): + def __init__(self): + super().__init__() + self.msg = _("Search end date (--until) is required when searching events.") + + +class InvalidEventTypeError(RuntimeError): + def __init__(self, invalid_event: EventType): + super().__init__() + self.invalid_event = invalid_event + supported_events = ", ".join([event.name for _, event in enumerate(EventType)]) + self.msg = _( + "Invalid event type {event}.\nSupported events are {events}." + ).format( + event=self.invalid_event, + events=supported_events, + ) + + class CompileError(RuntimeError): def __init__(self, msg): super().__init__() diff --git a/kosmorro/locales/messages.pot b/kosmorro/locales/messages.pot index 166b0e49..b256ae48 100644 --- a/kosmorro/locales/messages.pot +++ b/kosmorro/locales/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-07-07 13:10+0200\n" +"POT-Creation-Date: 2022-11-21 16:17-0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,94 +17,106 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.10.3\n" -#: kosmorro/__main__.py:82 +#: kosmorro/__main__.py:93 msgid "" "Save the planet and paper!\n" "Consider printing your PDF document only if really necessary, and use the" " other side of the sheet." msgstr "" -#: kosmorro/__main__.py:90 +#: kosmorro/__main__.py:101 msgid "" "PDF output will not contain the ephemerides, because you didn't provide " "the observation coordinates." msgstr "" -#: kosmorro/__main__.py:142 +#: kosmorro/__main__.py:181 msgid "The file could not be saved in \"{path}\": {error}" msgstr "" -#: kosmorro/__main__.py:156 +#: kosmorro/__main__.py:195 msgid "Please provide a file path to export in this format (--output)." msgstr "" -#: kosmorro/__main__.py:187 +#: kosmorro/__main__.py:226 msgid "Moon phase can only be computed between {min_date} and {max_date}" msgstr "" -#: kosmorro/__main__.py:238 +#: kosmorro/__main__.py:316 msgid "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" msgstr "" -#: kosmorro/__main__.py:251 +#: kosmorro/__main__.py:329 msgid "" "Compute the ephemerides and the events for a given date and a given " "position on Earth." msgstr "" -#: kosmorro/__main__.py:254 +#: kosmorro/__main__.py:332 msgid "" "By default, only the events will be computed for today.\n" "To compute also the ephemerides, latitude and longitude arguments are " "needed." msgstr "" -#: kosmorro/__main__.py:267 +#: kosmorro/__main__.py:345 msgid "Show the program version" msgstr "" -#: kosmorro/__main__.py:275 +#: kosmorro/__main__.py:353 msgid "" "The format to output the information to. If not provided, the output " "format will be inferred from the file extension of the output file." msgstr "" -#: kosmorro/__main__.py:285 +#: kosmorro/__main__.py:363 msgid "" "The observer's position on Earth, in the \"{latitude},{longitude}\" " "format. Can also be set in the KOSMORRO_POSITION environment variable." msgstr "" -#: kosmorro/__main__.py:295 +#: kosmorro/__main__.py:373 msgid "" "The date for which the ephemerides must be calculated. Can be in the " "YYYY-MM-DD format or an interval in the \"[+-]YyMmDd\" format (with Y, M," " and D numbers). Defaults to current date." msgstr "" -#: kosmorro/__main__.py:306 +#: kosmorro/__main__.py:384 msgid "" "The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). " "Can also be set in the KOSMORRO_TIMEZONE environment variable." msgstr "" -#: kosmorro/__main__.py:315 +#: kosmorro/__main__.py:395 +msgid "Search for specific event types by date." +msgstr "" + +#: kosmorro/__main__.py:402 +msgid "The date to begin searching for events. Default is today." +msgstr "" + +#: kosmorro/__main__.py:408 +msgid "The date to end searching for events." +msgstr "" + +#: kosmorro/__main__.py:414 msgid "Disable the colors in the console." msgstr "" -#: kosmorro/__main__.py:322 +#: kosmorro/__main__.py:421 msgid "" "A file to export the output to. If not given, the standard output is " "used. This argument is needed for PDF format." msgstr "" -#: kosmorro/__main__.py:331 +#: kosmorro/__main__.py:430 msgid "" "Do not generate a graph to represent the rise and set times in the PDF " "format." msgstr "" -#: kosmorro/__main__.py:339 +#: kosmorro/__main__.py:438 msgid "Show debugging messages" msgstr "" @@ -118,76 +130,76 @@ msgid "" "offset format." msgstr "" -#: kosmorro/dumper.py:137 +#: kosmorro/dumper.py:139 msgid "Expected events:" msgstr "" -#: kosmorro/dumper.py:144 +#: kosmorro/dumper.py:146 msgid "Note: All the hours are given in UTC." msgstr "" -#: kosmorro/dumper.py:151 +#: kosmorro/dumper.py:153 msgid "Note: All the hours are given in the UTC{offset} timezone." msgstr "" -#: kosmorro/dumper.py:205 kosmorro/dumper.py:339 +#: kosmorro/dumper.py:207 kosmorro/dumper.py:342 msgid "Object" msgstr "" -#: kosmorro/dumper.py:206 kosmorro/dumper.py:340 +#: kosmorro/dumper.py:208 kosmorro/dumper.py:343 msgid "Rise time" msgstr "" -#: kosmorro/dumper.py:207 kosmorro/dumper.py:342 +#: kosmorro/dumper.py:209 kosmorro/dumper.py:345 msgid "Culmination time" msgstr "" -#: kosmorro/dumper.py:208 kosmorro/dumper.py:344 +#: kosmorro/dumper.py:210 kosmorro/dumper.py:347 msgid "Set time" msgstr "" -#: kosmorro/dumper.py:234 +#: kosmorro/dumper.py:237 msgid "Moon phase is unavailable for this date." msgstr "" -#: kosmorro/dumper.py:238 kosmorro/dumper.py:348 +#: kosmorro/dumper.py:241 kosmorro/dumper.py:351 msgid "Moon phase:" msgstr "" -#: kosmorro/dumper.py:242 +#: kosmorro/dumper.py:245 msgid "{next_moon_phase} on {next_moon_phase_date} at {next_moon_phase_time}" msgstr "" -#: kosmorro/dumper.py:312 +#: kosmorro/dumper.py:315 msgid "Overview of your sky" msgstr "" -#: kosmorro/dumper.py:320 +#: kosmorro/dumper.py:323 msgid "" "This document summarizes the ephemerides and the events of {date}. It " "aims to help you to prepare your observation session. All the hours are " "given in {timezone}." msgstr "" -#: kosmorro/dumper.py:330 +#: kosmorro/dumper.py:333 msgid "" "Don't forget to check the weather forecast before you go out with your " "equipment." msgstr "" -#: kosmorro/dumper.py:337 +#: kosmorro/dumper.py:340 msgid "Ephemerides of the day" msgstr "" -#: kosmorro/dumper.py:346 +#: kosmorro/dumper.py:349 msgid "hours" msgstr "" -#: kosmorro/dumper.py:353 +#: kosmorro/dumper.py:356 msgid "Expected events" msgstr "" -#: kosmorro/dumper.py:493 +#: kosmorro/dumper.py:496 msgid "" "Building PDF was not possible, because some dependencies are not " "installed.\n" @@ -195,7 +207,7 @@ msgid "" "pdf/ for more information." msgstr "" -#: kosmorro/dumper.py:542 +#: kosmorro/dumper.py:545 #, python-format msgid "" "An error occurred during the compilation of the PDF.\n" @@ -203,16 +215,26 @@ msgid "" "share the content of the log file at /tmp/kosmorro-%s.log" msgstr "" -#: kosmorro/exceptions.py:35 +#: kosmorro/exceptions.py:36 msgid "The date must be between {minimum_date} and {maximum_date}" msgstr "" -#: kosmorro/exceptions.py:48 +#: kosmorro/exceptions.py:49 msgid "" "Invalid output format: {output_format}. Output file must end with: " "{accepted_extensions}" msgstr "" +#: kosmorro/exceptions.py:60 +msgid "Search end date (--until) is required when searching events." +msgstr "" + +#: kosmorro/exceptions.py:68 +msgid "" +"Invalid event type {event}.\n" +"Supported events are {events}." +msgstr "" + #: kosmorro/geolocation.py:14 #, python-format msgid "The given position (%s) is not valid."