Repository: conan-io/conan
Pull request #3825 (2018-10-22 21:59:56)

Feature/refactors graph load
Changelog: omit

Minors refactors and pep8





Patch:
diff --git a/conans/client/conan_api.py b/conans/client/conan_api.py
index aadb27449..21db43b9f 100644
--- a/conans/client/conan_api.py
+++ b/conans/client/conan_api.py
@@ -248,7 +248,7 @@ class ConanAPIV1(object):
 
     def _init_manager(self, action_recorder):
         """Every api call gets a new recorder and new manager"""
-        return ConanManager(self._client_cache, self._user_io, self._runner,
+        return ConanManager(self._client_cache, self._user_io,
                             self._remote_manager, action_recorder, self._registry,
                             self._graph_manager, self._plugin_manager)
 
diff --git a/conans/client/graph/graph.py b/conans/client/graph/graph.py
index 16570b31c..b41050ff3 100644
--- a/conans/client/graph/graph.py
+++ b/conans/client/graph/graph.py
@@ -56,10 +56,11 @@ class Node(object):
         return [edge.dst for edge in self.dependencies]
 
     def public_neighbors(self):
-        return [edge.dst for edge in self.dependencies if not edge.private]
+        return [edge.dst for edge in self.dependencies
+                if not edge.private and not edge.build_require]
 
     def private_neighbors(self):
-        return [edge.dst for edge in self.dependencies if edge.private]
+        return [edge.dst for edge in self.dependencies if edge.private or edge.build_require]
 
     def inverse_neighbors(self):
         return [edge.src for edge in self.dependants]
@@ -106,10 +107,11 @@ class Node(object):
 
 
 class Edge(object):
-    def __init__(self, src, dst, private=False):
+    def __init__(self, src, dst, private=False, build_require=False):
         self.src = src
         self.dst = dst
         self.private = private
+        self.build_require = build_require
 
     def __eq__(self, other):
         return self.src == self.src and self.dst == other.dst
@@ -134,7 +136,7 @@ class DepsGraph(object):
 
         for e in graph.root.dependencies:
             e.src = node
-            e.private = True
+            e.build_require = build_require
 
         node.dependencies = graph.root.dependencies + node.dependencies
 
@@ -143,9 +145,9 @@ class DepsGraph(object):
             self.root = node
         self.nodes.add(node)
 
-    def add_edge(self, src, dst, private=False):
+    def add_edge(self, src, dst, private=False, build_require=False):
         assert src in self.nodes and dst in self.nodes
-        edge = Edge(src, dst, private)
+        edge = Edge(src, dst, private, build_require)
         src.add_edge(edge)
         dst.add_edge(edge)
 
@@ -257,11 +259,11 @@ class DepsGraph(object):
             for dep in node.dependencies:
                 src = result_node
                 dst = nodes_map[dep.dst]
-                result.add_edge(src, dst, dep.private)
+                result.add_edge(src, dst, dep.private, dep.build_require)
             for dep in node.dependants:
                 src = nodes_map[dep.src]
                 dst = result_node
-                result.add_edge(src, dst, dep.private)
+                result.add_edge(src, dst, dep.private, dep.build_require)
 
         return result
 
diff --git a/conans/client/graph/graph_builder.py b/conans/client/graph/graph_builder.py
index b10b4efc4..0808a817d 100644
--- a/conans/client/graph/graph_builder.py
+++ b/conans/client/graph/graph_builder.py
@@ -22,11 +22,10 @@ class DepsGraphBuilder(object):
         self._workspace = workspace
         self._recorder = recorder
 
-    def load_graph(self, conanfile, check_updates, update, remote_name, processed_profile):
+    def load_graph(self, root_node, check_updates, update, remote_name, processed_profile):
         check_updates = check_updates or update
         dep_graph = DepsGraph()
         # compute the conanfile entry point for this dependency graph
-        root_node = Node(None, conanfile)
         dep_graph.add_node(root_node)
         public_deps = {}  # {name: Node} dict with public nodes, so they are not added again
         aliased = {}
diff --git a/conans/client/graph/graph_manager.py b/conans/client/graph/graph_manager.py
index 415e83107..b151ea93f 100644
--- a/conans/client/graph/graph_manager.py
+++ b/conans/client/graph/graph_manager.py
@@ -7,7 +7,7 @@ from conans.errors import conanfile_exception_formatter, ConanException
 from conans.model.conan_file import get_env_context_manager
 from conans.client.graph.graph_builder import DepsGraphBuilder
 from conans.client.graph.graph_binaries import GraphBinariesAnalyzer
-from conans.client.graph.graph import BINARY_BUILD, BINARY_WORKSPACE
+from conans.client.graph.graph import BINARY_BUILD, BINARY_WORKSPACE, Node
 from conans.client import settings_preprocessor
 from conans.client.output import ScopedOutput
 from conans.client.graph.build_mode import BuildMode
@@ -64,8 +64,8 @@ class GraphManager(object):
         cache_settings.remove_undefined()
         processed_profile = ProcessedProfile(cache_settings, profile, None)
         if conanfile_path.endswith(".py"):
-            conanfile = self._loader.load_conanfile(conanfile_path, output, consumer=True, local=True,
-                                                    processed_profile=processed_profile)
+            conanfile = self._loader.load_conanfile(conanfile_path, output, consumer=True,
+                                                    local=True, processed_profile=processed_profile)
         else:
             conanfile = self._loader.load_conanfile_txt(conanfile_path, output, processed_profile)
 
@@ -84,12 +84,13 @@ class GraphManager(object):
         settings_preprocessor.preprocess(cache_settings)
         processed_profile = ProcessedProfile(cache_settings, profile, create_reference=None)
         conanfile = self._loader.load_virtual([reference], processed_profile)
-        graph = builder.load_graph(conanfile, check_updates=False, update=False, remote_name=None,
+        root_node = Node(None, conanfile)
+        graph = builder.load_graph(root_node, check_updates=False, update=False, remote_name=None,
                                    processed_profile=processed_profile)
         return graph
 
-    def load_graph(self, reference, create_reference, profile, build_mode, check_updates, update, remote_name,
-                   recorder, workspace):
+    def load_graph(self, reference, create_reference, profile, build_mode, check_updates, update,
+                   remote_name, recorder, workspace):
 
         def _inject_require(conanfile, reference):
             """ test_package functionality requires injecting the tested package as requirement
@@ -116,14 +117,16 @@ class GraphManager(object):
         else:
             output = ScopedOutput("PROJECT", self._output)
             if reference.endswith(".py"):
-                conanfile = self._loader.load_conanfile(reference, output, processed_profile, consumer=True)
+                conanfile = self._loader.load_conanfile(reference, output, processed_profile,
+                                                        consumer=True)
                 if create_reference:  # create with test_package
                     _inject_require(conanfile, create_reference)
             else:
                 conanfile = self._loader.load_conanfile_txt(reference, output, processed_profile)
 
         build_mode = BuildMode(build_mode, self._output)
-        deps_graph = self._load_graph(conanfile, check_updates, update,
+        root_node = Node(None, conanfile)
+        deps_graph = self._load_graph(root_node, check_updates, update,
                                       build_mode=build_mode, remote_name=remote_name,
                                       profile_build_requires=profile.build_requires,
                                       recorder=recorder, workspace=workspace,
@@ -166,29 +169,39 @@ class GraphManager(object):
 
             if package_build_requires:
                 node.conanfile.build_requires_options.clear_unscoped_options()
-                virtual = self._loader.load_virtual(package_build_requires.values(), scope_options=False,
-                                                    build_requires_options=node.conanfile.build_requires_options,
+                build_requires_options = node.conanfile.build_requires_options
+                virtual = self._loader.load_virtual(package_build_requires.values(),
+                                                    scope_options=False,
+                                                    build_requires_options=build_requires_options,
                                                     processed_profile=processed_profile)
-                build_requires_package_graph = self._load_graph(virtual, check_updates, update, build_mode,
-                                                                remote_name, profile_build_requires,
-                                                                recorder, workspace, processed_profile)
+                virtual_node = Node(None, virtual)
+                build_requires_package_graph = self._load_graph(virtual_node, check_updates, update,
+                                                                build_mode, remote_name,
+                                                                profile_build_requires,
+                                                                recorder, workspace,
+                                                                processed_profile)
                 graph.add_graph(node, build_requires_package_graph, build_require=True)
 
             if new_profile_build_requires:
                 node.conanfile.build_requires_options.clear_unscoped_options()
-                virtual = self._loader.load_virtual(new_profile_build_requires.values(), scope_options=False,
-                                                    build_requires_options=node.conanfile.build_requires_options,
+                build_requires_options = node.conanfile.build_requires_options
+                virtual = self._loader.load_virtual(new_profile_build_requires.values(),
+                                                    scope_options=False,
+                                                    build_requires_options=build_requires_options,
                                                     processed_profile=processed_profile)
-
-                build_requires_profile_graph = self._load_graph(virtual, check_updates, update, build_mode,
-                                                                remote_name, new_profile_build_requires,
-                                                                recorder, workspace, processed_profile)
+                virtual_node = Node(None, virtual)
+                build_requires_profile_graph = self._load_graph(virtual_node, check_updates, update,
+                                                                build_mode, remote_name,
+                                                                new_profile_build_requires,
+                                                                recorder, workspace,
+                                                                processed_profile)
                 graph.add_graph(node, build_requires_profile_graph, build_require=True)
 
-    def _load_graph(self, conanfile, check_updates, update, build_mode, remote_name,
+    def _load_graph(self, root_node, check_updates, update, build_mode, remote_name,
                     profile_build_requires, recorder, workspace, processed_profile):
-        builder = DepsGraphBuilder(self._proxy, self._output, self._loader, self._resolver, workspace, recorder)
-        graph = builder.load_graph(conanfile, check_updates, update, remote_name, processed_profile)
+        builder = DepsGraphBuilder(self._proxy, self._output, self._loader, self._resolver,
+                                   workspace, recorder)
+        graph = builder.load_graph(root_node, check_updates, update, remote_name, processed_profile)
         if build_mode is None:
             return graph
         binaries_analyzer = GraphBinariesAnalyzer(self._client_cache, self._output,
diff --git a/conans/client/manager.py b/conans/client/manager.py
index 75f9f3fd8..eada0f99a 100644
--- a/conans/client/manager.py
+++ b/conans/client/manager.py
@@ -18,16 +18,12 @@ from conans.client.graph.printer import print_graph
 
 
 class ConanManager(object):
-    """ Manage all the commands logic  The main entry point for all the client
-    business logic
-    """
-    def __init__(self, client_cache, user_io, runner, remote_manager,
+    def __init__(self, client_cache, user_io, remote_manager,
                  recorder, registry, graph_manager, plugin_manager):
         assert isinstance(user_io, UserIO)
         assert isinstance(client_cache, ClientCache)
         self._client_cache = client_cache
         self._user_io = user_io
-        self._runner = runner
         self._remote_manager = remote_manager
         self._recorder = recorder
         self._registry = registry


Test patch:
diff --git a/conans/test/model/fake_retriever.py b/conans/test/model/fake_retriever.py
index 329bfadfa..ef82e4809 100644
--- a/conans/test/model/fake_retriever.py
+++ b/conans/test/model/fake_retriever.py
@@ -1,9 +1,10 @@
 import os
 
-from conans.test.utils.test_files import temp_folder
+from conans.client.graph.graph import Node
 from conans.model.ref import ConanFileReference
-from conans.tools import save
 from conans.paths import CONANFILE
+from conans.test.utils.test_files import temp_folder
+from conans.tools import save
 
 
 class Retriever(object):
@@ -15,8 +16,9 @@ class Retriever(object):
     def root(self, content, processed_profile):
         conan_path = os.path.join(self.folder, "root.py")
         save(conan_path, content)
-        conanfile = self.loader.load_conanfile(conan_path, self.output, processed_profile, consumer=True)
-        return conanfile
+        conanfile = self.loader.load_conanfile(conan_path, self.output, processed_profile,
+                                               consumer=True)
+        return Node(None, conanfile)
 
     def conan(self, conan_ref, content):
         if isinstance(conan_ref, str):
diff --git a/conans/test/model/version_ranges_test.py b/conans/test/model/version_ranges_test.py
index 35e442021..62f7a408e 100644
--- a/conans/test/model/version_ranges_test.py
+++ b/conans/test/model/version_ranges_test.py
@@ -1,17 +1,18 @@
-import unittest
 from collections import namedtuple, Counter
+import unittest
+
+from parameterized import parameterized
 
-from conans.test.utils.tools import TestBufferConanOutput
-from conans.paths import SimplePaths
 from conans.client.graph.graph_builder import DepsGraphBuilder
-from conans.model.ref import ConanFileReference
-from conans.client.loader import ConanFileLoader, ProcessedProfile
-from conans.model.requires import Requirements
+from conans.client.graph.python_requires import ConanPythonRequire
 from conans.client.graph.range_resolver import RangeResolver, satisfying
-from parameterized import parameterized
+from conans.client.loader import ConanFileLoader, ProcessedProfile
 from conans.errors import ConanException
+from conans.model.ref import ConanFileReference
+from conans.model.requires import Requirements
+from conans.paths import SimplePaths
 from conans.test.model.fake_retriever import Retriever
-from conans.client.graph.python_requires import ConanPythonRequire
+from conans.test.utils.tools import TestBufferConanOutput
 
 
 class BasicMaxVersionTest(unittest.TestCase):
@@ -20,7 +21,8 @@ class BasicMaxVersionTest(unittest.TestCase):
         result = satisfying(["1.1.1", "1.1.11", "1.1.21", "1.1.111"], "", output)
         self.assertEqual(result, "1.1.111")
         # prereleases are ordered
-        result = satisfying(["1.1.1-a.1", "1.1.1-a.11", "1.1.1-a.111", "1.1.1-a.21"], "~1.1.1-a", output)
+        result = satisfying(["1.1.1-a.1", "1.1.1-a.11", "1.1.1-a.111", "1.1.1-a.21"], "~1.1.1-a",
+                            output)
         self.assertEqual(result, "1.1.1-a.111")
         result = satisfying(["1.1.1", "1.1.1-11", "1.1.1-111", "1.1.1-21"], "", output)
         self.assertEqual(result, "1.1.1")
@@ -131,7 +133,8 @@ class VersionRangesTest(unittest.TestCase):
         self.remote_search = MockSearchRemote()
         paths = SimplePaths(self.retriever.folder)
         self.resolver = RangeResolver(self.output, paths, self.remote_search)
-        self.builder = DepsGraphBuilder(self.retriever, self.output, self.loader, self.resolver, None, None)
+        self.builder = DepsGraphBuilder(self.retriever, self.output, self.loader, self.resolver,
+                                        None, None)
 
         for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]:
             say_content = """