diff --git a/.scripts/tests-e2e.sh b/.scripts/tests-e2e.sh index 725812e..4ed0bbe 100755 --- a/.scripts/tests-e2e.sh +++ b/.scripts/tests-e2e.sh @@ -128,6 +128,19 @@ assertSuccess "ls $HOME/kosmorro/export/document.pdf" assertSuccess "$KOSMORRO_COMMAND --position=\"50.5876;3.0624\" -d 2020-01-27 --format=pdf -o $HOME/kosmorro/export/document-no-graph.pdf --no-graph" assertSuccess "ls $HOME/kosmorro/export/document-no-graph.pdf" +# If format argument is given, use it even if it conflicts with file extension +assertSuccess "$KOSMORRO_COMMAND --position=\"50.5876;3.0624\" -d 2020-01-27 --format=json -o $HOME/kosmorro/export/txt-document.txt" +assertSuccess "ls $HOME/kosmorro/export/txt-document.txt" + +assertSuccess "$KOSMORRO_COMMAND --position=\"50.5876;3.0624\" -d 2020-01-27 -o $HOME/kosmorro/export/txt-document.txt" +assertSuccess "ls $HOME/kosmorro/export/txt-document.txt" + +assertSuccess "$KOSMORRO_COMMAND --position=\"50.5876;3.0624\" -d 2020-01-27 -o $HOME/kosmorro/export/json-document.json" +assertSuccess "ls $HOME/kosmorro/export/json-document.json" + +assertSuccess "$KOSMORRO_COMMAND --position=\"50.5876;3.0624\" -d 2020-01-27 -o $HOME/kosmorro/export/pdf-document.pdf" +assertSuccess "ls $HOME/kosmorro/export/pdf-document.pdf" + # man page assertSuccess "man --pager=cat kosmorro" diff --git a/_kosmorro/exceptions.py b/_kosmorro/exceptions.py index 88ae9b8..4c36c3e 100644 --- a/_kosmorro/exceptions.py +++ b/_kosmorro/exceptions.py @@ -39,6 +39,19 @@ class OutOfRangeDateError(RuntimeError): ) +class InvalidOutputFormatError(RuntimeError): + def __init__(self, output_format: str, accepted_extensions: [str]): + super().__init__() + self.output_format = output_format + self.accepted_extensions = accepted_extensions + self.msg = _( + "Invalid output format: {output_format}. Output file must end with: {accepted_extensions}" + ).format( + output_format=output_format, + accepted_extensions=", ".join(accepted_extensions), + ) + + class CompileError(RuntimeError): def __init__(self, msg): super().__init__() diff --git a/_kosmorro/locales/messages.pot b/_kosmorro/locales/messages.pot index 51395ea..2938de2 100644 --- a/_kosmorro/locales/messages.pot +++ b/_kosmorro/locales/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: kosmorro 0.10.1\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-08-10 20:23+0200\n" +"POT-Creation-Date: 2021-08-24 17:06-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -116,6 +116,12 @@ msgstr "" msgid "The date must be between {minimum_date} and {maximum_date}" msgstr "" +#: _kosmorro/exceptions.py:47 +msgid "" +"Invalid output format: {output_format}. Output file must end with: " +"{accepted_extensions}" +msgstr "" + #: _kosmorro/geolocation.py:14 #, python-format msgid "The given position (%s) is not valid." @@ -125,104 +131,106 @@ msgstr "" msgid "The given Plus Code seems to be a short code, please provide a full code." msgstr "" -#: _kosmorro/main.py:58 +#: _kosmorro/main.py:73 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:67 +#: _kosmorro/main.py:82 msgid "" "PDF output will not contain the ephemerides, because you didn't provide " "the observation coordinates." msgstr "" -#: _kosmorro/main.py:112 +#: _kosmorro/main.py:132 msgid "The file could not be saved in \"{path}\": {error}" msgstr "" -#: _kosmorro/main.py:126 +#: _kosmorro/main.py:146 msgid "Please provide a file path to export in this format (--output)." msgstr "" -#: _kosmorro/main.py:159 +#: _kosmorro/main.py:179 msgid "Moon phase can only be displayed between {min_date} and {max_date}" msgstr "" -#: _kosmorro/main.py:198 +#: _kosmorro/main.py:228 msgid "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" msgstr "" -#: _kosmorro/main.py:208 +#: _kosmorro/main.py:238 msgid "Do you really want to clear Kosmorro's cache? [yN] " msgstr "" -#: _kosmorro/main.py:216 +#: _kosmorro/main.py:246 msgid "Incorrect answer, cache not cleared." msgstr "" -#: _kosmorro/main.py:226 +#: _kosmorro/main.py:256 msgid "" "Compute the ephemerides and the events for a given date and a given " "position on Earth." msgstr "" -#: _kosmorro/main.py:229 +#: _kosmorro/main.py:259 msgid "" "By default, only the events will be computed for today ({date}).\n" "To compute also the ephemerides, latitude and longitude arguments are " "needed." msgstr "" -#: _kosmorro/main.py:243 +#: _kosmorro/main.py:273 msgid "Show the program version" msgstr "" -#: _kosmorro/main.py:251 +#: _kosmorro/main.py:281 msgid "Delete all the files from Kosmorro's cache." msgstr "" -#: _kosmorro/main.py:259 -msgid "The format to output the information to" +#: _kosmorro/main.py:289 +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:266 +#: _kosmorro/main.py:299 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:276 +#: _kosmorro/main.py:309 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 today ({default_date})." msgstr "" -#: _kosmorro/main.py:287 +#: _kosmorro/main.py:320 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:296 +#: _kosmorro/main.py:329 msgid "Disable the colors in the console." msgstr "" -#: _kosmorro/main.py:303 +#: _kosmorro/main.py:336 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:312 +#: _kosmorro/main.py:345 msgid "" "Do not generate a graph to represent the rise and set times in the PDF " "format." msgstr "" -#: _kosmorro/main.py:320 +#: _kosmorro/main.py:353 msgid "Show debugging messages" msgstr "" diff --git a/_kosmorro/main.py b/_kosmorro/main.py index 56c5c52..1716e2f 100644 --- a/_kosmorro/main.py +++ b/_kosmorro/main.py @@ -20,6 +20,7 @@ import argparse import locale import re import sys +import os.path from kosmorrolib import Position, get_ephemerides, get_events, get_moon_phase from kosmorrolib.__version__ import __version__ as kosmorrolib_version @@ -31,7 +32,11 @@ from . import dumper, environment, debug from .date import parse_date from .geolocation import get_position from .__version__ import __version__ as kosmorro_version -from .exceptions import UnavailableFeatureError, OutOfRangeDateError as DateRangeError +from .exceptions import ( + InvalidOutputFormatError, + UnavailableFeatureError, + OutOfRangeDateError as DateRangeError, +) from _kosmorro.i18n.utils import _, SHORT_DATE_FORMAT @@ -53,6 +58,16 @@ def main(): position = get_position(args.position) if args.position not in [None, ""] else None + # if output format is not specified, try to use output file extension as output format + if args.output is not None and output_format is None: + file_extension = os.path.splitext(args.output)[-1][1:].lower() + if file_extension: + output_format = file_extension + + # default to .txt if output format was not given and output file did not have file extension + if output_format is None: + output_format = "txt" + if output_format == "pdf": print( _( @@ -88,6 +103,10 @@ def main(): args.colors, args.show_graph, ) + except InvalidOutputFormatError as error: + print(colored(error.msg, "red")) + debug.debug_print(error) + return 3 except UnavailableFeatureError as error: print(colored(error.msg, "red")) debug.debug_print(error) @@ -99,9 +118,10 @@ def main(): if args.output is not None: try: - pdf_content = output.to_string() - with open(args.output, "wb") as output_file: - output_file.write(pdf_content) + file_content = output.to_string() + opening_mode = get_opening_mode(output_format) + with open(args.output, opening_mode) as output_file: + output_file.write(file_content) except UnavailableFeatureError as error: print(colored(error.msg, "red")) debug.debug_print(error) @@ -168,25 +188,35 @@ def get_information( events_list = get_events(compute_date, timezone) - return get_dumpers()[output_format]( - ephemerides=eph, - moon_phase=moon_phase, - events=events_list, - date=compute_date, - timezone=timezone, - with_colors=colors, - show_graph=show_graph, - ) + try: + return get_dumpers()[output_format]( + ephemerides=eph, + moon_phase=moon_phase, + events=events_list, + date=compute_date, + timezone=timezone, + with_colors=colors, + show_graph=show_graph, + ) + except KeyError as error: + raise InvalidOutputFormatError(output_format, list(get_dumpers().keys())) def get_dumpers() -> {str: dumper.Dumper}: return { - "text": dumper.TextDumper, + "txt": dumper.TextDumper, "json": dumper.JsonDumper, "pdf": dumper.PdfDumper, } +def get_opening_mode(format: str) -> str: + if format == "pdf": + return "wb" + + return "w" + + def output_version() -> bool: python_version = "%d.%d.%d" % ( sys.version_info[0], @@ -254,9 +284,12 @@ def get_args(output_formats: [str]): "--format", "-f", type=str, - default=output_formats[0], + default=None, choices=output_formats, - help=_("The format to output the information to"), + help=_( + "The format to output the information to. If not provided, the output format " + "will be inferred from the file extension of the output file." + ), ) parser.add_argument( "--position", diff --git a/manpage/kosmorro.1.md b/manpage/kosmorro.1.md index c27738f..445fca2 100644 --- a/manpage/kosmorro.1.md +++ b/manpage/kosmorro.1.md @@ -31,8 +31,8 @@ `--output=`_OUTPUT_, `-o` _OUTPUT_ a file to export the output to; if not given, the standard output is used -`--format=`_FORMAT_, `-f` _FORMAT_ - the format under which the information have to be output; one of the following: text, json, pdf +`--format=`_FORMAT_, `-f` _FORMAT_ (optional) + the format under which the information have to be output; one of the following: text, json, pdf. If no format is provided, the output format will be inferred from the extension of the output file `--no-graph` present the ephemerides in a table instead of a graph; PDF output format only @@ -68,7 +68,7 @@ kosmorro --latitude=50.5876 --longitude=3.0624 --date=2022-04-01 Compute the ephemerides for Lille, France, on April 1st, 2022, and export them in a PDF document: ``` -kosmorro --latitude=50.5876 --longitude=3.0624 -date=2022-04-01 --format=pdf --output=file.pdf +kosmorro --latitude=50.5876 --longitude=3.0624 -date=2022-04-01 --output=file.pdf ``` ## AUTHOR