From 6502f0a8610128c631e90ca99e1a9ec09bfd296a Mon Sep 17 00:00:00 2001 From: memsharded Date: Mon, 8 Jan 2024 17:18:53 +0100 Subject: [PATCH 1/5] explore nested ANY settings.yml --- conans/model/settings.py | 9 +++++-- conans/test/unittests/model/settings_test.py | 27 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/conans/model/settings.py b/conans/model/settings.py index 189bb71185d..d55e0f37452 100644 --- a/conans/model/settings.py +++ b/conans/model/settings.py @@ -106,6 +106,11 @@ def _get_child(self, item): raise undefined_field(self._name, item, None, self._value) if self._value is None: raise ConanException("'%s' value not defined" % self._name) + return self._get_definition() + + def _get_definition(self): + if self._value not in self._definition and "ANY" in self._definition: + return self._definition["ANY"] return self._definition[self._value] def __getattr__(self, item): @@ -142,7 +147,7 @@ def values_list(self): partial_name = ".".join(self._name.split(".")[1:]) result.append((partial_name, self._value)) if isinstance(self._definition, dict): - sub_config_dict = self._definition[self._value] + sub_config_dict = self._get_definition() result.extend(sub_config_dict.values_list) return result @@ -150,7 +155,7 @@ def validate(self): if self._value is None and None not in self._definition: raise ConanException("'%s' value not defined" % self._name) if isinstance(self._definition, dict): - self._definition[self._value].validate() + self._get_definition().validate() def possible_values(self): if isinstance(self._definition, list): diff --git a/conans/test/unittests/model/settings_test.py b/conans/test/unittests/model/settings_test.py index b80904ff3f6..94d4a44673c 100644 --- a/conans/test/unittests/model/settings_test.py +++ b/conans/test/unittests/model/settings_test.py @@ -1,3 +1,4 @@ +import textwrap import unittest import pytest @@ -48,6 +49,32 @@ def test_none_any(self): self.assertTrue(settings.os == "Windows") self.assertEqual("os=Windows", settings.dumps()) + def test_nested_any(self): + yml = textwrap.dedent("""\ + os: + ANY: + version: [null, ANY] + Ubuntu: + version: ["18.04", "20.04"] + """) + settings = Settings.loads(yml) + settings.os = "Windows" + settings.validate() + self.assertTrue(settings.os == "Windows") + self.assertIn("os=Windows", settings.dumps()) + settings.os.version = 2 + self.assertTrue(settings.os == "Windows") + self.assertEqual("os=Windows\nos.version=2", settings.dumps()) + settings.os = "Ubuntu" + with self.assertRaisesRegex(ConanException, "'settings.os.version' value not defined"): + settings.validate() + with self.assertRaisesRegex(ConanException, + "Invalid setting '3' is not a valid 'settings.os.version'"): + settings.os.version = 3 + settings.os.version = "20.04" + self.assertEqual("os=Ubuntu\nos.version=20.04", settings.dumps()) + self.assertTrue(settings.os.version == "20.04") + def test_getattr_none(self): yml = "os: [None, Windows]" settings = Settings.loads(yml) From bcb9ca4cad711ce86c5565680b71b70a6f2edae4 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 10 Jan 2024 13:19:40 +0100 Subject: [PATCH 2/5] wip --- .../integration/package_id/build_id_test.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/conans/test/integration/package_id/build_id_test.py b/conans/test/integration/package_id/build_id_test.py index 3a6078e31d3..260897adc2f 100644 --- a/conans/test/integration/package_id/build_id_test.py +++ b/conans/test/integration/package_id/build_id_test.py @@ -134,6 +134,50 @@ def build(self): client.run("create . --name=pkg --version=0.1 ", assert_error=True) assert "ERROR: pkg/0.1: Error in build() method, line 5" in client.out + def test_any_os_arch(self): + conanfile_os = textwrap.dedent(""" + import os + from conan import ConanFile + + class MyTest(ConanFile): + name = "pkg" + version = "0.1" + settings = "os", "arch", "build_type" + + def build_id(self): + self.info_build.settings.build_type = "Any" + self.info_build.settings.os = "Any" + self.info_build.settings.arch = "Any" + + def build(self): + self.output.info("Building my code!") + + def package(self): + self.output.info("Packaging %s-%s!" % (self.settings.os, self.settings.arch)) + """) + + client = TestClient() + client.save({"conanfile.py": conanfile_os}) + client.run("create . -s os=Windows -s arch=x86_64 -s build_type=Release") + print(client.out) + assert "pkg/0.1: Calling build()" in client.out + assert "Building my code!" in client.out + assert "Packaging Release!" in client.out + # Debug must not build + client.run("create . -s os=Windows -s build_type=Debug") + assert "pkg/0.1: Calling build()" not in client.out + assert "Building my code!" not in client.out + assert "Packaging Debug!" in client.out + + client.run("create . -s os=Linux -s build_type=Release") + assert "pkg/0.1: Calling build()" in client.out + assert "Building my code!" in client.out + assert "Packaging Release!" in client.out + client.run("create . -s os=Linux -s build_type=Debug") + assert "Building my code!" in client.out + assert "pkg/0.1: Calling build()" in client.out + assert "Packaging Debug!" in client.out + def test_remove_require(): c = TestClient() From 0b8802660cab3e2fdbd036e28e6b9585daba6f54 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 10 Jan 2024 16:06:46 +0100 Subject: [PATCH 3/5] fixing test --- conans/model/settings.py | 1 + .../integration/package_id/build_id_test.py | 18 ++++-------------- .../integration/package_id/package_id_test.py | 7 +++---- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/conans/model/settings.py b/conans/model/settings.py index d55e0f37452..5adbaefa4a1 100644 --- a/conans/model/settings.py +++ b/conans/model/settings.py @@ -72,6 +72,7 @@ def copy_conaninfo_settings(self): else: result._definition = {k: v.copy_conaninfo_settings() for k, v in self._definition.items()} + result._definition["ANY"] = SettingsItem([], "ANY") return result def __bool__(self): diff --git a/conans/test/integration/package_id/build_id_test.py b/conans/test/integration/package_id/build_id_test.py index 260897adc2f..ed39685946b 100644 --- a/conans/test/integration/package_id/build_id_test.py +++ b/conans/test/integration/package_id/build_id_test.py @@ -159,24 +159,14 @@ def package(self): client = TestClient() client.save({"conanfile.py": conanfile_os}) client.run("create . -s os=Windows -s arch=x86_64 -s build_type=Release") - print(client.out) assert "pkg/0.1: Calling build()" in client.out assert "Building my code!" in client.out - assert "Packaging Release!" in client.out - # Debug must not build - client.run("create . -s os=Windows -s build_type=Debug") + assert "Packaging Windows-x86_64!" in client.out + # Others must not build + client.run("create . -s os=Linux -s arch=x86 -s build_type=Debug") assert "pkg/0.1: Calling build()" not in client.out assert "Building my code!" not in client.out - assert "Packaging Debug!" in client.out - - client.run("create . -s os=Linux -s build_type=Release") - assert "pkg/0.1: Calling build()" in client.out - assert "Building my code!" in client.out - assert "Packaging Release!" in client.out - client.run("create . -s os=Linux -s build_type=Debug") - assert "Building my code!" in client.out - assert "pkg/0.1: Calling build()" in client.out - assert "Packaging Debug!" in client.out + assert "Packaging Linux-x86!" in client.out def test_remove_require(): diff --git a/conans/test/integration/package_id/package_id_test.py b/conans/test/integration/package_id/package_id_test.py index 7f2904e7d27..42c3fed02ae 100644 --- a/conans/test/integration/package_id/package_id_test.py +++ b/conans/test/integration/package_id/package_id_test.py @@ -159,8 +159,7 @@ def package_id(self): def test_package_id_validate_settings(): - """ ``self.info`` has some validation, the first time it executes - https://github.com/conan-io/conan/issues/12693 + """ ``self.info`` has no validation, as it allows to be mutated """ conanfile = textwrap.dedent(""" from conan import ConanFile @@ -173,8 +172,8 @@ def package_id(self): """) c = TestClient() c.save({"conanfile.py": conanfile}) - c.run("create . --name=pkg --version=0.1", assert_error=True) - assert "ConanException: Invalid setting 'DONT_EXIST' is not a valid 'settings.os' value" in c.out + c.run("create . --name=pkg --version=0.1") + # It used to fail, class TestBuildRequiresHeaderOnly: From c504ad76bc146b425062f4c4800117b88eafc23c Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 11 Jan 2024 15:31:02 +0100 Subject: [PATCH 4/5] merged upstream --- conans/test/integration/package_id/build_id_test.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/conans/test/integration/package_id/build_id_test.py b/conans/test/integration/package_id/build_id_test.py index ed39685946b..4cf358e5880 100644 --- a/conans/test/integration/package_id/build_id_test.py +++ b/conans/test/integration/package_id/build_id_test.py @@ -142,12 +142,13 @@ def test_any_os_arch(self): class MyTest(ConanFile): name = "pkg" version = "0.1" - settings = "os", "arch", "build_type" + settings = "os", "arch", "build_type", "compiler" def build_id(self): - self.info_build.settings.build_type = "Any" - self.info_build.settings.os = "Any" - self.info_build.settings.arch = "Any" + self.info_build.settings.build_type = "AnyValue" + self.info_build.settings.os = "AnyValue" + self.info_build.settings.arch = "AnyValue" + self.info_build.settings.compiler = "AnyValue" def build(self): self.output.info("Building my code!") From a393363f4ab0e852ec3f79fb1142fe415f64fc87 Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 11 Jan 2024 16:34:25 +0100 Subject: [PATCH 5/5] more tests --- conans/model/settings.py | 2 +- conans/test/integration/package_id/package_id_test.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/conans/model/settings.py b/conans/model/settings.py index 5adbaefa4a1..7270f8745f2 100644 --- a/conans/model/settings.py +++ b/conans/model/settings.py @@ -72,7 +72,7 @@ def copy_conaninfo_settings(self): else: result._definition = {k: v.copy_conaninfo_settings() for k, v in self._definition.items()} - result._definition["ANY"] = SettingsItem([], "ANY") + result._definition["ANY"] = Settings() return result def __bool__(self): diff --git a/conans/test/integration/package_id/package_id_test.py b/conans/test/integration/package_id/package_id_test.py index 42c3fed02ae..9400203c135 100644 --- a/conans/test/integration/package_id/package_id_test.py +++ b/conans/test/integration/package_id/package_id_test.py @@ -59,6 +59,7 @@ class TestConan(ConanFile): def package_id(self): self.info.settings.arch = "kk=kk" + self.info.settings.os = "yy=yy" """) client = TestClient(default_server_user=True)