Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev Env settings window has been created - all required restructuring implemented. #177

Merged
merged 2 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions dem/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

from dem import __command__
from dem.cli.console import stderr, stdout
from dem.core.exceptions import RegistryError, ContainerEngineError, InternalError, DataStorageError
from dem.core.exceptions import RegistryError, ContainerEngineError, InternalError, DataStorageError, \
CatalogError, ToolImageError
import dem.cli.main
from dem.core.core import Core
from dem.core.platform import Platform
Expand All @@ -24,9 +25,6 @@ def main() -> None:
# Load the configuration file
dem.cli.main.platform.config_file.update()

# Load the Dev Envs
dem.cli.main.platform.load_dev_envs()

# Run the CLI application
dem.cli.main.typer_cli(prog_name=__command__)
except LookupError as e:
Expand All @@ -42,7 +40,7 @@ def main() -> None:
stdout.print("\nHint: The input repository might not exist in the registry.")
elif "400" in str(e):
stdout.print("\nHint: The input parameters might not be valid.")
except (ContainerEngineError, InternalError) as e:
except (ContainerEngineError, InternalError, ToolImageError) as e:
stderr.print("[red]" + str(e) + "[/]")
except DataStorageError as e:
stderr.print("[red]" + str(e) + "[/]")
Expand All @@ -53,6 +51,8 @@ def main() -> None:
elif "dev_env.json" in str(e):
stdout.print("Restoring the original Dev Env descriptor file...")
dem.cli.main.platform.dev_env_json.restore()
except CatalogError as e:
stderr.print(f"[red]{str(e)}[/]")

# Call the main() when run as `python -m`
if __name__ == "__main__":
Expand Down
5 changes: 4 additions & 1 deletion dem/cli/command/assign_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def execute(platform: Platform, dev_env_name: str, project_path: str) -> None:
dev_env_name -- the name of the Development Environment to assign
project_path -- the path to the project to assign the Development Environment to
"""
# Load the Dev Envs
platform.load_dev_envs()

if not os.path.isdir(project_path):
stderr.print(f"[red]Error: The {project_path} path does not exist.[/]")
return
Expand All @@ -24,4 +27,4 @@ def execute(platform: Platform, dev_env_name: str, project_path: str) -> None:
stderr.print(f"[red]Error: The {dev_env_name} Development Environment does not exist.[/]")
else:
platform.assign_dev_env(dev_env_to_assign, project_path)
stdout.print(f"\n[green]Successfully assigned the {dev_env_name} Dev Env to the project at{project_path}![/]")
stdout.print(f"\n[green]Successfully assigned the {dev_env_name} Dev Env to the project at {project_path}![/]")
3 changes: 3 additions & 0 deletions dem/cli/command/clone_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ def execute(platform: Platform, dev_env_name: str) -> None:
platform -- the platform
dev_env_name -- name of the Dev Env to clone
"""
# Load the Dev Envs
platform.load_dev_envs()

catalog_dev_env: DevEnv | None = None

if not platform.dev_env_catalogs.catalogs:
Expand Down
3 changes: 3 additions & 0 deletions dem/cli/command/cp_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ def cp_given_dev_env(platform: Platform, dev_env_to_cp: DevEnv,
platform.flush_descriptors()

def execute(platform: Platform, dev_env_to_cp_name: str, new_dev_env_name: str) -> None:
# Load the Dev Envs
platform.load_dev_envs()

dev_env_to_cp = get_dev_env_to_cp(platform, dev_env_to_cp_name)

if (dev_env_to_cp is not None and
Expand Down
149 changes: 36 additions & 113 deletions dem/cli/command/create_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,137 +2,55 @@
# dem/cli/command/create_cmd.py

import typer
from dem.core.dev_env import DevEnv, DevEnv
from dem.core.tool_images import ToolImages
from dem.core.dev_env import DevEnv
from dem.core.tool_images import ToolImage
from dem.core.platform import Platform
from dem.core.exceptions import PlatformError
from dem.cli.console import stdout, stderr
from dem.cli.tui.panel.tool_type_selector import ToolTypeSelectorPanel
from dem.cli.tui.panel.tool_image_selector import ToolImageSelectorPanel
from dem.cli.tui.window.dev_env_settings_window import DevEnvSettingsWindow
from dem.cli.tui.printable_tool_image import convert_to_printable_tool_images

tool_image_statuses = {
ToolImages.LOCAL_ONLY: "local",
ToolImages.REGISTRY_ONLY: "registry",
ToolImages.LOCAL_AND_REGISTRY: "local and registry"
}
def open_dev_env_settings_panel(all_tool_images: dict[str, ToolImage]) -> list[str]:
""" Open the Development Environment settings panel.
Args:
all_tool_images -- the Tool Images

def get_tool_image_list(tool_images: ToolImages) -> list[list[str]]:
"""
Combine the registry and local tool images, and assign the availabilities.

Args:
tool_images -- all the tool images
Returns:
the selected Tool Image names
"""
tool_image_list = []

for tool_image in tool_images.registry.elements:
if tool_image in tool_images.local.elements:
tool_image_list.append([tool_image, tool_image_statuses[ToolImages.LOCAL_AND_REGISTRY]])
else:
tool_image_list.append([tool_image, tool_image_statuses[ToolImages.REGISTRY_ONLY]])

for tool_image in tool_images.local.elements:
if tool_image not in tool_images.registry.elements:
tool_image_list.append([tool_image, tool_image_statuses[ToolImages.LOCAL_ONLY]])
dev_env_settings_panel = DevEnvSettingsWindow(convert_to_printable_tool_images(all_tool_images))
dev_env_settings_panel.wait_for_user()

return tool_image_list

def handle_tool_type_selector_panel(tool_type_selector_panel: ToolTypeSelectorPanel,
dev_env_name: str) -> list[str]:
tool_type_selector_panel.tool_type_menu.set_title("What kind of tools would you like to include in [cyan]" + dev_env_name + "[/]?")

tool_type_selector_panel.wait_for_user()

if "cancel" in tool_type_selector_panel.cancel_next_menu.get_selection():
if "cancel" in dev_env_settings_panel.cancel_save_menu.get_selection():
raise typer.Abort()

tool_type_selector_panel.cancel_next_menu.is_selected = False

return tool_type_selector_panel.tool_type_menu.get_selected_tool_types()

def handle_tool_image_selector_panel(tool_image_selector_panel: ToolImageSelectorPanel,
tool_type:str) -> str | None:
tool_image_selector_panel.tool_image_menu.set_title("Select tool image for: [yellow]" + tool_type + "[/]")
tool_image_selector_panel.wait_for_user()

if tool_image_selector_panel.back_menu.is_selected is True:
# Reset the back menu selection
tool_image_selector_panel.back_menu.is_selected = False
return None
else:
tool_image_selector_panel.tool_image_menu.is_selected = False
return tool_image_selector_panel.tool_image_menu.get_selected_tool_image()

def get_dev_env_descriptor_from_user(dev_env_name: str, tool_image_list: list[list[str]]) -> dict:
current_panel = ToolTypeSelectorPanel(list(DevEnv.supported_tool_types))
panel_list = [current_panel]

tool_index = 0
panel_index = 0
tool_selection = {}
while current_panel is not None:
if isinstance(current_panel, ToolTypeSelectorPanel):
selected_tool_types = handle_tool_type_selector_panel(current_panel, dev_env_name)

# Remove the not selected tool type from the tool_selection.
for tool_type in list(tool_selection.keys()):
if tool_type not in selected_tool_types:
del tool_selection[tool_type]

if len(panel_list) > 1:
current_panel = panel_list[1]
current_panel.dev_env_status.reset_table(selected_tool_types)
else:
current_panel = ToolImageSelectorPanel(tool_image_list, selected_tool_types)
panel_list.append(current_panel)

tool_index = 0
panel_index = 1
else:
selected_tool_image = handle_tool_image_selector_panel(current_panel, selected_tool_types[tool_index])

if selected_tool_image is None:
tool_selection[selected_tool_types[tool_index]] = "<not selected>"

panel_index -= 1
current_panel = panel_list[panel_index]

if tool_index != 0:
tool_index -= 1
else:
tool_selection[selected_tool_types[tool_index]] = selected_tool_image

tool_index += 1

if tool_index == len(selected_tool_types):
break

panel_index += 1
if len(panel_list) > panel_index:
current_panel = panel_list[panel_index]
else:
current_panel = ToolImageSelectorPanel(tool_image_list, selected_tool_types)
panel_list.append(current_panel)

current_panel.dev_env_status.reset_table(selected_tool_types)
return dev_env_settings_panel.selected_tool_images

if isinstance(current_panel, ToolImageSelectorPanel):
current_panel.dev_env_status.set_tool_image(tool_selection)
def create_new_dev_env_descriptor(dev_env_name: str, selected_tool_images: list[str]) -> dict:
""" Create a new Development Environment descriptor.

Args:
dev_env_name -- the name of the Development Environment
selected_tool_images -- the selected Tool Images

Returns:
the descriptor of the new Development Environment
"""
dev_env_descriptor = {
"name": dev_env_name,
"tools": []
}

for tool_type, tool_image in tool_selection.items():
for tool_image in selected_tool_images:
if "/" in tool_image:
registry, image = tool_image.split("/")
image_name = registry + '/' + image.split(":")[0]
else:
image = tool_image
image_name = image.split(":")[0]

tool_descriptor = {
"type": tool_type,
"image_name": image_name,
"image_version": image.split(":")[1]
}
Expand All @@ -147,8 +65,9 @@ def create_new_dev_env(platform: Platform, new_dev_env_descriptor: dict) -> None
platform -- the platform
new_dev_env_descriptor -- the descriptor of the new Development Environment
"""
new_dev_env = DevEnv(new_dev_env_descriptor)
platform.local_dev_envs.append(new_dev_env)
dev_env = DevEnv(descriptor=new_dev_env_descriptor)
dev_env.assign_tool_image_instances(platform.tool_images)
platform.local_dev_envs.append(dev_env)

def create_dev_env(platform: Platform, dev_env_name: str) -> None:
""" Create a new Development Environment or overwrite an existing one.
Expand Down Expand Up @@ -178,11 +97,11 @@ def create_dev_env(platform: Platform, dev_env_name: str) -> None:
stderr.print(f"[red]{str(e)}[/]")
raise typer.Abort()

tool_image_list = get_tool_image_list(platform.tool_images)
new_dev_env_descriptor = get_dev_env_descriptor_from_user(dev_env_name, tool_image_list)
selected_tool_images = open_dev_env_settings_panel(platform.tool_images.all_tool_images)
new_dev_env_descriptor = create_new_dev_env_descriptor(dev_env_name, selected_tool_images)

if dev_env_original is not None:
dev_env_original.tools = new_dev_env_descriptor["tools"]
dev_env_original.tool_image_descriptors = new_dev_env_descriptor["tools"]
else:
create_new_dev_env(platform, new_dev_env_descriptor)

Expand All @@ -196,6 +115,10 @@ def execute(platform: Platform, dev_env_name: str) -> None:
Exceptions:
Abort -- if the name of the Development Environment contains whitespace characters
"""
# Load the Dev Envs
platform.load_dev_envs()
platform.assign_tool_image_instances_to_all_dev_envs()

create_dev_env(platform, dev_env_name)
platform.flush_descriptors()
stdout.print(f"The [green]{dev_env_name}[/] Development Environment has been created!")
Expand Down
3 changes: 3 additions & 0 deletions dem/cli/command/delete_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import typer

def execute(platform: Platform, dev_env_name: str) -> None:
# Load the Dev Envs
platform.load_dev_envs()

dev_env_to_delete: DevEnv | None = platform.get_dev_env_by_name(dev_env_name)

if dev_env_to_delete is None:
Expand Down
3 changes: 3 additions & 0 deletions dem/cli/command/export_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ def export(dev_env: DevEnv, export_path: str):
dev_env.export(export_path)

def execute(platform: Platform, dev_env_name: str, export_path: str) -> None:
# Load the Dev Envs
platform.load_dev_envs()

dev_env = platform.get_dev_env_by_name(dev_env_name)
if dev_env:
try:
Expand Down
37 changes: 19 additions & 18 deletions dem/cli/command/info_cmd.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,44 @@
"""info CLI command implementation."""
# dem/cli/command/info_cmd.py

from dem.core.tool_images import ToolImages
from dem.core.tool_images import ToolImage
from dem.core.dev_env import DevEnv, DevEnv
from dem.cli.console import stdout, stderr
from dem.core.platform import Platform
from rich.table import Table

image_status_messages = {
ToolImages.NOT_AVAILABLE: "[red]Error: Required image is not available![/]",
ToolImages.LOCAL_ONLY: "Image is available locally.",
ToolImages.REGISTRY_ONLY: "Image is available in the registry.",
ToolImages.LOCAL_AND_REGISTRY: "Image is available locally and in the registry.",
ToolImage.NOT_AVAILABLE: "[red]Error: Required image is not available![/]",
ToolImage.LOCAL_ONLY: "Image is available locally.",
ToolImage.REGISTRY_ONLY: "Image is available in the registry.",
ToolImage.LOCAL_AND_REGISTRY: "Image is available locally and in the registry.",
}

def print_info(dev_env: (DevEnv | DevEnv)) -> None:

def print_info(dev_env: DevEnv) -> None:
tool_info_table = Table()
tool_info_table.add_column("Type")
tool_info_table.add_column("Image")
tool_info_table.add_column("Status")
for tool in dev_env.tools:
tool_info_table.add_row(tool["type"], tool["image_name"] + ':' + tool["image_version"],
image_status_messages[tool["image_status"]])

for tool_image in dev_env.tool_images:
tool_info_table.add_row(tool_image.name,
image_status_messages[tool_image.availability])
stdout.print(tool_info_table)

def execute(platform: Platform, arg_dev_env_name: str) -> None:
# Load the Dev Envs
platform.load_dev_envs()
platform.assign_tool_image_instances_to_all_dev_envs()

dev_env = platform.get_dev_env_by_name(arg_dev_env_name)

if dev_env is None:
for catalog in platform.dev_env_catalogs.catalogs:
catalog.request_dev_envs()
dev_env = catalog.get_dev_env_by_name(arg_dev_env_name)
if dev_env is not None:
dev_env.check_image_availability(platform.tool_images)
print_info(dev_env)
else:
dev_env.check_image_availability(platform.tool_images)
print_info(dev_env)
dev_env.assign_tool_image_instances(platform.tool_images)
break

if dev_env is None:
stderr.print("[red]Error: Unknown Development Environment: " + arg_dev_env_name + "[/]")
stderr.print(f"[red]Error: Unknown Development Environment: {arg_dev_env_name}[/]\n")
else:
print_info(dev_env)
3 changes: 3 additions & 0 deletions dem/cli/command/init_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def execute(platform: Platform, project_path: str) -> None:
platform -- the platform
project_path -- the path to the project to initialize
"""
# Load the Dev Envs
platform.load_dev_envs()

if not os.path.isdir(project_path):
stderr.print(f"[red]Error: The {project_path} path does not exist.[/]")
return
Expand Down
4 changes: 4 additions & 0 deletions dem/cli/command/install_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ def execute(platform: Platform, dev_env_name: str) -> None:
platform -- the platform
dev_env_name -- the name of the Development Environment to install
"""
# Load the Dev Envs
platform.load_dev_envs()
platform.assign_tool_image_instances_to_all_dev_envs()

dev_env_to_install: DevEnv | None = platform.get_dev_env_by_name(dev_env_name)

if dev_env_to_install is None:
Expand Down
Loading
Loading