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 2025/04/28 13:19:41 UTC

(tooling-trusted-release) branch main updated: Use a string primary key instead of an integer for Committee objects

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 0b31d0e  Use a string primary key instead of an integer for Committee objects
0b31d0e is described below

commit 0b31d0ebd6be1ea97182ee7241ef5140a003f664
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Mon Apr 28 14:18:29 2025 +0100

    Use a string primary key instead of an integer for Committee objects
---
 atr/db/__init__.py     | 15 ++++++---------
 atr/db/models.py       | 13 +++++++------
 atr/routes/keys.py     |  6 +++---
 atr/routes/preview.py  |  5 ++++-
 atr/routes/projects.py |  2 +-
 5 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/atr/db/__init__.py b/atr/db/__init__.py
index 9f94376..0fbc765 100644
--- a/atr/db/__init__.py
+++ b/atr/db/__init__.py
@@ -145,11 +145,10 @@ class Session(sqlalchemy.ext.asyncio.AsyncSession):
 
     def committee(
         self,
-        id: Opt[int] = NOT_SET,
         name: Opt[str] = NOT_SET,
         full_name: Opt[str] = NOT_SET,
         is_podling: Opt[bool] = NOT_SET,
-        parent_committee_id: Opt[int] = NOT_SET,
+        parent_committee_name: Opt[str] = NOT_SET,
         committee_members: Opt[list[str]] = NOT_SET,
         committers: Opt[list[str]] = NOT_SET,
         release_managers: Opt[list[str]] = NOT_SET,
@@ -160,16 +159,14 @@ class Session(sqlalchemy.ext.asyncio.AsyncSession):
     ) -> Query[models.Committee]:
         query = sqlmodel.select(models.Committee)
 
-        if is_defined(id):
-            query = query.where(models.Committee.id == id)
         if is_defined(name):
             query = query.where(models.Committee.name == name)
         if is_defined(full_name):
             query = query.where(models.Committee.full_name == full_name)
         if is_defined(is_podling):
             query = query.where(models.Committee.is_podling == is_podling)
-        if is_defined(parent_committee_id):
-            query = query.where(models.Committee.parent_committee_id == parent_committee_id)
+        if is_defined(parent_committee_name):
+            query = query.where(models.Committee.parent_committee_name == parent_committee_name)
         if is_defined(committee_members):
             query = query.where(models.Committee.committee_members == committee_members)
         if is_defined(committers):
@@ -276,7 +273,7 @@ class Session(sqlalchemy.ext.asyncio.AsyncSession):
         name: Opt[str] = NOT_SET,
         full_name: Opt[str] = NOT_SET,
         is_podling: Opt[bool] = NOT_SET,
-        committee_id: Opt[int] = NOT_SET,
+        committee_name: Opt[str] = NOT_SET,
         vote_policy_id: Opt[int] = NOT_SET,
         _committee: bool = False,
         _releases: bool = False,
@@ -293,8 +290,8 @@ class Session(sqlalchemy.ext.asyncio.AsyncSession):
             query = query.where(models.Project.full_name == full_name)
         if is_defined(is_podling):
             query = query.where(models.Project.is_podling == is_podling)
-        if is_defined(committee_id):
-            query = query.where(models.Project.committee_id == committee_id)
+        if is_defined(committee_name):
+            query = query.where(models.Project.committee_name == committee_name)
         if is_defined(vote_policy_id):
             query = query.where(models.Project.vote_policy_id == vote_policy_id)
 
diff --git a/atr/db/models.py b/atr/db/models.py
index 488b9c8..0b5ab57 100644
--- a/atr/db/models.py
+++ b/atr/db/models.py
@@ -75,7 +75,7 @@ class UserRole(str, enum.Enum):
 
 
 class KeyLink(sqlmodel.SQLModel, table=True):
-    committee_id: int = sqlmodel.Field(foreign_key="committee.id", primary_key=True)
+    committee_name: str = sqlmodel.Field(foreign_key="committee.name", primary_key=True)
     key_fingerprint: str = sqlmodel.Field(foreign_key="publicsigningkey.fingerprint", primary_key=True)
 
 
@@ -113,8 +113,9 @@ class VotePolicy(sqlmodel.SQLModel, table=True):
 
 
 class Committee(sqlmodel.SQLModel, table=True):
-    id: int = sqlmodel.Field(default=None, primary_key=True)
-    name: str = sqlmodel.Field(unique=True)
+    # TODO: Consider using key or label for primary string keys
+    # Then we can use simply "name" for full_name, and make it str rather than str | None
+    name: str = sqlmodel.Field(unique=True, primary_key=True)
     full_name: str | None = sqlmodel.Field(default=None)
     # True only if this is an incubator podling with a PPMC
     is_podling: bool = sqlmodel.Field(default=False)
@@ -122,10 +123,10 @@ class Committee(sqlmodel.SQLModel, table=True):
     # One-to-many: A committee can have multiple child committees, each child committee belongs to one parent committee
     child_committees: list["Committee"] = sqlmodel.Relationship(
         sa_relationship_kwargs=dict(
-            backref=sqlalchemy.orm.backref("parent_committee", remote_side="Committee.id"),
+            backref=sqlalchemy.orm.backref("parent_committee", remote_side="Committee.name"),
         ),
     )
-    parent_committee_id: int | None = sqlmodel.Field(default=None, foreign_key="committee.id")
+    parent_committee_name: str | None = sqlmodel.Field(default=None, foreign_key="committee.name")
     # One-to-many: A committee can have multiple projects, each project belongs to one committee
     projects: list["Project"] = sqlmodel.Relationship(back_populates="committee")
 
@@ -165,7 +166,7 @@ class Project(sqlmodel.SQLModel, table=True):
     programming_languages: str | None = sqlmodel.Field(default=None)
 
     # Many-to-one: A project belongs to one committee, a committee can have multiple projects
-    committee_id: int | None = sqlmodel.Field(default=None, foreign_key="committee.id")
+    committee_name: str | None = sqlmodel.Field(default=None, foreign_key="committee.name")
     committee: Committee | None = sqlmodel.Relationship(back_populates="projects")
 
     # One-to-many: A project can have multiple releases, each release belongs to one project
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 97e4173..2cd8ab0 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -295,11 +295,11 @@ async def key_user_session_add(
         committee_statuses: dict[str, str] = {}
         for committee_name in selected_committees:
             committee = await data.committee(name=committee_name).get()
-            if committee and committee.id:
+            if committee and committee.name:
                 # Check whether the link already exists
                 link_exists = await data.execute(
                     sqlmodel.select(models.KeyLink).where(
-                        models.KeyLink.committee_id == committee.id,
+                        models.KeyLink.committee_name == committee.name,
                         models.KeyLink.key_fingerprint == key_record.fingerprint,
                     )
                 )
@@ -307,7 +307,7 @@ async def key_user_session_add(
                     committee_statuses[committee_name] = "newly_linked"
                     # Link doesn't exist, create it
                     logging.debug(f"Linking key {fingerprint} to committee {committee_name}")
-                    link = models.KeyLink(committee_id=committee.id, key_fingerprint=key_record.fingerprint)
+                    link = models.KeyLink(committee_name=committee.name, key_fingerprint=key_record.fingerprint)
                     data.add(link)
                 else:
                     committee_statuses[committee_name] = "already_linked"
diff --git a/atr/routes/preview.py b/atr/routes/preview.py
index 82cc0fc..9bd74a9 100644
--- a/atr/routes/preview.py
+++ b/atr/routes/preview.py
@@ -77,7 +77,10 @@ async def delete(session: routes.CommitterSession) -> response.Response:
     async with db.session() as data:
         project = await data.project(name=project_name).get()
         if not project or not any(
-            (c.id == project.committee_id and (session.uid in c.committee_members or session.uid in c.committers))
+            (
+                (c.name == project.committee_name)
+                and ((session.uid in c.committee_members) or (session.uid in c.committers))
+            )
             for c in (await session.user_committees)
         ):
             return await session.redirect(root.index, error="You do not have access to this project")
diff --git a/atr/routes/projects.py b/atr/routes/projects.py
index 1609c8e..23fa74b 100644
--- a/atr/routes/projects.py
+++ b/atr/routes/projects.py
@@ -321,7 +321,7 @@ async def _add_project(form: AddFormProtocol, asf_id: str) -> response.Response:
             description=base_project.description,
             category=base_project.category,
             programming_languages=base_project.programming_languages,
-            committee_id=base_project.committee_id,
+            committee_name=base_project.committee_name,
             vote_policy_id=base_project.vote_policy_id,
             created=datetime.datetime.now(datetime.UTC),
             created_by=asf_id,


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