diff --git a/swh/web/client/client.py b/swh/web/client/client.py --- a/swh/web/client/client.py +++ b/swh/web/client/client.py @@ -189,6 +189,9 @@ if http_method == "get": r = requests.get(url, **req_args, headers=headers) r.raise_for_status() + elif http_method == "post": + r = requests.post(url, **req_args, headers=headers) + r.raise_for_status() elif http_method == "head": r = requests.head(url, **req_args, headers=headers) else: @@ -399,6 +402,28 @@ else: done = True + def known( + self, swhids: Iterator[SWHIDish], **req_args + ) -> Dict[SWHID, Dict[Any, Any]]: + """Verify the presence in the archive of several objects at once + + Args: + swhids: SWHIDs of the objects to verify + + Returns: + a dictionary mapping object SWHIDs to archive information about them; the + dictionary includes a "known" key associated to a boolean value that is true + if and only if the object is known to the archive + + Raises: + requests.HTTPError: if HTTP request fails + + """ + r = self._call( + "known/", http_method="post", json=list(map(str, swhids)), **req_args + ) + return {parse_swhid(k): v for k, v in r.json().items()} + def content_exists(self, swhid: SWHIDish, **req_args) -> bool: """Check if a content object exists in the archive diff --git a/swh/web/client/tests/conftest.py b/swh/web/client/tests/conftest.py --- a/swh/web/client/tests/conftest.py +++ b/swh/web/client/tests/conftest.py @@ -29,6 +29,19 @@ "Link": f'<{API_URL}/origin/https://github.com/NixOS/nixpkgs/visits/?last_visit=40&per_page=10>; rel="next"' # NoQA: E501 } requests_mock.get(f"{API_URL}/{api_call}", text=data, headers=headers) + + def known_callback(request, context): + known_swhids = [ + "swh:1:cnt:fe95a46679d128ff167b7c55df5d02356c5a1ae1", + "swh:1:dir:977fc4b98c0e85816348cebd3b12026407c368b6", + "swh:1:rev:aafb16d69fd30ff58afdd69036a26047f3aebdc6", + "swh:1:rel:208f61cc7a5dbc9879ae6e5c2f95891e270f09ef", + "swh:1:snp:6a3a2cf0b2b90ce7ae1cf0a221ed68035b686f5a", + ] + return {swhid: {"known": swhid in known_swhids} for swhid in request.json()} + + requests_mock.register_uri("POST", f"{API_URL}/known/", json=known_callback) + return requests_mock diff --git a/swh/web/client/tests/test_web_api_client.py b/swh/web/client/tests/test_web_api_client.py --- a/swh/web/client/tests/test_web_api_client.py +++ b/swh/web/client/tests/test_web_api_client.py @@ -150,6 +150,25 @@ assert visits[7]["snapshot"] == parse_swhid(snapshot_swhid) +def test_known(web_api_client, web_api_mock): + # full list of SWHIDs for which we mock a {known: True} answer + known_swhids = [ + "swh:1:cnt:fe95a46679d128ff167b7c55df5d02356c5a1ae1", + "swh:1:dir:977fc4b98c0e85816348cebd3b12026407c368b6", + "swh:1:rev:aafb16d69fd30ff58afdd69036a26047f3aebdc6", + "swh:1:rel:208f61cc7a5dbc9879ae6e5c2f95891e270f09ef", + "swh:1:snp:6a3a2cf0b2b90ce7ae1cf0a221ed68035b686f5a", + ] + bogus_swhids = [s[:20] + "c0ffee" + s[26:] for s in known_swhids] + all_swhids = known_swhids + bogus_swhids + + known_res = web_api_client.known(all_swhids) + + assert {str(k) for k in known_res} == set(all_swhids) + for swhid, info in known_res.items(): + assert info["known"] == (str(swhid) in known_swhids) + + def test_get_json(web_api_client, web_api_mock): swhids = [ "swh:1:cnt:fe95a46679d128ff167b7c55df5d02356c5a1ae1",