Skip to content

Commit 689a949

Browse files
zyvabn
authored andcommitted
locker: reuse locked metadata for nested deps
Resolves: #3115
1 parent 63a512d commit 689a949

File tree

2 files changed

+66
-5
lines changed

2 files changed

+66
-5
lines changed

poetry/packages/locker.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,15 @@ def __get_locked_package(
234234
# project level dependencies take precedence
235235
continue
236236

237-
# we make a copy to avoid any side-effects
238-
requirement = deepcopy(requirement)
237+
locked_package = __get_locked_package(requirement)
238+
if locked_package:
239+
# create dependency from locked package to retain dependency metadata
240+
# if this is not done, we can end-up with incorrect nested dependencies
241+
requirement = locked_package.to_dependency()
242+
else:
243+
# we make a copy to avoid any side-effects
244+
requirement = deepcopy(requirement)
245+
239246
requirement._category = pkg.category
240247

241248
if pinned_versions:

tests/utils/test_exporter.py

+57-3
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,18 @@ def poetry(fixture_dir, locker):
5959
return p
6060

6161

62-
def set_package_requires(poetry):
62+
def set_package_requires(poetry, skip=None):
63+
skip = skip or set()
6364
packages = poetry.locker.locked_repository(with_dev_reqs=True).packages
6465
poetry.package.requires = [
65-
pkg.to_dependency() for pkg in packages if pkg.category == "main"
66+
pkg.to_dependency()
67+
for pkg in packages
68+
if pkg.category == "main" and pkg.name not in skip
6669
]
6770
poetry.package.dev_requires = [
68-
pkg.to_dependency() for pkg in packages if pkg.category == "dev"
71+
pkg.to_dependency()
72+
for pkg in packages
73+
if pkg.category == "dev" and pkg.name not in skip
6974
]
7075

7176

@@ -503,6 +508,55 @@ def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, poetry)
503508
assert expected == content
504509

505510

511+
def test_exporter_can_export_requirements_txt_with_nested_packages(tmp_dir, poetry):
512+
poetry.locker.mock_lock_data(
513+
{
514+
"package": [
515+
{
516+
"name": "foo",
517+
"version": "1.2.3",
518+
"category": "main",
519+
"optional": False,
520+
"python-versions": "*",
521+
"source": {
522+
"type": "git",
523+
"url": "https://github.com/foo/foo.git",
524+
"reference": "123456",
525+
},
526+
},
527+
{
528+
"name": "bar",
529+
"version": "4.5.6",
530+
"category": "main",
531+
"optional": False,
532+
"python-versions": "*",
533+
"dependencies": {"foo": "rev 123456"},
534+
},
535+
],
536+
"metadata": {
537+
"python-versions": "*",
538+
"content-hash": "123456789",
539+
"hashes": {"foo": [], "bar": []},
540+
},
541+
}
542+
)
543+
set_package_requires(poetry, skip={"foo"})
544+
545+
exporter = Exporter(poetry)
546+
547+
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
548+
549+
with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
550+
content = f.read()
551+
552+
expected = """\
553+
bar==4.5.6
554+
foo @ git+https://github.com/foo/foo.git@123456
555+
"""
556+
557+
assert expected == content
558+
559+
506560
def test_exporter_can_export_requirements_txt_with_git_packages_and_markers(
507561
tmp_dir, poetry
508562
):

0 commit comments

Comments
 (0)