Add the main flow that prints the results of the lectures

Task: MIL-004#3
This commit is contained in:
2026-10-13 15:32:21 +08:00
parent 844abb7482
commit d823e24616
+108
View File
@@ -0,0 +1,108 @@
## @file __main__.py
# @brief Command line of the weather data project: `python -m weather`.
#
# Prints the results of both lectures in the order of the lectures. The csv
# part needs no third-party package; the pandas part needs the `pandas` extra.
# A file is written only when `--export PATH` is given.
"""Prints the results of the weather lectures; run with `python -m weather`."""
import argparse
import sys
from collections.abc import Sequence
from pathlib import Path
from weather.constants import MONDAY, PANDAS_MISSING_MESSAGE
from weather.csv_reader import read_rows, read_temperatures
## @brief Value that `main` returns when the run succeeded.
EXIT_OK = 0
## @brief Value that `main` returns when the optional pandas extra is missing.
EXIT_PANDAS_MISSING = 1
def _build_parser() -> argparse.ArgumentParser:
"""! @brief Build the command line parser with its one optional flag.
@return The parser of `python -m weather`.
"""
parser = argparse.ArgumentParser(
prog="weather",
description="Print the results of the weather data lectures.",
)
parser.add_argument(
"--export",
metavar="PATH",
type=Path,
default=None,
help="also write the scores table to this CSV file",
)
return parser
def _print_csv_part() -> None:
"""! @brief Print the rows and temperatures read with the csv library."""
print("Rows (csv library):")
for row in read_rows():
print(row)
print(f"Temperatures (csv library): {read_temperatures()}")
def _print_pandas_part(export_path: Path | None) -> None:
"""! @brief Print the pandas results and export the scores when asked.
@param export_path File to write the scores table to; `None` writes nothing.
@throws ImportError When `pandas` is not installed.
"""
# Imported here so that the csv part runs without the optional extra.
from weather.analysis import (
average_temp,
average_temp_mean,
day_in_fahrenheit,
hottest_row,
max_temp,
read_data,
row_for_day,
to_data_dict,
to_temp_list,
)
from weather.export import create_scores_frame, export_frame
data = read_data()
print(f"Data frame (pandas):\n{data}")
print(f"Data dict: {to_data_dict(data)}")
print(f"Temp list: {to_temp_list(data)}")
print(f"Average temperature (sum / len): {average_temp(data)}")
print(f"Average temperature (mean): {average_temp_mean(data)}")
print(f"Maximum temperature: {max_temp(data)}")
print(f"Row of {MONDAY}:\n{row_for_day(data, MONDAY)}")
print(f"Hottest row:\n{hottest_row(data)}")
print(f"{MONDAY} in Fahrenheit: {day_in_fahrenheit(data, MONDAY)}")
scores = create_scores_frame()
print(f"Scores frame (from a dictionary):\n{scores}")
if export_path is not None:
export_frame(scores, export_path)
print(f"Scores frame exported to: {export_path}")
def main(argv: Sequence[str] | None = None) -> int:
"""! @brief Print the results of the lectures and optionally export a table.
@param argv The command line arguments; `sys.argv[1:]` when `None`.
@return `0` on success, `1` when the pandas extra is not installed.
"""
args = _build_parser().parse_args(argv)
_print_csv_part()
try:
_print_pandas_part(args.export)
except ImportError as error:
if error.name != "pandas":
raise
print(PANDAS_MISSING_MESSAGE, file=sys.stderr)
return EXIT_PANDAS_MISSING
return EXIT_OK
if __name__ == "__main__":
raise SystemExit(main())