From a44339927c23d235d7d3dc14ca7d5f945f0d6495 Mon Sep 17 00:00:00 2001 From: Jens Tirsvad Nielsen Date: Tue, 13 Oct 2026 15:26:20 +0800 Subject: [PATCH] Add constants.py and its test Task: MIL-001#3 --- src/weather/__init__.py | 14 ++++++++++++ src/weather/constants.py | 48 ++++++++++++++++++++++++++++++++++++++++ tests/conftest.py | 16 ++++++++++++++ tests/test_constants.py | 36 ++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 src/weather/__init__.py create mode 100644 src/weather/constants.py create mode 100644 tests/conftest.py create mode 100644 tests/test_constants.py diff --git a/src/weather/__init__.py b/src/weather/__init__.py new file mode 100644 index 0000000..425bd54 --- /dev/null +++ b/src/weather/__init__.py @@ -0,0 +1,14 @@ +## @package weather +# @brief Reading CSV weather data, from Udemy's 100 Days of Code (day 25). +# +# @mainpage Weather Data +# +# The day-25 lectures read the weather data of one week from the file +# weather_data.csv: first with Python's built-in csv library, then with the +# pandas library, which makes the same work a one-liner. The package keeps the +# two ways side by side: csv_reader.py uses the standard library only, and +# analysis.py and export.py need the optional pandas extra. +# +# The constants of the package are in constants.py. + +"""Reading CSV weather data, from Udemy's 100 Days of Code (day 25).""" diff --git a/src/weather/constants.py b/src/weather/constants.py new file mode 100644 index 0000000..f28690a --- /dev/null +++ b/src/weather/constants.py @@ -0,0 +1,48 @@ +## @file constants.py +# @brief Constants of the weather data project. +# +# Every value that the day-25 lectures fix lives here, so that no other module +# contains a magic string or number: the name of the data file, the names of +# its columns, the factors of the Fahrenheit conversion and the name of the +# exported file. + +"""Constants of the weather data project, as fixed by the day-25 lectures.""" + +from pathlib import Path +from typing import Final + +## @brief Folder of this package; the data file lies next to the modules. +PACKAGE_DIR: Final[Path] = Path(__file__).resolve().parent + +## @brief Name of the weather data file of the lecture. +DATA_FILE_NAME: Final[str] = "weather_data.csv" + +## @brief Full path of the weather data file, independent of the working folder. +DATA_FILE: Final[Path] = PACKAGE_DIR / DATA_FILE_NAME + +## @brief Name of the file that the exported table is written to by default. +EXPORT_FILE_NAME: Final[str] = "new_data.csv" + +## @brief Encoding of the CSV files that are read and written. +FILE_ENCODING: Final[str] = "utf-8" + +## @brief Name of the column that holds the day of the week. +COLUMN_DAY: Final[str] = "day" + +## @brief Name of the column that holds the temperature in degrees Celsius. +COLUMN_TEMP: Final[str] = "temp" + +## @brief Name of the column that holds the weather condition, such as `Sunny`. +COLUMN_CONDITION: Final[str] = "condition" + +## @brief Position of the temperature in a row that `csv.reader` returns. +TEMP_COLUMN_INDEX: Final[int] = 1 + +## @brief Numerator of the Celsius to Fahrenheit factor: `temp * 9 / 5 + 32`. +FAHRENHEIT_NUMERATOR: Final[int] = 9 + +## @brief Denominator of the Celsius to Fahrenheit factor: `temp * 9 / 5 + 32`. +FAHRENHEIT_DENOMINATOR: Final[int] = 5 + +## @brief Offset of the Celsius to Fahrenheit conversion: `temp * 9 / 5 + 32`. +FAHRENHEIT_OFFSET: Final[int] = 32 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..ff287b5 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,16 @@ +"""Shared pytest configuration for the weather data tests.""" + +from pathlib import Path + +import pytest + + +@pytest.fixture(autouse=True) +def isolated_working_directory(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: + """Run every test in an empty temporary working directory. + + The export has a default file name relative to the working directory. Without + this fixture, a test that uses the default would write into the folder pytest + was started from. + """ + monkeypatch.chdir(tmp_path) diff --git a/tests/test_constants.py b/tests/test_constants.py new file mode 100644 index 0000000..c9872de --- /dev/null +++ b/tests/test_constants.py @@ -0,0 +1,36 @@ +"""Tests of the constants that the day-25 lectures fix.""" + +from weather import constants + + +def test_data_file_is_the_one_of_the_lecture() -> None: + assert constants.DATA_FILE_NAME == "weather_data.csv" + + +def test_data_file_lies_next_to_the_modules_not_in_the_working_folder() -> None: + assert constants.DATA_FILE.is_absolute() + assert constants.DATA_FILE.parent == constants.PACKAGE_DIR + assert constants.DATA_FILE.name == constants.DATA_FILE_NAME + + +def test_column_names_match_the_header_of_the_lecture() -> None: + assert constants.COLUMN_DAY == "day" + assert constants.COLUMN_TEMP == "temp" + assert constants.COLUMN_CONDITION == "condition" + + +def test_temperature_is_the_second_value_of_a_row() -> None: + assert constants.TEMP_COLUMN_INDEX == 1 + + +def test_fahrenheit_factors_give_the_lecture_formula() -> None: + celsius = 100 + fahrenheit = ( + celsius * constants.FAHRENHEIT_NUMERATOR / constants.FAHRENHEIT_DENOMINATOR + + constants.FAHRENHEIT_OFFSET + ) + assert fahrenheit == 212 + + +def test_exported_file_has_the_name_of_the_lecture() -> None: + assert constants.EXPORT_FILE_NAME == "new_data.csv"