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 2b12d77 Move code to record a user vote to the vote writer
2b12d77 is described below
commit 2b12d779d30eec147ed552c85c36be24ff021f6b
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Sep 11 18:44:27 2025 +0100
Move code to record a user vote to the vote writer
---
atr/routes/vote.py | 57 ++------------------------------------------
atr/storage/__init__.py | 9 +++++++
atr/storage/writers/vote.py | 58 +++++++++++++++++++++++++++++++++++++++++----
3 files changed, 65 insertions(+), 59 deletions(-)
diff --git a/atr/routes/vote.py b/atr/routes/vote.py
index bed8378..cb1ce7d 100644
--- a/atr/routes/vote.py
+++ b/atr/routes/vote.py
@@ -18,7 +18,6 @@
import quart
import werkzeug.wrappers.response as response
-import atr.db as db
import atr.db.interaction as interaction
import atr.forms as forms
import atr.log as log
@@ -27,7 +26,6 @@ import atr.models.sql as sql
import atr.routes as routes
import atr.routes.compose as compose
import atr.storage as storage
-import atr.tasks.message as message
import atr.util as util
@@ -147,7 +145,8 @@ async def selected_post(session: routes.CommitterSession,
project_name: str, ver
if await form.validate_on_submit():
vote = str(form.vote_value.data)
comment = str(form.vote_comment.data)
- email_recipient, error_message = await _send_vote(session, release,
vote, comment)
+ async with
storage.write_as_committee_participant(release.committee.name) as wacm:
+ email_recipient, error_message = await
wacm.vote.send_user_vote(release, vote, comment, session.fullname)
if error_message:
return await session.redirect(
selected, project_name=project_name,
version_name=version_name, error=error_message
@@ -166,55 +165,3 @@ async def selected_post(session: routes.CommitterSession,
project_name: str, ver
return await session.redirect(
selected, project_name=project_name, version_name=version_name,
error=error_message
)
-
-
-async def _send_vote(
- session: routes.CommitterSession,
- release: sql.Release,
- vote: str,
- comment: str,
-) -> tuple[str, str]:
- # Get the email thread
- latest_vote_task = await interaction.release_latest_vote_task(release)
- if latest_vote_task is None:
- return "", "No vote task found."
- vote_thread_mid = interaction.task_mid_get(latest_vote_task)
- if vote_thread_mid is None:
- return "", "No vote thread found."
-
- # Construct the reply email
- original_subject = latest_vote_task.task_args["subject"]
-
- # Arguments for the task to cast a vote
- email_recipient = latest_vote_task.task_args["email_to"]
- email_sender = f"{session.uid}@apache.org"
- subject = f"Re: {original_subject}"
- body = [f"{vote.lower()} ({session.uid}) {session.fullname}"]
- if comment:
- body.append(f"{comment}")
- # Only include the signature if there is a comment
- body.append(f"-- \n{session.fullname} ({session.uid})")
- body_text = "\n\n".join(body)
- in_reply_to = vote_thread_mid
-
- # TODO: Move this to the storage interface
- task = sql.Task(
- status=sql.TaskStatus.QUEUED,
- task_type=sql.TaskType.MESSAGE_SEND,
- task_args=message.Send(
- email_sender=email_sender,
- email_recipient=email_recipient,
- subject=subject,
- body=body_text,
- in_reply_to=in_reply_to,
- ).model_dump(),
- asf_uid=util.unwrap(session.uid),
- project_name=release.project.name,
- version_name=release.version,
- )
- async with db.session() as data:
- data.add(task)
- await data.flush()
- await data.commit()
-
- return email_recipient, ""
diff --git a/atr/storage/__init__.py b/atr/storage/__init__.py
index 4b195f9..86b1dc4 100644
--- a/atr/storage/__init__.py
+++ b/atr/storage/__init__.py
@@ -446,6 +446,15 @@ async def write_as_committee_member(
yield w.as_committee_member(committee_name)
[email protected]
+async def write_as_committee_participant(
+ committee_name: str,
+ asf_uid: str | None | ArgumentNoneType = ArgumentNone,
+) -> AsyncGenerator[WriteAsCommitteeParticipant]:
+ async with write(asf_uid) as w:
+ yield w.as_committee_participant(committee_name)
+
+
@contextlib.asynccontextmanager
async def write_as_project_committee_member(
project_name: str,
diff --git a/atr/storage/writers/vote.py b/atr/storage/writers/vote.py
index 416f343..424e876 100644
--- a/atr/storage/writers/vote.py
+++ b/atr/storage/writers/vote.py
@@ -29,7 +29,6 @@ import atr.revision as revision
import atr.storage as storage
import atr.tasks.message as message
import atr.tasks.vote as tasks_vote
-import atr.user as user
import atr.util as util
@@ -76,6 +75,57 @@ class CommitteeParticipant(FoundationCommitter):
self.__asf_uid = asf_uid
self.__committee_name = committee_name
+ async def send_user_vote(
+ self,
+ release: sql.Release,
+ vote: str,
+ comment: str,
+ fullname: str,
+ ) -> tuple[str, str]:
+ # Get the email thread
+ latest_vote_task = await interaction.release_latest_vote_task(release)
+ if latest_vote_task is None:
+ return "", "No vote task found."
+ vote_thread_mid = interaction.task_mid_get(latest_vote_task)
+ if vote_thread_mid is None:
+ return "", "No vote thread found."
+
+ # Construct the reply email
+ original_subject = latest_vote_task.task_args["subject"]
+
+ # Arguments for the task to cast a vote
+ email_recipient = latest_vote_task.task_args["email_to"]
+ email_sender = f"{self.__asf_uid}@apache.org"
+ subject = f"Re: {original_subject}"
+ body = [f"{vote.lower()} ({self.__asf_uid}) {fullname}"]
+ if comment:
+ body.append(f"{comment}")
+ # Only include the signature if there is a comment
+ body.append(f"-- \n{fullname} ({self.__asf_uid})")
+ body_text = "\n\n".join(body)
+ in_reply_to = vote_thread_mid
+
+ # TODO: Move this to the storage interface
+ task = sql.Task(
+ status=sql.TaskStatus.QUEUED,
+ task_type=sql.TaskType.MESSAGE_SEND,
+ task_args=message.Send(
+ email_sender=email_sender,
+ email_recipient=email_recipient,
+ subject=subject,
+ body=body_text,
+ in_reply_to=in_reply_to,
+ ).model_dump(),
+ asf_uid=self.__asf_uid,
+ project_name=release.project.name,
+ version_name=release.version,
+ )
+ self.__data.add(task)
+ await self.__data.flush()
+ await self.__data.commit()
+
+ return email_recipient, ""
+
class CommitteeMember(CommitteeParticipant):
def __init__(
@@ -377,6 +427,6 @@ class CommitteeMember(CommitteeParticipant):
# (The message should be shown on the vote resolution page)
return task
- def __committee_member_or_admin(self, committee: sql.Committee, asf_uid:
str) -> None:
- if not (user.is_committee_member(committee, asf_uid) or
user.is_admin(asf_uid)):
- raise storage.AccessError("You do not have permission to perform
this action")
+ # def __committee_member_or_admin(self, committee: sql.Committee, asf_uid:
str) -> None:
+ # if not (user.is_committee_member(committee, asf_uid) or
user.is_admin(asf_uid)):
+ # raise storage.AccessError("You do not have permission to perform
this action")
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]