From bd3257cca6e84b5648fd376835ec259a36f1108a Mon Sep 17 00:00:00 2001 From: Patrick Ribbsaeter Date: Tue, 21 Jul 2026 23:16:25 +0200 Subject: [PATCH 1/4] Add CLDR source version to Windows mapping Fetch windowsZones.xml from the exact latest commit and record that SHA in the generated module. AI-assisted-by: OpenAI Codex (GPT-5.6 Sol) --- generate_windows_to_olson_mapping.py | 29 ++++++--- news/1575.feature | 1 + .../test_generate_windows_to_olson_mapping.py | 61 +++++++++++++++++++ .../tests/test_windows_to_olson_version.py | 11 ++++ src/icalendar/timezone/windows_to_olson.py | 7 ++- 5 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 news/1575.feature create mode 100644 src/icalendar/tests/test_generate_windows_to_olson_mapping.py create mode 100644 src/icalendar/tests/test_windows_to_olson_version.py diff --git a/generate_windows_to_olson_mapping.py b/generate_windows_to_olson_mapping.py index d0081da..7033d3b 100644 --- a/generate_windows_to_olson_mapping.py +++ b/generate_windows_to_olson_mapping.py @@ -13,11 +13,17 @@ import urllib.request as req import xml.etree.ElementTree as ET from pathlib import Path -# Get the XML data from the CLDR on GitHub and save to a file. -# Unfortunately, the CLDR does not have a latest or stable tag -# that points to the stable version. -# Use the `main` branch, which is the development branch. -url = "https://raw.githubusercontent.com/unicode-org/cldr/refs/heads/main/common/supplemental/windowsZones.xml" +CLDR_PATH = "common/supplemental/windowsZones.xml" +commits_url = ( + f"https://api.github.com/repos/unicode-org/cldr/commits?path={CLDR_PATH}&per_page=1" +) +with req.urlopen(commits_url) as response: # noqa: S310 + version = json.load(response)[0]["sha"] + +# Fetch the XML from the commit recorded in the generated module. Using the +# commit instead of `main` ensures that the data and version cannot diverge if +# CLDR changes between the two requests. +url = f"https://raw.githubusercontent.com/unicode-org/cldr/{version}/{CLDR_PATH}" with req.urlopen(url) as response: # noqa: S310 xml_content = response.read() @@ -35,24 +41,27 @@ file = "windows_to_olson.py" filepath = Path(DEST, file) print(f"Writing {filepath}") # noqa: T201 with Path.open(filepath, "w") as f: - f.write("""\"\"\" + f.write(f'''""" This module contains mappings from Windows timezone identifiers to Olson timezone identifiers. This file is automatically generated by generate_windows_to_olson_mapping.py. Do not edit manually. -The data is taken from the Unicode Consortium [0]. +The data is taken from the Unicode Consortium [0] at commit +``{version}``. The proposal and rationale for this mapping is also available at the Unicode Consortium [1]. -[0] https://raw.githubusercontent.com/unicode-org/cldr/refs/heads/main/common/supplemental/windowsZones.xml +[0] https://github.com/unicode-org/cldr/blob/{version}/{CLDR_PATH} [1] https://cldr.unicode.org/development/development-process/design-proposals/extended-windows-olson-zid-mapping -\"\"\" +""" + +version = "{version}" -""") +''') f.write("WINDOWS_TO_OLSON = ") f.write(json.dumps(dict(result), indent=4, sort_keys=True)) f.write("\n") diff --git a/news/1575.feature b/news/1575.feature new file mode 100644 index 0000000..727256a --- /dev/null +++ b/news/1575.feature @@ -0,0 +1 @@ +Record the exact CLDR commit used to generate the Windows-to-Olson timezone mapping and fetch the mapping from that pinned revision. I used AI to assist me with this change. diff --git a/src/icalendar/tests/test_generate_windows_to_olson_mapping.py b/src/icalendar/tests/test_generate_windows_to_olson_mapping.py new file mode 100644 index 0000000..aa36708 --- /dev/null +++ b/src/icalendar/tests/test_generate_windows_to_olson_mapping.py @@ -0,0 +1,61 @@ +import io +import json +import runpy +from pathlib import Path +from urllib import request + +CLDR_SHA = "0123456789abcdef0123456789abcdef01234567" +COMMITS_URL = ( + "https://api.github.com/repos/unicode-org/cldr/commits" + "?path=common/supplemental/windowsZones.xml&per_page=1" +) +RAW_URL = ( + "https://raw.githubusercontent.com/unicode-org/cldr/" + f"{CLDR_SHA}/common/supplemental/windowsZones.xml" +) + + +class Response(io.BytesIO): + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + +class Output(io.StringIO): + def close(self): + """Keep generated content available after the writer context exits.""" + + +def test_generator_pins_mapping_to_latest_cldr_commit(monkeypatch): + """The generated mapping and its version use the same CLDR commit.""" + requested_urls = [] + + def urlopen(url): + requested_urls.append(url) + if url == COMMITS_URL: + return Response(json.dumps([{"sha": CLDR_SHA}]).encode()) + if url == RAW_URL: + return Response( + b"" + b'' + b"" + ) + raise AssertionError(f"Unexpected URL: {url}") + + output = Output() + + def open_output(_path, _mode): + return output + + monkeypatch.setattr(request, "urlopen", urlopen) + monkeypatch.setattr(Path, "open", open_output) + + runpy.run_path("generate_windows_to_olson_mapping.py", run_name="__main__") + + generated = output.getvalue() + assert requested_urls == [COMMITS_URL, RAW_URL] + assert f'version = "{CLDR_SHA}"' in generated + assert '"Test Standard Time": "Etc/Test"' in generated diff --git a/src/icalendar/tests/test_windows_to_olson_version.py b/src/icalendar/tests/test_windows_to_olson_version.py new file mode 100644 index 0000000..6a96dfa --- /dev/null +++ b/src/icalendar/tests/test_windows_to_olson_version.py @@ -0,0 +1,11 @@ +import re + +from icalendar.timezone import windows_to_olson + + +def test_windows_to_olson_records_cldr_source_version(): + """The generated mapping identifies the exact CLDR source commit.""" + assert re.fullmatch(r"[0-9a-f]{40}", windows_to_olson.version) + documentation = windows_to_olson.__doc__ + assert documentation is not None + assert f"cldr/blob/{windows_to_olson.version}/" in documentation diff --git a/src/icalendar/timezone/windows_to_olson.py b/src/icalendar/timezone/windows_to_olson.py index 450ad50..5eb735e 100644 --- a/src/icalendar/timezone/windows_to_olson.py +++ b/src/icalendar/timezone/windows_to_olson.py @@ -5,16 +5,19 @@ Olson timezone identifiers. This file is automatically generated by generate_windows_to_olson_mapping.py. Do not edit manually. -The data is taken from the Unicode Consortium [0]. +The data is taken from the Unicode Consortium [0] at commit +``c33a1f0a23e3b676b406345fe0b42c130defc51d``. The proposal and rationale for this mapping is also available at the Unicode Consortium [1]. -[0] https://raw.githubusercontent.com/unicode-org/cldr/refs/heads/main/common/supplemental/windowsZones.xml +[0] https://github.com/unicode-org/cldr/blob/c33a1f0a23e3b676b406345fe0b42c130defc51d/common/supplemental/windowsZones.xml [1] https://cldr.unicode.org/development/development-process/design-proposals/extended-windows-olson-zid-mapping """ +version = "c33a1f0a23e3b676b406345fe0b42c130defc51d" + WINDOWS_TO_OLSON = { "AUS Central Standard Time": "Australia/Darwin", "AUS Eastern Standard Time": "Australia/Sydney", -- 2.55.0.windows.3 From 4dc5d06cf93de880f8d47b0047ac92ed97235524 Mon Sep 17 00:00:00 2001 From: Patrick Ribbsaeter Date: Tue, 21 Jul 2026 23:27:02 +0200 Subject: [PATCH 2/4] Make generator test independent of working directory Resolve the generator from the test file location so the regression test works when pytest is launched outside the repository root. AI-assisted-by: OpenAI Codex (GPT-5.6 Sol) --- src/icalendar/tests/test_generate_windows_to_olson_mapping.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/icalendar/tests/test_generate_windows_to_olson_mapping.py b/src/icalendar/tests/test_generate_windows_to_olson_mapping.py index aa36708..570cd26 100644 --- a/src/icalendar/tests/test_generate_windows_to_olson_mapping.py +++ b/src/icalendar/tests/test_generate_windows_to_olson_mapping.py @@ -53,7 +53,8 @@ def test_generator_pins_mapping_to_latest_cldr_commit(monkeypatch): monkeypatch.setattr(request, "urlopen", urlopen) monkeypatch.setattr(Path, "open", open_output) - runpy.run_path("generate_windows_to_olson_mapping.py", run_name="__main__") + generator = Path(__file__).parents[3] / "generate_windows_to_olson_mapping.py" + runpy.run_path(str(generator), run_name="__main__") generated = output.getvalue() assert requested_urls == [COMMITS_URL, RAW_URL] -- 2.55.0.windows.3 From f9b4ef0a68dfa8c8a33f55ee61ec39190589aab3 Mon Sep 17 00:00:00 2001 From: Patrick Ribbsaeter Date: Wed, 22 Jul 2026 00:22:19 +0200 Subject: [PATCH 3/4] Make CLDR main branch target explicit AI-assisted-by: OpenAI Codex (GPT-5.6 Sol) --- generate_windows_to_olson_mapping.py | 2 +- src/icalendar/tests/test_generate_windows_to_olson_mapping.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/generate_windows_to_olson_mapping.py b/generate_windows_to_olson_mapping.py index 7033d3b..0df31a1 100644 --- a/generate_windows_to_olson_mapping.py +++ b/generate_windows_to_olson_mapping.py @@ -15,7 +15,7 @@ from pathlib import Path CLDR_PATH = "common/supplemental/windowsZones.xml" commits_url = ( - f"https://api.github.com/repos/unicode-org/cldr/commits?path={CLDR_PATH}&per_page=1" + f"https://api.github.com/repos/unicode-org/cldr/commits?path={CLDR_PATH}&sha=main&per_page=1" ) with req.urlopen(commits_url) as response: # noqa: S310 version = json.load(response)[0]["sha"] diff --git a/src/icalendar/tests/test_generate_windows_to_olson_mapping.py b/src/icalendar/tests/test_generate_windows_to_olson_mapping.py index 570cd26..4f84c33 100644 --- a/src/icalendar/tests/test_generate_windows_to_olson_mapping.py +++ b/src/icalendar/tests/test_generate_windows_to_olson_mapping.py @@ -7,7 +7,7 @@ from urllib import request CLDR_SHA = "0123456789abcdef0123456789abcdef01234567" COMMITS_URL = ( "https://api.github.com/repos/unicode-org/cldr/commits" - "?path=common/supplemental/windowsZones.xml&per_page=1" + "?path=common/supplemental/windowsZones.xml&sha=main&per_page=1" ) RAW_URL = ( "https://raw.githubusercontent.com/unicode-org/cldr/" -- 2.55.0.windows.3 From d1f24de361c6b035d9a637571331dec79625ffbd Mon Sep 17 00:00:00 2001 From: Patrick Ribbsaeter Date: Wed, 22 Jul 2026 00:33:31 +0200 Subject: [PATCH 4/4] Address changelog attribution and formatting --- generate_windows_to_olson_mapping.py | 4 +--- news/1575.feature | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/generate_windows_to_olson_mapping.py b/generate_windows_to_olson_mapping.py index 0df31a1..2bf79a4 100644 --- a/generate_windows_to_olson_mapping.py +++ b/generate_windows_to_olson_mapping.py @@ -14,9 +14,7 @@ import xml.etree.ElementTree as ET from pathlib import Path CLDR_PATH = "common/supplemental/windowsZones.xml" -commits_url = ( - f"https://api.github.com/repos/unicode-org/cldr/commits?path={CLDR_PATH}&sha=main&per_page=1" -) +commits_url = f"https://api.github.com/repos/unicode-org/cldr/commits?path={CLDR_PATH}&sha=main&per_page=1" with req.urlopen(commits_url) as response: # noqa: S310 version = json.load(response)[0]["sha"] diff --git a/news/1575.feature b/news/1575.feature index 727256a..437b6ed 100644 --- a/news/1575.feature +++ b/news/1575.feature @@ -1 +1 @@ -Record the exact CLDR commit used to generate the Windows-to-Olson timezone mapping and fetch the mapping from that pinned revision. I used AI to assist me with this change. +Record the exact CLDR commit used to generate the Windows-to-Olson timezone mapping and fetch the mapping from that pinned revision. I used AI to assist me with this change. @patrickswedish -- 2.55.0.windows.3