guess output format based on output file extension check for empty output file default to .txt if no file extension provided change default output format back to txt add tests update man page fix default output format directly return output dumper use keys from dumpers in key error message fix man pages prevent output format from being overridden use first dumper key as default format update messages and formatting update help message for format argument specify list type in InvalidOutputFormat exception make default output format more apparent update messagespull/205/head
@@ -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 "$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" | 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 | # man page | ||||
assertSuccess "man --pager=cat kosmorro" | assertSuccess "man --pager=cat kosmorro" | ||||
@@ -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): | class CompileError(RuntimeError): | ||||
def __init__(self, msg): | def __init__(self, msg): | ||||
super().__init__() | super().__init__() | ||||
@@ -8,7 +8,7 @@ msgid "" | |||||
msgstr "" | msgstr "" | ||||
"Project-Id-Version: kosmorro 0.10.1\n" | "Project-Id-Version: kosmorro 0.10.1\n" | ||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" | "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" | ||||
@@ -116,6 +116,12 @@ msgstr "" | |||||
msgid "The date must be between {minimum_date} and {maximum_date}" | msgid "The date must be between {minimum_date} and {maximum_date}" | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/exceptions.py:47 | |||||
msgid "" | |||||
"Invalid output format: {output_format}. Output file must end with: " | |||||
"{accepted_extensions}" | |||||
msgstr "" | |||||
#: _kosmorro/geolocation.py:14 | #: _kosmorro/geolocation.py:14 | ||||
#, python-format | #, python-format | ||||
msgid "The given position (%s) is not valid." | 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." | msgid "The given Plus Code seems to be a short code, please provide a full code." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:58 | #: _kosmorro/main.py:73 | ||||
msgid "" | msgid "" | ||||
"Save the planet and paper!\n" | "Save the planet and paper!\n" | ||||
"Consider printing your PDF document only if really necessary, and use the" | "Consider printing your PDF document only if really necessary, and use the" | ||||
" other side of the sheet." | " other side of the sheet." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:67 | #: _kosmorro/main.py:82 | ||||
msgid "" | msgid "" | ||||
"PDF output will not contain the ephemerides, because you didn't provide " | "PDF output will not contain the ephemerides, because you didn't provide " | ||||
"the observation coordinates." | "the observation coordinates." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:112 | #: _kosmorro/main.py:132 | ||||
msgid "The file could not be saved in \"{path}\": {error}" | msgid "The file could not be saved in \"{path}\": {error}" | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:126 | #: _kosmorro/main.py:146 | ||||
msgid "Please provide a file path to export in this format (--output)." | msgid "Please provide a file path to export in this format (--output)." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:159 | #: _kosmorro/main.py:179 | ||||
msgid "Moon phase can only be displayed between {min_date} and {max_date}" | msgid "Moon phase can only be displayed between {min_date} and {max_date}" | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:198 | #: _kosmorro/main.py:228 | ||||
msgid "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" | msgid "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:208 | #: _kosmorro/main.py:238 | ||||
msgid "Do you really want to clear Kosmorro's cache? [yN] " | msgid "Do you really want to clear Kosmorro's cache? [yN] " | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:216 | #: _kosmorro/main.py:246 | ||||
msgid "Incorrect answer, cache not cleared." | msgid "Incorrect answer, cache not cleared." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:226 | #: _kosmorro/main.py:256 | ||||
msgid "" | msgid "" | ||||
"Compute the ephemerides and the events for a given date and a given " | "Compute the ephemerides and the events for a given date and a given " | ||||
"position on Earth." | "position on Earth." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:229 | #: _kosmorro/main.py:259 | ||||
msgid "" | msgid "" | ||||
"By default, only the events will be computed for today ({date}).\n" | "By default, only the events will be computed for today ({date}).\n" | ||||
"To compute also the ephemerides, latitude and longitude arguments are " | "To compute also the ephemerides, latitude and longitude arguments are " | ||||
"needed." | "needed." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:243 | #: _kosmorro/main.py:273 | ||||
msgid "Show the program version" | msgid "Show the program version" | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:251 | #: _kosmorro/main.py:281 | ||||
msgid "Delete all the files from Kosmorro's cache." | msgid "Delete all the files from Kosmorro's cache." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:259 | #: _kosmorro/main.py:289 | ||||
msgid "The format to output the information to" | 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 "" | msgstr "" | ||||
#: _kosmorro/main.py:266 | #: _kosmorro/main.py:299 | ||||
msgid "" | msgid "" | ||||
"The observer's position on Earth, in the \"{latitude},{longitude}\" " | "The observer's position on Earth, in the \"{latitude},{longitude}\" " | ||||
"format.Can also be set in the KOSMORRO_POSITION environment variable." | "format.Can also be set in the KOSMORRO_POSITION environment variable." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:276 | #: _kosmorro/main.py:309 | ||||
msgid "" | msgid "" | ||||
"The date for which the ephemerides must be calculated. Can be in the " | "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," | "YYYY-MM-DD format or an interval in the \"[+-]YyMmDd\" format (with Y, M," | ||||
" and D numbers). Defaults to today ({default_date})." | " and D numbers). Defaults to today ({default_date})." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:287 | #: _kosmorro/main.py:320 | ||||
msgid "" | msgid "" | ||||
"The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). " | "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." | "Can also be set in the KOSMORRO_TIMEZONE environment variable." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:296 | #: _kosmorro/main.py:329 | ||||
msgid "Disable the colors in the console." | msgid "Disable the colors in the console." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:303 | #: _kosmorro/main.py:336 | ||||
msgid "" | msgid "" | ||||
"A file to export the output to. If not given, the standard output is " | "A file to export the output to. If not given, the standard output is " | ||||
"used. This argument is needed for PDF format." | "used. This argument is needed for PDF format." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:312 | #: _kosmorro/main.py:345 | ||||
msgid "" | msgid "" | ||||
"Do not generate a graph to represent the rise and set times in the PDF " | "Do not generate a graph to represent the rise and set times in the PDF " | ||||
"format." | "format." | ||||
msgstr "" | msgstr "" | ||||
#: _kosmorro/main.py:320 | #: _kosmorro/main.py:353 | ||||
msgid "Show debugging messages" | msgid "Show debugging messages" | ||||
msgstr "" | msgstr "" | ||||
@@ -20,6 +20,7 @@ import argparse | |||||
import locale | import locale | ||||
import re | import re | ||||
import sys | import sys | ||||
import os.path | |||||
from kosmorrolib import Position, get_ephemerides, get_events, get_moon_phase | from kosmorrolib import Position, get_ephemerides, get_events, get_moon_phase | ||||
from kosmorrolib.__version__ import __version__ as kosmorrolib_version | from kosmorrolib.__version__ import __version__ as kosmorrolib_version | ||||
@@ -31,7 +32,11 @@ from . import dumper, environment, debug | |||||
from .date import parse_date | from .date import parse_date | ||||
from .geolocation import get_position | from .geolocation import get_position | ||||
from .__version__ import __version__ as kosmorro_version | 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 | 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 | 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": | if output_format == "pdf": | ||||
print( | print( | ||||
_( | _( | ||||
@@ -88,6 +103,10 @@ def main(): | |||||
args.colors, | args.colors, | ||||
args.show_graph, | args.show_graph, | ||||
) | ) | ||||
except InvalidOutputFormatError as error: | |||||
print(colored(error.msg, "red")) | |||||
debug.debug_print(error) | |||||
return 3 | |||||
except UnavailableFeatureError as error: | except UnavailableFeatureError as error: | ||||
print(colored(error.msg, "red")) | print(colored(error.msg, "red")) | ||||
debug.debug_print(error) | debug.debug_print(error) | ||||
@@ -99,9 +118,10 @@ def main(): | |||||
if args.output is not None: | if args.output is not None: | ||||
try: | try: | ||||
pdf_content = output.to_string() | file_content = output.to_string() | ||||
with open(args.output, "wb") as output_file: | opening_mode = get_opening_mode(output_format) | ||||
output_file.write(pdf_content) | with open(args.output, opening_mode) as output_file: | ||||
output_file.write(file_content) | |||||
except UnavailableFeatureError as error: | except UnavailableFeatureError as error: | ||||
print(colored(error.msg, "red")) | print(colored(error.msg, "red")) | ||||
debug.debug_print(error) | debug.debug_print(error) | ||||
@@ -168,25 +188,35 @@ def get_information( | |||||
events_list = get_events(compute_date, timezone) | events_list = get_events(compute_date, timezone) | ||||
return get_dumpers()[output_format]( | try: | ||||
ephemerides=eph, | return get_dumpers()[output_format]( | ||||
moon_phase=moon_phase, | ephemerides=eph, | ||||
events=events_list, | moon_phase=moon_phase, | ||||
date=compute_date, | events=events_list, | ||||
timezone=timezone, | date=compute_date, | ||||
with_colors=colors, | timezone=timezone, | ||||
show_graph=show_graph, | 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}: | def get_dumpers() -> {str: dumper.Dumper}: | ||||
return { | return { | ||||
"text": dumper.TextDumper, | "txt": dumper.TextDumper, | ||||
"json": dumper.JsonDumper, | "json": dumper.JsonDumper, | ||||
"pdf": dumper.PdfDumper, | "pdf": dumper.PdfDumper, | ||||
} | } | ||||
def get_opening_mode(format: str) -> str: | |||||
if format == "pdf": | |||||
return "wb" | |||||
return "w" | |||||
def output_version() -> bool: | def output_version() -> bool: | ||||
python_version = "%d.%d.%d" % ( | python_version = "%d.%d.%d" % ( | ||||
sys.version_info[0], | sys.version_info[0], | ||||
@@ -254,9 +284,12 @@ def get_args(output_formats: [str]): | |||||
"--format", | "--format", | ||||
"-f", | "-f", | ||||
type=str, | type=str, | ||||
default=output_formats[0], | default=None, | ||||
choices=output_formats, | 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( | parser.add_argument( | ||||
"--position", | "--position", | ||||
@@ -31,8 +31,8 @@ | |||||
`--output=`_OUTPUT_, `-o` _OUTPUT_ | `--output=`_OUTPUT_, `-o` _OUTPUT_ | ||||
a file to export the output to; if not given, the standard output is used | a file to export the output to; if not given, the standard output is used | ||||
`--format=`_FORMAT_, `-f` _FORMAT_ | `--format=`_FORMAT_, `-f` _FORMAT_ (optional) | ||||
the format under which the information have to be output; one of the following: text, json, pdf | 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` | `--no-graph` | ||||
present the ephemerides in a table instead of a graph; PDF output format only | 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: | 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 | ## AUTHOR | ||||