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

Fix for sys platform markers from Pipfile + fix for vcs subdirectory fragments #5871

Merged
merged 8 commits into from
Aug 26, 2023
1 change: 1 addition & 0 deletions news/5870.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix recent regressions with local/editable file installs.
1 change: 1 addition & 0 deletions news/5871.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes the vcs subdirectory fragments regression; fixes sys_platform markers regression.
4 changes: 4 additions & 0 deletions pipenv/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,10 @@ def generate_package_pipfile_entry(self, package, pip_line, category=None):
vcs_parts = vcs_part.rsplit("@", 1)
entry["ref"] = vcs_parts[1].split("#", 1)[0].strip()
entry[vcs] = vcs_parts[0].strip()

# Check and extract subdirectory fragment
if package.link.subdirectory_fragment:
entry["subdirectory"] = package.link.subdirectory_fragment
break
else:
entry["version"] = specifier
Expand Down
11 changes: 9 additions & 2 deletions pipenv/utils/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ def clean_resolved_dep(project, dep, is_top_level=False, current_entry=None):
else:
lockfile[vcs_type] = dep[vcs_type]
lockfile["ref"] = dep.get("ref")
if "subdirectory" in dep:
lockfile["subdirectory"] = dep["subdirectory"]
is_vcs_or_file = True

if "editable" in dep:
Expand Down Expand Up @@ -965,6 +967,9 @@ def install_req_from_pipfile(name, pipfile):

if vcs:
vcs_url = _pipfile[vcs]
subdirectory = _pipfile.get("subdirectory", "")
if subdirectory:
subdirectory = f"#subdirectory={subdirectory}"
fallback_ref = ""
if ("ssh://" in vcs_url and vcs_url.count("@") >= 2) or (
"ssh://" not in vcs_url and "@" in vcs_url
Expand All @@ -977,9 +982,11 @@ def install_req_from_pipfile(name, pipfile):
if not req_str.startswith(f"{vcs}+"):
req_str = f"{vcs}+{req_str}"
if f"{vcs}+file://" in req_str:
req_str = f"-e {req_str}#egg={name}{extras_str}"
req_str = (
f"-e {req_str}#egg={name}{extras_str}{subdirectory.replace('#', '&')}"
)
else:
req_str = f"{name}{extras_str}@ {req_str}"
req_str = f"{name}{extras_str}@ {req_str}{subdirectory}"
elif "path" in _pipfile:
req_str = str(Path(_pipfile["path"]).as_posix())
elif "file" in _pipfile:
Expand Down
2 changes: 2 additions & 0 deletions pipenv/utils/locking.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ def format_requirement_for_lockfile(
entry[vcs] = original_deps[name]
else:
entry[vcs] = req.link.url
if pipfile_entry.get("subdirectory"):
entry["subdirectory"] = pipfile_entry["subdirectory"]
if req.req:
entry["version"] = str(req.specifier)
elif version:
Expand Down
17 changes: 2 additions & 15 deletions pipenv/utils/markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@ class PipenvMarkers(BaseModel):
implementation_name: Optional[str] = None
implementation_version: Optional[str] = None

@property
def line_part(self):
return " and ".join([f"{k} {v}" for k, v in self.dict().items() if v is not None])

@property
def pipfile_part(self):
return {"markers": self.as_line}

@classmethod
def make_marker(cls, marker_string):
try:
Expand All @@ -53,20 +45,15 @@ def make_marker(cls, marker_string):
)
return marker

@classmethod
def from_line(cls, line):
if ";" in line:
line = line.rsplit(";", 1)[1].strip()
marker = cls.make_marker(line)
return marker

@classmethod
def from_pipfile(cls, name, pipfile):
attr_fields = list(cls.__fields__)
found_keys = [k for k in pipfile.keys() if k in attr_fields]
marker_strings = [f"{k} {pipfile[k]}" for k in found_keys]
if pipfile.get("markers"):
marker_strings.append(pipfile.get("markers"))
if pipfile.get("sys_platform"):
marker_strings.append(f"sys_platform '{pipfile['sys_platform']}'")
markers = set()
for marker in marker_strings:
markers.add(marker)
Expand Down
29 changes: 19 additions & 10 deletions pipenv/utils/requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,18 @@ def requirement_from_lockfile(
return f"{package_name}=={package_info}"
else:
return package_name

markers = (
"; {}".format(package_info["markers"])
if include_markers and "markers" in package_info and package_info["markers"]
else ""
)
os_markers = (
"; {}".format(package_info["os_markers"])
if include_markers and "os_markers" in package_info and package_info["os_markers"]
else ""
)

# Handling vcs repositories
for vcs in VCS_LIST:
if vcs in package_info:
Expand All @@ -171,13 +183,16 @@ def requirement_from_lockfile(
if "extras" in package_info
else ""
)
subdirectory = package_info.get("subdirectory", "")
include_vcs = "" if f"{vcs}+" in url else f"{vcs}+"
egg_fragment = "" if "#egg=" in url else f"#egg={package_name}"
ref_str = "" if not ref or f"@{ref}" in url else f"@{ref}"
if is_editable_path(url) or "file://" in url:
pip_line = f"-e {include_vcs}{url}{ref_str}{egg_fragment}{extras}"
pip_line += f"&subdirectory={subdirectory}" if subdirectory else ""
else:
pip_line = f"{package_name}{extras}@ {include_vcs}{url}{ref_str}"
pip_line += f"#subdirectory={subdirectory}" if subdirectory else ""
return pip_line
# Handling file-sourced packages
for k in ["file", "path"]:
Expand All @@ -187,6 +202,10 @@ def requirement_from_lockfile(
if is_editable_path(path):
line.append("-e")
line.append(f"{package_info[k]}")
if os_markers:
line.append(os_markers)
if markers:
line.append(markers)
pip_line = " ".join(line)
return pip_line

Expand All @@ -197,16 +216,6 @@ def requirement_from_lockfile(
if include_hashes and "hashes" in package_info
else ""
)
markers = (
"; {}".format(package_info["markers"])
if include_markers and "markers" in package_info and package_info["markers"]
else ""
)
os_markers = (
"; {}".format(package_info["os_markers"])
if include_markers and "os_markers" in package_info and package_info["os_markers"]
else ""
)
extras = (
"[{}]".format(",".join(package_info.get("extras", [])))
if "extras" in package_info
Expand Down