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/6385.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix for broken import requirements in ``2025.0.0``
2 changes: 2 additions & 0 deletions pipenv/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,8 @@ def proper_names_db_path(self) -> str:
self._proper_names_db_path = Path(
self.virtualenv_location, "pipenv-proper-names.txt"
)
# Ensure the parent directory exists before touching the file
self._proper_names_db_path.parent.mkdir(parents=True, exist_ok=True)
self._proper_names_db_path.touch() # Ensure the file exists.
return self._proper_names_db_path

Expand Down
23 changes: 12 additions & 11 deletions pipenv/routines/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,17 +282,6 @@ def do_install(
pipfile_categories=pipfile_categories,
)

do_init(
project,
package_args,
system=system,
allow_global=system,
deploy=deploy,
pypi_mirror=pypi_mirror,
skip_lock=skip_lock,
categories=pipfile_categories,
)

do_install_validations(
project,
package_args,
Expand All @@ -306,6 +295,18 @@ def do_install(
categories=pipfile_categories,
skip_lock=skip_lock,
)

do_init(
project,
package_args,
system=system,
allow_global=system,
deploy=deploy,
pypi_mirror=pypi_mirror,
skip_lock=skip_lock,
categories=pipfile_categories,
)

if not (deploy or system):
new_packages, _ = handle_new_packages(
project,
Expand Down
4 changes: 3 additions & 1 deletion pipenv/utils/requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ def import_requirements(project, r=None, dev=False, categories=None):
indexes.append(extra_index)
if trusted_host:
trusted_hosts.append(get_host_and_port(trusted_host))
for f in parse_requirements(r, session=PipSession()):
# Convert Path object to string to avoid 'PosixPath' has no attribute 'decode' error
req_path = str(r) if isinstance(r, Path) else r
for f in parse_requirements(req_path, session=PipSession()):
package = install_req_from_parsed_requirement(f)
if package.name not in BAD_PACKAGES:
if package.link is not None:
Expand Down
16 changes: 14 additions & 2 deletions pipenv/utils/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,14 @@ def finder(self, ignore_compatibility=False):
def parsed_default_constraints(self):
pip_options = self.pip_options
pip_options.extra_index_urls = []
# Convert Path object to string to avoid 'PosixPath' has no attribute 'decode' error
constraint_file = (
str(self.default_constraint_file)
if isinstance(self.default_constraint_file, Path)
else self.default_constraint_file
)
parsed_default_constraints = parse_requirements(
self.default_constraint_file,
constraint_file,
constraint=True,
finder=self.finder(),
session=self.session,
Expand All @@ -358,9 +364,15 @@ def parsed_constraints(self):
"""Get parsed constraints including those from default packages if needed."""
pip_options = self.pip_options
pip_options.extra_index_urls = []
# Convert Path object to string to avoid 'PosixPath' has no attribute 'decode' error
constraint_file = (
str(self.prepare_constraint_file())
if isinstance(self.prepare_constraint_file(), Path)
else self.prepare_constraint_file()
)
constraints = list(
parse_requirements(
self.prepare_constraint_file(),
constraint_file,
finder=self.finder(),
session=self.session,
options=pip_options,
Expand Down
38 changes: 34 additions & 4 deletions tests/integration/test_import_requirements.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import tempfile
from pathlib import Path
from unittest import mock

import pytest
Expand All @@ -22,7 +23,7 @@ def test_auth_with_pw_redacted(
):
mock_find_package_name_from_directory.return_value = "myproject"
with pipenv_instance_pypi() as p:
p.pipenv("run shell")
p.pipenv("shell")
project = Project()
requirements_file = tempfile.NamedTemporaryFile(mode="w+", delete=False)
requirements_file.write(
Expand All @@ -47,7 +48,7 @@ def test_auth_with_username_redacted(
):
mock_find_package_name_from_directory.return_value = "myproject"
with pipenv_instance_pypi() as p:
p.pipenv("run shell")
p.pipenv("shell")
project = Project()
requirements_file = tempfile.NamedTemporaryFile(mode="w+", delete=False)
requirements_file.write(
Expand All @@ -73,7 +74,7 @@ def test_auth_with_pw_are_variables_passed_to_pipfile(
):
mock_find_package_name_from_directory.return_value = "myproject"
with pipenv_instance_pypi() as p:
p.pipenv("run shell")
p.pipenv("shell")
project = Project()
requirements_file = tempfile.NamedTemporaryFile(mode="w+", delete=False)
requirements_file.write(
Expand All @@ -99,7 +100,7 @@ def test_auth_with_only_username_variable_passed_to_pipfile(
):
mock_find_package_name_from_directory.return_value = "myproject"
with pipenv_instance_pypi() as p:
p.pipenv("run shell")
p.pipenv("shell")
project = Project()
requirements_file = tempfile.NamedTemporaryFile(mode="w+", delete=False)
requirements_file.write(
Expand All @@ -109,3 +110,32 @@ def test_auth_with_only_username_variable_passed_to_pipfile(
import_requirements(project, r=requirements_file.name)
os.unlink(requirements_file.name)
assert p.pipfile["packages"]["myproject"] == {'git': 'https://${AUTH_USER}@github.com/user/myproject.git', 'ref': 'main'}



@pytest.mark.integration
def test_import_requirements_with_path_object(pipenv_instance_pypi):
"""Test that import_requirements can handle Path objects correctly."""
# Create a temporary requirements.txt file
with pipenv_instance_pypi() as p:
req_file_path = Path(p.path) / "requirements.txt"
with open(req_file_path, "w") as f:
f.write("requests\n")

try:
# Create a Project instance
project = Project()

# Call import_requirements with a Path object
import_requirements(project, r=req_file_path)

# Verify that the package was added to the Pipfile
with open("Pipfile") as f:
pipfile_content = f.read()
assert "requests" in pipfile_content
finally:
# Clean up
if os.path.exists(req_file_path):
os.unlink(req_file_path)
if os.path.exists("Pipfile"):
os.unlink("Pipfile")