diff --git a/conan/cli/formatters/graph/graph.py b/conan/cli/formatters/graph/graph.py index 3c6ef38df8e..878a90758a0 100644 --- a/conan/cli/formatters/graph/graph.py +++ b/conan/cli/formatters/graph/graph.py @@ -14,6 +14,8 @@ from conans.util.files import load +# FIXME: Check all this code when format_graph_[html/dot] use serialized graph + class _PrinterGraphItem(object): def __init__(self, _id, node, is_build_time_node): self.id = _id @@ -39,19 +41,13 @@ def is_build_requires(self): return self._is_build_time_node def data(self): - - def ensure_iterable(value): - if isinstance(value, (list, tuple)): - return value - return value, - return { 'build_id': build_id(self._conanfile), 'url': self._conanfile.url, 'homepage': self._conanfile.homepage, 'license': self._conanfile.license, 'author': self._conanfile.author, - 'topics': ensure_iterable(self._conanfile.topics) if self._conanfile.topics else None + 'topics': self._conanfile.topics } diff --git a/conan/cli/formatters/graph/graph_info_text.py b/conan/cli/formatters/graph/graph_info_text.py index 6c5edc90227..2da47f2172e 100644 --- a/conan/cli/formatters/graph/graph_info_text.py +++ b/conan/cli/formatters/graph/graph_info_text.py @@ -6,15 +6,15 @@ def filter_graph(graph, package_filter, field_filter=None): if package_filter is not None: - graph["nodes"] = [n for n in graph["nodes"] - if any(fnmatch.fnmatch(n["ref"] or "", p) for p in package_filter)] + graph["nodes"] = {id_: n for id_, n in graph["nodes"].items() + if any(fnmatch.fnmatch(n["ref"] or "", p) for p in package_filter)} if field_filter is not None: if "ref" not in field_filter: field_filter.append("ref") - result = [] - for n in graph["nodes"]: + result = {} + for id_, n in graph["nodes"].items(): new_node = OrderedDict((k, v) for k, v in n.items() if k in field_filter) - result.append(new_node) + result[id_] = new_node graph["nodes"] = result return graph @@ -31,7 +31,7 @@ def format_graph_info(result): out.title("Basic graph information") serial = graph.serialize() serial = filter_graph(serial, package_filter, field_filter) - for n in serial["nodes"]: + for n in serial["nodes"].values(): out.writeln(f"{n['ref']}:") # FIXME: This can be empty for consumers and it is ugly ":" _serial_pretty_printer(n, indent=" ") if graph.error: diff --git a/conans/client/graph/graph.py b/conans/client/graph/graph.py index 101394301d3..96170d65b97 100644 --- a/conans/client/graph/graph.py +++ b/conans/client/graph/graph.py @@ -222,9 +222,11 @@ def serialize(self): result["info_invalid"] = getattr(getattr(self.conanfile, "info", None), "invalid", None) # Adding the conanfile information: settings, options, etc result.update(self.conanfile.serialize()) + result.pop("requires", None) # superseded by "dependencies" (graph.transitive_deps) + result["dependencies"] = {d.node.id: d.require.serialize() + for d in self.transitive_deps.values() if d.node is not None} result["context"] = self.context result["test"] = self.test - result["requires"] = {n.id: n.ref.repr_notime() for n in self.neighbors()} return result def overrides(self): @@ -381,6 +383,8 @@ def serialize(self): for i, n in enumerate(self.nodes): n.id = i result = OrderedDict() - result["nodes"] = [n.serialize() for n in self.nodes] + result["nodes"] = {n.id: n.serialize() for n in self.nodes} result["root"] = {self.root.id: repr(self.root.ref)} # TODO: ref of consumer/virtual + result["overrides"] = self.overrides().serialize() + result["resolved_ranges"] = {repr(r): s.repr_notime() for r, s in self.resolved_ranges.items()} return result diff --git a/conans/model/conan_file.py b/conans/model/conan_file.py index 2c19df67002..104137ee613 100644 --- a/conans/model/conan_file.py +++ b/conans/model/conan_file.py @@ -125,14 +125,12 @@ def serialize(self): for a in ("name", "user", "channel", "url", "license", "author", "description", "homepage", "build_policy", "upload_policy", "revision_mode", "provides", "deprecated", "win_bash", "win_bash_run", - "default_options", "options_description",): + "default_options", "options_description"): v = getattr(self, a, None) - if v is not None: - result[a] = v - if self.version is not None: - result["version"] = str(self.version) - if self.topics is not None: - result["topics"] = list(self.topics) + result[a] = v + + result["version"] = str(self.version) if self.version is not None else None + result["topics"] = list(self.topics) if self.topics is not None else None result["package_type"] = str(self.package_type) settings = self.settings diff --git a/conans/test/functional/command/test_build.py b/conans/test/functional/command/test_build.py index 56f7f8960d5..8a45d026f03 100644 --- a/conans/test/functional/command/test_build.py +++ b/conans/test/functional/command/test_build.py @@ -64,8 +64,8 @@ def build(self): client.save({"conanfile.py": conanfile_scope_env}, clean_first=True) client.run("build conanfile.py --build=missing") - assert hellopkg_result["graph"]["nodes"][1]["package_folder"] in client.out - assert hellotools_result["graph"]["nodes"][1]["package_folder"] in client.out + assert hellopkg_result["graph"]["nodes"]["1"]["package_folder"] in client.out + assert hellotools_result["graph"]["nodes"]["1"]["package_folder"] in client.out def test_build_with_deps_env_info(): diff --git a/conans/test/functional/tools/system/package_manager_test.py b/conans/test/functional/tools/system/package_manager_test.py index 289c656d93e..d9b485020b5 100644 --- a/conans/test/functional/tools/system/package_manager_test.py +++ b/conans/test/functional/tools/system/package_manager_test.py @@ -178,7 +178,7 @@ def system_requirements(self): redirect_stdout="graph.json") graph = json.loads(client.load("graph.json")) assert {"apt-get": {"install": ["pkg1", "pkg2"], "missing": []}} == \ - graph["graph"]["nodes"][0]["system_requires"] + graph["graph"]["nodes"]["0"]["system_requires"] # plain report, do not check client.run("graph info . -c tools.system.package_manager:tool=apt-get " @@ -186,7 +186,7 @@ def system_requirements(self): redirect_stdout="graph2.json") graph2 = json.loads(client.load("graph2.json")) # TODO: Unify format of ``graph info`` and ``install`` - assert {"apt-get": {"install": ["pkg1", "pkg2"]}} == graph2["nodes"][0]["system_requires"] + assert {"apt-get": {"install": ["pkg1", "pkg2"]}} == graph2["nodes"]["0"]["system_requires"] # Check report-installed with patch.object(_SystemPackageManagerTool, '_conanfile_run', MagicMock(return_value=True)): @@ -195,7 +195,7 @@ def system_requirements(self): redirect_stdout="graph2.json") graph2 = json.loads(client.load("graph2.json")) assert {"apt-get": {"install": ["pkg1", "pkg2"], - 'missing': ['pkg1', 'pkg2']}} == graph2["nodes"][0]["system_requires"] + 'missing': ['pkg1', 'pkg2']}} == graph2["nodes"]["0"]["system_requires"] # Default "check" will fail, as dpkg-query not installed client.run("graph info . -c tools.system.package_manager:tool=apt-get " diff --git a/conans/test/integration/command/create_test.py b/conans/test/integration/command/create_test.py index b47248fa89c..72716cae5e4 100644 --- a/conans/test/integration/command/create_test.py +++ b/conans/test/integration/command/create_test.py @@ -8,7 +8,7 @@ from conans.model.recipe_ref import RecipeReference from conans.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID, GenConanfile -from conans.util.files import load, save +from conans.util.files import load class CreateTest(unittest.TestCase): @@ -70,7 +70,6 @@ def system_requirements(self): client.run("create . --name=pkg --version=0.1 --user=lasote") assert "pkg/0.1@lasote:" in client.out - def test_error_create_name_version(self): client = TestClient() client.save({"conanfile.py": GenConanfile().with_name("hello").with_version("1.2")}) @@ -87,7 +86,7 @@ def test_create_user_channel(self): self.assertIn("pkg/0.1@lasote/channel: Generating the package", client.out) client.run("list * -c") self.assertIn("pkg/0.1@lasote/channel", client.out) - + # test default without user and channel client.run("create . ") self.assertIn("pkg/0.1: Generating the package", client.out) @@ -308,7 +307,7 @@ def package_info(self): self.client.save({"conanfile.py": conanfile}) self.client.run("create . --format=json") data = json.loads(self.client.stdout) - cpp_info_data = data["graph"]["nodes"][1]["cpp_info"] + cpp_info_data = data["graph"]["nodes"]["1"]["cpp_info"] self.assertIn("libpkg1", cpp_info_data["pkg1"]["libs"]) self.assertListEqual([], cpp_info_data["pkg1"]["requires"]) self.assertIn("libpkg2", cpp_info_data["pkg2"]["libs"]) @@ -370,7 +369,7 @@ def test_create_format_json(): .... }, {'ref': 'hello/0.1#18d5440ae45afc4c36139a160ac071c7', - 'requires': {'2': 'pkg/0.2#db78b8d06a78af5c3ac56706f133098d'}, + 'dependencies': {'1': {'ref': 'hello/0.1', 'visible': 'True', ...}}, .... }, {'ref': 'pkg/0.2#44a1a27ac2ea1fbcf434a05c4d57388d', @@ -437,7 +436,7 @@ class MyTest(ConanFile): pkg_pkg_ref = 'pkg/0.2#db78b8d06a78af5c3ac56706f133098d' consumer_info = hello_pkg_info = pkg_pkg_info = None - for n in nodes: + for _, n in nodes.items(): ref = n["ref"] if ref == consumer_ref: consumer_info = n @@ -456,13 +455,31 @@ class MyTest(ConanFile): assert consumer_info["settings"] == {'arch': 'x86', 'build_type': 'Debug', 'compiler': 'gcc', 'compiler.libcxx': 'libstdc++', 'compiler.version': '12', 'os': 'Linux'} - assert consumer_info["requires"] == {'1': hello_pkg_ref} + consumer_deps = { + '1': {'ref': 'hello/0.1', 'run': 'False', 'libs': 'True', 'skip': 'False', + 'test': 'False', 'force': 'False', 'direct': 'True', 'build': 'False', + 'transitive_headers': 'None', 'transitive_libs': 'None', 'headers': 'True', + 'package_id_mode': 'None', 'visible': 'True'}, + '2': {'ref': 'pkg/0.2', 'run': 'False', 'libs': 'True', 'skip': 'False', 'test': 'False', + 'force': 'False', 'direct': 'False', 'build': 'False', 'transitive_headers': 'None', + 'transitive_libs': 'None', 'headers': 'True', 'package_id_mode': 'None', + 'visible': 'True'} + } + assert consumer_info["dependencies"] == consumer_deps # hello/0.1 pkg information assert hello_pkg_info["package_id"] == "8eba237c0fb239fcb7daa47979ab99258eaaa7d1" assert hello_pkg_info["prev"] == "d95380a07c35273509dfc36b26f6cec1" assert hello_pkg_info["settings"] == {} assert hello_pkg_info["options"] == {} - assert hello_pkg_info["requires"] == {'2': pkg_pkg_ref} + hello_pkg_info_deps = { + "2": { + "ref": "pkg/0.2", "run": "False", "libs": "True", "skip": "False", "test": "False", + "force": "False", "direct": "True", "build": "False", "transitive_headers": "None", + "transitive_libs": "None", "headers": "True", "package_id_mode": "semver_mode", + "visible": "True" + } + } + assert hello_pkg_info["dependencies"] == hello_pkg_info_deps # pkg/0.2 pkg information assert pkg_pkg_info["package_id"] == "fb1439470288b15b2da269ed97b1a5f2f5d1f766" assert pkg_pkg_info["prev"] == "6949b0f89941d2a5994f9e6e4a89a331" @@ -470,7 +487,7 @@ class MyTest(ConanFile): assert pkg_pkg_info["settings"] == {'build_type': 'Debug', 'compiler': 'gcc', 'compiler.libcxx': 'libstdc++', 'compiler.version': '12'} assert pkg_pkg_info["options"] == {'fPIC': 'True', 'shared': 'False'} - assert pkg_pkg_info["requires"] == {} + assert pkg_pkg_info["dependencies"] == {} def test_create_format_json_and_deps_cpp_info(): @@ -495,7 +512,7 @@ def test_create_format_json_and_deps_cpp_info(): 'objects': None, 'properties': {'pkg_config_aliases': ['compo1_alias'], 'pkg_config_name': 'compo1'}, - 'requires': None, + 'dependencies': None, 'resdirs': None, 'sharedlinkflags': None, 'srcdirs': None, @@ -519,7 +536,7 @@ def test_create_format_json_and_deps_cpp_info(): 'properties': {'pkg_config_aliases': ['pkg_alias1', 'pkg_alias2'], 'pkg_config_name': 'pkg_other_name'}, - 'requires': None, + 'dependencies': None, 'resdirs': ['/path ' 'with ' 'spaces/.conan2/p/d15a235e212166d9/p/res'], @@ -569,7 +586,7 @@ def package_info(self): hello_pkg_ref = 'hello/0.1#18d5440ae45afc4c36139a160ac071c7' pkg_pkg_ref = 'pkg/0.2#926714b5fb0a994f47ec37e071eba1da' hello_cpp_info = pkg_cpp_info = None - for n in nodes: + for _, n in nodes.items(): ref = n["ref"] if ref == hello_pkg_ref: assert n['binary'] == "Build" diff --git a/conans/test/integration/command/export_pkg_test.py b/conans/test/integration/command/export_pkg_test.py index 98ae0fd179e..52beb043c6c 100644 --- a/conans/test/integration/command/export_pkg_test.py +++ b/conans/test/integration/command/export_pkg_test.py @@ -297,7 +297,7 @@ def test_export_pkg_json(self): # Wrong folders client.run("export-pkg . --format=json", redirect_stdout="file.json") graph = json.loads(client.load("file.json")) - assert "pkg/0.1" in graph["graph"]["nodes"][0]["ref"] + assert "pkg/0.1" in graph["graph"]["nodes"]["0"]["ref"] def test_export_pkg_no_ref(self): client = TestClient() @@ -403,7 +403,7 @@ def package_info(self): hello_pkg_ref = 'hello/0.1#18d5440ae45afc4c36139a160ac071c7' pkg_pkg_ref = 'pkg/0.2#926714b5fb0a994f47ec37e071eba1da' hello_cpp_info = pkg_cpp_info = None - for n in nodes: + for _, n in nodes.items(): ref = n["ref"] if ref == hello_pkg_ref: assert n['binary'] is None # The exported package has no binary status diff --git a/conans/test/integration/command/info/info_test.py b/conans/test/integration/command/info/info_test.py index c99e733d57d..c33e404d0cc 100644 --- a/conans/test/integration/command/info/info_test.py +++ b/conans/test/integration/command/info/info_test.py @@ -70,7 +70,7 @@ class MyTest(ConanFile): """) client.save({"conanfile.py": conanfile}) client.run("graph info . --format=json") - recipe = json.loads(client.stdout)["nodes"][0] + recipe = json.loads(client.stdout)["nodes"]["0"] assert type(recipe["topics"]) == list assert recipe["topics"] == ["foo"] assert type(recipe["provides"]) == list @@ -90,7 +90,7 @@ class MyTest(ConanFile): """) client2.save({"conanfile.py": conanfile2}) client2.run("graph info . --format=json") - recipe = json.loads(client2.stdout)["nodes"][0] + recipe = json.loads(client2.stdout)["nodes"]["0"] assert type(recipe["topics"]) == list assert recipe["topics"] == ["foo"] assert type(recipe["provides"]) == list @@ -163,10 +163,10 @@ def test_json_package_filter(self): conanfile = GenConanfile("pkg", "0.1").with_setting("build_type") client.save({"conanfile.py": conanfile}) client.run("graph info . --package-filter=nothing --format=json") - assert '"nodes": []' in client.out + assert '"nodes": {}' in client.out client.run("graph info . --package-filter=pkg* --format=json") graph = json.loads(client.stdout) - assert graph["nodes"][0]["ref"] == "pkg/0.1" + assert graph["nodes"]["0"]["ref"] == "pkg/0.1" def test_json_info_outputs(self): client = TestClient() @@ -174,7 +174,7 @@ def test_json_info_outputs(self): client.save({"conanfile.py": conanfile}) client.run("graph info . -s build_type=Debug --format=json") graph = json.loads(client.stdout) - assert graph["nodes"][0]["settings"]["build_type"] == "Debug" + assert graph["nodes"]["0"]["settings"]["build_type"] == "Debug" class TestAdvancedCliOutput: @@ -199,7 +199,7 @@ class pkg(ConanFile): client.run("graph info . --format=json") info = json.loads(client.stdout) - assert info["nodes"][0]["python_requires"] == ['tool/0.1#4d670581ccb765839f2239cc8dff8fbd'] + assert info["nodes"]["0"]["python_requires"] == ['tool/0.1#4d670581ccb765839f2239cc8dff8fbd'] def test_build_id_info(self): client = TestClient() diff --git a/conans/test/integration/command/info/test_info_folders.py b/conans/test/integration/command/info/test_info_folders.py index e834ff66fb4..e8eda3928cd 100644 --- a/conans/test/integration/command/info/test_info_folders.py +++ b/conans/test/integration/command/info/test_info_folders.py @@ -48,11 +48,11 @@ def test_basic(): client.run(f"export . --user=user --channel=testing") client.run(f"graph info --requires=package/0.1.0@user/testing --format=json") nodes = json.loads(client.stdout)["nodes"] - assert client.cache_folder in nodes[1]["recipe_folder"] - assert os.path.basename(nodes[1]["recipe_folder"]).strip() == EXPORT_FOLDER - assert nodes[1]["source_folder"] is None - assert nodes[1]["build_folder"] is None - assert nodes[1]["package_folder"] is None + assert client.cache_folder in nodes["1"]["recipe_folder"] + assert os.path.basename(nodes["1"]["recipe_folder"]).strip() == EXPORT_FOLDER + assert nodes["1"]["source_folder"] is None + assert nodes["1"]["build_folder"] is None + assert nodes["1"]["package_folder"] is None def test_build_id(): @@ -86,7 +86,7 @@ def test_deps_basic(client_deps): found_ref = False assert len(nodes["nodes"]) == 3 - for node in nodes["nodes"]: + for _, node in nodes["nodes"].items(): if node["ref"] == "conanfile": assert node["source_folder"] is None else: @@ -103,22 +103,22 @@ def test_deps_specific_information(client_deps): client_deps.run("graph info . --package-filter package/* --format=json") nodes = json.loads(client_deps.stdout)["nodes"] assert len(nodes) == 1 - assert "package/0.1.0@user/testing" in nodes[0]["ref"] - assert nodes[0]["source_folder"] is None - assert nodes[0]["build_folder"] is None - assert nodes[0]["package_folder"] is None + assert "package/0.1.0@user/testing" in nodes["2"]["ref"] + assert nodes["2"]["source_folder"] is None + assert nodes["2"]["build_folder"] is None + assert nodes["2"]["package_folder"] is None client_deps.run("graph info . --package-filter package* --format=json") nodes = json.loads(client_deps.stdout)["nodes"] assert len(nodes) == 2 - assert "package2/0.2.0@user/testing" in nodes[0]["ref"] - assert nodes[0]["source_folder"] is None - assert nodes[0]["build_folder"] is None - assert nodes[0]["package_folder"] is None - assert "package/0.1.0@user/testing" in nodes[1]["ref"] - assert nodes[1]["source_folder"] is None - assert nodes[1]["build_folder"] is None - assert nodes[1]["package_folder"] is None + assert "package2/0.2.0@user/testing" in nodes["1"]["ref"] + assert nodes["1"]["source_folder"] is None + assert nodes["1"]["build_folder"] is None + assert nodes["1"]["package_folder"] is None + assert "package/0.1.0@user/testing" in nodes["2"]["ref"] + assert nodes["2"]["source_folder"] is None + assert nodes["2"]["build_folder"] is None + assert nodes["2"]["package_folder"] is None def test_single_field(): @@ -128,10 +128,10 @@ def test_single_field(): client.run(f"graph info --requires package/0.1.0@user/testing --format=json") nodes = json.loads(client.stdout)["nodes"] assert len(nodes) == 2 - assert "package/0.1.0@user/testing" in nodes[1]["ref"] - assert nodes[1]["source_folder"] is None - assert nodes[1]["build_folder"] is None - assert nodes[1]["package_folder"] is None + assert "package/0.1.0@user/testing" in nodes["1"]["ref"] + assert nodes["1"]["source_folder"] is None + assert nodes["1"]["build_folder"] is None + assert nodes["1"]["package_folder"] is None def test_direct_conanfile(): diff --git a/conans/test/integration/command/install/install_test.py b/conans/test/integration/command/install/install_test.py index 5bce30c279d..cfb48a9ec18 100644 --- a/conans/test/integration/command/install/install_test.py +++ b/conans/test/integration/command/install/install_test.py @@ -429,7 +429,7 @@ def package_info(self): hello_pkg_ref = 'hello/0.1' # no revision available pkg_pkg_ref = 'pkg/0.2#926714b5fb0a994f47ec37e071eba1da' hello_cpp_info = pkg_cpp_info = None - for n in nodes: + for _, n in nodes.items(): ref = n["ref"] if ref == hello_pkg_ref: assert n['binary'] is None @@ -438,7 +438,7 @@ def package_info(self): assert n['binary'] == "Cache" pkg_cpp_info = n['cpp_info'] - hello = nodes[0] + hello = nodes["0"] assert hello["ref"] == hello_pkg_ref assert hello["recipe_folder"] == client.current_folder assert hello["build_folder"] == client.current_folder diff --git a/conans/test/integration/graph/test_validate_build.py b/conans/test/integration/graph/test_validate_build.py index 99d88d2d361..5e263e1d482 100644 --- a/conans/test/integration/graph/test_validate_build.py +++ b/conans/test/integration/graph/test_validate_build.py @@ -46,11 +46,11 @@ def package_id(self): # What happens with a conan info? t.run(f"graph info --requires=foo/1.0 {settings_gcc} --format=json", redirect_stdout="myjson") myjson = json.loads(t.load("myjson"))["nodes"] - assert myjson[1]["invalid_build"] == "This doesn't build in GCC" + assert myjson["1"]["invalid_build"] == "This doesn't build in GCC" t.run(f"graph info --requires=foo/1.0 {settings_clang} --format=json", redirect_stdout="myjson") myjson = json.loads(t.load("myjson"))["nodes"] - assert myjson[1]["invalid_build"] is False + assert myjson["1"]["invalid_build"] is False def test_with_options_validate_build_test(): diff --git a/conans/test/integration/graph/version_ranges/version_range_override_test.py b/conans/test/integration/graph/version_ranges/version_range_override_test.py index 377814b11d8..e13cd51b158 100644 --- a/conans/test/integration/graph/version_ranges/version_range_override_test.py +++ b/conans/test/integration/graph/version_ranges/version_range_override_test.py @@ -1,5 +1,5 @@ # coding=utf-8 - +import json import unittest import pytest @@ -127,3 +127,21 @@ def test_override(self): t.run("create . --build=missing --build=pkga") self.assertIn("ros_core/pr-53@3rdparty/snapshot", t.out) self.assertIn("ros_perception/1.1.4@3rdparty/unstable", t.out) + + # Check information got by graph info + t.run("graph info . --format json") + info = json.loads(t.stdout) + expected_overrides = { + "ros_core/[~1.1]@3rdparty/unstable": [ + "ros_core/pr-53@3rdparty/snapshot" + ], + "ros_core/1.1.4@3rdparty/unstable": [ + "ros_core/pr-53@3rdparty/snapshot#4d670581ccb765839f2239cc8dff8fbd" + ] + } + self.assertEqual(info["overrides"], expected_overrides) + expected_resolved_ranges = { + "pkgb/[~0]@common/unstable": "pkgb/0.1@common/unstable", + "ros_perception/[~1.1]@3rdparty/unstable": "ros_perception/1.1.4@3rdparty/unstable" + } + self.assertEqual(info["resolved_ranges"], expected_resolved_ranges) diff --git a/conans/test/integration/lockfile/test_graph_overrides.py b/conans/test/integration/lockfile/test_graph_overrides.py index 2727e0d41e2..cf2b6a9dcae 100644 --- a/conans/test/integration/lockfile/test_graph_overrides.py +++ b/conans/test/integration/lockfile/test_graph_overrides.py @@ -29,12 +29,14 @@ def test_overrides_half_diamond(override, force): assert "pkga/0.2" in requires assert "pkga/0.1" not in requires c.run("graph info pkgc --lockfile=pkgc/conan.lock --format=json") - assert "pkga/0.2" in c.stdout - assert "pkga/0.1" not in c.stdout + dependencies = json.loads(c.stdout)["nodes"]["0"]["dependencies"] + assert "pkga/0.2" in str(dependencies) + assert "pkga/0.1" not in str(dependencies) # apply the lockfile to pkgb, should it lock to pkga/0.2 c.run("graph info pkgb --lockfile=pkgc/conan.lock --format=json") - assert "pkga/0.2" in c.stdout - assert "pkga/0.1" not in c.stdout + dependencies = json.loads(c.stdout)["nodes"]["0"]["dependencies"] + assert "pkga/0.2" in str(dependencies) + assert "pkga/0.1" not in str(dependencies) @pytest.mark.parametrize("override, force", [(True, False), (False, True)]) @@ -123,14 +125,28 @@ def test_overrides_diamond(override, force): assert "pkga/0.2" not in requires assert "pkga/0.1" not in requires c.run("graph info pkgd --lockfile=pkgd/conan.lock --format=json") - assert "pkga/0.3" in c.stdout - assert "pkga/0.2" not in c.stdout - assert "pkga/0.1" not in c.stdout + json_graph = json.loads(c.stdout) + deps = json_graph["nodes"]["0"]["dependencies"] + assert "pkga/0.3" in str(deps) + assert "pkga/0.2" not in str(deps) + assert "pkga/0.1" not in str(deps) + # Redundant assert, but checking "overrides" summary + overrides = json_graph["overrides"] + assert len(overrides) == 2 + assert overrides['pkga/0.1'] == ['pkga/0.3'] + assert overrides['pkga/0.2'] == ['pkga/0.3#e3afb975277bc245212d6e8de88f4f8f'] + # apply the lockfile to pkgb, should it lock to pkga/0.3 c.run("graph info pkgb --lockfile=pkgd/conan.lock --format=json") - assert "pkga/0.3" in c.stdout - assert "pkga/0.2" not in c.stdout - assert "pkga/0.1" not in c.stdout + json_graph = json.loads(c.stdout) + deps = json_graph["nodes"]["0"]["dependencies"] + assert "pkga/0.3" in str(deps) + assert "pkga/0.2" not in str(deps) + assert "pkga/0.1" not in str(deps) + # Redundant assert, but checking "overrides" summary + overrides = json_graph["overrides"] + assert len(overrides) == 1 + assert overrides["pkga/0.1"] == ["pkga/0.3"] @pytest.mark.parametrize("override, force", [(True, False), (False, True)]) @@ -162,14 +178,16 @@ def test_overrides_diamond_ranges(override, force): assert "pkga/0.2" not in requires assert "pkga/0.1" not in requires c.run("graph info pkgd --lockfile=pkgd/conan.lock --format=json") - assert "pkga/0.3" in c.stdout - assert "pkga/0.2" not in c.stdout - assert "pkga/0.1" not in c.stdout + dependencies = json.loads(c.stdout)["nodes"]["0"]["dependencies"] + assert "pkga/0.3" in str(dependencies) + assert "pkga/0.2" not in str(dependencies) + assert "pkga/0.1" not in str(dependencies) # apply the lockfile to pkgb, should it lock to pkga/0.3 c.run("graph info pkgb --lockfile=pkgd/conan.lock --format=json") - assert "pkga/0.3" in c.stdout - assert "pkga/0.2" not in c.stdout - assert "pkga/0.1" not in c.stdout + dependencies = json.loads(c.stdout)["nodes"]["0"]["dependencies"] + assert "pkga/0.3" in str(dependencies) + assert "pkga/0.2" not in str(dependencies) + assert "pkga/0.1" not in str(dependencies) @pytest.mark.parametrize("override1, force1", [(True, False), (False, True)]) diff --git a/conans/test/integration/package_id/test_validate.py b/conans/test/integration/package_id/test_validate.py index 3f0f0e32c77..13d3ca3a6a2 100644 --- a/conans/test/integration/package_id/test_validate.py +++ b/conans/test/integration/package_id/test_validate.py @@ -44,8 +44,8 @@ def validate(self): client.run("graph info --require pkg/0.1 -s os=Windows --format json") myjson = json.loads(client.stdout) - self.assertEqual(myjson["nodes"][1]["binary"], BINARY_INVALID) - assert myjson["nodes"][1]["info_invalid"] == "Windows not supported" in client.out + self.assertEqual(myjson["nodes"]["1"]["binary"], BINARY_INVALID) + assert myjson["nodes"]["1"]["info_invalid"] == "Windows not supported" in client.out def test_validate_header_only(self): client = TestClient()