|
| 1 | +import subprocess |
| 2 | +import sys |
1 | 3 | from typing import Callable, List
|
2 | 4 | from unittest import mock
|
3 | 5 |
|
@@ -120,3 +122,35 @@ def is_requirement_command(command: Command) -> bool:
|
120 | 122 | return isinstance(command, RequirementCommand)
|
121 | 123 |
|
122 | 124 | check_commands(is_requirement_command, ["download", "install", "wheel"])
|
| 125 | + |
| 126 | + |
| 127 | +@pytest.mark.parametrize( |
| 128 | + "command", ["cache", "check", "config", "freeze", "hash", "help", "inspect", "show"] |
| 129 | +) |
| 130 | +def test_no_network_imports(command: str) -> None: |
| 131 | + """ |
| 132 | + Verify that commands that don't access the network do NOT import network code. |
| 133 | +
|
| 134 | + This helps to reduce the startup time of these commands. |
| 135 | +
|
| 136 | + Note: This won't catch lazy network imports, but it'll catch top-level |
| 137 | + network imports which were accidently added (which is the most likely way |
| 138 | + to regress anyway). |
| 139 | + """ |
| 140 | + code = f""" |
| 141 | +import sys |
| 142 | +from pip._internal.commands import create_command |
| 143 | +
|
| 144 | +command = create_command("{command}") |
| 145 | +names = sorted(mod.__name__ for mod in sys.modules.values()) |
| 146 | +for mod in names: |
| 147 | + print(mod) |
| 148 | + """ |
| 149 | + proc = subprocess.run( |
| 150 | + [sys.executable], encoding="utf-8", input=code, capture_output=True, check=True |
| 151 | + ) |
| 152 | + imported = proc.stdout.splitlines() |
| 153 | + assert not any("pip._internal.index" in mod for mod in imported) |
| 154 | + assert not any("pip._internal.network" in mod for mod in imported) |
| 155 | + assert not any("requests" in mod for mod in imported) |
| 156 | + assert not any("urllib3" in mod for mod in imported) |
0 commit comments