def status(obj, long_format, plugins): """Print information about (successfully) installed plugins.""" host = obj["host"] plugins_local_dir = obj["plugins_local_dir"] local_versions = PluginInfos.make_from_local_store( plugins_local_dir).filter_to_latest() plugin_infos = PluginInfos.make_from_encapsia(host) if plugins: specs = PluginSpecs.make_from_spec_strings(plugins) plugin_infos = specs.filter(plugin_infos) headers = ["name*", "version**", "available**", "installed"] if long_format: headers.extend(["description", "plugin-tags"]) info = [] for pi in plugin_infos: pi_info = [ pi.name_and_variant(), pi.formatted_version(), _get_available_from_local_store(local_versions, pi), pi.extras["installed"], ] if long_format: pi_info.extend( [pi.extras["description"], pi.extras["plugin-tags"]]) info.append(pi_info) lib.log(tabulate(info, headers=headers)) _log_message_explaining_headers()
def add(obj, versions, latest_existing, plugins): """Add plugin(s) to local store from file, URL, or S3.""" plugins_local_dir = obj["plugins_local_dir"] plugins_s3_buckets = obj["plugins_s3_buckets"] plugins_force = obj["plugins_force"] host = obj["host"] specs_to_search_in_s3 = [] to_download_from_s3 = [] s3_versions = None # For performance, only fetch if/when first needed. added_from_file_or_uri = False for plugin in plugins: if Path(plugin).is_file(): _add_to_local_store_from_uri( plugins_local_dir, Path(plugin).resolve().as_uri(), plugins_force, ) added_from_file_or_uri = True elif urllib.parse.urlparse(plugin).scheme != "": _add_to_local_store_from_uri(plugins_local_dir, plugin, plugins_force) added_from_file_or_uri = True else: specs_to_search_in_s3.append(PluginSpec.make_from_string(plugin)) if versions: specs_to_search_in_s3.extend( PluginSpecs.make_from_version_dict( lib.read_toml(Path(versions).expanduser()))) if latest_existing: specs_to_search_in_s3.extend( PluginSpecs.make_from_plugininfos( PluginInfos.make_from_encapsia(host))) if specs_to_search_in_s3: s3_versions = PluginInfos.make_from_s3_buckets(plugins_s3_buckets) to_download_from_s3.extend(pi for spec in specs_to_search_in_s3 if ( pi := s3_versions.latest_version_matching_spec(spec)) is not None) if to_download_from_s3: for pi in to_download_from_s3: _add_to_local_store_from_s3(pi, plugins_local_dir, force=plugins_force) else: if not added_from_file_or_uri: lib.log("Nothing to do!")
def test_filter(self, plugininfo_list): pis = PluginInfos(plugininfo_list) expected = [ PluginInfo.make_from_name_variant_version(*nvv) for nvv in [ ("bar", "", "1.0.0"), ("bar", "trial", "1.0.0"), ("foo", "", "2.0.0"), ] ] assert sorted(PluginSpecs(["foo-2", "bar-ANY"]).filter(pis)) == expected
def test_make_from_version_dict(self, versions_file): versions = toml.load(versions_file) specs = PluginSpecs.make_from_version_dict(versions) specs_list = list(specs) assert len(specs_list) == 3 assert specs_list[0].name == "first" assert specs_list[0].variant == "" assert specs_list[0].version_prefix == "1.0.0" assert specs_list[0].exact_match is True assert specs_list[1].name == "second" assert specs_list[1].variant == "not_quite" assert specs_list[1].version_prefix == "2.0.0-1" assert specs_list[1].exact_match is True assert specs_list[2].name == "third" assert specs_list[2].variant == "" assert specs_list[2].version_prefix == "2.0.0" assert specs_list[2].exact_match is False
def upstream(obj, plugins, all_versions): """Print information about plugins on S3. By default, only includes latest versions. """ plugins_s3_buckets = obj["plugins_s3_buckets"] lib.log( f"Searching for plugins in S3 bucket(s): {', '.join(plugins_s3_buckets)}" ) plugin_infos = PluginInfos.make_from_s3_buckets(plugins_s3_buckets) if plugins: plugin_infos = PluginSpecs.make_from_spec_strings(plugins).filter( plugin_infos) if not all_versions: plugin_infos = plugin_infos.filter_to_latest() info = ([ r.name_and_variant(), r.formatted_version(), r.get_s3_bucket(), r.get_s3_path(), ] for r in sorted(plugin_infos)) lib.log(tabulate(info, headers=["name*", "version**", "bucket", "path"])) _log_message_explaining_headers()
def ls(obj, all_versions, long_format, plugins): """Print information about plugins in local store. By default, only includes latest versions. """ plugins_local_dir = obj["plugins_local_dir"] plugin_infos = PluginInfos.make_from_local_store(plugins_local_dir) if not all_versions: plugin_infos = plugin_infos.filter_to_latest() if plugins: plugin_infos = PluginSpecs.make_from_spec_strings(plugins).filter( plugin_infos) def _read_description(pi): filename = plugins_local_dir / pi.get_filename() try: with lib.temp_directory() as tmp_dir: lib.extract_targz(filename, tmp_dir) manifests = list(tmp_dir.glob("**/plugin.toml")) return lib.read_toml(manifests[0])["description"] except Exception: lib.log_error(f"Malformed? Unable to read: {filename}") return "N/A" if long_format: info = ([ pi.name_and_variant(), pi.formatted_version(), _read_description(pi) ] for pi in sorted(plugin_infos)) lib.log(tabulate(info, headers=["name*", "version**", "description"])) else: info = ([pi.name_and_variant(), pi.formatted_version()] for pi in sorted(plugin_infos)) lib.log(tabulate(info, headers=["name*", "version**"])) _log_message_explaining_headers()
def install(obj, versions, show_logs, latest_existing, plugins): """Install/upgrade plugins by name, from files, or from a versions.toml file. Plugins provided as files are put in the local store before being installed. When described by name alone, the latest plugin of that name in the local store will be used. Plugins specified in the versions.toml file will be taken from the local store. """ plugins_local_dir = obj["plugins_local_dir"] plugins_force = obj["plugins_force"] host = obj["host"] # Create a list of installation candidates. to_install_candidates = [] for plugin in plugins: plugin_filename = Path(plugin).resolve() if plugin_filename.is_file(): # If it looks like a file then just add it. _add_to_local_store_from_uri(plugins_local_dir, plugin_filename.as_uri(), force=True) to_install_candidates.append( PluginInfo.make_from_filename(plugin_filename)) else: # Else assume it is a spec for a plugin already in the local store. to_install_candidates.append(PluginSpec.make_from_string(plugin)) if versions: # Assume plugins already present in local store. to_install_candidates.extend( PluginSpecs.make_from_version_dict( lib.read_toml(Path(versions).expanduser()))) if latest_existing: to_install_candidates.extend( PluginSpec(pi.name, pi.variant) for pi in PluginInfos.make_from_encapsia(host)) # Work out and list installation plan. # to_install_candidates = sorted(PluginInfos(to_install_candidates)) installed = PluginInfos.make_from_encapsia(host) local_store = PluginInfos.make_from_local_store(plugins_local_dir) plan = _create_install_plan(to_install_candidates, installed, local_store, force_install=plugins_force) to_install = [i[0] for i in plan if i[4] != "skip"] headers = ["name*", "existing version**", "new version**", "action"] lib.log(tabulate([i[1:] for i in plan], headers=headers)) _log_message_explaining_headers() # Seek confirmation unless force. if to_install and not plugins_force: click.confirm( "Do you wish to proceed with the above plan?", abort=True, ) # Install them. lib.log("") if to_install: api = lib.get_api(**obj) for pi in to_install: success = _install_plugin(api, plugins_local_dir / pi.get_filename(), print_output=show_logs) if not success: lib.log_error("Some plugins failed to install.", abort=True) else: lib.log("Nothing to do!")
def freeze(obj): """Print currently installed plugins as versions TOML.""" versions = PluginSpecs.make_from_plugininfos( PluginInfos.make_from_encapsia(obj["host"])).as_version_dict() lib.log_output(toml.dumps(versions))
def test_as_version_dict(self, versions_file): versions = toml.load(versions_file) specs = PluginSpecs.make_from_version_dict(versions) assert specs.as_version_dict() == versions