Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f79cd18
refactor the install routines further to provide clairty and meet the…
matteius Oct 18, 2024
15d07f7
Handle the removal from pipfile
matteius Oct 18, 2024
f292a19
Eliminate bugs/complexity of pipfile caching
matteius Oct 19, 2024
c2385ab
add more careful logic to remove conflicting entries from Pipfile to …
matteius Oct 19, 2024
190e629
fix test assumption about not-sorting.
matteius Oct 19, 2024
d63e77e
refine var name and fix issue with update command installing to wrong…
matteius Oct 19, 2024
fe5c4d1
fix upgrade url/file dependencies
matteius Oct 19, 2024
8515236
Fix issue with upgrade path hard coding the category default
matteius Oct 19, 2024
ef1f4e8
Fix edge case of test in CI by ensuring it raises DeployFailure (this…
matteius Oct 19, 2024
46c5db7
Actually that didn't fix that test
matteius Oct 19, 2024
287d848
PR cleanup
matteius Oct 19, 2024
95e6c87
eliminate egg fragment as of pip 22.2; also correct behavior of edita…
matteius Oct 21, 2024
a10cf7e
More cleanup
matteius Oct 21, 2024
da53b47
Try solving for issue where vcs ref is getting dropped from resolver …
matteius Oct 21, 2024
cf842b0
solving for issue where vcs ref is getting dropped from resolver entry.
matteius Oct 22, 2024
089bc2d
Fix lint
matteius Oct 22, 2024
1663b3b
fix vcs updates commit hash when relocking
matteius Oct 22, 2024
95ab685
fix test that was never run because of name collision
matteius Oct 22, 2024
b2c094b
fix VCS environment variable expansion
matteius Oct 22, 2024
c74f9a6
Clean up lint, add news fragment and address issue 6167
matteius Oct 22, 2024
8977f13
fix import
matteius Oct 22, 2024
5268bde
Updated logic for determining available python version string.
matteius Oct 21, 2024
526ed94
Refactor do_check routine to be more modular and address concerns abo…
matteius Oct 19, 2024
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
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ For most users, we recommend installing Pipenv using `pip`:

pip install --user pipenv

Or, if you\'re using Fedora:

sudo dnf install pipenv

Or, if you\'re using FreeBSD:

pkg install py39-pipenv
Expand Down
15 changes: 9 additions & 6 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@
#
import os

import pipenv.vendor.click

# Hackery to get the CLI docs to generate
from pipenv.vendor import click

# Path hackery to get current version number.
here = os.path.abspath(os.path.dirname(__file__))

about = {}
with open(os.path.join(here, "..", "pipenv", "__version__.py")) as f:
exec(f.read(), about)

# Hackery to get the CLI docs to generate
import click

import pipenv.vendor.click

click.Command = pipenv.vendor.click.Command
click.Group = pipenv.vendor.click.Group
click.BaseCommand = pipenv.vendor.click.BaseCommand
Expand Down Expand Up @@ -80,7 +80,10 @@

# General information about the project.
project = "pipenv"
copyright = '2020. A project founded by Kenneth Reitz and maintained by <a href="https://www.pypa.io/en/latest/">Python Packaging Authority (PyPA).</a>'
copyright = (
"2020. A project founded by Kenneth Reitz and maintained by "
'<a href="https://www.pypa.io/en/latest/">Python Packaging Authority (PyPA).</a>'
)
author = "Python Packaging Authority"

# The version info for the project you're documenting, acts as replacement for
Expand Down
13 changes: 13 additions & 0 deletions news/6276.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Features & Bug Fixes
-------------------
- Refactored and simplified install routines, improving maintainability and reliability (#6276)
- Split install logic into smaller, focused functions.
- Eliminated Pipfile caching for now to prevent bugs and reduce complexity.
- Fixed edge cases with package category selection.
- Improved handling of VCS dependencies during updates, fixing when ref is a revision and not a branch.

- Enhanced VCS URL handling with better environment variable support (#6276)
- More reliable expansion of environment variables in Git URLs.
- Better handling of authentication components in VCS URLs.
- Improved error messaging for missing environment variables.
- Fixed issue where Git reference could be dropped during relock.
9 changes: 6 additions & 3 deletions pipenv/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,12 @@ def safe_import(self, name: str) -> ModuleType:
def python_version(self) -> str | None:
with self.activated() as active:
if active:
sysconfig = self.safe_import("sysconfig")
py_version = sysconfig.get_python_version()
return py_version
from pipenv.patched.pip._vendor.packaging.version import Version

# Extract version parts
version_str = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
python_version = Version(version_str) # Create PEP 440 compliant version
return str(python_version) # Return the string representation
else:
return None

Expand Down
58 changes: 21 additions & 37 deletions pipenv/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,6 @@ def preferred_newlines(f):
return DEFAULT_NEWLINES


# (path, file contents) => TOMLFile
# keeps track of pipfiles that we've seen so we do not need to re-parse 'em
_pipfile_cache = {}


class SourceNotFound(KeyError):
pass

Expand Down Expand Up @@ -670,16 +665,9 @@ def requirements_location(self) -> str | None:

@property
def parsed_pipfile(self) -> tomlkit.toml_document.TOMLDocument | TPipfile:
"""Parse Pipfile into a TOMLFile and cache it

(call clear_pipfile_cache() afterwards if mutating)"""
"""Parse Pipfile into a TOMLFile"""
contents = self.read_pipfile()
# use full contents to get around str/bytes 2/3 issues
cache_key = (self.pipfile_location, contents)
if cache_key not in _pipfile_cache:
parsed = self._parse_pipfile(contents)
_pipfile_cache[cache_key] = parsed
return _pipfile_cache[cache_key]
return self._parse_pipfile(contents)

def read_pipfile(self) -> str:
# Open the pipfile, read it into memory.
Expand All @@ -691,10 +679,6 @@ def read_pipfile(self) -> str:

return contents

def clear_pipfile_cache(self) -> None:
"""Clear pipfile cache (e.g., so we can mutate parsed pipfile)"""
_pipfile_cache.clear()

def _parse_pipfile(
self, contents: str
) -> tomlkit.toml_document.TOMLDocument | TPipfile:
Expand Down Expand Up @@ -991,8 +975,6 @@ def write_toml(self, data, path=None):
formatted_data = cleanup_toml(formatted_data)
with open(path, "w", newline=newlines) as f:
f.write(formatted_data)
# pipfile is mutated!
self.clear_pipfile_cache()

def write_lockfile(self, content):
"""Write out the lockfile."""
Expand Down Expand Up @@ -1088,7 +1070,6 @@ def find_source(sources, name=None, url=None):

sources = (self.sources, self.pipfile_sources())
if refresh:
self.clear_pipfile_cache()
sources = reversed(sources)
found = next(
iter(find_source(source, name=name, url=url) for source in sources), None
Expand All @@ -1099,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 @@ -1244,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
20 changes: 10 additions & 10 deletions pipenv/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ def make_requirement(name=None, entry=None):
def clean_initial_dict(cls, entry_dict):
from pipenv.patched.pip._vendor.packaging.requirements import Requirement

entry_dict.get("version", "")
version = entry_dict.get("version", "")
if isinstance(version, Requirement):
version = str(version.specifier)
Expand Down Expand Up @@ -250,6 +249,8 @@ def marker_to_str(marker):

@cached_property
def get_cleaned_dict(self):
from pipenv.utils.constants import VCS_LIST

self.validate_constraints()
if self.entry.extras != self.lockfile_entry.extras:
entry_extras = list(self.entry.extras)
Expand All @@ -268,6 +269,12 @@ def get_cleaned_dict(self):
_, self.entry_dict = self.get_markers_from_dict(self.entry_dict)
if self.resolver.index_lookup.get(self.name):
self.entry_dict["index"] = self.resolver.index_lookup[self.name]

# Handle VCS entries
for key in VCS_LIST:
if key in self.lockfile_dict:
self.entry_dict[key] = self.lockfile_dict[key]
self.entry_dict.pop("version", None)
return self.entry_dict

@property
Expand All @@ -290,9 +297,7 @@ def pipfile_entry(self):

@property
def entry(self):
if self._entry is None:
self._entry = self.make_requirement(self.name, self.entry_dict)
return self._entry
return self.make_requirement(self.name, self.lockfile_dict)

@property
def normalized_name(self):
Expand Down Expand Up @@ -548,18 +553,13 @@ def __getattribute__(self, key):

def clean_results(results, resolver, project, category):
from pipenv.utils.dependencies import (
get_lockfile_section_using_pipfile_category,
translate_markers,
)

if not project.lockfile_exists:
return results
lockfile = project.lockfile_content
lockfile_section = get_lockfile_section_using_pipfile_category(category)
reverse_deps = project.environment.reverse_dependencies()
new_results = [
r for r in results if r["name"] not in lockfile.get(lockfile_section, {})
]
new_results = []
for result in results:
name = result.get("name")
entry_dict = result.copy()
Expand Down
Loading
Loading