diff --git a/CONTRIBUTORS b/CONTRIBUTORS index bcf34f8..f638976 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,2 +1,3 @@ Antoine Eiche Léo Andrès +Franck Bret diff --git a/docs/package-loader-specifications.rst b/docs/package-loader-specifications.rst index caad4ac..1d734b8 100644 --- a/docs/package-loader-specifications.rst +++ b/docs/package-loader-specifications.rst @@ -1,133 +1,133 @@ .. _package-loader-specifications: Package loader specifications ============================= Release fields -------------- Here is an overview of the fields (+ internal version name + branch name) used by each package loader, after D6616: .. list-table:: Fields used by each package loader :header-rows: 1 * - Loader - internal version - branch name - name - message - synthetic - author - date - Notes * - archive - passed as arg - ``release_name(​version)`` - =version - "Synthetic release for archive at {p_info.url}\n" - true - "" - passed as arg - * - cran - ``metadata.get(​"Version", passed as arg)`` - ``release_name(​version)`` - =version - standard message - true - ``metadata.get(​"Maintainer", "")`` - ``metadata.get(​"Date")`` - metadata is intrinsic * - crates - - passed as arg + - ``p_info.​version`` - ``release_name(​version, filename)`` - =version - Synthetic release for Crate source package {p_info.name} version {p_info.version} {description} - true - from intrinsic metadata - from extrinsic metadata - ``i_metadata`` for intrinsic metadata, ``e_metadata`` for extrinsic metadata * - debian - =``version`` - ``release_name(​version)`` - =``i_version`` - standard message (using ``i_version``) - true - ``metadata​.changelog​.person`` - ``metadata​.changelog​.date`` - metadata is intrinsic. Old revisions have ``dsc`` as type ``i_version`` is the intrinsic version (eg. ``0.7.2-3``) while ``version`` contains the debian suite name (eg. ``stretch/contrib/0.7.2-3``) and is passed as arg * - deposit - HEAD - only HEAD - HEAD - "{client}: Deposit {id} in collection {collection}\n" - true - original author - ```` from SWORD XML - revisions had parents * - maven-loader - passed as arg - HEAD - ``release_name(version)`` - "Synthetic release for archive at {p_info.url}\n" - true - "" - passed as arg - Only one artefact per url (jar/zip src) * - nixguix - URL - URL - URL - None - true - "" - None - it's the URL of the artifact referenced by the derivation * - npm - ``metadata​["version"]`` - ``release_name(​version)`` - =version - standard message - true - from int metadata or "" - from ext metadata or None - * - opam - as given by opam - "{opam_package}​.{version}" - =version - standard message - true - from metadata - None - "{self.opam_package}​.{version}" matches the version names used by opam's backend. metadata is extrinsic * - pypi - ``metadata​["version"]`` - ``release_name(​version)`` or ``release_name(​version, filename)`` - =version - ``metadata[​'comment_text']}`` or standard message - true - from int metadata or "" - from ext metadata or None - metadata is intrinsic using this function:: def release_name(version: str, filename: Optional[str] = None) -> str: if filename: return "releases/%s/%s" % (version, filename) return "releases/%s" % version and "standard message" being:: msg = ( f"Synthetic release for {PACKAGE_MANAGER} source package {name} " f"version {version}\n" ) The ``target_type`` field is always ``dir``, and the target the id of a directory loaded by unpacking a tarball/zip file/... diff --git a/swh/loader/package/crates/loader.py b/swh/loader/package/crates/loader.py index e9c52e4..c61d126 100644 --- a/swh/loader/package/crates/loader.py +++ b/swh/loader/package/crates/loader.py @@ -1,351 +1,354 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from distutils.version import StrictVersion import json from pathlib import Path from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple from urllib.parse import urlparse import attr import toml from typing_extensions import TypedDict from swh.loader.package.loader import BasePackageInfo, PackageLoader from swh.loader.package.utils import api_info, cached_method, release_name from swh.model.model import ObjectType, Person, Release, Sha1Git, TimestampWithTimezone from swh.storage.interface import StorageInterface class ExtrinsicPackageMetadata(TypedDict): """Data structure for package extrinsic metadata pulled from http api endpoint. We set only the keys we need according to what is available when querying https://crates.io/api/v1/crates/, where `name` is the name of the crate package (see JSON response example at https://crates.io/api/v1/crates/hg-core). Usage example: .. code-block:: python e_metadata = ExtrinsicPackageMetadata(**self.info()) """ # noqa categories: List[Dict[Any, Any]] """Related categories""" crate: Dict[Any, Any] """Crate project information""" keywords: List[Any] """Keywords""" versions: List[Dict[Any, Any]] """A list of released versions for a crate""" class ExtrinsicVersionPackageMetadata(TypedDict): """Data structure for specific package version extrinsic metadata, pulled from http api endpoint. Similar to `ExtrinsicPackageMetadata` in its usage, but we flatten the data related to a specific version. """ crate: str """The package name""" crate_size: int """The package size""" created_at: str """First released at""" downloads: str """Number of downloads""" license: str """Package license""" num: str """Package version""" published_by: Dict[Any, Any] """Publishers information""" updated_at: str """Last update""" yanked: bool """Is that version yanked? (yanked means release-level deprecation)""" class IntrinsicPackageMetadata(TypedDict): """Data structure for specific package version intrinsic metadata. Data is extracted from the crate package's .toml file. Then the data of the 'package' entry is flattened. Cargo.toml file content example: .. code-block:: toml [package] name = "hg-core" version = "0.0.1" authors = ["Georges Racinet "] description = "Mercurial pure Rust core library, with no assumption on Python bindings (FFI)" homepage = "https://mercurial-scm.org" license = "GPL-2.0-or-later" repository = "https://www.mercurial-scm.org/repo/hg" [lib] name = "hg" [dev-dependencies.rand] version = "~0.6" [dev-dependencies.rand_pcg] version = "~0.1" :param toml: toml object """ name: str """The package name""" version: str """Package version""" authors: List[str] """Authors""" description: str """Package and release description""" homepage: str """Homepage of the project""" license: str """Package license""" repository: str """Source code repository""" @attr.s class CratesPackageInfo(BasePackageInfo): name = attr.ib(type=str) """Name of the package""" version = attr.ib(type=str) """Current version""" e_metadata: Dict[str, Any] = attr.ib(factory=ExtrinsicPackageMetadata) """Extrinsic package metadata, common to all versions""" e_metadata_version: Dict[str, Any] = attr.ib( factory=ExtrinsicVersionPackageMetadata ) """Extrinsic package metadata specific to a version""" i_metadata: Dict[str, Any] = attr.ib(factory=IntrinsicPackageMetadata) """Intrinsic metadata of the current package version""" def extract_intrinsic_metadata(dir_path: Path) -> Dict[str, Any]: """Extract intrinsic metadata from Cargo.toml file at dir_path. Each crate archive has a Cargo.toml at the root of the archive. Args: dir_path: A directory on disk where a Cargo.toml must be present Returns: A dict mapping from toml parser """ return toml.load(dir_path / "Cargo.toml") def extract_author(p_info: CratesPackageInfo) -> Person: """Extract package author from intrinsic metadata and return it as a `Person` model. Args: p_info: CratesPackageInfo that should contains i_metadata entries Returns: Only one author (Person) of the package. Currently limited by internal detail of the swh stack (see T3887). """ authors = p_info.i_metadata["authors"] fullname = authors[0] # TODO: here we have a list of author, see T3887 return Person.from_fullname(fullname.encode()) def extract_description(p_info: CratesPackageInfo) -> str: """Extract package description from intrinsic metadata and return it as a string. Args: p_info: CratesPackageInfo that should contains i_metadata and entries Returns: Package description from metadata. """ return p_info.i_metadata["description"] class CratesLoader(PackageLoader[CratesPackageInfo]): """Load Crates package origins into swh archive.""" visit_type = "crates" def __init__( self, storage: StorageInterface, url: str, - package_name: str, - version: str, - checksum: Optional[str] = None, + artifacts: List[Dict[str, Any]], max_content_size: Optional[int] = None, ): """Constructor Args: - url : str - Origin url (e.g. - https://static.crates.io/crates//-.crate) + url: + Origin url, (e.g. https://crates.io/api/v1/crates/) - package_name : str - Crate package name + artifacts: + A list of dict listing all existing released versions for a + package (Usually set with crates lister `extra_loader_arguments`). + Each line is a dict that should have an `url` + (where to download package specific version) and a `version` entry. - version : str - Crate package version - checksum : str, optional - Checksum for the package file to download - """ + Example:: + + [ + { + "version": , + "url": "https://static.crates.io/crates//-.crate", + } + ] + """ # noqa super().__init__(storage=storage, url=url, max_content_size=max_content_size) - self.name = package_name - self.provider_url = f"https://crates.io/api/v1/crates/{self.name}" - # Check consistency of name, version, url - filename = urlparse(url).path.split("/")[-1] - assert f"{self.name}-{version}.crate" == filename + self.url = url + self.artifacts: Dict[str, Dict] = { + artifact["version"]: artifact for artifact in artifacts + } @cached_method def _raw_info(self) -> bytes: - """Get crate metadata (fetched from http api endpoint set as self.provider_url) + """Get crate metadata (fetched from http api endpoint set as self.url) Returns: Content response as bytes. Content response is a json document. """ - return api_info(self.provider_url) + return api_info(self.url) @cached_method def info(self) -> Dict: """Parse http api json response and return the crate metadata information as a Dict.""" return json.loads(self._raw_info()) def get_versions(self) -> Sequence[str]: """Get all released versions of a crate Returns: A sequence of versions Example:: ["0.1.1", "0.10.2"] """ - versions = [version["num"] for version in self.info()["versions"]] + versions = list(self.artifacts.keys()) versions.sort(key=StrictVersion) return versions def get_default_version(self) -> str: """Get the newest release version of a crate Returns: A string representing a version Example:: "0.1.2" """ - return self.info()["crate"]["newest_version"] + return self.get_versions()[-1] def get_package_info(self, version: str) -> Iterator[Tuple[str, CratesPackageInfo]]: """Get release name and package information from version Args: version: crate version (e.g: "0.1.0") Returns: Iterator of tuple (release_name, p_info) """ - filename = f"{self.name}-{version}.crate" - url = f"https://static.crates.io/crates/{self.name}/{self.name}-{version}.crate" + artifact = self.artifacts[version] + filename = artifact["filename"] + package_name = urlparse(self.url).path.split("/")[-1] + url = artifact["url"] # Get extrinsic metadata from http api - - # Raw crate info e_metadata = ExtrinsicPackageMetadata(**self.info()) # type: ignore[misc] + # Extract crate info for current version (One .crate file for a given version) (crate_version,) = [ crate for crate in e_metadata["versions"] if crate["num"] == version ] e_metadata_version = ExtrinsicVersionPackageMetadata( # type: ignore[misc] **crate_version ) p_info = CratesPackageInfo( - name=self.name, + name=package_name, filename=filename, url=url, version=version, e_metadata=e_metadata, e_metadata_version=e_metadata_version, ) yield release_name(version, filename), p_info def build_release( self, p_info: CratesPackageInfo, uncompressed_path: str, directory: Sha1Git ) -> Optional[Release]: # Extract intrinsic metadata from dir_path/Cargo.toml name = p_info.name version = p_info.version dir_path = Path(uncompressed_path, f"{name}-{version}") i_metadata_raw = extract_intrinsic_metadata(dir_path) # Get only corresponding key of IntrinsicPackageMetadata i_metadata_keys = [k for k in IntrinsicPackageMetadata.__annotations__.keys()] # We use data only from "package" entry - i_metadata = { k: v for k, v in i_metadata_raw["package"].items() if k in i_metadata_keys } p_info.i_metadata = IntrinsicPackageMetadata(**i_metadata) # type: ignore[misc] author = extract_author(p_info) description = extract_description(p_info) message = ( f"Synthetic release for Crate source package {p_info.name} " f"version {p_info.version}\n" f"{description}\n" ) # The only way to get a value for updated_at is through extrinsic metadata updated_at = p_info.e_metadata_version.get("updated_at") return Release( name=version.encode(), author=author, date=TimestampWithTimezone.from_iso8601(updated_at), message=message.encode(), target_type=ObjectType.DIRECTORY, target=directory, synthetic=True, ) diff --git a/swh/loader/package/crates/tasks.py b/swh/loader/package/crates/tasks.py index 2d774c9..9385263 100644 --- a/swh/loader/package/crates/tasks.py +++ b/swh/loader/package/crates/tasks.py @@ -1,16 +1,14 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from celery import shared_task from swh.loader.package.crates.loader import CratesLoader @shared_task(name=__name__ + ".LoadCrates") -def load_crates(*, url=None, package_name: str, version: str, checksum=None): +def load_crates(*, url=None, artifacts: list): """Load Rust crate package""" - return CratesLoader.from_configfile( - url=url, package_name=package_name, version=version, checksum=checksum - ).load() + return CratesLoader.from_configfile(url=url, artifacts=artifacts).load() diff --git a/swh/loader/package/crates/tests/test_crates.py b/swh/loader/package/crates/tests/test_crates.py index e577462..8d7f750 100644 --- a/swh/loader/package/crates/tests/test_crates.py +++ b/swh/loader/package/crates/tests/test_crates.py @@ -1,214 +1,287 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information +import pytest + from swh.loader.package.crates.loader import CratesLoader from swh.loader.tests import assert_last_visit_matches, check_snapshot, get_stats from swh.model.hashutil import hash_to_bytes from swh.model.model import ( ObjectType, Person, Release, Snapshot, SnapshotBranch, TargetType, TimestampWithTimezone, ) CRATES_EXTRA = [ { - "name": "hg-core", - "version": "0.0.1", - "url": "https://static.crates.io/crates/hg-core/hg-core-0.0.1.crate", - "checksum": "7fe168efadebadb9da6a329fdc027036e233b662285730cad27220e11e53c384", + "url": "https://crates.io/api/v1/crates/hg-core", + "artifacts": [ + { + "checksums": { + "sha256": "48a45b46c2a8c38348adb1205b13c3c5eb0174e0c0fec52cc88e9fb1de14c54d", # noqa: B950 + }, + "filename": "hg-core-0.0.1.crate", + "url": "https://static.crates.io/crates/hg-core/hg-core-0.0.1.crate", + "version": "0.0.1", + }, + ], }, { - "name": "micro-timer", - "version": "0.4.0", - "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.4.0.crate", - "checksum": "5de32cb59a062672560d6f0842c4aa7714727457b9fe2daf8987d995a176a405", + "url": "https://crates.io/api/v1/crates/micro-timer", + "artifacts": [ + { + "checksums": { + "sha256": "69ad8fd116f8af0298ae4e83e587b1600af12709022471e25581c3aeb1da77ce", # noqa: B950 + }, + "filename": "micro-timer-0.1.0.crate", + "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.1.0.crate", + "version": "0.1.0", + }, + { + "checksums": { + "sha256": "7b3f65fe0e109daad8d47e1938c9b5f9353efacd86bbe7ff013f84ae7ca758bf", # noqa: B950 + }, + "filename": "micro-timer-0.1.1.crate", + "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.1.1.crate", + "version": "0.1.1", + }, + { + "checksums": { + "sha256": "16439fea388f712c1df7737ceb8f784d407844624b4796faf1e1bf8bbaa97445", # noqa: B950 + }, + "filename": "micro-timer-0.1.2.crate", + "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.1.2.crate", + "version": "0.1.2", + }, + { + "checksums": { + "sha256": "336b4c0f071d16674747faa4643d742cc096fec2bf8cf01bb1a98d984bedcaf1", # noqa: B950 + }, + "filename": "micro-timer-0.2.0.crate", + "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.2.0.crate", + "version": "0.2.0", + }, + { + "checksums": { + "sha256": "987429cd6162a80ed5ff44fc790f5090b1c6d617ac73a2e272965ed91201d79b", # noqa: B950 + }, + "filename": "micro-timer-0.2.1.crate", + "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.2.1.crate", + "version": "0.2.1", + }, + { + "checksums": { + "sha256": "25b31d6cb9112984323d05d7a353f272ae5d7a307074f9ab9b25c00121b8c947", # noqa: B950 + }, + "filename": "micro-timer-0.3.0.crate", + "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.3.0.crate", + "version": "0.3.0", + }, + { + "checksums": { + "sha256": "2620153e1d903d26b72b89f0e9c48d8c4756cba941c185461dddc234980c298c", # noqa: B950 + }, + "filename": "micro-timer-0.3.1.crate", + "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.3.1.crate", + "version": "0.3.1", + }, + { + "checksums": { + "sha256": "5de32cb59a062672560d6f0842c4aa7714727457b9fe2daf8987d995a176a405", # noqa: B950 + }, + "filename": "micro-timer-0.4.0.crate", + "url": "https://static.crates.io/crates/micro-timer/micro-timer-0.4.0.crate", + "version": "0.4.0", + }, + ], }, ] def test_get_versions(requests_mock_datadir, swh_storage): loader = CratesLoader( swh_storage, url=CRATES_EXTRA[1]["url"], - package_name=CRATES_EXTRA[1]["name"], - version=CRATES_EXTRA[1]["version"], + artifacts=CRATES_EXTRA[1]["artifacts"], ) assert loader.get_versions() == [ "0.1.0", "0.1.1", "0.1.2", "0.2.0", "0.2.1", "0.3.0", "0.3.1", "0.4.0", ] def test_get_default_version(requests_mock_datadir, swh_storage): loader = CratesLoader( swh_storage, url=CRATES_EXTRA[1]["url"], - package_name=CRATES_EXTRA[1]["name"], - version=CRATES_EXTRA[1]["version"], + artifacts=CRATES_EXTRA[1]["artifacts"], ) assert loader.get_default_version() == "0.4.0" -def test_crate_origin_not_found(swh_storage, requests_mock_datadir): - url = "https://nowhere-to-run/nowhere-to-hide-0.0.1.crate" +def test_crate_invalid_origin_archive_not_found(swh_storage, requests_mock_datadir): + url = "https://nowhere-to-run/nowhere-to-hide" loader = CratesLoader( swh_storage, url, - package_name="nowhere-to-hide", - version="0.0.1", + artifacts=[ + { + "filename": "nowhere-to-hide-0.0.1.crate", + "url": "https://nowhere-to-run/nowhere-to-hide-0.0.1.crate", + "version": "0.0.1", + }, + ], ) - assert loader.load() == {"status": "failed"} - - assert_last_visit_matches( - swh_storage, url, status="not_found", type="crates", snapshot=None - ) + with pytest.raises(Exception): + assert loader.load() == {"status": "failed"} + assert_last_visit_matches( + swh_storage, url, status="not_found", type="crates", snapshot=None + ) def test_crates_loader_load_one_version(datadir, requests_mock_datadir, swh_storage): loader = CratesLoader( swh_storage, url=CRATES_EXTRA[0]["url"], - package_name=CRATES_EXTRA[0]["name"], - version=CRATES_EXTRA[0]["version"], + artifacts=CRATES_EXTRA[0]["artifacts"], ) actual_load_status = loader.load() assert actual_load_status["status"] == "eventful" assert actual_load_status["snapshot_id"] is not None expected_snapshot_id = "353cd6858c88ee8210432ea1098993c2e9966561" expected_release_id = "d578833534017430f1b93eb741620899620c2505" assert expected_snapshot_id == actual_load_status["snapshot_id"] expected_snapshot = Snapshot( id=hash_to_bytes(actual_load_status["snapshot_id"]), branches={ b"releases/0.0.1/hg-core-0.0.1.crate": SnapshotBranch( target=hash_to_bytes(expected_release_id), target_type=TargetType.RELEASE, ), b"HEAD": SnapshotBranch( target=b"releases/0.0.1/hg-core-0.0.1.crate", target_type=TargetType.ALIAS, ), }, ) check_snapshot(expected_snapshot, swh_storage) stats = get_stats(swh_storage) assert { "content": 1, "directory": 2, "origin": 1, "origin_visit": 1, "release": 1, "revision": 0, "skipped_content": 0, "snapshot": 1, } == stats assert swh_storage.release_get([hash_to_bytes(expected_release_id)])[0] == Release( name=b"0.0.1", message=b"Synthetic release for Crate source package hg-core version " b"0.0.1\nMercurial pure Rust core library, with no assumption " b"on Python bindings (FFI)\n", target=hash_to_bytes("674c3b0b54628d55b93a79dc7adf304efc01b371"), target_type=ObjectType.DIRECTORY, synthetic=True, author=Person.from_fullname(b"Georges Racinet "), date=TimestampWithTimezone.from_iso8601("2019-04-16T18:48:11.404457+00:00"), id=hash_to_bytes(expected_release_id), ) def test_crates_loader_load_n_versions(datadir, requests_mock_datadir, swh_storage): url = CRATES_EXTRA[1]["url"] loader = CratesLoader( swh_storage, - url=url, - package_name=CRATES_EXTRA[1]["name"], - version=CRATES_EXTRA[1]["version"], - checksum=CRATES_EXTRA[1]["checksum"], + url=CRATES_EXTRA[1]["url"], + artifacts=CRATES_EXTRA[1]["artifacts"], ) + actual_load_status = loader.load() assert actual_load_status["status"] == "eventful" assert actual_load_status["snapshot_id"] is not None expected_snapshot_id = "016cbbe3bb78424c35b898015a2d80d79359e2ad" assert expected_snapshot_id == actual_load_status["snapshot_id"] expected_snapshot = Snapshot( id=hash_to_bytes(expected_snapshot_id), branches={ b"releases/0.4.0/micro-timer-0.4.0.crate": SnapshotBranch( target=hash_to_bytes("3237c1174c4ccfa8e934d1bfd8d80b3a89760e39"), target_type=TargetType.RELEASE, ), b"releases/0.3.1/micro-timer-0.3.1.crate": SnapshotBranch( target=hash_to_bytes("8b727a280051cdb90468ede2746e176e6fdf355f"), target_type=TargetType.RELEASE, ), b"releases/0.3.0/micro-timer-0.3.0.crate": SnapshotBranch( target=hash_to_bytes("f45ec236ae50fb37e924a3d2cc093e72b6cbf1cd"), target_type=TargetType.RELEASE, ), b"releases/0.2.1/micro-timer-0.2.1.crate": SnapshotBranch( target=hash_to_bytes("50a60a2c3696df7cd1b623bd7dbea2c89b994e42"), target_type=TargetType.RELEASE, ), b"releases/0.2.0/micro-timer-0.2.0.crate": SnapshotBranch( target=hash_to_bytes("f0592dc0ae05399d872017d0260c45b875cb590e"), target_type=TargetType.RELEASE, ), b"releases/0.1.2/micro-timer-0.1.2.crate": SnapshotBranch( target=hash_to_bytes("9220d7823fc40ab44e3ae3227522e7de672fad3e"), target_type=TargetType.RELEASE, ), b"releases/0.1.1/micro-timer-0.1.1.crate": SnapshotBranch( target=hash_to_bytes("38529b7e355f79fdce31a3ba891e146174e10237"), target_type=TargetType.RELEASE, ), b"releases/0.1.0/micro-timer-0.1.0.crate": SnapshotBranch( target=hash_to_bytes("5e5e6120af55b65c577e09331df54e70fad5e8b0"), target_type=TargetType.RELEASE, ), b"HEAD": SnapshotBranch( target=b"releases/0.4.0/micro-timer-0.4.0.crate", target_type=TargetType.ALIAS, ), }, ) check_snapshot(expected_snapshot, swh_storage) stats = get_stats(swh_storage) assert { "content": 8, "directory": 16, "origin": 1, "origin_visit": 1, "release": 8, "revision": 0, "skipped_content": 0, "snapshot": 1, } == stats assert_last_visit_matches( swh_storage, url, status="full", type="crates", snapshot=expected_snapshot.id, ) diff --git a/swh/loader/package/crates/tests/test_tasks.py b/swh/loader/package/crates/tests/test_tasks.py index b38412f..b60e2d4 100644 --- a/swh/loader/package/crates/tests/test_tasks.py +++ b/swh/loader/package/crates/tests/test_tasks.py @@ -1,25 +1,24 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information def test_tasks_crates_loader( mocker, swh_scheduler_celery_app, swh_scheduler_celery_worker, swh_config ): mock_load = mocker.patch("swh.loader.package.crates.loader.CratesLoader.load") mock_load.return_value = {"status": "eventful"} res = swh_scheduler_celery_app.send_task( "swh.loader.package.crates.tasks.LoadCrates", kwargs=dict( - url="some-url/crates/some-package/some-package-0.0.1.crate", - package_name="some-package", - version="0.0.1", + url="some-url/api/v1/crates/some-package", + artifacts=[{"version": "0.0.1", "url": "some-package-0.0.1.crate"}], ), ) assert res res.wait() assert res.successful() assert mock_load.called assert res.result == {"status": "eventful"}