Skip to content

Fix Issue 6347: default constraints not applying to other categories #6364

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions pipenv/utils/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,10 +367,8 @@ def parsed_constraints(self):
)
)

# Only add default constraints for dev packages if setting allows
if self.category != "default" and self.project.settings.get(
"use_default_constraints", True
):
# Always add default constraints for dev packages
if self.category != "default":
constraints.extend(self.parsed_default_constraints)

return constraints
Expand Down Expand Up @@ -412,10 +410,8 @@ def constraints(self):
for c in possible_constraints_list:
constraints_list.add(c)

# Only use default_constraints when installing dev-packages and setting allows
if self.category != "default" and self.project.settings.get(
"use_default_constraints", True
):
# Always use default_constraints when installing dev-packages
if self.category != "default":
constraints_list |= self.default_constraints

return constraints_list
Expand Down Expand Up @@ -852,6 +848,15 @@ def venv_resolve_deps(
deps = convert_deps_to_pip(
deps, project.pipfile_sources(), include_index=True
)

# For dev packages, add constraints from default packages
constraints = deps.copy()
if pipfile_category != "packages" and "default" in lockfile:
# Get the locked versions from default packages
for pkg_name, pkg_data in lockfile["default"].items():
if isinstance(pkg_data, dict) and "version" in pkg_data:
# Add as a constraint to ensure compatibility
constraints[pkg_name] = pkg_data["version"]
# Useful for debugging and hitting breakpoints in the resolver
if project.s.PIPENV_RESOLVER_PARENT_PYTHON:
try:
Expand Down Expand Up @@ -900,8 +905,23 @@ def venv_resolve_deps(
with tempfile.NamedTemporaryFile(
mode="w+", prefix="pipenv", suffix="constraints.txt", delete=False
) as constraints_file:
# Write the current category dependencies
for dep_name, pip_line in deps.items():
constraints_file.write(f"{dep_name}, {pip_line}\n")

# For dev packages, add explicit constraints from default packages
if pipfile_category != "packages" and "default" in lockfile:
for pkg_name, pkg_data in lockfile["default"].items():
if isinstance(pkg_data, dict) and "version" in pkg_data:
# Add as a constraint to ensure compatibility
version = pkg_data["version"]
constraints_file.write(
f"{pkg_name}, {pkg_name}{version}\n"
)
st.console.print(
f"Adding constraint: {pkg_name}{version}"
)

cmd.append("--constraints-file")
cmd.append(constraints_file.name)
st.console.print("Resolving dependencies...")
Expand Down
79 changes: 79 additions & 0 deletions tests/integration/test_dev_package_constraints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import os

Check failure on line 1 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F401)

tests/integration/test_dev_package_constraints.py:1:8: F401 `os` imported but unused
import pytest

from pipenv.utils.shell import temp_environ

Check failure on line 4 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

tests/integration/test_dev_package_constraints.py:1:1: I001 Import block is un-sorted or un-formatted

Check failure on line 4 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F401)

tests/integration/test_dev_package_constraints.py:4:32: F401 `pipenv.utils.shell.temp_environ` imported but unused


@pytest.mark.lock
@pytest.mark.dev
def test_dev_packages_respect_default_package_constraints(pipenv_instance_private_pypi):
"""
Test that dev packages respect constraints from default packages.

Check failure on line 12 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

tests/integration/test_dev_package_constraints.py:12:1: W293 Blank line contains whitespace
This test verifies the fix for the issue where pipenv may ignore install_requires
from setup.py and lock incompatible versions. The specific case is when httpx is
pinned in default packages and respx is in dev packages, respx should be locked
to a version compatible with the httpx version.
"""
with pipenv_instance_private_pypi() as p:
# First test: explicit version constraint in Pipfile
with open(p.pipfile_path, "w") as f:
contents = """
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
httpx = "==0.24.1"

[dev-packages]
respx = "*"

[requires]
python_version = "3.9"
""".strip()
f.write(contents)

c = p.pipenv("lock")
assert c.returncode == 0

Check failure on line 40 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

tests/integration/test_dev_package_constraints.py:40:1: W293 Blank line contains whitespace
# Verify httpx is locked to 0.24.1
assert "httpx" in p.lockfile["default"]
assert p.lockfile["default"]["httpx"]["version"] == "==0.24.1"

Check failure on line 44 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

tests/integration/test_dev_package_constraints.py:44:1: W293 Blank line contains whitespace
# Verify respx is locked to a compatible version (0.21.1 is the last compatible version)
assert "respx" in p.lockfile["develop"]
assert p.lockfile["develop"]["respx"]["version"] == "==0.21.1"

Check failure on line 48 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

tests/integration/test_dev_package_constraints.py:48:1: W293 Blank line contains whitespace
# Second test: implicit version constraint through another dependency
with open(p.pipfile_path, "w") as f:
contents = """
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
httpx = "*"
xrpl-py = ">=1.8.0"
websockets = ">=9.0.1,<11.0"

[dev-packages]
respx = "*"

[requires]
python_version = "3.9"
""".strip()
f.write(contents)

Check failure on line 69 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

tests/integration/test_dev_package_constraints.py:69:1: W293 Blank line contains whitespace
c = p.pipenv("lock")
assert c.returncode == 0

Check failure on line 72 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

tests/integration/test_dev_package_constraints.py:72:1: W293 Blank line contains whitespace
# Verify httpx is still locked to 0.24.1 (due to constraints from other packages)
assert "httpx" in p.lockfile["default"]
assert p.lockfile["default"]["httpx"]["version"] == "==0.24.1"

Check failure on line 76 in tests/integration/test_dev_package_constraints.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

tests/integration/test_dev_package_constraints.py:76:1: W293 Blank line contains whitespace
# Verify respx is still locked to a compatible version
assert "respx" in p.lockfile["develop"]
assert p.lockfile["develop"]["respx"]["version"] == "==0.21.1"
Loading