Skip to content

Commit

Permalink
locker: unify duplicate dependencies on export
Browse files Browse the repository at this point in the history
  • Loading branch information
abn committed Oct 13, 2020
1 parent 4468d5e commit 79f8ed9
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 17 deletions.
19 changes: 13 additions & 6 deletions poetry/packages/locker.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import itertools
import json
import logging
import os
import re

from copy import deepcopy
from hashlib import sha256
from typing import Iterable
from typing import Iterator
from typing import List
from typing import Optional
Expand Down Expand Up @@ -188,7 +188,7 @@ def locked_repository(
@classmethod
def get_project_dependencies(
cls, project_requires, locked_packages, pinned_versions=False, with_nested=False
): # type: (List[Dependency], List[Package], bool, bool) -> List[Dependency]
): # type: (List[Dependency], List[Package], bool, bool) -> Iterable[Dependency]
# group packages entries by name, this is required because requirement might use
# different constraints
packages_by_name = {}
Expand Down Expand Up @@ -296,10 +296,17 @@ def __walk_level(

__walk_level(dependencies, 0)

return sorted(
itertools.chain(dependencies, nested_dependencies.values()),
key=lambda x: x.name.lower(),
)
# Merge same dependencies using marker union
for requirement in dependencies:
key = (requirement.name, requirement.pretty_constraint)
if key not in nested_dependencies:
nested_dependencies[key] = requirement
else:
nested_dependencies[key].marker = nested_dependencies[key].marker.union(
requirement.marker
)

return sorted(nested_dependencies.values(), key=lambda x: x.name.lower())

def get_project_dependency_packages(
self, project_requires, dev=False, extras=None
Expand Down
18 changes: 7 additions & 11 deletions tests/utils/test_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,12 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers(
assert expected == {}


@pytest.mark.parametrize(
"dev,lines",
[(False, ['a==1.2.3; python_version < "3.8"']), (True, ["a==1.2.3", "b==4.5.6"])],
)
def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers_any(
tmp_dir, poetry
tmp_dir, poetry, dev, lines
):
poetry.locker.mock_lock_data(
{
Expand Down Expand Up @@ -295,24 +299,16 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers_a
Factory.create_dependency(
name="b", constraint=dict(version="^4.5.6"), category="dev"
),
Factory.create_dependency(name="a", constraint=dict(version="^1.2.3")),
]

exporter = Exporter(poetry)

exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=dev)

with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()

assert (
content
== """\
a==1.2.3
a==1.2.3; python_version < "3.8"
b==4.5.6
"""
)
assert content.strip() == "\n".join(lines)


def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes(
Expand Down

0 comments on commit 79f8ed9

Please sign in to comment.