def setUp(self): self.conan_reference = ConanFileReference.loads("openssl/2.0.3@lasote/testing") self.package_reference = PackageReference(self.conan_reference, "123123123") self.remote_client = MockRemoteClient() self.output = TestBufferConanOutput() self.client_cache = ClientCache(temp_folder(), temp_folder(), self.output) self.remotes = [("default", "url1"), ("other", "url2"), ("last", "url3")] self.manager = RemoteManager(self.client_cache, self.remote_client, self.output)
def __init__(self, base_folder=None, current_folder=None, servers=None, users=None, client_version=CLIENT_VERSION, min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION, requester_class=None, runner=None, path_with_spaces=True): """ storage_folder: Local storage path current_folder: Current execution folder servers: dict of {remote_name: TestServer} logins is a list of (user, password) for auto input in order if required==> [("lasote", "mypass"), ("other", "otherpass")] """ self.all_output = "" # For debugging purpose, append all the run outputs self.users = users or { "default": [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)] } self.servers = servers or {} self.client_version = Version(str(client_version)) self.min_server_compatible_version = Version( str(min_server_compatible_version)) self.base_folder = base_folder or temp_folder(path_with_spaces) # Define storage_folder, if not, it will be read from conf file & pointed to real user home self.storage_folder = os.path.join(self.base_folder, ".conan", "data") self.client_cache = ClientCache(self.base_folder, self.storage_folder, TestBufferConanOutput()) search_adapter = DiskSearchAdapter() self.search_manager = DiskSearchManager(self.client_cache, search_adapter) self._default_settings(get_env("CONAN_COMPILER", "gcc"), get_env("CONAN_COMPILER_VERSION", "4.8"), get_env("CONAN_LIBCXX", "libstdc++")) self.requester_class = requester_class self.conan_runner = runner self.init_dynamic_vars() save(self.client_cache.registry, "") registry = RemoteRegistry(self.client_cache.registry, TestBufferConanOutput()) for name, server in self.servers.items(): if isinstance(server, TestServer): registry.add(name, server.fake_url) else: registry.add(name, server) logger.debug("Client storage = %s" % self.storage_folder) self.current_folder = current_folder or temp_folder(path_with_spaces)
def migrate_and_get_client_cache(base_folder, out, manager, storage_folder=None): # Init paths client_cache = ClientCache(base_folder, storage_folder, out) # Migration system migrator = ClientMigrator(client_cache, Version(CLIENT_VERSION), out, manager) migrator.migrate() # Init again paths, migration could change config client_cache = ClientCache(base_folder, storage_folder, out) return client_cache
def __init__(self, base_folder=None, current_folder=None, servers=None, users=None, client_version=CLIENT_VERSION, min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION, requester_class=None, runner=None, path_with_spaces=True, default_profile=True): """ storage_folder: Local storage path current_folder: Current execution folder servers: dict of {remote_name: TestServer} logins is a list of (user, password) for auto input in order if required==> [("lasote", "mypass"), ("other", "otherpass")] """ self.all_output = "" # For debugging purpose, append all the run outputs self.users = users or { "default": [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)] } self.client_version = Version(str(client_version)) self.min_server_compatible_version = Version( str(min_server_compatible_version)) self.base_folder = base_folder or temp_folder(path_with_spaces) # Define storage_folder, if not, it will be read from conf file & pointed to real user home self.storage_folder = os.path.join(self.base_folder, ".conan", "data") self.client_cache = ClientCache(self.base_folder, self.storage_folder, TestBufferConanOutput()) search_adapter = DiskSearchAdapter() self.search_manager = DiskSearchManager(self.client_cache, search_adapter) self.requester_class = requester_class self.conan_runner = runner self.update_servers(servers) self.init_dynamic_vars() logger.debug("Client storage = %s" % self.storage_folder) self.current_folder = current_folder or temp_folder(path_with_spaces) # Enforcing VS 2015, even if VS2017 is auto detected if default_profile: profile = self.client_cache.default_profile if profile.settings.get("compiler.version") == "15": profile.settings["compiler.version"] = "14" save(self.client_cache.default_profile_path, profile.dumps())
class RemoteManagerTest(unittest.TestCase): """Unit test""" def setUp(self): self.conan_reference = ConanFileReference.loads( "openssl/2.0.3@lasote/testing") self.package_reference = PackageReference(self.conan_reference, "123123123") self.remote_client = MockRemoteClient() self.output = TestBufferConanOutput() self.client_cache = ClientCache(temp_folder(), temp_folder(), self.output) self.manager = RemoteManager(self.client_cache, self.remote_client, self.output) def test_no_remotes(self): client = TestClient() files = cpp_hello_conan_files("Hello0", "0.1") client.save(files) client.run("export lasote/stable") client.run("upload Hello0/0.1@lasote/stable", ignore_error=True) self.assertIn("ERROR: No default remote defined", client.user_io.out) def method_called_test(self): save( os.path.join(self.client_cache.package(self.package_reference), CONANINFO), "asdasd") manifest = FileTreeManifest.create( self.client_cache.package(self.package_reference)) save( os.path.join(self.client_cache.package(self.package_reference), CONAN_MANIFEST), str(manifest)) self.assertFalse(self.remote_client.upload_package.called) self.manager.upload_package(self.package_reference, Remote("other", "url", True), 1, 0) self.assertTrue(self.remote_client.upload_package.called) self.assertFalse(self.remote_client.get_conan_digest.called) self.manager.get_conan_digest(self.conan_reference, Remote("other", "url", True)) self.assertTrue(self.remote_client.get_conan_digest.called) self.assertFalse(self.remote_client.get_recipe.called) self.manager.get_recipe(self.conan_reference, temp_folder(), Remote("other", "url", True)) self.assertTrue(self.remote_client.get_recipe.called) self.assertFalse(self.remote_client.get_package.called) self.manager.get_package(self.package_reference, temp_folder(), Remote("other", "url", True)) self.assertTrue(self.remote_client.get_package.called)
class RemoteManagerTest(unittest.TestCase): """Unit test""" def setUp(self): self.conan_reference = ConanFileReference.loads("openssl/2.0.3@lasote/testing") self.package_reference = PackageReference(self.conan_reference, "123123123") self.remote_client = MockRemoteClient() self.output = TestBufferConanOutput() self.client_cache = ClientCache(temp_folder(), temp_folder(), self.output) self.remotes = [("default", "url1"), ("other", "url2"), ("last", "url3")] self.manager = RemoteManager(self.client_cache, self.remote_client, self.output) def test_no_remotes(self): client = TestClient() files = cpp_hello_conan_files("Hello0", "0.1") client.save(files) client.run("export lasote/stable") client.run("upload Hello0/0.1@lasote/stable", ignore_error=True) self.assertIn("ERROR: No default remote defined", client.user_io.out) def remote_selection_test(self): save(os.path.join(self.client_cache.export(self.conan_reference), CONANFILE), "asdasd") save(os.path.join(self.client_cache.export(self.conan_reference), CONAN_MANIFEST), "asdasd") # If no remote is specified will look to first self.assertRaises(NotFoundException, self.manager.upload_conan, self.conan_reference, None) # If remote is specified took it self.assertRaises(NotFoundException, self.manager.upload_conan, self.conan_reference, Remote("other", "url")) def method_called_test(self): save(os.path.join(self.client_cache.package(self.package_reference), CONANINFO), "asdasd") manifest = FileTreeManifest.create(self.client_cache.package(self.package_reference)) save(os.path.join(self.client_cache.package(self.package_reference), CONAN_MANIFEST), str(manifest)) self.assertFalse(self.remote_client.upload_package.called) self.manager.upload_package(self.package_reference, Remote("other", "url")) self.assertTrue(self.remote_client.upload_package.called) self.assertFalse(self.remote_client.get_conan_digest.called) self.manager.get_conan_digest(self.conan_reference, Remote("other", "url")) self.assertTrue(self.remote_client.get_conan_digest.called) self.assertFalse(self.remote_client.get_recipe.called) self.manager.get_recipe(self.conan_reference, temp_folder(), Remote("other", "url")) self.assertTrue(self.remote_client.get_recipe.called) self.assertFalse(self.remote_client.get_package.called) self.manager.get_package(self.package_reference, temp_folder(), Remote("other", "url")) self.assertTrue(self.remote_client.get_package.called)
def _init_collaborators(self, user_io=None): output = TestBufferConanOutput() self.user_io = user_io or MockedUserIO(self.users, out=output) self.client_cache = ClientCache(self.base_folder, self.storage_folder, output) self.runner = TestRunner(output, runner=self.conan_runner) # Check if servers are real real_servers = False for server in self.servers.values(): if isinstance(server, str): # Just URI real_servers = True with tools.environment_append(self.client_cache.conan_config.env_vars): if real_servers: requester = requests.Session() else: if self.requester_class: requester = self.requester_class(self.servers) else: requester = TestRequester(self.servers) self.requester = ConanRequester(requester, self.client_cache, get_request_timeout()) self.hook_manager = HookManager(self.client_cache.hooks_path, get_env("CONAN_HOOKS", list()), self.user_io.out) self.localdb, self.rest_api_client, self.remote_manager = Conan.instance_remote_manager( self.requester, self.client_cache, self.user_io, self.client_version, self.min_server_compatible_version, self.hook_manager) set_global_instances(output, self.requester)
def setUp(self): self.conan_reference = ConanFileReference.loads("openssl/2.0.3@lasote/testing") self.package_reference = PackageReference(self.conan_reference, "123123123") self.remote_client = MockRemoteClient() self.output = TestBufferConanOutput() self.client_cache = ClientCache(temp_folder(), temp_folder(), self.output) self.manager = RemoteManager(self.client_cache, self.remote_client, self.output)
def get_command(): def instance_remote_manager(client_cache): requester = requests.Session() requester.proxies = client_cache.conan_config.proxies # Verify client version against remotes version_checker_requester = VersionCheckerRequester( requester, Version(CLIENT_VERSION), Version(MIN_SERVER_COMPATIBLE_VERSION), out) # To handle remote connections rest_api_client = RestApiClient(out, requester=version_checker_requester) # To store user and token localdb = LocalDB(client_cache.localdb) # Wraps RestApiClient to add authentication support (same interface) auth_manager = ConanApiAuthManager(rest_api_client, user_io, localdb) # Handle remote connections remote_manager = RemoteManager(client_cache, auth_manager, out) return remote_manager use_color = get_env("CONAN_COLOR_DISPLAY", 1) if use_color and hasattr(sys.stdout, "isatty") and sys.stdout.isatty(): import colorama colorama.init() color = True else: color = False out = ConanOutput(sys.stdout, color) user_io = UserIO(out=out) user_folder = os.getenv("CONAN_USER_HOME", conan_expand_user("~")) try: # To capture exceptions in conan.conf parsing client_cache = ClientCache(user_folder, None, out) # obtain a temp ConanManager instance to execute the migrations remote_manager = instance_remote_manager(client_cache) # Get a DiskSearchManager search_adapter = DiskSearchAdapter() search_manager = DiskSearchManager(client_cache, search_adapter) manager = ConanManager(client_cache, user_io, ConanRunner(), remote_manager, search_manager) client_cache = migrate_and_get_client_cache(user_folder, out, manager) except Exception as e: out.error(str(e)) sys.exit(True) # Get the new command instance after migrations have been done remote_manager = instance_remote_manager(client_cache) # Get a search manager search_adapter = DiskSearchAdapter() search_manager = DiskSearchManager(client_cache, search_adapter) command = Command(client_cache, user_io, ConanRunner(), remote_manager, search_manager) return command
def migrate_and_get_client_cache(base_folder, out, storage_folder=None): # Init paths client_cache = ClientCache(base_folder, storage_folder, out) # Migration system migrator = ClientMigrator(client_cache, Version(client_version), out) migrator.migrate() return client_cache
def __init__(self, base_folder=None, current_folder=None, servers=None, users=None, client_version=CLIENT_VERSION, min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION, requester_class=None, runner=None, path_with_spaces=True): """ storage_folder: Local storage path current_folder: Current execution folder servers: dict of {remote_name: TestServer} logins is a list of (user, password) for auto input in order if required==> [("lasote", "mypass"), ("other", "otherpass")] """ self.all_output = "" # For debugging purpose, append all the run outputs self.users = users or { "default": [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)] } self.client_version = Version(str(client_version)) self.min_server_compatible_version = Version( str(min_server_compatible_version)) self.base_folder = base_folder or temp_folder(path_with_spaces) # Define storage_folder, if not, it will be read from conf file & pointed to real user home self.storage_folder = os.path.join(self.base_folder, ".conan", "data") self.client_cache = ClientCache(self.base_folder, self.storage_folder, TestBufferConanOutput()) self.requester_class = requester_class self.conan_runner = runner if servers and len(servers) > 1 and not isinstance( servers, OrderedDict): raise Exception( """Testing framework error: Servers should be an OrderedDict. e.g: servers = OrderedDict() servers["r1"] = server servers["r2"] = TestServer() """) self.servers = servers or {} if servers is not False: # Do not mess with registry remotes self.update_servers() self.init_dynamic_vars() logger.debug("Client storage = %s" % self.storage_folder) self.current_folder = current_folder or temp_folder(path_with_spaces)
def conan_compiler_info(self): """return the compiler and its version readed in conan.conf""" out = ConanOutput(sys.stdout) cache = ClientCache(os.environ.get("CONAN_USER_HOME", "~/"), None, out) if hasattr(cache, "default_profile"): profile = cache.default_profile settings = profile.settings else: settings = dict(cache.conan_config.get_conf("settings_defaults")) return settings["compiler"], settings["compiler.version"]
def env_setting_override_test(self): tmp_dir = temp_folder() out = MockOut() cache = ClientCache(tmp_dir, None, out) base_settings = OrderedDict(detect_defaults_settings(out)) with tools.environment_append({"CONAN_ENV_COMPILER_VERSION": "4.6"}): expected = copy.copy(base_settings) expected["compiler.version"] = "4.6" self.assertEquals(cache.default_profile.settings, expected) tmp_dir = temp_folder() cache = ClientCache(tmp_dir, None, out) with tools.environment_append({}): self.assertEquals(cache.default_profile.settings, base_settings) tmp_dir = temp_folder() cache = ClientCache(tmp_dir, None, out) # If compiler is overwritten compiler subsettings are not assigned with tools.environment_append({"CONAN_ENV_COMPILER": "Visual Studio"}): expected = copy.copy(base_settings) expected["compiler"] = "Visual Studio" self.assertEquals(cache.default_profile.settings, expected) tmp_dir = temp_folder() cache = ClientCache(tmp_dir, None, out) with tools.environment_append({ "CONAN_ENV_COMPILER": "Visual Studio", "CONAN_ENV_COMPILER_VERSION": "14", "CONAN_ENV_COMPILER_RUNTIME": "MDd" }): expected = copy.copy(base_settings) expected["compiler"] = "Visual Studio" expected["compiler.runtime"] = "MDd" expected["compiler.version"] = "14" self.assertEquals(cache.default_profile.settings, expected)
def setUp(self): folder = temp_folder() self.paths = ClientCache(folder, store_folder=folder, output=TestBufferConanOutput())
class TestClient(object): """ Test wrap of the conans application to launch tests in the same way as in command line """ def __init__(self, base_folder=None, current_folder=None, servers=None, users=None, client_version=CLIENT_VERSION, min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION, requester_class=None, runner=None, path_with_spaces=True, default_profile=True): """ storage_folder: Local storage path current_folder: Current execution folder servers: dict of {remote_name: TestServer} logins is a list of (user, password) for auto input in order if required==> [("lasote", "mypass"), ("other", "otherpass")] """ self.all_output = "" # For debugging purpose, append all the run outputs self.users = users or { "default": [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)] } self.client_version = Version(str(client_version)) self.min_server_compatible_version = Version( str(min_server_compatible_version)) self.base_folder = base_folder or temp_folder(path_with_spaces) # Define storage_folder, if not, it will be read from conf file & pointed to real user home self.storage_folder = os.path.join(self.base_folder, ".conan", "data") self.client_cache = ClientCache(self.base_folder, self.storage_folder, TestBufferConanOutput()) search_adapter = DiskSearchAdapter() self.search_manager = DiskSearchManager(self.client_cache, search_adapter) self.requester_class = requester_class self.conan_runner = runner self.update_servers(servers) self.init_dynamic_vars() logger.debug("Client storage = %s" % self.storage_folder) self.current_folder = current_folder or temp_folder(path_with_spaces) # Enforcing VS 2015, even if VS2017 is auto detected if default_profile: profile = self.client_cache.default_profile # if profile.settings.get("compiler.version") == "15": # profile.settings["compiler.version"] = "14" # save(self.client_cache.default_profile_path, profile.dumps()) def update_servers(self, servers): self.servers = servers or {} save(self.client_cache.registry, "") registry = RemoteRegistry(self.client_cache.registry, TestBufferConanOutput()) for name, server in self.servers.items(): if isinstance(server, TestServer): registry.add(name, server.fake_url) else: registry.add(name, server) @property def paths(self): return self.client_cache @property def default_compiler_visual_studio(self): settings = self.client_cache.default_profile.settings return settings.get("compiler", None) == "Visual Studio" @property def out(self): return self.user_io.out @contextmanager def chdir(self, newdir): old_dir = self.current_folder if not os.path.isabs(newdir): newdir = os.path.join(old_dir, newdir) mkdir(newdir) self.current_folder = newdir try: yield finally: self.current_folder = old_dir def _init_collaborators(self, user_io=None): output = TestBufferConanOutput() self.user_io = user_io or MockedUserIO(self.users, out=output) self.runner = TestRunner(output, runner=self.conan_runner) # Check if servers are real real_servers = False for server in self.servers.values(): if isinstance(server, str): # Just URI real_servers = True if real_servers: requester = requests else: if self.requester_class: requester = self.requester_class(self.servers) else: requester = TestRequester(self.servers) # Verify client version against remotes self.requester = VersionCheckerRequester( requester, self.client_version, self.min_server_compatible_version, output) put_headers = self.client_cache.read_put_headers() self.rest_api_client = RestApiClient(output, requester=self.requester, put_headers=put_headers) # To store user and token self.localdb = LocalDB(self.client_cache.localdb) # Wraps RestApiClient to add authentication support (same interface) auth_manager = ConanApiAuthManager(self.rest_api_client, self.user_io, self.localdb) # Handle remote connections self.remote_manager = RemoteManager(self.client_cache, auth_manager, self.user_io.out) set_global_instances(output, self.requester) def init_dynamic_vars(self, user_io=None): # Migration system self.client_cache = migrate_and_get_client_cache( self.base_folder, TestBufferConanOutput(), storage_folder=self.storage_folder) # Maybe something have changed with migrations self._init_collaborators(user_io) def run(self, command_line, user_io=None, ignore_error=False): """ run a single command as in the command line. If user or password is filled, user_io will be mocked to return this tuple if required """ self.init_dynamic_vars(user_io) conan = Conan(self.client_cache, self.user_io, self.runner, self.remote_manager, self.search_manager, settings_preprocessor) outputer = CommandOutputer(self.user_io, self.client_cache) command = Command(conan, self.client_cache, self.user_io, outputer) args = shlex.split(command_line) current_dir = os.getcwd() os.chdir(self.current_folder) old_path = sys.path[:] sys.path.append(os.path.join(self.client_cache.conan_folder, "python")) old_modules = list(sys.modules.keys()) try: error = command.run(args) finally: sys.path = old_path os.chdir(current_dir) # Reset sys.modules to its prev state. A .copy() DOES NOT WORK added_modules = set(sys.modules).difference(old_modules) for added in added_modules: sys.modules.pop(added, None) if not ignore_error and error: logger.error(self.user_io.out) print(self.user_io.out) raise Exception("Command failed:\n%s" % command_line) self.all_output += str(self.user_io.out) return error def save(self, files, path=None, clean_first=False): """ helper metod, will store files in the current folder param files: dict{filename: filecontents} """ path = path or self.current_folder if clean_first: shutil.rmtree(self.current_folder, ignore_errors=True) save_files(path, files) if not files: mkdir(self.current_folder)
class TestClient(object): """ Test wrap of the conans application to launch tests in the same way as in command line """ def __init__(self, base_folder=None, current_folder=None, servers=None, users=None, client_version=CLIENT_VERSION, min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION, requester_class=None, runner=None, path_with_spaces=True): """ storage_folder: Local storage path current_folder: Current execution folder servers: dict of {remote_name: TestServer} logins is a list of (user, password) for auto input in order if required==> [("lasote", "mypass"), ("other", "otherpass")] """ self.all_output = "" # For debugging purpose, append all the run outputs self.users = users or {"default": [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)]} self.servers = servers or {} self.client_version = Version(str(client_version)) self.min_server_compatible_version = Version(str(min_server_compatible_version)) self.base_folder = base_folder or temp_folder(path_with_spaces) # Define storage_folder, if not, it will be read from conf file & pointed to real user home self.storage_folder = os.path.join(self.base_folder, ".conan", "data") self.client_cache = ClientCache(self.base_folder, self.storage_folder, TestBufferConanOutput()) search_adapter = DiskSearchAdapter() self.search_manager = DiskSearchManager(self.client_cache, search_adapter) self._default_settings(get_env("CONAN_COMPILER", "gcc"), get_env("CONAN_COMPILER_VERSION", "4.8"), get_env("CONAN_LIBCXX", "libstdc++")) self.requester_class = requester_class self.conan_runner = runner self.init_dynamic_vars() save(self.client_cache.registry, "") registry = RemoteRegistry(self.client_cache.registry, TestBufferConanOutput()) for name, server in self.servers.items(): if isinstance(server, TestServer): registry.add(name, server.fake_url) else: registry.add(name, server) logger.debug("Client storage = %s" % self.storage_folder) self.current_folder = current_folder or temp_folder(path_with_spaces) @property def paths(self): return self.client_cache def _default_settings(self, compiler, compiler_version, libcxx): """ allows to change the default settings in the file, to change compiler, version """ # Set default settings in global defined self.client_cache.conan_config # For create the default file if not existing text = load(self.client_cache.conan_conf_path) # prevent TestClient instances with reused paths to write again the compiler if compiler != "Visual Studio": text = text.replace("compiler.runtime=MD", "") if "compiler=" not in text: # text = text.replace("build_type=Release", "") text += "\ncompiler=%s" % compiler text += "\ncompiler.version=%s" % compiler_version if compiler != "Visual Studio": text += "\ncompiler.libcxx=%s" % libcxx save(self.client_cache.conan_conf_path, text) @property def default_compiler_visual_studio(self): text = load(self.client_cache.conan_conf_path) return "compiler=Visual Studio" in text def _init_collaborators(self, user_io=None): output = TestBufferConanOutput() self.user_io = user_io or MockedUserIO(self.users, out=output) self.runner = TestRunner(output, runner=self.conan_runner) # Check if servers are real real_servers = False for server in self.servers.values(): if isinstance(server, str): # Just URI real_servers = True if real_servers: requester = requests else: if self.requester_class: requester = self.requester_class(self.servers) else: requester = TestRequester(self.servers) # Verify client version against remotes self.requester = VersionCheckerRequester(requester, self.client_version, self.min_server_compatible_version, output) put_headers = self.client_cache.read_put_headers() self.rest_api_client = RestApiClient(output, requester=self.requester, put_headers=put_headers) # To store user and token self.localdb = LocalDB(self.client_cache.localdb) # Wraps RestApiClient to add authentication support (same interface) auth_manager = ConanApiAuthManager(self.rest_api_client, self.user_io, self.localdb) # Handle remote connections self.remote_manager = RemoteManager(self.client_cache, auth_manager, self.user_io.out) def init_dynamic_vars(self, user_io=None): # Migration system self.client_cache = migrate_and_get_client_cache(self.base_folder, TestBufferConanOutput(), storage_folder=self.storage_folder) # Maybe something have changed with migrations self._init_collaborators(user_io) def run(self, command_line, user_io=None, ignore_error=False): """ run a single command as in the command line. If user or password is filled, user_io will be mocked to return this tuple if required """ self.init_dynamic_vars(user_io) command = Command(self.client_cache, self.user_io, self.runner, self.remote_manager, self.search_manager) args = shlex.split(command_line) current_dir = os.getcwd() os.chdir(self.current_folder) old_modules = list(sys.modules.keys()) try: error = command.run(args) finally: os.chdir(current_dir) # Reset sys.modules to its prev state. A .copy() DOES NOT WORK added_modules = set(sys.modules).difference(old_modules) for added in added_modules: sys.modules.pop(added, None) if not ignore_error and error: logger.error(self.user_io.out) raise Exception("Command failed:\n%s" % command_line) self.all_output += str(self.user_io.out) return error def save(self, files, path=None, clean_first=False): """ helper metod, will store files in the current folder param files: dict{filename: filecontents} """ path = path or self.current_folder if clean_first: shutil.rmtree(self.current_folder, ignore_errors=True) save_files(path, files)
def __init__(self, base_folder=None, current_folder=None, servers=None, users=None, client_version=CLIENT_VERSION, min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION, requester_class=None, runner=None, path_with_spaces=True, block_v2=None, revisions=None, cpu_count=1): """ storage_folder: Local storage path current_folder: Current execution folder servers: dict of {remote_name: TestServer} logins is a list of (user, password) for auto input in order if required==> [("lasote", "mypass"), ("other", "otherpass")] """ self.block_v2 = block_v2 or get_env("CONAN_API_V2_BLOCKED", True) if self.block_v2: self.revisions = False else: self.revisions = revisions or get_env( "CONAN_CLIENT_REVISIONS_ENABLED", False) self.block_v2 = False self.all_output = "" # For debugging purpose, append all the run outputs self.users = users or { "default": [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)] } self.client_version = Version(str(client_version)) self.min_server_compatible_version = Version( str(min_server_compatible_version)) self.base_folder = base_folder or temp_folder(path_with_spaces) # Define storage_folder, if not, it will be read from conf file & pointed to real user home self.storage_folder = os.path.join(self.base_folder, ".conan", "data") self.client_cache = ClientCache(self.base_folder, self.storage_folder, TestBufferConanOutput()) self.requester_class = requester_class self.conan_runner = runner if cpu_count: self.client_cache.conan_config replace_in_file(os.path.join(self.client_cache.conan_conf_path), "# cpu_count = 1", "cpu_count = %s" % cpu_count, output=TestBufferConanOutput()) # Invalidate the cached config self.client_cache.invalidate() if self.revisions: # Generate base file self.client_cache.conan_config replace_in_file(os.path.join(self.client_cache.conan_conf_path), "revisions_enabled = False", "revisions_enabled = True", strict=False) # Invalidate the cached config self.client_cache.invalidate() if servers and len(servers) > 1 and not isinstance( servers, OrderedDict): raise Exception( """Testing framework error: Servers should be an OrderedDict. e.g: servers = OrderedDict() servers["r1"] = server servers["r2"] = TestServer() """) self.servers = servers or {} if servers is not False: # Do not mess with registry remotes self.update_servers() self.init_dynamic_vars() logger.debug("Client storage = %s" % self.storage_folder) self.current_folder = current_folder or temp_folder(path_with_spaces)
class TestClient(object): """ Test wrap of the conans application to launch tests in the same way as in command line """ def __init__(self, base_folder=None, current_folder=None, servers=None, users=None, client_version=CLIENT_VERSION, min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION, requester_class=None, runner=None, path_with_spaces=True, block_v2=None, revisions=None): """ storage_folder: Local storage path current_folder: Current execution folder servers: dict of {remote_name: TestServer} logins is a list of (user, password) for auto input in order if required==> [("lasote", "mypass"), ("other", "otherpass")] """ self.block_v2 = block_v2 or get_env("CONAN_API_V2_BLOCKED", True) if self.block_v2: self.revisions = False else: self.revisions = revisions or get_env( "CONAN_CLIENT_REVISIONS_ENABLED", False) self.block_v2 = False self.all_output = "" # For debugging purpose, append all the run outputs self.users = users or { "default": [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)] } self.client_version = Version(str(client_version)) self.min_server_compatible_version = Version( str(min_server_compatible_version)) self.base_folder = base_folder or temp_folder(path_with_spaces) # Define storage_folder, if not, it will be read from conf file & pointed to real user home self.storage_folder = os.path.join(self.base_folder, ".conan", "data") self.client_cache = ClientCache(self.base_folder, self.storage_folder, TestBufferConanOutput()) self.requester_class = requester_class self.conan_runner = runner if self.revisions: # Generate base file self.client_cache.conan_config replace_in_file(os.path.join(self.client_cache.conan_conf_path), "revisions_enabled = False", "revisions_enabled = True", strict=False) # Invalidate the cached config self.client_cache.invalidate() if servers and len(servers) > 1 and not isinstance( servers, OrderedDict): raise Exception( """Testing framework error: Servers should be an OrderedDict. e.g: servers = OrderedDict() servers["r1"] = server servers["r2"] = TestServer() """) self.servers = servers or {} if servers is not False: # Do not mess with registry remotes self.update_servers() self.init_dynamic_vars() logger.debug("Client storage = %s" % self.storage_folder) self.current_folder = current_folder or temp_folder(path_with_spaces) def update_servers(self): save(self.client_cache.registry, dump_registry({}, {}, {})) registry = RemoteRegistry(self.client_cache.registry, TestBufferConanOutput()) def add_server_to_registry(name, server): if isinstance(server, TestServer): registry.remotes.add(name, server.fake_url) else: registry.remotes.add(name, server) for name, server in self.servers.items(): if name == "default": add_server_to_registry(name, server) for name, server in self.servers.items(): if name != "default": add_server_to_registry(name, server) @property def remote_registry(self): return RemoteRegistry(self.client_cache.registry, TestBufferConanOutput()) @property def paths(self): return self.client_cache @property def default_compiler_visual_studio(self): settings = self.client_cache.default_profile.settings return settings.get("compiler", None) == "Visual Studio" @property def out(self): return self.user_io.out @contextmanager def chdir(self, newdir): old_dir = self.current_folder if not os.path.isabs(newdir): newdir = os.path.join(old_dir, newdir) mkdir(newdir) self.current_folder = newdir try: yield finally: self.current_folder = old_dir def _init_collaborators(self, user_io=None): output = TestBufferConanOutput() self.user_io = user_io or MockedUserIO(self.users, out=output) self.client_cache = ClientCache(self.base_folder, self.storage_folder, output) self.runner = TestRunner(output, runner=self.conan_runner) # Check if servers are real real_servers = False for server in self.servers.values(): if isinstance(server, str): # Just URI real_servers = True with tools.environment_append(self.client_cache.conan_config.env_vars): if real_servers: requester = requests.Session() else: if self.requester_class: requester = self.requester_class(self.servers) else: requester = TestRequester(self.servers) self.requester = ConanRequester(requester, self.client_cache, get_request_timeout()) self.hook_manager = HookManager(self.client_cache.hooks_path, get_env("CONAN_HOOKS", list()), self.user_io.out) self.localdb, self.rest_api_client, self.remote_manager = Conan.instance_remote_manager( self.requester, self.client_cache, self.user_io, self.client_version, self.min_server_compatible_version, self.hook_manager) self.rest_api_client.block_v2 = self.block_v2 return output, self.requester def init_dynamic_vars(self, user_io=None): # Migration system self.client_cache = migrate_and_get_client_cache( self.base_folder, TestBufferConanOutput(), storage_folder=self.storage_folder) # Maybe something have changed with migrations return self._init_collaborators(user_io) def run(self, command_line, user_io=None, ignore_error=False, should_error=False): """ run a single command as in the command line. If user or password is filled, user_io will be mocked to return this tuple if required """ output, requester = self.init_dynamic_vars(user_io) with tools.environment_append(self.client_cache.conan_config.env_vars): # Settings preprocessor interactive = not get_env("CONAN_NON_INTERACTIVE", False) conan = Conan(self.client_cache, self.user_io, self.runner, self.remote_manager, self.hook_manager, interactive=interactive) outputer = CommandOutputer(self.user_io, self.client_cache) command = Command(conan, self.client_cache, self.user_io, outputer) args = shlex.split(command_line) current_dir = os.getcwd() os.chdir(self.current_folder) old_path = sys.path[:] sys.path.append(os.path.join(self.client_cache.conan_folder, "python")) old_modules = list(sys.modules.keys()) old_output, old_requester = set_global_instances(output, requester) try: error = command.run(args) finally: set_global_instances(old_output, old_requester) sys.path = old_path os.chdir(current_dir) # Reset sys.modules to its prev state. A .copy() DOES NOT WORK added_modules = set(sys.modules).difference(old_modules) for added in added_modules: sys.modules.pop(added, None) if not ignore_error and error and not should_error: exc_message = "\n{command_header}\n{command}\n{output_header}\n{output}\n{output_footer}\n".format( command_header='{:-^80}'.format(" Command failed: "), output_header='{:-^80}'.format(" Output: "), output_footer='-' * 80, command=command_line, output=self.user_io.out) raise Exception(exc_message) if should_error and not error: raise Exception("This command should have failed: %s" % command_line) self.all_output += str(self.user_io.out) return error def save(self, files, path=None, clean_first=False): """ helper metod, will store files in the current folder param files: dict{filename: filecontents} """ path = path or self.current_folder if clean_first: shutil.rmtree(self.current_folder, ignore_errors=True) save_files(path, files) if not files: mkdir(self.current_folder) def get_revision(self, conan_ref): return self.client_cache.load_metadata(conan_ref).recipe.revision def get_package_revision(self, package_ref): metadata = self.client_cache.load_metadata(package_ref.conan) return metadata.packages[package_ref.package_id].revision