Skip to content

Commit

Permalink
add more careful logic to remove conflicting entries from Pipfile to …
Browse files Browse the repository at this point in the history
…prevent lock resolution failure. Remove caching properties that can become stale.
  • Loading branch information
matteius committed Oct 19, 2024
1 parent 7f70dc5 commit 82e44b6
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 32 deletions.
35 changes: 19 additions & 16 deletions pipenv/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -1080,15 +1080,16 @@ def find_source(sources, name=None, url=None):
return found

def get_package_name_in_pipfile(self, package_name, category):
"""Get the equivalent package name in pipfile"""
section = self.parsed_pipfile.get(category)
if section is None:
section = {}
package_name = pep423_name(package_name)
section = self.parsed_pipfile.get(category, {})
normalized_name = pep423_name(package_name)
for name in section:
if pep423_name(name) == package_name:
if pep423_name(name) == normalized_name:
return name
return None
return package_name # Return original name if not found

def get_pipfile_entry(self, package_name, category):
name = self.get_package_name_in_pipfile(package_name, category)
return self.parsed_pipfile.get(category, {}).get(name)

def _sort_category(self, category) -> Table:
# copy table or create table from dict-like object
Expand Down Expand Up @@ -1225,26 +1226,28 @@ def add_pipfile_entry_to_pipfile(self, name, normalized_name, entry, category=No
newly_added = False

# Read and append Pipfile.
p = self.parsed_pipfile
parsed_pipfile = self.parsed_pipfile

# Set empty group if it doesn't exist yet.
if category not in p:
p[category] = {}
if category not in parsed_pipfile:
parsed_pipfile[category] = {}

if name and name != normalized_name:
self.remove_package_from_pipfile(name, category=category)
section = parsed_pipfile.get(category, {})
for entry_name in section.copy().keys():
if entry_name.lower() == normalized_name.lower():
del parsed_pipfile[category][entry_name]

# Add the package to the group.
if normalized_name not in p[category]:
if normalized_name not in parsed_pipfile[category]:
newly_added = True

p[category][normalized_name] = entry
parsed_pipfile[category][normalized_name] = entry

if self.settings.get("sort_pipfile"):
p[category] = self._sort_category(p[category])
parsed_pipfile[category] = self._sort_category(parsed_pipfile[category])

# Write Pipfile.
self.write_toml(p)
self.write_toml(parsed_pipfile)
return newly_added, category, normalized_name

def src_name_from_url(self, index_url):
Expand Down
10 changes: 5 additions & 5 deletions pipenv/routines/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,13 @@ def upgrade(
install_req, _ = expansive_install_req_from_line(package, expand_env=True)
if index_name:
install_req.index = index_name
name, normalized_name, pipfile_entry = project.generate_package_pipfile_entry(
install_req, package, category=pipfile_category

_, _, normalized_name = project.add_package_to_pipfile(
install_req, package, dev=dev, category=pipfile_category
)
project.add_pipfile_entry_to_pipfile(
name, normalized_name, pipfile_entry, category=pipfile_category
requested_packages[pipfile_category][normalized_name] = (
project.get_pipfile_entry(normalized_name, category=pipfile_category)
)
requested_packages[pipfile_category][normalized_name] = pipfile_entry
requested_install_reqs[pipfile_category][normalized_name] = install_req

if project.pipfile_exists:
Expand Down
18 changes: 7 additions & 11 deletions pipenv/utils/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import sys
import tempfile
import warnings
from functools import cached_property, lru_cache
from functools import lru_cache
from pathlib import Path
from typing import Dict, List, Optional

Expand Down Expand Up @@ -284,10 +284,6 @@ def prepare_constraint_file(self):
return constraint_filename

@property
def constraint_file(self):
return self.prepare_constraint_file()

@cached_property
def default_constraint_file(self):
default_constraints = get_constraints_from_deps(self.project.packages)
default_constraint_filename = prepare_constraint_file(
Expand Down Expand Up @@ -326,7 +322,7 @@ def prepare_index_lookup(self):
alt_index_lookup[req_name] = index_mapping[index]
return alt_index_lookup

@cached_property
@property
def package_finder(self):
finder = get_package_finder(
install_cmd=self.pip_command,
Expand All @@ -344,18 +340,18 @@ def finder(self, ignore_compatibility=False):
finder._ignore_compatibility = ignore_compatibility
return finder

@cached_property
@property
def parsed_constraints(self):
pip_options = self.pip_options
pip_options.extra_index_urls = []
return parse_requirements(
self.constraint_file,
self.prepare_constraint_file(),
finder=self.finder(),
session=self.session,
options=pip_options,
)

@cached_property
@property
def parsed_default_constraints(self):
pip_options = self.pip_options
pip_options.extra_index_urls = []
Expand All @@ -368,7 +364,7 @@ def parsed_default_constraints(self):
)
return set(parsed_default_constraints)

@cached_property
@property
def default_constraints(self):
possible_default_constraints = [
install_req_from_parsed_requirement(
Expand Down Expand Up @@ -584,7 +580,7 @@ def collect_hashes(self, ireq):
return {self.project.get_hash_from_link(self.hash_cache, link)}
return set()

@cached_property
@property
def resolve_hashes(self):
if self.results is not None:
for ireq in self.results:
Expand Down

0 comments on commit 82e44b6

Please sign in to comment.