Source code for swh.osv.download_nvd_osv

# Copyright (C) 2025-2026  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

import contextlib
import multiprocessing.dummy
from pathlib import Path
import tarfile
import threading

from google.cloud import storage
import pyzstd
import tqdm


[docs] def download_to_tarballs(path: Path) -> None: storage_client = storage.Client.create_anonymous_client() bucket = storage_client.bucket(bucket_name="cve-osv-conversion") try: path.mkdir() except FileExistsError: pass blobs = list( tqdm.tqdm( bucket.list_blobs(prefix="osv-output/"), desc="Listing blobs", ) ) with contextlib.ExitStack() as stack: threadlocal = threading.local() with multiprocessing.dummy.Pool( 128, initializer=lambda: _open_tarfile(threadlocal, stack, path) ) as p: for _ in tqdm.tqdm( p.imap_unordered(lambda blob: _download_blob(blob, threadlocal), blobs), total=len(blobs), desc="Downloading blobs", ): pass
def _open_tarfile( threadlocal: threading.local, stack: contextlib.ExitStack, path: Path ) -> None: fd = stack.enter_context( pyzstd.open( str(path / f"shard_{threading.current_thread().ident}.tar.zst"), "w" ) ) threadlocal.tarfile = stack.enter_context(tarfile.open(fileobj=fd, mode="w")) def _download_blob(blob: storage.blob.Blob, threadlocal: threading.local) -> None: if blob.name == "osv-output/.placeholder": return tarinfo = tarfile.TarInfo(name=blob.name) tarinfo.size = blob.size threadlocal.tarfile.addfile(tarinfo, blob.open("rb")) if __name__ == "__main__": download_to_tarballs(Path("./nvd_cve"))