Example #1
0
    def _load_graph(self, root_node, check_updates, update, build_mode,
                    remotes, recorder, profile_host, profile_build,
                    apply_build_requires, graph_lock):
        assert isinstance(build_mode, BuildMode)
        profile_host_build_requires = profile_host.build_requires
        builder = DepsGraphBuilder(self._proxy, self._output, self._loader,
                                   self._resolver, recorder)
        graph = builder.load_graph(root_node, check_updates, update, remotes,
                                   profile_host, profile_build, graph_lock)

        self._recurse_build_requires(graph,
                                     builder,
                                     check_updates,
                                     update,
                                     build_mode,
                                     remotes,
                                     profile_host_build_requires,
                                     recorder,
                                     profile_host,
                                     profile_build,
                                     graph_lock,
                                     apply_build_requires=apply_build_requires)

        # Sort of closures, for linking order
        inverse_levels = {
            n: i
            for i, level in enumerate(graph.inverse_levels()) for n in level
        }
        for node in graph.nodes:
            node.public_closure.pop(node.name, context=node.context)
            # List sort is stable, will keep the original order of closure, but prioritize levels
            node.public_closure.sort(key_fn=lambda n: inverse_levels[n])

        return graph
Example #2
0
    def _load_graph(self, root_node, check_updates, update, build_mode, remote_name,
                    profile_build_requires, recorder, processed_profile, apply_build_requires):

        assert isinstance(build_mode, BuildMode)
        builder = DepsGraphBuilder(self._proxy, self._output, self._loader, self._resolver,
                                   recorder)
        graph = builder.load_graph(root_node, check_updates, update, remote_name, processed_profile)
        binaries_analyzer = GraphBinariesAnalyzer(self._cache, self._output,
                                                  self._remote_manager)

        self._recurse_build_requires(graph, builder, binaries_analyzer, check_updates, update,
                                     build_mode, remote_name,
                                     profile_build_requires, recorder, processed_profile,
                                     apply_build_requires=apply_build_requires)

        # Sort of closures, for linking order
        inverse_levels = {n: i for i, level in enumerate(graph.inverse_levels()) for n in level}
        for node in graph.nodes:
            closure = node.public_closure
            closure.pop(node.name)
            node_order = list(closure.values())
            # List sort is stable, will keep the original order of the closure, but prioritize levels
            node_order.sort(key=lambda n: inverse_levels[n])
            node.public_closure = node_order

        return graph
Example #3
0
    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(root_node, check_updates, update,
                                   remote_name, processed_profile)
        if build_mode is None:
            return graph
        binaries_analyzer = GraphBinariesAnalyzer(self._cache, self._output,
                                                  self._remote_manager,
                                                  workspace)
        binaries_analyzer.evaluate_graph(graph, build_mode, update,
                                         remote_name)

        self._recurse_build_requires(graph, check_updates, update, build_mode,
                                     remote_name, profile_build_requires,
                                     recorder, workspace, processed_profile)
        return graph
Example #4
0
    def setUp(self):
        self.output = TestBufferConanOutput()
        self.loader = ConanFileLoader(None, Settings.loads(""), Profile())
        self.retriever = Retriever(self.loader, self.output)
        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)

        for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]:
            say_content = """
from conans import ConanFile

class SayConan(ConanFile):
    name = "Say"
    version = "%s"
""" % v
            say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v)
            self.retriever.conan(say_ref, say_content)
Example #5
0
 def load_simple_graph(self, reference, profile, recorder):
     # Loads a graph without computing the binaries. It is necessary for
     # export-pkg command, not hitting the server
     # # https://github.com/conan-io/conan/issues/3432
     builder = DepsGraphBuilder(self._proxy,
                                self._output,
                                self._loader,
                                self._resolver,
                                workspace=None,
                                recorder=recorder)
     processed_profile = ProcessedProfile(profile, create_reference=None)
     conanfile = self._loader.load_virtual([reference], processed_profile)
     root_node = Node(None, conanfile, recipe=RECIPE_VIRTUAL)
     graph = builder.load_graph(root_node,
                                check_updates=False,
                                update=False,
                                remote_name=None,
                                processed_profile=processed_profile)
     return graph
Example #6
0
 def load_simple_graph(self, reference, profile, recorder):
     # Loads a graph without computing the binaries. It is necessary for
     # export-pkg command, not hitting the server
     # # https://github.com/conan-io/conan/issues/3432
     builder = DepsGraphBuilder(self._proxy,
                                self._output,
                                self._loader,
                                self._resolver,
                                workspace=None,
                                recorder=recorder)
     cache_settings = self._client_cache.settings.copy()
     cache_settings.values = profile.settings_values
     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,
                                processed_profile=processed_profile)
     return graph
Example #7
0
    def load_graph(self,
                   conanfile,
                   check_updates,
                   update,
                   build_mode,
                   remote_name=None,
                   profile_build_requires=None):
        builder = DepsGraphBuilder(self._proxy, self._output, self._loader,
                                   self._resolver, self._workspace)
        graph = builder.load_graph(conanfile, check_updates, update,
                                   remote_name)
        if build_mode is None:
            return graph
        binaries_analyzer = GraphBinariesAnalyzer(self._client_cache,
                                                  self._output,
                                                  self._remote_manager,
                                                  self._registry,
                                                  self._workspace)
        binaries_analyzer.evaluate_graph(graph, build_mode, update,
                                         remote_name)

        self._recurse_build_requires(graph, check_updates, update, build_mode,
                                     remote_name, profile_build_requires)
        return graph
Example #8
0
    def setUp(self):
        self.output = TestBufferConanOutput()
        self.loader = ConanFileLoader(None, Settings.loads(""), Profile())
        self.retriever = Retriever(self.loader, self.output)
        self.remote_search = MockSearchRemote()
        self.resolver = RequireResolver(self.output, self.retriever, self.remote_search)
        self.builder = DepsGraphBuilder(self.retriever, self.output, self.loader, self.resolver)

        for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]:
            say_content = """
from conans import ConanFile

class SayConan(ConanFile):
    name = "Say"
    version = "%s"
""" % v
            say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v)
            self.retriever.conan(say_ref, say_content)
Example #9
0
 def _get_graph_builder(self, loader, remote_proxy):
     resolver = RangeResolver(self._user_io.out, self._client_cache, remote_proxy)
     graph_builder = DepsGraphBuilder(remote_proxy, self._user_io.out, loader, resolver)
     return graph_builder
Example #10
0
class VersionRangesTest(unittest.TestCase):

    def setUp(self):
        self.output = TestBufferConanOutput()
        self.loader = ConanFileLoader(None, self.output, ConanPythonRequire(None, None))
        self.retriever = Retriever(self.loader)
        self.remote_search = MockSearchRemote()
        paths = SimplePaths(self.retriever.folder)
        self.resolver = RangeResolver(paths, self.remote_search)
        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 = """
from conans import ConanFile

class SayConan(ConanFile):
    name = "Say"
    version = "%s"
""" % v
            say_ref = ConanFileReference.loads("Say/%s@myuser/testing" % v)
            self.retriever.conan(say_ref, say_content)

    def root(self, content, update=False):
        self.loader.cached_conanfiles = {}
        processed_profile = test_processed_profile()
        root_conan = self.retriever.root(content, processed_profile)
        deps_graph = self.builder.load_graph(root_conan, update, update, None, processed_profile)
        self.output.write("\n".join(self.resolver.output))
        return deps_graph

    def test_local_basic(self):
        for expr, solution in [(">0.0", "2.2.1"),
                               (">0.1,<1", "0.3"),
                               (">0.1,<1||2.1", "2.1"),
                               ("", "2.2.1"),
                               ("~0", "0.3"),
                               ("~=1", "1.2.1"),
                               ("~1.1", "1.1.2"),
                               ("~=2", "2.2.1"),
                               ("~=2.1", "2.1"),
                               ]:
            deps_graph = self.root(hello_content % expr)

            self.assertEqual(2, len(deps_graph.nodes))
            hello = _get_nodes(deps_graph, "Hello")[0]
            say = _get_nodes(deps_graph, "Say")[0]
            self.assertEqual(_get_edges(deps_graph), {Edge(hello, say)})

            self.assertEqual(hello.ref, None)
            conanfile = hello.conanfile
            self.assertEqual(conanfile.version, "1.2")
            self.assertEqual(conanfile.name, "Hello")
            say_ref = ConanFileReference.loads("Say/%s@myuser/testing" % solution)
            self.assertEqual(_clear_revs(conanfile.requires), Requirements(str(say_ref)))

    def test_remote_basic(self):
        self.resolver._local_search = None
        remote_packages = []
        for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]:
            say_ref = ConanFileReference.loads("Say/%s@myuser/testing" % v)
            remote_packages.append(say_ref)
        self.remote_search.packages = remote_packages
        for expr, solution in [(">0.0", "2.2.1"),
                               (">0.1,<1", "0.3"),
                               (">0.1,<1||2.1", "2.1"),
                               ("", "2.2.1"),
                               ("~0", "0.3"),
                               ("~=1", "1.2.1"),
                               ("~1.1", "1.1.2"),
                               ("~=2", "2.2.1"),
                               ("~=2.1", "2.1"),
                               ]:
            deps_graph = self.root(hello_content % expr, update=True)
            self.assertEqual(self.remote_search.count, {'Say/*@myuser/testing': 1})
            self.assertEqual(2, len(deps_graph.nodes))
            hello = _get_nodes(deps_graph, "Hello")[0]
            say = _get_nodes(deps_graph, "Say")[0]
            self.assertEqual(_get_edges(deps_graph), {Edge(hello, say)})

            self.assertEqual(hello.ref, None)
            conanfile = hello.conanfile
            self.assertEqual(conanfile.version, "1.2")
            self.assertEqual(conanfile.name, "Hello")
            say_ref = ConanFileReference.loads("Say/%s@myuser/testing" % solution)
            self.assertEqual(_clear_revs(conanfile.requires), Requirements(str(say_ref)))

    def test_remote_optimized(self):
        self.resolver._local_search = None
        remote_packages = []
        for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]:
            say_ref = ConanFileReference.loads("Say/%s@myuser/testing" % v)
            remote_packages.append(say_ref)
        self.remote_search.packages = remote_packages

        dep_content = """from conans import ConanFile
class Dep1Conan(ConanFile):
    requires = "Say/[%s]@myuser/testing"
"""
        dep_ref = ConanFileReference.loads("Dep1/0.1@myuser/testing")
        self.retriever.conan(dep_ref, dep_content % ">=0.1")
        dep_ref = ConanFileReference.loads("Dep2/0.1@myuser/testing")
        self.retriever.conan(dep_ref, dep_content % ">=0.1")

        hello_content = """from conans import ConanFile
class HelloConan(ConanFile):
    name = "Hello"
    requires = "Dep1/0.1@myuser/testing", "Dep2/0.1@myuser/testing"
"""
        deps_graph = self.root(hello_content, update=True)
        self.assertEqual(4, len(deps_graph.nodes))
        hello = _get_nodes(deps_graph, "Hello")[0]
        say = _get_nodes(deps_graph, "Say")[0]
        dep1 = _get_nodes(deps_graph, "Dep1")[0]
        dep2 = _get_nodes(deps_graph, "Dep2")[0]
        self.assertEqual(_get_edges(deps_graph), {Edge(hello, dep1), Edge(hello, dep2),
                                                  Edge(dep1, say), Edge(dep2, say)})

        # Most important check: counter of calls to remote
        self.assertEqual(self.remote_search.count, {'Say/*@myuser/testing': 1})

    @parameterized.expand([("", "0.3", None, None),
                           ('"Say/1.1@myuser/testing"', "1.1", False, False),
                           ('"Say/0.2@myuser/testing"', "0.2", False, True),
                           ('("Say/1.1@myuser/testing", "override")', "1.1", True, False),
                           ('("Say/0.2@myuser/testing", "override")', "0.2", True, True),
                           # ranges
                           ('"Say/[<=1.2]@myuser/testing"', "1.2.1", False, False),
                           ('"Say/[>=0.2,<=1.0]@myuser/testing"', "0.3", False, True),
                           ('"Say/[>=0.2 <=1.0]@myuser/testing"', "0.3", False, True),
                           ('("Say/[<=1.2]@myuser/testing", "override")', "1.2.1", True, False),
                           ('("Say/[>=0.2,<=1.0]@myuser/testing", "override")', "0.3", True, True),
                           ('("Say/[>=0.2 <=1.0]@myuser/testing", "override")', "0.3", True, True),
                           ])
    def transitive_test(self, version_range, solution, override, valid):
        hello_text = hello_content % ">0.1, <1"
        hello_ref = ConanFileReference.loads("Hello/1.2@myuser/testing")
        self.retriever.conan(hello_ref, hello_text)

        chat_content = """
from conans import ConanFile

class ChatConan(ConanFile):
    name = "Chat"
    version = "2.3"
    requires = "Hello/1.2@myuser/testing", %s
"""
        if valid is False:
            with self.assertRaisesRegexp(ConanException, "not valid"):
                self.root(chat_content % version_range)
            return

        deps_graph = self.root(chat_content % version_range)
        hello = _get_nodes(deps_graph, "Hello")[0]
        say = _get_nodes(deps_graph, "Say")[0]
        chat = _get_nodes(deps_graph, "Chat")[0]
        edges = {Edge(hello, say), Edge(chat, hello)}
        if override is not None:
            self.assertIn("overridden", self.output)
        else:
            self.assertNotIn("overridden", self.output)
        if override is False:
            edges = {Edge(hello, say), Edge(chat, say), Edge(chat, hello)}

        if valid is True:
            self.assertIn(" valid", self.output)
            self.assertNotIn("not valid", self.output)
        elif valid is False:
            self.assertIn("not valid", self.output)
        self.assertEqual(3, len(deps_graph.nodes))

        self.assertEqual(_get_edges(deps_graph), edges)

        self.assertEqual(hello.ref.copy_clear_rev(), hello_ref)
        conanfile = hello.conanfile
        self.assertEqual(conanfile.version, "1.2")
        self.assertEqual(conanfile.name, "Hello")
        say_ref = ConanFileReference.loads("Say/%s@myuser/testing" % solution)
        self.assertEqual(_clear_revs(conanfile.requires), Requirements(str(say_ref)))

    def duplicated_error_test(self):
        content = """
from conans import ConanFile

class Log3cppConan(ConanFile):
    name = "log4cpp"
    version = "1.1.1"
"""
        log4cpp_ref = ConanFileReference.loads("log4cpp/1.1.1@myuser/testing")
        self.retriever.conan(log4cpp_ref, content)

        content = """
from conans import ConanFile

class LoggerInterfaceConan(ConanFile):
    name = "LoggerInterface"
    version = "0.1.1"

    def requirements(self):
        self.requires("log4cpp/[~1.1]@myuser/testing")
"""
        logiface_ref = ConanFileReference.loads("LoggerInterface/0.1.1@myuser/testing")
        self.retriever.conan(logiface_ref, content)

        content = """
from conans import ConanFile

class OtherConan(ConanFile):
    name = "other"
    version = "2.0.11549"
    requires = "LoggerInterface/[~0.1]@myuser/testing"
"""
        other_ref = ConanFileReference.loads("other/2.0.11549@myuser/testing")
        self.retriever.conan(other_ref, content)

        content = """
from conans import ConanFile

class Project(ConanFile):
    requires = "LoggerInterface/[~0.1]@myuser/testing", "other/[~2.0]@myuser/testing"
"""
        deps_graph = self.root(content)

        log4cpp = _get_nodes(deps_graph, "log4cpp")[0]
        logger_interface = _get_nodes(deps_graph, "LoggerInterface")[0]
        other = _get_nodes(deps_graph, "other")[0]

        self.assertEqual(4, len(deps_graph.nodes))

        self.assertEqual(log4cpp.ref.copy_clear_rev(), log4cpp_ref)
        conanfile = log4cpp.conanfile
        self.assertEqual(conanfile.version, "1.1.1")
        self.assertEqual(conanfile.name, "log4cpp")

        self.assertEqual(logger_interface.ref.copy_clear_rev(), logiface_ref)
        conanfile = logger_interface.conanfile
        self.assertEqual(conanfile.version, "0.1.1")
        self.assertEqual(conanfile.name, "LoggerInterface")

        self.assertEqual(other.ref.copy_clear_rev(), other_ref)
        conanfile = other.conanfile
        self.assertEqual(conanfile.version, "2.0.11549")
        self.assertEqual(conanfile.name, "other")
Example #11
0
 def _get_graph_builder(self, loader, remote_proxy):
     local_search = self._search_manager
     resolver = RequireResolver(self._user_io.out, local_search, remote_proxy)
     graph_builder = DepsGraphBuilder(remote_proxy, self._user_io.out, loader, resolver)
     return graph_builder
Example #12
0
class VersionRangesTest(unittest.TestCase):

    def setUp(self):
        self.output = TestBufferConanOutput()
        self.loader = ConanFileLoader(None, Settings.loads(""), Profile())
        self.retriever = Retriever(self.loader, self.output)
        self.remote_search = MockSearchRemote()
        self.resolver = RequireResolver(self.output, self.retriever, self.remote_search)
        self.builder = DepsGraphBuilder(self.retriever, self.output, self.loader, self.resolver)

        for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]:
            say_content = """
from conans import ConanFile

class SayConan(ConanFile):
    name = "Say"
    version = "%s"
""" % v
            say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v)
            self.retriever.conan(say_ref, say_content)

    def root(self, content):
        root_conan = self.retriever.root(content)
        deps_graph = self.builder.load_graph(root_conan, False, False)
        return deps_graph

    def test_local_basic(self):
        for expr, solution in [(">0.0", "2.2.1"),
                               (">0.1,<1", "0.3"),
                               (">0.1,<1||2.1", "2.1"),
                               ("", "2.2.1"),
                               ("~0", "0.3"),
                               ("~=1", "1.2.1"),
                               ("~1.1", "1.1.2"),
                               ("~=2", "2.2.1"),
                               ("~=2.1", "2.1"),
                               ]:
            deps_graph = self.root(hello_content % expr)

            self.assertEqual(2, len(deps_graph.nodes))
            hello = _get_nodes(deps_graph, "Hello")[0]
            say = _get_nodes(deps_graph, "Say")[0]
            self.assertEqual(_get_edges(deps_graph), {Edge(hello, say)})

            self.assertEqual(hello.conan_ref, None)
            conanfile = hello.conanfile
            self.assertEqual(conanfile.version, "1.2")
            self.assertEqual(conanfile.name, "Hello")
            say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % solution)
            self.assertEqual(conanfile.requires, Requirements(str(say_ref)))

    def test_remote_basic(self):
        self.resolver._local_search = None
        remote_packages = []
        for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]:
            say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v)
            remote_packages.append(say_ref)
        self.remote_search.packages = remote_packages
        self.test_local_basic()

    @parameterized.expand([("", "0.3", None, None),
                           ('"Say/1.1@memsharded/testing"', "1.1", False, False),
                           ('"Say/0.2@memsharded/testing"', "0.2", False, True),
                           ('("Say/1.1@memsharded/testing", "override")', "1.1", True, False),
                           ('("Say/0.2@memsharded/testing", "override")', "0.2", True, True),
                           # ranges
                           ('"Say/[<=1.2]@memsharded/testing"', "1.2.1", False, False),
                           ('"Say/[>=0.2,<=1.0]@memsharded/testing"', "0.3", False, True),
                           ('("Say/[<=1.2]@memsharded/testing", "override")', "1.2.1", True, False),
                           ('("Say/[>=0.2,<=1.0]@memsharded/testing", "override")', "0.3", True, True),
                           ])
    def transitive_test(self, version_range, solution, override, valid):
        hello_text = hello_content % ">0.1, <1"
        hello_ref = ConanFileReference.loads("Hello/1.2@memsharded/testing")
        self.retriever.conan(hello_ref, hello_text)

        chat_content = """
from conans import ConanFile

class ChatConan(ConanFile):
    name = "Chat"
    version = "2.3"
    requires = "Hello/1.2@memsharded/testing", %s
"""
        if valid is False:
            with self.assertRaisesRegexp(ConanException, "not valid"):
                self.root(chat_content % version_range)
            return

        deps_graph = self.root(chat_content % version_range)
        hello = _get_nodes(deps_graph, "Hello")[0]
        say = _get_nodes(deps_graph, "Say")[0]
        chat = _get_nodes(deps_graph, "Chat")[0]
        edges = {Edge(hello, say), Edge(chat, hello)}
        if override is not None:
            self.assertIn("override", self.output)
        else:
            self.assertNotIn("override", self.output)
        if override is False:
            edges = {Edge(hello, say), Edge(chat, say), Edge(chat, hello)}

        if valid is True:
            self.assertIn(" valid", self.output)
        elif valid is False:
            self.assertIn("not valid", self.output)
        self.assertEqual(3, len(deps_graph.nodes))

        self.assertEqual(_get_edges(deps_graph), edges)

        self.assertEqual(hello.conan_ref, hello_ref)
        conanfile = hello.conanfile
        self.assertEqual(conanfile.version, "1.2")
        self.assertEqual(conanfile.name, "Hello")
        say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % solution)
        self.assertEqual(conanfile.requires, Requirements(str(say_ref)))

    def duplicated_error_test(self):
        content = """
from conans import ConanFile

class Log3cppConan(ConanFile):
    name = "log4cpp"
    version = "1.1.1"
"""
        log4cpp_ref = ConanFileReference.loads("log4cpp/1.1.1@memsharded/testing")
        self.retriever.conan(log4cpp_ref, content)

        content = """
from conans import ConanFile

class LoggerInterfaceConan(ConanFile):
    name = "LoggerInterface"
    version = "0.1.1"

    def requirements(self):
        self.requires("log4cpp/[~1.1]@memsharded/testing")
"""
        logiface_ref = ConanFileReference.loads("LoggerInterface/0.1.1@memsharded/testing")
        self.retriever.conan(logiface_ref, content)

        content = """
from conans import ConanFile

class OtherConan(ConanFile):
    name = "other"
    version = "2.0.11549"
    requires = "LoggerInterface/[~0.1]@memsharded/testing"
"""
        other_ref = ConanFileReference.loads("other/2.0.11549@memsharded/testing")
        self.retriever.conan(other_ref, content)

        content = """
from conans import ConanFile

class Project(ConanFile):
    requires = "LoggerInterface/[~0.1]@memsharded/testing", "other/[~2.0]@memsharded/testing"
"""
        deps_graph = self.root(content)

        log4cpp = _get_nodes(deps_graph, "log4cpp")[0]
        logger_interface = _get_nodes(deps_graph, "LoggerInterface")[0]
        other = _get_nodes(deps_graph, "other")[0]

        self.assertEqual(4, len(deps_graph.nodes))

        self.assertEqual(log4cpp.conan_ref, log4cpp_ref)
        conanfile = log4cpp.conanfile
        self.assertEqual(conanfile.version, "1.1.1")
        self.assertEqual(conanfile.name, "log4cpp")

        self.assertEqual(logger_interface.conan_ref, logiface_ref)
        conanfile = logger_interface.conanfile
        self.assertEqual(conanfile.version, "0.1.1")
        self.assertEqual(conanfile.name, "LoggerInterface")

        self.assertEqual(other.conan_ref, other_ref)
        conanfile = other.conanfile
        self.assertEqual(conanfile.version, "2.0.11549")
        self.assertEqual(conanfile.name, "other")
Example #13
0
class VersionRangesTest(unittest.TestCase):
    def setUp(self):
        self.output = TestBufferConanOutput()
        self.loader = ConanFileLoader(None, Settings.loads(""), Profile())
        self.retriever = Retriever(self.loader, self.output)
        self.remote_search = MockSearchRemote()
        self.resolver = RequireResolver(self.output, self.retriever,
                                        self.remote_search)
        self.builder = DepsGraphBuilder(self.retriever, self.output,
                                        self.loader, self.resolver)

        for v in [
                "0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"
        ]:
            say_content = """
from conans import ConanFile

class SayConan(ConanFile):
    name = "Say"
    version = "%s"
""" % v
            say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v)
            self.retriever.conan(say_ref, say_content)

    def root(self, content):
        root_conan = self.retriever.root(content)
        deps_graph = self.builder.load_graph(root_conan, False, False)
        return deps_graph

    def test_local_basic(self):
        for expr, solution in [
            (">0.0", "2.2.1"),
            (">0.1,<1", "0.3"),
            (">0.1,<1||2.1", "2.1"),
            ("", "2.2.1"),
            ("~0", "0.3"),
            ("~=1", "1.2.1"),
            ("~1.1", "1.1.2"),
            ("~=2", "2.2.1"),
            ("~=2.1", "2.1"),
        ]:
            deps_graph = self.root(hello_content % expr)

            self.assertEqual(2, len(deps_graph.nodes))
            hello = _get_nodes(deps_graph, "Hello")[0]
            say = _get_nodes(deps_graph, "Say")[0]
            self.assertEqual(_get_edges(deps_graph), {Edge(hello, say)})

            self.assertEqual(hello.conan_ref, None)
            conanfile = hello.conanfile
            self.assertEqual(conanfile.version, "1.2")
            self.assertEqual(conanfile.name, "Hello")
            say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" %
                                               solution)
            self.assertEqual(conanfile.requires, Requirements(str(say_ref)))

    def test_remote_basic(self):
        self.resolver._local_search = None
        remote_packages = []
        for v in [
                "0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"
        ]:
            say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v)
            remote_packages.append(say_ref)
        self.remote_search.packages = remote_packages
        self.test_local_basic()

    @parameterized.expand([
        ("", "0.3", None, None),
        ('"Say/1.1@memsharded/testing"', "1.1", False, False),
        ('"Say/0.2@memsharded/testing"', "0.2", False, True),
        ('("Say/1.1@memsharded/testing", "override")', "1.1", True, False),
        ('("Say/0.2@memsharded/testing", "override")', "0.2", True, True),
        # ranges
        ('"Say/[<=1.2]@memsharded/testing"', "1.2.1", False, False),
        ('"Say/[>=0.2,<=1.0]@memsharded/testing"', "0.3", False, True),
        ('("Say/[<=1.2]@memsharded/testing", "override")', "1.2.1", True,
         False),
        ('("Say/[>=0.2,<=1.0]@memsharded/testing", "override")', "0.3", True,
         True),
    ])
    def transitive_test(self, version_range, solution, override, valid):
        hello_text = hello_content % ">0.1, <1"
        hello_ref = ConanFileReference.loads("Hello/1.2@memsharded/testing")
        self.retriever.conan(hello_ref, hello_text)

        chat_content = """
from conans import ConanFile

class ChatConan(ConanFile):
    name = "Chat"
    version = "2.3"
    requires = "Hello/1.2@memsharded/testing", %s
"""
        if valid is False:
            with self.assertRaisesRegexp(ConanException, "not valid"):
                self.root(chat_content % version_range)
            return

        deps_graph = self.root(chat_content % version_range)
        hello = _get_nodes(deps_graph, "Hello")[0]
        say = _get_nodes(deps_graph, "Say")[0]
        chat = _get_nodes(deps_graph, "Chat")[0]
        edges = {Edge(hello, say), Edge(chat, hello)}
        if override is not None:
            self.assertIn("override", self.output)
        else:
            self.assertNotIn("override", self.output)
        if override is False:
            edges = {Edge(hello, say), Edge(chat, say), Edge(chat, hello)}

        if valid is True:
            self.assertIn(" valid", self.output)
        elif valid is False:
            self.assertIn("not valid", self.output)
        self.assertEqual(3, len(deps_graph.nodes))

        self.assertEqual(_get_edges(deps_graph), edges)

        self.assertEqual(hello.conan_ref, hello_ref)
        conanfile = hello.conanfile
        self.assertEqual(conanfile.version, "1.2")
        self.assertEqual(conanfile.name, "Hello")
        say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" %
                                           solution)
        self.assertEqual(conanfile.requires, Requirements(str(say_ref)))

    def duplicated_error_test(self):
        content = """
from conans import ConanFile

class Log3cppConan(ConanFile):
    name = "log4cpp"
    version = "1.1.1"
"""
        log4cpp_ref = ConanFileReference.loads(
            "log4cpp/1.1.1@memsharded/testing")
        self.retriever.conan(log4cpp_ref, content)

        content = """
from conans import ConanFile

class LoggerInterfaceConan(ConanFile):
    name = "LoggerInterface"
    version = "0.1.1"

    def requirements(self):
        self.requires("log4cpp/[~1.1]@memsharded/testing")
"""
        logiface_ref = ConanFileReference.loads(
            "LoggerInterface/0.1.1@memsharded/testing")
        self.retriever.conan(logiface_ref, content)

        content = """
from conans import ConanFile

class OtherConan(ConanFile):
    name = "other"
    version = "2.0.11549"
    requires = "LoggerInterface/[~0.1]@memsharded/testing"
"""
        other_ref = ConanFileReference.loads(
            "other/2.0.11549@memsharded/testing")
        self.retriever.conan(other_ref, content)

        content = """
from conans import ConanFile

class Project(ConanFile):
    requires = "LoggerInterface/[~0.1]@memsharded/testing", "other/[~2.0]@memsharded/testing"
"""
        deps_graph = self.root(content)

        log4cpp = _get_nodes(deps_graph, "log4cpp")[0]
        logger_interface = _get_nodes(deps_graph, "LoggerInterface")[0]
        other = _get_nodes(deps_graph, "other")[0]

        self.assertEqual(4, len(deps_graph.nodes))

        self.assertEqual(log4cpp.conan_ref, log4cpp_ref)
        conanfile = log4cpp.conanfile
        self.assertEqual(conanfile.version, "1.1.1")
        self.assertEqual(conanfile.name, "log4cpp")

        self.assertEqual(logger_interface.conan_ref, logiface_ref)
        conanfile = logger_interface.conanfile
        self.assertEqual(conanfile.version, "0.1.1")
        self.assertEqual(conanfile.name, "LoggerInterface")

        self.assertEqual(other.conan_ref, other_ref)
        conanfile = other.conanfile
        self.assertEqual(conanfile.version, "2.0.11549")
        self.assertEqual(conanfile.name, "other")