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 d3ad23d Rename and remove some API endpoints
d3ad23d is described below
commit d3ad23d122b85e860d959ee09e446126a673bf79
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue Jul 29 14:11:35 2025 +0100
Rename and remove some API endpoints
---
atr/blueprints/api/api.py | 140 +++++++++++++++-------------------------------
atr/models/api.py | 63 +++++++--------------
2 files changed, 66 insertions(+), 137 deletions(-)
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index 93a174c..6e5c005 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -361,39 +361,6 @@ async def jwt_create(data: models.api.JwtCreateArgs) ->
DictResponse:
).model_dump(), 200
-# TODO: Deprecate this endpoint
[email protected]("/keys")
-@quart_schema.validate_querystring(models.api.KeysQuery)
-@quart_schema.validate_response(models.api.KeysResults, 200)
-async def keys_endpoint(query_args: models.api.KeysQuery) -> DictResponse:
- """
- All public OpenPGP keys, with pagination support.
-
- Warning: this endpoint is deprecated.
- """
- # TODO: Rather than pagination, let's support keys by committee and by user
- # That way, consumers can scroll through committees or users
- # Which performs logical pagination, rather than arbitrary window
pagination
- _pagination_args_validate(query_args)
- via = sql.validate_instrumented_attribute
- async with db.session() as data:
- statement = (
- sqlmodel.select(sql.PublicSigningKey)
- .limit(query_args.limit)
- .offset(query_args.offset)
- .order_by(via(sql.PublicSigningKey.fingerprint).asc())
- )
- paged_keys = (await data.execute(statement)).scalars().all()
- count = (
- await
data.execute(sqlalchemy.select(sqlalchemy.func.count(via(sql.PublicSigningKey.fingerprint))))
- ).scalar_one()
- return models.api.KeysResults(
- endpoint="/keys",
- data=paged_keys,
- count=count,
- ).model_dump(), 200
-
-
@api.BLUEPRINT.route("/keys/add", methods=["POST"])
@jwtoken.require
@quart_schema.security_scheme([{"BearerAuth": []}])
@@ -461,22 +428,6 @@ async def keys_delete(data: models.api.KeysDeleteArgs) ->
DictResponse:
).model_dump(), 200
-# @api.BLUEPRINT.route("/keys/committee/<committee>")
-# @quart_schema.validate_response(models.api.KeysUserResults, 200)
-# async def keys_committee(committee: str) -> DictResponse:
-# """Return all public signing keys for a specific committee."""
-# _simple_check(committee)
-# async with db.session() as data:
-# committee_object = await data.committee(
-# name=committee, _public_signing_keys=True
-# ).demand(exceptions.NotFound(f"Committee '{committee}' was not
found"))
-# keys = committee_object.public_signing_keys
-# return models.api.KeysCommitteeResults(
-# endpoint="/keys/committee",
-# keys=keys,
-# ).model_dump(), 200
-
-
@api.BLUEPRINT.route("/keys/get/<fingerprint>")
@quart_schema.validate_response(models.api.KeysGetResults, 200)
async def keys_get(fingerprint: str) -> DictResponse:
@@ -569,68 +520,44 @@ async def keys_user(asf_uid: str) -> DictResponse:
).model_dump(), 200
-# TODO: Call this release/paths
[email protected]("/list/<project>/<version>")
[email protected]("/list/<project>/<version>/<revision>")
-@quart_schema.validate_response(models.api.ListResults, 200)
-async def list_endpoint(project: str, version: str, revision: str | None =
None) -> DictResponse:
- _simple_check(project, version, revision)
[email protected]("/projects/get/<name>")
+@quart_schema.validate_response(models.api.ProjectsGetResults, 200)
+async def projects_get(name: str) -> DictResponse:
+ _simple_check(name)
async with db.session() as data:
- release_name = sql.release_name(project, version)
- release = await
data.release(name=release_name).demand(exceptions.NotFound())
- if revision is None:
- dir_path = util.release_directory(release)
- else:
- await data.revision(release_name=release_name,
number=revision).demand(exceptions.NotFound())
- dir_path = util.release_directory_version(release) / revision
- if not (await aiofiles.os.path.isdir(dir_path)):
- raise exceptions.NotFound("Files not found")
- files: list[str] = [str(path) for path in [p async for p in
util.paths_recursive(dir_path)]]
- files.sort()
- return models.api.ListResults(
- endpoint="/list",
- rel_paths=files,
+ project = await data.project(name=name).demand(exceptions.NotFound())
+ return models.api.ProjectsGetResults(
+ endpoint="/projects/get",
+ project=project,
).model_dump(), 200
[email protected]("/project/<name>")
-@quart_schema.validate_response(models.api.ProjectResults, 200)
-async def project(name: str) -> DictResponse:
- _simple_check(name)
[email protected]("/projects/list")
+@quart_schema.validate_response(models.api.ProjectsListResults, 200)
+async def projects_list() -> DictResponse:
+ """List all projects in the database."""
+ # TODO: Add pagination?
async with db.session() as data:
- project = await data.project(name=name).demand(exceptions.NotFound())
- return models.api.ProjectResults(
- endpoint="/project",
- project=project,
+ projects = await data.project().all()
+ return models.api.ProjectsListResults(
+ endpoint="/projects/list",
+ projects=projects,
).model_dump(), 200
[email protected]("/project/releases/<name>")
-@quart_schema.validate_response(models.api.ProjectReleasesResults, 200)
-async def project_releases(name: str) -> DictResponse:
[email protected]("/projects/releases/<name>")
+@quart_schema.validate_response(models.api.ProjectsReleasesResults, 200)
+async def projects_releases(name: str) -> DictResponse:
"""List all releases for a specific project."""
_simple_check(name)
async with db.session() as data:
releases = await data.release(project_name=name).all()
- return models.api.ProjectReleasesResults(
- endpoint="/project/releases",
+ return models.api.ProjectsReleasesResults(
+ endpoint="/projects/releases",
releases=releases,
).model_dump(), 200
[email protected]("/projects")
-@quart_schema.validate_response(models.api.ProjectsResults, 200)
-async def projects() -> DictResponse:
- """List all projects in the database."""
- # TODO: Add pagination?
- async with db.session() as data:
- projects = await data.project().all()
- return models.api.ProjectsResults(
- endpoint="/projects",
- projects=projects,
- ).model_dump(), 200
-
-
@api.BLUEPRINT.route("/releases")
@quart_schema.validate_querystring(models.api.ReleasesQuery)
@quart_schema.validate_response(models.api.ReleasesResults, 200)
@@ -714,6 +641,29 @@ async def releases_delete(data:
models.api.ReleasesDeleteArgs) -> DictResponse:
).model_dump(), 200
[email protected]("/releases/paths/<project>/<version>")
[email protected]("/releases/paths/<project>/<version>/<revision>")
+@quart_schema.validate_response(models.api.ReleasesPathsResults, 200)
+async def release_paths(project: str, version: str, revision: str | None =
None) -> DictResponse:
+ _simple_check(project, version, revision)
+ async with db.session() as data:
+ release_name = sql.release_name(project, version)
+ release = await
data.release(name=release_name).demand(exceptions.NotFound())
+ if revision is None:
+ dir_path = util.release_directory(release)
+ else:
+ await data.revision(release_name=release_name,
number=revision).demand(exceptions.NotFound())
+ dir_path = util.release_directory_version(release) / revision
+ if not (await aiofiles.os.path.isdir(dir_path)):
+ raise exceptions.NotFound("Files not found")
+ files: list[str] = [str(path) for path in [p async for p in
util.paths_recursive(dir_path)]]
+ files.sort()
+ return models.api.ReleasesPathsResults(
+ endpoint="/releases/paths",
+ rel_paths=files,
+ ).model_dump(), 200
+
+
@api.BLUEPRINT.route("/releases/project/<project>")
@quart_schema.validate_querystring(models.api.ReleasesProjectQuery)
async def releases_project(project: str, query_args:
models.api.ReleasesProjectQuery) -> DictResponse:
diff --git a/atr/models/api.py b/atr/models/api.py
index 2abeb5f..61c82cc 100644
--- a/atr/models/api.py
+++ b/atr/models/api.py
@@ -99,11 +99,6 @@ class DraftDeleteResults(schema.Strict):
success: str = schema.Field(..., **example("Draft 'example-0.0.1'
deleted"))
-class ListResults(schema.Strict):
- endpoint: Literal["/list"] = schema.Field(alias="endpoint")
- rel_paths: Sequence[str]
-
-
class JwtCreateArgs(schema.Strict):
asfuid: str = schema.Field(..., **example("user"))
pat: str = schema.Field(...,
**example("8M5t4GCU63EdOy4NNXgXn7o-bc-muK8TRg5W-DeBaWY"))
@@ -115,18 +110,6 @@ class JwtCreateResults(schema.Strict):
jwt: str = schema.Field(...,
**example("eyJhbGciOiJIUzI1[...]mMjLiuyu5CSpyHI="))
[email protected]
-class KeysQuery:
- offset: int = 0
- limit: int = 20
-
-
-class KeysResults(schema.Strict):
- endpoint: Literal["/keys"] = schema.Field(alias="endpoint")
- data: Sequence[sql.PublicSigningKey]
- count: int = schema.Field(..., **example(10))
-
-
class KeysAddArgs(schema.Strict):
asfuid: str = schema.Field(..., **example("user"))
key: str = schema.Field(
@@ -141,11 +124,6 @@ class KeysAddResults(schema.Strict):
fingerprint: str = schema.Field(...,
**example("0123456789abcdef0123456789abcdef01234567"))
-# class KeysCommitteeResults(schema.Strict):
-# endpoint: Literal["/keys/committee"] = schema.Field(alias="endpoint")
-# keys: Sequence[sql.PublicSigningKey]
-
-
class KeysDeleteArgs(schema.Strict):
fingerprint: str = schema.Field(...,
**example("0123456789abcdef0123456789abcdef01234567"))
@@ -207,19 +185,19 @@ class KeysUserResults(schema.Strict):
keys: Sequence[sql.PublicSigningKey]
-class ProjectResults(schema.Strict):
- endpoint: Literal["/project"] = schema.Field(alias="endpoint")
+class ProjectsGetResults(schema.Strict):
+ endpoint: Literal["/projects/get"] = schema.Field(alias="endpoint")
project: sql.Project
-class ProjectReleasesResults(schema.Strict):
- endpoint: Literal["/project/releases"] = schema.Field(alias="endpoint")
- releases: Sequence[sql.Release]
+class ProjectsListResults(schema.Strict):
+ endpoint: Literal["/projects/list"] = schema.Field(alias="endpoint")
+ projects: Sequence[sql.Project]
-class ProjectsResults(schema.Strict):
- endpoint: Literal["/projects"] = schema.Field(alias="endpoint")
- projects: Sequence[sql.Project]
+class ProjectsReleasesResults(schema.Strict):
+ endpoint: Literal["/projects/releases"] = schema.Field(alias="endpoint")
+ releases: Sequence[sql.Release]
@dataclasses.dataclass
@@ -255,6 +233,11 @@ class ReleasesDeleteResults(schema.Strict):
deleted: str
+class ReleasesPathsResults(schema.Strict):
+ endpoint: Literal["/releases/paths"] = schema.Field(alias="endpoint")
+ rel_paths: Sequence[str]
+
+
@dataclasses.dataclass
class ReleasesProjectQuery:
limit: int = 20
@@ -426,20 +409,18 @@ Results = Annotated[
| CommitteesProjectsResults
| DraftDeleteResults
| JwtCreateResults
- | KeysResults
| KeysAddResults
| KeysDeleteResults
| KeysGetResults
- # | KeysCommitteeResults
| KeysUploadResults
| KeysUserResults
- | ListResults
- | ProjectResults
- | ProjectReleasesResults
- | ProjectsResults
+ | ProjectsGetResults
+ | ProjectsListResults
+ | ProjectsReleasesResults
| ReleasesResults
| ReleasesCreateResults
| ReleasesDeleteResults
+ | ReleasesPathsResults
| ReleasesProjectResults
| ReleasesVersionResults
| ReleasesRevisionsResults
@@ -479,20 +460,18 @@ validate_committees_list =
validator(CommitteesListResults)
validate_committees_projects = validator(CommitteesProjectsResults)
validate_draft_delete = validator(DraftDeleteResults)
validate_jwt_create = validator(JwtCreateResults)
-validate_keys = validator(KeysResults)
validate_keys_add = validator(KeysAddResults)
-# validate_keys_committee = validator(KeysCommitteeResults)
validate_keys_delete = validator(KeysDeleteResults)
validate_keys_get = validator(KeysGetResults)
validate_keys_upload = validator(KeysUploadResults)
validate_keys_user = validator(KeysUserResults)
-validate_list = validator(ListResults)
-validate_project = validator(ProjectResults)
-validate_project_releases = validator(ProjectReleasesResults)
-validate_projects = validator(ProjectsResults)
+validate_projects_get = validator(ProjectsGetResults)
+validate_projects_list = validator(ProjectsListResults)
+validate_projects_releases = validator(ProjectsReleasesResults)
validate_releases = validator(ReleasesResults)
validate_releases_create = validator(ReleasesCreateResults)
validate_releases_delete = validator(ReleasesDeleteResults)
+validate_releases_paths = validator(ReleasesPathsResults)
validate_releases_project = validator(ReleasesProjectResults)
validate_releases_version = validator(ReleasesVersionResults)
validate_releases_revisions = validator(ReleasesRevisionsResults)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]