Skip to content

Commit

Permalink
group packages correctly when exporting
Browse files Browse the repository at this point in the history
  • Loading branch information
dimbleby committed Feb 5, 2022
1 parent 31657e7 commit 58d2355
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/poetry/packages/locker.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def get_project_dependencies(
requirement.marker
)

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

def get_project_dependency_packages(
self,
Expand Down
24 changes: 16 additions & 8 deletions src/poetry/utils/exporter.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import itertools
import urllib.parse

from collections import defaultdict
from typing import TYPE_CHECKING
from typing import Dict
from typing import List
from typing import Optional
from typing import Sequence
from typing import Union
Expand All @@ -15,6 +17,8 @@
from pathlib import Path

from cleo.io.io import IO
from poetry.core.packages.dependency_package import DependencyPackage
from poetry.core.packages.package import Package

from poetry.poetry import Poetry

Expand Down Expand Up @@ -70,14 +74,18 @@ def _export_requirements_txt(
content = ""
dependency_lines = set()

for package, groups in itertools.groupby(
self._poetry.locker.get_project_dependency_packages(
project_requires=self._poetry.package.all_requires,
dev=dev,
extras=extras,
),
lambda dependency_package: dependency_package.package,
# Group by package.
dependency_packages: Dict["Package", List["DependencyPackage"]] = defaultdict(
list
)
for dependency_package in self._poetry.locker.get_project_dependency_packages(
project_requires=self._poetry.package.all_requires,
dev=dev,
extras=extras,
):
dependency_packages[dependency_package.package].append(dependency_package)

for package, groups in dependency_packages.items():
line = ""
dependency_packages = list(groups)
dependency = dependency_packages[0].dependency
Expand Down
108 changes: 108 additions & 0 deletions tests/utils/test_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1775,3 +1775,111 @@ def test_exporter_exports_requirements_txt_to_standard_output(
"""

assert out == expected


def test_exporter_doesnt_confuse_repeated_packages(
tmp_dir: str, poetry: "Poetry", capsys: "CaptureFixture"
):
# Testcase derived from <https://github.com/python-poetry/poetry/issues/5141>.
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "celery",
"version": "5.1.2",
"category": "main",
"optional": False,
"python-versions": "<3.7",
"dependencies": {
"click": ">=7.0,<8.0",
"click-didyoumean": ">=0.0.3",
"click-plugins": ">=1.1.1",
},
},
{
"name": "celery",
"version": "5.2.3",
"category": "main",
"optional": False,
"python-versions": ">=3.7",
"dependencies": {
"click": ">=8.0.3,<9.0",
"click-didyoumean": ">=0.0.3",
"click-plugins": ">=1.1.1",
},
},
{
"name": "click",
"version": "7.1.2",
"category": "main",
"optional": False,
"python-versions": (
">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
),
},
{
"name": "click",
"version": "8.0.3",
"category": "main",
"optional": False,
"python-versions": ">=3.6",
"dependencies": {},
},
{
"name": "click-didyoumean",
"version": "0.0.3",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {"click": "*"},
},
{
"name": "click-didyoumean",
"version": "0.3.0",
"category": "main",
"optional": False,
"python-versions": ">=3.6.2,<4.0.0",
"dependencies": {"click": ">=7"},
},
{
"name": "click-plugins",
"version": "1.1.1",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {"click": ">=4.0"},
},
],
"metadata": {
"lock-version": "1.1",
"python-versions": "^3.6",
"content-hash": (
"832b13a88e5020c27cbcd95faa577bf0dbf054a65c023b45dc9442b640d414e6"
),
"hashes": {
"celery": [],
"click-didyoumean": [],
"click-plugins": [],
"click": [],
},
},
}
)
set_package_requires(poetry)

exporter = Exporter(poetry)

exporter.export("requirements.txt", Path(tmp_dir), sys.stdout)

out, err = capsys.readouterr()
expected = (
'celery==5.1.2 ; python_version < "3.7"\n'
'celery==5.2.3 ; python_version >= "3.7"\n'
"click-didyoumean==0.0.3\n"
'click-didyoumean==0.3.0 ; python_full_version >= "3.6.2" and python_full_version < "4.0.0"\n' # noqa: E501
"click-plugins==1.1.1\n"
'click==7.1.2 ; python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "3.7" or python_full_version >= "3.5.0" and python_version < "3.7" or python_full_version >= "3.6.2" and python_full_version < "4.0.0" or python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"\n' # noqa: E501
'click==8.0.3 ; python_version >= "3.6"\n'
)

assert out == expected

0 comments on commit 58d2355

Please sign in to comment.