Skip to content

Commit 0e6449d

Browse files
committed
The list-tools command implemented.
1 parent e5833bc commit 0e6449d

14 files changed

+457
-30
lines changed

dem/cli/command/list_cmd.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -82,31 +82,31 @@ def list_all_cat_dev_envs(platform: Platform) -> None:
8282
for catalog in platform.dev_env_catalogs.catalogs:
8383
list_actual_cat_dev_envs(catalog)
8484

85-
def list_selected_cat_dev_envs(platform: Platform, cat: List[str]) -> None:
85+
def list_selected_cat_dev_envs(platform: Platform, selected_cats: List[str]) -> None:
8686
""" List the Development Environments from the specified catalogs.
8787
8888
Args:
8989
platform -- the Platform
90-
cat -- the specified catalogs
90+
selected_cats -- the specified catalogs
9191
"""
92-
for cat_name in cat:
92+
for cat_name in selected_cats:
9393
for catalog in platform.dev_env_catalogs.catalogs:
9494
if catalog.name == cat_name:
9595
list_actual_cat_dev_envs(catalog)
9696
break
9797
else:
9898
stderr.print(f"[red]Error: Catalog '{cat_name}' not found![/]")
9999

100-
def execute(platform: Platform, cat: bool, specified_cats: list[str]) -> None:
100+
def execute(platform: Platform, cat: bool, selected_cats: list[str]) -> None:
101101
""" List Development Environments
102102
103103
Args:
104104
cat -- if true list all Development Environments in the catalogs
105-
specified_cats -- list the Development Environments from the specified catalogs
105+
selected_cats -- list the Development Environments from the specified catalogs
106106
"""
107-
if cat and not specified_cats:
107+
if cat and not selected_cats:
108108
list_all_cat_dev_envs(platform)
109-
elif specified_cats:
110-
list_selected_cat_dev_envs(platform, specified_cats)
109+
elif selected_cats:
110+
list_selected_cat_dev_envs(platform, selected_cats)
111111
else:
112112
list_local_dev_envs(platform)

dem/cli/command/list_tools_cmd.py

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
"""list-tools command implementation."""
2+
# dem/cli/command/list_tools_cmd.py
3+
4+
from dem.core.platform import Platform
5+
from dem.core.tool_images import ToolImage
6+
from dem.cli.console import stdout, stderr
7+
from rich.table import Table
8+
import typer
9+
10+
def list_local_tools(platform: Platform) -> None:
11+
""" List the local tools.
12+
13+
Args:
14+
platform -- the Platform
15+
16+
Exceptions:
17+
typer.Abort -- if no local tool images are available
18+
"""
19+
# by settings this to True, the update method won't try to update the registry tools
20+
platform.local_only = True
21+
22+
if not platform.tool_images.all_tool_images:
23+
stdout.print("[yellow]No local tool images are available.[/]")
24+
raise typer.Abort()
25+
26+
stdout.print(f"\n [italic]Local Tool Images[/]")
27+
# sorted will return a list of tuples, so we can iterate over the items
28+
for tool_image in sorted(platform.tool_images.all_tool_images.items()):
29+
# tool_image[0] is the name of the tool image and tool_image[1] is the ToolImage instance
30+
stdout.print(f" {tool_image[0]}")
31+
32+
def update_tools_from_selected_regs(platform: Platform, specified_regs: list[str]) -> None:
33+
""" Update the tools from the selected registries only.
34+
35+
Args:
36+
platform -- the Platform
37+
specified_regs -- the selected registry names
38+
39+
Exceptions:
40+
typer.Abort -- if an unknown registry is specified
41+
"""
42+
# by settings this to True, the update method won't start automatically so we can provide
43+
# the selected registry names
44+
platform.disable_tool_update = True
45+
46+
available_regs = set([reg["name"] for reg in platform.config_file.registries])
47+
specified_regs = set(specified_regs)
48+
49+
if not specified_regs.issubset(available_regs):
50+
for unkown_reg in specified_regs - available_regs:
51+
stderr.print(f"[red]Error: Registry {unkown_reg} is not available![/]")
52+
raise typer.Abort()
53+
54+
platform.tool_images.update(reg_selection=specified_regs)
55+
56+
def list_tools_from_regs(platform: Platform, table: Table) -> None:
57+
""" List the available tools from the registries.
58+
59+
Args:
60+
platform -- the Platform
61+
table -- the rich Table instance to fill with the tool image data
62+
"""
63+
table.add_column("Name")
64+
table.add_column("Available locally?")
65+
# sorted will return a list of tuples, so we can iterate over the items
66+
for tool_image in sorted(platform.tool_images.get_registry_ones().items()):
67+
# tool_image[0] is the name of the tool image and tool_image[1] is the ToolImage instance
68+
tool_image_name = tool_image[0]
69+
tool_image: ToolImage = tool_image[1]
70+
71+
if tool_image.availability == ToolImage.LOCAL_AND_REGISTRY:
72+
available_locally = "[green]✔[/]"
73+
else:
74+
available_locally = ""
75+
76+
table.add_row(tool_image_name, available_locally)
77+
78+
def list_tools_from_selected_regs(platform: Platform, specified_regs: list[str]) -> None:
79+
""" List the available tools from the selected registries only.
80+
81+
Args:
82+
platform -- the Platform
83+
specified_regs -- the selected registry names
84+
85+
Exceptions:
86+
typer.Abort -- if no tool images are available in the selected registries
87+
"""
88+
update_tools_from_selected_regs(platform, specified_regs)
89+
90+
if not platform.tool_images.get_registry_ones():
91+
stdout.print("[yellow]No tool images are available in the selected registries.[/]")
92+
raise typer.Abort()
93+
94+
table = Table()
95+
list_tools_from_regs(platform, table)
96+
stdout.print(f"\n [italic]Available Tool Images from the selected registries[/]")
97+
stdout.print(table)
98+
99+
def list_tools_from_all_regs(platform: Platform) -> None:
100+
""" List the available tools from all registries.
101+
102+
Args:
103+
platform -- the Platform
104+
105+
Exceptions:
106+
typer.Abort -- if no tool images are available in the registries
107+
"""
108+
if not platform.tool_images.get_registry_ones():
109+
stdout.print("[yellow]No tool images are available in the registries.[/]")
110+
raise typer.Abort()
111+
112+
table = Table()
113+
list_tools_from_regs(platform, table)
114+
stdout.print(f"\n [italic]Available Tool Images from all registries[/]")
115+
stdout.print(table)
116+
117+
def execute(platform: Platform, reg: bool, selected_regs: list[str]) -> None:
118+
""" List the available tools.
119+
120+
Args:
121+
platform -- the Platform
122+
reg -- the flag to list the tools from the registries
123+
selected_regs -- the selected registry names
124+
125+
Exceptions:
126+
typer.Abort -- if no tool images are available either locally or in the registries or
127+
if an unknown registry is specified
128+
"""
129+
if not reg:
130+
list_local_tools(platform)
131+
elif selected_regs:
132+
list_tools_from_selected_regs(platform, selected_regs)
133+
else:
134+
list_tools_from_all_regs(platform)

dem/cli/main.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
rename_cmd, run_cmd, export_cmd, load_cmd, clone_cmd, add_reg_cmd, \
1111
list_reg_cmd, del_reg_cmd, add_cat_cmd, list_cat_cmd, del_cat_cmd, \
1212
add_host_cmd, uninstall_cmd, install_cmd, assign_cmd, init_cmd, \
13-
list_host_cmd, del_host_cmd
13+
list_host_cmd, del_host_cmd, list_tools_cmd
1414
from dem.cli.console import stdout
1515
from dem.core.platform import Platform
1616
from dem.core.exceptions import InternalError
@@ -81,7 +81,9 @@ def list_(cat: Annotated[bool, typer.Option(help="List the Dev Envs available fr
8181
show_default=False)] = False,
8282
ctx: Annotated[typer.Context, typer.Option()] = None) -> None:
8383
"""
84-
List the locally available Dev Envs.
84+
List the Dev Envs.
85+
86+
By default the local Dev Envs will be listed.
8587
8688
--cat: List the available Dev Envs from the catalogs. Specify the catalogs' name to list the Dev
8789
Envs from. More then one catalog can be specified. If no catalog is specified, all the available
@@ -92,6 +94,24 @@ def list_(cat: Annotated[bool, typer.Option(help="List the Dev Envs available fr
9294
else:
9395
raise InternalError("Error: The platform hasn't been initialized properly!")
9496

97+
@typer_cli.command(context_settings={"allow_extra_args": True})
98+
def list_tools(reg: Annotated[bool, typer.Option(help="List the available tools in the registries.",
99+
show_default=False)] = False,
100+
ctx: Annotated[typer.Context, typer.Option()] = None) -> None:
101+
"""
102+
List the available tools.
103+
104+
By default the local tools will be listed.
105+
106+
--reg: List the available tools in the registries. Specify the registry's name to list the tools
107+
from. More then one registry can be specified. If no registry is specified, all the available
108+
registries will be used.
109+
"""
110+
if platform and ctx:
111+
list_tools_cmd.execute(platform, reg, ctx.args)
112+
else:
113+
raise InternalError("Error: The platform hasn't been initialized properly!")
114+
95115
@typer_cli.command()
96116
def info(dev_env_name: Annotated[str, typer.Argument(help="Name of the Development Environment to get info about.",
97117
autocompletion=autocomplete_dev_env_name)]) -> None:

dem/cli/tui/printable_tool_image.py

+2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ def __init__ (self, tool_image: ToolImage):
1616

1717
def convert_to_printable_tool_images(all_tool_images: dict[str, ToolImage]) -> list[PrintableToolImage]:
1818
printable_tool_images = []
19+
# sorted will return a list of tuples, so we can iterate over the items
1920
for tool_image in sorted(all_tool_images.items()):
21+
# tool_image[0] is the name of the tool image and tool_image[1] is the ToolImage instance
2022
printable_tool_images.append(PrintableToolImage(tool_image[1]))
2123

2224
return printable_tool_images

dem/core/exceptions.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ def __init__(self, message: str = "") -> None:
1111

1212
class RegistryError(Exception):
1313
"""Raised when the communication with registry fails."""
14-
pass
14+
15+
base_message = "Registry error: "
16+
17+
def __init__(self, message: str) -> None:
18+
super().__init__(self.base_message + message)
1519

1620
class ToolImageError(Exception):
1721
"""Raised when there is a problem with the tool image."""

dem/core/platform.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@ class Platform(Core):
1919
- The available tool images.
2020
- The available Development Environments.
2121
- External resources.
22-
23-
Class variables:
24-
local_only -- work with the local tool images only
2522
"""
26-
local_only = False
2723

2824
def _dev_env_json_version_check(self, dev_env_json_major_version: int) -> None:
2925
""" Check that the json file is supported.
@@ -43,6 +39,12 @@ def __init__(self) -> None:
4339
self._registries = None
4440
self._hosts = None
4541

42+
# Set this to true in the platform instance to work with the local tool images only
43+
self.local_only = False
44+
# Set this to true in the platform instance so when first accessing the `tool_images`
45+
# instance variable, do not automatically update the tool images from the registries
46+
self.disable_tool_update = False
47+
4648
def load_dev_envs(self) -> None:
4749
""" Load the Development Environments from the dev_env.json file.
4850
@@ -69,7 +71,8 @@ def tool_images(self) -> ToolImages:
6971
"""
7072
if self._tool_images is None:
7173
self._tool_images = ToolImages(self.container_engine, self.registries)
72-
self._tool_images.update(local_only=self.local_only)
74+
if not self.disable_tool_update:
75+
self._tool_images.update(local_only=self.local_only)
7376
return self._tool_images
7477

7578
@property

dem/core/registry.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from dem.core.core import Core
55
from dem.core.container_engine import ContainerEngine
6+
from dem.core.exceptions import RegistryError
67
import requests
78
from typing import Generator
89
from abc import ABC, abstractmethod
@@ -185,19 +186,24 @@ def _add_registry_instance(self, registry_config: dict) -> None:
185186
else:
186187
self.registries.append(DockerRegistry(self._container_engine, registry_config))
187188

188-
def list_repos(self) -> list[str]:
189+
def list_repos(self, reg_selection: list[str]) -> list[str]:
189190
""" List the available repositories.
191+
192+
Args:
193+
reg_selection -- the selected registries, empty list means all registries
190194
191195
Return with the list of repositories.
192196
"""
193197
repo_list: list[str] = []
194198

195199
for registry in self.registries:
196-
try:
197-
repo_list.extend(registry.repos)
198-
except Exception as e:
199-
self.user_output.error(str(e))
200-
self.user_output.error("[red]Error: The " + registry._registry_config["name"] + " registry is not available.[/]")
200+
if not reg_selection or registry._registry_config["name"] in reg_selection:
201+
try:
202+
repo_list.extend(registry.repos)
203+
except Exception as e:
204+
self.user_output.error(str(e))
205+
self.user_output.error("[red]Error: The " + registry._registry_config["name"] + \
206+
" registry is not available.[/]")
201207

202208
return repo_list
203209

dem/core/tool_images.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ def __init__(self, container_engine: ContainerEngine, registries: Registries) ->
4646
self.registries = registries
4747
self.all_tool_images = {}
4848

49-
def update(self, local_only = False, registry_only = False) -> None:
49+
def update(self, local_only: bool = False, registry_only: bool = False,
50+
reg_selection: list[str] = []) -> None:
5051
""" Update the list of available tools.
5152
5253
Args:
@@ -60,7 +61,7 @@ def update(self, local_only = False, registry_only = False) -> None:
6061
local_tool_image_names = self.container_engine.get_local_tool_images()
6162

6263
if not local_only:
63-
registry_tool_image_names = self.registries.list_repos()
64+
registry_tool_image_names = self.registries.list_repos(reg_selection)
6465

6566
for tool_image_name in local_tool_image_names:
6667
tool_image = ToolImage(tool_image_name)

docs/commands.md

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
## **`dem list [OPTIONS]`**
1+
# Development Environment management
2+
3+
## **`dem list [OPTIONS] [*CATALOG_NAMES]`**
24

35
List the locally available Dev Envs.
46

@@ -10,12 +12,27 @@ catalogs will be used.
1012

1113
Examples:
1214

15+
- `dem list` List the locally available Dev Envs.
1316
- `dem list --cat` List all the Dev Envs from all the available catalogs.
1417
- `dem list --cat catalog1 catalog2` List all the Dev Envs from the catalog1 and catalog2.
1518

1619
---
1720

18-
# Development Environment management
21+
## **`dem list-tools [OPTIONS] [*REGISTRY_NAMES]`**
22+
23+
List the available tools.
24+
25+
Options:
26+
27+
`--reg`: List the available tools from the registries. Specify the registries' name to list the
28+
tools from. More then one registry can be specified. If no registry is specified, all the available
29+
registries will be used.
30+
31+
Examples:
32+
33+
- `dem list-tools` List the locally available tools.
34+
- `dem list-tools --reg` List all the tools from all the available registries.
35+
- `dem list-tools --reg registry1 registry2` List all the tools from the registry1 and registry2.
1936

2037
## **`dem info DEV_ENV_NAME`**
2138

0 commit comments

Comments
 (0)