From aa34f7fc3568df1e548a59fb22a6194e9b59943a Mon Sep 17 00:00:00 2001 From: Juan David Buitrago Date: Tue, 26 Jul 2022 21:05:15 -0500 Subject: [PATCH 01/13] feat: migrate project init command to a clean architecture --- tvm/cli.py | 110 +++++++++--------- tvm/environment_manager/__init__.py | 1 + .../application/__init__.py | 1 + .../application/tutor_project_init.py | 14 +++ tvm/environment_manager/domain/__init__.py | 1 + .../domain/environment_manager_repository.py | 14 +++ .../infrastructure/__init__.py | 1 + .../environment_manager_git_repository.py | 82 +++++++++++++ 8 files changed, 172 insertions(+), 52 deletions(-) create mode 100644 tvm/environment_manager/__init__.py create mode 100644 tvm/environment_manager/application/__init__.py create mode 100644 tvm/environment_manager/application/tutor_project_init.py create mode 100644 tvm/environment_manager/domain/__init__.py create mode 100644 tvm/environment_manager/domain/environment_manager_repository.py create mode 100644 tvm/environment_manager/infrastructure/__init__.py create mode 100644 tvm/environment_manager/infrastructure/environment_manager_git_repository.py diff --git a/tvm/cli.py b/tvm/cli.py index 5ceae6f..83d7571 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -18,6 +18,8 @@ from click.shell_completion import CompletionItem from tvm import __version__ +from tvm.environment_manager.application.tutor_project_init import TutorProjectInit +from tvm.environment_manager.infrastructure.environment_manager_git_repository import EnvironmentManagerGitRepository from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE from tvm.templates.tvm_activate import TVM_ACTIVATE_SCRIPT from tvm.version_manager.application.tutor_plugin_installer import TutorPluginInstaller @@ -130,18 +132,18 @@ def setup_tvm(): pass -def setup_version_virtualenv(version=None) -> None: - """Create virtualenv and install tutor cloned.""" - # Create virtualenv - subprocess.run(f'cd {TVM_PATH}/{version}; virtualenv venv', - shell=True, check=True, - executable='/bin/bash') +# def setup_version_virtualenv(version=None) -> None: +# """Create virtualenv and install tutor cloned.""" +# # Create virtualenv +# subprocess.run(f'cd {TVM_PATH}/{version}; virtualenv venv', +# shell=True, check=True, +# executable='/bin/bash') - # Install tutor - subprocess.run(f'source {TVM_PATH}/{version}/venv/bin/activate;' - f'pip install -e {TVM_PATH}/{version}/overhangio-tutor-*/', - shell=True, check=True, - executable='/bin/bash') +# # Install tutor +# subprocess.run(f'source {TVM_PATH}/{version}/venv/bin/activate;' +# f'pip install -e {TVM_PATH}/{version}/overhangio-tutor-*/', +# shell=True, check=True, +# executable='/bin/bash') @click.command(name="list") @@ -428,17 +430,17 @@ def projects() -> None: """Hold the main wrapper for the `tvm project` command.""" -def create_project(project: str) -> None: - """Duplicate the version directory and rename it.""" - if not os.path.exists(f"{TVM_PATH}/{project}"): - tutor_version = project.split("@")[0] - tutor_version_folder = f"{TVM_PATH}/{tutor_version}" +# def create_project(project: str) -> None: +# """Duplicate the version directory and rename it.""" +# if not os.path.exists(f"{TVM_PATH}/{project}"): +# tutor_version = project.split("@")[0] +# tutor_version_folder = f"{TVM_PATH}/{tutor_version}" - tvm_project = f"{TVM_PATH}/{project}" - copy_tree(tutor_version_folder, tvm_project) +# tvm_project = f"{TVM_PATH}/{project}" +# copy_tree(tutor_version_folder, tvm_project) - shutil.rmtree(f"{tvm_project}/venv") - setup_version_virtualenv(project) +# shutil.rmtree(f"{tvm_project}/venv") +# setup_version_virtualenv(project) @click.command(name="init") @@ -464,38 +466,42 @@ def init(name: str = None, version: str = None): if not os.path.exists(tvm_environment): pathlib.Path(f"{tvm_environment}/bin").mkdir(parents=True, exist_ok=True) - # Create config json - tvm_project_config_file = f"{tvm_environment}/config.json" - data = { - "version": f"{version}", - "tutor_root": f"{tvm_project_folder}", - "tutor_plugins_root": f"{tvm_project_folder}/plugins" - } - with open(tvm_project_config_file, 'w', encoding='utf-8') as info_file: - json.dump(data, info_file, indent=4) - - # Create activate script - context = { - "version": f"{version}", - "tutor_root": f"{tvm_project_folder}", - "tutor_plugins_root": f"{tvm_project_folder}/plugins" - } - activate_script = f"{tvm_environment}/bin/activate" - with open(activate_script, 'w', encoding='utf-8') as activate_file: - activate_file.write(TVM_ACTIVATE_SCRIPT.render(**context)) - - # Create tutor switcher - context = { - 'version': data.get('version', None), - 'tvm': f"{TVM_PATH}", - } - tutor_file = f"{tvm_environment}/bin/tutor" - with open(tutor_file, 'w', encoding='utf-8') as switcher_file: - switcher_file.write(TUTOR_SWITCHER_TEMPLATE.render(**context)) - # set execute permissions - os.chmod(tutor_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH) - - create_project(project=version) + repository = EnvironmentManagerGitRepository() + initialize = TutorProjectInit(repository=repository) + initialize(version, tvm_project_folder) + + # # Create config json + # tvm_project_config_file = f"{tvm_environment}/config.json" + # data = { + # "version": f"{version}", + # "tutor_root": f"{tvm_project_folder}", + # "tutor_plugins_root": f"{tvm_project_folder}/plugins" + # } + # with open(tvm_project_config_file, 'w', encoding='utf-8') as info_file: + # json.dump(data, info_file, indent=4) + + # # Create activate script + # context = { + # "version": f"{version}", + # "tutor_root": f"{tvm_project_folder}", + # "tutor_plugins_root": f"{tvm_project_folder}/plugins" + # } + # activate_script = f"{tvm_environment}/bin/activate" + # with open(activate_script, 'w', encoding='utf-8') as activate_file: + # activate_file.write(TVM_ACTIVATE_SCRIPT.render(**context)) + + # # Create tutor switcher + # context = { + # 'version': data.get('version', None), + # 'tvm': f"{TVM_PATH}", + # } + # tutor_file = f"{tvm_environment}/bin/tutor" + # with open(tutor_file, 'w', encoding='utf-8') as switcher_file: + # switcher_file.write(TUTOR_SWITCHER_TEMPLATE.render(**context)) + # # set execute permissions + # os.chmod(tutor_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH) + + # create_project(project=version) else: raise click.UsageError('There is already a project initiated.') from IndexError diff --git a/tvm/environment_manager/__init__.py b/tvm/environment_manager/__init__.py new file mode 100644 index 0000000..6a76807 --- /dev/null +++ b/tvm/environment_manager/__init__.py @@ -0,0 +1 @@ +"""Environment manager init.""" \ No newline at end of file diff --git a/tvm/environment_manager/application/__init__.py b/tvm/environment_manager/application/__init__.py new file mode 100644 index 0000000..22270ef --- /dev/null +++ b/tvm/environment_manager/application/__init__.py @@ -0,0 +1 @@ +"""Application init.""" \ No newline at end of file diff --git a/tvm/environment_manager/application/tutor_project_init.py b/tvm/environment_manager/application/tutor_project_init.py new file mode 100644 index 0000000..c913898 --- /dev/null +++ b/tvm/environment_manager/application/tutor_project_init.py @@ -0,0 +1,14 @@ +"""Tutor project initialize.""" +from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository + + +class TutorProjectInit: + """Tutor project init for environment manager.""" + + def __init__(self, repository: EnvironmentManagerRepository) -> None: + """init.""" + self.repository = repository + + def __call__(self, version, tvm_project_folder) -> None: + """call.""" + self.repository.project_init(version, tvm_project_folder) diff --git a/tvm/environment_manager/domain/__init__.py b/tvm/environment_manager/domain/__init__.py new file mode 100644 index 0000000..c9cfdb2 --- /dev/null +++ b/tvm/environment_manager/domain/__init__.py @@ -0,0 +1 @@ +"""Domain init.""" \ No newline at end of file diff --git a/tvm/environment_manager/domain/environment_manager_repository.py b/tvm/environment_manager/domain/environment_manager_repository.py new file mode 100644 index 0000000..8938bcd --- /dev/null +++ b/tvm/environment_manager/domain/environment_manager_repository.py @@ -0,0 +1,14 @@ +"""Environment manager repository methods.""" +from abc import ABC, abstractmethod +from typing import List, Optional + +from tvm.version_manager.domain.tutor_version import TutorVersion + + +class EnvironmentManagerRepository(ABC): + """Administrate environment manager repository methods.""" + + @staticmethod + @abstractmethod + def project_init(self, version, tvm_project_folder) -> None: + """Tutor Project Init to environment manager.""" diff --git a/tvm/environment_manager/infrastructure/__init__.py b/tvm/environment_manager/infrastructure/__init__.py new file mode 100644 index 0000000..a7fcb2f --- /dev/null +++ b/tvm/environment_manager/infrastructure/__init__.py @@ -0,0 +1 @@ +"""Infrastructure init.""" \ No newline at end of file diff --git a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py new file mode 100644 index 0000000..91a1493 --- /dev/null +++ b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py @@ -0,0 +1,82 @@ +"""Actions to initialize a project.""" +from distutils.dir_util import copy_tree +import json +import os +import pathlib +import shutil +import stat +import subprocess +from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository + + +from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE +from tvm.templates.tvm_activate import TVM_ACTIVATE_SCRIPT + +TVM_PATH = pathlib.Path.home() / '.tvm' + + +class EnvironmentManagerGitRepository(EnvironmentManagerRepository): + """Principals commands to manage TVM.""" + + def project_init(self, version: str, tvm_project_folder: str) -> None: + """Initialize tutor project.""" + tvm_environment = tvm_project_folder / '.tvm' + data = { + "version": f"{version}", + "tutor_root": f"{tvm_project_folder}", + "tutor_plugins_root": f"{tvm_project_folder}/plugins" + } + context = { + 'version': data.get('version', None), + 'tvm': f"{TVM_PATH}", + } + + self.create_config_json(tvm_environment, data) + self.create_active_script(tvm_environment, data) + self.create_tutor_switcher(tvm_environment, context) + self.create_project(version) + + def create_config_json(self, tvm_environment: str, data: dict) -> None: + """Create configuration json file""" + tvm_project_config_file = f"{tvm_environment}/config.json" + with open(tvm_project_config_file, 'w', encoding='utf-8') as info_file: + json.dump(data, info_file, indent=4) + + def create_active_script(self, tvm_environment: str, context: dict) -> None: + """Create active script file.""" + activate_script = f"{tvm_environment}/bin/activate" + with open(activate_script, 'w', encoding='utf-8') as activate_file: + activate_file.write(TVM_ACTIVATE_SCRIPT.render(**context)) + + def create_tutor_switcher(self, tvm_environment: str, context: dict) -> None: + """Create tutor switcher file.""" + tutor_file = f"{tvm_environment}/bin/tutor" + with open(tutor_file, 'w', encoding='utf-8') as switcher_file: + switcher_file.write(TUTOR_SWITCHER_TEMPLATE.render(**context)) + # set execute permissions + os.chmod(tutor_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH) + + def create_project(self, project: str) -> None: + """Duplicate the version directory and rename it.""" + if not os.path.exists(f"{TVM_PATH}/{project}"): + tutor_version = project.split("@")[0] + tutor_version_folder = f"{TVM_PATH}/{tutor_version}" + + tvm_project = f"{TVM_PATH}/{project}" + copy_tree(tutor_version_folder, tvm_project) + + shutil.rmtree(f"{tvm_project}/venv") + self.setup_version_virtualenv(project) + + def setup_version_virtualenv(self, version=None) -> None: + """Create virtualenv and install tutor cloned.""" + # Create virtualenv + subprocess.run(f'cd {TVM_PATH}/{version}; virtualenv venv', + shell=True, check=True, + executable='/bin/bash') + + # Install tutor + subprocess.run(f'source {TVM_PATH}/{version}/venv/bin/activate;' + f'pip install -e {TVM_PATH}/{version}/overhangio-tutor-*/', + shell=True, check=True, + executable='/bin/bash') From 7a6caa8b0198b6bd4a570310614130597e72a45b Mon Sep 17 00:00:00 2001 From: Alejandro Cardenas Date: Wed, 27 Jul 2022 10:59:09 -0500 Subject: [PATCH 02/13] fix: solve issue in project plugin instal --- tvm/cli.py | 54 +++++----------- .../application/plugin_installer.py | 11 ++++ .../application/plugin_uninstaller.py | 11 ++++ .../application/tutor_project_init.py | 4 +- .../domain/environment_manager_repository.py | 14 ++++- .../domain/project_name.py | 14 +++++ .../domain/project_name_format_error.py | 2 + .../environment_manager_git_repository.py | 62 ++++++++++++++----- tvm/templates/tvm_activate.py | 4 +- .../application/tutor_plugin_installer.py | 9 ++- .../application/tutor_plugin_uninstaller.py | 9 ++- .../domain/version_manager_repository.py | 4 +- .../version_manager_git_repository.py | 11 ++-- 13 files changed, 139 insertions(+), 70 deletions(-) create mode 100644 tvm/environment_manager/application/plugin_installer.py create mode 100644 tvm/environment_manager/application/plugin_uninstaller.py create mode 100644 tvm/environment_manager/domain/project_name.py create mode 100644 tvm/environment_manager/domain/project_name_format_error.py diff --git a/tvm/cli.py b/tvm/cli.py index 83d7571..f7fb810 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -9,7 +9,6 @@ import string import subprocess import sys -from distutils.dir_util import copy_tree from distutils.version import LooseVersion from typing import Optional @@ -18,6 +17,8 @@ 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_init import TutorProjectInit from tvm.environment_manager.infrastructure.environment_manager_git_repository import EnvironmentManagerGitRepository from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE @@ -466,42 +467,9 @@ def init(name: str = None, version: str = None): if not os.path.exists(tvm_environment): pathlib.Path(f"{tvm_environment}/bin").mkdir(parents=True, exist_ok=True) - repository = EnvironmentManagerGitRepository() + repository = EnvironmentManagerGitRepository(project_path=f"{tvm_project_folder}") initialize = TutorProjectInit(repository=repository) - initialize(version, tvm_project_folder) - - # # Create config json - # tvm_project_config_file = f"{tvm_environment}/config.json" - # data = { - # "version": f"{version}", - # "tutor_root": f"{tvm_project_folder}", - # "tutor_plugins_root": f"{tvm_project_folder}/plugins" - # } - # with open(tvm_project_config_file, 'w', encoding='utf-8') as info_file: - # json.dump(data, info_file, indent=4) - - # # Create activate script - # context = { - # "version": f"{version}", - # "tutor_root": f"{tvm_project_folder}", - # "tutor_plugins_root": f"{tvm_project_folder}/plugins" - # } - # activate_script = f"{tvm_environment}/bin/activate" - # with open(activate_script, 'w', encoding='utf-8') as activate_file: - # activate_file.write(TVM_ACTIVATE_SCRIPT.render(**context)) - - # # Create tutor switcher - # context = { - # 'version': data.get('version', None), - # 'tvm': f"{TVM_PATH}", - # } - # tutor_file = f"{tvm_environment}/bin/tutor" - # with open(tutor_file, 'w', encoding='utf-8') as switcher_file: - # switcher_file.write(TUTOR_SWITCHER_TEMPLATE.render(**context)) - # # set execute permissions - # os.chmod(tutor_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH) - - # create_project(project=version) + initialize(version) else: raise click.UsageError('There is already a project initiated.') from IndexError @@ -512,23 +480,29 @@ def install_plugin(options): """Use the package installer pip in current tutor version.""" options = list(options) options.insert(0, "install") + if "TVM_PROJECT_ENV" in os.environ: - run_on_tutor_venv('pip', options, version=get_project_version(os.environ.get("TVM_PROJECT_ENV"))) + repository = EnvironmentManagerGitRepository(os.environ.get("TVM_PROJECT_ENV")) + installer = PluginInstaller(repository=repository) else: repository = VersionManagerGitRepository() installer = TutorPluginInstaller(repository=repository) - installer(options) + installer(options) @click.command(name="uninstall", context_settings={"ignore_unknown_options": True}) @click.argument('options', nargs=-1, type=click.UNPROCESSED) def uninstall_plugin(options): """Use the package installer pip in current tutor version.""" - repository = VersionManagerGitRepository() - uninstaller = TutorPluginUninstaller(repository=repository) options = list(options) options.insert(0, "uninstall") options.append("-y") + if "TVM_PROJECT_ENV" in os.environ: + repository = EnvironmentManagerGitRepository(os.environ.get("TVM_PROJECT_ENV")) + uninstaller = PluginUninstaller(repository=repository) + else: + repository = VersionManagerGitRepository() + uninstaller = TutorPluginUninstaller(repository=repository) uninstaller(options) diff --git a/tvm/environment_manager/application/plugin_installer.py b/tvm/environment_manager/application/plugin_installer.py new file mode 100644 index 0000000..38f7219 --- /dev/null +++ b/tvm/environment_manager/application/plugin_installer.py @@ -0,0 +1,11 @@ +from typing import List + +from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository + + +class PluginInstaller: + def __init__(self, repository: EnvironmentManagerRepository) -> None: + self.repository = repository + + def __call__(self, options: List) -> None: + self.repository.install_plugin(options=options) diff --git a/tvm/environment_manager/application/plugin_uninstaller.py b/tvm/environment_manager/application/plugin_uninstaller.py new file mode 100644 index 0000000..c0d0660 --- /dev/null +++ b/tvm/environment_manager/application/plugin_uninstaller.py @@ -0,0 +1,11 @@ +from typing import List + +from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository + + +class PluginUninstaller: + def __init__(self, repository: EnvironmentManagerRepository) -> None: + self.repository = repository + + def __call__(self, options: List) -> None: + self.repository.uninstall_plugin(options=options) diff --git a/tvm/environment_manager/application/tutor_project_init.py b/tvm/environment_manager/application/tutor_project_init.py index c913898..f45cb1d 100644 --- a/tvm/environment_manager/application/tutor_project_init.py +++ b/tvm/environment_manager/application/tutor_project_init.py @@ -9,6 +9,6 @@ def __init__(self, repository: EnvironmentManagerRepository) -> None: """init.""" self.repository = repository - def __call__(self, version, tvm_project_folder) -> None: + def __call__(self, version) -> None: """call.""" - self.repository.project_init(version, tvm_project_folder) + self.repository.project_init(version) diff --git a/tvm/environment_manager/domain/environment_manager_repository.py b/tvm/environment_manager/domain/environment_manager_repository.py index 8938bcd..1c2653d 100644 --- a/tvm/environment_manager/domain/environment_manager_repository.py +++ b/tvm/environment_manager/domain/environment_manager_repository.py @@ -10,5 +10,17 @@ class EnvironmentManagerRepository(ABC): @staticmethod @abstractmethod - def project_init(self, version, tvm_project_folder) -> None: + def project_init(self, version) -> None: """Tutor Project Init to environment manager.""" + + @abstractmethod + def current_version(self) -> None: + """Get the project's version""" + + @abstractmethod + def install_plugin(self, options: List) -> None: + """Install a pip package""" + + @abstractmethod + def uninstall_plugin(self, options: List) -> None: + """Uninstall a pip package""" diff --git a/tvm/environment_manager/domain/project_name.py b/tvm/environment_manager/domain/project_name.py new file mode 100644 index 0000000..af250e2 --- /dev/null +++ b/tvm/environment_manager/domain/project_name.py @@ -0,0 +1,14 @@ +import re + +from tvm.environment_manager.domain.project_name_format_error import ProjectNameFormatError + + +class ProjectName(str): + + def __init__(self, value: str): # pylint: disable=super-init-not-called + """Raise BadParameter if the value is not a project name.""" + self._value = value + + result = re.match(r"^v([0-9]+)\.([0-9]+)\.([0-9]+)\@[a-zA-Z0-9]+$", value) + if not result: + raise ProjectNameFormatError("format must be 'vX.Y.Z@project_name'") diff --git a/tvm/environment_manager/domain/project_name_format_error.py b/tvm/environment_manager/domain/project_name_format_error.py new file mode 100644 index 0000000..bb1c824 --- /dev/null +++ b/tvm/environment_manager/domain/project_name_format_error.py @@ -0,0 +1,2 @@ +class ProjectNameFormatError(Exception): + pass diff --git a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py index 91a1493..8f489d3 100644 --- a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py +++ b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py @@ -6,8 +6,10 @@ import shutil import stat import subprocess -from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository +from typing import List +from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository +from tvm.environment_manager.domain.project_name import ProjectName from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE from tvm.templates.tvm_activate import TVM_ACTIVATE_SCRIPT @@ -17,40 +19,48 @@ class EnvironmentManagerGitRepository(EnvironmentManagerRepository): """Principals commands to manage TVM.""" + def __init__(self, project_path: str) -> None: + self.PROJECT_PATH = project_path + self.TVM_ENVIRONMENT = f"{project_path}/.tvm" - def project_init(self, version: str, tvm_project_folder: str) -> None: + def project_init(self, version: str) -> None: """Initialize tutor project.""" - tvm_environment = tvm_project_folder / '.tvm' data = { "version": f"{version}", - "tutor_root": f"{tvm_project_folder}", - "tutor_plugins_root": f"{tvm_project_folder}/plugins" + "tutor_root": f"{self.PROJECT_PATH}", + "tutor_plugins_root": f"{self.PROJECT_PATH}/plugins" } context = { 'version': data.get('version', None), 'tvm': f"{TVM_PATH}", } - self.create_config_json(tvm_environment, data) - self.create_active_script(tvm_environment, data) - self.create_tutor_switcher(tvm_environment, context) + self.create_config_json(data) + self.create_active_script(data) + self.create_tutor_switcher(context) self.create_project(version) - def create_config_json(self, tvm_environment: str, data: dict) -> None: + def current_version(self) -> ProjectName: + info_file_path = f'{self.TVM_ENVIRONMENT}/config.json' + with open(info_file_path, 'r', encoding='utf-8') as info_file: + data = json.load(info_file) + return ProjectName(data.get('version')) + + def create_config_json(self, data: dict) -> None: """Create configuration json file""" - tvm_project_config_file = f"{tvm_environment}/config.json" + tvm_project_config_file = f"{self.TVM_ENVIRONMENT}/config.json" with open(tvm_project_config_file, 'w', encoding='utf-8') as info_file: json.dump(data, info_file, indent=4) - def create_active_script(self, tvm_environment: str, context: dict) -> None: + def create_active_script(self, context: dict) -> None: """Create active script file.""" - activate_script = f"{tvm_environment}/bin/activate" + activate_script = f"{self.TVM_ENVIRONMENT}/bin/activate" with open(activate_script, 'w', encoding='utf-8') as activate_file: activate_file.write(TVM_ACTIVATE_SCRIPT.render(**context)) - def create_tutor_switcher(self, tvm_environment: str, context: dict) -> None: + def create_tutor_switcher(self, context: dict) -> None: """Create tutor switcher file.""" - tutor_file = f"{tvm_environment}/bin/tutor" + tutor_file = f"{self.TVM_ENVIRONMENT}/bin/tutor" with open(tutor_file, 'w', encoding='utf-8') as switcher_file: switcher_file.write(TUTOR_SWITCHER_TEMPLATE.render(**context)) # set execute permissions @@ -68,7 +78,8 @@ def create_project(self, project: str) -> None: shutil.rmtree(f"{tvm_project}/venv") self.setup_version_virtualenv(project) - def setup_version_virtualenv(self, version=None) -> None: + @staticmethod + def setup_version_virtualenv(version=None) -> None: """Create virtualenv and install tutor cloned.""" # Create virtualenv subprocess.run(f'cd {TVM_PATH}/{version}; virtualenv venv', @@ -80,3 +91,24 @@ def setup_version_virtualenv(self, version=None) -> None: f'pip install -e {TVM_PATH}/{version}/overhangio-tutor-*/', shell=True, check=True, executable='/bin/bash') + + def run_command_in_virtualenv(self, options: List, name: ProjectName = None): + """Use virtual environment to run command.""" + if not name: + name = self.current_version() + + try: + subprocess.run( + f"source {TVM_PATH}/{name}/venv/bin/activate;" f'pip {" ".join(options)}', + shell=True, + check=True, + executable="/bin/bash", + ) + except subprocess.CalledProcessError as ex: + raise Exception(f"Error running venv commands: {ex.output}") from ex + + def install_plugin(self, options: List) -> None: + self.run_command_in_virtualenv(options=options) + + def uninstall_plugin(self, options: List) -> None: + self.run_command_in_virtualenv(options=options) diff --git a/tvm/templates/tvm_activate.py b/tvm/templates/tvm_activate.py index 84e8f99..e0080dc 100644 --- a/tvm/templates/tvm_activate.py +++ b/tvm/templates/tvm_activate.py @@ -51,10 +51,10 @@ } # unset irrelevant variables tvmoff nondestructive -TVM_PROJECT_ENV="{{ tutor_root }}/.tvm" +TVM_PROJECT_ENV="{{ tutor_root }}" export TVM_PROJECT_ENV _TVM_OLD_VIRTUAL_PATH="$PATH" -PATH="$TVM_PROJECT_ENV/bin:$PATH" +PATH="$TVM_PROJECT_ENV/.tvm/bin:$PATH" export PATH if ! [ -z "${TUTOR_ROOT+_}" ] ; then _TVM_OLD_TUTOR_ROOT="$TUTOR_ROOT" diff --git a/tvm/version_manager/application/tutor_plugin_installer.py b/tvm/version_manager/application/tutor_plugin_installer.py index 9f3d83d..c99ced5 100644 --- a/tvm/version_manager/application/tutor_plugin_installer.py +++ b/tvm/version_manager/application/tutor_plugin_installer.py @@ -1,4 +1,7 @@ """Tutor plugin installer application.""" +from typing import List + +from tvm.version_manager.domain.tutor_version import TutorVersion from tvm.version_manager.domain.version_manager_repository import VersionManagerRepository @@ -9,6 +12,8 @@ def __init__(self, repository: VersionManagerRepository) -> None: """init.""" self.repository = repository - def __call__(self, options) -> None: + def __call__(self, options: List, version: TutorVersion = None) -> None: """call.""" - self.repository.install_plugin(options) + if version: + version = TutorVersion(version=version) + self.repository.install_plugin(options=options, version=version) diff --git a/tvm/version_manager/application/tutor_plugin_uninstaller.py b/tvm/version_manager/application/tutor_plugin_uninstaller.py index 36335de..496c6b8 100644 --- a/tvm/version_manager/application/tutor_plugin_uninstaller.py +++ b/tvm/version_manager/application/tutor_plugin_uninstaller.py @@ -1,4 +1,7 @@ """Tutor plugin uninstaller application.""" +from typing import List + +from tvm.version_manager.domain.tutor_version import TutorVersion from tvm.version_manager.domain.version_manager_repository import VersionManagerRepository @@ -9,6 +12,8 @@ def __init__(self, repository: VersionManagerRepository) -> None: """init.""" self.repository = repository - def __call__(self, options) -> None: + def __call__(self, options: List, version: str = None) -> None: """call.""" - self.repository.uninstall_plugin(options) + if version: + version = TutorVersion(version=version) + self.repository.uninstall_plugin(options=options, version=version) diff --git a/tvm/version_manager/domain/version_manager_repository.py b/tvm/version_manager/domain/version_manager_repository.py index 065736c..c1f1be9 100644 --- a/tvm/version_manager/domain/version_manager_repository.py +++ b/tvm/version_manager/domain/version_manager_repository.py @@ -44,9 +44,9 @@ def version_is_installed(version: str) -> None: """Version is installed method.""" @abstractmethod - def install_plugin(self, options: List) -> None: + def install_plugin(self, options: List, version: TutorVersion = None) -> None: """Install tutor plugin.""" @abstractmethod - def uninstall_plugin(self, options: List) -> None: + def uninstall_plugin(self, options: List, version: TutorVersion = None) -> None: """Uninstall tutor plugin.""" diff --git a/tvm/version_manager/infrastructure/version_manager_git_repository.py b/tvm/version_manager/infrastructure/version_manager_git_repository.py index b72c7be..2483fe1 100644 --- a/tvm/version_manager/infrastructure/version_manager_git_repository.py +++ b/tvm/version_manager/infrastructure/version_manager_git_repository.py @@ -165,11 +165,14 @@ def create_virtualenv(self, version: TutorVersion) -> None: executable="/bin/bash", ) - def run_command_in_virtualenv(self, options: List): + def run_command_in_virtualenv(self, options: List, version: TutorVersion = None): """Use virtual environment to run command.""" + if not version: + version = self.current_version(self.TVM_PATH) + try: subprocess.run( - f"source {self.TVM_PATH}/venv/bin/activate;" f'pip {" ".join(options)}', + f"source {self.TVM_PATH}/{version}/venv/bin/activate;" f'pip {" ".join(options)}', shell=True, check=True, executable="/bin/bash", @@ -177,11 +180,11 @@ def run_command_in_virtualenv(self, options: List): except subprocess.CalledProcessError as ex: raise Exception(f"Error running venv commands: {ex.output}") from ex - def install_plugin(self, options: List) -> None: + def install_plugin(self, options: List, version: TutorVersion = None) -> None: """Install plugin for virtual environment.""" self.run_command_in_virtualenv(options) - def uninstall_plugin(self, options: List) -> None: + def uninstall_plugin(self, options: List, version: TutorVersion = None) -> None: """Uninstall plugin for virtual environment.""" self.run_command_in_virtualenv(options) From 37b50223fb92277092a2b9bf391eb20c3aeaa9e4 Mon Sep 17 00:00:00 2001 From: Juan David Buitrago Date: Wed, 27 Jul 2022 12:19:17 -0500 Subject: [PATCH 03/13] refactor: improve project init command architecture --- tvm/cli.py | 33 +----------- ...oject_init.py => tutor_project_creator.py} | 10 ++-- .../domain/environment_manager_repository.py | 6 +-- .../environment_manager_git_repository.py | 50 +++++++++++-------- 4 files changed, 40 insertions(+), 59 deletions(-) rename tvm/environment_manager/application/{tutor_project_init.py => tutor_project_creator.py} (61%) diff --git a/tvm/cli.py b/tvm/cli.py index f7fb810..47ab549 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -4,7 +4,6 @@ import pathlib import random import re -import shutil import stat import string import subprocess @@ -19,10 +18,9 @@ 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_init import TutorProjectInit +from tvm.environment_manager.application.tutor_project_creator import TutorProjectCreator from tvm.environment_manager.infrastructure.environment_manager_git_repository import EnvironmentManagerGitRepository from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE -from tvm.templates.tvm_activate import TVM_ACTIVATE_SCRIPT from tvm.version_manager.application.tutor_plugin_installer import TutorPluginInstaller from tvm.version_manager.application.tutor_plugin_uninstaller import TutorPluginUninstaller from tvm.version_manager.application.tutor_version_enabler import TutorVersionEnabler @@ -133,20 +131,6 @@ def setup_tvm(): pass -# def setup_version_virtualenv(version=None) -> None: -# """Create virtualenv and install tutor cloned.""" -# # Create virtualenv -# subprocess.run(f'cd {TVM_PATH}/{version}; virtualenv venv', -# shell=True, check=True, -# executable='/bin/bash') - -# # Install tutor -# subprocess.run(f'source {TVM_PATH}/{version}/venv/bin/activate;' -# f'pip install -e {TVM_PATH}/{version}/overhangio-tutor-*/', -# shell=True, check=True, -# executable='/bin/bash') - - @click.command(name="list") @click.option("-l", "--limit", default=10, help="number of `latest versions` to list") def list_versions(limit: int): @@ -431,19 +415,6 @@ def projects() -> None: """Hold the main wrapper for the `tvm project` command.""" -# def create_project(project: str) -> None: -# """Duplicate the version directory and rename it.""" -# if not os.path.exists(f"{TVM_PATH}/{project}"): -# tutor_version = project.split("@")[0] -# tutor_version_folder = f"{TVM_PATH}/{tutor_version}" - -# tvm_project = f"{TVM_PATH}/{project}" -# copy_tree(tutor_version_folder, tvm_project) - -# shutil.rmtree(f"{tvm_project}/venv") -# setup_version_virtualenv(project) - - @click.command(name="init") @click.argument('name', required=False) @click.argument('version', required=False) @@ -468,7 +439,7 @@ def init(name: str = None, version: str = None): pathlib.Path(f"{tvm_environment}/bin").mkdir(parents=True, exist_ok=True) repository = EnvironmentManagerGitRepository(project_path=f"{tvm_project_folder}") - initialize = TutorProjectInit(repository=repository) + initialize = TutorProjectCreator(repository=repository) initialize(version) else: raise click.UsageError('There is already a project initiated.') from IndexError diff --git a/tvm/environment_manager/application/tutor_project_init.py b/tvm/environment_manager/application/tutor_project_creator.py similarity index 61% rename from tvm/environment_manager/application/tutor_project_init.py rename to tvm/environment_manager/application/tutor_project_creator.py index f45cb1d..cdde18b 100644 --- a/tvm/environment_manager/application/tutor_project_init.py +++ b/tvm/environment_manager/application/tutor_project_creator.py @@ -1,9 +1,11 @@ """Tutor project initialize.""" -from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository +from tvm.environment_manager.domain.environment_manager_repository import ( + EnvironmentManagerRepository, +) -class TutorProjectInit: - """Tutor project init for environment manager.""" +class TutorProjectCreator: + """Tutor project initialize for environment manager.""" def __init__(self, repository: EnvironmentManagerRepository) -> None: """init.""" @@ -11,4 +13,4 @@ def __init__(self, repository: EnvironmentManagerRepository) -> None: def __call__(self, version) -> None: """call.""" - self.repository.project_init(version) + self.repository.project_creator(version) diff --git a/tvm/environment_manager/domain/environment_manager_repository.py b/tvm/environment_manager/domain/environment_manager_repository.py index 1c2653d..e7e6570 100644 --- a/tvm/environment_manager/domain/environment_manager_repository.py +++ b/tvm/environment_manager/domain/environment_manager_repository.py @@ -1,8 +1,6 @@ """Environment manager repository methods.""" from abc import ABC, abstractmethod -from typing import List, Optional - -from tvm.version_manager.domain.tutor_version import TutorVersion +from typing import List class EnvironmentManagerRepository(ABC): @@ -10,7 +8,7 @@ class EnvironmentManagerRepository(ABC): @staticmethod @abstractmethod - def project_init(self, version) -> None: + def project_creator(self, version) -> None: """Tutor Project Init to environment manager.""" @abstractmethod diff --git a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py index 8f489d3..28250b6 100644 --- a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py +++ b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py @@ -8,31 +8,34 @@ import subprocess from typing import List -from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository +from tvm.environment_manager.domain.environment_manager_repository import ( + EnvironmentManagerRepository, +) from tvm.environment_manager.domain.project_name import ProjectName from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE from tvm.templates.tvm_activate import TVM_ACTIVATE_SCRIPT -TVM_PATH = pathlib.Path.home() / '.tvm' +TVM_PATH = pathlib.Path.home() / ".tvm" class EnvironmentManagerGitRepository(EnvironmentManagerRepository): """Principals commands to manage TVM.""" + def __init__(self, project_path: str) -> None: self.PROJECT_PATH = project_path self.TVM_ENVIRONMENT = f"{project_path}/.tvm" - def project_init(self, version: str) -> None: + def project_creator(self, version: str) -> None: """Initialize tutor project.""" data = { "version": f"{version}", "tutor_root": f"{self.PROJECT_PATH}", - "tutor_plugins_root": f"{self.PROJECT_PATH}/plugins" + "tutor_plugins_root": f"{self.PROJECT_PATH}/plugins", } context = { - 'version': data.get('version', None), - 'tvm': f"{TVM_PATH}", + "version": data.get("version", None), + "tvm": f"{TVM_PATH}", } self.create_config_json(data) @@ -41,27 +44,27 @@ def project_init(self, version: str) -> None: self.create_project(version) def current_version(self) -> ProjectName: - info_file_path = f'{self.TVM_ENVIRONMENT}/config.json' - with open(info_file_path, 'r', encoding='utf-8') as info_file: + info_file_path = f"{self.TVM_ENVIRONMENT}/config.json" + with open(info_file_path, "r", encoding="utf-8") as info_file: data = json.load(info_file) - return ProjectName(data.get('version')) + return ProjectName(data.get("version")) def create_config_json(self, data: dict) -> None: """Create configuration json file""" tvm_project_config_file = f"{self.TVM_ENVIRONMENT}/config.json" - with open(tvm_project_config_file, 'w', encoding='utf-8') as info_file: + with open(tvm_project_config_file, "w", encoding="utf-8") as info_file: json.dump(data, info_file, indent=4) def create_active_script(self, context: dict) -> None: """Create active script file.""" activate_script = f"{self.TVM_ENVIRONMENT}/bin/activate" - with open(activate_script, 'w', encoding='utf-8') as activate_file: + with open(activate_script, "w", encoding="utf-8") as activate_file: activate_file.write(TVM_ACTIVATE_SCRIPT.render(**context)) def create_tutor_switcher(self, context: dict) -> None: """Create tutor switcher file.""" tutor_file = f"{self.TVM_ENVIRONMENT}/bin/tutor" - with open(tutor_file, 'w', encoding='utf-8') as switcher_file: + with open(tutor_file, "w", encoding="utf-8") as switcher_file: switcher_file.write(TUTOR_SWITCHER_TEMPLATE.render(**context)) # set execute permissions os.chmod(tutor_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH) @@ -82,15 +85,21 @@ def create_project(self, project: str) -> None: def setup_version_virtualenv(version=None) -> None: """Create virtualenv and install tutor cloned.""" # Create virtualenv - subprocess.run(f'cd {TVM_PATH}/{version}; virtualenv venv', - shell=True, check=True, - executable='/bin/bash') + subprocess.run( + f"cd {TVM_PATH}/{version}; virtualenv venv", + shell=True, + check=True, + executable="/bin/bash", + ) # Install tutor - subprocess.run(f'source {TVM_PATH}/{version}/venv/bin/activate;' - f'pip install -e {TVM_PATH}/{version}/overhangio-tutor-*/', - shell=True, check=True, - executable='/bin/bash') + subprocess.run( + f"source {TVM_PATH}/{version}/venv/bin/activate;" + f"pip install -e {TVM_PATH}/{version}/overhangio-tutor-*/", + shell=True, + check=True, + executable="/bin/bash", + ) def run_command_in_virtualenv(self, options: List, name: ProjectName = None): """Use virtual environment to run command.""" @@ -99,7 +108,8 @@ def run_command_in_virtualenv(self, options: List, name: ProjectName = None): try: subprocess.run( - f"source {TVM_PATH}/{name}/venv/bin/activate;" f'pip {" ".join(options)}', + f"source {TVM_PATH}/{name}/venv/bin/activate;" + f'pip {" ".join(options)}', shell=True, check=True, executable="/bin/bash", From 1eea14e72385df2531b3b3d36e5968e10f9b9812 Mon Sep 17 00:00:00 2001 From: Alejandro Cardenas Date: Wed, 27 Jul 2022 11:37:39 -0500 Subject: [PATCH 04/13] feat: create project folder --- tvm/cli.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tvm/cli.py b/tvm/cli.py index 47ab549..1e4e801 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -426,13 +426,13 @@ def init(name: str = None, version: str = None): if not version_is_installed(version): raise click.UsageError(f'Could not find target: {version}') - if not name: - letters = string.ascii_letters - name = ''.join(random.choice(letters) for i in range(10)) + if name: + tvm_project_folder = pathlib.Path().resolve() / name + else: + name = f"{pathlib.Path().resolve()}".split("/")[-1] + tvm_project_folder = pathlib.Path().resolve() version = f"{version}@{name}" - - tvm_project_folder = pathlib.Path().resolve() tvm_environment = tvm_project_folder / '.tvm' if not os.path.exists(tvm_environment): From b95a9c7a39daa8ab441fe0155fb992fca8a05320 Mon Sep 17 00:00:00 2001 From: Alejandro Cardenas Date: Wed, 27 Jul 2022 12:12:13 -0500 Subject: [PATCH 05/13] fix: improve error message when version isnt installed --- tvm/cli.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tvm/cli.py b/tvm/cli.py index 1e4e801..7e3833a 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -330,8 +330,9 @@ def use(version: str): enabler(version=version) except TutorVersionFormatError as format_err: raise click.UsageError(f"{format_err}") - except Exception as error: - raise click.UsageError(f'The version {version} is not installed.') from error + except Exception: + raise click.ClickException(f'The version {version} is not installed you should install it before using it.\n' + f'You could run the command `tvm install {version}` to install it.') def get_env_by_tutor_version(version): From 7300c2d54dd1cfa87f250cf72f1b780f8a286801 Mon Sep 17 00:00:00 2001 From: Alejandro Cardenas Date: Wed, 27 Jul 2022 12:56:36 -0500 Subject: [PATCH 06/13] fix: solve tvm list issue --- tvm/cli.py | 60 +++++++----------------------------------------------- 1 file changed, 7 insertions(+), 53 deletions(-) diff --git a/tvm/cli.py b/tvm/cli.py index 7e3833a..96b0168 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -142,13 +142,15 @@ def list_versions(limit: int): repository = VersionManagerGitRepository() lister = TutorVersionLister(repository=repository) version_names = lister(limit=limit) + local_versions = repository.local_versions(f"{TVM_PATH}") + version_names = list(set(version_names + local_versions)) version_names = sorted(version_names, reverse=True, key=LooseVersion) - local_versions = repository.local_versions(TVM_PATH) - global_active = repository.current_version(TVM_PATH) + global_active = repository.current_version(f"{TVM_PATH}") project_version = None if "TVM_PROJECT_ENV" in os.environ: - project_version = get_project_version(os.environ.get("TVM_PROJECT_ENV")) + repository = EnvironmentManagerGitRepository(project_path=os.environ.get("TVM_PROJECT_ENV")) + project_version = repository.current_version() for name in version_names: color = "yellow" if name in local_versions: @@ -163,47 +165,6 @@ def list_versions(limit: int): name = f"{name} (active)" click.echo(click.style(name, fg=color)) - -@click.command(name="list") -@click.option('-l', '--limit', default=10, help='number of `latest versions` to list') -def list_versions_backup(limit: int): - """ - Get all the versions from github. - - Print and mark the both the installed ones and the current. - """ - # from github - api_info = requests.get(f'{VERSIONS_URL}?per_page={limit}').json() - api_versions = [x.get('name') for x in api_info] - - # from the local .tvm - local_versions = get_local_versions() - - click.echo(f'Listing the latest {limit} versions of tutor') - version_names = list(set(api_versions + local_versions)) - version_names = sorted(version_names, reverse=True, key=LooseVersion) - - project_version = None - if "TVM_PROJECT_ENV" in os.environ: - project_version = get_project_version(os.environ.get("TVM_PROJECT_ENV")) - - global_active = get_active_version() - - for name in version_names: - color = 'yellow' - if name in local_versions: - color = 'green' - if name == global_active: - if project_version: - color = 'blue' - name = f'{name} (global)' - else: - name = f'{name} (active)' - if project_version and project_version == name: - name = f'{name} (active)' - click.echo(click.style(name, fg=color)) - - @click.command(name="install") @click.argument('version', required=True) def install(version: str): @@ -251,14 +212,6 @@ def get_active_version() -> str: return 'No active version installed' -def get_project_version(tvm_project_path) -> str: - """Read the current active version from the json/bash switcher.""" - info_file_path = f'{tvm_project_path}/config.json' - with open(info_file_path, 'r', encoding='utf-8') as info_file: - data = json.load(info_file) - return data.get('version') - - def get_current_info(file: str = None) -> Optional[dict]: """Get the JSON data from the config file.""" if not file: @@ -383,7 +336,8 @@ def list_plugins(): """List installed plugins by tutor version.""" project_version = None if "TVM_PROJECT_ENV" in os.environ: - project_version = get_project_version(os.environ.get("TVM_PROJECT_ENV")) + repository = EnvironmentManagerGitRepository(project_path=os.environ.get("TVM_PROJECT_ENV")) + project_version = repository.current_version() global_active = get_active_version() From 6993f8f80eeacc9ef589daa96b3a51058e19c086 Mon Sep 17 00:00:00 2001 From: Alejandro Cardenas Date: Wed, 27 Jul 2022 13:26:37 -0500 Subject: [PATCH 07/13] feat: make the coloring scheme much clear to list commands --- tvm/cli.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/tvm/cli.py b/tvm/cli.py index 96b0168..d5cf5ad 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -152,15 +152,11 @@ def list_versions(limit: int): repository = EnvironmentManagerGitRepository(project_path=os.environ.get("TVM_PROJECT_ENV")) project_version = repository.current_version() for name in version_names: - color = "yellow" + color = "white" if name in local_versions: color = "green" - if name == global_active: - if project_version: - color = "blue" - name = f"{name} (global)" - else: - name = f"{name} (active)" + if name == global_active and not project_version: + name = f"{name} (active)" if project_version and project_version == name: name = f"{name} (active)" click.echo(click.style(name, fg=color)) @@ -345,11 +341,8 @@ def list_plugins(): for version in local_versions: version = str(version) - if version == global_active: - if project_version: - click.echo(click.style(f"{version} (global)", fg='blue')) - else: - click.echo(click.style(f"{version} (active)", fg='green')) + if version == global_active and not project_version: + click.echo(click.style(f"{version} (active)", fg='green')) elif project_version and version == project_version: click.echo(click.style(f"{version} (active)", fg='green')) else: From eaf29b5caee50c9c050899c844fa0f95efa3711c Mon Sep 17 00:00:00 2001 From: Alejandro Cardenas Date: Wed, 27 Jul 2022 14:17:04 -0500 Subject: [PATCH 08/13] feat: add logger to explain why we need sudo permissions --- tvm/cli.py | 40 ++++++++----------- tvm/settings.py | 11 +++++ tvm/share/domain/client_logger_repository.py | 9 +++++ .../click_client_logger_repository.py | 9 +++++ .../version_manager_git_repository.py | 9 ++++- 5 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 tvm/settings.py create mode 100644 tvm/share/domain/client_logger_repository.py create mode 100644 tvm/share/infrastructure/click_client_logger_repository.py diff --git a/tvm/cli.py b/tvm/cli.py index d5cf5ad..eb4dcc6 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -19,7 +19,7 @@ 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.infrastructure.environment_manager_git_repository import EnvironmentManagerGitRepository +from tvm.settings import version_manager, environment_manager from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE from tvm.version_manager.application.tutor_plugin_installer import TutorPluginInstaller from tvm.version_manager.application.tutor_plugin_uninstaller import TutorPluginUninstaller @@ -30,7 +30,6 @@ from tvm.version_manager.application.tutor_vesion_lister import TutorVersionLister from tvm.version_manager.domain.tutor_version_format_error import TutorVersionFormatError from tvm.version_manager.domain.tutor_version_is_not_installed import TutorVersionIsNotInstalled -from tvm.version_manager.infrastructure.version_manager_git_repository import VersionManagerGitRepository VERSIONS_URL = "https://api.github.com/repos/overhangio/tutor/tags" TVM_PATH = pathlib.Path.home() / '.tvm' @@ -139,17 +138,16 @@ def list_versions(limit: int): Print and mark the both the installed ones and the current. """ - repository = VersionManagerGitRepository() - lister = TutorVersionLister(repository=repository) + lister = TutorVersionLister(repository=version_manager) version_names = lister(limit=limit) - local_versions = repository.local_versions(f"{TVM_PATH}") + local_versions = version_manager.local_versions(f"{TVM_PATH}") version_names = list(set(version_names + local_versions)) version_names = sorted(version_names, reverse=True, key=LooseVersion) - global_active = repository.current_version(f"{TVM_PATH}") + global_active = version_manager.current_version(f"{TVM_PATH}") project_version = None if "TVM_PROJECT_ENV" in os.environ: - repository = EnvironmentManagerGitRepository(project_path=os.environ.get("TVM_PROJECT_ENV")) + repository = environment_manager(project_path=os.environ.get("TVM_PROJECT_ENV")) project_version = repository.current_version() for name in version_names: color = "white" @@ -161,12 +159,12 @@ def list_versions(limit: int): name = f"{name} (active)" click.echo(click.style(name, fg=color)) + @click.command(name="install") @click.argument('version', required=True) def install(version: str): """Install the given VERSION of tutor in the .tvm directory.""" - repository = VersionManagerGitRepository() - finder = TutorVersionFinder(repository=repository) + finder = TutorVersionFinder(repository=version_manager) tutor_version = finder(version=version) try: if not tutor_version: @@ -176,7 +174,7 @@ def install(version: str): except Exception as err: raise click.UsageError(f'Could not find target: {version}') from err - installer = TutorVersionInstaller(repository=repository) + installer = TutorVersionInstaller(repository=version_manager) installer(version=tutor_version) @@ -184,8 +182,7 @@ def install(version: str): @click.argument('version', required=True) def uninstall(version: str): """Install the given VERSION of tutor in the .tvm directory.""" - repository = VersionManagerGitRepository() - uninstaller = TutorVersionUninstaller(repository=repository) + uninstaller = TutorVersionUninstaller(repository=version_manager) try: uninstaller(version=version) click.echo(click.style( @@ -271,10 +268,9 @@ def set_switch_from_file(file: str = None) -> None: @click.argument('version', required=True) def use(version: str): """Configure the path to use VERSION.""" - repository = VersionManagerGitRepository() - enabler = TutorVersionEnabler(repository=repository) + enabler = TutorVersionEnabler(repository=version_manager) try: - if not VersionManagerGitRepository.version_is_installed(version=version): + if not version_manager.version_is_installed(version=version): raise Exception enabler(version=version) except TutorVersionFormatError as format_err: @@ -332,7 +328,7 @@ def list_plugins(): """List installed plugins by tutor version.""" project_version = None if "TVM_PROJECT_ENV" in os.environ: - repository = EnvironmentManagerGitRepository(project_path=os.environ.get("TVM_PROJECT_ENV")) + repository = environment_manager(project_path=os.environ.get("TVM_PROJECT_ENV")) project_version = repository.current_version() global_active = get_active_version() @@ -386,7 +382,7 @@ def init(name: str = None, version: str = None): if not os.path.exists(tvm_environment): pathlib.Path(f"{tvm_environment}/bin").mkdir(parents=True, exist_ok=True) - repository = EnvironmentManagerGitRepository(project_path=f"{tvm_project_folder}") + repository = environment_manager(project_path=f"{tvm_project_folder}") initialize = TutorProjectCreator(repository=repository) initialize(version) else: @@ -401,11 +397,10 @@ def install_plugin(options): options.insert(0, "install") if "TVM_PROJECT_ENV" in os.environ: - repository = EnvironmentManagerGitRepository(os.environ.get("TVM_PROJECT_ENV")) + repository = environment_manager(os.environ.get("TVM_PROJECT_ENV")) installer = PluginInstaller(repository=repository) else: - repository = VersionManagerGitRepository() - installer = TutorPluginInstaller(repository=repository) + installer = TutorPluginInstaller(repository=version_manager) installer(options) @@ -417,11 +412,10 @@ def uninstall_plugin(options): options.insert(0, "uninstall") options.append("-y") if "TVM_PROJECT_ENV" in os.environ: - repository = EnvironmentManagerGitRepository(os.environ.get("TVM_PROJECT_ENV")) + repository = environment_manager(os.environ.get("TVM_PROJECT_ENV")) uninstaller = PluginUninstaller(repository=repository) else: - repository = VersionManagerGitRepository() - uninstaller = TutorPluginUninstaller(repository=repository) + uninstaller = TutorPluginUninstaller(repository=version_manager) uninstaller(options) diff --git a/tvm/settings.py b/tvm/settings.py new file mode 100644 index 0000000..dfe6d1e --- /dev/null +++ b/tvm/settings.py @@ -0,0 +1,11 @@ +from tvm.environment_manager.infrastructure.environment_manager_git_repository import EnvironmentManagerGitRepository +from tvm.share.infrastructure.click_client_logger_repository import ClickClientLoggerRepository +from tvm.version_manager.infrastructure.version_manager_git_repository import VersionManagerGitRepository + +logger = ClickClientLoggerRepository() +version_manager = VersionManagerGitRepository(logger=logger) + + +def environment_manager(project_path: str) -> EnvironmentManagerGitRepository: + return EnvironmentManagerGitRepository(project_path=project_path) + diff --git a/tvm/share/domain/client_logger_repository.py b/tvm/share/domain/client_logger_repository.py new file mode 100644 index 0000000..ba1cfcc --- /dev/null +++ b/tvm/share/domain/client_logger_repository.py @@ -0,0 +1,9 @@ +import abc +from abc import abstractmethod + + +class ClientLoggerRepository(abc.ABC): + + @abstractmethod + def echo(self, message) -> None: + pass diff --git a/tvm/share/infrastructure/click_client_logger_repository.py b/tvm/share/infrastructure/click_client_logger_repository.py new file mode 100644 index 0000000..19003ef --- /dev/null +++ b/tvm/share/infrastructure/click_client_logger_repository.py @@ -0,0 +1,9 @@ +import click + +from tvm.share.domain.client_logger_repository import ClientLoggerRepository + + +class ClickClientLoggerRepository(ClientLoggerRepository): + + def echo(self, message) -> None: + click.echo(click.style(message, fg="yellow")) diff --git a/tvm/version_manager/infrastructure/version_manager_git_repository.py b/tvm/version_manager/infrastructure/version_manager_git_repository.py index 2483fe1..8ebf736 100644 --- a/tvm/version_manager/infrastructure/version_manager_git_repository.py +++ b/tvm/version_manager/infrastructure/version_manager_git_repository.py @@ -10,6 +10,7 @@ import requests +from tvm.share.domain.client_logger_repository import ClientLoggerRepository from tvm.version_manager.domain.tutor_version import TutorVersion from tvm.version_manager.domain.tutor_version_is_not_installed import TutorVersionIsNotInstalled from tvm.version_manager.domain.version_manager_repository import VersionManagerRepository @@ -24,8 +25,9 @@ class VersionManagerGitRepository(VersionManagerRepository): ZIPPBALL_URL = "https://api.github.com/repos/overhangio/tutor/zipball/refs/tags/" TVM_PATH = pathlib.Path.home() / ".tvm" - def __init__(self) -> None: + def __init__(self, logger: ClientLoggerRepository) -> None: """init.""" + self.logger = logger self.setup() def setup(self): @@ -47,6 +49,11 @@ def setup(self): try: os.symlink(f"{self.TVM_PATH}/tutor_switcher", "/usr/local/bin/tutor") except PermissionError: + self.logger.echo( + "Don't Worry, TVM just needs sudo permissions to create the tutor_switcher's symlink" + "in /usr/local/bin/tutor.\n" + "You can find more information about it in our docs." + ) subprocess.call( [ "sudo", From 621db1afbe18b3caf1561b5383d2d5b22f0ce08f Mon Sep 17 00:00:00 2001 From: Alejandro Cardenas Date: Wed, 27 Jul 2022 16:22:36 -0500 Subject: [PATCH 09/13] feat: change tvm list limit --- requirements/base.in | 1 + requirements/base.txt | 50 +++++--- requirements/dev.in | 2 + requirements/dev.txt | 115 ++++++++++++------ requirements/pip-tools.txt | 22 ++-- requirements/pip.txt | 8 +- tvm/cli.py | 4 +- .../version_manager_git_repository.py | 5 +- 8 files changed, 143 insertions(+), 64 deletions(-) diff --git a/requirements/base.in b/requirements/base.in index c028714..1584702 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -6,3 +6,4 @@ requests jinja2 pyyaml GitPython +requests-cache diff --git a/requirements/base.txt b/requirements/base.txt index dbc1abd..2a56af9 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,30 +1,52 @@ # -# This file is autogenerated by pip-compile with python 3.8 +# This file is autogenerated by pip-compile with python 3.10 # To update, run: # # make upgrade # -certifi==2021.5.30 +appdirs==1.4.4 + # via requests-cache +attrs==21.4.0 + # via + # cattrs + # requests-cache +cattrs==22.1.0 + # via requests-cache +certifi==2022.6.15 # via requests -charset-normalizer==2.0.4 +charset-normalizer==2.1.0 # via requests -click==8.0.1 +click==8.1.3 # via -r requirements/base.in -gitdb==4.0.7 +exceptiongroup==1.0.0rc8 + # via + # cattrs + # requests-cache +gitdb==4.0.9 # via gitpython -gitpython==3.1.18 +gitpython==3.1.27 # via -r requirements/base.in -idna==3.2 +idna==3.3 # via requests -jinja2==3.0.1 +jinja2==3.1.2 # via -r requirements/base.in -markupsafe==2.0.1 +markupsafe==2.1.1 # via jinja2 -pyyaml==5.4.1 +pyyaml==6.0 # via -r requirements/base.in -requests==2.26.0 +requests==2.28.1 + # via + # -r requirements/base.in + # requests-cache +requests-cache==0.9.5 # via -r requirements/base.in -smmap==4.0.0 +six==1.16.0 + # via url-normalize +smmap==5.0.0 # via gitdb -urllib3==1.26.6 - # via requests +url-normalize==1.4.3 + # via requests-cache +urllib3==1.26.11 + # via + # requests + # requests-cache diff --git a/requirements/dev.in b/requirements/dev.in index 7b09914..aa7a336 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -9,3 +9,5 @@ pydocstyle coverage pytest pudb +requests +requests-cache diff --git a/requirements/dev.txt b/requirements/dev.txt index cd49377..2b96859 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,96 +1,139 @@ # -# This file is autogenerated by pip-compile with python 3.8 +# This file is autogenerated by pip-compile with python 3.10 # To update, run: # # make upgrade # -astroid==2.7.3 +appdirs==1.4.4 + # via + # -r requirements/base.txt + # requests-cache +astroid==2.11.7 # via pylint -attrs==21.2.0 - # via pytest -certifi==2021.5.30 +attrs==21.4.0 + # via + # -r requirements/base.txt + # cattrs + # pytest + # requests-cache +cattrs==22.1.0 + # via + # -r requirements/base.txt + # requests-cache +certifi==2022.6.15 # via # -r requirements/base.txt # requests -charset-normalizer==2.0.4 +charset-normalizer==2.1.0 # via # -r requirements/base.txt # requests -click==8.0.1 +click==8.1.3 # via -r requirements/base.txt -coverage==5.5 +coverage==6.4.2 # via -r requirements/dev.in -gitdb==4.0.7 +dill==0.3.5.1 + # via pylint +exceptiongroup==1.0.0rc8 + # via + # -r requirements/base.txt + # cattrs + # requests-cache +gitdb==4.0.9 # via # -r requirements/base.txt # gitpython -gitpython==3.1.18 +gitpython==3.1.27 # via -r requirements/base.txt -idna==3.2 +idna==3.3 # via # -r requirements/base.txt # requests iniconfig==1.1.1 # via pytest -isort==5.9.3 +isort==5.10.1 # via pylint -jedi==0.18.0 +jedi==0.18.1 # via pudb -jinja2==3.0.1 +jinja2==3.1.2 # via -r requirements/base.txt -lazy-object-proxy==1.6.0 +lazy-object-proxy==1.7.1 # via astroid -markupsafe==2.0.1 +markupsafe==2.1.1 # via # -r requirements/base.txt # jinja2 -mccabe==0.6.1 +mccabe==0.7.0 # via pylint -packaging==21.0 - # via pytest -parso==0.8.2 +packaging==21.3 + # via + # pudb + # pytest +parso==0.8.3 # via jedi -platformdirs==2.3.0 +platformdirs==2.5.2 # via pylint pluggy==1.0.0 # via pytest -pudb==2021.1 +pudb==2022.1.2 # via -r requirements/dev.in -py==1.10.0 +py==1.11.0 # via pytest -pycodestyle==2.7.0 +pycodestyle==2.8.0 # via -r requirements/dev.in pydocstyle==6.1.1 # via -r requirements/dev.in -pygments==2.10.0 +pygments==2.12.0 # via pudb -pylint==2.10.2 +pylint==2.14.5 # via -r requirements/dev.in -pyparsing==2.4.7 +pyparsing==3.0.9 # via packaging -pytest==6.2.5 +pytest==7.1.2 # via -r requirements/dev.in -pyyaml==5.4.1 - # via -r requirements/base.txt -requests==2.26.0 +pyyaml==6.0 # via -r requirements/base.txt -smmap==4.0.0 +requests==2.28.1 + # via + # -r requirements/base.txt + # -r requirements/dev.in + # requests-cache +requests-cache==0.9.5 + # via + # -r requirements/base.txt + # -r requirements/dev.in +six==1.16.0 + # via + # -r requirements/base.txt + # url-normalize +smmap==5.0.0 # via # -r requirements/base.txt # gitdb -snowballstemmer==2.1.0 +snowballstemmer==2.2.0 # via pydocstyle -toml==0.10.2 +tomli==2.0.1 # via # pylint # pytest -urllib3==1.26.6 +tomlkit==0.11.1 + # via pylint +url-normalize==1.4.3 + # via + # -r requirements/base.txt + # requests-cache +urllib3==1.26.11 # via # -r requirements/base.txt # requests + # requests-cache urwid==2.1.2 + # via + # pudb + # urwid-readline +urwid-readline==0.13 # via pudb -wrapt==1.12.1 +wrapt==1.14.1 # via astroid # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index 3a172bb..f81aeed 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -1,18 +1,26 @@ # -# This file is autogenerated by pip-compile with python 3.8 +# This file is autogenerated by pip-compile with python 3.10 # To update, run: # # make upgrade # -click==8.0.1 +build==0.8.0 # via pip-tools -pep517==0.11.0 +click==8.1.3 # via pip-tools -pip-tools==6.2.0 +packaging==21.3 + # via build +pep517==0.12.0 + # via build +pip-tools==6.8.0 # via -r requirements/pip-tools.in -tomli==1.2.1 - # via pep517 -wheel==0.37.0 +pyparsing==3.0.9 + # via packaging +tomli==2.0.1 + # via + # build + # pep517 +wheel==0.37.1 # via pip-tools # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/pip.txt b/requirements/pip.txt index 36c04ed..ae45351 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -1,14 +1,14 @@ # -# This file is autogenerated by pip-compile with python 3.8 +# This file is autogenerated by pip-compile with python 3.10 # To update, run: # # make upgrade # -wheel==0.37.0 +wheel==0.37.1 # via -r requirements/pip.in # The following packages are considered to be unsafe in a requirements file: -pip==21.2.4 +pip==22.2.1 # via -r requirements/pip.in -setuptools==57.4.0 +setuptools==63.2.0 # via -r requirements/pip.in diff --git a/tvm/cli.py b/tvm/cli.py index eb4dcc6..a6aeb96 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -131,7 +131,7 @@ def setup_tvm(): @click.command(name="list") -@click.option("-l", "--limit", default=10, help="number of `latest versions` to list") +@click.option("-l", "--limit", default=100, help="number of `latest versions` to list") def list_versions(limit: int): """ Get all the versions from github. @@ -142,7 +142,7 @@ def list_versions(limit: int): version_names = lister(limit=limit) local_versions = version_manager.local_versions(f"{TVM_PATH}") version_names = list(set(version_names + local_versions)) - version_names = sorted(version_names, reverse=True, key=LooseVersion) + version_names = sorted(version_names, reverse=False, key=LooseVersion) global_active = version_manager.current_version(f"{TVM_PATH}") project_version = None diff --git a/tvm/version_manager/infrastructure/version_manager_git_repository.py b/tvm/version_manager/infrastructure/version_manager_git_repository.py index 8ebf736..0d05085 100644 --- a/tvm/version_manager/infrastructure/version_manager_git_repository.py +++ b/tvm/version_manager/infrastructure/version_manager_git_repository.py @@ -9,6 +9,8 @@ from typing import List, Optional import requests +import requests_cache +from datetime import timedelta from tvm.share.domain.client_logger_repository import ClientLoggerRepository from tvm.version_manager.domain.tutor_version import TutorVersion @@ -105,8 +107,9 @@ def set_switcher(self) -> None: switcher_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH ) - def get_version_from_api(self, limit: int = 10): + def get_version_from_api(self, limit: int = 100): """Return api information form request.""" + requests_cache.install_cache('github_cache', expire_after=timedelta(days=1)) api_info = requests.get(f"{self.VERSIONS_URL}?per_page={limit}").json() return api_info From 58c48638705e077123ce1c136e56ccf53b86a223 Mon Sep 17 00:00:00 2001 From: Alejandro Cardenas Date: Wed, 27 Jul 2022 16:54:56 -0500 Subject: [PATCH 10/13] feat: add virtualenvs binaries to the path --- .../environment_manager_git_repository.py | 18 ++++-------------- tvm/templates/tvm_activate.py | 2 +- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py index 28250b6..0fd21aa 100644 --- a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py +++ b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py @@ -33,14 +33,9 @@ def project_creator(self, version: str) -> None: "tutor_root": f"{self.PROJECT_PATH}", "tutor_plugins_root": f"{self.PROJECT_PATH}/plugins", } - context = { - "version": data.get("version", None), - "tvm": f"{TVM_PATH}", - } self.create_config_json(data) self.create_active_script(data) - self.create_tutor_switcher(context) self.create_project(version) def current_version(self) -> ProjectName: @@ -57,18 +52,13 @@ def create_config_json(self, data: dict) -> None: def create_active_script(self, context: dict) -> None: """Create active script file.""" + context.update({ + "tvm_path": TVM_PATH + }) activate_script = f"{self.TVM_ENVIRONMENT}/bin/activate" with open(activate_script, "w", encoding="utf-8") as activate_file: activate_file.write(TVM_ACTIVATE_SCRIPT.render(**context)) - def create_tutor_switcher(self, context: dict) -> None: - """Create tutor switcher file.""" - tutor_file = f"{self.TVM_ENVIRONMENT}/bin/tutor" - with open(tutor_file, "w", encoding="utf-8") as switcher_file: - switcher_file.write(TUTOR_SWITCHER_TEMPLATE.render(**context)) - # set execute permissions - os.chmod(tutor_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH) - def create_project(self, project: str) -> None: """Duplicate the version directory and rename it.""" if not os.path.exists(f"{TVM_PATH}/{project}"): @@ -86,7 +76,7 @@ def setup_version_virtualenv(version=None) -> None: """Create virtualenv and install tutor cloned.""" # Create virtualenv subprocess.run( - f"cd {TVM_PATH}/{version}; virtualenv venv", + f"cd {TVM_PATH}/{version}; virtualenv --prompt {version} venv", shell=True, check=True, executable="/bin/bash", diff --git a/tvm/templates/tvm_activate.py b/tvm/templates/tvm_activate.py index e0080dc..bc6c154 100644 --- a/tvm/templates/tvm_activate.py +++ b/tvm/templates/tvm_activate.py @@ -54,7 +54,7 @@ TVM_PROJECT_ENV="{{ tutor_root }}" export TVM_PROJECT_ENV _TVM_OLD_VIRTUAL_PATH="$PATH" -PATH="$TVM_PROJECT_ENV/.tvm/bin:$PATH" +PATH="{{tvm_path}}/{{version}}/venv/bin:$PATH" export PATH if ! [ -z "${TUTOR_ROOT+_}" ] ; then _TVM_OLD_TUTOR_ROOT="$TUTOR_ROOT" From 610bc578308913159ac8a0bc700663b94421a695 Mon Sep 17 00:00:00 2001 From: Juan David Buitrago Date: Thu, 28 Jul 2022 06:55:06 -0500 Subject: [PATCH 11/13] test: add unit test for init command --- tests/environment_manager/__init__.py | 0 .../application/__init__.py | 0 .../application/test_plugin_installer.py | 32 +++++++++++++++++ .../application/test_plugin_uninstaller.py | 34 +++++++++++++++++++ .../application/test_tutor_project_creator.py | 34 +++++++++++++++++++ .../infrastructure/__init__.py | 0 ...nvironment_manager_in_memory_repository.py | 34 +++++++++++++++++++ .../version_manager_in_memory_repository.py | 4 +-- 8 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 tests/environment_manager/__init__.py create mode 100644 tests/environment_manager/application/__init__.py create mode 100644 tests/environment_manager/application/test_plugin_installer.py create mode 100644 tests/environment_manager/application/test_plugin_uninstaller.py create mode 100644 tests/environment_manager/application/test_tutor_project_creator.py create mode 100644 tests/environment_manager/infrastructure/__init__.py create mode 100644 tests/environment_manager/infrastructure/environment_manager_in_memory_repository.py diff --git a/tests/environment_manager/__init__.py b/tests/environment_manager/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/environment_manager/application/__init__.py b/tests/environment_manager/application/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/environment_manager/application/test_plugin_installer.py b/tests/environment_manager/application/test_plugin_installer.py new file mode 100644 index 0000000..669d24b --- /dev/null +++ b/tests/environment_manager/application/test_plugin_installer.py @@ -0,0 +1,32 @@ +import pytest + +from tests.environment_manager.infrastructure.environment_manager_in_memory_repository import ( + EnvironmentManagerInMemoryRepository, +) +from tvm.environment_manager.application.plugin_installer import PluginInstaller + + +def test_should_install_the_tutor_plugin(): + # Given + options = ["tutor-mfe"] + repository = EnvironmentManagerInMemoryRepository() + + # When + installer = PluginInstaller(repository=repository) + installer(options) + + # Then + assert options in repository.PLUGINS_INSTALLED + + +def test_should_fail_if_not_add_tutor_plugin(): + # Given + options = [] + repository = EnvironmentManagerInMemoryRepository() + + # When + installer = PluginInstaller(repository=repository) + + # Then + with pytest.raises(Exception) as format_err: + installer(options) diff --git a/tests/environment_manager/application/test_plugin_uninstaller.py b/tests/environment_manager/application/test_plugin_uninstaller.py new file mode 100644 index 0000000..2fa94ed --- /dev/null +++ b/tests/environment_manager/application/test_plugin_uninstaller.py @@ -0,0 +1,34 @@ +import pytest + +from tests.environment_manager.infrastructure.environment_manager_in_memory_repository import ( + EnvironmentManagerInMemoryRepository, +) +from tvm.environment_manager.application.plugin_uninstaller import ( + PluginUninstaller, +) + + +def test_should_uninstall_the_tutor_plugin(): + # Given + options = "codejail" + repository = EnvironmentManagerInMemoryRepository() + + # When + uninstaller = PluginUninstaller(repository=repository) + uninstaller(options) + + # Then + assert options not in repository.PLUGINS_INSTALLED + + +def test_should_fail_if_not_add_tutor_plugin(): + # Given + options = "tutor-mfe" + repository = EnvironmentManagerInMemoryRepository() + + # When + uninstaller = PluginUninstaller(repository=repository) + + # Then + with pytest.raises(Exception) as format_err: + uninstaller(options) diff --git a/tests/environment_manager/application/test_tutor_project_creator.py b/tests/environment_manager/application/test_tutor_project_creator.py new file mode 100644 index 0000000..36fce8c --- /dev/null +++ b/tests/environment_manager/application/test_tutor_project_creator.py @@ -0,0 +1,34 @@ +import pytest + +from tests.environment_manager.infrastructure.environment_manager_in_memory_repository import ( + EnvironmentManagerInMemoryRepository, +) +from tvm.environment_manager.application.tutor_project_creator import ( + TutorProjectCreator, +) + + +def test_should_create_tutor_project(): + # Given + project_name = "v13.1.0@testtutor" + repository = EnvironmentManagerInMemoryRepository() + + # When + inicialize = TutorProjectCreator(repository=repository) + inicialize(project_name) + + # Then + assert project_name in repository.PROJECT_NAME + + +def test_should_fail_if_project_name_exists(): + # Given + project_name = "v13.1.0@tutortest" + repository = EnvironmentManagerInMemoryRepository() + + # When + inicialize = TutorProjectCreator(repository=repository) + + # Then + with pytest.raises(Exception) as format_err: + inicialize(project_name) diff --git a/tests/environment_manager/infrastructure/__init__.py b/tests/environment_manager/infrastructure/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/environment_manager/infrastructure/environment_manager_in_memory_repository.py b/tests/environment_manager/infrastructure/environment_manager_in_memory_repository.py new file mode 100644 index 0000000..1c16b28 --- /dev/null +++ b/tests/environment_manager/infrastructure/environment_manager_in_memory_repository.py @@ -0,0 +1,34 @@ +from typing import List + +from tvm.environment_manager.domain.project_name import ProjectName +from tvm.environment_manager.domain.environment_manager_repository import ( + EnvironmentManagerRepository, +) + + +class EnvironmentManagerInMemoryRepository(EnvironmentManagerRepository): + PLUGINS_INSTALLED = ["codejail"] + PROJECT_NAME = ["v13.1.0@tutortest"] + + def project_creator(self, version: str) -> None: + if version not in self.PROJECT_NAME: + self.PROJECT_NAME.append(version) + else: + raise Exception('There is already a project initiated.') + + + def install_plugin(self, options: List) -> None: + if options: + self.PLUGINS_INSTALLED.append(options) + else: + raise Exception(f"Error running venv commands: None") + + def uninstall_plugin(self, options: List) -> None: + if options == self.PLUGINS_INSTALLED[0]: + self.PLUGINS_INSTALLED.clear() + else: + raise Exception(f"Error running venv commands: None") + + @staticmethod + def current_version(self) -> None: + pass diff --git a/tests/version_manager/infrastructure/version_manager_in_memory_repository.py b/tests/version_manager/infrastructure/version_manager_in_memory_repository.py index 2613cf0..1781ec3 100644 --- a/tests/version_manager/infrastructure/version_manager_in_memory_repository.py +++ b/tests/version_manager/infrastructure/version_manager_in_memory_repository.py @@ -41,13 +41,13 @@ def use_version(self, version: TutorVersion) -> None: def version_is_installed(version: str) -> None: pass - def install_plugin(self, options: List) -> None: + def install_plugin(self, options: List, version: str = None) -> None: if options: self.PLUGINS_INSTALLED.append(options) else: raise Exception(f"Error running venv commands: None") - def uninstall_plugin(self, options: List) -> None: + def uninstall_plugin(self, options: List, version: str = None) -> None: if options == self.PLUGINS_INSTALLED[0]: self.PLUGINS_INSTALLED.clear() else: From 934afb588b07242623f24c42187944dc0a488f9b Mon Sep 17 00:00:00 2001 From: Juan David Buitrago Date: Thu, 28 Jul 2022 13:13:24 -0500 Subject: [PATCH 12/13] style: complete docstring --- .../environment_manager_in_memory_repository.py | 1 - tests/test_cli.py | 2 +- tvm/cli.py | 5 +---- tvm/environment_manager/__init__.py | 2 +- tvm/environment_manager/application/__init__.py | 2 +- .../application/plugin_installer.py | 5 +++++ .../application/plugin_uninstaller.py | 5 +++++ .../application/tutor_project_creator.py | 4 +--- tvm/environment_manager/domain/__init__.py | 2 +- .../domain/environment_manager_repository.py | 7 +++---- tvm/environment_manager/domain/project_name.py | 2 ++ .../domain/project_name_format_error.py | 5 ++++- .../infrastructure/__init__.py | 2 +- .../environment_manager_git_repository.py | 17 ++++++++--------- tvm/settings.py | 3 ++- tvm/share/domain/client_logger_repository.py | 4 +++- .../click_client_logger_repository.py | 3 +++ .../version_manager_git_repository.py | 4 ++-- 18 files changed, 44 insertions(+), 31 deletions(-) diff --git a/tests/environment_manager/infrastructure/environment_manager_in_memory_repository.py b/tests/environment_manager/infrastructure/environment_manager_in_memory_repository.py index 1c16b28..041efa5 100644 --- a/tests/environment_manager/infrastructure/environment_manager_in_memory_repository.py +++ b/tests/environment_manager/infrastructure/environment_manager_in_memory_repository.py @@ -1,6 +1,5 @@ from typing import List -from tvm.environment_manager.domain.project_name import ProjectName from tvm.environment_manager.domain.environment_manager_repository import ( EnvironmentManagerRepository, ) diff --git a/tests/test_cli.py b/tests/test_cli.py index c2a009c..0afc632 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -3,7 +3,7 @@ from click.exceptions import BadParameter from click.testing import CliRunner -from tvm.cli import cli, install, uninstall, validate_version, projects +from tvm.cli import cli, install, validate_version, projects def test_should_return_all_tvm_cli_commands(): diff --git a/tvm/cli.py b/tvm/cli.py index a6aeb96..01e7e2f 100644 --- a/tvm/cli.py +++ b/tvm/cli.py @@ -2,24 +2,21 @@ import json import os import pathlib -import random import re import stat -import string import subprocess import sys from distutils.version import LooseVersion from typing import Optional import click -import requests 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.settings import version_manager, environment_manager +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 from tvm.version_manager.application.tutor_plugin_uninstaller import TutorPluginUninstaller diff --git a/tvm/environment_manager/__init__.py b/tvm/environment_manager/__init__.py index 6a76807..3de1a4f 100644 --- a/tvm/environment_manager/__init__.py +++ b/tvm/environment_manager/__init__.py @@ -1 +1 @@ -"""Environment manager init.""" \ No newline at end of file +"""Environment manager init.""" diff --git a/tvm/environment_manager/application/__init__.py b/tvm/environment_manager/application/__init__.py index 22270ef..ea16916 100644 --- a/tvm/environment_manager/application/__init__.py +++ b/tvm/environment_manager/application/__init__.py @@ -1 +1 @@ -"""Application init.""" \ No newline at end of file +"""Application init.""" diff --git a/tvm/environment_manager/application/plugin_installer.py b/tvm/environment_manager/application/plugin_installer.py index 38f7219..7164f85 100644 --- a/tvm/environment_manager/application/plugin_installer.py +++ b/tvm/environment_manager/application/plugin_installer.py @@ -1,11 +1,16 @@ +"""Tutor plugin installer application.""" from typing import List from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository class PluginInstaller: + """Tutor plugin installer for environment manager.""" + def __init__(self, repository: EnvironmentManagerRepository) -> None: + """init.""" self.repository = repository def __call__(self, options: List) -> None: + """call.""" self.repository.install_plugin(options=options) diff --git a/tvm/environment_manager/application/plugin_uninstaller.py b/tvm/environment_manager/application/plugin_uninstaller.py index c0d0660..0e0763a 100644 --- a/tvm/environment_manager/application/plugin_uninstaller.py +++ b/tvm/environment_manager/application/plugin_uninstaller.py @@ -1,11 +1,16 @@ +"""Tutor plugin uninstaller application.""" from typing import List from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository class PluginUninstaller: + """Tutor plugin uninstaller for environment manager.""" + def __init__(self, repository: EnvironmentManagerRepository) -> None: + """init.""" self.repository = repository def __call__(self, options: List) -> None: + """call.""" self.repository.uninstall_plugin(options=options) diff --git a/tvm/environment_manager/application/tutor_project_creator.py b/tvm/environment_manager/application/tutor_project_creator.py index cdde18b..e4b1bb6 100644 --- a/tvm/environment_manager/application/tutor_project_creator.py +++ b/tvm/environment_manager/application/tutor_project_creator.py @@ -1,7 +1,5 @@ """Tutor project initialize.""" -from tvm.environment_manager.domain.environment_manager_repository import ( - EnvironmentManagerRepository, -) +from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository class TutorProjectCreator: diff --git a/tvm/environment_manager/domain/__init__.py b/tvm/environment_manager/domain/__init__.py index c9cfdb2..4685fd2 100644 --- a/tvm/environment_manager/domain/__init__.py +++ b/tvm/environment_manager/domain/__init__.py @@ -1 +1 @@ -"""Domain init.""" \ No newline at end of file +"""Domain init.""" diff --git a/tvm/environment_manager/domain/environment_manager_repository.py b/tvm/environment_manager/domain/environment_manager_repository.py index e7e6570..3f9ed5c 100644 --- a/tvm/environment_manager/domain/environment_manager_repository.py +++ b/tvm/environment_manager/domain/environment_manager_repository.py @@ -6,19 +6,18 @@ class EnvironmentManagerRepository(ABC): """Administrate environment manager repository methods.""" - @staticmethod @abstractmethod def project_creator(self, version) -> None: """Tutor Project Init to environment manager.""" @abstractmethod def current_version(self) -> None: - """Get the project's version""" + """Get the project's version.""" @abstractmethod def install_plugin(self, options: List) -> None: - """Install a pip package""" + """Install a pip package.""" @abstractmethod def uninstall_plugin(self, options: List) -> None: - """Uninstall a pip package""" + """Uninstall a pip package.""" diff --git a/tvm/environment_manager/domain/project_name.py b/tvm/environment_manager/domain/project_name.py index af250e2..0fc0d39 100644 --- a/tvm/environment_manager/domain/project_name.py +++ b/tvm/environment_manager/domain/project_name.py @@ -1,9 +1,11 @@ +"""Project name domain.""" import re from tvm.environment_manager.domain.project_name_format_error import ProjectNameFormatError class ProjectName(str): + """Project name fotmat.""" def __init__(self, value: str): # pylint: disable=super-init-not-called """Raise BadParameter if the value is not a project name.""" diff --git a/tvm/environment_manager/domain/project_name_format_error.py b/tvm/environment_manager/domain/project_name_format_error.py index bb1c824..d2429c4 100644 --- a/tvm/environment_manager/domain/project_name_format_error.py +++ b/tvm/environment_manager/domain/project_name_format_error.py @@ -1,2 +1,5 @@ +"""Project name format error.""" + + class ProjectNameFormatError(Exception): - pass + """Project name format error exception.""" diff --git a/tvm/environment_manager/infrastructure/__init__.py b/tvm/environment_manager/infrastructure/__init__.py index a7fcb2f..23dee23 100644 --- a/tvm/environment_manager/infrastructure/__init__.py +++ b/tvm/environment_manager/infrastructure/__init__.py @@ -1 +1 @@ -"""Infrastructure init.""" \ No newline at end of file +"""Infrastructure init.""" diff --git a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py index 0fd21aa..f52cbb1 100644 --- a/tvm/environment_manager/infrastructure/environment_manager_git_repository.py +++ b/tvm/environment_manager/infrastructure/environment_manager_git_repository.py @@ -1,19 +1,14 @@ """Actions to initialize a project.""" -from distutils.dir_util import copy_tree import json import os import pathlib import shutil -import stat import subprocess +from distutils.dir_util import copy_tree from typing import List -from tvm.environment_manager.domain.environment_manager_repository import ( - EnvironmentManagerRepository, -) +from tvm.environment_manager.domain.environment_manager_repository import EnvironmentManagerRepository from tvm.environment_manager.domain.project_name import ProjectName - -from tvm.templates.tutor_switcher import TUTOR_SWITCHER_TEMPLATE from tvm.templates.tvm_activate import TVM_ACTIVATE_SCRIPT TVM_PATH = pathlib.Path.home() / ".tvm" @@ -23,6 +18,7 @@ class EnvironmentManagerGitRepository(EnvironmentManagerRepository): """Principals commands to manage TVM.""" def __init__(self, project_path: str) -> None: + """Initialize usefull variables.""" self.PROJECT_PATH = project_path self.TVM_ENVIRONMENT = f"{project_path}/.tvm" @@ -39,13 +35,14 @@ def project_creator(self, version: str) -> None: self.create_project(version) def current_version(self) -> ProjectName: + """Project name in current version.""" info_file_path = f"{self.TVM_ENVIRONMENT}/config.json" with open(info_file_path, "r", encoding="utf-8") as info_file: data = json.load(info_file) return ProjectName(data.get("version")) def create_config_json(self, data: dict) -> None: - """Create configuration json file""" + """Create configuration json file.""" tvm_project_config_file = f"{self.TVM_ENVIRONMENT}/config.json" with open(tvm_project_config_file, "w", encoding="utf-8") as info_file: json.dump(data, info_file, indent=4) @@ -91,7 +88,7 @@ def setup_version_virtualenv(version=None) -> None: executable="/bin/bash", ) - def run_command_in_virtualenv(self, options: List, name: ProjectName = None): + def run_command_in_virtualenv(self, options: List, name: ProjectName = None): # pylint: duplicate-code """Use virtual environment to run command.""" if not name: name = self.current_version() @@ -108,7 +105,9 @@ def run_command_in_virtualenv(self, options: List, name: ProjectName = None): raise Exception(f"Error running venv commands: {ex.output}") from ex def install_plugin(self, options: List) -> None: + """Install a tutor version.""" self.run_command_in_virtualenv(options=options) def uninstall_plugin(self, options: List) -> None: + """Uninstall a tutor version.""" self.run_command_in_virtualenv(options=options) diff --git a/tvm/settings.py b/tvm/settings.py index dfe6d1e..f7d0e66 100644 --- a/tvm/settings.py +++ b/tvm/settings.py @@ -1,3 +1,4 @@ +"""Settings file for tutor.""" from tvm.environment_manager.infrastructure.environment_manager_git_repository import EnvironmentManagerGitRepository from tvm.share.infrastructure.click_client_logger_repository import ClickClientLoggerRepository from tvm.version_manager.infrastructure.version_manager_git_repository import VersionManagerGitRepository @@ -7,5 +8,5 @@ def environment_manager(project_path: str) -> EnvironmentManagerGitRepository: + """Environment manager repository.""" return EnvironmentManagerGitRepository(project_path=project_path) - diff --git a/tvm/share/domain/client_logger_repository.py b/tvm/share/domain/client_logger_repository.py index ba1cfcc..2cd21bb 100644 --- a/tvm/share/domain/client_logger_repository.py +++ b/tvm/share/domain/client_logger_repository.py @@ -1,9 +1,11 @@ +"""Domain clien logger repository.""" import abc from abc import abstractmethod class ClientLoggerRepository(abc.ABC): + """Clien logger.""" @abstractmethod def echo(self, message) -> None: - pass + """Echo a message.""" diff --git a/tvm/share/infrastructure/click_client_logger_repository.py b/tvm/share/infrastructure/click_client_logger_repository.py index 19003ef..0a71108 100644 --- a/tvm/share/infrastructure/click_client_logger_repository.py +++ b/tvm/share/infrastructure/click_client_logger_repository.py @@ -1,9 +1,12 @@ +"""Infrastructure click clien logger repository.""" import click from tvm.share.domain.client_logger_repository import ClientLoggerRepository class ClickClientLoggerRepository(ClientLoggerRepository): + """click clien logger repository.""" def echo(self, message) -> None: + """Echo message.""" click.echo(click.style(message, fg="yellow")) diff --git a/tvm/version_manager/infrastructure/version_manager_git_repository.py b/tvm/version_manager/infrastructure/version_manager_git_repository.py index 0d05085..1ff5832 100644 --- a/tvm/version_manager/infrastructure/version_manager_git_repository.py +++ b/tvm/version_manager/infrastructure/version_manager_git_repository.py @@ -6,11 +6,11 @@ import stat import subprocess import zipfile +from datetime import timedelta from typing import List, Optional import requests import requests_cache -from datetime import timedelta from tvm.share.domain.client_logger_repository import ClientLoggerRepository from tvm.version_manager.domain.tutor_version import TutorVersion @@ -175,7 +175,7 @@ def create_virtualenv(self, version: TutorVersion) -> None: executable="/bin/bash", ) - def run_command_in_virtualenv(self, options: List, version: TutorVersion = None): + def run_command_in_virtualenv(self, options: List, version: TutorVersion = None): # pylint: duplicate-code """Use virtual environment to run command.""" if not version: version = self.current_version(self.TVM_PATH) From a7d688ca0c29b6474a21799712ef54c45dc53624 Mon Sep 17 00:00:00 2001 From: henrrypg Date: Fri, 29 Jul 2022 10:02:55 -0500 Subject: [PATCH 13/13] fix: module not found --- tvm/share/__init__.py | 1 + tvm/share/domain/__init__.py | 1 + tvm/share/infrastructure/__init__.py | 1 + 3 files changed, 3 insertions(+) create mode 100644 tvm/share/__init__.py create mode 100644 tvm/share/domain/__init__.py create mode 100644 tvm/share/infrastructure/__init__.py diff --git a/tvm/share/__init__.py b/tvm/share/__init__.py new file mode 100644 index 0000000..888e8d7 --- /dev/null +++ b/tvm/share/__init__.py @@ -0,0 +1 @@ +"""Share init.""" diff --git a/tvm/share/domain/__init__.py b/tvm/share/domain/__init__.py new file mode 100644 index 0000000..e251ada --- /dev/null +++ b/tvm/share/domain/__init__.py @@ -0,0 +1 @@ +"""Domain module for TVM.""" diff --git a/tvm/share/infrastructure/__init__.py b/tvm/share/infrastructure/__init__.py new file mode 100644 index 0000000..e458e37 --- /dev/null +++ b/tvm/share/infrastructure/__init__.py @@ -0,0 +1 @@ +"""Infrastructure for TVM."""