2022-01-08 14:25:04 +01:00
|
|
|
import json
|
2023-04-11 09:34:00 +02:00
|
|
|
import textwrap
|
2022-01-08 14:25:04 +01:00
|
|
|
from pathlib import Path
|
2023-07-25 17:25:05 +02:00
|
|
|
from typing import Any, Dict, Tuple
|
2022-01-08 14:25:04 +01:00
|
|
|
|
|
|
|
import pytest
|
2022-07-10 11:55:06 +02:00
|
|
|
from packaging.utils import canonicalize_name
|
2022-01-08 14:25:04 +01:00
|
|
|
|
|
|
|
from ..lib import PipTestEnvironment, TestData
|
|
|
|
|
|
|
|
|
2022-07-10 11:55:06 +02:00
|
|
|
def _install_dict(report: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
|
return {canonicalize_name(i["metadata"]["name"]): i for i in report["install"]}
|
|
|
|
|
|
|
|
|
2022-01-08 14:25:04 +01:00
|
|
|
def test_install_report_basic(
|
|
|
|
script: PipTestEnvironment, shared_data: TestData, tmp_path: Path
|
|
|
|
) -> None:
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"simplewheel",
|
|
|
|
"--dry-run",
|
|
|
|
"--no-index",
|
|
|
|
"--find-links",
|
|
|
|
str(shared_data.root / "packages/"),
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert "install" in report
|
|
|
|
assert len(report["install"]) == 1
|
2022-07-10 11:55:06 +02:00
|
|
|
simplewheel_report = _install_dict(report)["simplewheel"]
|
2022-01-08 14:25:04 +01:00
|
|
|
assert simplewheel_report["metadata"]["name"] == "simplewheel"
|
|
|
|
assert simplewheel_report["requested"] is True
|
|
|
|
assert simplewheel_report["is_direct"] is False
|
|
|
|
url = simplewheel_report["download_info"]["url"]
|
|
|
|
assert url.startswith("file://")
|
|
|
|
assert url.endswith("/packages/simplewheel-2.0-1-py2.py3-none-any.whl")
|
|
|
|
assert (
|
|
|
|
simplewheel_report["download_info"]["archive_info"]["hash"]
|
|
|
|
== "sha256=191d6520d0570b13580bf7642c97ddfbb46dd04da5dd2cf7bef9f32391dfe716"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def test_install_report_dep(
|
|
|
|
script: PipTestEnvironment, shared_data: TestData, tmp_path: Path
|
|
|
|
) -> None:
|
|
|
|
"""Test dependencies are present in the install report with requested=False."""
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"require_simple",
|
|
|
|
"--dry-run",
|
|
|
|
"--no-index",
|
|
|
|
"--find-links",
|
|
|
|
str(shared_data.root / "packages/"),
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert len(report["install"]) == 2
|
2022-07-10 11:55:06 +02:00
|
|
|
assert _install_dict(report)["require-simple"]["requested"] is True
|
|
|
|
assert _install_dict(report)["simple"]["requested"] is False
|
2022-01-08 14:25:04 +01:00
|
|
|
|
|
|
|
|
2023-08-14 19:09:50 +02:00
|
|
|
def test_yanked_version(
|
|
|
|
script: PipTestEnvironment, data: TestData, tmp_path: Path
|
|
|
|
) -> None:
|
|
|
|
"""
|
|
|
|
Test is_yanked is True when explicitly requesting a yanked package.
|
|
|
|
Yanked files are always ignored, unless they are the only file that
|
|
|
|
matches a version specifier that "pins" to an exact version (PEP 592).
|
|
|
|
"""
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"simple==3.0",
|
|
|
|
"--index-url",
|
|
|
|
data.index_url("yanked"),
|
|
|
|
"--dry-run",
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
allow_stderr_warning=True,
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
simple_report = _install_dict(report)["simple"]
|
|
|
|
assert simple_report["requested"] is True
|
|
|
|
assert simple_report["is_direct"] is False
|
|
|
|
assert simple_report["is_yanked"] is True
|
|
|
|
assert simple_report["metadata"]["version"] == "3.0"
|
|
|
|
|
|
|
|
|
|
|
|
def test_skipped_yanked_version(
|
|
|
|
script: PipTestEnvironment, data: TestData, tmp_path: Path
|
|
|
|
) -> None:
|
|
|
|
"""
|
|
|
|
Test is_yanked is False when not explicitly requesting a yanked package.
|
|
|
|
Yanked files are always ignored, unless they are the only file that
|
|
|
|
matches a version specifier that "pins" to an exact version (PEP 592).
|
|
|
|
"""
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"simple",
|
|
|
|
"--index-url",
|
|
|
|
data.index_url("yanked"),
|
|
|
|
"--dry-run",
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
simple_report = _install_dict(report)["simple"]
|
|
|
|
assert simple_report["requested"] is True
|
|
|
|
assert simple_report["is_direct"] is False
|
|
|
|
assert simple_report["is_yanked"] is False
|
|
|
|
assert simple_report["metadata"]["version"] == "2.0"
|
|
|
|
|
|
|
|
|
2023-07-25 16:34:23 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"specifiers",
|
|
|
|
[
|
|
|
|
# result should be the same regardless of the method and order in which
|
|
|
|
# extras are specified
|
|
|
|
("Paste[openid]==1.7.5.1",),
|
|
|
|
("Paste==1.7.5.1", "Paste[openid]==1.7.5.1"),
|
|
|
|
("Paste[openid]==1.7.5.1", "Paste==1.7.5.1"),
|
|
|
|
],
|
|
|
|
)
|
2022-01-08 14:25:04 +01:00
|
|
|
@pytest.mark.network
|
2023-07-25 16:34:23 +02:00
|
|
|
def test_install_report_index(
|
2023-07-25 17:25:05 +02:00
|
|
|
script: PipTestEnvironment, tmp_path: Path, specifiers: Tuple[str, ...]
|
2023-07-25 16:34:23 +02:00
|
|
|
) -> None:
|
2022-01-08 14:25:04 +01:00
|
|
|
"""Test report for sdist obtained from index."""
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"--dry-run",
|
2023-07-25 16:34:23 +02:00
|
|
|
*specifiers,
|
2022-01-08 14:25:04 +01:00
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert len(report["install"]) == 2
|
2022-07-10 11:55:06 +02:00
|
|
|
install_dict = _install_dict(report)
|
|
|
|
assert install_dict["paste"]["requested"] is True
|
|
|
|
assert install_dict["python-openid"]["requested"] is False
|
|
|
|
paste_report = install_dict["paste"]
|
2022-01-08 14:25:04 +01:00
|
|
|
assert paste_report["download_info"]["url"].startswith(
|
|
|
|
"https://files.pythonhosted.org/"
|
|
|
|
)
|
|
|
|
assert paste_report["download_info"]["url"].endswith("/Paste-1.7.5.1.tar.gz")
|
|
|
|
assert (
|
|
|
|
paste_report["download_info"]["archive_info"]["hash"]
|
|
|
|
== "sha256=11645842ba8ec986ae8cfbe4c6cacff5c35f0f4527abf4f5581ae8b4ad49c0b6"
|
|
|
|
)
|
2022-06-04 12:56:38 +02:00
|
|
|
assert paste_report["requested_extras"] == ["openid"]
|
2022-06-03 22:36:57 +02:00
|
|
|
assert "requires_dist" in paste_report["metadata"]
|
2022-01-08 14:25:04 +01:00
|
|
|
|
|
|
|
|
2023-07-25 16:38:51 +02:00
|
|
|
@pytest.mark.network
|
|
|
|
def test_install_report_index_multiple_extras(
|
|
|
|
script: PipTestEnvironment, tmp_path: Path
|
|
|
|
) -> None:
|
|
|
|
"""Test report for sdist obtained from index, with multiple extras requested."""
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"--dry-run",
|
|
|
|
"Paste[openid]",
|
|
|
|
"Paste[subprocess]",
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
install_dict = _install_dict(report)
|
|
|
|
assert "paste" in install_dict
|
|
|
|
assert install_dict["paste"]["requested_extras"] == ["openid", "subprocess"]
|
|
|
|
|
|
|
|
|
2023-04-11 14:48:26 +02:00
|
|
|
@pytest.mark.network
|
|
|
|
def test_install_report_direct_archive(
|
|
|
|
script: PipTestEnvironment, tmp_path: Path, shared_data: TestData
|
|
|
|
) -> None:
|
|
|
|
"""Test report for direct URL archive."""
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
str(shared_data.root / "packages" / "simplewheel-1.0-py2.py3-none-any.whl"),
|
|
|
|
"--dry-run",
|
|
|
|
"--no-index",
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert "install" in report
|
|
|
|
assert len(report["install"]) == 1
|
|
|
|
simplewheel_report = _install_dict(report)["simplewheel"]
|
|
|
|
assert simplewheel_report["metadata"]["name"] == "simplewheel"
|
|
|
|
assert simplewheel_report["requested"] is True
|
|
|
|
assert simplewheel_report["is_direct"] is True
|
|
|
|
url = simplewheel_report["download_info"]["url"]
|
|
|
|
assert url.startswith("file://")
|
|
|
|
assert url.endswith("/packages/simplewheel-1.0-py2.py3-none-any.whl")
|
|
|
|
assert (
|
|
|
|
simplewheel_report["download_info"]["archive_info"]["hash"]
|
|
|
|
== "sha256=e63aa139caee941ec7f33f057a5b987708c2128238357cf905429846a2008718"
|
|
|
|
)
|
|
|
|
assert simplewheel_report["download_info"]["archive_info"]["hashes"] == {
|
|
|
|
"sha256": "e63aa139caee941ec7f33f057a5b987708c2128238357cf905429846a2008718"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-01-08 14:25:04 +01:00
|
|
|
@pytest.mark.network
|
|
|
|
def test_install_report_vcs_and_wheel_cache(
|
|
|
|
script: PipTestEnvironment, tmp_path: Path
|
|
|
|
) -> None:
|
|
|
|
"""Test report for VCS reference, and interactions with the wheel cache."""
|
|
|
|
cache_dir = tmp_path / "cache"
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"git+https://github.com/pypa/pip-test-package"
|
|
|
|
"@5547fa909e83df8bd743d3978d6667497983a4b7",
|
|
|
|
"--cache-dir",
|
|
|
|
str(cache_dir),
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert len(report["install"]) == 1
|
2022-07-10 11:55:06 +02:00
|
|
|
pip_test_package_report = report["install"][0]
|
2022-01-08 14:25:04 +01:00
|
|
|
assert pip_test_package_report["is_direct"] is True
|
|
|
|
assert pip_test_package_report["requested"] is True
|
|
|
|
assert (
|
|
|
|
pip_test_package_report["download_info"]["url"]
|
|
|
|
== "https://github.com/pypa/pip-test-package"
|
|
|
|
)
|
|
|
|
assert pip_test_package_report["download_info"]["vcs_info"]["vcs"] == "git"
|
|
|
|
assert (
|
|
|
|
pip_test_package_report["download_info"]["vcs_info"]["commit_id"]
|
|
|
|
== "5547fa909e83df8bd743d3978d6667497983a4b7"
|
|
|
|
)
|
|
|
|
# Now do it again to make sure the cache is used and that the report still contains
|
|
|
|
# the original VCS url.
|
|
|
|
report_path.unlink()
|
|
|
|
result = script.pip(
|
|
|
|
"install",
|
|
|
|
"pip-test-package @ git+https://github.com/pypa/pip-test-package"
|
|
|
|
"@5547fa909e83df8bd743d3978d6667497983a4b7",
|
|
|
|
"--ignore-installed",
|
|
|
|
"--cache-dir",
|
|
|
|
str(cache_dir),
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
assert "Using cached pip_test_package" in result.stdout
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert len(report["install"]) == 1
|
2022-07-10 11:55:06 +02:00
|
|
|
pip_test_package_report = report["install"][0]
|
2022-01-08 14:25:04 +01:00
|
|
|
assert pip_test_package_report["is_direct"] is True
|
|
|
|
assert pip_test_package_report["requested"] is True
|
|
|
|
assert (
|
|
|
|
pip_test_package_report["download_info"]["url"]
|
|
|
|
== "https://github.com/pypa/pip-test-package"
|
|
|
|
)
|
|
|
|
assert pip_test_package_report["download_info"]["vcs_info"]["vcs"] == "git"
|
|
|
|
assert (
|
|
|
|
pip_test_package_report["download_info"]["vcs_info"]["commit_id"]
|
|
|
|
== "5547fa909e83df8bd743d3978d6667497983a4b7"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.network
|
|
|
|
def test_install_report_vcs_editable(
|
|
|
|
script: PipTestEnvironment, tmp_path: Path
|
|
|
|
) -> None:
|
|
|
|
"""Test report remote editable."""
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"--editable",
|
|
|
|
"git+https://github.com/pypa/pip-test-package"
|
|
|
|
"@5547fa909e83df8bd743d3978d6667497983a4b7"
|
|
|
|
"#egg=pip-test-package",
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert len(report["install"]) == 1
|
2022-07-10 11:55:06 +02:00
|
|
|
pip_test_package_report = report["install"][0]
|
2022-01-08 14:25:04 +01:00
|
|
|
assert pip_test_package_report["is_direct"] is True
|
|
|
|
assert pip_test_package_report["download_info"]["url"].startswith("file://")
|
|
|
|
assert pip_test_package_report["download_info"]["url"].endswith(
|
|
|
|
"/src/pip-test-package"
|
|
|
|
)
|
|
|
|
assert pip_test_package_report["download_info"]["dir_info"]["editable"] is True
|
2022-06-26 17:38:57 +02:00
|
|
|
|
|
|
|
|
2023-04-11 09:34:00 +02:00
|
|
|
@pytest.mark.network
|
|
|
|
def test_install_report_local_path_with_extras(
|
|
|
|
script: PipTestEnvironment, tmp_path: Path, shared_data: TestData
|
|
|
|
) -> None:
|
|
|
|
"""Test report remote editable."""
|
|
|
|
project_path = tmp_path / "pkga"
|
|
|
|
project_path.mkdir()
|
|
|
|
project_path.joinpath("pyproject.toml").write_text(
|
|
|
|
textwrap.dedent(
|
|
|
|
"""\
|
|
|
|
[project]
|
|
|
|
name = "pkga"
|
|
|
|
version = "1.0"
|
|
|
|
|
|
|
|
[project.optional-dependencies]
|
|
|
|
test = ["simple"]
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
)
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"--dry-run",
|
|
|
|
"--no-build-isolation",
|
|
|
|
"--no-index",
|
|
|
|
"--find-links",
|
|
|
|
str(shared_data.root / "packages/"),
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
str(project_path) + "[test]",
|
2023-04-11 22:24:12 +02:00
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert len(report["install"]) == 2
|
|
|
|
pkga_report = report["install"][0]
|
|
|
|
assert pkga_report["metadata"]["name"] == "pkga"
|
|
|
|
assert pkga_report["is_direct"] is True
|
|
|
|
assert pkga_report["requested"] is True
|
|
|
|
assert pkga_report["requested_extras"] == ["test"]
|
|
|
|
simple_report = report["install"][1]
|
|
|
|
assert simple_report["metadata"]["name"] == "simple"
|
|
|
|
assert simple_report["is_direct"] is False
|
|
|
|
assert simple_report["requested"] is False
|
|
|
|
assert "requested_extras" not in simple_report
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.network
|
|
|
|
def test_install_report_editable_local_path_with_extras(
|
|
|
|
script: PipTestEnvironment, tmp_path: Path, shared_data: TestData
|
|
|
|
) -> None:
|
|
|
|
"""Test report remote editable."""
|
|
|
|
project_path = tmp_path / "pkga"
|
|
|
|
project_path.mkdir()
|
|
|
|
project_path.joinpath("pyproject.toml").write_text(
|
|
|
|
textwrap.dedent(
|
|
|
|
"""\
|
|
|
|
[project]
|
|
|
|
name = "pkga"
|
|
|
|
version = "1.0"
|
|
|
|
|
|
|
|
[project.optional-dependencies]
|
|
|
|
test = ["simple"]
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
)
|
|
|
|
report_path = tmp_path / "report.json"
|
|
|
|
script.pip(
|
|
|
|
"install",
|
|
|
|
"--dry-run",
|
|
|
|
"--no-build-isolation",
|
|
|
|
"--no-index",
|
|
|
|
"--find-links",
|
|
|
|
str(shared_data.root / "packages/"),
|
|
|
|
"--report",
|
|
|
|
str(report_path),
|
|
|
|
"--editable",
|
|
|
|
str(project_path) + "[test]",
|
2023-04-11 09:34:00 +02:00
|
|
|
)
|
|
|
|
report = json.loads(report_path.read_text())
|
|
|
|
assert len(report["install"]) == 2
|
|
|
|
pkga_report = report["install"][0]
|
|
|
|
assert pkga_report["metadata"]["name"] == "pkga"
|
|
|
|
assert pkga_report["is_direct"] is True
|
|
|
|
assert pkga_report["requested"] is True
|
|
|
|
assert pkga_report["requested_extras"] == ["test"]
|
|
|
|
simple_report = report["install"][1]
|
|
|
|
assert simple_report["metadata"]["name"] == "simple"
|
|
|
|
assert simple_report["is_direct"] is False
|
|
|
|
assert simple_report["requested"] is False
|
|
|
|
assert "requested_extras" not in simple_report
|
|
|
|
|
|
|
|
|
2022-06-26 17:38:57 +02:00
|
|
|
def test_install_report_to_stdout(
|
|
|
|
script: PipTestEnvironment, shared_data: TestData
|
|
|
|
) -> None:
|
|
|
|
result = script.pip(
|
|
|
|
"install",
|
|
|
|
"simplewheel",
|
|
|
|
"--quiet",
|
|
|
|
"--dry-run",
|
|
|
|
"--no-index",
|
|
|
|
"--find-links",
|
|
|
|
str(shared_data.root / "packages/"),
|
|
|
|
"--report",
|
|
|
|
"-",
|
|
|
|
)
|
|
|
|
report = json.loads(result.stdout)
|
|
|
|
assert "install" in report
|
|
|
|
assert len(report["install"]) == 1
|