diff --git a/assets/src/bundles/origin/visits-reporting.js b/assets/src/bundles/origin/visits-reporting.js
--- a/assets/src/bundles/origin/visits-reporting.js
+++ b/assets/src/bundles/origin/visits-reporting.js
@@ -112,8 +112,8 @@
// process input visits
let firstFullVisit;
allVisits.forEach((v, i) => {
- // Turn Unix epoch into Javascript Date object
- v.date = new Date(Math.floor(v.date * 1000));
+ // Turn Python ISO8601 string date into Javascript UTC Date object
+ v.date = new Date(v.date.slice(0, -6));
const visitLink = '' + v.formatted_date + '';
if (v.status === 'full') {
if (!firstFullVisit) {
diff --git a/swh/web/browse/snapshot_context.py b/swh/web/browse/snapshot_context.py
--- a/swh/web/browse/snapshot_context.py
+++ b/swh/web/browse/snapshot_context.py
@@ -8,6 +8,7 @@
from collections import defaultdict
from typing import Any, Dict, List, Optional, Tuple
+from django.http import HttpRequest, HttpResponse
from django.shortcuts import render
from django.utils.html import escape
@@ -48,7 +49,9 @@
_empty_snapshot_id = Snapshot(branches={}).id.hex()
-def _get_branch(branches, branch_name, snapshot_id):
+def _get_branch(
+ branches: List[SnapshotBranchInfo], branch_name: str, snapshot_id: str
+) -> Optional[SnapshotBranchInfo]:
"""
Utility function to get a specific branch from a snapshot.
Returns None if the branch cannot be found.
@@ -71,9 +74,12 @@
if snp_branch and snp_branch[0]["name"] == branch_name:
branches.append(snp_branch[0])
return snp_branch[0]
+ return None
-def _get_release(releases, release_name, snapshot_id):
+def _get_release(
+ releases: List[SnapshotReleaseInfo], release_name: Optional[str], snapshot_id: str
+) -> Optional[SnapshotReleaseInfo]:
"""
Utility function to get a specific release from a snapshot.
Returns None if the release cannot be found.
@@ -81,7 +87,7 @@
filtered_releases = [r for r in releases if r["name"] == release_name]
if filtered_releases:
return filtered_releases[0]
- else:
+ elif release_name:
# case where a large branches list has been truncated
try:
# git origins have specific branches for releases
@@ -102,11 +108,18 @@
if snp_release and snp_release[0]["name"] == release_name:
releases.append(snp_release[0])
return snp_release[0]
+ return None
def _branch_not_found(
- branch_type, branch, snapshot_id, snapshot_sizes, origin_info, timestamp, visit_id
-):
+ branch_type: str,
+ branch: str,
+ snapshot_id: str,
+ snapshot_sizes: Dict[str, int],
+ origin_info: Optional[OriginInfo],
+ timestamp: Optional[str],
+ visit_id: Optional[int],
+) -> None:
"""
Utility function to raise an exception when a specified branch/release
can not be found.
@@ -131,25 +144,25 @@
branch,
snapshot_id,
)
- elif visit_id and snapshot_sizes[target_type] == 0:
+ elif visit_id and snapshot_sizes[target_type] == 0 and origin_info:
msg = (
"Origin with url %s"
" for visit with id %s has an empty list"
" of %s!" % (origin_info["url"], visit_id, branch_type_plural)
)
- elif visit_id:
+ elif visit_id and origin_info:
msg = (
"%s %s associated to visit with"
" id %s for origin with url %s"
" not found!" % (branch_type, branch, visit_id, origin_info["url"])
)
- elif snapshot_sizes[target_type] == 0:
+ elif snapshot_sizes[target_type] == 0 and origin_info and timestamp:
msg = (
"Origin with url %s"
" for visit with timestamp %s has an empty list"
" of %s!" % (origin_info["url"], timestamp, branch_type_plural)
)
- else:
+ elif origin_info and timestamp:
msg = (
"%s %s associated to visit with"
" timestamp %s for origin with "
@@ -569,6 +582,7 @@
# HEAD alias targets a release
release_name = archive.lookup_release(head["target"])["name"]
head_rel = _get_release(releases, release_name, snapshot_id)
+ assert head_rel is not None
if head_rel["target_type"] == "revision":
revision = archive.lookup_revision(head_rel["target"])
root_directory = revision["directory"]
@@ -663,7 +677,9 @@
return snapshot_context
-def _build_breadcrumbs(snapshot_context: SnapshotContext, path: str):
+def _build_breadcrumbs(
+ snapshot_context: SnapshotContext, path: Optional[str]
+) -> List[Dict[str, str]]:
origin_info = snapshot_context["origin_info"]
url_args = snapshot_context["url_args"]
query_params = dict(snapshot_context["query_params"])
@@ -700,14 +716,18 @@
return breadcrumbs
-def _check_origin_url(snapshot_id, origin_url):
+def _check_origin_url(snapshot_id: Optional[str], origin_url: Optional[str]) -> None:
if snapshot_id is None and origin_url is None:
raise BadInputExc("An origin URL must be provided as query parameter.")
def browse_snapshot_directory(
- request, snapshot_id=None, origin_url=None, timestamp=None, path=None
-):
+ request: HttpRequest,
+ snapshot_id: Optional[str] = None,
+ origin_url: Optional[str] = None,
+ timestamp: Optional[str] = None,
+ path: Optional[str] = None,
+) -> HttpResponse:
"""
Django view implementation for browsing a directory in a snapshot context.
"""
@@ -728,7 +748,7 @@
root_directory = snapshot_context["root_directory"]
sha1_git = root_directory
- error_info = {
+ error_info: Dict[str, Any] = {
"status_code": 200,
"description": None,
}
@@ -813,7 +833,7 @@
dir_path = "/" + path
swh_objects = []
- vault_cooking = {
+ vault_cooking: Dict[str, Any] = {
"directory_context": False,
"directory_swhid": None,
"revision_context": False,
@@ -932,7 +952,12 @@
PER_PAGE = 100
-def browse_snapshot_log(request, snapshot_id=None, origin_url=None, timestamp=None):
+def browse_snapshot_log(
+ request: HttpRequest,
+ snapshot_id: Optional[str] = None,
+ origin_url: Optional[str] = None,
+ timestamp: Optional[str] = None,
+) -> HttpResponse:
"""
Django view implementation for browsing a revision history in a
snapshot context.
@@ -991,9 +1016,10 @@
query_params = snapshot_context["query_params"]
snapshot_id = snapshot_context["snapshot_id"]
- query_params["per_page"] = per_page
+ query_params["per_page"] = str(per_page)
revs_ordering = request.GET.get("revs_ordering", "")
- query_params["revs_ordering"] = revs_ordering or None
+ if revs_ordering:
+ query_params["revs_ordering"] = revs_ordering
if origin_info:
browse_view_name = "browse-origin-log"
@@ -1002,14 +1028,14 @@
prev_log_url = None
if len(rev_log) > offset + per_page:
- query_params["offset"] = offset + per_page
+ query_params["offset"] = str(offset + per_page)
prev_log_url = reverse(
browse_view_name, url_args=url_args, query_params=query_params
)
next_log_url = None
if offset != 0:
- query_params["offset"] = offset - per_page
+ query_params["offset"] = str(offset - per_page)
next_log_url = reverse(
browse_view_name, url_args=url_args, query_params=query_params
)
@@ -1029,7 +1055,7 @@
"snapshot": snapshot_id,
}
- if origin_info:
+ if origin_info and visit_info:
revision_metadata["origin url"] = origin_info["url"]
revision_metadata["origin visit date"] = format_utc_iso_date(visit_info["date"])
revision_metadata["origin visit type"] = visit_info["type"]
@@ -1077,8 +1103,12 @@
def browse_snapshot_branches(
- request, snapshot_id=None, origin_url=None, timestamp=None, branch_name_include=None
-):
+ request: HttpRequest,
+ snapshot_id: Optional[str] = None,
+ origin_url: Optional[str] = None,
+ timestamp: Optional[str] = None,
+ branch_name_include: Optional[str] = None,
+) -> HttpResponse:
"""
Django view implementation for browsing a list of branches in a snapshot
context.
@@ -1093,8 +1123,8 @@
visit_id=visit_id or None,
)
- branches_bc = request.GET.get("branches_breadcrumbs", "")
- branches_bc = branches_bc.split(",") if branches_bc else []
+ branches_bc_str = request.GET.get("branches_breadcrumbs", "")
+ branches_bc = branches_bc_str.split(",") if branches_bc_str else []
branches_from = branches_bc[-1] if branches_bc else ""
origin_info = snapshot_context["origin_info"]
@@ -1113,9 +1143,10 @@
target_types=["revision", "alias"],
branch_name_include_substring=branch_name_include,
)
- displayed_branches = []
+ displayed_branches: List[Dict[str, Any]] = []
if snapshot:
- displayed_branches, _, _ = process_snapshot_branches(snapshot)
+ branches, _, _ = process_snapshot_branches(snapshot)
+ displayed_branches = [dict(branch) for branch in branches]
for branch in displayed_branches:
rev_query_params = {}
@@ -1190,11 +1221,11 @@
def browse_snapshot_releases(
- request,
- snapshot_id=None,
- origin_url=None,
- timestamp=None,
- release_name_include=None,
+ request: HttpRequest,
+ snapshot_id: Optional[str] = None,
+ origin_url: Optional[str] = None,
+ timestamp: Optional[str] = None,
+ release_name_include: Optional[str] = None,
):
"""
Django view implementation for browsing a list of releases in a snapshot
@@ -1210,8 +1241,8 @@
visit_id=visit_id or None,
)
- rel_bc = request.GET.get("releases_breadcrumbs", "")
- rel_bc = rel_bc.split(",") if rel_bc else []
+ rel_bc_str = request.GET.get("releases_breadcrumbs", "")
+ rel_bc = rel_bc_str.split(",") if rel_bc_str else []
rel_from = rel_bc[-1] if rel_bc else ""
origin_info = snapshot_context["origin_info"]
@@ -1225,9 +1256,10 @@
target_types=["release", "alias"],
branch_name_include_substring=release_name_include,
)
- displayed_releases = []
+ displayed_releases: List[Dict[str, Any]] = []
if snapshot:
- _, displayed_releases, _ = process_snapshot_branches(snapshot)
+ _, releases, _ = process_snapshot_branches(snapshot)
+ displayed_releases = [dict(release) for release in releases]
for release in displayed_releases:
query_params_tgt = {"snapshot": snapshot_id, "release": release["name"]}
diff --git a/swh/web/browse/views/content.py b/swh/web/browse/views/content.py
--- a/swh/web/browse/views/content.py
+++ b/swh/web/browse/views/content.py
@@ -5,8 +5,9 @@
import difflib
from distutils.util import strtobool
+from typing import Any, Dict, Optional
-from django.http import HttpResponse, JsonResponse
+from django.http import HttpRequest, HttpResponse, JsonResponse
from django.shortcuts import redirect, render
from swh.model.hashutil import hash_to_hex
@@ -32,11 +33,11 @@
@browse_route(
- r"content/(?P[0-9a-z_:]*[0-9a-f]+.)/raw/",
+ r"content/(?P[0-9a-z_:]*[0-9a-f]+)/raw/",
view_name="browse-content-raw",
checksum_args=["query_string"],
)
-def content_raw(request, query_string):
+def content_raw(request: HttpRequest, query_string: str) -> HttpResponse:
"""Django view that produces a raw display of a content identified
by its hash value.
@@ -70,10 +71,12 @@
@browse_route(
- r"content/(?P.*)/diff/(?P.*)/",
+ r"content/(?P.+)/diff/(?P.+)/",
view_name="diff-contents",
)
-def _contents_diff(request, from_query_string, to_query_string):
+def _contents_diff(
+ request: HttpRequest, from_query_string: str, to_query_string: str
+) -> HttpResponse:
"""
Browse endpoint used to compute unified diffs between two contents.
@@ -102,11 +105,11 @@
content_to_size = 0
content_from_lines = []
content_to_lines = []
- force = request.GET.get("force", "false")
+ force_str = request.GET.get("force", "false")
path = request.GET.get("path", None)
language = "plaintext"
- force = bool(strtobool(force))
+ force = bool(strtobool(force_str))
if from_query_string == to_query_string:
diff_str = "File renamed without changes"
@@ -173,7 +176,7 @@
return JsonResponse(diff_data)
-def _get_content_from_request(request):
+def _get_content_from_request(request: HttpRequest) -> Dict[str, Any]:
path = request.GET.get("path")
if path is None:
raise BadInputExc("The path query parameter must be provided.")
@@ -196,16 +199,19 @@
browse_context="content",
)
root_directory = snapshot_context["root_directory"]
+ assert root_directory is not None # to keep mypy happy
return archive.lookup_directory_with_path(root_directory, path)
@browse_route(
- r"content/(?P[0-9a-z_:]*[0-9a-f]+.)/",
+ r"content/(?P[0-9a-z_:]*[0-9a-f]+)/",
r"content/",
view_name="browse-content",
checksum_args=["query_string"],
)
-def content_display(request, query_string=None):
+def content_display(
+ request: HttpRequest, query_string: Optional[str] = None
+) -> HttpResponse:
"""Django view that produces an HTML display of a content identified
by its hash value.
@@ -215,11 +221,11 @@
"""
if query_string is None:
# this case happens when redirected from origin/content or snapshot/content
- content = _get_content_from_request(request)
+ content_data = _get_content_from_request(request)
return redirect(
reverse(
"browse-content",
- url_args={"query_string": f"sha1_git:{content['target']}"},
+ url_args={"query_string": f"sha1_git:{content_data['target']}"},
query_params=request.GET,
),
)
@@ -233,7 +239,7 @@
snapshot_id = request.GET.get("snapshot") or request.GET.get("snapshot_id")
path = request.GET.get("path")
content_data = {}
- error_info = {"status_code": 200, "description": None}
+ error_info: Dict[str, Any] = {"status_code": 200, "description": None}
try:
content_data = request_content(query_string)
except NotFoundExc as e:
@@ -327,9 +333,9 @@
query_params=query_params,
)
breadcrumbs.append({"name": pi["name"], "url": dir_url})
- breadcrumbs.append({"name": filename, "url": None})
+ breadcrumbs.append({"name": filename, "url": ""})
- if path and root_dir != path:
+ if path and root_dir is not None and root_dir != path:
dir_info = archive.lookup_directory_with_path(root_dir, path)
directory_id = dir_info["target"]
elif root_dir != path:
@@ -360,10 +366,10 @@
sha256=content_checksums.get("sha256"),
blake2s256=content_checksums.get("blake2s256"),
content_url=content_url,
- mimetype=content_data.get("mimetype"),
- encoding=content_data.get("encoding"),
+ mimetype=content_data.get("mimetype", ""),
+ encoding=content_data.get("encoding", ""),
size=content_data.get("length", 0),
- language=content_data.get("language"),
+ language=content_data.get("language", ""),
root_directory=root_dir,
path=f"/{path}" if path else None,
filename=filename or "",
@@ -418,7 +424,7 @@
heading = "Content - %s" % content_checksums.get("sha1_git")
if breadcrumbs:
- content_path = "/".join([bc["name"] for bc in breadcrumbs])
+ content_path = "/".join(bc["name"] for bc in breadcrumbs)
heading += " - %s" % content_path
return render(
diff --git a/swh/web/browse/views/directory.py b/swh/web/browse/views/directory.py
--- a/swh/web/browse/views/directory.py
+++ b/swh/web/browse/views/directory.py
@@ -4,8 +4,9 @@
# See top-level LICENSE file for more information
import os
+from typing import Any, Dict, Optional
-from django.http import HttpResponse
+from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect, render
from swh.model.swhids import ObjectType
@@ -23,21 +24,24 @@
from swh.web.common.utils import gen_path_info, reverse, swh_object_icons
-def _directory_browse(request, sha1_git, path=None):
+def _directory_browse(
+ request: HttpRequest, sha1_git: str, path: Optional[str] = None
+) -> HttpResponse:
root_sha1_git = sha1_git
- error_info = {"status_code": 200, "description": None}
+ dir_sha1_git: Optional[str] = sha1_git
+ error_info: Dict[str, Any] = {"status_code": 200, "description": None}
if path:
try:
dir_info = archive.lookup_directory_with_path(sha1_git, path)
- sha1_git = dir_info["target"]
+ dir_sha1_git = dir_info["target"]
except NotFoundExc as e:
error_info["status_code"] = 404
error_info["description"] = f"NotFoundExc: {str(e)}"
- sha1_git = None
+ dir_sha1_git = None
dirs, files = [], []
- if sha1_git is not None:
- dirs, files = get_directory_entries(sha1_git)
+ if dir_sha1_git is not None:
+ dirs, files = get_directory_entries(dir_sha1_git)
origin_url = request.GET.get("origin_url")
if not origin_url:
origin_url = request.GET.get("origin")
@@ -56,7 +60,7 @@
except NotFoundExc as e:
if str(e).startswith("Origin"):
raw_dir_url = reverse(
- "browse-directory", url_args={"sha1_git": sha1_git}
+ "browse-directory", url_args={"sha1_git": dir_sha1_git}
)
error_message = (
"The Software Heritage archive has a directory "
@@ -144,7 +148,7 @@
dir_metadata = DirectoryMetadata(
object_type=ObjectType.DIRECTORY,
- object_id=sha1_git,
+ object_id=dir_sha1_git,
directory=root_sha1_git,
nb_files=len(files),
nb_dirs=len(dirs),
@@ -159,12 +163,14 @@
vault_cooking = {
"directory_context": True,
- "directory_swhid": f"swh:1:dir:{sha1_git}",
+ "directory_swhid": f"swh:1:dir:{dir_sha1_git}",
"revision_context": False,
"revision_swhid": None,
}
- swh_objects = [SWHObjectInfo(object_type=ObjectType.DIRECTORY, object_id=sha1_git)]
+ swh_objects = [
+ SWHObjectInfo(object_type=ObjectType.DIRECTORY, object_id=dir_sha1_git)
+ ]
if snapshot_context:
if snapshot_context["revision_id"]:
@@ -190,7 +196,7 @@
swhids_info = get_swhids_info(swh_objects, snapshot_context, dir_metadata)
- heading = "Directory - %s" % sha1_git
+ heading = "Directory - %s" % dir_sha1_git
if breadcrumbs:
dir_path = "/".join([bc["name"] for bc in breadcrumbs]) + "/"
heading += " - %s" % dir_path
@@ -244,7 +250,7 @@
view_name="browse-directory",
checksum_args=["sha1_git"],
)
-def directory_browse(request, sha1_git):
+def directory_browse(request: HttpRequest, sha1_git: str) -> HttpResponse:
"""Django view for browsing the content of a directory identified
by its sha1_git value.
@@ -259,7 +265,9 @@
view_name="browse-directory-legacy",
checksum_args=["sha1_git"],
)
-def directory_browse_legacy(request, sha1_git, path):
+def directory_browse_legacy(
+ request: HttpRequest, sha1_git: str, path: str
+) -> HttpResponse:
"""Django view for browsing the content of a directory identified
by its sha1_git value.
@@ -274,13 +282,15 @@
view_name="browse-directory-resolve-content-path",
checksum_args=["sha1_git"],
)
-def _directory_resolve_content_path(request, sha1_git):
+def _directory_resolve_content_path(
+ request: HttpRequest, sha1_git: str
+) -> HttpResponse:
"""
Internal endpoint redirecting to data url for a specific file path
relative to a root directory.
"""
try:
- path = os.path.normpath(request.GET.get("path"))
+ path = os.path.normpath(request.GET.get("path", ""))
if not path.startswith("../"):
dir_info = archive.lookup_directory_with_path(sha1_git, path)
if dir_info["type"] == "file":
diff --git a/swh/web/browse/views/origin.py b/swh/web/browse/views/origin.py
--- a/swh/web/browse/views/origin.py
+++ b/swh/web/browse/views/origin.py
@@ -1,8 +1,11 @@
-# Copyright (C) 2021 The Software Heritage developers
+# Copyright (C) 2021-2022 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
+from typing import Optional
+
+from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect, render
from swh.web.browse.browseurls import browse_route
@@ -25,7 +28,7 @@
r"origin/directory/",
view_name="browse-origin-directory",
)
-def origin_directory_browse(request):
+def origin_directory_browse(request: HttpRequest) -> HttpResponse:
"""Django view for browsing the content of a directory associated
to an origin for a given visit.
@@ -47,7 +50,12 @@
r"origin/(?P.+)/directory/",
view_name="browse-origin-directory-legacy",
)
-def origin_directory_browse_legacy(request, origin_url, timestamp=None, path=None):
+def origin_directory_browse_legacy(
+ request: HttpRequest,
+ origin_url: str,
+ timestamp: Optional[str] = None,
+ path: Optional[str] = None,
+) -> HttpResponse:
"""Django view for browsing the content of a directory associated
to an origin for a given visit.
@@ -68,7 +76,7 @@
r"origin/content/",
view_name="browse-origin-content",
)
-def origin_content_browse(request):
+def origin_content_browse(request: HttpRequest) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/content` instead
@@ -87,7 +95,12 @@
r"origin/(?P.+)/content/",
view_name="browse-origin-content-legacy",
)
-def origin_content_browse_legacy(request, origin_url, path=None, timestamp=None):
+def origin_content_browse_legacy(
+ request: HttpRequest,
+ origin_url: str,
+ path: Optional[str] = None,
+ timestamp: Optional[str] = None,
+) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/content` instead
@@ -106,7 +119,7 @@
r"origin/log/",
view_name="browse-origin-log",
)
-def origin_log_browse(request):
+def origin_log_browse(request: HttpRequest) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/snapshot/log` instead
@@ -123,7 +136,9 @@
r"origin/(?P.+)/log/",
view_name="browse-origin-log-legacy",
)
-def origin_log_browse_legacy(request, origin_url, timestamp=None):
+def origin_log_browse_legacy(
+ request: HttpRequest, origin_url: str, timestamp: Optional[str] = None
+) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/snapshot/log` instead
@@ -145,7 +160,7 @@
r"origin/branches/",
view_name="browse-origin-branches",
)
-def origin_branches_browse(request):
+def origin_branches_browse(request: HttpRequest) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/snapshot/branches` instead
@@ -163,7 +178,9 @@
r"origin/(?P.+)/branches/",
view_name="browse-origin-branches-legacy",
)
-def origin_branches_browse_legacy(request, origin_url, timestamp=None):
+def origin_branches_browse_legacy(
+ request: HttpRequest, origin_url: str, timestamp: Optional[str] = None
+) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/snapshot/branches` instead
@@ -182,7 +199,7 @@
r"origin/releases/",
view_name="browse-origin-releases",
)
-def origin_releases_browse(request):
+def origin_releases_browse(request: HttpRequest) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/snapshot/releases` instead
@@ -200,7 +217,9 @@
r"origin/(?P.+)/releases/",
view_name="browse-origin-releases-legacy",
)
-def origin_releases_browse_legacy(request, origin_url, timestamp=None):
+def origin_releases_browse_legacy(
+ request: HttpRequest, origin_url: str, timestamp: Optional[str] = None
+) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/snapshot/releases` instead
@@ -215,12 +234,15 @@
return redirect_to_new_route(request, "browse-snapshot-releases")
-def _origin_visits_browse(request, origin_url):
+def _origin_visits_browse(
+ request: HttpRequest, origin_url: Optional[str]
+) -> HttpResponse:
if origin_url is None:
raise BadInputExc("An origin URL must be provided as query parameter.")
origin_info = archive.lookup_origin({"url": origin_url})
origin_visits = get_origin_visits(origin_info)
+
snapshot_context = get_snapshot_context(origin_url=origin_url)
for i, visit in enumerate(origin_visits):
@@ -242,7 +264,7 @@
)
if not snapshot:
visit["snapshot"] = ""
- visit["date"] = parse_iso8601_date_to_utc(visit["date"]).timestamp()
+ visit["date"] = parse_iso8601_date_to_utc(visit["date"]).isoformat()
heading = "Origin visits - %s" % origin_url
@@ -263,7 +285,7 @@
@browse_route(r"origin/visits/", view_name="browse-origin-visits")
-def origin_visits_browse(request):
+def origin_visits_browse(request: HttpRequest) -> HttpResponse:
"""Django view that produces an HTML display of visits reporting
for a given origin.
@@ -276,7 +298,7 @@
@browse_route(
r"origin/(?P.+)/visits/", view_name="browse-origin-visits-legacy"
)
-def origin_visits_browse_legacy(request, origin_url):
+def origin_visits_browse_legacy(request: HttpRequest, origin_url: str) -> HttpResponse:
"""Django view that produces an HTML display of visits reporting
for a given origin.
@@ -287,7 +309,7 @@
@browse_route(r"origin/", view_name="browse-origin")
-def origin_browse(request):
+def origin_browse(request: HttpRequest) -> HttpResponse:
"""Django view that redirects to the display of the latest archived
snapshot for a given software origin.
"""
@@ -299,7 +321,7 @@
@browse_route(r"origin/(?P.+)/", view_name="browse-origin-legacy")
-def origin_browse_legacy(request, origin_url):
+def origin_browse_legacy(request: HttpRequest, origin_url: str) -> HttpResponse:
"""Django view that redirects to the display of the latest archived
snapshot for a given software origin.
"""
diff --git a/swh/web/browse/views/release.py b/swh/web/browse/views/release.py
--- a/swh/web/browse/views/release.py
+++ b/swh/web/browse/views/release.py
@@ -3,6 +3,9 @@
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
+from typing import Optional
+
+from django.http import HttpRequest, HttpResponse
from django.shortcuts import render
from swh.model.swhids import ObjectType
@@ -19,7 +22,7 @@
from swh.web.common import archive
from swh.web.common.exc import NotFoundExc, sentry_capture_exception
from swh.web.common.identifiers import get_swhids_info
-from swh.web.common.typing import ReleaseMetadata, SWHObjectInfo
+from swh.web.common.typing import ReleaseMetadata, SnapshotContext, SWHObjectInfo
from swh.web.common.utils import format_utc_iso_date, reverse
@@ -28,7 +31,7 @@
view_name="browse-release",
checksum_args=["sha1_git"],
)
-def release_browse(request, sha1_git):
+def release_browse(request: HttpRequest, sha1_git: str) -> HttpResponse:
"""
Django view that produces an HTML display of a release
identified by its id.
@@ -36,7 +39,7 @@
The url that points to it is :http:get:`/browse/release/(sha1_git)/`.
"""
release = archive.lookup_release(sha1_git)
- snapshot_context = {}
+ snapshot_context: Optional[SnapshotContext] = None
origin_info = None
snapshot_id = request.GET.get("snapshot_id")
if not snapshot_id:
@@ -76,7 +79,8 @@
snapshot_id, release_name=release["name"]
)
- snapshot_id = snapshot_context.get("snapshot_id", None)
+ if snapshot_context is not None:
+ snapshot_id = snapshot_context.get("snapshot_id", None)
release_metadata = ReleaseMetadata(
object_type=ObjectType.RELEASE,
diff --git a/swh/web/browse/views/revision.py b/swh/web/browse/views/revision.py
--- a/swh/web/browse/views/revision.py
+++ b/swh/web/browse/views/revision.py
@@ -6,8 +6,9 @@
import hashlib
import json
import textwrap
+from typing import Any, Dict, List, Optional
-from django.http import JsonResponse
+from django.http import HttpRequest, HttpResponse, JsonResponse
from django.shortcuts import render
from django.utils.safestring import mark_safe
@@ -30,7 +31,7 @@
from swh.web.common import archive
from swh.web.common.exc import NotFoundExc, http_status_code_message
from swh.web.common.identifiers import get_swhids_info
-from swh.web.common.typing import RevisionMetadata, SWHObjectInfo
+from swh.web.common.typing import RevisionMetadata, SnapshotContext, SWHObjectInfo
from swh.web.common.utils import (
format_utc_iso_date,
gen_path_info,
@@ -39,7 +40,12 @@
)
-def _gen_content_url(revision, query_string, path, snapshot_context):
+def _gen_content_url(
+ revision: Dict[str, Any],
+ query_string: str,
+ path: str,
+ snapshot_context: Optional[SnapshotContext],
+) -> str:
if snapshot_context:
query_params = snapshot_context["query_params"]
query_params["path"] = path
@@ -55,7 +61,7 @@
return content_url
-def _gen_diff_link(idx, diff_anchor, link_text):
+def _gen_diff_link(idx: int, diff_anchor: str, link_text: str) -> str:
if idx < _max_displayed_file_diffs:
return gen_link(diff_anchor, link_text)
else:
@@ -66,7 +72,11 @@
_max_displayed_file_diffs = 1000
-def _gen_revision_changes_list(revision, changes, snapshot_context):
+def _gen_revision_changes_list(
+ revision: Dict[str, Any],
+ changes: List[Dict[str, Any]],
+ snapshot_context: Optional[SnapshotContext],
+) -> str:
"""
Returns a HTML string describing the file changes
introduced in a revision.
@@ -151,7 +161,7 @@
view_name="diff-revision",
checksum_args=["sha1_git"],
)
-def _revision_diff(request, sha1_git):
+def _revision_diff(request: HttpRequest, sha1_git: str) -> HttpResponse:
"""
Browse internal endpoint to compute revision diff
"""
@@ -161,7 +171,8 @@
if not origin_url:
origin_url = request.GET.get("origin", None)
timestamp = request.GET.get("timestamp", None)
- visit_id = request.GET.get("visit_id", None)
+ visit_id_str = request.GET.get("visit_id", None)
+ visit_id = int(visit_id_str) if visit_id_str is not None else None
if origin_url:
snapshot_context = get_snapshot_context(
origin_url=origin_url, timestamp=timestamp, visit_id=visit_id
@@ -186,7 +197,7 @@
view_name="browse-revision-log",
checksum_args=["sha1_git"],
)
-def revision_log_browse(request, sha1_git):
+def revision_log_browse(request: HttpRequest, sha1_git: str) -> HttpResponse:
"""
Django view that produces an HTML display of the history
log for a revision identified by its id.
@@ -296,7 +307,7 @@
view_name="browse-revision",
checksum_args=["sha1_git"],
)
-def revision_browse(request, sha1_git):
+def revision_browse(request: HttpRequest, sha1_git: str) -> HttpResponse:
"""
Django view that produces an HTML display of a revision
identified by its id.
@@ -350,7 +361,7 @@
elif snapshot_id:
snapshot_context = get_snapshot_context(snapshot_id)
- error_info = {"status_code": 200, "description": None}
+ error_info: Dict[str, Any] = {"status_code": 200, "description": None}
if path:
try:
diff --git a/swh/web/browse/views/snapshot.py b/swh/web/browse/views/snapshot.py
--- a/swh/web/browse/views/snapshot.py
+++ b/swh/web/browse/views/snapshot.py
@@ -1,9 +1,11 @@
-# Copyright (C) 2018-2019 The Software Heritage developers
+# Copyright (C) 2018-2022 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
+from typing import Optional
+from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect
from swh.web.browse.browseurls import browse_route
@@ -18,7 +20,7 @@
from swh.web.common.utils import redirect_to_new_route, reverse
-def get_snapshot_from_request(request):
+def get_snapshot_from_request(request: HttpRequest) -> str:
snapshot = request.GET.get("snapshot")
if snapshot:
return snapshot
@@ -34,7 +36,7 @@
view_name="browse-snapshot",
checksum_args=["snapshot_id"],
)
-def snapshot_browse(request, snapshot_id):
+def snapshot_browse(request: HttpRequest, snapshot_id: str) -> HttpResponse:
"""Django view for browsing the content of a snapshot.
The url that points to it is :http:get:`/browse/snapshot/(snapshot_id)/`
@@ -52,7 +54,7 @@
view_name="browse-snapshot-directory",
checksum_args=["snapshot_id"],
)
-def snapshot_directory_browse(request, snapshot_id):
+def snapshot_directory_browse(request: HttpRequest, snapshot_id: str) -> HttpResponse:
"""Django view for browsing the content of a directory collected
in a snapshot.
@@ -71,7 +73,9 @@
view_name="browse-snapshot-directory-legacy",
checksum_args=["snapshot_id"],
)
-def snapshot_directory_browse_legacy(request, snapshot_id, path=None):
+def snapshot_directory_browse_legacy(
+ request: HttpRequest, snapshot_id: str, path: Optional[str] = None
+) -> HttpResponse:
"""Django view for browsing the content of a directory collected
in a snapshot.
@@ -91,7 +95,7 @@
view_name="browse-snapshot-content",
checksum_args=["snapshot_id"],
)
-def snapshot_content_browse(request, snapshot_id):
+def snapshot_content_browse(request: HttpRequest, snapshot_id: str) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/content` instead
@@ -109,7 +113,9 @@
view_name="browse-snapshot-content-legacy",
checksum_args=["snapshot_id"],
)
-def snapshot_content_browse_legacy(request, snapshot_id, path):
+def snapshot_content_browse_legacy(
+ request: HttpRequest, snapshot_id: str, path: str
+) -> HttpResponse:
"""
This route is deprecated; use http:get:`/browse/content` instead
@@ -128,7 +134,9 @@
view_name="browse-snapshot-log",
checksum_args=["snapshot_id"],
)
-def snapshot_log_browse(request, snapshot_id=None):
+def snapshot_log_browse(
+ request: HttpRequest, snapshot_id: Optional[str] = None
+) -> HttpResponse:
"""Django view that produces an HTML display of revisions history (aka
the commit log) collected in a snapshot.
@@ -161,7 +169,9 @@
view_name="browse-snapshot-branches",
checksum_args=["snapshot_id"],
)
-def snapshot_branches_browse(request, snapshot_id=None):
+def snapshot_branches_browse(
+ request: HttpRequest, snapshot_id: Optional[str] = None
+) -> HttpResponse:
"""Django view that produces an HTML display of the list of branches
collected in a snapshot.
@@ -196,7 +206,9 @@
view_name="browse-snapshot-releases",
checksum_args=["snapshot_id"],
)
-def snapshot_releases_browse(request, snapshot_id=None):
+def snapshot_releases_browse(
+ request: HttpRequest, snapshot_id: Optional[str] = None
+) -> HttpResponse:
"""Django view that produces an HTML display of the list of releases
collected in a snapshot.
diff --git a/swh/web/common/identifiers.py b/swh/web/common/identifiers.py
--- a/swh/web/common/identifiers.py
+++ b/swh/web/common/identifiers.py
@@ -1,9 +1,9 @@
-# Copyright (C) 2020-2021 The Software Heritage developers
+# Copyright (C) 2020-2022 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
-from typing import Any, Dict, Iterable, List, Optional
+from typing import Any, Dict, Iterable, List, Mapping, Optional
from urllib.parse import quote, unquote
from typing_extensions import TypedDict
@@ -274,7 +274,7 @@
def get_swhids_info(
swh_objects: Iterable[SWHObjectInfo],
snapshot_context: Optional[SnapshotContext] = None,
- extra_context: Optional[Dict[str, Any]] = None,
+ extra_context: Optional[Mapping[str, Any]] = None,
) -> List[SWHIDInfo]:
"""
Returns a list of dict containing info related to SWHIDs of objects.
diff --git a/swh/web/common/typing.py b/swh/web/common/typing.py
--- a/swh/web/common/typing.py
+++ b/swh/web/common/typing.py
@@ -137,7 +137,7 @@
class SWHObjectInfo(TypedDict):
object_type: ObjectType
- object_id: str
+ object_id: Optional[str]
class SWHIDContext(TypedDict, total=False):
@@ -182,12 +182,12 @@
class DirectoryMetadata(SWHObjectInfo, SWHObjectInfoMetadata):
- directory: str
- nb_files: int
- nb_dirs: int
- sum_file_sizes: int
+ directory: Optional[str]
+ nb_files: Optional[int]
+ nb_dirs: Optional[int]
+ sum_file_sizes: Optional[int]
root_directory: Optional[str]
- path: str
+ path: Optional[str]
revision: Optional[str]
revision_found: Optional[bool]
release: Optional[str]