You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sb...@apache.org on 2026/06/11 15:19:44 UTC

(tooling-trusted-releases) 02/02: Update dependencies with a 3 day cooldown

This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch sbp
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git

commit d43dae5fe03fc3706b64ed6be215ee1396031255
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Thu Jun 11 16:19:19 2026 +0100

    Update dependencies with a 3 day cooldown
---
 .pre-commit-config.yaml                    |  2 +-
 pip-audit.requirements                     |  2 +-
 scripts/check_when_dependencies_updated.py | 77 ++++++++++++++++++++++++------
 uv.lock                                    |  9 ++--
 4 files changed, 70 insertions(+), 20 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 8d8b39d1..260e192d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -97,7 +97,7 @@ repos:
     - id: zizmor
       args: [--min-severity, low]
 - repo: https://github.com/pypa/pip-audit
-  rev: v2.10.0
+  rev: v2.10.1
   hooks:
     - id: pip-audit
       args:
diff --git a/pip-audit.requirements b/pip-audit.requirements
index ff965a8f..428f6e00 100644
--- a/pip-audit.requirements
+++ b/pip-audit.requirements
@@ -86,7 +86,7 @@ cyclonedx-python-lib==11.9.0
 decouple-types==1.0.2
 defusedxml==0.7.1
     # via py-serializable
-distlib==0.4.2
+distlib==0.4.1
     # via virtualenv
 djlint==1.39.0
 dnspython==2.8.0
diff --git a/scripts/check_when_dependencies_updated.py b/scripts/check_when_dependencies_updated.py
index 39e77c2c..162c487c 100755
--- a/scripts/check_when_dependencies_updated.py
+++ b/scripts/check_when_dependencies_updated.py
@@ -19,11 +19,15 @@
 
 import datetime
 import pathlib
+import subprocess
 import sys
 from typing import Final
 
 _MAX_AGE_DAYS: Final[int] = 30
 
+# With a relative exclude-newer-span, uv records only this placeholder
+_SENTINEL_PREFIX: Final[str] = "0001-01-01"
+
 
 def main() -> None:
     lock_path = pathlib.Path("uv.lock")
@@ -31,15 +35,11 @@ def main() -> None:
         print("ERROR: uv.lock not found", file=sys.stderr)
         sys.exit(1)
 
-    exclude_newer = _parse_exclude_newer(lock_path)
-    if exclude_newer is None:
-        print("ERROR: No exclude-newer timestamp in uv.lock", file=sys.stderr)
-        print("Run: make update-deps", file=sys.stderr)
-        sys.exit(1)
-
-    timestamp = _parse_timestamp(exclude_newer)
+    options = _parse_options(lock_path)
+    timestamp = _last_updated(lock_path, options)
     if timestamp is None:
-        print(f"ERROR: Could not parse timestamp: {exclude_newer}", file=sys.stderr)
+        print("ERROR: Could not determine when uv.lock was last updated", file=sys.stderr)
+        print("Run: make update-deps", file=sys.stderr)
         sys.exit(1)
 
     now = datetime.datetime.now(datetime.UTC)
@@ -47,19 +47,68 @@ def main() -> None:
 
     if age > datetime.timedelta(days=_MAX_AGE_DAYS):
         print(f"ERROR: Dependencies are {age.days} days old (the limit is {_MAX_AGE_DAYS} days)", file=sys.stderr)
-        print(f"Last updated: {exclude_newer}", file=sys.stderr)
+        print(f"Last updated: {timestamp.isoformat()}", file=sys.stderr)
         print("Run: make update-deps", file=sys.stderr)
         sys.exit(1)
 
     print(f"OK: Dependencies are {age.days} days old (the limit is {_MAX_AGE_DAYS} days)")
 
 
-def _parse_exclude_newer(lock_path: pathlib.Path) -> str | None:
+def _last_updated(lock_path: pathlib.Path, options: dict[str, str]) -> datetime.datetime | None:
+    exclude_newer = options.get("exclude-newer")
+    if exclude_newer is not None and not exclude_newer.startswith(_SENTINEL_PREFIX):
+        return _parse_timestamp(exclude_newer)
+    if "exclude-newer-span" not in options:
+        return None
+    # The lockfile carries no resolution timestamp in span mode, so we use
+    # git instead, counting uncommitted changes to uv.lock as an update now
+    if _is_modified(lock_path):
+        return datetime.datetime.now(datetime.UTC)
+    return _last_commit_time(lock_path)
+
+
+def _parse_options(lock_path: pathlib.Path) -> dict[str, str]:
+    options: dict[str, str] = {}
+    in_options = False
     for line in lock_path.read_text(encoding="utf-8").splitlines():
-        if line.startswith("exclude-newer"):
-            _, _, value = line.partition("=")
-            return value.strip().strip('"')
-    return None
+        if line.startswith("["):
+            in_options = line.strip() == "[options]"
+            continue
+        if not in_options:
+            continue
+        key, eq, value = line.partition("=")
+        if not eq:
+            continue
+        value = value.strip()
+        if value.startswith('"'):
+            value = value[1:].partition('"')[0]
+        options[key.strip()] = value
+    return options
+
+
+def _is_modified(lock_path: pathlib.Path) -> bool:
+    result = subprocess.run(
+        ["git", "status", "--porcelain", "--", str(lock_path)],
+        capture_output=True,
+        text=True,
+        check=False,
+    )
+    return result.returncode == 0 and result.stdout.strip() != ""
+
+
+def _last_commit_time(lock_path: pathlib.Path) -> datetime.datetime | None:
+    result = subprocess.run(
+        ["git", "log", "-1", "--format=%cI", "--", str(lock_path)],
+        capture_output=True,
+        text=True,
+        check=False,
+    )
+    if result.returncode != 0:
+        return None
+    text = result.stdout.strip()
+    if not text:
+        return None
+    return _parse_timestamp(text)
 
 
 def _parse_timestamp(timestamp_str: str) -> datetime.datetime | None:
diff --git a/uv.lock b/uv.lock
index 60f4f8dc..e03eb895 100644
--- a/uv.lock
+++ b/uv.lock
@@ -3,7 +3,8 @@ revision = 3
 requires-python = "==3.13.*"
 
 [options]
-exclude-newer = "2026-06-08T20:24:43Z"
+exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values.
+exclude-newer-span = "P3D"
 
 [[package]]
 name = "aiofiles"
@@ -484,11 +485,11 @@ wheels = [
 
 [[package]]
 name = "distlib"
-version = "0.4.2"
+version = "0.4.1"
 source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/46/8d/873e9252ea2c0e0c857884e0a2899ec43ade132345df1925ef24cbe64f18/distlib-0.4.2.tar.gz", hash = "sha256:baeb401c90f27acd15c4861ae0847d1e731c27ac3dbf4210643ba61fa1e813db", size = 614914, upload-time = "2026-06-08T16:24:15.439Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/86/b2/d6fc3f2347f43dada79e5ff118493e8109c98400a0e29a1d5264a3aa479b/distlib-0.4.1.tar.gz", hash = "sha256:c3804d0d2d4b5fcd44036eb860cb6660485fcdf5c2aba53dc324d805837ea65b", size = 610526, upload-time = "2026-06-02T11:17:40.691Z" }
 wheels = [
-    { url = "https://files.pythonhosted.org/packages/c1/60/aa891c893821d4d127292ed66c6940d1d715894bd5a0ce048056bc641773/distlib-0.4.2-py2.py3-none-any.whl", hash = "sha256:ca4cb11e5d746b5ec13c199cbf19ae27a241f89702b54e153a74332955446067", size = 470510, upload-time = "2026-06-08T16:24:13.208Z" },
+    { url = "https://files.pythonhosted.org/packages/25/18/3497c4fa83a76dcb154923fd2075522e8dd6995ecee4093c00ae18160046/distlib-0.4.1-py2.py3-none-any.whl", hash = "sha256:9c2c552c68cbadc619f2d0ed3a69e27c351a3f4c9baa9ffb7df9e9cdc3d19a97", size = 469216, upload-time = "2026-06-02T11:17:38.779Z" },
 ]
 
 [[package]]


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org