From 8260bcc44e08bba31da39436c174f798728250eb Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Tue, 21 Apr 2026 19:10:34 -0400 Subject: [PATCH 1/7] feat(rhel): add Red Hat Enterprise Linux support Fetches lifecycle data from the official Red Hat Product Life Cycle Data API (access.redhat.com/product-life-cycles/api/v1). Maps phases as: - begin_support: General availability date - end_support: End of Maintenance support - end_extended_support: End of ELS add-on begin_dev is set equal to begin_support so that is_in_development_on always returns False (Red Hat does not publish pre-GA development dates). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/distro_support/rhel.json | 42 ++++++++++++++++++++++++++++++++++ src/distro_support/rhel.py | 44 ++++++++++++++++++++++++++++++++++++ tools/update.py | 4 +++- 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/distro_support/rhel.json create mode 100644 src/distro_support/rhel.py diff --git a/src/distro_support/rhel.json b/src/distro_support/rhel.json new file mode 100644 index 0000000..fa06830 --- /dev/null +++ b/src/distro_support/rhel.json @@ -0,0 +1,42 @@ +{ + "7": { + "distribution": "rhel", + "version": "7", + "begin_support": "2014-06-10", + "end_support": "2024-06-30", + "begin_dev": "2014-06-10", + "end_extended_support": "2029-05-31" + }, + "6": { + "distribution": "rhel", + "version": "6", + "begin_support": "2010-11-10", + "end_support": "2020-11-30", + "begin_dev": "2010-11-10", + "end_extended_support": "2024-06-30" + }, + "10": { + "distribution": "rhel", + "version": "10", + "begin_support": "2025-05-20", + "end_support": "2035-05-31", + "begin_dev": "2025-05-20", + "end_extended_support": "2038-05-31" + }, + "9": { + "distribution": "rhel", + "version": "9", + "begin_support": "2022-05-18", + "end_support": "2032-05-31", + "begin_dev": "2022-05-18", + "end_extended_support": "2035-05-31" + }, + "8": { + "distribution": "rhel", + "version": "8", + "begin_support": "2019-05-07", + "end_support": "2029-05-31", + "begin_dev": "2019-05-07", + "end_extended_support": "2032-05-31" + } +} diff --git a/src/distro_support/rhel.py b/src/distro_support/rhel.py new file mode 100644 index 0000000..08e14f8 --- /dev/null +++ b/src/distro_support/rhel.py @@ -0,0 +1,44 @@ +"""Information about Red Hat Enterprise Linux support.""" + +import json +from urllib import request + +SUPPORT_INFO_URL = "https://access.redhat.com/product-life-cycles/api/v1/products?name=Red+Hat+Enterprise+Linux" + +_PHASE_GA = "general availability" +_PHASE_MAINTENANCE = "maintenance support" +_PHASE_ELS = "extended life cycle support (els) add-on" + + +def _parse_date(value: str | None) -> str | None: + """Return an ISO date string (YYYY-MM-DD), or None for missing/non-date values.""" + if not value or value.upper() == "N/A" or value.lower() == "ongoing": + return None + return value[:10] + + +def get_distro_info() -> dict[str, dict[str, str | None]]: + req = request.Request(SUPPORT_INFO_URL, headers={"User-Agent": "distro-support"}) + with request.urlopen(req) as response: + if response.status != 200: + raise ConnectionError(response.status) + data = json.loads(response.read()) + + series = {} + for version in data["data"][0]["versions"]: + ver = version["name"] + phases = {p["name"].lower(): p for p in version["phases"]} + + series[ver] = { + "distribution": "rhel", + "version": ver, + "begin_support": _parse_date(phases.get(_PHASE_GA, {}).get("end_date")), + "end_support": _parse_date( + phases.get(_PHASE_MAINTENANCE, {}).get("end_date") + ), + "begin_dev": _parse_date(phases.get(_PHASE_GA, {}).get("end_date")), + "end_extended_support": _parse_date( + phases.get(_PHASE_ELS, {}).get("end_date") + ), + } + return series diff --git a/tools/update.py b/tools/update.py index 0e47d7f..89be391 100644 --- a/tools/update.py +++ b/tools/update.py @@ -3,7 +3,7 @@ import json import pathlib -from distro_support import alpine, debian, devuan, ubuntu +from distro_support import alpine, debian, devuan, rhel, ubuntu def update(module): @@ -20,3 +20,5 @@ def update(module): update(devuan) print("Updating Alpine data") update(alpine) + print("Updating RHEL data") + update(rhel) From d6213f6fced8fb30991135bb25cd68b4bab84db0 Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Tue, 21 Apr 2026 19:10:48 -0400 Subject: [PATCH 2/7] test(rhel): add tests for RHEL downloader and support range Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/test_get_support_range.py | 4 + tests/test_rhel_downloader.py | 178 ++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 tests/test_rhel_downloader.py diff --git a/tests/test_get_support_range.py b/tests/test_get_support_range.py index 7e67cd4..c2e8d18 100644 --- a/tests/test_get_support_range.py +++ b/tests/test_get_support_range.py @@ -16,12 +16,16 @@ ("ubuntu", "25.10", date(2025, 8, 12), False, True, None), ("debian", "1.1", date(2000, 1, 1), False, False, None), ("debian", "", date(3000, 1, 1), False, True, None), +<<<<<<< HEAD ("devuan", "4", date(2022, 1, 1), True, False, None), ("devuan", "4", date(2030, 1, 1), False, False, None), ("devuan", "7", date(2026, 1, 1), False, True, None), # Alpine has no begin_dev, so in_dev=None signals NoDevelopmentInfoError ("alpine", "3.20", date(2025, 1, 1), True, None, None), ("alpine", "3.17", date(2025, 1, 1), False, None, None), + ("rhel", "9", date(2023, 1, 1), True, False, False), + ("rhel", "9", date(2033, 1, 1), False, False, True), + ("rhel", "7", date(2025, 1, 1), False, False, True), ], ) def test_get_support_range( diff --git a/tests/test_rhel_downloader.py b/tests/test_rhel_downloader.py new file mode 100644 index 0000000..f61d603 --- /dev/null +++ b/tests/test_rhel_downloader.py @@ -0,0 +1,178 @@ +"""Tests for the RHEL downloader.""" + +import json +from unittest.mock import MagicMock, patch + +import pytest + +from distro_support.rhel import _parse_date, get_distro_info + +# Minimal realistic API response mirroring the Red Hat lifecycle API structure. +_FAKE_API_RESPONSE = { + "data": [ + { + "versions": [ + { + "name": "9", + "phases": [ + { + "name": "General availability", + "end_date": "2022-05-18T00:00:00.000Z", + }, + { + "name": "Full support", + "end_date": "2027-05-31T00:00:00.000Z", + }, + { + "name": "Maintenance support", + "end_date": "2032-05-31T00:00:00.000Z", + }, + { + "name": "Extended life cycle support (ELS) add-on", + "end_date": "2035-05-31T00:00:00.000Z", + }, + { + "name": "Extended life phase", + "end_date": "Ongoing", + }, + ], + }, + { + "name": "7", + "phases": [ + { + "name": "General availability", + "end_date": "2014-06-10T00:00:00.000Z", + }, + { + "name": "Full support", + "end_date": "2019-08-06T00:00:00.000Z", + }, + { + "name": "Maintenance support", + "end_date": "2024-06-30T00:00:00.000Z", + }, + { + "name": "Extended life cycle support (ELS) add-on", + "end_date": "2029-05-31T00:00:00.000Z", + }, + { + "name": "Extended life phase", + "end_date": "Ongoing", + }, + ], + }, + { + # Version with N/A GA date (as seen in some older entries) + "name": "6", + "phases": [ + { + "name": "General availability", + "end_date": "N/A", + }, + { + "name": "Maintenance support", + "end_date": "2020-11-30T00:00:00.000Z", + }, + # No ELS phase for this entry + ], + }, + ] + } + ] +} + + +def _make_mock_response(data: dict): + mock_response = MagicMock() + mock_response.status = 200 + mock_response.read.return_value = json.dumps(data).encode() + mock_response.__enter__ = lambda s: s + mock_response.__exit__ = MagicMock(return_value=False) + return mock_response + + +@pytest.fixture +def mock_urlopen(): + with patch("distro_support.rhel.request.urlopen") as mock: + mock.return_value = _make_mock_response(_FAKE_API_RESPONSE) + yield mock + + +class TestParseDate: + def test_iso_timestamp(self): + assert _parse_date("2022-05-18T00:00:00.000Z") == "2022-05-18" + + def test_plain_iso_date(self): + assert _parse_date("2022-05-18") == "2022-05-18" + + def test_ongoing_returns_none(self): + assert _parse_date("Ongoing") is None + + def test_ongoing_case_insensitive(self): + assert _parse_date("ongoing") is None + + def test_na_returns_none(self): + assert _parse_date("N/A") is None + + def test_na_case_insensitive(self): + assert _parse_date("n/a") is None + + def test_none_returns_none(self): + assert _parse_date(None) is None + + def test_empty_string_returns_none(self): + assert _parse_date("") is None + + +class TestGetDistroInfo: + def test_returns_all_versions(self, mock_urlopen): + result = get_distro_info() + assert set(result.keys()) == {"9", "7", "6"} + + def test_distribution_name(self, mock_urlopen): + result = get_distro_info() + for ver in result.values(): + assert ver["distribution"] == "rhel" + + def test_version_field_matches_key(self, mock_urlopen): + result = get_distro_info() + for key, ver in result.items(): + assert ver["version"] == key + + def test_begin_dev_equals_begin_support(self, mock_urlopen): + """begin_dev is set to the GA date so is_in_development_on always returns False.""" + result = get_distro_info() + for ver in result.values(): + assert ver["begin_dev"] == ver["begin_support"] + + def test_full_version_dates(self, mock_urlopen): + result = get_distro_info() + assert result["9"]["begin_support"] == "2022-05-18" + assert result["9"]["end_support"] == "2032-05-31" + assert result["9"]["end_extended_support"] == "2035-05-31" + + def test_ongoing_eol_is_none(self, mock_urlopen): + # Extended life phase is "Ongoing" — should not bleed into our fields + result = get_distro_info() + assert result["9"]["end_extended_support"] == "2035-05-31" + + def test_na_ga_date_is_none(self, mock_urlopen): + result = get_distro_info() + assert result["6"]["begin_support"] is None + + def test_missing_els_phase_is_none(self, mock_urlopen): + result = get_distro_info() + assert result["6"]["end_extended_support"] is None + + def test_sends_user_agent(self, mock_urlopen): + get_distro_info() + req = mock_urlopen.call_args[0][0] + assert req.get_header("User-agent") == "distro-support" + + def test_http_error_raises(self): + mock_response = _make_mock_response(_FAKE_API_RESPONSE) + mock_response.status = 503 + with patch("distro_support.rhel.request.urlopen", return_value=mock_response): + with pytest.raises(ConnectionError): + get_distro_info() From bb6b73948c842bac06bfb9b2cce5bad508cf805f Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Tue, 21 Apr 2026 21:50:08 -0400 Subject: [PATCH 3/7] fix: address Gemini and Codacy review feedback on RHEL module - Use json.load() instead of json.loads(response.read()) for efficiency - Replace ConnectionError with RuntimeError for HTTP error status - Guard against empty data[] response to avoid IndexError - Use .get() for 'versions' and 'phases' for schema robustness - Calculate GA date once and reuse for begin_support and begin_dev - Rename ubuntu_data variable in update.py to data_path (generic) - Add sort_keys=True to json.dumps for deterministic output order - Re-sort existing ubuntu and debian JSON data files accordingly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/distro_support/debian.json | 224 ++++++++--------- src/distro_support/rhel.py | 18 +- src/distro_support/ubuntu.json | 440 ++++++++++++++++----------------- tools/update.py | 6 +- 4 files changed, 348 insertions(+), 340 deletions(-) diff --git a/src/distro_support/debian.json b/src/distro_support/debian.json index e279c49..5d5102f 100644 --- a/src/distro_support/debian.json +++ b/src/distro_support/debian.json @@ -1,170 +1,170 @@ { - "1.1": { + "": { + "begin_dev": "1993-08-16", + "begin_support": null, "distribution": "debian", - "version": "1.1", + "end_extended_support": null, + "end_support": null, + "version": "" + }, + "1.1": { + "begin_dev": "1993-08-16", "begin_support": "1996-06-17", + "distribution": "debian", + "end_extended_support": null, "end_support": "1997-06-05", - "begin_dev": "1993-08-16", - "end_extended_support": null + "version": "1.1" }, "1.2": { - "distribution": "debian", - "version": "1.2", + "begin_dev": "1996-06-17", "begin_support": "1996-12-12", + "distribution": "debian", + "end_extended_support": null, "end_support": "1998-06-05", - "begin_dev": "1996-06-17", - "end_extended_support": null + "version": "1.2" }, "1.3": { - "distribution": "debian", - "version": "1.3", + "begin_dev": "1996-12-12", "begin_support": "1997-06-05", + "distribution": "debian", + "end_extended_support": null, "end_support": "1999-03-09", - "begin_dev": "1996-12-12", - "end_extended_support": null + "version": "1.3" }, - "2.0": { + "10": { + "begin_dev": "2017-06-17", + "begin_support": "2019-07-06", + "distribution": "debian", + "end_extended_support": "2029-06-30", + "end_support": "2022-09-10", + "version": "10" + }, + "11": { + "begin_dev": "2019-07-06", + "begin_support": "2021-08-14", + "distribution": "debian", + "end_extended_support": "2031-06-30", + "end_support": "2024-08-14", + "version": "11" + }, + "12": { + "begin_dev": "2021-08-14", + "begin_support": "2023-06-10", + "distribution": "debian", + "end_extended_support": "2033-06-30", + "end_support": "2026-07-11", + "version": "12" + }, + "13": { + "begin_dev": "2023-06-10", + "begin_support": "2025-08-09", + "distribution": "debian", + "end_extended_support": "2035-06-30", + "end_support": "2028-08-09", + "version": "13" + }, + "14": { + "begin_dev": "2025-08-09", + "begin_support": null, "distribution": "debian", - "version": "2.0", + "end_extended_support": null, + "end_support": null, + "version": "14" + }, + "15": { + "begin_dev": "2027-08-01", + "begin_support": null, + "distribution": "debian", + "end_extended_support": null, + "end_support": null, + "version": "15" + }, + "2.0": { + "begin_dev": "1997-06-05", "begin_support": "1998-07-24", + "distribution": "debian", + "end_extended_support": null, "end_support": "2000-03-09", - "begin_dev": "1997-06-05", - "end_extended_support": null + "version": "2.0" }, "2.1": { - "distribution": "debian", - "version": "2.1", + "begin_dev": "1998-07-24", "begin_support": "1999-03-09", + "distribution": "debian", + "end_extended_support": null, "end_support": "2000-10-30", - "begin_dev": "1998-07-24", - "end_extended_support": null + "version": "2.1" }, "2.2": { - "distribution": "debian", - "version": "2.2", + "begin_dev": "1999-03-09", "begin_support": "2000-08-15", + "distribution": "debian", + "end_extended_support": null, "end_support": "2003-06-30", - "begin_dev": "1999-03-09", - "end_extended_support": null + "version": "2.2" }, "3.0": { - "distribution": "debian", - "version": "3.0", + "begin_dev": "2000-08-15", "begin_support": "2002-07-19", + "distribution": "debian", + "end_extended_support": null, "end_support": "2006-06-30", - "begin_dev": "2000-08-15", - "end_extended_support": null + "version": "3.0" }, "3.1": { - "distribution": "debian", - "version": "3.1", + "begin_dev": "2002-07-19", "begin_support": "2005-06-06", + "distribution": "debian", + "end_extended_support": null, "end_support": "2008-03-31", - "begin_dev": "2002-07-19", - "end_extended_support": null + "version": "3.1" }, "4.0": { - "distribution": "debian", - "version": "4.0", + "begin_dev": "2005-06-06", "begin_support": "2007-04-08", + "distribution": "debian", + "end_extended_support": null, "end_support": "2010-02-15", - "begin_dev": "2005-06-06", - "end_extended_support": null + "version": "4.0" }, "5.0": { - "distribution": "debian", - "version": "5.0", + "begin_dev": "2007-04-08", "begin_support": "2009-02-14", + "distribution": "debian", + "end_extended_support": null, "end_support": "2012-02-06", - "begin_dev": "2007-04-08", - "end_extended_support": null + "version": "5.0" }, "6.0": { - "distribution": "debian", - "version": "6.0", + "begin_dev": "2009-02-14", "begin_support": "2011-02-06", + "distribution": "debian", + "end_extended_support": null, "end_support": "2014-05-31", - "begin_dev": "2009-02-14", - "end_extended_support": null + "version": "6.0" }, "7": { - "distribution": "debian", - "version": "7", + "begin_dev": "2011-02-06", "begin_support": "2013-05-04", + "distribution": "debian", + "end_extended_support": "2020-06-30", "end_support": "2016-04-25", - "begin_dev": "2011-02-06", - "end_extended_support": "2020-06-30" + "version": "7" }, "8": { - "distribution": "debian", - "version": "8", + "begin_dev": "2013-05-04", "begin_support": "2015-04-26", + "distribution": "debian", + "end_extended_support": "2025-06-30", "end_support": "2018-06-17", - "begin_dev": "2013-05-04", - "end_extended_support": "2025-06-30" + "version": "8" }, "9": { - "distribution": "debian", - "version": "9", - "begin_support": "2017-06-17", - "end_support": "2020-07-18", "begin_dev": "2015-04-26", - "end_extended_support": "2027-06-30" - }, - "10": { - "distribution": "debian", - "version": "10", - "begin_support": "2019-07-06", - "end_support": "2022-09-10", - "begin_dev": "2017-06-17", - "end_extended_support": "2029-06-30" - }, - "11": { - "distribution": "debian", - "version": "11", - "begin_support": "2021-08-14", - "end_support": "2024-08-14", - "begin_dev": "2019-07-06", - "end_extended_support": "2031-06-30" - }, - "12": { - "distribution": "debian", - "version": "12", - "begin_support": "2023-06-10", - "end_support": "2026-07-11", - "begin_dev": "2021-08-14", - "end_extended_support": "2033-06-30" - }, - "13": { - "distribution": "debian", - "version": "13", - "begin_support": "2025-08-09", - "end_support": "2028-08-09", - "begin_dev": "2023-06-10", - "end_extended_support": "2035-06-30" - }, - "14": { - "distribution": "debian", - "version": "14", - "begin_support": null, - "end_support": null, - "begin_dev": "2025-08-09", - "end_extended_support": null - }, - "15": { - "distribution": "debian", - "version": "15", - "begin_support": null, - "end_support": null, - "begin_dev": "2027-08-01", - "end_extended_support": null - }, - "": { + "begin_support": "2017-06-17", "distribution": "debian", - "version": "", - "begin_support": null, - "end_support": null, - "begin_dev": "1993-08-16", - "end_extended_support": null + "end_extended_support": "2027-06-30", + "end_support": "2020-07-18", + "version": "9" } } diff --git a/src/distro_support/rhel.py b/src/distro_support/rhel.py index 08e14f8..fb0c93b 100644 --- a/src/distro_support/rhel.py +++ b/src/distro_support/rhel.py @@ -21,22 +21,28 @@ def get_distro_info() -> dict[str, dict[str, str | None]]: req = request.Request(SUPPORT_INFO_URL, headers={"User-Agent": "distro-support"}) with request.urlopen(req) as response: if response.status != 200: - raise ConnectionError(response.status) - data = json.loads(response.read()) + raise RuntimeError( + f"Unexpected HTTP status from Red Hat API: {response.status}" + ) + data = json.load(response) + + if not data.get("data"): + return {} series = {} - for version in data["data"][0]["versions"]: + for version in data["data"][0].get("versions", []): ver = version["name"] - phases = {p["name"].lower(): p for p in version["phases"]} + phases = {p["name"].lower(): p for p in version.get("phases", [])} + ga_date = _parse_date(phases.get(_PHASE_GA, {}).get("end_date")) series[ver] = { "distribution": "rhel", "version": ver, - "begin_support": _parse_date(phases.get(_PHASE_GA, {}).get("end_date")), + "begin_support": ga_date, "end_support": _parse_date( phases.get(_PHASE_MAINTENANCE, {}).get("end_date") ), - "begin_dev": _parse_date(phases.get(_PHASE_GA, {}).get("end_date")), + "begin_dev": ga_date, "end_extended_support": _parse_date( phases.get(_PHASE_ELS, {}).get("end_date") ), diff --git a/src/distro_support/ubuntu.json b/src/distro_support/ubuntu.json index f3bd81a..59b191c 100644 --- a/src/distro_support/ubuntu.json +++ b/src/distro_support/ubuntu.json @@ -1,354 +1,354 @@ { - "4.10": { - "distribution": "ubuntu", - "version": "4.10", - "begin_support": "2004-10-20", - "end_support": "2006-04-30", - "begin_dev": "2004-03-05", - "end_extended_support": null - }, - "5.04": { - "distribution": "ubuntu", - "version": "5.04", - "begin_support": "2005-04-08", - "end_support": "2006-10-31", - "begin_dev": "2004-10-20", - "end_extended_support": null - }, - "5.10": { - "distribution": "ubuntu", - "version": "5.10", - "begin_support": "2005-10-12", - "end_support": "2007-04-13", - "begin_dev": "2005-04-08", - "end_extended_support": null - }, - "6.06": { - "distribution": "ubuntu", - "version": "6.06", - "begin_support": "2006-06-01", - "end_support": "2009-07-14", - "begin_dev": "2005-10-12", - "end_extended_support": null - }, - "6.10": { - "distribution": "ubuntu", - "version": "6.10", - "begin_support": "2006-10-26", - "end_support": "2008-04-25", - "begin_dev": "2006-06-01", - "end_extended_support": null - }, - "7.04": { - "distribution": "ubuntu", - "version": "7.04", - "begin_support": "2007-04-19", - "end_support": "2008-10-19", - "begin_dev": "2006-10-26", - "end_extended_support": null - }, - "7.10": { - "distribution": "ubuntu", - "version": "7.10", - "begin_support": "2007-10-18", - "end_support": "2009-04-18", - "begin_dev": "2007-04-19", - "end_extended_support": null - }, - "8.04": { - "distribution": "ubuntu", - "version": "8.04", - "begin_support": "2008-04-24", - "end_support": "2011-05-12", - "begin_dev": "2007-10-18", - "end_extended_support": null - }, - "8.10": { - "distribution": "ubuntu", - "version": "8.10", - "begin_support": "2008-10-30", - "end_support": "2010-04-30", - "begin_dev": "2008-04-24", - "end_extended_support": null - }, - "9.04": { - "distribution": "ubuntu", - "version": "9.04", - "begin_support": "2009-04-23", - "end_support": "2010-10-23", - "begin_dev": "2008-10-30", - "end_extended_support": null - }, - "9.10": { - "distribution": "ubuntu", - "version": "9.10", - "begin_support": "2009-10-29", - "end_support": "2011-04-30", - "begin_dev": "2009-04-23", - "end_extended_support": null - }, "10.04": { - "distribution": "ubuntu", - "version": "10.04", + "begin_dev": "2009-10-29", "begin_support": "2010-04-29", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2013-05-09", - "begin_dev": "2009-10-29", - "end_extended_support": null + "version": "10.04" }, "10.10": { - "distribution": "ubuntu", - "version": "10.10", + "begin_dev": "2010-04-29", "begin_support": "2010-10-10", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2012-04-10", - "begin_dev": "2010-04-29", - "end_extended_support": null + "version": "10.10" }, "11.04": { - "distribution": "ubuntu", - "version": "11.04", + "begin_dev": "2010-10-10", "begin_support": "2011-04-28", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2012-10-28", - "begin_dev": "2010-10-10", - "end_extended_support": null + "version": "11.04" }, "11.10": { - "distribution": "ubuntu", - "version": "11.10", + "begin_dev": "2011-04-28", "begin_support": "2011-10-13", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2013-05-09", - "begin_dev": "2011-04-28", - "end_extended_support": null + "version": "11.10" }, "12.04": { - "distribution": "ubuntu", - "version": "12.04", + "begin_dev": "2011-10-13", "begin_support": "2012-04-26", + "distribution": "ubuntu", + "end_extended_support": "2019-04-26", "end_support": "2017-04-28", - "begin_dev": "2011-10-13", - "end_extended_support": "2019-04-26" + "version": "12.04" }, "12.10": { - "distribution": "ubuntu", - "version": "12.10", + "begin_dev": "2012-04-26", "begin_support": "2012-10-18", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2014-05-16", - "begin_dev": "2012-04-26", - "end_extended_support": null + "version": "12.10" }, "13.04": { - "distribution": "ubuntu", - "version": "13.04", + "begin_dev": "2012-10-18", "begin_support": "2013-04-25", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2014-01-27", - "begin_dev": "2012-10-18", - "end_extended_support": null + "version": "13.04" }, "13.10": { - "distribution": "ubuntu", - "version": "13.10", + "begin_dev": "2013-04-25", "begin_support": "2013-10-17", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2014-07-17", - "begin_dev": "2013-04-25", - "end_extended_support": null + "version": "13.10" }, "14.04": { - "distribution": "ubuntu", - "version": "14.04", + "begin_dev": "2013-10-17", "begin_support": "2014-04-17", + "distribution": "ubuntu", + "end_extended_support": "2024-04-25", "end_support": "2019-04-25", - "begin_dev": "2013-10-17", - "end_extended_support": "2024-04-25" + "version": "14.04" }, "14.10": { - "distribution": "ubuntu", - "version": "14.10", + "begin_dev": "2014-04-17", "begin_support": "2014-10-23", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2015-07-23", - "begin_dev": "2014-04-17", - "end_extended_support": null + "version": "14.10" }, "15.04": { - "distribution": "ubuntu", - "version": "15.04", + "begin_dev": "2014-10-23", "begin_support": "2015-04-23", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2016-02-04", - "begin_dev": "2014-10-23", - "end_extended_support": null + "version": "15.04" }, "15.10": { - "distribution": "ubuntu", - "version": "15.10", + "begin_dev": "2015-04-23", "begin_support": "2015-10-22", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2016-07-28", - "begin_dev": "2015-04-23", - "end_extended_support": null + "version": "15.10" }, "16.04": { - "distribution": "ubuntu", - "version": "16.04", + "begin_dev": "2015-10-22", "begin_support": "2016-04-21", + "distribution": "ubuntu", + "end_extended_support": "2026-04-23", "end_support": "2021-04-30", - "begin_dev": "2015-10-22", - "end_extended_support": "2026-04-23" + "version": "16.04" }, "16.10": { - "distribution": "ubuntu", - "version": "16.10", + "begin_dev": "2016-04-21", "begin_support": "2016-10-13", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2017-07-20", - "begin_dev": "2016-04-21", - "end_extended_support": null + "version": "16.10" }, "17.04": { - "distribution": "ubuntu", - "version": "17.04", + "begin_dev": "2016-10-13", "begin_support": "2017-04-13", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2018-01-13", - "begin_dev": "2016-10-13", - "end_extended_support": null + "version": "17.04" }, "17.10": { - "distribution": "ubuntu", - "version": "17.10", + "begin_dev": "2017-04-13", "begin_support": "2017-10-19", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2018-07-19", - "begin_dev": "2017-04-13", - "end_extended_support": null + "version": "17.10" }, "18.04": { - "distribution": "ubuntu", - "version": "18.04", + "begin_dev": "2017-10-19", "begin_support": "2018-04-26", + "distribution": "ubuntu", + "end_extended_support": "2028-04-26", "end_support": "2023-05-31", - "begin_dev": "2017-10-19", - "end_extended_support": "2028-04-26" + "version": "18.04" }, "18.10": { - "distribution": "ubuntu", - "version": "18.10", + "begin_dev": "2018-04-26", "begin_support": "2018-10-18", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2019-07-18", - "begin_dev": "2018-04-26", - "end_extended_support": null + "version": "18.10" }, "19.04": { - "distribution": "ubuntu", - "version": "19.04", + "begin_dev": "2018-10-18", "begin_support": "2019-04-18", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2020-01-23", - "begin_dev": "2018-10-18", - "end_extended_support": null + "version": "19.04" }, "19.10": { - "distribution": "ubuntu", - "version": "19.10", + "begin_dev": "2019-04-18", "begin_support": "2019-10-17", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2020-07-17", - "begin_dev": "2019-04-18", - "end_extended_support": null + "version": "19.10" }, "20.04": { - "distribution": "ubuntu", - "version": "20.04", + "begin_dev": "2019-10-17", "begin_support": "2020-04-23", + "distribution": "ubuntu", + "end_extended_support": "2030-04-23", "end_support": "2025-05-29", - "begin_dev": "2019-10-17", - "end_extended_support": "2030-04-23" + "version": "20.04" }, "20.10": { - "distribution": "ubuntu", - "version": "20.10", + "begin_dev": "2020-04-23", "begin_support": "2020-10-22", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2021-07-22", - "begin_dev": "2020-04-23", - "end_extended_support": null + "version": "20.10" }, "21.04": { - "distribution": "ubuntu", - "version": "21.04", + "begin_dev": "2020-10-22", "begin_support": "2021-04-22", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2022-01-20", - "begin_dev": "2020-10-22", - "end_extended_support": null + "version": "21.04" }, "21.10": { - "distribution": "ubuntu", - "version": "21.10", + "begin_dev": "2021-04-22", "begin_support": "2021-10-14", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2022-07-14", - "begin_dev": "2021-04-22", - "end_extended_support": null + "version": "21.10" }, "22.04": { - "distribution": "ubuntu", - "version": "22.04", + "begin_dev": "2021-10-14", "begin_support": "2022-04-21", + "distribution": "ubuntu", + "end_extended_support": "2032-04-21", "end_support": "2027-06-01", - "begin_dev": "2021-10-14", - "end_extended_support": "2032-04-21" + "version": "22.04" }, "22.10": { - "distribution": "ubuntu", - "version": "22.10", + "begin_dev": "2022-04-21", "begin_support": "2022-10-20", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2023-07-20", - "begin_dev": "2022-04-21", - "end_extended_support": null + "version": "22.10" }, "23.04": { - "distribution": "ubuntu", - "version": "23.04", + "begin_dev": "2022-10-20", "begin_support": "2023-04-20", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2024-01-25", - "begin_dev": "2022-10-20", - "end_extended_support": null + "version": "23.04" }, "23.10": { - "distribution": "ubuntu", - "version": "23.10", + "begin_dev": "2023-04-20", "begin_support": "2023-10-12", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2024-07-11", - "begin_dev": "2023-04-20", - "end_extended_support": null + "version": "23.10" }, "24.04": { - "distribution": "ubuntu", - "version": "24.04", + "begin_dev": "2023-10-12", "begin_support": "2024-04-25", + "distribution": "ubuntu", + "end_extended_support": "2034-04-25", "end_support": "2029-05-31", - "begin_dev": "2023-10-12", - "end_extended_support": "2034-04-25" + "version": "24.04" }, "24.10": { - "distribution": "ubuntu", - "version": "24.10", + "begin_dev": "2024-04-25", "begin_support": "2024-10-10", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2025-07-10", - "begin_dev": "2024-04-25", - "end_extended_support": null + "version": "24.10" }, "25.04": { - "distribution": "ubuntu", - "version": "25.04", + "begin_dev": "2024-10-10", "begin_support": "2025-04-17", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2026-01-15", - "begin_dev": "2024-10-10", - "end_extended_support": null + "version": "25.04" }, "25.10": { - "distribution": "ubuntu", - "version": "25.10", + "begin_dev": "2025-04-17", "begin_support": "2025-10-09", + "distribution": "ubuntu", + "end_extended_support": null, "end_support": "2026-07-09", - "begin_dev": "2025-04-17", - "end_extended_support": null + "version": "25.10" }, "26.04": { - "distribution": "ubuntu", - "version": "26.04", + "begin_dev": "2025-10-09", "begin_support": "2026-04-23", + "distribution": "ubuntu", + "end_extended_support": "2036-04-23", "end_support": "2031-05-29", - "begin_dev": "2025-10-09", - "end_extended_support": "2036-04-23" + "version": "26.04" + }, + "4.10": { + "begin_dev": "2004-03-05", + "begin_support": "2004-10-20", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2006-04-30", + "version": "4.10" + }, + "5.04": { + "begin_dev": "2004-10-20", + "begin_support": "2005-04-08", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2006-10-31", + "version": "5.04" + }, + "5.10": { + "begin_dev": "2005-04-08", + "begin_support": "2005-10-12", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2007-04-13", + "version": "5.10" + }, + "6.06": { + "begin_dev": "2005-10-12", + "begin_support": "2006-06-01", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2009-07-14", + "version": "6.06" + }, + "6.10": { + "begin_dev": "2006-06-01", + "begin_support": "2006-10-26", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2008-04-25", + "version": "6.10" + }, + "7.04": { + "begin_dev": "2006-10-26", + "begin_support": "2007-04-19", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2008-10-19", + "version": "7.04" + }, + "7.10": { + "begin_dev": "2007-04-19", + "begin_support": "2007-10-18", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2009-04-18", + "version": "7.10" + }, + "8.04": { + "begin_dev": "2007-10-18", + "begin_support": "2008-04-24", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2011-05-12", + "version": "8.04" + }, + "8.10": { + "begin_dev": "2008-04-24", + "begin_support": "2008-10-30", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2010-04-30", + "version": "8.10" + }, + "9.04": { + "begin_dev": "2008-10-30", + "begin_support": "2009-04-23", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2010-10-23", + "version": "9.04" + }, + "9.10": { + "begin_dev": "2009-04-23", + "begin_support": "2009-10-29", + "distribution": "ubuntu", + "end_extended_support": null, + "end_support": "2011-04-30", + "version": "9.10" } } diff --git a/tools/update.py b/tools/update.py index 89be391..9a187d2 100644 --- a/tools/update.py +++ b/tools/update.py @@ -7,8 +7,10 @@ def update(module): - ubuntu_data = pathlib.Path(module.__file__).with_suffix(".json") - ubuntu_data.write_text(json.dumps(module.get_distro_info(), indent=" ") + "\n") + data_path = pathlib.Path(module.__file__).with_suffix(".json") + data_path.write_text( + json.dumps(module.get_distro_info(), indent=" ", sort_keys=True) + "\n" + ) if __name__ == "__main__": From a34e68000122cdd3d5ad243532071e3f93eb02ea Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Tue, 21 Apr 2026 21:55:27 -0400 Subject: [PATCH 4/7] fix: update test to expect RuntimeError instead of ConnectionError Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/test_rhel_downloader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_rhel_downloader.py b/tests/test_rhel_downloader.py index f61d603..fe46790 100644 --- a/tests/test_rhel_downloader.py +++ b/tests/test_rhel_downloader.py @@ -174,5 +174,5 @@ def test_http_error_raises(self): mock_response = _make_mock_response(_FAKE_API_RESPONSE) mock_response.status = 503 with patch("distro_support.rhel.request.urlopen", return_value=mock_response): - with pytest.raises(ConnectionError): + with pytest.raises(RuntimeError): get_distro_info() From 439d9e00b0a75ac31345bc68792e45c85c907dbd Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Tue, 21 Apr 2026 22:04:46 -0400 Subject: [PATCH 5/7] fix: suppress Bandit B310 false positive on urlopen The URL is a hardcoded constant, not user input, so the audit warning does not apply. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/distro_support/rhel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/distro_support/rhel.py b/src/distro_support/rhel.py index fb0c93b..d6977c9 100644 --- a/src/distro_support/rhel.py +++ b/src/distro_support/rhel.py @@ -19,7 +19,7 @@ def _parse_date(value: str | None) -> str | None: def get_distro_info() -> dict[str, dict[str, str | None]]: req = request.Request(SUPPORT_INFO_URL, headers={"User-Agent": "distro-support"}) - with request.urlopen(req) as response: + with request.urlopen(req) as response: # nosec B310 if response.status != 200: raise RuntimeError( f"Unexpected HTTP status from Red Hat API: {response.status}" From a2df9d0ddfec5f0e737daa6dd7a4ef5db2219804 Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Tue, 21 Apr 2026 22:09:37 -0400 Subject: [PATCH 6/7] fix: restore correct version ordering in JSON data files - Sort versions numerically (not lexicographically) so 4.10 < 10.04 - Empty-string version (Debian sid) sorts last, preserving its position - Drop sort_keys=True which was reordering inner keys alphabetically; insertion order from get_distro_info() already provides the right order Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/distro_support/debian.json | 224 ++++++++--------- src/distro_support/rhel.json | 40 +-- src/distro_support/ubuntu.json | 440 ++++++++++++++++----------------- tools/update.py | 15 +- 4 files changed, 365 insertions(+), 354 deletions(-) diff --git a/src/distro_support/debian.json b/src/distro_support/debian.json index 5d5102f..e279c49 100644 --- a/src/distro_support/debian.json +++ b/src/distro_support/debian.json @@ -1,170 +1,170 @@ { - "": { - "begin_dev": "1993-08-16", - "begin_support": null, - "distribution": "debian", - "end_extended_support": null, - "end_support": null, - "version": "" - }, "1.1": { - "begin_dev": "1993-08-16", - "begin_support": "1996-06-17", "distribution": "debian", - "end_extended_support": null, + "version": "1.1", + "begin_support": "1996-06-17", "end_support": "1997-06-05", - "version": "1.1" + "begin_dev": "1993-08-16", + "end_extended_support": null }, "1.2": { - "begin_dev": "1996-06-17", - "begin_support": "1996-12-12", "distribution": "debian", - "end_extended_support": null, + "version": "1.2", + "begin_support": "1996-12-12", "end_support": "1998-06-05", - "version": "1.2" + "begin_dev": "1996-06-17", + "end_extended_support": null }, "1.3": { - "begin_dev": "1996-12-12", - "begin_support": "1997-06-05", "distribution": "debian", - "end_extended_support": null, + "version": "1.3", + "begin_support": "1997-06-05", "end_support": "1999-03-09", - "version": "1.3" - }, - "10": { - "begin_dev": "2017-06-17", - "begin_support": "2019-07-06", - "distribution": "debian", - "end_extended_support": "2029-06-30", - "end_support": "2022-09-10", - "version": "10" - }, - "11": { - "begin_dev": "2019-07-06", - "begin_support": "2021-08-14", - "distribution": "debian", - "end_extended_support": "2031-06-30", - "end_support": "2024-08-14", - "version": "11" - }, - "12": { - "begin_dev": "2021-08-14", - "begin_support": "2023-06-10", - "distribution": "debian", - "end_extended_support": "2033-06-30", - "end_support": "2026-07-11", - "version": "12" - }, - "13": { - "begin_dev": "2023-06-10", - "begin_support": "2025-08-09", - "distribution": "debian", - "end_extended_support": "2035-06-30", - "end_support": "2028-08-09", - "version": "13" - }, - "14": { - "begin_dev": "2025-08-09", - "begin_support": null, - "distribution": "debian", - "end_extended_support": null, - "end_support": null, - "version": "14" - }, - "15": { - "begin_dev": "2027-08-01", - "begin_support": null, - "distribution": "debian", - "end_extended_support": null, - "end_support": null, - "version": "15" + "begin_dev": "1996-12-12", + "end_extended_support": null }, "2.0": { - "begin_dev": "1997-06-05", - "begin_support": "1998-07-24", "distribution": "debian", - "end_extended_support": null, + "version": "2.0", + "begin_support": "1998-07-24", "end_support": "2000-03-09", - "version": "2.0" + "begin_dev": "1997-06-05", + "end_extended_support": null }, "2.1": { - "begin_dev": "1998-07-24", - "begin_support": "1999-03-09", "distribution": "debian", - "end_extended_support": null, + "version": "2.1", + "begin_support": "1999-03-09", "end_support": "2000-10-30", - "version": "2.1" + "begin_dev": "1998-07-24", + "end_extended_support": null }, "2.2": { - "begin_dev": "1999-03-09", - "begin_support": "2000-08-15", "distribution": "debian", - "end_extended_support": null, + "version": "2.2", + "begin_support": "2000-08-15", "end_support": "2003-06-30", - "version": "2.2" + "begin_dev": "1999-03-09", + "end_extended_support": null }, "3.0": { - "begin_dev": "2000-08-15", - "begin_support": "2002-07-19", "distribution": "debian", - "end_extended_support": null, + "version": "3.0", + "begin_support": "2002-07-19", "end_support": "2006-06-30", - "version": "3.0" + "begin_dev": "2000-08-15", + "end_extended_support": null }, "3.1": { - "begin_dev": "2002-07-19", - "begin_support": "2005-06-06", "distribution": "debian", - "end_extended_support": null, + "version": "3.1", + "begin_support": "2005-06-06", "end_support": "2008-03-31", - "version": "3.1" + "begin_dev": "2002-07-19", + "end_extended_support": null }, "4.0": { - "begin_dev": "2005-06-06", - "begin_support": "2007-04-08", "distribution": "debian", - "end_extended_support": null, + "version": "4.0", + "begin_support": "2007-04-08", "end_support": "2010-02-15", - "version": "4.0" + "begin_dev": "2005-06-06", + "end_extended_support": null }, "5.0": { - "begin_dev": "2007-04-08", - "begin_support": "2009-02-14", "distribution": "debian", - "end_extended_support": null, + "version": "5.0", + "begin_support": "2009-02-14", "end_support": "2012-02-06", - "version": "5.0" + "begin_dev": "2007-04-08", + "end_extended_support": null }, "6.0": { - "begin_dev": "2009-02-14", - "begin_support": "2011-02-06", "distribution": "debian", - "end_extended_support": null, + "version": "6.0", + "begin_support": "2011-02-06", "end_support": "2014-05-31", - "version": "6.0" + "begin_dev": "2009-02-14", + "end_extended_support": null }, "7": { - "begin_dev": "2011-02-06", - "begin_support": "2013-05-04", "distribution": "debian", - "end_extended_support": "2020-06-30", + "version": "7", + "begin_support": "2013-05-04", "end_support": "2016-04-25", - "version": "7" + "begin_dev": "2011-02-06", + "end_extended_support": "2020-06-30" }, "8": { - "begin_dev": "2013-05-04", - "begin_support": "2015-04-26", "distribution": "debian", - "end_extended_support": "2025-06-30", + "version": "8", + "begin_support": "2015-04-26", "end_support": "2018-06-17", - "version": "8" + "begin_dev": "2013-05-04", + "end_extended_support": "2025-06-30" }, "9": { - "begin_dev": "2015-04-26", - "begin_support": "2017-06-17", "distribution": "debian", - "end_extended_support": "2027-06-30", + "version": "9", + "begin_support": "2017-06-17", "end_support": "2020-07-18", - "version": "9" + "begin_dev": "2015-04-26", + "end_extended_support": "2027-06-30" + }, + "10": { + "distribution": "debian", + "version": "10", + "begin_support": "2019-07-06", + "end_support": "2022-09-10", + "begin_dev": "2017-06-17", + "end_extended_support": "2029-06-30" + }, + "11": { + "distribution": "debian", + "version": "11", + "begin_support": "2021-08-14", + "end_support": "2024-08-14", + "begin_dev": "2019-07-06", + "end_extended_support": "2031-06-30" + }, + "12": { + "distribution": "debian", + "version": "12", + "begin_support": "2023-06-10", + "end_support": "2026-07-11", + "begin_dev": "2021-08-14", + "end_extended_support": "2033-06-30" + }, + "13": { + "distribution": "debian", + "version": "13", + "begin_support": "2025-08-09", + "end_support": "2028-08-09", + "begin_dev": "2023-06-10", + "end_extended_support": "2035-06-30" + }, + "14": { + "distribution": "debian", + "version": "14", + "begin_support": null, + "end_support": null, + "begin_dev": "2025-08-09", + "end_extended_support": null + }, + "15": { + "distribution": "debian", + "version": "15", + "begin_support": null, + "end_support": null, + "begin_dev": "2027-08-01", + "end_extended_support": null + }, + "": { + "distribution": "debian", + "version": "", + "begin_support": null, + "end_support": null, + "begin_dev": "1993-08-16", + "end_extended_support": null } } diff --git a/src/distro_support/rhel.json b/src/distro_support/rhel.json index fa06830..86afdf5 100644 --- a/src/distro_support/rhel.json +++ b/src/distro_support/rhel.json @@ -1,12 +1,4 @@ { - "7": { - "distribution": "rhel", - "version": "7", - "begin_support": "2014-06-10", - "end_support": "2024-06-30", - "begin_dev": "2014-06-10", - "end_extended_support": "2029-05-31" - }, "6": { "distribution": "rhel", "version": "6", @@ -15,13 +7,21 @@ "begin_dev": "2010-11-10", "end_extended_support": "2024-06-30" }, - "10": { + "7": { "distribution": "rhel", - "version": "10", - "begin_support": "2025-05-20", - "end_support": "2035-05-31", - "begin_dev": "2025-05-20", - "end_extended_support": "2038-05-31" + "version": "7", + "begin_support": "2014-06-10", + "end_support": "2024-06-30", + "begin_dev": "2014-06-10", + "end_extended_support": "2029-05-31" + }, + "8": { + "distribution": "rhel", + "version": "8", + "begin_support": "2019-05-07", + "end_support": "2029-05-31", + "begin_dev": "2019-05-07", + "end_extended_support": "2032-05-31" }, "9": { "distribution": "rhel", @@ -31,12 +31,12 @@ "begin_dev": "2022-05-18", "end_extended_support": "2035-05-31" }, - "8": { + "10": { "distribution": "rhel", - "version": "8", - "begin_support": "2019-05-07", - "end_support": "2029-05-31", - "begin_dev": "2019-05-07", - "end_extended_support": "2032-05-31" + "version": "10", + "begin_support": "2025-05-20", + "end_support": "2035-05-31", + "begin_dev": "2025-05-20", + "end_extended_support": "2038-05-31" } } diff --git a/src/distro_support/ubuntu.json b/src/distro_support/ubuntu.json index 59b191c..f3bd81a 100644 --- a/src/distro_support/ubuntu.json +++ b/src/distro_support/ubuntu.json @@ -1,354 +1,354 @@ { + "4.10": { + "distribution": "ubuntu", + "version": "4.10", + "begin_support": "2004-10-20", + "end_support": "2006-04-30", + "begin_dev": "2004-03-05", + "end_extended_support": null + }, + "5.04": { + "distribution": "ubuntu", + "version": "5.04", + "begin_support": "2005-04-08", + "end_support": "2006-10-31", + "begin_dev": "2004-10-20", + "end_extended_support": null + }, + "5.10": { + "distribution": "ubuntu", + "version": "5.10", + "begin_support": "2005-10-12", + "end_support": "2007-04-13", + "begin_dev": "2005-04-08", + "end_extended_support": null + }, + "6.06": { + "distribution": "ubuntu", + "version": "6.06", + "begin_support": "2006-06-01", + "end_support": "2009-07-14", + "begin_dev": "2005-10-12", + "end_extended_support": null + }, + "6.10": { + "distribution": "ubuntu", + "version": "6.10", + "begin_support": "2006-10-26", + "end_support": "2008-04-25", + "begin_dev": "2006-06-01", + "end_extended_support": null + }, + "7.04": { + "distribution": "ubuntu", + "version": "7.04", + "begin_support": "2007-04-19", + "end_support": "2008-10-19", + "begin_dev": "2006-10-26", + "end_extended_support": null + }, + "7.10": { + "distribution": "ubuntu", + "version": "7.10", + "begin_support": "2007-10-18", + "end_support": "2009-04-18", + "begin_dev": "2007-04-19", + "end_extended_support": null + }, + "8.04": { + "distribution": "ubuntu", + "version": "8.04", + "begin_support": "2008-04-24", + "end_support": "2011-05-12", + "begin_dev": "2007-10-18", + "end_extended_support": null + }, + "8.10": { + "distribution": "ubuntu", + "version": "8.10", + "begin_support": "2008-10-30", + "end_support": "2010-04-30", + "begin_dev": "2008-04-24", + "end_extended_support": null + }, + "9.04": { + "distribution": "ubuntu", + "version": "9.04", + "begin_support": "2009-04-23", + "end_support": "2010-10-23", + "begin_dev": "2008-10-30", + "end_extended_support": null + }, + "9.10": { + "distribution": "ubuntu", + "version": "9.10", + "begin_support": "2009-10-29", + "end_support": "2011-04-30", + "begin_dev": "2009-04-23", + "end_extended_support": null + }, "10.04": { - "begin_dev": "2009-10-29", - "begin_support": "2010-04-29", "distribution": "ubuntu", - "end_extended_support": null, + "version": "10.04", + "begin_support": "2010-04-29", "end_support": "2013-05-09", - "version": "10.04" + "begin_dev": "2009-10-29", + "end_extended_support": null }, "10.10": { - "begin_dev": "2010-04-29", - "begin_support": "2010-10-10", "distribution": "ubuntu", - "end_extended_support": null, + "version": "10.10", + "begin_support": "2010-10-10", "end_support": "2012-04-10", - "version": "10.10" + "begin_dev": "2010-04-29", + "end_extended_support": null }, "11.04": { - "begin_dev": "2010-10-10", - "begin_support": "2011-04-28", "distribution": "ubuntu", - "end_extended_support": null, + "version": "11.04", + "begin_support": "2011-04-28", "end_support": "2012-10-28", - "version": "11.04" + "begin_dev": "2010-10-10", + "end_extended_support": null }, "11.10": { - "begin_dev": "2011-04-28", - "begin_support": "2011-10-13", "distribution": "ubuntu", - "end_extended_support": null, + "version": "11.10", + "begin_support": "2011-10-13", "end_support": "2013-05-09", - "version": "11.10" + "begin_dev": "2011-04-28", + "end_extended_support": null }, "12.04": { - "begin_dev": "2011-10-13", - "begin_support": "2012-04-26", "distribution": "ubuntu", - "end_extended_support": "2019-04-26", + "version": "12.04", + "begin_support": "2012-04-26", "end_support": "2017-04-28", - "version": "12.04" + "begin_dev": "2011-10-13", + "end_extended_support": "2019-04-26" }, "12.10": { - "begin_dev": "2012-04-26", - "begin_support": "2012-10-18", "distribution": "ubuntu", - "end_extended_support": null, + "version": "12.10", + "begin_support": "2012-10-18", "end_support": "2014-05-16", - "version": "12.10" + "begin_dev": "2012-04-26", + "end_extended_support": null }, "13.04": { - "begin_dev": "2012-10-18", - "begin_support": "2013-04-25", "distribution": "ubuntu", - "end_extended_support": null, + "version": "13.04", + "begin_support": "2013-04-25", "end_support": "2014-01-27", - "version": "13.04" + "begin_dev": "2012-10-18", + "end_extended_support": null }, "13.10": { - "begin_dev": "2013-04-25", - "begin_support": "2013-10-17", "distribution": "ubuntu", - "end_extended_support": null, + "version": "13.10", + "begin_support": "2013-10-17", "end_support": "2014-07-17", - "version": "13.10" + "begin_dev": "2013-04-25", + "end_extended_support": null }, "14.04": { - "begin_dev": "2013-10-17", - "begin_support": "2014-04-17", "distribution": "ubuntu", - "end_extended_support": "2024-04-25", + "version": "14.04", + "begin_support": "2014-04-17", "end_support": "2019-04-25", - "version": "14.04" + "begin_dev": "2013-10-17", + "end_extended_support": "2024-04-25" }, "14.10": { - "begin_dev": "2014-04-17", - "begin_support": "2014-10-23", "distribution": "ubuntu", - "end_extended_support": null, + "version": "14.10", + "begin_support": "2014-10-23", "end_support": "2015-07-23", - "version": "14.10" + "begin_dev": "2014-04-17", + "end_extended_support": null }, "15.04": { - "begin_dev": "2014-10-23", - "begin_support": "2015-04-23", "distribution": "ubuntu", - "end_extended_support": null, + "version": "15.04", + "begin_support": "2015-04-23", "end_support": "2016-02-04", - "version": "15.04" + "begin_dev": "2014-10-23", + "end_extended_support": null }, "15.10": { - "begin_dev": "2015-04-23", - "begin_support": "2015-10-22", "distribution": "ubuntu", - "end_extended_support": null, + "version": "15.10", + "begin_support": "2015-10-22", "end_support": "2016-07-28", - "version": "15.10" + "begin_dev": "2015-04-23", + "end_extended_support": null }, "16.04": { - "begin_dev": "2015-10-22", - "begin_support": "2016-04-21", "distribution": "ubuntu", - "end_extended_support": "2026-04-23", + "version": "16.04", + "begin_support": "2016-04-21", "end_support": "2021-04-30", - "version": "16.04" + "begin_dev": "2015-10-22", + "end_extended_support": "2026-04-23" }, "16.10": { - "begin_dev": "2016-04-21", - "begin_support": "2016-10-13", "distribution": "ubuntu", - "end_extended_support": null, + "version": "16.10", + "begin_support": "2016-10-13", "end_support": "2017-07-20", - "version": "16.10" + "begin_dev": "2016-04-21", + "end_extended_support": null }, "17.04": { - "begin_dev": "2016-10-13", - "begin_support": "2017-04-13", "distribution": "ubuntu", - "end_extended_support": null, + "version": "17.04", + "begin_support": "2017-04-13", "end_support": "2018-01-13", - "version": "17.04" + "begin_dev": "2016-10-13", + "end_extended_support": null }, "17.10": { - "begin_dev": "2017-04-13", - "begin_support": "2017-10-19", "distribution": "ubuntu", - "end_extended_support": null, + "version": "17.10", + "begin_support": "2017-10-19", "end_support": "2018-07-19", - "version": "17.10" + "begin_dev": "2017-04-13", + "end_extended_support": null }, "18.04": { - "begin_dev": "2017-10-19", - "begin_support": "2018-04-26", "distribution": "ubuntu", - "end_extended_support": "2028-04-26", + "version": "18.04", + "begin_support": "2018-04-26", "end_support": "2023-05-31", - "version": "18.04" + "begin_dev": "2017-10-19", + "end_extended_support": "2028-04-26" }, "18.10": { - "begin_dev": "2018-04-26", - "begin_support": "2018-10-18", "distribution": "ubuntu", - "end_extended_support": null, + "version": "18.10", + "begin_support": "2018-10-18", "end_support": "2019-07-18", - "version": "18.10" + "begin_dev": "2018-04-26", + "end_extended_support": null }, "19.04": { - "begin_dev": "2018-10-18", - "begin_support": "2019-04-18", "distribution": "ubuntu", - "end_extended_support": null, + "version": "19.04", + "begin_support": "2019-04-18", "end_support": "2020-01-23", - "version": "19.04" + "begin_dev": "2018-10-18", + "end_extended_support": null }, "19.10": { - "begin_dev": "2019-04-18", - "begin_support": "2019-10-17", "distribution": "ubuntu", - "end_extended_support": null, + "version": "19.10", + "begin_support": "2019-10-17", "end_support": "2020-07-17", - "version": "19.10" + "begin_dev": "2019-04-18", + "end_extended_support": null }, "20.04": { - "begin_dev": "2019-10-17", - "begin_support": "2020-04-23", "distribution": "ubuntu", - "end_extended_support": "2030-04-23", + "version": "20.04", + "begin_support": "2020-04-23", "end_support": "2025-05-29", - "version": "20.04" + "begin_dev": "2019-10-17", + "end_extended_support": "2030-04-23" }, "20.10": { - "begin_dev": "2020-04-23", - "begin_support": "2020-10-22", "distribution": "ubuntu", - "end_extended_support": null, + "version": "20.10", + "begin_support": "2020-10-22", "end_support": "2021-07-22", - "version": "20.10" + "begin_dev": "2020-04-23", + "end_extended_support": null }, "21.04": { - "begin_dev": "2020-10-22", - "begin_support": "2021-04-22", "distribution": "ubuntu", - "end_extended_support": null, + "version": "21.04", + "begin_support": "2021-04-22", "end_support": "2022-01-20", - "version": "21.04" + "begin_dev": "2020-10-22", + "end_extended_support": null }, "21.10": { - "begin_dev": "2021-04-22", - "begin_support": "2021-10-14", "distribution": "ubuntu", - "end_extended_support": null, + "version": "21.10", + "begin_support": "2021-10-14", "end_support": "2022-07-14", - "version": "21.10" + "begin_dev": "2021-04-22", + "end_extended_support": null }, "22.04": { - "begin_dev": "2021-10-14", - "begin_support": "2022-04-21", "distribution": "ubuntu", - "end_extended_support": "2032-04-21", + "version": "22.04", + "begin_support": "2022-04-21", "end_support": "2027-06-01", - "version": "22.04" + "begin_dev": "2021-10-14", + "end_extended_support": "2032-04-21" }, "22.10": { - "begin_dev": "2022-04-21", - "begin_support": "2022-10-20", "distribution": "ubuntu", - "end_extended_support": null, + "version": "22.10", + "begin_support": "2022-10-20", "end_support": "2023-07-20", - "version": "22.10" + "begin_dev": "2022-04-21", + "end_extended_support": null }, "23.04": { - "begin_dev": "2022-10-20", - "begin_support": "2023-04-20", "distribution": "ubuntu", - "end_extended_support": null, + "version": "23.04", + "begin_support": "2023-04-20", "end_support": "2024-01-25", - "version": "23.04" + "begin_dev": "2022-10-20", + "end_extended_support": null }, "23.10": { - "begin_dev": "2023-04-20", - "begin_support": "2023-10-12", "distribution": "ubuntu", - "end_extended_support": null, + "version": "23.10", + "begin_support": "2023-10-12", "end_support": "2024-07-11", - "version": "23.10" + "begin_dev": "2023-04-20", + "end_extended_support": null }, "24.04": { - "begin_dev": "2023-10-12", - "begin_support": "2024-04-25", "distribution": "ubuntu", - "end_extended_support": "2034-04-25", + "version": "24.04", + "begin_support": "2024-04-25", "end_support": "2029-05-31", - "version": "24.04" + "begin_dev": "2023-10-12", + "end_extended_support": "2034-04-25" }, "24.10": { - "begin_dev": "2024-04-25", - "begin_support": "2024-10-10", "distribution": "ubuntu", - "end_extended_support": null, + "version": "24.10", + "begin_support": "2024-10-10", "end_support": "2025-07-10", - "version": "24.10" + "begin_dev": "2024-04-25", + "end_extended_support": null }, "25.04": { - "begin_dev": "2024-10-10", - "begin_support": "2025-04-17", "distribution": "ubuntu", - "end_extended_support": null, + "version": "25.04", + "begin_support": "2025-04-17", "end_support": "2026-01-15", - "version": "25.04" + "begin_dev": "2024-10-10", + "end_extended_support": null }, "25.10": { - "begin_dev": "2025-04-17", - "begin_support": "2025-10-09", "distribution": "ubuntu", - "end_extended_support": null, + "version": "25.10", + "begin_support": "2025-10-09", "end_support": "2026-07-09", - "version": "25.10" + "begin_dev": "2025-04-17", + "end_extended_support": null }, "26.04": { - "begin_dev": "2025-10-09", - "begin_support": "2026-04-23", "distribution": "ubuntu", - "end_extended_support": "2036-04-23", + "version": "26.04", + "begin_support": "2026-04-23", "end_support": "2031-05-29", - "version": "26.04" - }, - "4.10": { - "begin_dev": "2004-03-05", - "begin_support": "2004-10-20", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2006-04-30", - "version": "4.10" - }, - "5.04": { - "begin_dev": "2004-10-20", - "begin_support": "2005-04-08", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2006-10-31", - "version": "5.04" - }, - "5.10": { - "begin_dev": "2005-04-08", - "begin_support": "2005-10-12", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2007-04-13", - "version": "5.10" - }, - "6.06": { - "begin_dev": "2005-10-12", - "begin_support": "2006-06-01", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2009-07-14", - "version": "6.06" - }, - "6.10": { - "begin_dev": "2006-06-01", - "begin_support": "2006-10-26", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2008-04-25", - "version": "6.10" - }, - "7.04": { - "begin_dev": "2006-10-26", - "begin_support": "2007-04-19", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2008-10-19", - "version": "7.04" - }, - "7.10": { - "begin_dev": "2007-04-19", - "begin_support": "2007-10-18", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2009-04-18", - "version": "7.10" - }, - "8.04": { - "begin_dev": "2007-10-18", - "begin_support": "2008-04-24", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2011-05-12", - "version": "8.04" - }, - "8.10": { - "begin_dev": "2008-04-24", - "begin_support": "2008-10-30", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2010-04-30", - "version": "8.10" - }, - "9.04": { - "begin_dev": "2008-10-30", - "begin_support": "2009-04-23", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2010-10-23", - "version": "9.04" - }, - "9.10": { - "begin_dev": "2009-04-23", - "begin_support": "2009-10-29", - "distribution": "ubuntu", - "end_extended_support": null, - "end_support": "2011-04-30", - "version": "9.10" + "begin_dev": "2025-10-09", + "end_extended_support": "2036-04-23" } } diff --git a/tools/update.py b/tools/update.py index 9a187d2..caa01e6 100644 --- a/tools/update.py +++ b/tools/update.py @@ -6,11 +6,22 @@ from distro_support import alpine, debian, devuan, rhel, ubuntu +def _version_sort_key(version: str) -> tuple[int, ...]: + if not version: + return (float("inf"),) # type: ignore[return-value] + try: + return tuple(int(x) for x in version.split(".")) + except ValueError: + return (0,) + + def update(module): data_path = pathlib.Path(module.__file__).with_suffix(".json") - data_path.write_text( - json.dumps(module.get_distro_info(), indent=" ", sort_keys=True) + "\n" + data = module.get_distro_info() + sorted_data = dict( + sorted(data.items(), key=lambda item: _version_sort_key(item[0])) ) + data_path.write_text(json.dumps(sorted_data, indent=" ") + "\n") if __name__ == "__main__": From 0a68ef6185f2fd00d5e8512c58a2c0df34c250f9 Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Tue, 21 Apr 2026 22:16:31 -0400 Subject: [PATCH 7/7] Fix type error in _version_sort_key: use sys.maxsize instead of float("inf") float("inf") returns tuple[float] which doesn't match the tuple[int, ...] return type annotation. sys.maxsize achieves the same "sort last" effect while keeping the type consistent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/test_get_support_range.py | 1 - tools/update.py | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_get_support_range.py b/tests/test_get_support_range.py index c2e8d18..0aa18fb 100644 --- a/tests/test_get_support_range.py +++ b/tests/test_get_support_range.py @@ -16,7 +16,6 @@ ("ubuntu", "25.10", date(2025, 8, 12), False, True, None), ("debian", "1.1", date(2000, 1, 1), False, False, None), ("debian", "", date(3000, 1, 1), False, True, None), -<<<<<<< HEAD ("devuan", "4", date(2022, 1, 1), True, False, None), ("devuan", "4", date(2030, 1, 1), False, False, None), ("devuan", "7", date(2026, 1, 1), False, True, None), diff --git a/tools/update.py b/tools/update.py index caa01e6..1c3064e 100644 --- a/tools/update.py +++ b/tools/update.py @@ -2,13 +2,14 @@ import json import pathlib +import sys from distro_support import alpine, debian, devuan, rhel, ubuntu def _version_sort_key(version: str) -> tuple[int, ...]: if not version: - return (float("inf"),) # type: ignore[return-value] + return (sys.maxsize,) try: return tuple(int(x) for x in version.split(".")) except ValueError: