Skip to content

Commit

Permalink
Fix passing constraints file path into pipx install operation via `…
Browse files Browse the repository at this point in the history
…--pip-args` (#1390)
  • Loading branch information
guysalt authored Jun 30, 2024
1 parent 801665f commit f04e81e
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 2 deletions.
1 change: 1 addition & 0 deletions changelog.d/1389.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix passing constraints file path into `pipx install` operation via `pip` args
4 changes: 3 additions & 1 deletion src/pipx/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ def get_pip_args(parsed_args: Dict[str, str]) -> List[str]:
pip_args += ["--index-url", parsed_args["index_url"]]

if parsed_args.get("pip_args"):
pip_args += shlex.split(parsed_args.get("pip_args", ""), posix=not WINDOWS)
# Stripping the single quote that can be parsed from several shells
pip_args_striped = parsed_args["pip_args"].strip("'")
pip_args += shlex.split(pip_args_striped, posix=not WINDOWS)

# make sure --editable is last because it needs to be right before
# package specification
Expand Down
22 changes: 21 additions & 1 deletion src/pipx/package_specifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,27 @@ def parse_specifier_for_install(package_spec: str, pip_args: List[str]) -> Tuple
)
pip_args.remove("--editable")

return (package_or_url, pip_args)
for index, option in enumerate(pip_args):
if not option.startswith(("-c", "--constraint")):
continue

if option in ("-c", "--constraint"):
argument_index = index + 1
if argument_index < len(pip_args):
constraints_file = pip_args[argument_index]
pip_args[argument_index] = str(Path(constraints_file).expanduser().resolve())

else: # option == "--constraint=some_path"
option_list = option.split("=")

if len(option_list) == 2:
key, value = option_list
value_path = Path(value).expanduser().resolve()
pip_args[index] = f"{key}={value_path}"

break

return package_or_url, pip_args


def parse_specifier_for_metadata(package_spec: str) -> str:
Expand Down
33 changes: 33 additions & 0 deletions tests/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,39 @@ def test_pip_args_with_windows_path(pipx_temp_env, capsys):
assert r"D:\\TEST\\DIR" in captured.err


@pytest.mark.parametrize("constraint_flag", ["-c ", "--constraint ", "--constraint="])
def test_pip_args_with_constraint_relative_path(constraint_flag, pipx_temp_env, tmp_path, caplog):
constraint_file_name = "constraints.txt"
package_name = "ipython"
package_version = "8.23.0"

os.chdir(tmp_path)
constraints_file = tmp_path / constraint_file_name
constraints_file.write_text(f"{package_name}!={package_version}")
constraints_file.touch()

assert not run_pipx_cli(["install", f"--pip-args='{constraint_flag}{constraint_file_name}'", package_name])

assert f"{constraint_flag}{constraints_file}" in caplog.text

subprocess_package_version = subprocess.run([package_name, "--version"], capture_output=True, text=True, check=False)
subprocess_package_version_output = subprocess_package_version.stdout.strip()
assert subprocess_package_version_output != package_version


@pytest.mark.parametrize("constraint_flag", ["-c ", "--constraint ", "--constraint="])
def test_pip_args_with_wrong_constraint_fail(constraint_flag, pipx_ultra_temp_env, tmp_path, capsys):
constraint_file_name = "constraints.txt"
os.chdir(tmp_path)

assert run_pipx_cli(["install", f"--pip-args='{constraint_flag}{constraint_file_name}'", "pycowsay"])

assert (
f"ERROR: Could not open requirements file: [Errno 2] No such file or directory: '{constraint_file_name}'"
in capsys.readouterr().err
)


def test_install_suffix(pipx_temp_env, capsys):
name = "pbr"

Expand Down

0 comments on commit f04e81e

Please sign in to comment.