Skip to content

Commit ab2cc23

Browse files
committed
Run pip-compile in env python rather than pip-tools python
1 parent 5330964 commit ab2cc23

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

piptools/scripts/compile.py

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
import itertools
44
import os
55
import shlex
6+
import shutil
67
import sys
78
import tempfile
9+
import typing
810
from pathlib import Path
11+
from subprocess import run # nosec
912
from typing import IO, Any, BinaryIO, cast
1013

1114
import click
@@ -79,9 +82,9 @@ def _determine_linesep(
7982
)
8083
@click.pass_context
8184
@options.version
82-
@options.color
8385
@options.verbose
8486
@options.quiet
87+
@options.color
8588
@options.dry_run
8689
@options.pre
8790
@options.rebuild
@@ -122,11 +125,69 @@ def _determine_linesep(
122125
@options.build_deps_for
123126
@options.all_build_deps
124127
@options.only_build_deps
128+
@typing.no_type_check
125129
def cli(
130+
*args,
131+
verbose: int,
132+
quiet: int,
133+
**kwargs,
134+
):
135+
"""
136+
Compiles requirements.txt from requirements.in, pyproject.toml, setup.cfg,
137+
or setup.py specs.
138+
"""
139+
log.verbosity = verbose - quiet
140+
current_python = sys.executable
141+
log.debug(f"{current_python=}")
142+
env_python = shutil.which("python")
143+
log.debug(f"{env_python=}")
144+
if current_python != env_python:
145+
# pip-tools probably installed globally (e.g. via pipx)
146+
# install pip-tools in a venv made by env_python and run it there
147+
click.echo("Installing pip-tools in temporary venv...", err=True)
148+
with tempfile.TemporaryDirectory(prefix="pip-tools-env-") as venv_path:
149+
log.debug(f"Installing venv at {venv_path}")
150+
run( # nosec
151+
[
152+
env_python,
153+
"-m",
154+
"venv",
155+
venv_path,
156+
],
157+
capture_output=(not log.verbosity),
158+
check=True,
159+
)
160+
temp_python = venv_path + "/bin/python"
161+
log.debug(f"{temp_python=}")
162+
run( # nosec
163+
[
164+
temp_python,
165+
"-m",
166+
"pip",
167+
"install",
168+
"pip-tools", # TODO fix to this version of pip-tools?
169+
],
170+
capture_output=(not log.verbosity),
171+
check=True,
172+
)
173+
env = {**os.environ, "PATH": f"{venv_path}/bin:{os.environ['PATH']}"}
174+
run( # nosec
175+
[
176+
"pip-compile",
177+
*sys.argv[1:],
178+
],
179+
env=env,
180+
)
181+
else:
182+
# pip-tools running in current env python
183+
cli_runner(*args, verbose, quiet, **kwargs)
184+
185+
186+
def cli_runner(
126187
ctx: click.Context,
127-
color: bool | None,
128188
verbose: int,
129189
quiet: int,
190+
color: bool | None,
130191
dry_run: bool,
131192
pre: bool,
132193
rebuild: bool,

tests/test_cli_compile.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import shutil
77
import subprocess
88
import sys
9+
import venv
910
from textwrap import dedent
1011
from unittest import mock
1112
from unittest.mock import MagicMock
@@ -38,6 +39,12 @@
3839
)
3940

4041

42+
@pytest.fixture(autouse=True)
43+
def mock_run():
44+
with mock.patch("piptools.scripts.compile.run") as mock_run:
45+
yield mock_run
46+
47+
4148
@pytest.fixture(
4249
autouse=True,
4350
params=[
@@ -3771,3 +3778,11 @@ def test_stdout_should_not_be_read_when_stdin_is_not_a_plain_file(
37713778
out = runner.invoke(cli, [req_in.as_posix(), "--output-file", fifo.as_posix()])
37723779

37733780
assert out.exit_code == 0, out
3781+
3782+
3783+
@mock.patch("piptools.scripts.compile.cli_runner")
3784+
def test_pip_compile_run_with_env_python(mock_cli_runner, mock_run, runner, tmpdir):
3785+
venv.EnvBuilder(with_pip=True, symlinks=True).create(tmpdir)
3786+
runner.invoke(cli, ["--verbose"], env={"PATH": f"{tmpdir}/bin"})
3787+
mock_run.assert_called()
3788+
mock_cli_runner.assert_not_called()

0 commit comments

Comments
 (0)