diff --git a/licensecheck/packageinforesolver.py b/licensecheck/packageinforesolver.py index 37c4f39..097470a 100644 --- a/licensecheck/packageinforesolver.py +++ b/licensecheck/packageinforesolver.py @@ -7,6 +7,7 @@ import re from concurrent.futures import ThreadPoolExecutor from email.message import Message +from functools import lru_cache from importlib import metadata from importlib.metadata._meta import PackageMetadata from pathlib import Path @@ -113,6 +114,7 @@ def _get_package_info(self, package: Requirement) -> PackageInfo: return pkg_info +@lru_cache(maxsize=128) def normalize_license(lice: str) -> str: licensing = Licensing() parsed = None @@ -182,9 +184,11 @@ def __init__(self, pypi_api: str, package: PackageInfo) -> None: def lazy_fetch(self) -> None: if self.resp is None: # Attempt to get versioned info first - rc, raw_resp = self.make_req( - url=f"{self.pypi_api_pypi}{self.package.name}/{self.package.version}/json" - ) + rc, raw_resp = -1, {} + if self.package.version is not None: + rc, raw_resp = self.make_req( + url=f"{self.pypi_api_pypi}{self.package.name}/{self.package.version}/json" + ) # Otherwise just get the latest if rc != HTTP_OK: rc, raw_resp = self.make_req(url=f"{self.pypi_api_pypi}/{self.package.name}/json") diff --git a/tests/test_packageinfo.py b/tests/test_packageinfo.py index 2bc454a..5297679 100644 --- a/tests/test_packageinfo.py +++ b/tests/test_packageinfo.py @@ -67,6 +67,28 @@ def test_getPackagePypiLocalNotFound() -> None: assert pkg.get_size() is None +def test_unpinned_remote_package_skips_versioned_request( + monkeypatch: pytest.MonkeyPatch, +) -> None: + pkg = RemotePackageInfo("https://pypi.org", aux_packageinfo("sample")) + requested_urls: list[str] = [] + + def make_req(_self: RemotePackageInfo, url: str) -> tuple[int, dict[str, object]]: + requested_urls.append(url) + return 200, {} + + class ProjectResponseStub: + @staticmethod + def model_validate(data: dict[str, object]) -> dict[str, object]: + return data + + monkeypatch.setattr("licensecheck.packageinforesolver.RemotePackageInfo.make_req", make_req) + monkeypatch.setattr("licensecheck.packageinforesolver.ProjectResponse", ProjectResponseStub) + pkg.lazy_fetch() + + assert requested_urls == ["https://pypi.org/pypi/sample/json"] + + def test_getPackages(package_info_manager: PackageInfoManager) -> None: package_info_manager.reqs = {aux_packageinfo("requests")} packages = package_info_manager.getPackages()