Skip to content

Commit

Permalink
feat(DS-322): add command for remove TVM project (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
Henrrypg authored Dec 22, 2022
1 parent 025f000 commit 12439ff
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 2 deletions.
15 changes: 15 additions & 0 deletions docs/source/tvm_topic_guides/environment_manager.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Index
------

- `Create a Project`_
- `Remove a Project Environment`_
- `Activate a Project Environment`_
- `Deactivate a Project Environment`_
- `List Environments and Projects`_
Expand All @@ -26,6 +27,20 @@ Create a Project
.. note:: The <tutor-version> parameter is optional. However, if you don't specify the version, the project will be created with the version you set previously with tvm use <tutor-version> or the latest version. If you specify the version, and the version isn't installed, it will be installed.


Remove a Project Environment
----------------------------

.. code-block:: bash
tvm project remove <tutor-version>@<project-name>
# For example:
# tvm project remove v14.0.0@tvm-test
.. note:: You can use the flag --prune to remove all the project folder. Ex: `tvm project remove v14.0.0@tvm-test --prune`


Activate a Project Environment
------------------------------

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import pytest

from tests.environment_manager.infrastructure.environment_manager_in_memory_repository import (
EnvironmentManagerInMemoryRepository,
)
from tvm.environment_manager.application.tutor_project_remover import (
TutorProjectRemover,
)


def test_should_remove_tutor_project():
# Given
repository = EnvironmentManagerInMemoryRepository()

# When
remove = TutorProjectRemover(repository=repository)
remove(prune=False)

# Then
assert repository.PROJECT_NAME == []
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ def project_creator(self, version: str) -> None:
else:
raise Exception('There is already a project initiated.')

def project_remover(self, prune: bool) -> None:
"""Tutor Project Remove to environment manager."""
if self.PROJECT_NAME:
self.PROJECT_NAME.clear()
else:
raise Exception('There is no project to remove.')


def install_plugin(self, options: List) -> None:
if options:
Expand Down
36 changes: 36 additions & 0 deletions tvm/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
from typing import Optional

import click
import yaml
from click.shell_completion import CompletionItem

from tvm import __version__
from tvm.environment_manager.application.plugin_installer import PluginInstaller
from tvm.environment_manager.application.plugin_uninstaller import PluginUninstaller
from tvm.environment_manager.application.tutor_project_creator import TutorProjectCreator
from tvm.environment_manager.application.tutor_project_remover import TutorProjectRemover
from tvm.environment_manager.domain.project_name import ProjectName
from tvm.settings import environment_manager, version_manager
from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE
from tvm.version_manager.application.tutor_plugin_installer import TutorPluginInstaller
Expand Down Expand Up @@ -408,6 +411,38 @@ def init(name: str = None, version: str = None):
raise click.UsageError('There is already a project initiated.') from IndexError


@click.command(name="remove")
@click.argument('project-name', required=True)
@click.option('--prune', is_flag=True, help="Remove all files in project folder.")
def remove(project_name: ProjectName, prune: bool):
"""Remove TVM project.
PROJECT-NAME: {VERSION}@{NAME} E.g. v1.0.0@my-project
"""
tvm_project_folder = TVM_PATH / project_name

if not os.path.exists(tvm_project_folder):
raise click.UsageError('There is no project initiated with this name and version.') from IndexError

if not os.path.exists(tvm_project_folder / 'config.yml'):
raise click.UsageError('This project was created in older version or have corrupted files.') from IndexError

with open(tvm_project_folder / 'config.yml', "r", encoding='utf-8') as f:
data = yaml.load(f, Loader=yaml.FullLoader)
click.echo(click.style("You are trying to remove the following paths and all its containing files:\n", fg='yellow')) # pylint: disable=line-too-long

for path in data['project_directories']:
if not prune:
path = f"{path}/.tvm"
click.echo(click.style(f"\t{path}", fg='yellow'))

click.confirm(text=f"\nAre you sure you want to remove the project {project_name}?", abort=True)

repository = environment_manager(project_path=f"{project_name}")
remover = TutorProjectRemover(repository=repository)
remover(prune=prune)


@click.command(name="install", context_settings={"ignore_unknown_options": True})
@click.argument('options', nargs=-1, type=click.UNPROCESSED)
def install_plugin(options):
Expand Down Expand Up @@ -499,6 +534,7 @@ def clear():
cli.add_command(use)
cli.add_command(projects)
projects.add_command(init)
projects.add_command(remove)
cli.add_command(plugins)
plugins.add_command(install_plugin)
plugins.add_command(uninstall_plugin)
Expand Down
14 changes: 14 additions & 0 deletions tvm/environment_manager/application/tutor_project_remover.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Tutor project initialize."""
from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository


class TutorProjectRemover:
"""Tutor project initialize for environment manager."""

def __init__(self, repository: EnvironmentManagerRepository) -> None:
"""init."""
self.repository = repository

def __call__(self, prune: bool) -> None:
"""call."""
self.repository.project_remover(prune=prune)
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class EnvironmentManagerRepository(ABC):
def project_creator(self, project_name: ProjectName) -> None:
"""Tutor Project Init to environment manager."""

@abstractmethod
def project_remover(self, prune: bool) -> None:
"""Tutor Project Remove to environment manager."""

@abstractmethod
def current_version(self) -> None:
"""Get the project's version."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
from distutils.dir_util import copy_tree # pylint: disable=W0402
from typing import List

import yaml

from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository
from tvm.environment_manager.domain.project_name import ProjectName
from tvm.share.domain.client_logger_repository import ClientLoggerRepository
from tvm.templates.tvm_activate import TVM_ACTIVATE_SCRIPT

TVM_PATH = pathlib.Path.home() / ".tvm"
Expand All @@ -17,8 +20,9 @@
class EnvironmentManagerGitRepository(EnvironmentManagerRepository):
"""Principals commands to manage TVM."""

def __init__(self, project_path: str) -> None:
def __init__(self, project_path: str, logger: ClientLoggerRepository) -> None:
"""Initialize usefull variables."""
self.logger = logger
self.PROJECT_PATH = project_path
self.TVM_ENVIRONMENT = f"{project_path}/.tvm"

Expand All @@ -34,6 +38,43 @@ def project_creator(self, project_name: ProjectName) -> None:
self.create_active_script(data)
self.create_project(project_name)

def project_remover(self, prune: bool) -> None:
"""Remove tutor project."""
with open(f"{TVM_PATH}/{self.PROJECT_PATH}/config.yml", "r", encoding='utf-8') as f:
data = yaml.load(f, Loader=yaml.FullLoader)

deleted_dirs = []
for project in data['project_directories']:
if os.path.exists(f"{project}"):
if not prune:
project = f"{project}/.tvm"
deleted_dirs.append(project)
self.remove_project(project)
else:
self.logger.echo(f"Project not found in {project}, if you moved it from the original path, you must remove it manually.\n") # pylint: disable=C0301

self.remove_project(f"{TVM_PATH}/{self.PROJECT_PATH}")
self.logger.echo(f"\nProject {self.PROJECT_PATH} removed from the following paths:") # pylint: disable=C0301
for project in deleted_dirs:
self.logger.echo(f"\t{project}")

def remove_project(self, project_path: str):
"""Remove project."""
try:
shutil.rmtree(f"{project_path}")
except PermissionError:
self.logger.echo(
"Don't Worry, TVM just needs sudo permissions to delete your project files."
)
subprocess.call(
[
"sudo",
"rm",
"-r",
f"{project_path}",
]
)

def current_version(self) -> ProjectName:
"""Project name in current version."""
info_file_path = f"{self.TVM_ENVIRONMENT}/config.json"
Expand Down Expand Up @@ -64,9 +105,19 @@ def create_project(self, project_name: ProjectName) -> None:

tvm_project = f"{TVM_PATH}/{project_name}"
copy_tree(tutor_version_folder, tvm_project)
with open(f"{tvm_project}/config.yml", "w", encoding='utf-8') as f:
data = {'project_directories': [f"{self.PROJECT_PATH}"]}
yaml.dump(data, f, default_flow_style=False)

shutil.rmtree(f"{tvm_project}/venv")
self.setup_version_virtualenv(project_name)
else:
with open(f"{TVM_PATH}/{project_name}/config.yml", "r+", encoding='utf-8') as f:
data = yaml.load(f, Loader=yaml.FullLoader)
data['project_directories'].append(f"{self.PROJECT_PATH}")
f.truncate(0)
f.seek(0)
yaml.dump(data, f, default_flow_style=False)

@staticmethod
def setup_version_virtualenv(version=None) -> None:
Expand Down
2 changes: 1 addition & 1 deletion tvm/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@

def environment_manager(project_path: str) -> EnvironmentManagerGitRepository:
"""Environment manager repository."""
return EnvironmentManagerGitRepository(project_path=project_path)
return EnvironmentManagerGitRepository(project_path=project_path, logger=logger)

0 comments on commit 12439ff

Please sign in to comment.