def bib_script(): from cobaya.mpi import is_main_process if not is_main_process(): return warn_deprecation() # Parse arguments and launch import argparse parser = argparse.ArgumentParser( prog="cobaya bib", description= "Prints bibliography to be cited for a component or input file.") parser.add_argument( "components_or_files", action="store", nargs="+", metavar="component_name or input_file.yaml", help="Component(s) or input file(s) whose bib info is requested.") kind_opt, kind_opt_ishort = "kind", 0 parser.add_argument( "-" + kind_opt[kind_opt_ishort], "--" + kind_opt, action="store", nargs=1, default=None, metavar="component_kind", help=("If component name given, " "kind of component whose bib is requested: " + ", ".join(['%s' % kind for kind in kinds]) + ". " + "Use only when component name is not unique (it would fail).")) arguments = parser.parse_args() # Case of files are_yaml = [(os.path.splitext(f)[1] in _yaml_extensions) for f in arguments.components_or_files] if all(are_yaml): infos = [load_input(f) for f in arguments.components_or_files] print(prettyprint_bib(*get_bib_info(*infos))) elif not any(are_yaml): if arguments.kind: arguments.kind = arguments.kind[0].lower() for component in arguments.components_or_files: try: print( create_banner(component, symbol=_default_symbol, length=_default_length)) print(get_bib_component(component, arguments.kind)) return except: if not arguments.kind: print( "Specify its kind with '--%s [component_kind]'." % kind_opt + "(NB: all requested components must have the same kind, " "or be requested separately).") print("") else: print("Give either a list of input yaml files, " "or of component names (not a mix of them).") return 1 return
def citation_script(): warn_deprecation() print( create_banner( "\nThis command will be deprecated soon. Use `cobaya-bib` instead.\n" )) bib_script()
def prettyprint_bib(blocks_text): txt = "" for block, text in blocks_text.items(): if not txt.endswith("\n\n"): txt += "\n" txt += create_banner(block, symbol=_default_symbol, length=_default_length) txt += "\n" + text return txt.lstrip().rstrip() + "\n"
def prettyprint_bib(descs, bibs): # Sort them "optimally" sorted_kinds = [k for k in dump_sort_cosmetic if k in descs] sorted_kinds += [k for k in descs if k not in dump_sort_cosmetic] txt = "" txt += create_banner( "Descriptions", symbol=_default_symbol, length=_default_length) + "\n" for kind in sorted_kinds: txt += kind + ":\n\n" for component, desc in descs[kind].items(): txt += " * [%s] %s\n" % (component, desc) txt += "\n" txt += "\n" + create_banner( "Bibtex", symbol=_default_symbol, length=_default_length) + "\n" for kind in sorted_kinds: for component, bib in bibs[kind].items(): txt += "\n### %s " % component + "########################" + "\n\n" txt += bib return txt.lstrip().rstrip() + "\n"
def pretty_repr_bib(descs, bibs): """ Generates a pretty-print multi-line string from component descriptions and bibliographical sources. """ # Sort them "optimally" sorted_kinds = [k for k in dump_sort_cosmetic if k in descs] sorted_kinds += [k for k in descs if k not in dump_sort_cosmetic] txt = "" txt += create_banner( "Descriptions", symbol=_default_symbol, length=_default_length) + "\n" for kind in sorted_kinds: txt += kind + ":\n\n" for component, desc in descs[kind].items(): txt += " * [%s] %s\n" % (component, desc) txt += "\n" txt += "\n" + create_banner( "Bibtex", symbol=_default_symbol, length=_default_length) + "\n" for kind in sorted_kinds: for component, bib in bibs[kind].items(): txt += "\n### %s " % component + "########################" + "\n\n" txt += bib return txt.lstrip().rstrip() + "\n"
def __getattr__(self, method): try: object.__getattr__(self, method) except AttributeError: if method.startswith("get"): # Deprecated method names # -- this will be deprecated in favour of the error below new_names = {"get_cl": "get_Cl"} if method in new_names: msg = create_banner( "Method '%s' has been re-capitalized to '%s'.\n" "Overriding for now, but please change it: " "this will produce an error in the future." % (method, new_names[method])) for line in msg.split("\n"): self.log.warning(line) return getattr(self, new_names[method]) # End of deprecation block ------------------------------ raise LoggedError( self.log, "Getter method for cosmology product %r is not known. " "Maybe you meant any of %r?", method, fuzzy_match(method, dir(self), n=3))
# Global import os import sys import numpy as np import logging # Local from cobaya.likelihood import Likelihood from cobaya.log import LoggedError from cobaya.conventions import _packages_path, kinds from cobaya.input import get_default_info from cobaya.install import pip_install, download_file from cobaya.tools import are_different_params_lists, create_banner _deprecation_msg_2015 = create_banner(""" The likelihoods from the Planck 2015 data release have been superseded by the 2018 ones, and will eventually be deprecated. """) pla_url_prefix = r"https://pla.esac.esa.int/pla-sl/data-action?COSMOLOGY.COSMOLOGY_OID=" last_version_supp_data_and_covmats = "v2.01" class _planck_clik_prototype(Likelihood): # Data type for aggregated chi2 (case sensitive) type = "CMB" path: str def initialize(self): if "2015" in self.get_name():
def install(*infos, **kwargs): if not log.root.handlers: logger_setup() path = kwargs.get("path") if not path: path = resolve_packages_path(infos) if not path: raise LoggedError( log, "No 'path' argument given, and none could be found in input infos " "(as %r), the %r env variable or the config file. " "Maybe specify one via a command line argument '-%s [...]'?", _packages_path, _packages_path_env, _packages_path_arg[0]) abspath = os.path.abspath(path) log.info("Installing external packages at '%s'", abspath) kwargs_install = { "force": kwargs.get("force", False), "no_progress_bars": kwargs.get("no_progress_bars") } for what in (_code, _data): kwargs_install[what] = kwargs.get(what, True) spath = os.path.join(abspath, what) if kwargs_install[what] and not os.path.exists(spath): try: os.makedirs(spath) except OSError: raise LoggedError( log, "Could not create the desired installation folder '%s'", spath) failed_components = [] skip_keywords = set(kwargs.get("skip", []) or []) skip_keywords_env = set( os.environ.get(_install_skip_env, "").replace(",", " ").lower().split()) skip_keywords = skip_keywords.union(skip_keywords_env) for kind, components in get_used_components(*infos).items(): for component in components: print() print(create_banner(kind + ":" + component, symbol="=", length=80)) print() if _skip_helper(component.lower(), skip_keywords, skip_keywords_env, log): continue info = (next( info for info in infos if component in info.get(kind, {}))[kind][component]) or {} if isinstance(info, str) or _external in info: log.warning( "Component '%s' is a custom function. " "Nothing to do.", component) continue try: imported_class = get_class(component, kind, component_path=info.pop( _component_path, None)) except ImportError as e: log.error("Component '%s' not recognized. [%s]." % (component, e)) failed_components += ["%s:%s" % (kind, component)] continue else: if _skip_helper(imported_class.__name__.lower(), skip_keywords, skip_keywords_env, log): continue is_installed = getattr(imported_class, "is_installed", None) if is_installed is None: log.info("%s.%s is a fully built-in component: nothing to do.", kind, imported_class.__name__) continue if is_installed(path=abspath, **kwargs_install): log.info("External component already installed.") if kwargs.get("just_check", False): continue if kwargs_install["force"]: log.info("Forcing re-installation, as requested.") else: log.info("Doing nothing.") continue else: if kwargs.get("just_check", False): log.info("NOT INSTALLED!") continue try: install_this = getattr(imported_class, "install", None) success = install_this(path=abspath, **kwargs_install) except KeyboardInterrupt: raise except: traceback.print_exception(*sys.exc_info(), file=sys.stdout) log.error( "An unknown error occurred. Delete the external packages " "folder %r and try again. " "Please, notify the developers if this error persists.", abspath) success = False if success: log.info("Successfully installed!") else: log.error( "Installation failed! Look at the error messages above. " "Solve them and try again, or, if you are unable to solve, " "install the packages required by this component manually." ) failed_components += ["%s:%s" % (kind, component)] continue # test installation if not is_installed(path=abspath, **kwargs_install): log.error( "Installation apparently worked, " "but the subsequent installation test failed! " "Look at the error messages above. " "Solve them and try again, or, if you are unable to solve, " "install the packages required by this component manually." ) failed_components += ["%s:%s" % (kind, component)] if failed_components: bullet = "\n - " raise LoggedError( log, "The installation (or installation test) of some component(s) has " "failed: %s\nCheck output of the installer of each component above " "for precise error info.\n", bullet + bullet.join(failed_components)) # Set the installation path in the global config file if not kwargs.get("no_set_global", False) and not kwargs.get( "just_check", False): write_packages_path_in_config_file(abspath) log.info( "The installation path has been written in the global config file." )
def install(*infos, **kwargs): debug = kwargs.get(_debug) if not log.root.handlers: logger_setup() path = kwargs.get("path") if not path: path = resolve_packages_path(infos) if not path: raise LoggedError( log, "No 'path' argument given, and none could be found in input infos " "(as %r), the %r env variable or the config file. " "Maybe specify one via a command line argument '-%s [...]'?", _packages_path, _packages_path_env, _packages_path_arg[0]) abspath = os.path.abspath(path) log.info("Installing external packages at '%s'", abspath) kwargs_install = {"force": kwargs.get("force", False), "no_progress_bars": kwargs.get("no_progress_bars")} for what in (_code, _data): kwargs_install[what] = kwargs.get(what, True) spath = os.path.join(abspath, what) if kwargs_install[what] and not os.path.exists(spath): try: os.makedirs(spath) except OSError: raise LoggedError( log, "Could not create the desired installation folder '%s'", spath) failed_components = [] skip_keywords_arg = set(kwargs.get("skip", []) or []) # NB: if passed with quotes as `--skip "a b"`, it's interpreted as a single key skip_keywords_arg = set(chain(*[word.split() for word in skip_keywords_arg])) skip_keywords_env = set( os.environ.get(_install_skip_env, "").replace(",", " ").lower().split()) skip_keywords = skip_keywords_arg.union(skip_keywords_env) for kind, components in get_used_components(*infos).items(): for component in components: print() print(create_banner(kind + ":" + component, symbol=_banner_symbol, length=_banner_length), end="") print() if _skip_helper(component.lower(), skip_keywords, skip_keywords_env, log): continue info = (next(info for info in infos if component in info.get(kind, {}))[kind][component]) or {} if isinstance(info, str) or _external in info: log.warning("Component '%s' is a custom function. " "Nothing to do.", component) continue try: imported_class = get_class(component, kind, component_path=info.pop(_component_path, None)) except ImportError as excpt: log.error("Component '%s' not recognized. [%s].", component, excpt) failed_components += ["%s:%s" % (kind, component)] continue else: if _skip_helper(imported_class.__name__.lower(), skip_keywords, skip_keywords_env, log): continue is_compatible = getattr(imported_class, "is_compatible", lambda: True)() if not is_compatible: log.info( "Skipping %r because it is not compatible with your OS.", component) continue log.info("Checking if dependencies have already been installed...") is_installed = getattr(imported_class, "is_installed", None) if is_installed is None: log.info("%s.%s is a fully built-in component: nothing to do.", kind, imported_class.__name__) continue install_path = abspath get_path = getattr(imported_class, "get_path", None) if get_path: install_path = get_path(install_path) has_been_installed = False if not debug: logging.disable(logging.ERROR) if kwargs.get("skip_global"): has_been_installed = is_installed(path="global", **kwargs_install) if not has_been_installed: has_been_installed = is_installed(path=install_path, **kwargs_install) if not debug: logging.disable(logging.NOTSET) if has_been_installed: log.info("External dependencies for this component already installed.") if kwargs.get(_test_run, False): continue if kwargs_install["force"] and not kwargs.get("skip_global"): log.info("Forcing re-installation, as requested.") else: log.info("Doing nothing.") continue else: log.info("Installation check failed!") if not debug: log.info( "(If you expected this to be already installed, re-run " "`cobaya-install` with --debug to get more verbose output.)") if kwargs.get(_test_run, False): continue log.info("Installing...") try: install_this = getattr(imported_class, "install", None) success = install_this(path=abspath, **kwargs_install) except KeyboardInterrupt: raise except: traceback.print_exception(*sys.exc_info(), file=sys.stdout) log.error("An unknown error occurred. Delete the external packages " "folder %r and try again. " "Please, notify the developers if this error persists.", abspath) success = False if success: log.info("Successfully installed! Let's check it...") else: log.error("Installation failed! Look at the error messages above. " "Solve them and try again, or, if you are unable to solve, " "install the packages required by this component manually.") failed_components += ["%s:%s" % (kind, component)] continue # test installation if not debug: logging.disable(logging.ERROR) successfully_installed = is_installed(path=install_path, **kwargs_install) if not debug: logging.disable(logging.NOTSET) if not successfully_installed: log.error("Installation apparently worked, " "but the subsequent installation test failed! " "Look at the error messages above, or re-run with --debug " "for more more verbose output. " "Try to solve the issues and try again, or, if you are unable " "to solve them, install the packages required by this " "component manually.") failed_components += ["%s:%s" % (kind, component)] else: log.info("Installation check successful.") print() print(create_banner(" * Summary * ", symbol=_banner_symbol, length=_banner_length), end="") print() if failed_components: bullet = "\n - " raise LoggedError( log, "The installation (or installation test) of some component(s) has " "failed: %s\nCheck output of the installer of each component above " "for precise error info.\n", bullet + bullet.join(failed_components)) log.info("All requested components' dependencies correctly installed.") # Set the installation path in the global config file if not kwargs.get("no_set_global", False) and not kwargs.get(_test_run, False): write_packages_path_in_config_file(abspath) log.info("The installation path has been written into the global config file: %s", os.path.join(get_config_path(), _packages_path_config_file))
def install(*infos, **kwargs): if not log.root.handlers: logger_setup() path = kwargs.get("path", ".") if not path: # See if we can get one (and only one) from infos paths = set( [p for p in [info.get(_path_install) for info in infos] if p]) if len(paths) == 1: path = paths[0] else: print("logging?") raise LoggedError( log, "No 'path' argument given and could not extract one (and only one) " "from the infos.") abspath = os.path.abspath(path) log.info("Installing modules at '%s'\n", abspath) kwargs_install = { "force": kwargs.get("force", False), "no_progress_bars": kwargs.get("no_progress_bars") } for what in (_code, _data): kwargs_install[what] = kwargs.get(what, True) spath = os.path.join(abspath, what) if kwargs_install[what] and not os.path.exists(spath): try: os.makedirs(spath) except OSError: raise LoggedError( log, "Could not create the desired installation folder '%s'", spath) failed_modules = [] skip_list = os.environ.get("COBAYA_TEST_SKIP", "").replace(",", " ").lower().split() for kind, modules in get_used_modules(*infos).items(): for module in modules: print(create_banner(kind + ":" + module, symbol="=", length=80)) if len([s for s in skip_list if s in module.lower()]): log.info("Skipping %s for test skip list %s" % (module, skip_list)) continue module_folder = get_class_module(module, kind) try: imported_module = import_module(module_folder, package=_package) imported_class = get_class(module, kind) if len([ s for s in skip_list if s in imported_class.__name__.lower() ]): log.info("Skipping %s for test skip list %s" % (imported_class.__name__, skip_list)) continue except ImportError as e: if kind == _likelihood: info = (next(info for info in infos if module in info.get( _likelihood, {}))[_likelihood][module]) or {} if isinstance(info, string_types) or _external in info: log.warning( "Module '%s' is a custom likelihood. " "Nothing to do.\n", module) else: log.error("Module '%s' not recognized. [%s]\n" % (module, e)) failed_modules += ["%s:%s" % (kind, module)] continue is_installed = getattr( imported_class, "is_installed", getattr(imported_module, "is_installed", None)) if is_installed is None: log.info("Built-in module: nothing to do.\n") continue if is_installed(path=abspath, **kwargs_install): log.info("External module already installed.\n") if kwargs.get("just_check", False): continue if kwargs_install["force"]: log.info("Forcing re-installation, as requested.") else: log.info("Doing nothing.\n") continue else: if kwargs.get("just_check", False): log.info("NOT INSTALLED!\n") continue try: install_this = getattr( imported_class, "install", getattr(imported_module, "install", None)) success = install_this(path=abspath, **kwargs_install) except: traceback.print_exception(*sys.exc_info(), file=sys.stdout) log.error( "An unknown error occurred. Delete the modules folder and try " "again. Notify the developers if this error persists.") success = False if success: log.info("Successfully installed!\n") else: log.error( "Installation failed! Look at the error messages above. " "Solve them and try again, or, if you are unable to solve, " "install this module manually.") failed_modules += ["%s:%s" % (kind, module)] continue # test installation if not is_installed(path=abspath, **kwargs_install): log.error( "Installation apparently worked, " "but the subsequent installation test failed! " "Look at the error messages above. " "Solve them and try again, or, if you are unable to solve, " "install this module manually.") failed_modules += ["%s:%s" % (kind, module)] if failed_modules: bullet = "\n - " raise LoggedError( log, "The installation (or installation test) of some module(s) has failed: " "%s\nCheck output of the installer of each module above " "for precise error info.\n", bullet + bullet.join(failed_modules))
def install(*infos, **kwargs): """ Installs the external packages required by the components mentioned in ``infos``. ``infos`` can be input dictionaries or single component names. :param force: force re-installation of apparently installed packages (default: ``False``). :param test: just check whether components are installed (default: ``False``). :param upgrade: force upgrade of obsolete components (default: ``False``). :param skip: keywords of components that will be skipped during installation. :param skip_global: skip installation of already-available Python modules (default: ``False``). :param debug: produce verbose debug output (default: ``False``). :param code: set to ``False`` to skip code packages (default: ``True``). :param data: set to ``False`` to skip data packages (default: ``True``). :param no_progress_bars: no progress bars shown; use when output is saved into a text file (e.g. when running on a cluster) (default: ``False``). :param no_set_global: do not store the installation path for later runs (default: ``False``). """ debug = kwargs.get("debug", False) logger = kwargs.get("logger") if not logger: logger_setup(debug=debug) logger = get_logger("install") path = kwargs.get("path") infos_not_single_names = [ info for info in infos if isinstance(info, Mapping) ] if not path: path = resolve_packages_path(*infos_not_single_names) if not path: raise LoggedError(logger, ( "No 'path' argument given, and none could be found in input infos " "(as %r), the %r env variable or the config file. " "Maybe specify one via a command line argument '-%s [...]'?"), packages_path_input, packages_path_env, packages_path_arg[0]) # General install path for all dependencies general_abspath = os.path.abspath(path) logger.info("Installing external packages at '%s'", general_abspath) # Set the installation path in the global config file if not kwargs.get("no_set_global", False) and not kwargs.get( "test", False): write_packages_path_in_config_file(general_abspath) logger.info( "The installation path has been written into the global config file: %s", os.path.join(get_config_path(), packages_path_config_file)) kwargs_install = { "force": kwargs.get("force", False), "no_progress_bars": kwargs.get("no_progress_bars") } for what in (code_path, data_path): kwargs_install[what] = kwargs.get(what, True) spath = os.path.join(general_abspath, what) if kwargs_install[what] and not os.path.exists(spath): try: os.makedirs(spath) except OSError: raise LoggedError( logger, f"Could not create the desired installation folder '{spath}'" ) # To check e.g. for a version upgrade, it needs to reload the component class and # all relevant imported modules: the implementation of `is_installed` for each # class is expected to always reload external modules if passed `reload=True` # (should be False by default to avoid deleting objects unnecessarily). kwargs_is_installed = {"reload": True} unknown_components = [] # could not be identified failed_components = [] # general errors obsolete_components = [] # older or unknown version already installed skip_keywords_arg = set(kwargs.get("skip", []) or []) # NB: if passed with quotes as `--skip "a b"`, it's interpreted as a single key skip_keywords_arg = set( chain(*[word.split() for word in skip_keywords_arg])) skip_keywords_env = set( os.environ.get(install_skip_env, "").replace(",", " ").lower().split()) skip_keywords = skip_keywords_arg.union(skip_keywords_env) # Combine all requested components and install them # NB: components mentioned by name may be repeated with those given in dict infos. # That's OK, because the install check will skip them in the 2nd pass used_components, components_infos = get_used_components(*infos, return_infos=True) for kind, components in used_components.items(): for component in components: name_w_kind = (kind + ":" if kind else "") + component print() print(create_banner(name_w_kind, symbol=_banner_symbol, length=_banner_length), end="") print() if _skip_helper(component.lower(), skip_keywords, skip_keywords_env, logger): continue info = components_infos[component] if isinstance(info, str) or "external" in info: logger.info( f"Component '{name_w_kind}' is a custom function. Nothing to do." ) continue try: class_name = (info or {}).get("class") if class_name: logger.info( f"Class to be installed for this component: {class_name}" ) imported_class = get_component_class(component, kind=kind, component_path=info.pop( "python_path", None), class_name=class_name, logger=logger) # Update the name if the kind was unknown if not kind: name_w_kind = imported_class.get_kind() + ":" + component except ComponentNotFoundError: logger.error( f"Component '{name_w_kind}' could not be identified. Skipping." ) unknown_components += [name_w_kind] continue except Exception: traceback.print_exception(*sys.exc_info(), file=sys.stdout) logger.error( f"An error occurred when loading '{name_w_kind}'. Skipping." ) failed_components += [name_w_kind] continue else: if _skip_helper(imported_class.__name__.lower(), skip_keywords, skip_keywords_env, logger): continue is_compatible = getattr(imported_class, "is_compatible", lambda: True)() if not is_compatible: logger.error(f"Skipping '{name_w_kind}' " "because it is not compatible with your OS.") failed_components += [name_w_kind] continue logger.info( "Checking if dependencies have already been installed...") is_installed = getattr(imported_class, "is_installed", None) if is_installed is None: logger.info( f"Component '{name_w_kind}' is a fully built-in component: " "nothing to do.") continue this_component_install_path = general_abspath get_path = getattr(imported_class, "get_path", None) if get_path: this_component_install_path = get_path( this_component_install_path) # Check previous installations and their versions has_been_installed = False is_old_version_msg = None with NoLogging(None if debug else logging.ERROR): try: if kwargs.get("skip_global"): has_been_installed = is_installed( path="global", **kwargs_install, **kwargs_is_installed) if not has_been_installed: has_been_installed = is_installed( path=this_component_install_path, **kwargs_install, **kwargs_is_installed) except VersionCheckError as excpt: is_old_version_msg = str(excpt) if has_been_installed: # no VersionCheckError was raised logger.info( "External dependencies for this component already installed." ) if kwargs.get("test", False): continue if kwargs_install["force"] and not kwargs.get("skip_global"): logger.info("Forcing re-installation, as requested.") else: logger.info("Doing nothing.") continue elif is_old_version_msg: logger.info(f"Version check failed: {is_old_version_msg}") obsolete_components += [name_w_kind] if kwargs.get("test", False): continue if not kwargs.get("upgrade", False) and not kwargs.get( "force", False): logger.info("Skipping because '--upgrade' not requested.") continue else: logger.info("Check found no existing installation") if not debug: logger.info( "(If you expected this to be already installed, re-run " "`cobaya-install` with --debug to get more verbose output.)" ) if kwargs.get("test", False): # We are only testing whether it was installed, so consider it failed failed_components += [name_w_kind] continue # Do the install logger.info("Installing...") try: install_this = getattr(imported_class, "install", None) success = install_this(path=general_abspath, **kwargs_install) except Exception: traceback.print_exception(*sys.exc_info(), file=sys.stdout) logger.error( "An unknown error occurred. Delete the external packages " "folder %r and try again. " "Please, notify the developers if this error persists.", general_abspath) success = False if success: logger.info("Successfully installed! Let's check it...") else: logger.error( "Installation failed! Look at the error messages above. " "Solve them and try again, or, if you are unable to solve them, " "install the packages required by this component manually." ) failed_components += [name_w_kind] continue # Test installation reloaded_class = get_component_class(component, kind=kind, component_path=info.pop( "python_path", None), class_name=class_name, logger=logger) reloaded_is_installed = getattr(reloaded_class, "is_installed", None) with NoLogging(None if debug else logging.ERROR): try: successfully_installed = reloaded_is_installed( path=this_component_install_path, **kwargs_install, **kwargs_is_installed) except Exception: traceback.print_exception(*sys.exc_info(), file=sys.stdout) successfully_installed = False if not successfully_installed: logger.error( "Installation apparently worked, " "but the subsequent installation test failed! " "This does not always mean that there was an actual error, " "and is sometimes fixed simply by running the installer " "again. If not, look closely at the error messages above, " "or re-run with --debug for more more verbose output. " "If you are unable to fix the issues above, " "try installing the packages required by this " "component manually.") failed_components += [name_w_kind] else: logger.info("Installation check successful.") print() print(create_banner(" * Summary * ", symbol=_banner_symbol, length=_banner_length), end="") print() bullet = "\n - " if unknown_components: suggestions_dict = { name: similar_internal_class_names(name) for name in unknown_components } suggestions_msg = \ bullet + bullet.join( f"{name}: did you mean any of the following? {sugg} " "(mind capitalization!)" for name, sugg in suggestions_dict.items()) raise LoggedError(logger, ( "The following components could not be identified and were skipped:" f"{suggestions_msg}")) if failed_components: raise LoggedError(logger, ( "The installation (or installation test) of some component(s) has " "failed: %s\nCheck output of the installer of each component above " "for precise error info.\n"), bullet + bullet.join(failed_components)) if obsolete_components: raise LoggedError(logger, ( "The following packages are obsolete. Re-run with `--upgrade` option" " (not upgrading by default to preserve possible user changes): %s" ), bullet + bullet.join(obsolete_components)) if not unknown_components and not failed_components and not obsolete_components: logger.info( "All requested components' dependencies correctly installed at " f"{general_abspath}")