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-releases-client.git


The following commit(s) were added to refs/heads/main by this push:
     new 1ea88bc  Use shared models to construct API POST inputs
1ea88bc is described below

commit 1ea88bc10b6313b832d204ebf20874ea0c3e7f12
Author: Sean B. Palmer <[email protected]>
AuthorDate: Mon Jul 14 19:15:39 2025 +0100

    Use shared models to construct API POST inputs
---
 pyproject.toml                  |  4 ++--
 src/atrclient/client.py         | 48 ++++++++++++++++++++---------------------
 src/atrclient/models/api.py     | 27 ++++++++++-------------
 src/atrclient/models/results.py |  2 --
 src/atrclient/models/sql.py     |  7 +++---
 uv.lock                         |  4 ++--
 6 files changed, 42 insertions(+), 50 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index d40b09e..92faecd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ build-backend = "hatchling.build"
 
 [project]
 name            = "apache-trusted-releases"
-version         = "0.20250714.1626"
+version         = "0.20250714.1815"
 description     = "ATR CLI and Python API"
 readme          = "README.md"
 requires-python = ">=3.13"
@@ -72,4 +72,4 @@ select = [
 ]
 
 [tool.uv]
-exclude-newer = "2025-07-14T16:26:00Z"
+exclude-newer = "2025-07-14T18:15:00Z"
diff --git a/src/atrclient/client.py b/src/atrclient/client.py
index ff83aeb..d849695 100755
--- a/src/atrclient/client.py
+++ b/src/atrclient/client.py
@@ -292,9 +292,9 @@ def app_dev_user() -> None:
 def app_draft_delete(project: str, version: str, /) -> None:
     jwt_value = config_jwt_usable()
     host, verify_ssl = config_host_get()
-    payload: dict[str, str] = {"project_name": project, "version": version}
+    args = models.api.ProjectVersion(project=project, version=version)
     url = f"https://{host}/api/draft/delete";
-    result = asyncio.run(web_post(url, payload, jwt_value, verify_ssl))
+    result = asyncio.run(web_post(url, args, jwt_value, verify_ssl))
     print_json(result)
 
 
@@ -404,10 +404,8 @@ def app_release_start(project: str, version: str, /) -> 
None:
     jwt_value = config_jwt_usable()
     host, verify_ssl = config_host_get()
     url = f"https://{host}/api/releases/create";
-
-    payload: dict[str, str] = {"project_name": project, "version": version}
-
-    result = asyncio.run(web_post(url, payload, jwt_value, verify_ssl))
+    args = models.api.ProjectVersion(project=project, version=version)
+    result = asyncio.run(web_post(url, args, jwt_value, verify_ssl))
     print_json(result)
 
 
@@ -461,14 +459,14 @@ def app_upload(project: str, version: str, path: str, 
filepath: str, /) -> None:
     with open(filepath, "rb") as f:
         content = f.read()
 
-    payload: dict[str, str] = {
-        "project_name": project,
-        "version": version,
-        "rel_path": path,
-        "content": base64.b64encode(content).decode("utf-8"),
-    }
+    args = models.api.ProjectVersionRelpathContent(
+        project=project,
+        version=version,
+        relpath=path,
+        content=base64.b64encode(content).decode("utf-8"),
+    )
 
-    result = asyncio.run(web_post(url, payload, jwt_value, verify_ssl))
+    result = asyncio.run(web_post(url, args, jwt_value, verify_ssl))
     print_json(result)
 
 
@@ -490,16 +488,16 @@ def app_vote_start(
     if body:
         with open(body, encoding="utf-8") as f:
             body_text = f.read()
-    payload: dict[str, Any] = {
-        "project_name": project,
-        "version": version,
-        "revision": revision,
-        "email_to": mailing_list,
-        "vote_duration": duration,
-        "subject": subject or f"[VOTE] Release {project} {version}",
-        "body": body_text or f"Release {project} {version} is ready for 
voting.",
-    }
-    result = asyncio.run(web_post(url, payload, jwt_value, verify_ssl))
+    args = models.api.VoteStart(
+        project=project,
+        version=version,
+        revision=revision,
+        email_to=mailing_list,
+        vote_duration=duration,
+        subject=subject or f"[VOTE] Release {project} {version}",
+        body=body_text or f"Release {project} {version} is ready for voting.",
+    )
+    result = asyncio.run(web_post(url, args, jwt_value, verify_ssl))
     print_json(result)
 
 
@@ -988,11 +986,11 @@ async def web_get_public(url: str, verify_ssl: bool = 
True) -> JSON:
             return data
 
 
-async def web_post(url: str, payload: dict[str, Any], jwt_token: str, 
verify_ssl: bool = True) -> JSON:
+async def web_post(url: str, args: models.schema.Strict, jwt_token: str, 
verify_ssl: bool = True) -> JSON:
     connector = None if verify_ssl else aiohttp.TCPConnector(ssl=False)
     headers = {"Authorization": f"Bearer {jwt_token}"}
     async with aiohttp.ClientSession(connector=connector, headers=headers) as 
session:
-        async with session.post(url, json=payload) as resp:
+        async with session.post(url, json=args.model_dump()) as resp:
             if resp.status not in (200, 201):
                 text = await resp.text()
                 show_error_and_exit(f"Error message from the 
API:\n{resp.status} {url}\n{text}")
diff --git a/src/atrclient/models/api.py b/src/atrclient/models/api.py
index f88f552..bb668ac 100644
--- a/src/atrclient/models/api.py
+++ b/src/atrclient/models/api.py
@@ -38,34 +38,29 @@ class Task(Pagination):
     status: str | None = None
 
 
-class DraftDeleteRequest(schema.Strict):
-    project_name: str
-    version: str
+class AsfuidPat(schema.Strict):
+    asfuid: str
+    pat: str
 
 
-class FileUploadRequest(schema.Strict):
-    project_name: str
+class ProjectVersion(schema.Strict):
+    project: str
     version: str
-    rel_path: str
-    content: str
 
 
-class PATJWTRequest(schema.Strict):
-    asfuid: str
-    pat: str
-
-
-class ReleaseCreateRequest(schema.Strict):
-    project_name: str
+class ProjectVersionRelpathContent(schema.Strict):
+    project: str
     version: str
+    relpath: str
+    content: str
 
 
 class ResultCount(schema.Strict):
     count: int
 
 
-class VoteStartRequest(schema.Strict):
-    project_name: str
+class VoteStart(schema.Strict):
+    project: str
     version: str
     revision: str
     email_to: str
diff --git a/src/atrclient/models/results.py b/src/atrclient/models/results.py
index 735b4e6..5f6c6f6 100644
--- a/src/atrclient/models/results.py
+++ b/src/atrclient/models/results.py
@@ -21,8 +21,6 @@ from pydantic import TypeAdapter
 
 from . import schema
 
-# TODO: If we put this in atr.tasks.results, we get a circular import error
-
 
 class HashingCheck(schema.Strict):
     """Result of the task to check the hash of a file."""
diff --git a/src/atrclient/models/sql.py b/src/atrclient/models/sql.py
index e7caab7..dea5604 100644
--- a/src/atrclient/models/sql.py
+++ b/src/atrclient/models/sql.py
@@ -834,14 +834,15 @@ def validate_instrumented_attribute(obj: Any) -> 
orm.InstrumentedAttribute:
     return obj
 
 
-RELEASE_LATEST_REVISION_NUMBER: Final = orm.column_property(
+RELEASE_LATEST_REVISION_NUMBER: Final = (
     sqlalchemy.select(validate_instrumented_attribute(Revision.number))
     .where(validate_instrumented_attribute(Revision.release_name) == 
Release.name)
     .order_by(validate_instrumented_attribute(Revision.seq).desc())
     .limit(1)
     .correlate_except(Revision)
-    .scalar_subquery(),
+    .scalar_subquery()
 )
 
+
 # https://github.com/fastapi/sqlmodel/issues/240#issuecomment-2074161775
-Release._latest_revision_number = RELEASE_LATEST_REVISION_NUMBER
+Release._latest_revision_number = 
orm.column_property(RELEASE_LATEST_REVISION_NUMBER)
diff --git a/uv.lock b/uv.lock
index 74ad27b..30c2a88 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2,7 +2,7 @@ version = 1
 requires-python = ">=3.13"
 
 [options]
-exclude-newer = "2025-07-14T16:26:00Z"
+exclude-newer = "2025-07-14T18:15:00Z"
 
 [[package]]
 name = "aiohappyeyeballs"
@@ -83,7 +83,7 @@ wheels = [
 
 [[package]]
 name = "apache-trusted-releases"
-version = "0.20250714.1626"
+version = "0.20250714.1815"
 source = { editable = "." }
 dependencies = [
     { name = "aiohttp" },


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

Reply via email to