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-release.git


The following commit(s) were added to refs/heads/main by this push:
     new c65d689  Make the storage authentication interface raise exceptions by 
default
c65d689 is described below

commit c65d689e43adfd98ea94cf7c0dc15aceacb13b6b
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Jul 23 15:38:48 2025 +0100

    Make the storage authentication interface raise exceptions by default
---
 atr/blueprints/admin/admin.py |  4 ++--
 atr/blueprints/api/api.py     | 10 +++++-----
 atr/routes/keys.py            | 17 ++++++++---------
 atr/storage/__init__.py       | 32 +++++++++++++++++---------------
 atr/storage/writers/keys.py   |  2 +-
 atr/tasks/keys.py             |  3 +--
 docs/storage-interface.html   |  6 +++---
 docs/storage-interface.md     |  6 +++---
 8 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/atr/blueprints/admin/admin.py b/atr/blueprints/admin/admin.py
index 14e0d52..8004a05 100644
--- a/atr/blueprints/admin/admin.py
+++ b/atr/blueprints/admin/admin.py
@@ -434,7 +434,7 @@ async def admin_keys_regenerate_all() -> quart.Response:
     outcomes = types.Outcomes[str]()
     async with storage.write(asf_uid) as write:
         for committee_name in committee_names:
-            wacm = write.as_committee_member(committee_name).result_or_none()
+            wacm = write.as_committee_member(committee_name)
             if wacm is None:
                 continue
             outcomes.append(await wacm.keys.autogenerate_keys_file())
@@ -674,7 +674,7 @@ async def admin_test() -> quart.wrappers.response.Response:
     if asf_uid is None:
         raise base.ASFQuartException("Invalid session, uid is None", 500)
     async with storage.write(asf_uid) as write:
-        wacm = write.as_committee_member("tooling").result_or_raise()
+        wacm = write.as_committee_member("tooling")
         start = time.perf_counter_ns()
         outcomes: types.Outcomes[types.Key] = await 
wacm.keys.ensure_stored(keys_file_text)
         end = time.perf_counter_ns()
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index 420758a..de2b92f 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -304,12 +304,12 @@ async def keys_add(data: models.api.KeysAddArgs) -> 
DictResponse:
     selected_committee_names = data.committees
 
     async with storage.write(asf_uid) as write:
-        wafc = write.as_foundation_committer().result_or_raise()
+        wafc = write.as_foundation_committer()
         ocr: types.Outcome[types.Key] = await 
wafc.keys.ensure_stored_one(data.key)
         key = ocr.result_or_raise()
 
         for selected_committee_name in selected_committee_names:
-            wacm = 
write.as_committee_member(selected_committee_name).result_or_raise()
+            wacm = write.as_committee_member(selected_committee_name)
             outcome: types.Outcome[types.LinkedCommittee] = await 
wacm.keys.associate_fingerprint(
                 key.key_model.fingerprint
             )
@@ -333,12 +333,12 @@ async def keys_delete(data: models.api.KeysDeleteArgs) -> 
DictResponse:
 
     outcomes = types.Outcomes[str]()
     async with storage.write(asf_uid) as write:
-        wafc = write.as_foundation_committer().result_or_raise()
+        wafc = write.as_foundation_committer()
         outcome: types.Outcome[sql.PublicSigningKey] = await 
wafc.keys.delete_key(fingerprint)
         key = outcome.result_or_raise()
 
         for committee in key.committees:
-            wacm = write.as_committee_member(committee.name).result_or_none()
+            wacm = 
write.as_committee_member_outcome(committee.name).result_or_none()
             if wacm is None:
                 continue
             outcomes.append(await wacm.keys.autogenerate_keys_file())
@@ -387,7 +387,7 @@ async def keys_upload(data: models.api.KeysUploadArgs) -> 
DictResponse:
     filetext = data.filetext
     selected_committee_name = data.committee
     async with storage.write(asf_uid) as write:
-        wacm = 
write.as_committee_member(selected_committee_name).result_or_raise()
+        wacm = write.as_committee_member(selected_committee_name)
         outcomes: types.Outcomes[types.Key] = await 
wacm.keys.ensure_associated(filetext)
 
         # TODO: It would be nice to serialise the actual outcomes
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index f25f521..0069ee1 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -161,14 +161,14 @@ async def add(session: routes.CommitterSession) -> str:
             selected_committee_names: list[str] = 
util.unwrap(form.selected_committees.data)
 
             async with storage.write(asf_uid) as write:
-                wafc = write.as_foundation_committer().result_or_raise()
+                wafc = write.as_foundation_committer()
                 ocr: types.Outcome[types.Key] = await 
wafc.keys.ensure_stored_one(key_text)
                 key = ocr.result_or_raise()
 
                 for selected_committee_name in selected_committee_names:
                     # TODO: Should this be committee member or committee 
participant?
                     # Also, should we emit warnings and continue here?
-                    wacp = 
write.as_committee_participant(selected_committee_name).result_or_raise()
+                    wacp = 
write.as_committee_participant(selected_committee_name)
                     outcome: types.Outcome[types.LinkedCommittee] = await 
wacp.keys.associate_fingerprint(
                         key.key_model.fingerprint
                     )
@@ -218,7 +218,7 @@ async def delete(session: routes.CommitterSession) -> 
response.Response:
 
     # Otherwise, delete an OpenPGP key
     async with storage.write(session.uid) as write:
-        wafc = write.as_foundation_committer().result_or_none()
+        wafc = write.as_foundation_committer_outcome().result_or_none()
         if wafc is None:
             return await session.redirect(keys, error="Key not found or not 
owned by you")
         outcome: types.Outcome[sql.PublicSigningKey] = await 
wafc.keys.delete_key(fingerprint)
@@ -279,7 +279,7 @@ async def details(session: routes.CommitterSession, 
fingerprint: str) -> str | r
             if affected_committee_names:
                 async with storage.write(session.uid) as write:
                     for affected_committee_name in affected_committee_names:
-                        wacm = 
write.as_committee_member(affected_committee_name).result_or_none()
+                        wacm = 
write.as_committee_member_outcome(affected_committee_name).result_or_none()
                         if wacm is None:
                             continue
                         await wacm.keys.autogenerate_keys_file()
@@ -304,7 +304,7 @@ async def details(session: routes.CommitterSession, 
fingerprint: str) -> str | r
 async def export(session: routes.CommitterSession, committee_name: str) -> 
quart.Response:
     """Export a KEYS file for a specific committee."""
     async with storage.write(session.uid) as write:
-        wafc = write.as_foundation_committer().result_or_raise()
+        wafc = write.as_foundation_committer()
         keys_file_text = await wafc.keys.keys_file_text(committee_name)
 
     return quart.Response(keys_file_text, mimetype="text/plain")
@@ -317,8 +317,7 @@ async def import_selected_revision(
     await util.validate_empty_form()
 
     async with storage.write(session.uid) as write:
-        access_outcome = await write.as_project_committee_member(project_name)
-        wacm = access_outcome.result_or_raise()
+        wacm = await write.as_project_committee_member(project_name)
         outcomes: types.Outcomes[types.Key] = await 
wacm.keys.import_keys_file(project_name, version_name)
 
     message = f"Uploaded {outcomes.result_count} keys,"
@@ -448,7 +447,7 @@ async def update_committee_keys(session: 
routes.CommitterSession, committee_name
         return await session.redirect(keys, error="Invalid request to update 
KEYS file.")
 
     async with storage.write(session.uid) as write:
-        wacm = write.as_committee_member(committee_name).result_or_raise()
+        wacm = write.as_committee_member(committee_name)
         match await wacm.keys.autogenerate_keys_file():
             case types.OutcomeResult():
                 await quart.flash(
@@ -527,7 +526,7 @@ async def upload(session: routes.CommitterSession) -> str:
             return await render(error="You must select at least one committee")
 
         async with storage.write(session.uid) as write:
-            wacm = 
write.as_committee_member(selected_committee).result_or_raise()
+            wacm = write.as_committee_member(selected_committee)
             outcomes = await wacm.keys.ensure_associated(keys_text)
         results = outcomes
         success_count = outcomes.result_count
diff --git a/atr/storage/__init__.py b/atr/storage/__init__.py
index 1adc9a7..70cd257 100644
--- a/atr/storage/__init__.py
+++ b/atr/storage/__init__.py
@@ -225,7 +225,10 @@ class Write:
     #         return types.OutcomeException(e)
     #     return types.OutcomeResult(wacm)
 
-    def as_committee_member(self, committee_name: str) -> 
types.Outcome[WriteAsCommitteeMember]:
+    def as_committee_member(self, committee_name: str) -> 
WriteAsCommitteeMember:
+        return 
self.as_committee_member_outcome(committee_name).result_or_raise()
+
+    def as_committee_member_outcome(self, committee_name: str) -> 
types.Outcome[WriteAsCommitteeMember]:
         if self.__asf_uid is None:
             return types.OutcomeException(AccessError("No ASF UID"))
         if committee_name not in self.__member_of:
@@ -236,7 +239,10 @@ class Write:
             return types.OutcomeException(e)
         return types.OutcomeResult(wacm)
 
-    def as_committee_participant(self, committee_name: str) -> 
types.Outcome[WriteAsCommitteeParticipant]:
+    def as_committee_participant(self, committee_name: str) -> 
WriteAsCommitteeParticipant:
+        return 
self.as_committee_participant_outcome(committee_name).result_or_raise()
+
+    def as_committee_participant_outcome(self, committee_name: str) -> 
types.Outcome[WriteAsCommitteeParticipant]:
         if self.__asf_uid is None:
             return types.OutcomeException(AccessError("No ASF UID"))
         if committee_name not in self.__participant_of:
@@ -247,7 +253,10 @@ class Write:
             return types.OutcomeException(e)
         return types.OutcomeResult(wacp)
 
-    def as_foundation_committer(self) -> 
types.Outcome[WriteAsFoundationCommitter]:
+    def as_foundation_committer(self) -> WriteAsFoundationCommitter:
+        return self.as_foundation_committer_outcome().result_or_raise()
+
+    def as_foundation_committer_outcome(self) -> 
types.Outcome[WriteAsFoundationCommitter]:
         if self.__asf_uid is None:
             return types.OutcomeException(AccessError("No ASF UID"))
         try:
@@ -259,7 +268,11 @@ class Write:
     # async def as_key_owner(self) -> types.Outcome[WriteAsKeyOwner]:
     #     ...
 
-    async def as_project_committee_member(self, project_name: str) -> 
types.Outcome[WriteAsCommitteeMember]:
+    async def as_project_committee_member(self, project_name: str) -> 
WriteAsCommitteeMember:
+        write_as_outcome = await 
self.as_project_committee_member_outcome(project_name)
+        return write_as_outcome.result_or_raise()
+
+    async def as_project_committee_member_outcome(self, project_name: str) -> 
types.Outcome[WriteAsCommitteeMember]:
         project = await self.__data.project(project_name, 
_committee=True).demand(
             AccessError(f"Project not found: {project_name}")
         )
@@ -360,16 +373,6 @@ class ContextManagers:
             r = Read(data, asf_uid, member_of, participant_of)
             yield r
 
-    @contextlib.asynccontextmanager
-    async def read_and_write(self, asf_uid: str | None = None) -> 
AsyncGenerator[tuple[Read, Write]]:
-        async with db.session() as data:
-            # TODO: Replace data with DatabaseReader and DatabaseWriter 
instances
-            member_of = await self.member_of(data, asf_uid)
-            participant_of = await self.participant_of(data, asf_uid)
-            r = Read(data, asf_uid, member_of, participant_of)
-            w = Write(data, asf_uid, member_of, participant_of)
-            yield r, w
-
     @contextlib.asynccontextmanager
     async def write(self, asf_uid: str | None = None) -> AsyncGenerator[Write]:
         async with db.session() as data:
@@ -383,5 +386,4 @@ class ContextManagers:
 _MANAGERS: Final[ContextManagers] = ContextManagers()
 
 read = _MANAGERS.read
-read_and_write = _MANAGERS.read_and_write
 write = _MANAGERS.write
diff --git a/atr/storage/writers/keys.py b/atr/storage/writers/keys.py
index c84d905..8b8683f 100644
--- a/atr/storage/writers/keys.py
+++ b/atr/storage/writers/keys.py
@@ -100,7 +100,7 @@ class FoundationCommitter:
             await self.__data.delete(key)
             await self.__data.commit()
             for committee in key.committees:
-                wacm = 
self.__write.as_committee_member(committee.name).result_or_none()
+                wacm = 
self.__write.as_committee_member_outcome(committee.name).result_or_none()
                 if wacm is None:
                     continue
                 await wacm.keys.autogenerate_keys_file()
diff --git a/atr/tasks/keys.py b/atr/tasks/keys.py
index 6fe5671..2b8740f 100644
--- a/atr/tasks/keys.py
+++ b/atr/tasks/keys.py
@@ -33,8 +33,7 @@ class ImportFile(schema.Strict):
 async def import_file(args: ImportFile) -> results.Results | None:
     """Import a KEYS file from a draft release candidate revision."""
     async with storage.write(args.asf_uid) as write:
-        access_outcome = await 
write.as_project_committee_member(args.project_name)
-        wacm = access_outcome.result_or_raise()
+        wacm = await write.as_project_committee_member(args.project_name)
         outcomes = await wacm.keys.import_keys_file(args.project_name, 
args.version_name)
         if outcomes.any_exception:
             # TODO: Log this? This code is unused anyway
diff --git a/docs/storage-interface.html b/docs/storage-interface.html
index 727a896..549d55f 100644
--- a/docs/storage-interface.html
+++ b/docs/storage-interface.html
@@ -9,12 +9,12 @@
 </ol>
 <p>Here is an actual example from our API code:</p>
 <pre><code class="language-python">async with storage.write(asf_uid) as write:
-    wafc = write.as_foundation_committer().writer_or_raise()
+    wafc = write.as_foundation_committer()
     ocr: types.Outcome[types.Key] = await wafc.keys.ensure_stored_one(data.key)
     key = ocr.result_or_raise()
 
     for selected_committee_name in selected_committee_names:
-        wacm = 
write.as_committee_member(selected_committee_name).writer_or_raise()
+        wacm = write.as_committee_member(selected_committee_name)
         outcome: types.Outcome[types.LinkedCommittee] = await 
wacm.keys.associate_fingerprint(
             key.key_model.fingerprint
         )
@@ -24,7 +24,7 @@
 <p>In this case we decide to raise as soon as there is any error. We could 
also choose instead to display a warning, ignore the error, etc.</p>
 <p>The first few lines in the context session show the classic three step 
approach. Here they are again with comments:</p>
 <pre><code class="language-python">    # 1. Request permissions
-    wafc = write.as_foundation_committer().writer_or_raise()
+    wafc = write.as_foundation_committer()
 
     # 2. Use the exposed functionality
     ocr: types.Outcome[types.Key] = await wafc.keys.ensure_stored_one(data.key)
diff --git a/docs/storage-interface.md b/docs/storage-interface.md
index 8710fb6..84f8b1a 100644
--- a/docs/storage-interface.md
+++ b/docs/storage-interface.md
@@ -14,12 +14,12 @@ Here is an actual example from our API code:
 
 ```python
 async with storage.write(asf_uid) as write:
-    wafc = write.as_foundation_committer().writer_or_raise()
+    wafc = write.as_foundation_committer()
     ocr: types.Outcome[types.Key] = await wafc.keys.ensure_stored_one(data.key)
     key = ocr.result_or_raise()
 
     for selected_committee_name in selected_committee_names:
-        wacm = 
write.as_committee_member(selected_committee_name).writer_or_raise()
+        wacm = write.as_committee_member(selected_committee_name)
         outcome: types.Outcome[types.LinkedCommittee] = await 
wacm.keys.associate_fingerprint(
             key.key_model.fingerprint
         )
@@ -34,7 +34,7 @@ The first few lines in the context session show the classic 
three step approach.
 
 ```python
     # 1. Request permissions
-    wafc = write.as_foundation_committer().writer_or_raise()
+    wafc = write.as_foundation_committer()
 
     # 2. Use the exposed functionality
     ocr: types.Outcome[types.Key] = await wafc.keys.ensure_stored_one(data.key)


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

Reply via email to