diff --git a/swh/web/api/apidoc.py b/swh/web/api/apidoc.py
--- a/swh/web/api/apidoc.py
+++ b/swh/web/api/apidoc.py
@@ -316,6 +316,7 @@
def api_doc(
route: str,
+ category: str,
noargs: bool = False,
tags: List[str] = [],
api_version: str = "1",
@@ -351,6 +352,7 @@
doc_desc = doc_data["description"]
APIUrls.add_doc_route(
route,
+ category,
re.split(r"\.\s", doc_desc)[0],
noargs=noargs,
api_version=api_version,
diff --git a/swh/web/api/apiurls.py b/swh/web/api/apiurls.py
--- a/swh/web/api/apiurls.py
+++ b/swh/web/api/apiurls.py
@@ -35,6 +35,7 @@
def add_doc_route(
cls,
route: str,
+ category: str,
docstring: str,
noargs: bool = False,
api_version: str = "1",
@@ -49,6 +50,7 @@
route_view_name = "api-%s-%s" % (api_version, route_name)
if route not in cls._apidoc_routes:
d = {
+ "category": category,
"docstring": docstring,
"route": "/api/%s%s" % (api_version, route),
"route_view_name": route_view_name,
@@ -60,7 +62,7 @@
def api_route(
url_pattern: str,
- view_name: Optional[str] = None,
+ view_name: str,
methods: List[str] = ["GET", "HEAD", "OPTIONS"],
throttle_scope: str = "swh_api",
api_version: str = "1",
diff --git a/swh/web/api/views/add_forge_now.py b/swh/web/api/views/add_forge_now.py
--- a/swh/web/api/views/add_forge_now.py
+++ b/swh/web/api/views/add_forge_now.py
@@ -107,7 +107,7 @@
"api-1-add-forge-request-create",
methods=["POST"],
)
-@api_doc("/add-forge/request/create")
+@api_doc("/add-forge/request/create", "request archival")
@format_docstring()
@transaction.atomic
def api_add_forge_request_create(request: Union[HttpRequest, Request]) -> HttpResponse:
@@ -190,7 +190,7 @@
"api-1-add-forge-request-update",
methods=["POST"],
)
-@api_doc("/add-forge/request/update", tags=["hidden"])
+@api_doc("/add-forge/request/update", "request archival", tags=["hidden"])
@format_docstring()
@transaction.atomic
def api_add_forge_request_update(
@@ -281,7 +281,7 @@
"api-1-add-forge-request-list",
methods=["GET"],
)
-@api_doc("/add-forge/request/list")
+@api_doc("/add-forge/request/list", "request archival")
@format_docstring()
def api_add_forge_request_list(request: Request):
"""
@@ -352,7 +352,7 @@
"api-1-add-forge-request-get",
methods=["GET"],
)
-@api_doc("/add-forge/request/get")
+@api_doc("/add-forge/request/get", "request archival")
@format_docstring()
def api_add_forge_request_get(request: Request, id: int):
"""
diff --git a/swh/web/api/views/content.py b/swh/web/api/views/content.py
--- a/swh/web/api/views/content.py
+++ b/swh/web/api/views/content.py
@@ -23,7 +23,7 @@
"api-1-content-filetype",
checksum_args=["q"],
)
-@api_doc("/content/filetype/")
+@api_doc("/content/filetype/", "metadata")
@format_docstring()
def api_content_filetype(request: Request, q: str):
"""
@@ -73,7 +73,7 @@
"api-1-content-language",
checksum_args=["q"],
)
-@api_doc("/content/language/")
+@api_doc("/content/language/", "metadata")
@format_docstring()
def api_content_language(request: Request, q: str):
"""
@@ -124,7 +124,7 @@
"api-1-content-license",
checksum_args=["q"],
)
-@api_doc("/content/license/")
+@api_doc("/content/license/", "metadata")
@format_docstring()
def api_content_license(request: Request, q: str):
"""
@@ -172,7 +172,7 @@
"api-1-content-raw",
checksum_args=["q"],
)
-@api_doc("/content/raw/")
+@api_doc("/content/raw/", "archive")
def api_content_raw(request: Request, q: str):
"""
.. http:get:: /api/1/content/[(hash_type):](hash)/raw/
@@ -218,7 +218,7 @@
@api_route(r"/content/known/search/", "api-1-content-known", methods=["POST"])
@api_route(r"/content/known/(?P(?!search).+)/", "api-1-content-known")
-@api_doc("/content/known/", tags=["hidden"])
+@api_doc("/content/known/", "archive", tags=["hidden"])
@format_docstring()
def api_check_content_known(request: Request, q: Optional[str] = None):
"""
@@ -288,7 +288,7 @@
@api_route(
r"/content/(?P[0-9a-z_:]*[0-9a-f]+)/", "api-1-content", checksum_args=["q"]
)
-@api_doc("/content/")
+@api_doc("/content/", "archive")
@format_docstring()
def api_content_metadata(request: Request, q: str):
"""
diff --git a/swh/web/api/views/directory.py b/swh/web/api/views/directory.py
--- a/swh/web/api/views/directory.py
+++ b/swh/web/api/views/directory.py
@@ -24,7 +24,7 @@
"api-1-directory",
checksum_args=["sha1_git"],
)
-@api_doc("/directory/")
+@api_doc("/directory/", "archive")
@format_docstring()
def api_directory(request: Request, sha1_git: str, path: Optional[str] = None):
"""
diff --git a/swh/web/api/views/graph.py b/swh/web/api/views/graph.py
--- a/swh/web/api/views/graph.py
+++ b/swh/web/api/views/graph.py
@@ -77,7 +77,7 @@
@api_route(r"/graph/", "api-1-graph-doc")
-@api_doc("/graph/")
+@api_doc("/graph/", "miscellaneous")
def api_graph(request: Request) -> None:
"""
.. http:get:: /api/1/graph/(graph_query)/
diff --git a/swh/web/api/views/identifiers.py b/swh/web/api/views/identifiers.py
--- a/swh/web/api/views/identifiers.py
+++ b/swh/web/api/views/identifiers.py
@@ -17,7 +17,7 @@
@api_route(r"/resolve/(?P.+)/", "api-1-resolve-swhid")
-@api_doc("/resolve/")
+@api_doc("/resolve/", "archive")
@format_docstring()
def api_resolve_swhid(request: Request, swhid: str):
"""
@@ -74,7 +74,7 @@
@api_route(r"/known/", "api-1-known", methods=["POST"])
-@api_doc("/known/")
+@api_doc("/known/", "archive")
@format_docstring()
def api_swhid_known(request: Request):
"""
diff --git a/swh/web/api/views/metadata.py b/swh/web/api/views/metadata.py
--- a/swh/web/api/views/metadata.py
+++ b/swh/web/api/views/metadata.py
@@ -26,7 +26,7 @@
f"/raw-extrinsic-metadata/swhid/(?P{SWHID_RE})/",
"api-1-raw-extrinsic-metadata-swhid",
)
-@api_doc("/raw-extrinsic-metadata/swhid/")
+@api_doc("/raw-extrinsic-metadata/swhid/", "metadata")
@format_docstring()
def api_raw_extrinsic_metadata_swhid(request: Request, target: str):
"""
@@ -223,7 +223,7 @@
f"/raw-extrinsic-metadata/swhid/(?P{SWHID_RE})/authorities/",
"api-1-raw-extrinsic-metadata-swhid-authorities",
)
-@api_doc("/raw-extrinsic-metadata/swhid/authorities/")
+@api_doc("/raw-extrinsic-metadata/swhid/authorities/", "metadata")
@format_docstring()
def api_raw_extrinsic_metadata_swhid_authorities(request: Request, target: str):
"""
@@ -290,7 +290,7 @@
"/raw-extrinsic-metadata/origin/(?P.*)/authorities/",
"api-1-raw-extrinsic-metadata-origin-authorities",
)
-@api_doc("/raw-extrinsic-metadata/origin/authorities/")
+@api_doc("/raw-extrinsic-metadata/origin/authorities/", "metadata")
@format_docstring()
def api_raw_extrinsic_metadata_origin_authorities(request: Request, origin_url: str):
"""
diff --git a/swh/web/api/views/origin.py b/swh/web/api/views/origin.py
--- a/swh/web/api/views/origin.py
+++ b/swh/web/api/views/origin.py
@@ -62,7 +62,7 @@
@api_route(r"/origins/", "api-1-origins")
-@api_doc("/origins/", noargs=True)
+@api_doc("/origins/", "archive", noargs=True)
@format_docstring(return_origin_array=DOC_RETURN_ORIGIN_ARRAY)
def api_origins(request: Request):
"""
@@ -117,7 +117,7 @@
@api_route(r"/origin/(?P.+)/get/", "api-1-origin")
-@api_doc("/origin/")
+@api_doc("/origin/", "archive")
@format_docstring(return_origin=DOC_RETURN_ORIGIN)
def api_origin(request: Request, origin_url: str):
"""
@@ -174,7 +174,7 @@
"api-1-origin-search",
throttle_scope="swh_api_origin_search",
)
-@api_doc("/origin/search/")
+@api_doc("/origin/search/", "archive")
@format_docstring(
return_origin_array=DOC_RETURN_ORIGIN_ARRAY, visit_types=_visit_types()
)
@@ -256,7 +256,7 @@
@api_route(r"/origin/metadata-search/", "api-1-origin-metadata-search")
-@api_doc("/origin/metadata-search/", noargs=True)
+@api_doc("/origin/metadata-search/", "metadata", noargs=True)
@format_docstring(return_origin_array=DOC_RETURN_ORIGIN_ARRAY)
def api_origin_metadata_search(request: Request):
"""
@@ -300,7 +300,7 @@
@api_route(r"/origin/(?P.+)/visits/", "api-1-origin-visits")
-@api_doc("/origin/visits/")
+@api_doc("/origin/visits/", "archive")
@format_docstring(return_origin_visit_array=DOC_RETURN_ORIGIN_VISIT_ARRAY)
def api_origin_visits(request: Request, origin_url: str):
"""
@@ -392,7 +392,7 @@
"api-1-origin-visit-latest",
throttle_scope="swh_api_origin_visit_latest",
)
-@api_doc("/origin/visit/latest/")
+@api_doc("/origin/visit/latest/", "archive")
@format_docstring(return_origin_visit=DOC_RETURN_ORIGIN_VISIT)
def api_origin_visit_latest(request: Request, origin_url: str):
"""
@@ -436,7 +436,7 @@
@api_route(
r"/origin/(?P.+)/visit/(?P[0-9]+)/", "api-1-origin-visit"
)
-@api_doc("/origin/visit/")
+@api_doc("/origin/visit/", "archive")
@format_docstring(return_origin_visit=DOC_RETURN_ORIGIN_VISIT)
def api_origin_visit(request: Request, visit_id: str, origin_url: str):
"""
@@ -478,7 +478,7 @@
@api_route(
r"/origin/(?P.+)/intrinsic-metadata/", "api-origin-intrinsic-metadata"
)
-@api_doc("/origin/intrinsic-metadata/")
+@api_doc("/origin/intrinsic-metadata/", "metadata")
@format_docstring()
def api_origin_intrinsic_metadata(request: Request, origin_url: str):
"""
diff --git a/swh/web/api/views/origin_save.py b/swh/web/api/views/origin_save.py
--- a/swh/web/api/views/origin_save.py
+++ b/swh/web/api/views/origin_save.py
@@ -40,7 +40,7 @@
throttle_scope="swh_save_origin",
never_cache=True,
)
-@api_doc("/origin/save/")
+@api_doc("/origin/save/", "request archival")
@format_docstring(visit_types=_savable_visit_types())
def api_save_origin(request: Request, visit_type: str, origin_url: str):
"""
diff --git a/swh/web/api/views/ping.py b/swh/web/api/views/ping.py
--- a/swh/web/api/views/ping.py
+++ b/swh/web/api/views/ping.py
@@ -10,7 +10,7 @@
@api_route(r"/ping/", "api-1-ping")
-@api_doc("/ping/", noargs=True)
+@api_doc("/ping/", "miscellaneous", noargs=True)
def ping(request: Request):
"""
.. http:get:: /api/1/ping/
diff --git a/swh/web/api/views/raw.py b/swh/web/api/views/raw.py
--- a/swh/web/api/views/raw.py
+++ b/swh/web/api/views/raw.py
@@ -32,7 +32,7 @@
"api-1-raw-object",
throttle_scope="swh_raw_object",
)
-@api_doc("/raw/")
+@api_doc("/raw/", "archive")
@format_docstring()
def api_raw_object(request: Request, swhid: str):
"""
diff --git a/swh/web/api/views/release.py b/swh/web/api/views/release.py
--- a/swh/web/api/views/release.py
+++ b/swh/web/api/views/release.py
@@ -15,7 +15,7 @@
@api_route(
r"/release/(?P[0-9a-f]+)/", "api-1-release", checksum_args=["sha1_git"]
)
-@api_doc("/release/")
+@api_doc("/release/", "archive")
@format_docstring()
def api_release(request: Request, sha1_git: str):
"""
diff --git a/swh/web/api/views/revision.py b/swh/web/api/views/revision.py
--- a/swh/web/api/views/revision.py
+++ b/swh/web/api/views/revision.py
@@ -42,7 +42,7 @@
@api_route(
r"/revision/(?P[0-9a-f]+)/", "api-1-revision", checksum_args=["sha1_git"]
)
-@api_doc("/revision/")
+@api_doc("/revision/", "archive")
@format_docstring(return_revision=DOC_RETURN_REVISION)
def api_revision(request: Request, sha1_git: str):
"""
@@ -85,7 +85,7 @@
"api-1-revision-raw-message",
checksum_args=["sha1_git"],
)
-@api_doc("/revision/raw/", tags=["hidden"])
+@api_doc("/revision/raw/", "archive", tags=["hidden"])
def api_revision_raw_message(request: Request, sha1_git: str):
"""Return the raw data of the message of revision identified by sha1_git"""
raw = archive.lookup_revision_message(sha1_git)
@@ -104,7 +104,7 @@
"api-1-revision-directory",
checksum_args=["sha1_git"],
)
-@api_doc("/revision/directory/")
+@api_doc("/revision/directory/", "archive")
@format_docstring()
def api_revision_directory(
request: Request, sha1_git: str, dir_path: Optional[str] = None
@@ -162,7 +162,7 @@
"api-1-revision-log",
checksum_args=["sha1_git"],
)
-@api_doc("/revision/log/")
+@api_doc("/revision/log/", "archive")
@format_docstring(return_revision_array=DOC_RETURN_REVISION_ARRAY)
def api_revision_log(request: Request, sha1_git: str):
"""
diff --git a/swh/web/api/views/snapshot.py b/swh/web/api/views/snapshot.py
--- a/swh/web/api/views/snapshot.py
+++ b/swh/web/api/views/snapshot.py
@@ -19,7 +19,7 @@
"api-1-snapshot",
checksum_args=["snapshot_id"],
)
-@api_doc("/snapshot/")
+@api_doc("/snapshot/", "archive")
@format_docstring()
def api_snapshot(request: Request, snapshot_id: str):
"""
diff --git a/swh/web/api/views/stat.py b/swh/web/api/views/stat.py
--- a/swh/web/api/views/stat.py
+++ b/swh/web/api/views/stat.py
@@ -11,7 +11,7 @@
@api_route(r"/stat/counters/", "api-1-stat-counters")
-@api_doc("/stat/counters/", noargs=True)
+@api_doc("/stat/counters/", "miscellaneous", noargs=True)
@format_docstring()
def api_stats(request: Request):
"""
diff --git a/swh/web/api/views/utils.py b/swh/web/api/views/utils.py
--- a/swh/web/api/views/utils.py
+++ b/swh/web/api/views/utils.py
@@ -83,9 +83,18 @@
@api_route(r"/", "api-1-endpoints")
def api_endpoints(request):
"""Display the list of opened api endpoints."""
- routes = APIUrls.get_app_endpoints().copy()
- for route, doc in routes.items():
+ routes_by_category = {}
+ for route, doc in APIUrls.get_app_endpoints().items():
doc["doc_intro"] = doc["docstring"].split("\n\n")[0]
- # Return a list of routes with consistent ordering
- env = {"doc_routes": sorted(routes.items())}
+ routes_by_category.setdefault(doc["category"], []).append(doc)
+
+ for routes in routes_by_category.values():
+ routes.sort(key=lambda route: route["route"])
+
+ # sort routes by alphabetical category name, with 'miscellaneous' at the end
+ misc_routes = routes_by_category.pop("miscellaneous")
+ sorted_routes = sorted(routes_by_category.items())
+ sorted_routes.append(("miscellaneous", misc_routes))
+
+ env = {"doc_routes": sorted_routes}
return Response(env, template_name="api/endpoints.html")
diff --git a/swh/web/api/views/vault.py b/swh/web/api/views/vault.py
--- a/swh/web/api/views/vault.py
+++ b/swh/web/api/views/vault.py
@@ -73,7 +73,7 @@
throttle_scope="swh_vault_cooking",
never_cache=True,
)
-@api_doc("/vault/flat/")
+@api_doc("/vault/flat/", "batch download")
@format_docstring()
def api_vault_cook_flat(request: Request, swhid: str):
"""
@@ -148,7 +148,7 @@
throttle_scope="swh_vault_cooking",
never_cache=True,
)
-@api_doc("/vault/directory/", tags=["deprecated"])
+@api_doc("/vault/directory/", "batch download", tags=["deprecated"])
@format_docstring()
def api_vault_cook_directory(request: Request, dir_id: str):
"""
@@ -174,7 +174,7 @@
f"/vault/flat/(?P{SWHID_RE})/raw/",
"api-1-vault-fetch-flat",
)
-@api_doc("/vault/flat/raw/")
+@api_doc("/vault/flat/raw/", "batch download")
def api_vault_fetch_flat(request: Request, swhid: str):
"""
.. http:get:: /api/1/vault/flat/(swhid)/raw/
@@ -213,7 +213,7 @@
"api-1-vault-fetch-directory",
checksum_args=["dir_id"],
)
-@api_doc("/vault/directory/raw/", tags=["hidden", "deprecated"])
+@api_doc("/vault/directory/raw/", "batch download", tags=["hidden", "deprecated"])
def api_vault_fetch_directory(request: Request, dir_id: str):
"""
.. http:get:: /api/1/vault/directory/(dir_id)/raw/
@@ -240,7 +240,7 @@
throttle_scope="swh_vault_cooking",
never_cache=True,
)
-@api_doc("/vault/gitfast/")
+@api_doc("/vault/gitfast/", "batch download")
@format_docstring()
def api_vault_cook_gitfast(request: Request, swhid: str):
"""
@@ -315,7 +315,7 @@
throttle_scope="swh_vault_cooking",
never_cache=True,
)
-@api_doc("/vault/revision/gitfast/", tags=["deprecated"])
+@api_doc("/vault/revision/gitfast/", "batch download", tags=["deprecated"])
@format_docstring()
def api_vault_cook_revision_gitfast(request: Request, rev_id: str):
"""
@@ -341,7 +341,7 @@
f"/vault/gitfast/(?P{SWHID_RE})/raw/",
"api-1-vault-fetch-gitfast",
)
-@api_doc("/vault/gitfast/raw/")
+@api_doc("/vault/gitfast/raw/", "batch download")
def api_vault_fetch_revision_gitfast(request: Request, swhid: str):
"""
.. http:get:: /api/1/vault/gitfast/(swhid)/raw/
@@ -380,7 +380,7 @@
"api-1-vault-fetch-revision_gitfast",
checksum_args=["rev_id"],
)
-@api_doc("/vault/revision_gitfast/raw/", tags=["hidden", "deprecated"])
+@api_doc("/vault/revision_gitfast/raw/", "batch download", tags=["hidden", "deprecated"])
def _api_vault_revision_gitfast_raw(request: Request, rev_id: str):
"""
.. http:get:: /api/1/vault/revision/(rev_id)/gitfast/raw/
@@ -404,7 +404,7 @@
throttle_scope="swh_vault_cooking",
never_cache=True,
)
-@api_doc("/vault/git-bare/")
+@api_doc("/vault/git-bare/", "batch download")
@format_docstring()
def api_vault_cook_git_bare(request: Request, swhid: str):
"""
@@ -479,7 +479,7 @@
f"/vault/git-bare/(?P{SWHID_RE})/raw/",
"api-1-vault-fetch-git-bare",
)
-@api_doc("/vault/git-bare/raw/")
+@api_doc("/vault/git-bare/raw/", "batch download")
def api_vault_fetch_revision_git_bare(request: Request, swhid: str):
"""
.. http:get:: /api/1/vault/git-bare/(swhid)/raw/
diff --git a/swh/web/templates/api/endpoints.html b/swh/web/templates/api/endpoints.html
--- a/swh/web/templates/api/endpoints.html
+++ b/swh/web/templates/api/endpoints.html
@@ -36,7 +36,9 @@
-
+{% for category, routes in doc_routes %}
+
{{ category }}
+
@@ -44,14 +46,14 @@
Description |
- {% for route, doc in doc_routes %}
+ {% for doc in routes %}
{% if "upcoming" in doc.tags %}
-
+ |
{% url doc.route_view_name %}
|
{% else %}
-
+ |
{{ doc.route }}
@@ -67,17 +69,10 @@
{% endfor %}
|
-
+{% endfor %}
{% endblock %}
diff --git a/swh/web/tests/api/test_apidoc.py b/swh/web/tests/api/test_apidoc.py
--- a/swh/web/tests/api/test_apidoc.py
+++ b/swh/web/tests/api/test_apidoc.py
@@ -81,13 +81,13 @@
def test_apidoc_nodoc_failure():
with pytest.raises(Exception):
- @api_doc("/my/nodoc/url/")
+ @api_doc("/my/nodoc/url/", "test")
def apidoc_nodoc_tester(request, arga=0, argb=0):
return Response(arga + argb)
@api_route(r"/some/(?P[0-9]+)/(?P[0-9]+)/", "api-1-some-doc-route")
-@api_doc("/some/doc/route/")
+@api_doc("/some/doc/route/", "test")
def apidoc_route(request, myarg, myotherarg, akw=0):
"""
Sample doc
@@ -108,7 +108,7 @@
@api_route(r"/test/error/(?P.+)/", "api-1-test-error")
-@api_doc("/test/error/")
+@api_doc("/test/error/", "test")
def apidoc_test_error_route(request, exc_name):
"""
Sample doc
@@ -128,7 +128,7 @@
r"/some/full/(?P[0-9]+)/(?P[0-9]+)/",
"api-1-some-complete-doc-route",
)
-@api_doc("/some/complete/doc/route/")
+@api_doc("/some/complete/doc/route/", "test")
def apidoc_full_stack(request, myarg, myotherarg, akw=0):
"""
Sample doc
@@ -151,7 +151,7 @@
@api_route(r"/test/post/only/", "api-1-test-post-only", methods=["POST"])
-@api_doc("/test/post/only/")
+@api_doc("/test/post/only/", "test")
def apidoc_test_post_only(request, exc_name):
"""
Sample doc
@@ -343,7 +343,7 @@
@api_route(r"/post/endpoint/", "api-1-post-endpoint", methods=["POST"])
-@api_doc("/post/endpoint/")
+@api_doc("/post/endpoint/", "test")
def apidoc_test_post_endpoint(request):
"""
.. http:post:: /api/1/post/endpoint/
@@ -433,7 +433,7 @@
@api_route(r"/endpoint/links/in/doc/", "api-1-endpoint-links-in-doc")
-@api_doc("/endpoint/links/in/doc/")
+@api_doc("/endpoint/links/in/doc/", "test")
def apidoc_test_endpoint_with_links_in_doc(request):
"""
.. http:get:: /api/1/post/endpoint/