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

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


The following commit(s) were added to refs/heads/main by this push:
     new 806ca1d  Add check result caching and apply to license checks
806ca1d is described below

commit 806ca1db6fe2f26718d21dda21c87c6d46d3ea14
Author: Sean B. Palmer <[email protected]>
AuthorDate: Mon Dec 22 15:16:30 2025 +0000

    Add check result caching and apply to license checks
---
 .pre-commit-config.yaml                         |  2 +-
 atr/models/sql.py                               |  1 +
 atr/tasks/checks/__init__.py                    | 66 ++++++++++++++++++++++++-
 atr/tasks/checks/license.py                     |  4 ++
 atr/tasks/checks/rat.py                         |  4 ++
 migrations/versions/0031_2025.12.22_0f049a07.py | 29 +++++++++++
 pyproject.toml                                  |  1 +
 uv.lock                                         | 48 +++++++++++++++---
 8 files changed, 146 insertions(+), 9 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 9b72a39..b3f0e96 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -102,7 +102,7 @@ repos:
   hooks:
     - id: pip-audit
 - repo: https://github.com/oxc-project/mirrors-oxlint
-  rev: v1.34.0
+  rev: v1.35.0
   hooks:
     - id: oxlint
       name: lint JS files with Oxlint
diff --git a/atr/models/sql.py b/atr/models/sql.py
index 2892d86..5b21220 100644
--- a/atr/models/sql.py
+++ b/atr/models/sql.py
@@ -857,6 +857,7 @@ class CheckResult(sqlmodel.SQLModel, table=True):
     data: Any = sqlmodel.Field(
         sa_column=sqlalchemy.Column(sqlalchemy.JSON), **example({"expected": 
"...", "found": "..."})
     )
+    input_hash: str | None = sqlmodel.Field(default=None, index=True, 
**example("blake3:7f83b1657ff1fc..."))
 
 
 class CheckResultIgnore(sqlmodel.SQLModel, table=True):
diff --git a/atr/tasks/checks/__init__.py b/atr/tasks/checks/__init__.py
index 574c9ab..97b7c29 100644
--- a/atr/tasks/checks/__init__.py
+++ b/atr/tasks/checks/__init__.py
@@ -21,8 +21,11 @@ import dataclasses
 import datetime
 import functools
 import pathlib
-from typing import TYPE_CHECKING, Any
+from typing import TYPE_CHECKING, Any, Final
 
+import aiofiles
+import aiofiles.os
+import blake3
 import sqlmodel
 
 if TYPE_CHECKING:
@@ -34,6 +37,8 @@ import atr.db as db
 import atr.models.sql as sql
 import atr.util as util
 
+_HASH_CHUNK_SIZE: Final[int] = 4 * 1024 * 1024
+
 
 # Pydantic does not like Callable types, so we use a dataclass instead
 # It says: "you should define `Callable`, then call 
`FunctionArguments.model_rebuild()`"
@@ -57,6 +62,8 @@ class Recorder:
     member_rel_path: str | None
     revision: str
     afresh: bool
+    __cached: bool
+    __input_hash: str | None
 
     def __init__(
         self,
@@ -76,6 +83,8 @@ class Recorder:
         self.afresh = afresh
         self.constructed = False
         self.member_problems: dict[sql.CheckResultStatus, int] = {}
+        self.__cached = False
+        self.__input_hash = None
 
         self.project_name = project_name
         self.version_name = version_name
@@ -129,6 +138,7 @@ class Recorder:
             status=status,
             message=message,
             data=data,
+            input_hash=self.__input_hash,
         )
 
         # It would be more efficient to keep a session open
@@ -186,6 +196,48 @@ class Recorder:
         abs_path = await self.abs_path()
         return matches(str(abs_path))
 
+    @property
+    def cached(self) -> bool:
+        return self.__cached
+
+    async def check_cache(self, path: pathlib.Path) -> bool:
+        if not await aiofiles.os.path.isfile(path):
+            return False
+
+        self.__input_hash = await _compute_file_hash(path)
+
+        async with db.session() as data:
+            stmt = (
+                sqlmodel.select(sql.CheckResult)
+                .where(sql.CheckResult.checker == self.checker)
+                .where(sql.CheckResult.input_hash == self.__input_hash)
+                .where(sql.CheckResult.primary_rel_path == 
self.primary_rel_path)
+            )
+            results = await data.execute(stmt)
+            cached_results = results.scalars().all()
+
+            if not cached_results:
+                return False
+
+            for cached in cached_results:
+                new_result = sql.CheckResult(
+                    release_name=self.release_name,
+                    revision_number=self.revision_number,
+                    checker=self.checker,
+                    primary_rel_path=self.primary_rel_path,
+                    member_rel_path=cached.member_rel_path,
+                    created=datetime.datetime.now(datetime.UTC),
+                    status=cached.status,
+                    message=cached.message,
+                    data=cached.data,
+                    input_hash=self.__input_hash,
+                )
+                data.add(new_result)
+            await data.commit()
+
+        self.__cached = True
+        return True
+
     async def clear(self, primary_rel_path: str | None = None, 
member_rel_path: str | None = None) -> None:
         async with db.session() as data:
             stmt = sqlmodel.delete(sql.CheckResult).where(
@@ -198,6 +250,10 @@ class Recorder:
             await data.execute(stmt)
             await data.commit()
 
+    @property
+    def input_hash(self) -> str | None:
+        return self.__input_hash
+
     async def exception(
         self, message: str, data: Any, primary_rel_path: str | None = None, 
member_rel_path: str | None = None
     ) -> sql.CheckResult:
@@ -259,3 +315,11 @@ def with_model(cls: type[schema.Strict]) -> 
Callable[[Callable[..., Any]], Calla
         return wrapper
 
     return decorator
+
+
+async def _compute_file_hash(path: pathlib.Path) -> str:
+    hasher = blake3.blake3()
+    async with aiofiles.open(path, "rb") as f:
+        while chunk := await f.read(_HASH_CHUNK_SIZE):
+            hasher.update(chunk)
+    return f"blake3:{hasher.hexdigest()}"
diff --git a/atr/tasks/checks/license.py b/atr/tasks/checks/license.py
index f8be11b..d4f9ce4 100644
--- a/atr/tasks/checks/license.py
+++ b/atr/tasks/checks/license.py
@@ -158,6 +158,10 @@ async def headers(args: checks.FunctionArguments) -> 
results.Results | None:
     if await recorder.primary_path_is_binary():
         return None
 
+    if await recorder.check_cache(artifact_abs_path):
+        log.info(f"Using cached license headers result for {artifact_abs_path} 
(rel: {args.primary_rel_path})")
+        return None
+
     log.info(f"Checking license headers for {artifact_abs_path} (rel: 
{args.primary_rel_path})")
 
     async with db.session() as data:
diff --git a/atr/tasks/checks/rat.py b/atr/tasks/checks/rat.py
index 1e87da0..fadae35 100644
--- a/atr/tasks/checks/rat.py
+++ b/atr/tasks/checks/rat.py
@@ -53,6 +53,10 @@ async def check(args: checks.FunctionArguments) -> 
results.Results | None:
         log.info(f"Skipping RAT check for binary artifact {artifact_abs_path} 
(rel: {args.primary_rel_path})")
         return None
 
+    if await recorder.check_cache(artifact_abs_path):
+        log.info(f"Using cached RAT result for {artifact_abs_path} (rel: 
{args.primary_rel_path})")
+        return None
+
     log.info(f"Checking RAT licenses for {artifact_abs_path} (rel: 
{args.primary_rel_path})")
 
     try:
diff --git a/migrations/versions/0031_2025.12.22_0f049a07.py 
b/migrations/versions/0031_2025.12.22_0f049a07.py
new file mode 100644
index 0000000..a77fe74
--- /dev/null
+++ b/migrations/versions/0031_2025.12.22_0f049a07.py
@@ -0,0 +1,29 @@
+"""Add an input hash field for check caching
+
+Revision ID: 0031_2025.12.22_0f049a07
+Revises: 0030_2025.12.05_211a31e3
+Create Date: 2025-12-22 14:59:17.175444+00:00
+"""
+
+from collections.abc import Sequence
+
+import sqlalchemy as sa
+from alembic import op
+
+# Revision identifiers, used by Alembic
+revision: str = "0031_2025.12.22_0f049a07"
+down_revision: str | None = "0030_2025.12.05_211a31e3"
+branch_labels: str | Sequence[str] | None = None
+depends_on: str | Sequence[str] | None = None
+
+
+def upgrade() -> None:
+    with op.batch_alter_table("checkresult", schema=None) as batch_op:
+        batch_op.add_column(sa.Column("input_hash", sa.String(), 
nullable=True))
+        batch_op.create_index(batch_op.f("ix_checkresult_input_hash"), 
["input_hash"], unique=False)
+
+
+def downgrade() -> None:
+    with op.batch_alter_table("checkresult", schema=None) as batch_op:
+        batch_op.drop_index(batch_op.f("ix_checkresult_input_hash"))
+        batch_op.drop_column("input_hash")
diff --git a/pyproject.toml b/pyproject.toml
index a1263df..e183ff8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,6 +18,7 @@ dependencies = [
   "alembic~=1.14",
   "asfquart @ git+https://github.com/apache/infrastructure-asfquart.git@main";,
   "asyncssh>=2.20.0,<3.0.0",
+  "blake3>=1.0.8",
   "blockbuster>=1.5.23,<2.0.0",
   "cmarkgfm>=2024.11.20",
   "cryptography~=44.0",
diff --git a/uv.lock b/uv.lock
index 8b73407..9e12959 100644
--- a/uv.lock
+++ b/uv.lock
@@ -3,7 +3,7 @@ revision = 3
 requires-python = "==3.13.*"
 
 [options]
-exclude-newer = "2025-12-19T17:04:05Z"
+exclude-newer = "2025-12-22T14:59:46Z"
 
 [[package]]
 name = "aiofiles"
@@ -191,15 +191,15 @@ dependencies = [
 
 [[package]]
 name = "asyncssh"
-version = "2.21.1"
+version = "2.22.0"
 source = { registry = "https://pypi.org/simple"; }
 dependencies = [
     { name = "cryptography" },
     { name = "typing-extensions" },
 ]
-sdist = { url = 
"https://files.pythonhosted.org/packages/6b/b8/065c20bb5c9b8991648c0f25b13e445b4f51556cc3fdd0ad13ce4787c156/asyncssh-2.21.1.tar.gz";,
 hash = 
"sha256:9943802955e2131536c2b1e71aacc68f56973a399937ed0b725086d7461c990c", size 
= 540515, upload-time = "2025-09-28T16:36:19.468Z" }
+sdist = { url = 
"https://files.pythonhosted.org/packages/fc/d5/957886c316466349d55c4de6a688a10a98295c0b4429deb8db1a17f3eb19/asyncssh-2.22.0.tar.gz";,
 hash = 
"sha256:c3ce72b01be4f97b40e62844dd384227e5ff5a401a3793007c42f86a5c8eb537", size 
= 540523, upload-time = "2025-12-21T23:38:30.5Z" }
 wheels = [
-    { url = 
"https://files.pythonhosted.org/packages/0e/89/4a9a61bc120ca68bce92b0ea176ddc0e550e58c60ab820603bd5246e7261/asyncssh-2.21.1-py3-none-any.whl";,
 hash = 
"sha256:f218f9f303c78df6627d0646835e04039a156d15e174ad63c058d62de61e1968", size 
= 375529, upload-time = "2025-09-28T16:36:17.68Z" },
+    { url = 
"https://files.pythonhosted.org/packages/ed/ae/0da2f2214fc183338af1afe5a103a2052fd03464e8eafbd827abff58a4d0/asyncssh-2.22.0-py3-none-any.whl";,
 hash = 
"sha256:d16465ccdf1ed20eba1131b14415b155e047f6f5be0d19f39c2e0b61331ee0e7", size 
= 374938, upload-time = "2025-12-21T23:38:28.976Z" },
 ]
 
 [[package]]
@@ -211,6 +211,38 @@ wheels = [
     { url = 
"https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl";,
 hash = 
"sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size 
= 67615, upload-time = "2025-10-06T13:54:43.17Z" },
 ]
 
+[[package]]
+name = "blake3"
+version = "1.0.8"
+source = { registry = "https://pypi.org/simple"; }
+sdist = { url = 
"https://files.pythonhosted.org/packages/75/aa/abcd75e9600987a0bc6cfe9b6b2ff3f0e2cb08c170addc6e76035b5c4cb3/blake3-1.0.8.tar.gz";,
 hash = 
"sha256:513cc7f0f5a7c035812604c2c852a0c1468311345573de647e310aca4ab165ba", size 
= 117308, upload-time = "2025-10-14T06:47:48.83Z" }
+wheels = [
+    { url = 
"https://files.pythonhosted.org/packages/55/b8/11de9528c257f7f1633f957ccaff253b706838d22c5d2908e4735798ec01/blake3-1.0.8-cp313-cp313-macosx_10_12_x86_64.whl";,
 hash = 
"sha256:46dc20976bd6c235959ef0246ec73420d1063c3da2839a9c87ca395cf1fd7943", size 
= 347771, upload-time = "2025-10-14T06:46:04.248Z" },
+    { url = 
"https://files.pythonhosted.org/packages/50/26/f7668be55c909678b001ecacff11ad7016cd9b4e9c7cc87b5971d638c5a9/blake3-1.0.8-cp313-cp313-macosx_11_0_arm64.whl";,
 hash = 
"sha256:d17eb6382634b3a5bc0c0e0454d5265b0becaeeadb6801ed25150b39a999d0cc", size 
= 325431, upload-time = "2025-10-14T06:46:06.136Z" },
+    { url = 
"https://files.pythonhosted.org/packages/77/57/e8a85fa261894bf7ce7af928ff3408aab60287ab8d58b55d13a3f700b619/blake3-1.0.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl";,
 hash = 
"sha256:19fc6f2b7edab8acff6895fc6e38c19bd79f4c089e21153020c75dfc7397d52d", size 
= 370994, upload-time = "2025-10-14T06:46:07.398Z" },
+    { url = 
"https://files.pythonhosted.org/packages/62/cd/765b76bb48b8b294fea94c9008b0d82b4cfa0fa2f3c6008d840d01a597e4/blake3-1.0.8-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl";,
 hash = 
"sha256:4f54cff7f15d91dc78a63a2dd02a3dccdc932946f271e2adb4130e0b4cf608ba", size 
= 374372, upload-time = "2025-10-14T06:46:08.698Z" },
+    { url = 
"https://files.pythonhosted.org/packages/36/7a/32084eadbb28592bb07298f0de316d2da586c62f31500a6b1339a7e7b29b/blake3-1.0.8-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl";,
 hash = 
"sha256:e7e12a777f6b798eb8d06f875d6e108e3008bd658d274d8c676dcf98e0f10537", size 
= 447627, upload-time = "2025-10-14T06:46:10.002Z" },
+    { url = 
"https://files.pythonhosted.org/packages/a7/f4/3788a1d86e17425eea147e28d7195d7053565fc279236a9fd278c2ec495e/blake3-1.0.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl";,
 hash = 
"sha256:ddfc59b0176fb31168f08d5dd536e69b1f4f13b5a0f4b0c3be1003efd47f9308", size 
= 507536, upload-time = "2025-10-14T06:46:11.614Z" },
+    { url = 
"https://files.pythonhosted.org/packages/fe/01/4639cba48513b94192681b4da472cdec843d3001c5344d7051ee5eaef606/blake3-1.0.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl";,
 hash = 
"sha256:a2336d5b2a801a7256da21150348f41610a6c21dae885a3acb1ebbd7333d88d8", size 
= 394105, upload-time = "2025-10-14T06:46:12.808Z" },
+    { url = 
"https://files.pythonhosted.org/packages/21/ae/6e55c19c8460fada86cd1306a390a09b0c5a2e2e424f9317d2edacea439f/blake3-1.0.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl";,
 hash = 
"sha256:e4072196547484c95a5a09adbb952e9bb501949f03f9e2a85e7249ef85faaba8", size 
= 386928, upload-time = "2025-10-14T06:46:16.284Z" },
+    { url = 
"https://files.pythonhosted.org/packages/ee/6c/05b7a5a907df1be53a8f19e7828986fc6b608a44119641ef9c0804fbef15/blake3-1.0.8-cp313-cp313-musllinux_1_1_aarch64.whl";,
 hash = 
"sha256:0eab3318ec02f8e16fe549244791ace2ada2c259332f0c77ab22cf94dfff7130", size 
= 550003, upload-time = "2025-10-14T06:46:17.791Z" },
+    { url = 
"https://files.pythonhosted.org/packages/b4/03/f0ea4adfedc1717623be6460b3710fcb725ca38082c14274369803f727e1/blake3-1.0.8-cp313-cp313-musllinux_1_1_x86_64.whl";,
 hash = 
"sha256:a33b9a1fb6d1d559a8e0d04b041e99419a6bb771311c774f6ff57ed7119c70ed", size 
= 553857, upload-time = "2025-10-14T06:46:19.088Z" },
+    { url = 
"https://files.pythonhosted.org/packages/cc/6f/e5410d2e2a30c8aba8389ffc1c0061356916bf5ecd0a210344e7b69b62ab/blake3-1.0.8-cp313-cp313-win32.whl";,
 hash = 
"sha256:e171b169cb7ea618e362a4dddb7a4d4c173bbc08b9ba41ea3086dd1265530d4f", size 
= 228315, upload-time = "2025-10-14T06:46:20.391Z" },
+    { url = 
"https://files.pythonhosted.org/packages/79/ef/d9c297956dfecd893f29f59e7b22445aba5b47b7f6815d9ba5dcd73fcae6/blake3-1.0.8-cp313-cp313-win_amd64.whl";,
 hash = 
"sha256:3168c457255b5d2a2fc356ba696996fcaff5d38284f968210d54376312107662", size 
= 215477, upload-time = "2025-10-14T06:46:21.542Z" },
+    { url = 
"https://files.pythonhosted.org/packages/20/ba/eaa7723d66dd8ab762a3e85e139bb9c46167b751df6e950ad287adb8fb61/blake3-1.0.8-cp313-cp313t-macosx_10_12_x86_64.whl";,
 hash = 
"sha256:b4d672c24dc15ec617d212a338a4ca14b449829b6072d09c96c63b6e6b621aed", size 
= 347289, upload-time = "2025-10-14T06:46:22.772Z" },
+    { url = 
"https://files.pythonhosted.org/packages/47/b3/6957f6ee27f0d5b8c4efdfda68a1298926a88c099f4dd89c711049d16526/blake3-1.0.8-cp313-cp313t-macosx_11_0_arm64.whl";,
 hash = 
"sha256:1af0e5a29aa56d4fba904452ae784740997440afd477a15e583c38338e641f41", size 
= 324444, upload-time = "2025-10-14T06:46:24.729Z" },
+    { url = 
"https://files.pythonhosted.org/packages/13/da/722cebca11238f3b24d3cefd2361c9c9ea47cfa0ad9288eeb4d1e0b7cf93/blake3-1.0.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl";,
 hash = 
"sha256:ef153c5860d5bf1cc71aece69b28097d2a392913eb323d6b52555c875d0439fc", size 
= 370441, upload-time = "2025-10-14T06:46:26.29Z" },
+    { url = 
"https://files.pythonhosted.org/packages/2e/d5/2f7440c8e41c0af995bad3a159e042af0f4ed1994710af5b4766ca918f65/blake3-1.0.8-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl";,
 hash = 
"sha256:e8ae3689f0c7bfa6ce6ae45cab110e4c3442125c4c23b28f1f097856de26e4d1", size 
= 374312, upload-time = "2025-10-14T06:46:27.451Z" },
+    { url = 
"https://files.pythonhosted.org/packages/a6/6c/fb6a7812e60ce3e110bcbbb11f167caf3e975c589572c41e1271f35f2c41/blake3-1.0.8-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl";,
 hash = 
"sha256:3fb83532f7456ddeb68dae1b36e1f7c52f9cb72852ac01159bbcb1a12b0f8be0", size 
= 447007, upload-time = "2025-10-14T06:46:29.056Z" },
+    { url = 
"https://files.pythonhosted.org/packages/13/3b/c99b43fae5047276ea9d944077c190fc1e5f22f57528b9794e21f7adedc6/blake3-1.0.8-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl";,
 hash = 
"sha256:6ae7754c7d96e92a70a52e07c732d594cf9924d780f49fffd3a1e9235e0f5ba7", size 
= 507323, upload-time = "2025-10-14T06:46:30.661Z" },
+    { url = 
"https://files.pythonhosted.org/packages/fc/bb/ba90eddd592f8c074a0694cb0a744b6bd76bfe67a14c2b490c8bdfca3119/blake3-1.0.8-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl";,
 hash = 
"sha256:4bacaae75e98dee3b7da6c5ee3b81ee21a3352dd2477d6f1d1dbfd38cdbf158a", size 
= 393449, upload-time = "2025-10-14T06:46:31.805Z" },
+    { url = 
"https://files.pythonhosted.org/packages/25/ed/58a2acd0b9e14459cdaef4344db414d4a36e329b9720921b442a454dd443/blake3-1.0.8-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl";,
 hash = 
"sha256:9456c829601d72852d8ba0af8dae0610f7def1d59f5942efde1e2ef93e8a8b57", size 
= 386844, upload-time = "2025-10-14T06:46:33.195Z" },
+    { url = 
"https://files.pythonhosted.org/packages/4a/04/fed09845b18d90862100c8e48308261e2f663aab25d3c71a6a0bdda6618b/blake3-1.0.8-cp313-cp313t-musllinux_1_1_aarch64.whl";,
 hash = 
"sha256:497ef8096ec4ac1ffba9a66152cee3992337cebf8ea434331d8fd9ce5423d227", size 
= 549550, upload-time = "2025-10-14T06:46:35.23Z" },
+    { url = 
"https://files.pythonhosted.org/packages/d6/65/1859fddfabc1cc72548c2269d988819aad96d854e25eae00531517925901/blake3-1.0.8-cp313-cp313t-musllinux_1_1_x86_64.whl";,
 hash = 
"sha256:511133bab85ff60ed143424ce484d08c60894ff7323f685d7a6095f43f0c85c3", size 
= 553805, upload-time = "2025-10-14T06:46:36.532Z" },
+    { url = 
"https://files.pythonhosted.org/packages/c1/c7/2969352017f62378e388bb07bb2191bc9a953f818dc1cd6b9dd5c24916e1/blake3-1.0.8-cp313-cp313t-win32.whl";,
 hash = 
"sha256:9c9fbdacfdeb68f7ca53bb5a7a5a593ec996eaf21155ad5b08d35e6f97e60877", size 
= 228068, upload-time = "2025-10-14T06:46:37.826Z" },
+    { url = 
"https://files.pythonhosted.org/packages/d8/fc/923e25ac9cadfff1cd20038bcc0854d0f98061eb6bc78e42c43615f5982d/blake3-1.0.8-cp313-cp313t-win_amd64.whl";,
 hash = 
"sha256:3cec94ed5676821cf371e9c9d25a41b4f3ebdb5724719b31b2749653b7cc1dfa", size 
= 215369, upload-time = "2025-10-14T06:46:39.054Z" },
+]
+
 [[package]]
 name = "blinker"
 version = "1.9.0"
@@ -986,11 +1018,11 @@ sdist = { url = 
"https://files.pythonhosted.org/packages/a6/91/86a6eac449ddfae23
 
 [[package]]
 name = "nodeenv"
-version = "1.9.1"
+version = "1.10.0"
 source = { registry = "https://pypi.org/simple"; }
-sdist = { url = 
"https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz";,
 hash = 
"sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size 
= 47437, upload-time = "2024-06-04T18:44:11.171Z" }
+sdist = { url = 
"https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz";,
 hash = 
"sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size 
= 55611, upload-time = "2025-12-20T14:08:54.006Z" }
 wheels = [
-    { url = 
"https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl";,
 hash = 
"sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size 
= 22314, upload-time = "2024-06-04T18:44:08.352Z" },
+    { url = 
"https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl";,
 hash = 
"sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size 
= 23438, upload-time = "2025-12-20T14:08:52.782Z" },
 ]
 
 [[package]]
@@ -1778,6 +1810,7 @@ dependencies = [
     { name = "alembic" },
     { name = "asfquart" },
     { name = "asyncssh" },
+    { name = "blake3" },
     { name = "blockbuster" },
     { name = "cmarkgfm" },
     { name = "cryptography" },
@@ -1836,6 +1869,7 @@ requires-dist = [
     { name = "alembic", specifier = "~=1.14" },
     { name = "asfquart", git = 
"https://github.com/apache/infrastructure-asfquart.git?rev=main"; },
     { name = "asyncssh", specifier = ">=2.20.0,<3.0.0" },
+    { name = "blake3", specifier = ">=1.0.8" },
     { name = "blockbuster", specifier = ">=1.5.23,<2.0.0" },
     { name = "cmarkgfm", specifier = ">=2024.11.20" },
     { name = "cryptography", specifier = "~=44.0" },


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to