|
1 | 1 | """Basic CLI functionality checks.
|
2 | 2 | """
|
| 3 | +import subprocess |
| 4 | +import sys |
| 5 | +from pathlib import Path |
3 | 6 | from textwrap import dedent
|
4 | 7 |
|
5 | 8 | import pytest
|
6 | 9 |
|
| 10 | +from pip._internal.commands import commands_dict |
7 | 11 | from tests.lib import PipTestEnvironment
|
8 | 12 |
|
9 | 13 |
|
@@ -45,3 +49,47 @@ def test_entrypoints_work(entrypoint: str, script: PipTestEnvironment) -> None:
|
45 | 49 | result2 = script.run("fake_pip", "-V", allow_stderr_warning=True)
|
46 | 50 | assert result.stdout == result2.stdout
|
47 | 51 | assert "old script wrapper" in result2.stderr
|
| 52 | + |
| 53 | + |
| 54 | +@pytest.mark.parametrize( |
| 55 | + "command", |
| 56 | + set(commands_dict).symmetric_difference( |
| 57 | + # Exclude commands that are expected to use the network. |
| 58 | + # TODO: uninstall and list should only import network modules as needed |
| 59 | + {"install", "uninstall", "download", "search", "index", "wheel", "list"} |
| 60 | + ), |
| 61 | +) |
| 62 | +def test_no_network_imports(command: str, tmp_path: Path) -> None: |
| 63 | + """ |
| 64 | + Verify that commands that don't access the network do NOT import network code. |
| 65 | +
|
| 66 | + This helps to reduce the startup time of these commands. |
| 67 | +
|
| 68 | + Note: This won't catch lazy network imports, but it'll catch top-level |
| 69 | + network imports which were accidently added (which is the most likely way |
| 70 | + to regress anyway). |
| 71 | + """ |
| 72 | + file = Path(tmp_path, f"imported_modules_for_{command}") |
| 73 | + code = f""" |
| 74 | +import runpy |
| 75 | +import sys |
| 76 | +
|
| 77 | +sys.argv[1:] = [{command!r}, "--help"] |
| 78 | +
|
| 79 | +try: |
| 80 | + runpy.run_module("pip", alter_sys=True, run_name="__main__") |
| 81 | +finally: |
| 82 | + with open({str(file)!r}, "w") as f: |
| 83 | + print(*sys.modules.keys(), sep="\\n", file=f) |
| 84 | + """ |
| 85 | + subprocess.run( |
| 86 | + [sys.executable], |
| 87 | + input=code, |
| 88 | + encoding="utf-8", |
| 89 | + check=True, |
| 90 | + ) |
| 91 | + imported = file.read_text().splitlines() |
| 92 | + assert not any("pip._internal.index" in mod for mod in imported) |
| 93 | + assert not any("pip._internal.network" in mod for mod in imported) |
| 94 | + assert not any("requests" in mod for mod in imported) |
| 95 | + assert not any("urllib3" in mod for mod in imported) |
0 commit comments