Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix requires(..., package_id_mode=) with diamonds #16987

Merged
merged 2 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion conans/model/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ def __init__(self, ref, package_id, default_package_id_mode):
try:
func_package_id_mode = getattr(self, default_package_id_mode)
except AttributeError:
raise ConanException("'%s' is not a known package_id_mode" % default_package_id_mode)
raise ConanException(f"require {self._ref} package_id_mode='{default_package_id_mode}' "
"is not a known package_id_mode")
else:
func_package_id_mode()

Expand Down
5 changes: 4 additions & 1 deletion conans/model/requires.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,10 @@ def aggregate(self, other):
self.transitive_libs = self.transitive_libs or other.transitive_libs
if not other.test:
self.test = False # it it was previously a test, but also required by non-test
# TODO: self.package_id_mode => Choose more restrictive?
# package_id_mode is not being propagated downstream. So it is enough to check if the
# current require already defined it or not
if self.package_id_mode is None:
self.package_id_mode = other.package_id_mode

def transform_downstream(self, pkg_type, require, dep_pkg_type):
"""
Expand Down
85 changes: 84 additions & 1 deletion test/integration/package_id/package_id_requires_modes_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class TestPackageIDRequirementsModes:
[("unrelated_mode", "2.0", "", ""),
("patch_mode", "1.0.0.1", "1.0.1", "1.0.1"),
("minor_mode", "1.0.1", "1.2", "1.2.Z"),
("minor_mode", "1.0.1", "1.2", "1.2.Z"),
("major_mode", "1.5", "2.0", "2.Y.Z"),
("semver_mode", "1.5", "2.0", "2.Y.Z"),
("full_mode", "1.0", "1.0.0.1", "1.0.0.1")])
Expand Down Expand Up @@ -110,3 +109,87 @@ def package_id(self):
self.assertIn("dep2/1.0@user/testing: PkgNames: ['dep1']", client.out)
self.assertIn("consumer/1.0@user/testing: PKGNAMES: ['dep1', 'dep2']", client.out)
self.assertIn("consumer/1.0@user/testing: Created", client.out)


class TestRequirementPackageId:
""" defining requires(..., package_id_mode)
"""

@pytest.mark.parametrize("mode, pattern",
[("patch_mode", "1.2.3"),
("minor_mode", "1.2.Z"),
("major_mode", "1.Y.Z")])
def test(self, mode, pattern):
c = TestClient(light=True)
pkg = GenConanfile("pkg", "0.1").with_requirement("dep/1.2.3", package_id_mode=mode)
c.save({"dep/conanfile.py": GenConanfile("dep", "1.2.3"),
"pkg/conanfile.py": pkg})
c.run("create dep")
c.run("create pkg")
c.run("list pkg:*")
assert f"dep/{pattern}" in c.out

def test_wrong_mode(self):
c = TestClient(light=True)
pkg = GenConanfile("pkg", "0.1").with_requirement("dep/1.2.3", package_id_mode="nothing")
c.save({"dep/conanfile.py": GenConanfile("dep", "1.2.3"),
"pkg/conanfile.py": pkg})
c.run("create dep")
c.run("create pkg", assert_error=True)
assert "ERROR: require dep/1.2.3 package_id_mode='nothing' is not a known package_id_mode" \
in c.out

@pytest.mark.parametrize("mode, pattern",
[("patch_mode", "1.2.3"),
("minor_mode", "1.2.Z"),
("major_mode", "1.Y.Z")])
def test_half_diamond(self, mode, pattern):
# pkg -> libb -> liba
# \----(mode)----/
c = TestClient(light=True)
pkg = GenConanfile("pkg", "0.1").with_requirement("liba/1.2.3", package_id_mode=mode)\
.with_requirement("libb/1.2.3")
c.save({"liba/conanfile.py": GenConanfile("liba", "1.2.3"),
"libb/conanfile.py": GenConanfile("libb", "1.2.3").with_requires("liba/1.2.3"),
"pkg/conanfile.py": pkg})
c.run("create liba")
c.run("create libb")
c.run("create pkg")
c.run("list pkg:*")
assert f"liba/{pattern}" in c.out
# reverse order also works the same
pkg = GenConanfile("pkg", "0.1").with_requirement("libb/1.2.3")\
.with_requirement("liba/1.2.3", package_id_mode=mode)
c.save({"pkg/conanfile.py": pkg})
c.run("create pkg")
c.run("list pkg:*")
assert f"liba/{pattern}" in c.out

@pytest.mark.parametrize("mode, pattern",
[("patch_mode", "1.2.3"),
("minor_mode", "1.2.Z"),
("major_mode", "1.Y.Z")])
def test_half_diamond_conflict(self, mode, pattern):
# pkg -> libb --(mode)-> liba
# \----(mode)-----------/
# The libb->liba mode is not propagated down to pkg, so it doesn't really conflict
c = TestClient(light=True)
pkg = GenConanfile("pkg", "0.1").with_requirement("liba/1.2.3", package_id_mode=mode) \
.with_requirement("libb/1.2.3")
libb = GenConanfile("libb", "1.2.3").with_requirement("liba/1.2.3",
package_id_mode="patch_mode")
c.save({"liba/conanfile.py": GenConanfile("liba", "1.2.3"),
"libb/conanfile.py": libb,
"pkg/conanfile.py": pkg})
c.run("create liba")
c.run("create libb")
c.run("create pkg")
c.run("list pkg:*")
assert f"liba/{pattern}" in c.out
# reverse order also works the same
pkg = GenConanfile("pkg", "0.1").with_requirement("libb/1.2.3") \
.with_requirement("liba/1.2.3", package_id_mode=mode)
c.save({"pkg/conanfile.py": pkg})
c.run("create pkg")
c.run("list pkg:*")
assert f"liba/{pattern}" in c.out