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

arm 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 7a934b2a #1013 - use DB IntegrityError to warn user their project 
already exists. Fix small form validation bug.
7a934b2a is described below

commit 7a934b2a00fb4a7def022046a7cba95d7bf0587b
Author: Alastair McFarlane <[email protected]>
AuthorDate: Fri Apr 3 15:03:45 2026 +0100

    #1013 - use DB IntegrityError to warn user their project already exists. 
Fix small form validation bug.
---
 atr/form.py                    | 11 ++++++-----
 atr/storage/writers/project.py | 28 ++++++++++++++++++++--------
 2 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/atr/form.py b/atr/form.py
index 507e12bf..29df179f 100644
--- a/atr/form.py
+++ b/atr/form.py
@@ -109,11 +109,12 @@ def flash_error_data(
             # This comes from raising a `ValueError` in a 
`pydantic.model_validator`
             if isinstance(ctx_error, ValueError) and len(ctx_error.args) >= 2 
and isinstance(ctx_error.args[1], str):
                 loc = (ctx_error.args[1],)
-                msg = ctx_error.args[0]
-            # Now reconstruct the field_name and label
-            field_name, field_label = name_and_label(concrete_cls, i, loc)
-            if isinstance(original, dict):
-                original = original[field_name]
+                if loc:
+                    msg = ctx_error.args[0]
+                    # Now reconstruct the field_name and label
+                    field_name, field_label = name_and_label(concrete_cls, i, 
loc)
+                    if isinstance(original, dict):
+                        original = original[field_name]
         msg = msg.replace(": An email address", " because an email address")
         msg = msg.replace("Value error, ", "")
 
diff --git a/atr/storage/writers/project.py b/atr/storage/writers/project.py
index a107c4d3..2b532b8f 100644
--- a/atr/storage/writers/project.py
+++ b/atr/storage/writers/project.py
@@ -19,6 +19,9 @@
 from __future__ import annotations
 
 import datetime
+import sqlite3
+
+import sqlalchemy.exc
 
 import atr.db as db
 import atr.models.safe as safe
@@ -150,7 +153,6 @@ class CommitteeMember(CommitteeParticipant):
         if await self.__data.project(key=label).get():
             raise storage.AccessError(f"Project {label} already exists")
 
-        # TODO: Fix the potential race condition here
         project = sql.Project(
             key=label,
             name=display_name,
@@ -167,13 +169,23 @@ class CommitteeMember(CommitteeParticipant):
         if super_project and super_project.release_policy:
             project.release_policy = super_project.release_policy.duplicate()
 
-        self.__data.add(project)
-        await self.__data.commit()
-        self.__write_as.append_to_audit_log(
-            asf_uid=self.__asf_uid,
-            committee_key=str(committee_key),
-            project_key=label,
-        )
+        try:
+            self.__data.add(project)
+            await self.__data.commit()
+            self.__write_as.append_to_audit_log(
+                asf_uid=self.__asf_uid,
+                committee_key=str(committee_key),
+                project_key=label,
+            )
+        except sqlalchemy.exc.IntegrityError as e:
+            if (
+                isinstance(e.orig, sqlite3.IntegrityError)
+                and (e.orig.sqlite_errorcode == 
sqlite3.SQLITE_CONSTRAINT_PRIMARYKEY)
+                and ("project.key" in str(e.orig))
+            ):
+                raise storage.AccessError(f"Project {label} already exists")
+            else:
+                raise
 
     async def delete(self, project_key: safe.ProjectKey) -> None:
         project = await self.__data.project(


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

Reply via email to