From 85ecc3b59c2c4bbe49afebc925b2bf5daf2a8b1b Mon Sep 17 00:00:00 2001 From: KennyMcSimpson <70093673+KennyMcSimpson@users.noreply.github.com> Date: Sat, 24 Oct 2026 22:23:19 +0800 Subject: [PATCH] Format conditional requests with locale-independent HTTP dates --- noxfile.py | 2 +- sphinx_json_schema_spec/__init__.py | 3 +- .../tests/test_fetching.py | 41 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 sphinx_json_schema_spec/tests/test_fetching.py diff --git a/noxfile.py b/noxfile.py index f385768..db8be87 100644 --- a/noxfile.py +++ b/noxfile.py @@ -71,7 +71,7 @@ def typing(session): """ Check static typing. """ - session.install("mypy", "types-docutils", "types-lxml", ROOT) + session.install("mypy", "pytest", "types-docutils", "types-lxml", ROOT) session.run("python", "-m", "mypy", PACKAGE) diff --git a/sphinx_json_schema_spec/__init__.py b/sphinx_json_schema_spec/__init__.py index 85919a9..c93d28f 100644 --- a/sphinx_json_schema_spec/__init__.py +++ b/sphinx_json_schema_spec/__init__.py @@ -4,6 +4,7 @@ from contextlib import suppress from datetime import UTC, datetime +from email.utils import format_datetime from importlib import metadata from pathlib import Path from urllib.parse import urljoin @@ -76,7 +77,7 @@ def fetch_or_load(cache_path, url): with suppress(FileNotFoundError): modified = datetime.fromtimestamp(cache_path.stat().st_mtime, UTC) - date = modified.strftime("%a, %d %b %Y %I:%M:%S UTC") + date = format_datetime(modified, usegmt=True) headers["If-Modified-Since"] = date request = urllib.request.Request(url, headers=headers) diff --git a/sphinx_json_schema_spec/tests/test_fetching.py b/sphinx_json_schema_spec/tests/test_fetching.py new file mode 100644 index 0000000..bc3a335 --- /dev/null +++ b/sphinx_json_schema_spec/tests/test_fetching.py @@ -0,0 +1,41 @@ +from datetime import UTC, datetime +from io import BytesIO +import locale +import os + +import pytest + +from sphinx_json_schema_spec import fetch_or_load + + +@pytest.mark.parametrize("time_locale", ["C", ""]) +def test_conditional_request_uses_http_date( + tmp_path, + monkeypatch, + time_locale, +): + cache_path = tmp_path / "spec.html" + cache_path.write_bytes(b"cached") + modified = datetime(2025, 1, 2, 15, 4, 5, tzinfo=UTC).timestamp() + os.utime(cache_path, (modified, modified)) + requests = [] + + class Response(BytesIO): + code = 200 + + def urlopen(request, context): + requests.append(request) + return Response(b"fresh") + + monkeypatch.setattr("urllib.request.urlopen", urlopen) + previous_locale = locale.setlocale(locale.LC_TIME) + try: + locale.setlocale(locale.LC_TIME, time_locale) + result = fetch_or_load(cache_path, "https://example.com/spec.html") + finally: + locale.setlocale(locale.LC_TIME, previous_locale) + + assert requests[0].get_header("If-modified-since") == ( + "Thu, 02 Jan 2025 15:04:05 GMT" + ) + assert result.find("body").text == "fresh"