Skip to content

Commit d0c15a2

Browse files
committed
Resolve symlinks in locker.lock path to real physical paths
Fixes #5849
1 parent 3f54fdc commit d0c15a2

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

src/poetry/packages/locker.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,8 @@ def _dump_package(self, package: Package) -> dict[str, Any]:
603603
# The lock file should only store paths relative to the root project
604604
url = Path(
605605
os.path.relpath(
606-
Path(url).as_posix(), self._lock.path.parent.as_posix()
606+
Path(os.path.realpath(url)).as_posix(),
607+
Path(os.path.realpath(self._lock.path.parent)).as_posix(),
607608
)
608609
).as_posix()
609610

tests/packages/test_locker.py

+77
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import json
44
import logging
5+
import os
56
import tempfile
67
import uuid
78

@@ -753,3 +754,79 @@ def test_content_hash_with_legacy_is_compatible(
753754
content_hash = locker._get_content_hash()
754755

755756
assert (content_hash == old_content_hash) or fresh
757+
758+
759+
def test_lock_file_resolves_file_url_symlinks(root: ProjectPackage):
760+
"""
761+
Create directories and file structure as follows:
762+
763+
d1/
764+
d1/testsymlink -> d1/d2/d3
765+
d1/d2/d3/lock_file
766+
d1/d4/source_file
767+
768+
Using the testsymlink as the Locker.lock file path should correctly resolve to
769+
the real physical path of the source_file when calculating the relative path
770+
from the lock_file, i.e. "../../d4/source_file" instead of the unresolved path
771+
from the symlink itself which would have been "../d4/source_file"
772+
773+
See https://github.com/python-poetry/poetry/issues/5849
774+
"""
775+
with tempfile.TemporaryDirectory() as d1:
776+
symlink_path = Path(d1).joinpath("testsymlink")
777+
with tempfile.TemporaryDirectory(dir=d1) as d2, tempfile.TemporaryDirectory(
778+
dir=d1
779+
) as d4, tempfile.TemporaryDirectory(dir=d2) as d3, tempfile.NamedTemporaryFile(
780+
dir=d4
781+
) as source_file, tempfile.NamedTemporaryFile(
782+
dir=d3
783+
) as lock_file:
784+
lock_file.close()
785+
symlink_path.symlink_to(Path(d3))
786+
locker = Locker(
787+
str(symlink_path) + os.sep + lock_file.name.split(os.sep)[-1], {}
788+
)
789+
790+
package_local = Package(
791+
"local-package",
792+
"1.2.3",
793+
source_type="file",
794+
source_url=source_file.name,
795+
source_reference="develop",
796+
source_resolved_reference="123456",
797+
)
798+
packages = [
799+
package_local,
800+
]
801+
802+
locker.set_lock_data(root, packages)
803+
804+
with locker.lock.open(encoding="utf-8") as f:
805+
content = f.read()
806+
807+
expected = f"""\
808+
[[package]]
809+
name = "local-package"
810+
version = "1.2.3"
811+
description = ""
812+
category = "main"
813+
optional = false
814+
python-versions = "*"
815+
816+
[package.source]
817+
type = "file"
818+
url = "{Path(os.path.relpath(Path(os.path.realpath(source_file.name)).as_posix(),
819+
Path(os.path.realpath(Path(lock_file.name).parent)).as_posix())).as_posix()}"
820+
reference = "develop"
821+
resolved_reference = "123456"
822+
823+
[metadata]
824+
lock-version = "1.1"
825+
python-versions = "*"
826+
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
827+
828+
[metadata.files]
829+
local-package = []
830+
"""
831+
832+
assert content == expected

0 commit comments

Comments
 (0)