Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions news/6288.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes issue with --skip-lock not providing pip the proper package specifier when version was a string (issue did not impact dict with version key).
1 change: 0 additions & 1 deletion pipenv/routines/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,6 @@ def do_install_dependencies(
install_req, markers, req_line = install_req_from_pipfile(
req_name, pipfile_entry
)
req_line = f"{req_line}; {markers}" if markers else f"{req_line}"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

install_req_from_pipfile already takes into account the markers so this must have been another bug.

deps_list.append(
(
install_req,
Expand Down
4 changes: 2 additions & 2 deletions pipenv/utils/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,8 @@ def install_req_from_pipfile(name: str, pipfile: Dict[str, Any]) -> Tuple[Any, A
vcs = next(iter([vcs for vcs in VCS_LIST if pipfile.startswith(f"{vcs}+")]), None)
if vcs is not None:
_pipfile[vcs] = pipfile
else: # normal named requirement
_pipfile["version"] = pipfile

extras = _pipfile.get("extras", [])
extras_str = f"[{','.join(extras)}]" if extras else ""
Expand Down Expand Up @@ -1213,8 +1215,6 @@ def handle_non_vcs_requirement(
return file_path_from_pipfile(_pipfile["file"], _pipfile)
else:
version = get_version(_pipfile)
if version and not is_star(version) and COMPARE_OP.match(version) is None:
version = f"=={version}"
if is_star(version) or version == "==*":
version = ""

Expand Down
69 changes: 69 additions & 0 deletions tests/integration/test_install_twists.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,72 @@ def test_install_skip_lock(pipenv_instance_private_pypi):
assert c.returncode == 0
c = p.pipenv('run python -c "import six"')
assert c.returncode == 0


@pytest.mark.install
@pytest.mark.skip_lock
def test_skip_lock_installs_correct_version(pipenv_instance_pypi):
"""Ensure --skip-lock installs the exact version specified in Pipfile."""
with pipenv_instance_pypi() as p:
with open(p.pipfile_path, "w") as f:
contents = """
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
gunicorn = "==20.0.2"
""".strip()
f.write(contents)

# Install with --skip-lock
c = p.pipenv("install --skip-lock")
assert c.returncode == 0

# Verify installed version matches Pipfile specification
c = p.pipenv("run pip freeze")
assert c.returncode == 0

# Find gunicorn in pip freeze output
packages = [line.strip() for line in c.stdout.split("\n")]
gunicorn_line = next(line for line in packages if line.startswith("gunicorn"))

assert gunicorn_line == "gunicorn==20.0.2"


@pytest.mark.install
@pytest.mark.skip_lock
def test_skip_lock_respects_markers(pipenv_instance_pypi):
"""Ensure --skip-lock correctly handles packages with markers."""
with pipenv_instance_pypi() as p:
with open(p.pipfile_path, "w") as f:
contents = """
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
# Use python version markers since they're platform-independent
simplejson = {version = "==3.17.2", markers = "python_version < '4'"}
urllib3 = {version = "==1.26.6", markers = "python_version < '2'"}
""".strip()
f.write(contents)

# Install with --skip-lock
c = p.pipenv("install --skip-lock")
assert c.returncode == 0

# Verify installed versions match markers
c = p.pipenv("run pip freeze")
assert c.returncode == 0
packages = [line.strip() for line in c.stdout.split("\n")]

# simplejson should be installed (python_version < '4' is always True for Python 3.x)
simplejson_line = next((line for line in packages if line.startswith("simplejson")), None)
assert simplejson_line == "simplejson==3.17.2"

# urllib3 should not be installed (python_version < '2' is always False for Python 3.x)
urllib3_line = next((line for line in packages if line.startswith("urllib3")), None)
assert urllib3_line is None
Loading