diff --git a/pirel/releases.py b/pirel/releases.py index f57b938..97c582f 100644 --- a/pirel/releases.py +++ b/pirel/releases.py @@ -1,11 +1,12 @@ from __future__ import annotations +import calendar import datetime import json import logging import urllib.error import urllib.request -from typing import Any, Optional +from typing import Any, Literal, Optional import humanize import typer @@ -35,10 +36,16 @@ logger = logging.getLogger("pirel") -def parse_date(date_str: str) -> datetime.date: +def parse_date( + date_str: str, default_day: Literal["first", "last"] = "last" +) -> datetime.date: if len(date_str) == len("yyyy-mm"): - # We need a full yyyy-mm-dd, so let's approximate - return datetime.date.fromisoformat(date_str + "-01") + if default_day == "last": + last_day_of_month = calendar.monthrange(*map(int, date_str.split("-")))[1] + _date_str = f"{date_str}-{last_day_of_month}" + else: + _date_str = f"{date_str}-01" + return datetime.date.fromisoformat(_date_str) return datetime.date.fromisoformat(date_str) diff --git a/tests/test_cli.py b/tests/test_cli.py index 600ab6d..fabed93 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -28,12 +28,12 @@ ┏━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━┓ ┃ Version ┃ Status ┃ Released ┃ End-of-life ┃ ┡━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━┩ -│ 3.14 │ feature │ 2025-10-01 │ 2030-10-01 │ -│ 3.13 │ bugfix │ 2024-10-07 │ 2029-10-01 │ -│ 3.12 │ bugfix │ 2023-10-02 │ 2028-10-01 │ -│ 3.11 │ security │ 2022-10-24 │ 2027-10-01 │ -│ 3.10 │ security │ 2021-10-04 │ 2026-10-01 │ -│ 3.9 │ security │ 2020-10-05 │ 2025-10-01 │ +│ 3.14 │ feature │ 2025-10-01 │ 2030-10-31 │ +│ 3.13 │ bugfix │ 2024-10-07 │ 2029-10-31 │ +│ 3.12 │ bugfix │ 2023-10-02 │ 2028-10-31 │ +│ 3.11 │ security │ 2022-10-24 │ 2027-10-31 │ +│ 3.10 │ security │ 2021-10-04 │ 2026-10-31 │ +│ 3.9 │ security │ 2020-10-05 │ 2025-10-31 │ │ 3.8 │ end-of-life │ 2019-10-14 │ 2024-10-07 │ │ 3.7 │ end-of-life │ 2018-06-27 │ 2023-06-27 │ │ 3.6 │ end-of-life │ 2016-12-23 │ 2021-12-23 │ @@ -50,12 +50,12 @@ PYVER_TO_CHECK_OUTPUT = { "3.8": ":warning: You are using Python 3.8 which has reached end-of-life! Please upgrade to a newer version of Python (EOL 2024-10-07)", - "3.9": ":heavy_check_mark: You are using Python 3.9 which has security support for more than 10 months (EOL 2025-10-01)", - "3.10": ":heavy_check_mark: You are using Python 3.10 which has security support for more than 1 year, 10 months (EOL 2026-10-01)", - "3.11": ":heavy_check_mark: You are using Python 3.11 which has security support for more than 2 years (EOL 2027-10-01)", - "3.12": ":rocket: You are using Python 3.12 which is actively maintained (bugfixes) and has security support for more than 3 years (EOL 2028-10-01)", - "3.13": ":rocket: You are using Python 3.13 which is actively maintained (bugfixes) and has security support for more than 4 years (EOL 2029-10-01)", - "3.14": ":sparkles: You are using Python 3.14 which is not released yet and still accepts new features (EOL 2030-10-01)", + "3.9": ":heavy_check_mark: You are using Python 3.9 which has security support for more than 11 months (EOL 2025-10-31)", + "3.10": ":heavy_check_mark: You are using Python 3.10 which has security support for more than 1 year, 11 months (EOL 2026-10-31)", + "3.11": ":heavy_check_mark: You are using Python 3.11 which has security support for more than 2 years (EOL 2027-10-31)", + "3.12": ":rocket: You are using Python 3.12 which is actively maintained (bugfixes) and has security support for more than 3 years (EOL 2028-10-31)", + "3.13": ":rocket: You are using Python 3.13 which is actively maintained (bugfixes) and has security support for more than 4 years (EOL 2029-10-31)", + "3.14": ":sparkles: You are using Python 3.14 which is not released yet and still accepts new features (EOL 2030-10-31)", } DATE_FREEZE = datetime.date(2024, 11, 3) RELEASE_CYCLE_DATA_PATH = ( @@ -211,6 +211,8 @@ def test_pirel_check(mock_release_cycle_file, global_cli_args): 1 if "end-of-life" in PYVER_TO_CHECK_OUTPUT[pyver.as_release] else 0 ) + print(f"Frozen date is: {DATE_FREEZE}") + # Call CLI _args = [*global_cli_args, "check"] result = runner.invoke(app, _args)