Commit 73437a84 by Florian Apolloner Committed by Steph Samson

Fixed propagation of markers to dependencies. Fixes #3254

parent cddd6759
...@@ -269,9 +269,9 @@ class Locker(object): ...@@ -269,9 +269,9 @@ class Locker(object):
if key not in nested_dependencies: if key not in nested_dependencies:
nested_dependencies[key] = requirement nested_dependencies[key] = requirement
else: else:
nested_dependencies[key].marker = nested_dependencies[ nested_dependencies[key].marker = nested_dependencies[key].marker.union(
key requirement.marker
].marker.intersect(requirement.marker) )
return cls.__walk_dependency_level( return cls.__walk_dependency_level(
dependencies=next_level_dependencies, dependencies=next_level_dependencies,
......
...@@ -175,6 +175,200 @@ foo==1.2.3; python_version < "3.7" ...@@ -175,6 +175,200 @@ foo==1.2.3; python_version < "3.7"
assert expected == content assert expected == content
def test_exporter_can_export_requirements_txt_poetry(tmp_dir, poetry):
"""Regression test for #3254"""
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "poetry",
"version": "1.1.4",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {"keyring": "*"},
},
{
"name": "junit-xml",
"version": "1.9",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {"six": "*"},
},
{
"name": "keyring",
"version": "21.8.0",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {
"SecretStorage": {
"version": "*",
"markers": "sys_platform == 'linux'",
}
},
},
{
"name": "secretstorage",
"version": "3.3.0",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {"cryptography": "*"},
},
{
"name": "cryptography",
"version": "3.2",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {"six": "*"},
},
{
"name": "six",
"version": "1.15.0",
"category": "main",
"optional": False,
"python-versions": "*",
},
],
"metadata": {
"python-versions": "*",
"content-hash": "123456789",
"hashes": {
"poetry": [],
"keyring": [],
"secretstorage": [],
"cryptography": [],
"six": [],
"junit-xml": [],
},
},
}
)
set_package_requires(
poetry, skip={"keyring", "secretstorage", "cryptography", "six"}
)
exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()
# The dependency graph:
# junit-xml 1.9 Creates JUnit XML test result documents that can be read by tools such as Jenkins
# └── six *
# poetry 1.1.4 Python dependency management and packaging made easy.
# ├── keyring >=21.2.0,<22.0.0
# │ ├── importlib-metadata >=1
# │ │ └── zipp >=0.5
# │ ├── jeepney >=0.4.2
# │ ├── pywin32-ctypes <0.1.0 || >0.1.0,<0.1.1 || >0.1.1
# │ └── secretstorage >=3.2 -- On linux only
# │ ├── cryptography >=2.0
# │ │ └── six >=1.4.1
# │ └── jeepney >=0.6 (circular dependency aborted here)
expected = {
"poetry": dependency_from_pep_508("poetry==1.1.4"),
"junit-xml": dependency_from_pep_508("junit-xml==1.9"),
"keyring": dependency_from_pep_508("keyring==21.8.0"),
"secretstorage": dependency_from_pep_508(
"secretstorage==3.3.0; sys_platform=='linux'"
),
"cryptography": dependency_from_pep_508(
"cryptography==3.2; sys_platform=='linux'"
),
"six": dependency_from_pep_508("six==1.15.0"),
}
for line in content.strip().split("\n"):
dependency = dependency_from_pep_508(line)
assert dependency.name in expected
expected_dependency = expected.pop(dependency.name)
assert dependency == expected_dependency
print(dependency.marker)
print(expected_dependency.marker)
assert dependency.marker == expected_dependency.marker
def test_exporter_can_export_requirements_txt_pyinstaller(tmp_dir, poetry):
"""Regression test for #3254"""
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "pyinstaller",
"version": "4.0",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {
"altgraph": "*",
"macholib": {
"version": "*",
"markers": "sys_platform == 'darwin'",
},
},
},
{
"name": "altgraph",
"version": "0.17",
"category": "main",
"optional": False,
"python-versions": "*",
},
{
"name": "macholib",
"version": "1.8",
"category": "main",
"optional": False,
"python-versions": "*",
"dependencies": {"altgraph": ">=0.15"},
},
],
"metadata": {
"python-versions": "*",
"content-hash": "123456789",
"hashes": {"pyinstaller": [], "altgraph": [], "macholib": []},
},
}
)
set_package_requires(poetry, skip={"altgraph", "macholib"})
exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()
# Rationale for the results:
# * PyInstaller has an explicit dependency on altgraph, so it must always be installed.
# * PyInstaller requires macholib on Darwin, which in turn requires altgraph.
# The dependency graph:
# pyinstaller 4.0 PyInstaller bundles a Python application and all its dependencies into a single package.
# ├── altgraph *
# ├── macholib >=1.8 -- only on Darwin
# │ └── altgraph >=0.15
expected = {
"pyinstaller": dependency_from_pep_508("pyinstaller==4.0"),
"altgraph": dependency_from_pep_508("altgraph==0.17"),
"macholib": dependency_from_pep_508("macholib==1.8; sys_platform == 'darwin'"),
}
for line in content.strip().split("\n"):
dependency = dependency_from_pep_508(line)
assert dependency.name in expected
expected_dependency = expected.pop(dependency.name)
assert dependency == expected_dependency
assert dependency.marker == expected_dependency.marker
def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers( def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers(
tmp_dir, poetry tmp_dir, poetry
): ):
...@@ -241,7 +435,7 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers( ...@@ -241,7 +435,7 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers(
"c==7.8.9; sys_platform == 'win32' and python_version < '3.7'" "c==7.8.9; sys_platform == 'win32' and python_version < '3.7'"
), ),
"d": dependency_from_pep_508( "d": dependency_from_pep_508(
"d==0.0.1; python_version < '3.7' and platform_system == 'Windows' and sys_platform == 'win32'" "d==0.0.1; platform_system == 'Windows' and python_version < '3.7' or sys_platform == 'win32' and python_version < '3.7'"
), ),
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment