Skip to content

Commit d0ce82a

Browse files
committed
Correctly normalize paths relative to install path
Since the legacy installed-files.txt writes paths relatively to the egg-info directory, we need to introduce a new property on BaseDistribution to return that directory's path (analoguous to pkg_resources's Distribution.egg_info). Entries in RECORD are normalized with pathlib.Path so they have the correct path component separator depending on the platform (e.g. '/' on Windows), to match the previous behavior.
1 parent e1ccc43 commit d0ce82a

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

src/pip/_internal/commands/show.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import csv
22
import logging
3-
import os
3+
import pathlib
44
from optparse import Values
55
from typing import Iterator, List, NamedTuple, Optional
66

@@ -102,12 +102,17 @@ def _files_from_record(dist: BaseDistribution) -> Optional[Iterator[str]]:
102102
return None
103103
return (row[0] for row in csv.reader(text.splitlines()))
104104

105-
def _files_from_installed_files(dist: BaseDistribution) -> Optional[Iterator[str]]:
105+
def _files_from_legacy(dist: BaseDistribution) -> Optional[Iterator[str]]:
106106
try:
107107
text = dist.read_text('installed-files.txt')
108108
except FileNotFoundError:
109109
return None
110-
return (p for p in text.splitlines(keepends=False) if p)
110+
paths = (p for p in text.splitlines(keepends=False) if p)
111+
root = dist.location
112+
info = dist.metadata_directory
113+
if root is None or info is None:
114+
return paths
115+
return (str(pathlib.Path(info, p).resolve().relative_to(root)) for p in paths)
111116

112117
for query_name in query_names:
113118
try:
@@ -121,11 +126,11 @@ def _files_from_installed_files(dist: BaseDistribution) -> Optional[Iterator[str
121126
except FileNotFoundError:
122127
entry_points = []
123128

124-
files_iter = _files_from_record(dist) or _files_from_installed_files(dist)
129+
files_iter = _files_from_record(dist) or _files_from_legacy(dist)
125130
if files_iter is None:
126131
files: Optional[List[str]] = None
127132
else:
128-
files = sorted(os.path.relpath(p, dist.location) for p in files_iter)
133+
files = sorted(files_iter)
129134

130135
metadata = dist.metadata
131136

src/pip/_internal/metadata/base.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ def location(self) -> Optional[str]:
6060
"""
6161
raise NotImplementedError()
6262

63+
@property
64+
def metadata_directory(self) -> Optional[str]:
65+
"""Location of the metadata directory.
66+
67+
Similarly to ``location``, a string value is not necessarily a
68+
filesystem path. ``None`` means the distribution is created in-memory.
69+
70+
For a modern .dist-info installation on disk, this should be something
71+
like ``{location}/{raw_name}-{version}.dist-info``.
72+
"""
73+
raise NotImplementedError()
74+
6375
@property
6476
def canonical_name(self) -> "NormalizedName":
6577
raise NotImplementedError()

src/pip/_internal/metadata/pkg_resources.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ def from_wheel(cls, path: str, name: str) -> "Distribution":
4848
def location(self) -> Optional[str]:
4949
return self._dist.location
5050

51+
@property
52+
def metadata_directory(self) -> Optional[str]:
53+
return self._dist.egg_info
54+
5155
@property
5256
def canonical_name(self) -> "NormalizedName":
5357
return canonicalize_name(self._dist.project_name)

0 commit comments

Comments
 (0)