Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stop using requirementslib models #5793

Merged
merged 131 commits into from
Aug 19, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
d31f56b
Prototyping moving away from requirementslib models
matteius Jul 16, 2023
f7a45af
Check pt progress fixing the edge cases
matteius Jul 16, 2023
4b86ae7
debugging test runner
matteius Jul 16, 2023
4ae3192
change back test runner run_command even though the other way was le…
matteius Jul 16, 2023
81f6f93
change back test runner run_command even though the other way was le…
matteius Jul 16, 2023
383ae83
Fix edge case of editable + vcs
matteius Jul 16, 2023
9e83b55
Fix edge case of file
matteius Jul 16, 2023
8cbc031
check pt progress
matteius Jul 17, 2023
772a5c6
check pt progress
matteius Jul 19, 2023
f8f9162
address additional test failures
matteius Jul 19, 2023
f4e6024
check pt
matteius Jul 22, 2023
5391d63
check pt
matteius Jul 22, 2023
64c9eb1
undo change to pip
matteius Jul 22, 2023
b33267d
Check pt
matteius Jul 22, 2023
85f01b4
Remove --skip-lock flag
matteius Jul 22, 2023
0df5add
merge
matteius Jul 22, 2023
743b535
Restore prior resolver default behavior but maintain direct code path…
matteius Jul 22, 2023
381a283
add news fragment
matteius Jul 22, 2023
0d30cb7
add comments
matteius Jul 22, 2023
4fae08e
merge the resolver update into this branch
matteius Jul 22, 2023
612c24a
Addressing edge cases
matteius Jul 22, 2023
b9096d5
test correction
matteius Jul 22, 2023
5e649f7
Check pt progress
matteius Jul 23, 2023
c82103a
additional progress -- fix the upgrade command
matteius Jul 23, 2023
5707858
corrected mocks
matteius Jul 23, 2023
b99296e
corrected mocks
matteius Jul 23, 2023
9cd4d24
fix regression in refactor
matteius Jul 23, 2023
a332eaa
Handle wheel files with extras
matteius Jul 23, 2023
6a1db61
Fix file edge cases
matteius Jul 23, 2023
38b3299
Fix edge case
matteius Jul 23, 2023
ecca28c
fix
matteius Jul 23, 2023
4c49785
solve more edge cases.
matteius Jul 23, 2023
f462778
Fix part of index restricted packages and handle case of file reqs th…
matteius Jul 24, 2023
57ac7a1
Adjustments
matteius Jul 24, 2023
d09f3ab
revert change to test and it passes
matteius Jul 24, 2023
7c379f8
Revise test since PEP-440 does not support wildcard versions but does…
matteius Jul 24, 2023
ce21489
fix test assumptions
matteius Jul 24, 2023
23f8540
remove unused arg
matteius Jul 27, 2023
191578a
resolve merge conflict with main
matteius Jul 27, 2023
bb29f34
Possible edge case with CI being on different drives.
matteius Jul 27, 2023
3955baf
fix double file prefix
matteius Jul 27, 2023
8d4e8a0
fix some more edge case of various OS paths
matteius Jul 27, 2023
7c0807e
remove unused parse code and maintain relative paths in expansive_ins…
matteius Jul 27, 2023
8cb9174
dont interpret relative files as absolute
matteius Jul 27, 2023
814a769
GPT is is either going to put me in a hole or maybe fix a test or two
matteius Jul 27, 2023
83f9fa2
fix path in one OS break it in another
matteius Jul 27, 2023
a70c510
Merge branch 'main' into skip-lock-removal
matteius Jul 27, 2023
b8d9531
Merge branch 'skip-lock-removal' into draft-no-reqlib
matteius Jul 27, 2023
a63f4b4
Add unearth
matteius Jul 27, 2023
ef4cf76
corrected imports from unearth and correct conditional statement outs…
matteius Jul 27, 2023
9579b85
use unearth to resolve some edge cases
matteius Jul 27, 2023
34f76a6
add pdm-backend to the vendoring depends for unary and fix nt edge case
matteius Jul 27, 2023
1a1bbf5
Handle top level markers and other check points.
matteius Jul 29, 2023
64fdab8
Merge branch 'main' into draft-no-reqlib
matteius Jul 29, 2023
9d063d9
Address --outdated usage and fix bug with upgrade command
matteius Jul 29, 2023
692df48
revert adjustments to path logic (even though CI will fail).
matteius Jul 29, 2023
3639d9f
fix ruff warning and vcs installs
matteius Jul 29, 2023
145c29f
solve the mystery behind the constraints noqa line
matteius Jul 29, 2023
22e6123
simplify and remove dead code
matteius Jul 29, 2023
3fd7f7f
Ensure the os_name marker is AND with the other markers.
matteius Jul 29, 2023
3c2d64e
Address the remaining markers tests
matteius Jul 29, 2023
065f517
Remove unearth
matteius Jul 29, 2023
d04df48
remove dead code
matteius Jul 29, 2023
28d8e6f
Reduce unused vars
matteius Jul 30, 2023
c888387
fix most remaining tests
matteius Jul 30, 2023
9ed349a
resolve linux path issues
matteius Jul 30, 2023
8a627fc
fix more edge cases of linux
matteius Jul 30, 2023
2b1151f
fix more edge cases of linux
matteius Jul 30, 2023
14bfb7e
add conditional for windows
matteius Jul 30, 2023
9b7538c
Fix edge case of linux
matteius Jul 30, 2023
d3f519a
Merge branch 'draft-no-reqlib' of github.com:pypa/pipenv into draft-n…
matteius Jul 30, 2023
4b2d793
Handle windows differently
matteius Jul 30, 2023
9ce0c4e
Attempt to make this code more portable
matteius Jul 30, 2023
fa468da
Solve edge case with py3.7 and py3.8
matteius Jul 30, 2023
f0a8bb7
Handle windows path issue edge case
matteius Jul 30, 2023
3903c26
sort this method out to work on < python 3.8
matteius Jul 31, 2023
b90c63b
Remove duplicated install logic and ensure sys.exit(1); fix remaining…
matteius Jul 31, 2023
892bf5c
Skip this test on non-windows.
matteius Jul 31, 2023
8e665ce
use normpath to try and avoid windows CI errors
matteius Jul 31, 2023
6cec82a
smarter recursive search, handle not searching network paths; error w…
matteius Jul 31, 2023
7c723ff
Try fixing remaining 3 windows test CI failures.
matteius Jul 31, 2023
72dc6fe
Safety patch for windows python 3.7
matteius Jul 31, 2023
6bd1a26
remove errant commit
matteius Jul 31, 2023
d0466f6
Fixes for 5626 pip line deprecation warnings.
matteius Jul 31, 2023
22650f3
Add back window py 3.8 safety patch.
matteius Jul 31, 2023
2cb0524
Safety patch for older Pipfile vcs entries
matteius Aug 5, 2023
d6459be
Merge branch 'main' into draft-no-reqlib
matteius Aug 5, 2023
2f19540
fix lint
matteius Aug 5, 2023
07518f4
Fix edge case of markers in lockfile. Update pipenv lockfile to inst…
matteius Aug 5, 2023
8bc3dcd
Add python 3.12 beta to test runner
matteius Aug 5, 2023
623a9c7
Add python 3.12 beta to test runner
matteius Aug 5, 2023
2a4e0f0
Don't import distutils
matteius Aug 5, 2023
5a9b017
Only patch rmtree on the affected python versions
matteius Aug 5, 2023
efe3398
Merge branch 'main' into draft-no-reqlib
matteius Aug 5, 2023
c2571d2
Move what we still need from requirementslib into the pipenv utils an…
matteius Aug 5, 2023
9aba3c3
satisfy ruff
matteius Aug 5, 2023
e32645c
Further remove requirementslib.
matteius Aug 5, 2023
77e3932
force upgrade of virtualenv for python 3.12
matteius Aug 5, 2023
fa67879
Try patching the python 3.12 CI because its pulling an older pip
matteius Aug 5, 2023
a168dc9
Try patching the python 3.12 CI because its pulling an older pip
matteius Aug 5, 2023
9ce1075
remove virtualenv-clone
matteius Aug 5, 2023
72778eb
relock
matteius Aug 6, 2023
fbf5f41
Use project python
matteius Aug 6, 2023
cd68c7f
Revert "Use project python"
matteius Aug 6, 2023
fd16758
Revert "relock"
matteius Aug 6, 2023
226210a
Fix edge case with locking dependencies that do not match the Markers…
matteius Aug 6, 2023
d7b544f
Restrict black version, iterate on edge case involving markers and pa…
matteius Aug 6, 2023
0ba29b0
Default old_lock_data if not passed
matteius Aug 6, 2023
c065138
Adds news fragment
matteius Aug 6, 2023
920a90a
Skip tests that in py3.12 that involve packages that do not work with…
matteius Aug 6, 2023
bc3ce7e
Skip test on windows 3.8
matteius Aug 6, 2023
d5c96a7
skipif requires reason string
matteius Aug 6, 2023
dd4e228
skipif requires reason string
matteius Aug 6, 2023
d0db077
py 3.8 test failure.
matteius Aug 6, 2023
83e9f65
Try to address to CI test issues
matteius Aug 7, 2023
4a2b9de
Remove test that was strictly a test of the tomlkit library
matteius Aug 7, 2023
3e52aed
Solve problem with re-lock after initial file install succeeds.
matteius Aug 7, 2023
6eb2793
Try to apply python 3.8 windows test patch differently
matteius Aug 7, 2023
6b54847
Iterate on vcs edge cases discovered
matteius Aug 8, 2023
0dec26e
Do not include extras in constraints
matteius Aug 9, 2023
b310811
Support locking the vcs dependencies hash in the lockfile. Use key …
matteius Aug 12, 2023
7c1027a
Update vcs specifiers documentation; infer name from specific pip lin…
matteius Aug 12, 2023
816a3a5
trim possible extras from name
matteius Aug 12, 2023
7aad5bb
trim possible extras from name
matteius Aug 12, 2023
1f0884f
Provide helpful text and error for recently remmoved commands
matteius Aug 16, 2023
e31a958
start addressing the ruff errors that showed up recently but stall ou…
matteius Aug 16, 2023
a2849c2
Merge branch 'main' into draft-no-reqlib
matteius Aug 16, 2023
6f14e48
fix the merge deletion issue
matteius Aug 16, 2023
327db6d
Set the right log levels and verbosity to show users the errors gener…
matteius Aug 16, 2023
8a62691
Fix the collection of all matching package hashes for non-pypi indexe…
matteius Aug 17, 2023
9b3aa48
Merge branch 'main' into draft-no-reqlib
matteius Aug 18, 2023
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
41 changes: 22 additions & 19 deletions pipenv/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@
import typing
from pathlib import Path
from sysconfig import get_paths, get_python_version, get_scheme_names
from urllib.parse import urlparse
from urllib.request import url2pathname
from urllib.parse import unquote, urlparse

import pipenv
from pipenv.patched.pip._internal.commands.install import InstallCommand
from pipenv.patched.pip._internal.index.package_finder import PackageFinder
from pipenv.patched.pip._internal.req.req_install import InstallRequirement
from pipenv.patched.pip._internal.vcs.versioncontrol import VersionControl
from pipenv.patched.pip._vendor import pkg_resources
from pipenv.patched.pip._vendor.packaging.specifiers import SpecifierSet
from pipenv.patched.pip._vendor.packaging.utils import canonicalize_name
from pipenv.utils.dependencies import as_pipfile
from pipenv.utils.funktools import chunked, unnest
from pipenv.utils.indexes import prepare_pip_source_args
from pipenv.utils.processes import subprocess_run
Expand Down Expand Up @@ -200,11 +203,6 @@ def base_paths(self) -> dict[str, str]:
.. note:: The implementation of this is borrowed from a combination of pip and
virtualenv and is likely to change at some point in the future.

>>> from pipenv.core import project
>>> from pipenv.environment import Environment
>>> env = Environment(prefix=project.virtualenv_location, is_venv=True, sources=project.sources)
>>> import pprint
>>> pprint.pprint(env.base_paths)
{'PATH': '/home/hawk/.virtualenvs/pipenv-MfOPs1lW/bin::/bin:/usr/bin',
'PYTHONPATH': '/home/hawk/.virtualenvs/pipenv-MfOPs1lW/lib/python3.7/site-packages',
'data': '/home/hawk/.virtualenvs/pipenv-MfOPs1lW',
Expand Down Expand Up @@ -760,38 +758,43 @@ def is_installed(self, pkgname):

return any(d for d in self.get_distributions() if d.project_name == pkgname)

def is_satisfied(self, req):
def is_satisfied(self, req: InstallRequirement):
match = next(
iter(
d
for d in self.get_distributions()
if canonicalize_name(d.project_name) == req.normalized_name
if req.name
and canonicalize_name(d.project_name) == canonicalize_name(req.name)
),
None,
)
if match is not None:
if req.editable and req.line_instance.is_local and self.find_egg(match):
requested_path = req.line_instance.path
if req.editable and req.link and req.link.is_file:
requested_path = req.link.file_path
if os.path.exists(requested_path):
local_path = requested_path
else:
parsed_url = urlparse(requested_path)
local_path = url2pathname(parsed_url.path)
local_path = parsed_url.path
return requested_path and os.path.samefile(local_path, match.location)
elif match.has_metadata("direct_url.json"):
direct_url_metadata = json.loads(match.get_metadata("direct_url.json"))
commit_id = direct_url_metadata.get("vcs_info", {}).get("commit_id", "")
vcs_type = direct_url_metadata.get("vcs_info", {}).get("vcs", "")
_, pipfile_part = req.as_pipfile().popitem()
_, pipfile_part = as_pipfile(req).popitem()
vcs_backend = VersionControl.get_backend_for_scheme(req.link.scheme)
req_commit = (
unquote(vcs_backend().get_revision(req.link)) if vcs_backend else None
)
return (
vcs_type == req.vcs
and commit_id == req.commit_hash
and direct_url_metadata["url"] == pipfile_part[req.vcs]
vcs_type == req.link.scheme
and commit_id == req_commit
and direct_url_metadata["url"] == pipfile_part[req.link.scheme]
)
elif req.is_vcs or req.is_file_or_url:
elif req.link and req.link.is_vcs:
return False
elif req.line_instance.specifiers is not None:
return req.line_instance.specifiers.contains(
elif req.specifier is not None:
return SpecifierSet(str(req.specifier)).contains(
match.version, prereleases=True
)
return True
Expand Down
5 changes: 4 additions & 1 deletion pipenv/patched/pip/_internal/req/constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
operators = Specifier._operators.keys()


def _strip_extras(path: str) -> Tuple[str, Optional[str]]:
def _strip_extras(path: str) -> Tuple[Optional[str], Optional[str]]:
if path is None:
return None, None
m = re.match(r"^(.+)(\[[^\]]+\])$", path)
extras = None
if m:
Expand Down Expand Up @@ -305,6 +307,7 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar

if is_url(name):
link = Link(name)
_, extras_as_string = _strip_extras(link.egg_fragment)
else:
p, extras_as_string = _strip_extras(path)
url = _get_url_from_path(p, name)
Expand Down
127 changes: 115 additions & 12 deletions pipenv/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
import urllib.parse
from json.decoder import JSONDecodeError
from pathlib import Path
from tempfile import TemporaryDirectory
from urllib.parse import unquote

from pipenv.utils.constants import VCS_LIST
from pipenv.vendor.requirementslib.models.setup_info import unpack_url

try:
import tomllib as toml
Expand All @@ -23,10 +28,16 @@
from pipenv.patched.pip._internal.commands.install import InstallCommand
from pipenv.patched.pip._internal.configuration import Configuration
from pipenv.patched.pip._internal.exceptions import ConfigurationError
from pipenv.patched.pip._internal.network.download import Downloader
from pipenv.patched.pip._internal.req.req_install import InstallRequirement
from pipenv.patched.pip._vendor import pkg_resources
from pipenv.utils.constants import is_type_checking
from pipenv.utils.dependencies import (
find_package_name_from_directory,
find_package_name_from_tarball,
find_package_name_from_zipfile,
get_canonical_names,
install_req_from_line,
is_editable,
pep423_name,
python_version,
Expand All @@ -45,7 +56,11 @@
)
from pipenv.utils.toml import cleanup_toml, convert_toml_outline_tables
from pipenv.vendor import click, plette, tomlkit
from pipenv.vendor.requirementslib.models.utils import get_default_pyproject_backend
from pipenv.vendor.requirementslib.models.utils import (
get_default_pyproject_backend,
normalize_name,
)
from pipenv.vendor.requirementslib.utils import get_pip_command

try:
# this is only in Python3.8 and later
Expand Down Expand Up @@ -937,7 +952,9 @@ def find_source(sources, name=None, url=None):

def get_package_name_in_pipfile(self, package_name, category):
"""Get the equivalent package name in pipfile"""
section = self.parsed_pipfile.get(category, {})
section = self.parsed_pipfile.get(category)
if section is None:
section = {}
package_name = pep423_name(package_name)
for name in section.keys():
if pep423_name(name) == package_name:
Expand Down Expand Up @@ -969,30 +986,116 @@ def remove_packages_from_pipfile(self, packages):
self.write_toml(parsed)

def add_package_to_pipfile(self, package, dev=False, category=None):
from .vendor.requirementslib import Requirement

newly_added = False
category = category if category else "dev-packages" if dev else "packages"

# Read and append Pipfile.
p = self.parsed_pipfile
# Don't re-capitalize file URLs or VCSs.
if not isinstance(package, Requirement):
package = Requirement.from_line(package.strip(), parse_setup_info=False)
req_name, converted = package.pipfile_entry
category = category if category else "dev-packages" if dev else "packages"

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

# Don't re-capitalize file URLs or VCSs.
if not isinstance(package, InstallRequirement):
package = install_req_from_line(package.strip())

path_specifier = None
vcs_specifier = None
if package.link and package.link.scheme in [
"http",
"https",
"file",
"ftp",
"git+http",
"git+https",
"git+ssh",
"git+git",
"hg+http",
"hg+https",
"hg+ssh",
"svn+http",
"svn+https",
"svn+svn",
"bzr+http",
"bzr+https",
"bzr+ssh",
"bzr+sftp",
"bzr+ftp",
"bzr+lp",
]:
with TemporaryDirectory() as td:
cmd = get_pip_command()
options, _ = cmd.parser.parse_args([])
session = cmd._build_session(options)
file = unpack_url(
link=package.link,
location=td,
download=Downloader(session, "off"),
verbosity=1,
)
if file.path.endswith(".whl") or file.path.endswith(".zip"):
req_name = find_package_name_from_zipfile(file.path)
elif file.path.endswith(".tar.gz") or file.path.endswith(".tar.bz2"):
req_name = find_package_name_from_tarball(file.path)
else:
req_name = find_package_name_from_directory(file.path)
if package.link.scheme == "file":
path_specifier = package.link.url
else:
vcs_specifier = package.link.url_without_fragment
elif package.link and package.link.scheme == "file":
if package.link.file_path.endswith(".whl"):
req_name = find_package_name_from_zipfile(package.link.file_path)
elif package.link.file_path.endswith(".tar.gz"):
req_name = find_package_name_from_tarball(package.link.file_path)
else:
req_name = find_package_name_from_directory(package.link.file_path)
path_specifier = os.path.relpath(
package.link.file_path
) # Preserve the original file path
elif package.name:
req_name = package.name
else:
raise ValueError(f"Could not determine package name from {package}")

name = self.get_package_name_in_pipfile(req_name, category=category)
normalized_name = pep423_name(req_name)
if name and name != normalized_name:
self.remove_package_from_pipfile(name, category=category)

extras = package.extras
specifier = "*"
if package.req and package.specifier:
specifier = str(package.specifier)

# Add the package to the group.
normalized_name = normalize_name(req_name)
if normalized_name not in p[category]:
newly_added = True
p[category][normalized_name] = converted

# Construct package requirement
converted = {}
if extras:
converted["extras"] = list(extras)
if path_specifier:
converted["file"] = unquote(path_specifier)
elif vcs_specifier:
for vcs in VCS_LIST:
if vcs in package.link.scheme:
converted[vcs] = unquote(vcs_specifier)
break
else:
converted["version"] = specifier

if len(converted) == 1 and "version" in converted:
p[category][normalized_name] = specifier
else:
p[category][normalized_name] = converted

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

def src_name_from_url(self, index_url):
name, _, tld_guess = urllib.parse.urlsplit(index_url).netloc.rpartition(".")
Expand Down
Loading