Skip to content

Commit 31e16ee

Browse files
committed
correctly pop existing links for package overrides
1 parent 714b245 commit 31e16ee

File tree

7 files changed

+39
-21
lines changed

7 files changed

+39
-21
lines changed

python/private/py_executable.bzl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -680,17 +680,32 @@ def _create_venv_symlinks(ctx, venv_dir_map):
680680
return venv_files
681681

682682
def _build_link_map(entries):
683-
# dict[str kind, dict[str key or rel_path, tuple[str rel_path, str link_to_path]]]
683+
# dict[str kind, dict[str rel_path, str link_to_path]]
684684
link_map = {}
685+
686+
# Here we store venv paths by package
687+
# dict[str package, dict[str kind, list[str venv_path]]]
688+
pkg_map = {}
685689
for entry in entries:
686690
kind = entry.kind
687691
kind_map = link_map.setdefault(kind, {})
688692

693+
# If we detect that we are adding a dist-info for an already existing package
694+
# we need to pop all of the previous symlinks from the link_map
695+
if entry.venv_path.endswith(".dist-info") and entry.src in pkg_map:
696+
# dist-info will come always first
697+
for kind, dir_paths in pkg_map.pop(entry.src).items():
698+
for dir_path in dir_paths:
699+
link_map[kind].pop(dir_path)
700+
701+
pkg_venv_paths = pkg_map.setdefault(entry.src, {}).setdefault(entry.kind, [])
702+
pkg_venv_paths.append(entry.venv_path)
703+
689704
# We overwrite duplicates by design. The dependency closer to the
690705
# binary gets precedence due to the topological ordering.
691706
#
692707
# This allows us to store only one version of the dist-info that is needed
693-
kind_map[entry.key or entry.venv_path] = (entry.venv_path, entry.link_to_path)
708+
kind_map[entry.venv_path] = entry.link_to_path
694709

695710
# An empty link_to value means to not create the site package symlink.
696711
# Because of the topological ordering, this allows binaries to remove
@@ -710,7 +725,7 @@ def _build_link_map(entries):
710725
for _ in range(len(kind_map)):
711726
if not kind_map:
712727
break
713-
_, (dirname, value) = kind_map.popitem()
728+
dirname, value = kind_map.popitem()
714729
keep_kind_map[dirname] = value
715730
prefix = dirname + "/" # Add slash to prevent /X matching /XY
716731
for maybe_suffix in kind_map.keys():

python/private/py_info.bzl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,6 @@ VenvSymlinkEntry = provider(
5656
An entry in `PyInfo.venv_symlinks`
5757
""",
5858
fields = {
59-
"key": """
60-
:type: str | None
61-
62-
Represents the value that gets used to key entries so that each package is represented only once.
63-
""",
6459
"kind": """
6560
:type: str
6661
@@ -72,6 +67,11 @@ the venv to create the path under.
7267
7368
A runfiles-root relative path that `venv_path` will symlink to. If `None`,
7469
it means to not create a symlink.
70+
""",
71+
"src": """
72+
:type: str | None
73+
74+
Represents the PyPI package that the code originates from.
7575
""",
7676
"venv_path": """
7777
:type: str

python/private/py_library.bzl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ def _get_venv_symlinks(ctx, dist_info_metadata):
271271
repo_runfiles_dirname = None
272272
dirs_with_init = {} # dirname -> runfile path
273273
venv_symlinks = []
274-
package = ""
274+
package = None
275275
if dist_info_metadata:
276276
# in order to be able to have replacements in the venv, we have to add a
277277
# third value into the venv_symlinks, which would be the normalized
@@ -284,9 +284,9 @@ def _get_venv_symlinks(ctx, dist_info_metadata):
284284

285285
repo_runfiles_dirname = runfiles_root_path(ctx, dist_info_metadata.short_path).partition("/")[0]
286286
venv_symlinks.append(VenvSymlinkEntry(
287-
key = "{}.dist-info".format(package),
288287
kind = VenvSymlinkKind.LIB,
289288
link_to_path = paths.join(repo_runfiles_dirname, site_packages_root, dist_info_dir),
289+
src = package,
290290
venv_path = dist_info_dir,
291291
))
292292

@@ -308,9 +308,9 @@ def _get_venv_symlinks(ctx, dist_info_metadata):
308308
# This would be files that do not have directories and we just need to add
309309
# direct symlinks to them as is:
310310
venv_symlinks.append(VenvSymlinkEntry(
311-
key = None,
312311
kind = VenvSymlinkKind.LIB,
313312
link_to_path = paths.join(repo_runfiles_dirname, site_packages_root, filename),
313+
src = package,
314314
venv_path = filename,
315315
))
316316

@@ -330,9 +330,9 @@ def _get_venv_symlinks(ctx, dist_info_metadata):
330330

331331
for dirname in first_level_explicit_packages:
332332
venv_symlinks.append(VenvSymlinkEntry(
333-
key = None,
334333
kind = VenvSymlinkKind.LIB,
335334
link_to_path = paths.join(repo_runfiles_dirname, site_packages_root, dirname),
335+
src = package,
336336
venv_path = dirname,
337337
))
338338
return venv_symlinks
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
# Intentionally empty
2-
31
__version__ = "1.0.0"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Intentionally empty
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
# Intentionally empty
2-
31
__version__ = "2.0.0"

tests/venv_site_packages_libs/bin.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,26 @@ def test_imported_from_venv(self):
3333
def test_distinfo_is_overriden(self):
3434
self.assert_imported_from_venv("simple")
3535
module = importlib.import_module("simple")
36-
module_path = Path(module.__file__)
37-
site_packages = module_path.parent.parent
38-
39-
dist_info_dirs = [p.name for p in site_packages.glob("*.dist-info")]
40-
4136
self.assertEqual(
4237
"2.0.0",
4338
module.__version__,
4439
)
40+
module_path = Path(module.__file__)
41+
42+
site_packages = module_path.parent.parent
43+
dist_info_dirs = [p.name for p in site_packages.glob("*.dist-info")]
4544
self.assertEqual(
4645
["simple-2.0.0.dist-info"],
4746
dist_info_dirs,
4847
)
4948

49+
# Ensure that packages from simple v1 are not present
50+
files = [p.name for p in site_packages.glob("*")]
51+
self.assertNotIn(
52+
"simple_extras",
53+
files,
54+
)
55+
5056

5157
if __name__ == "__main__":
5258
unittest.main()

0 commit comments

Comments
 (0)