diff --git a/docs/reference_guides/commands/get_extensions.rst b/docs/reference_guides/commands/get_extensions.rst index 0b63a3a7c5..bc3a179707 100644 --- a/docs/reference_guides/commands/get_extensions.rst +++ b/docs/reference_guides/commands/get_extensions.rst @@ -84,6 +84,12 @@ options Just show list of binary extras +.. option:: --info + + Show information about available binary builds. Lists all platforms + and architectures and shows which (if any) matches the current system. + If given, all other options are ignored. + .. option:: --extra Add an extra binary package to the things to install. You can specify the diff --git a/idaes/commands/extensions.py b/idaes/commands/extensions.py index 841a1063c4..24ffcb5001 100644 --- a/idaes/commands/extensions.py +++ b/idaes/commands/extensions.py @@ -19,22 +19,35 @@ __author__ = "John Eslick" +from collections import defaultdict import os import logging +from platform import machine import click import idaes +from idaes.config import base_platforms, binary_distro_map, binary_arch_map +from idaes.config import canonical_arch, canonical_distro import idaes.commands.util.download_bin from idaes.commands import cb _log = logging.getLogger("idaes.commands.extensions") +def print_header(title: str, echo=click.echo, width=65): + echo("-" * width) + echo(f"IDAES Extensions {title}") + echo("=" * width) + + +def print_footer(echo=click.echo, width=65): + echo("") + echo("=" * width) + + def print_extensions_version(library_only=False, bin_directory=None): - click.echo("---------------------------------------------------") - click.echo("IDAES Extensions Build Versions") - click.echo("===================================================") + print_header("Build Versions") if bin_directory is None: bin_directory = idaes.bin_directory if not library_only: @@ -52,14 +65,12 @@ def print_extensions_version(library_only=False, bin_directory=None): except FileNotFoundError: v = "no version file found" click.echo("Library: v{}".format(v)) - click.echo("===================================================") + print_footer() return 0 def print_license(): - click.echo("---------------------------------------------------") - click.echo("IDAES Extensions License Information") - click.echo("===================================================") + print_header("License Information") fpath = os.path.join(idaes.bin_directory, "license.txt") try: with open(fpath, "r") as f: @@ -68,10 +79,53 @@ def print_license(): except FileNotFoundError: click.echo("no license file found") click.echo("") - click.echo("===================================================") + print_footer() return 0 +def print_build_info(): + fd, _ = idaes.commands.util.download_bin._get_file_downloader(False, None) + + print_header("Build Information") + + print("\nAll Builds (Platform-Architecture):") + for build in base_platforms: + print(f" {build}") + + for name, data in zip( + ("Platform", "Architecture"), + (binary_distro_map, binary_arch_map), + ): + print(f"\n{name} aliases:") + rmap = defaultdict(list) + _ = {rmap[v].append(k) for k, v in data.items()} + w = max((len(name) for name in rmap)) + name_fmt = f"{{name:>{w}s}}" + for name in sorted(rmap.keys()): + aliases = ", ".join(sorted(rmap[name])) + fname = name_fmt.format(name=name) + print(f" {fname}: {aliases}") + + print("\nCurrent system information:") + _, platform = idaes.commands.util.download_bin._get_arch_and_platform(fd, "auto") + arch = machine() + to_platform = canonical_distro(platform) + to_mach = canonical_arch(arch) + to_build = f"{to_platform}-{to_mach}" + has_build = to_build in base_platforms + + alias = "" if to_platform == platform else f" -> {to_platform}" + print(f" Platform: {platform}{alias}") + alias = "" if to_mach == arch else f" -> {to_mach}" + print(f" Architecture: {arch}{alias}") + if has_build: + print(f" Use build: {to_build}") + else: + print(" !! Unsupported platform/architecture combination") + + print_footer() + + @cb.command(name="get-extensions", help="Get solvers and libraries") @click.option( "--release", @@ -101,6 +155,7 @@ def print_license(): is_flag=True, help="Don't download anything, but report what would be done", ) +@click.option("--info", is_flag=True, help="List all builds") @click.option("--extra", multiple=True, help="Install extras") @click.option("--extras-only", is_flag=True, help="Only install extras") @click.option("--to", default=None, help="Put extensions in a alternate location") @@ -115,10 +170,16 @@ def get_extensions( nochecksum, library_only, no_download, + info, extras_only, extra, to, ): + """Main sub-command.""" + cmd_name = "idaes get-extensions" + if info: + print_build_info() + return if url is None and release is None: # the default release is only used if neither a release or url is given release = idaes.config.default_binary_release @@ -146,7 +207,10 @@ def get_extensions( click.echo("") click.echo(e) click.echo("") - click.echo("Specify an os with --distro :") + click.echo( + f"Use the command '{cmd_name} --distro ' to specify an OS distribution\n" + f"Use the command '{cmd_name} --info' to see supported platforms" + ) return if no_download: for k, i in d.items(): @@ -203,7 +267,10 @@ def bin_platform(distro): ) click.echo(idaes.commands.util.download_bin._get_release_platform(platform)) except idaes.commands.util.download_bin.UnsupportedPlatformError: - click.echo(f"No supported binaries found for {platform}.") + click.echo( + f"No supported binaries found for {platform}. " + f"Use the command 'idaes get-extensions --info' to see supported platforms" + ) @cb.command(name="extensions-license", help="show license info for binary extensions") diff --git a/idaes/commands/tests/test_commands.py b/idaes/commands/tests/test_commands.py index e6190db08a..c0c4c019fa 100644 --- a/idaes/commands/tests/test_commands.py +++ b/idaes/commands/tests/test_commands.py @@ -19,6 +19,7 @@ import logging import os from pathlib import Path +import re from shutil import rmtree import subprocess import sys @@ -126,9 +127,12 @@ def test_get_extensions_plat(runner): @pytest.mark.integration def test_get_extensions_bad_plat(runner): - result = runner.invoke(extensions.bin_platform, ["--distro", "johns_good_linux42"]) + platform_name = "johns_good_linux42" + result = runner.invoke(extensions.bin_platform, ["--distro", platform_name]) assert result.exit_code == 0 - assert result.output == "No supported binaries found for johns_good_linux42.\n" + for expr in (r"[Nn]o.*found.*" + platform_name, r"command.*--info"): + m = re.search(expr, result.output) + assert m, f"Could not find in bad platform output: '{expr}'" @pytest.mark.integration @@ -137,6 +141,12 @@ def test_extensions_license(runner): assert result.exit_code == 0 +@pytest.mark.integration +def test_extensions_info(runner): + result = runner.invoke(extensions.get_extensions, ["--info"]) + assert result.exit_code == 0 + + ########### # config # ###########