Skip to content

Commit 76aba3b

Browse files
committed
Don't add the constraints to the other package categories (rework test)
1 parent 0676c2a commit 76aba3b

File tree

2 files changed

+96
-25
lines changed

2 files changed

+96
-25
lines changed

Diff for: pipenv/routines/update.py

+17-3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ def upgrade(
286286

287287
package_args = list(packages) + [f"-e {pkg}" for pkg in editable_packages]
288288

289+
# Track which packages were explicitly requested for which categories
290+
explicitly_requested = {}
291+
for package in packages or []:
292+
package_name = package.split("==")[0] if "==" in package else package
293+
explicitly_requested[package_name] = categories[:] # Copy the original categories
294+
289295
# Check if we need to update packages in all categories
290296
# This is needed when a package is specified in one category but also used in others
291297
if packages:
@@ -295,6 +301,7 @@ def upgrade(
295301
]
296302

297303
# Check if any of the packages to upgrade are also in other categories
304+
additional_categories = []
298305
for category in all_lockfile_categories:
299306
if category in categories:
300307
continue # Skip categories already in the list
@@ -304,12 +311,15 @@ def upgrade(
304311
package_name = package.split("==")[0] if "==" in package else package
305312
if package_name in category_section:
306313
# If the package is also in this category, add it to categories
307-
categories.append(category)
314+
additional_categories.append(category)
308315
err.print(
309316
f"[bold][green]Package {package_name} found in {category} section, will update there too.[/bold][/green]"
310317
)
311318
break
312319

320+
# Add all additional categories at once to avoid duplicates
321+
categories.extend(additional_categories)
322+
313323
# Early conflict detection
314324
conflicts_found = False
315325
for package in package_args:
@@ -355,8 +365,12 @@ def upgrade(
355365
install_req, package, category=pipfile_category, index_name=index_name
356366
)
357367

358-
# Only add to Pipfile if explicitly requested
359-
if has_package_args:
368+
# Only add to Pipfile if this category was explicitly requested for this package
369+
# This prevents adding packages to categories where they're only implicit dependencies
370+
if has_package_args and (
371+
normalized_name not in explicitly_requested
372+
or category in explicitly_requested.get(normalized_name, [])
373+
):
360374
project.add_pipfile_entry_to_pipfile(
361375
name, normalized_name, pipfile_entry, category=pipfile_category
362376
)

Diff for: tests/integration/test_upgrade.py

+79-22
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,17 @@ def test_pipenv_dependency_incompatibility_resolution(pipenv_instance_pypi):
106106

107107

108108
@pytest.mark.upgrade
109-
def test_upgrade_updates_package_in_all_categories(pipenv_instance_private_pypi):
110-
"""Test that upgrading a package updates it in all categories where it appears."""
109+
def test_upgrade_updates_lockfile_in_all_categories(pipenv_instance_private_pypi):
110+
"""Test that upgrading a package updates it in all categories of the lockfile."""
111111
with pipenv_instance_private_pypi() as p:
112-
# Create a Pipfile with a package in multiple categories
112+
# Create a Pipfile with a package in default and a dev package that depends on it
113113
with open(p.pipfile_path, "w") as f:
114114
contents = """
115115
[packages]
116-
six = "==1.11.0"
116+
requests = "==2.25.0"
117117
118118
[dev-packages]
119-
six = "==1.11.0"
120-
121-
[custom-category]
122-
six = "==1.11.0"
119+
pytest = "*"
123120
""".strip()
124121
f.write(contents)
125122

@@ -132,24 +129,84 @@ def test_upgrade_updates_package_in_all_categories(pipenv_instance_private_pypi)
132129
with open(lockfile_path) as lockfile:
133130
lock_data = json.load(lockfile)
134131

135-
# Check initial versions in all categories
136-
assert lock_data["default"]["six"]["version"] == "==1.11.0"
137-
assert lock_data["develop"]["six"]["version"] == "==1.11.0"
132+
# Check initial version in default section
133+
assert lock_data["default"]["requests"]["version"] == "==2.25.0"
138134

139-
# Get the lockfile section for the custom category
140-
custom_section = get_lockfile_section_using_pipfile_category("custom-category")
141-
assert lock_data[custom_section]["six"]["version"] == "==1.11.0"
135+
# Check if requests is in develop section (as a dependency of pytest)
136+
# If it's there, note its initial version
137+
develop_has_requests = "requests" in lock_data["develop"]
138+
if develop_has_requests:
139+
initial_dev_version = lock_data["develop"]["requests"]["version"]
142140

143141
# Upgrade the package
144-
target_version = "1.16.0"
145-
c = p.pipenv(f"upgrade six=={target_version}")
146-
assert c.returncode == 0, f"Failed to upgrade six: {c.stderr}"
142+
target_version = "2.28.0"
143+
c = p.pipenv(f"upgrade requests=={target_version}")
144+
assert c.returncode == 0, f"Failed to upgrade requests: {c.stderr}"
147145

148-
# Verify the package was updated in all categories
146+
# Verify the package was updated in the lockfile
149147
with open(lockfile_path) as lockfile:
150148
updated_lock_data = json.load(lockfile)
151149

152-
# Check updated versions in all categories
153-
assert updated_lock_data["default"]["six"]["version"] == f"=={target_version}"
154-
assert updated_lock_data["develop"]["six"]["version"] == f"=={target_version}"
155-
assert updated_lock_data[custom_section]["six"]["version"] == f"=={target_version}"
150+
# Check updated version in default section
151+
assert updated_lock_data["default"]["requests"]["version"] == f"=={target_version}"
152+
153+
# If requests was in develop section, check it was updated there too
154+
if develop_has_requests:
155+
assert updated_lock_data["develop"]["requests"]["version"] == f"=={target_version}"
156+
157+
158+
@pytest.mark.upgrade
159+
def test_upgrade_only_adds_to_explicit_categories(pipenv_instance_private_pypi):
160+
"""Test that upgrading a package only adds it to the Pipfile for explicitly requested categories."""
161+
with pipenv_instance_private_pypi() as p:
162+
# Create a Pipfile with a package in default but not in dev-packages
163+
with open(p.pipfile_path, "w") as f:
164+
contents = """
165+
[packages]
166+
requests = "==2.25.0"
167+
168+
[dev-packages]
169+
pytest = "*"
170+
""".strip()
171+
f.write(contents)
172+
173+
# Lock the dependencies
174+
c = p.pipenv("lock")
175+
assert c.returncode == 0, f"Failed to lock dependencies: {c.stderr}"
176+
177+
# Verify initial state
178+
with open(p.pipfile_path) as pipfile:
179+
initial_pipfile_content = pipfile.read()
180+
181+
# Make sure requests is not in dev-packages initially
182+
assert "requests" not in initial_pipfile_content.split("[dev-packages]")[1].split("[")[0]
183+
184+
# Upgrade the package
185+
target_version = "2.28.0"
186+
c = p.pipenv(f"upgrade requests=={target_version}")
187+
assert c.returncode == 0, f"Failed to upgrade requests: {c.stderr}"
188+
189+
# Verify the Pipfile was updated correctly
190+
with open(p.pipfile_path) as pipfile:
191+
updated_pipfile_content = pipfile.read()
192+
193+
# Check that requests was updated in packages section
194+
packages_section = updated_pipfile_content.split("[packages]")[1].split("[")[0]
195+
assert f'requests = "=={target_version}"' in packages_section
196+
197+
# Check that requests was NOT added to dev-packages section
198+
dev_packages_section = updated_pipfile_content.split("[dev-packages]")[1].split("[")[0] if "[dev-packages]" in updated_pipfile_content else ""
199+
assert "requests" not in dev_packages_section
200+
201+
# Verify the lockfile was updated in both sections
202+
lockfile_path = os.path.join(p.path, "Pipfile.lock")
203+
with open(lockfile_path) as lockfile:
204+
updated_lock_data = json.load(lockfile)
205+
206+
# Check that requests was updated in default section
207+
assert updated_lock_data["default"]["requests"]["version"] == f"=={target_version}"
208+
209+
# Check if requests is in develop section (it might be there as a dependency of pytest)
210+
if "requests" in updated_lock_data["develop"]:
211+
# If it's there, it should be updated
212+
assert updated_lock_data["develop"]["requests"]["version"] == f"=={target_version}"

0 commit comments

Comments
 (0)