Improved venv support to all related commands

This commit is contained in:
Sven Heidemann 2022-06-27 11:50:22 +02:00
parent e8a4fe6142
commit 323e363b42
7 changed files with 81 additions and 28 deletions

View File

@ -58,22 +58,6 @@ class InstallService(CommandABC):
def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None): def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None):
time.sleep(t) time.sleep(t)
def _init_venv(self):
if self._is_virtual:
return
venv_path = os.path.abspath(os.path.join(self._env.working_directory, self._project_settings.python_executable))
if not os.path.exists(venv_path):
Console.spinner(
f'Creating venv {venv_path}',
VenvHelper.create_venv,
venv_path,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
)
Pip.set_executable(venv_path)
def _install_project(self): def _install_project(self):
""" """
Installs dependencies of CPl project Installs dependencies of CPl project
@ -211,11 +195,12 @@ class InstallService(CommandABC):
args.remove('simulate') args.remove('simulate')
Console.write_line('Running in simulation mode:') Console.write_line('Running in simulation mode:')
self._init_venv() VenvHelper.init_venv(self._is_virtual, self._env, self._project_settings)
if len(args) == 0: if len(args) == 0:
self._install_project() self._install_project()
else: else:
self._install_package(args[0]) self._install_package(args[0])
# shutil.rmtree(os.path.abspath(os.path.join(self._env.working_directory, self._project_settings.python_executable))) if not self._is_virtual:
Pip.reset_executable()

View File

@ -6,6 +6,7 @@ from typing import Optional
from packaging import version from packaging import version
import cpl_core import cpl_core
from cpl_cli.configuration.venv_helper_service import VenvHelper
from cpl_cli.source_creator.unittest_builder import UnittestBuilder from cpl_cli.source_creator.unittest_builder import UnittestBuilder
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
@ -36,7 +37,7 @@ class NewService(CommandABC):
self._config = configuration self._config = configuration
self._env = self._config.environment self._env = self._config.environment
self._workspace = self._config.get_configuration(WorkspaceSettings) self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings)
self._project: ProjectSettings = ProjectSettings() self._project: ProjectSettings = ProjectSettings()
self._project_dict = {} self._project_dict = {}
self._build: BuildSettings = BuildSettings() self._build: BuildSettings = BuildSettings()
@ -51,6 +52,7 @@ class NewService(CommandABC):
self._use_startup: bool = False self._use_startup: bool = False
self._use_service_providing: bool = False self._use_service_providing: bool = False
self._use_async: bool = False self._use_async: bool = False
self._use_venv: bool = False
@property @property
def help_message(self) -> str: def help_message(self) -> str:
@ -107,7 +109,7 @@ class NewService(CommandABC):
], ],
ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}', ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}',
ProjectSettingsNameEnum.python_path.value: { ProjectSettingsNameEnum.python_path.value: {
sys.platform: '' sys.platform: '../../venv/bin/python' if self._use_venv else ''
}, },
ProjectSettingsNameEnum.classifiers.value: [] ProjectSettingsNameEnum.classifiers.value: []
} }
@ -275,6 +277,22 @@ class NewService(CommandABC):
except Exception as e: except Exception as e:
Console.error('Could not create project', str(e)) Console.error('Could not create project', str(e))
def _create_venv(self):
project = self._project.name
if self._workspace is not None:
project = self._workspace.default_project
if self._env.working_directory.endswith(project):
project = ''
VenvHelper.init_venv(
False,
self._env,
self._project,
explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', ''))
)
def execute(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
@ -308,6 +326,9 @@ class NewService(CommandABC):
if 'service-providing' in args: if 'service-providing' in args:
self._use_service_providing = True self._use_service_providing = True
args.remove('service-providing') args.remove('service-providing')
if 'venv' in args:
self._use_venv = True
args.remove('venv')
console = self._config.get_configuration(ProjectTypeEnum.console.value) console = self._config.get_configuration(ProjectTypeEnum.console.value)
library = self._config.get_configuration(ProjectTypeEnum.library.value) library = self._config.get_configuration(ProjectTypeEnum.library.value)
@ -316,16 +337,22 @@ class NewService(CommandABC):
self._name = console self._name = console
self._schematic = ProjectTypeEnum.console.value self._schematic = ProjectTypeEnum.console.value
self._console(args) self._console(args)
if self._use_venv:
self._create_venv()
elif console is None and library is not None and unittest is None: elif console is None and library is not None and unittest is None:
self._name = library self._name = library
self._schematic = ProjectTypeEnum.library.value self._schematic = ProjectTypeEnum.library.value
self._library(args) self._library(args)
if self._use_venv:
self._create_venv()
elif console is None and library is None and unittest is not None: elif console is None and library is None and unittest is not None:
self._name = unittest self._name = unittest
self._schematic = ProjectTypeEnum.unittest.value self._schematic = ProjectTypeEnum.unittest.value
self._unittest(args) self._unittest(args)
if self._use_venv:
self._create_venv()
else: else:
self._help('Usage: cpl new <schematic> [options]') self._help('Usage: cpl new <schematic> [options]')

View File

@ -4,6 +4,7 @@ import subprocess
import textwrap import textwrap
import time import time
from cpl_cli.configuration.venv_helper_service import VenvHelper
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
@ -71,8 +72,7 @@ class UninstallService(CommandABC):
args.remove('--simulate') args.remove('--simulate')
Console.write_line('Running in simulation mode:') Console.write_line('Running in simulation mode:')
if not self._is_virtual: VenvHelper.init_venv(self._is_virtual, self._env, self._project_settings)
Pip.set_executable(self._project_settings.python_executable)
package = args[0] package = args[0]
is_in_dependencies = False is_in_dependencies = False

View File

@ -3,6 +3,7 @@ import os
import subprocess import subprocess
import textwrap import textwrap
from cpl_cli.configuration.venv_helper_service import VenvHelper
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
@ -168,7 +169,8 @@ class UpdateService(CommandABC):
Console.write_line('Running in simulation mode:') Console.write_line('Running in simulation mode:')
self._is_simulation = True self._is_simulation = True
Pip.set_executable(self._project_settings.python_executable) VenvHelper.init_venv(False, self._env, self._project_settings)
self._check_project_dependencies() self._check_project_dependencies()
self._check_outdated() self._check_outdated()
Pip.reset_executable() Pip.reset_executable()

View File

@ -2,9 +2,37 @@ import os
import subprocess import subprocess
import sys import sys
from cpl_cli.configuration import ProjectSettings
from cpl_core.environment import ApplicationEnvironmentABC
from cpl_core.utils import Pip
from cpl_core.console import Console, ForegroundColorEnum
class VenvHelper: class VenvHelper:
@staticmethod
def init_venv(is_virtual: bool, env: ApplicationEnvironmentABC, project_settings: ProjectSettings, explicit_path=None):
if is_virtual:
return
venv_path = os.path.abspath(os.path.join(env.working_directory, project_settings.python_executable))
if explicit_path is not None:
venv_path = os.path.abspath(explicit_path)
if not os.path.exists(venv_path):
Console.spinner(
f'Creating venv: {venv_path}',
VenvHelper.create_venv,
venv_path,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
)
Pip.set_executable(venv_path)
@staticmethod @staticmethod
def create_venv(path): def create_venv(path):
subprocess.run( subprocess.run(

View File

@ -50,7 +50,8 @@ class StartupArgumentExtension(StartupExtensionABC):
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'application-base', ['ab', 'AB']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'application-base', ['ab', 'AB']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'startup', ['s', 'S']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'startup', ['s', 'S']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'service-providing', ['sp', 'SP']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'service-providing', ['sp', 'SP']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'nothing', ['n', 'N']) .add_console_argument(ArgumentTypeEnum.Flag, '--', 'nothing', ['n', 'N']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'venv', ['v', 'V'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService, True, validators=[ProjectValidator]) config.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService, True, validators=[ProjectValidator])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService, True, validators=[WorkspaceValidator]) \ config.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService, True, validators=[WorkspaceValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])

View File

@ -12,10 +12,15 @@ class NewTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
os.chdir(os.path.abspath(PLAYGROUND_PATH)) os.chdir(os.path.abspath(PLAYGROUND_PATH))
def _test_project(self, project_type: str, name: str, *args): def _test_project(self, project_type: str, name: str, *args, test_venv=False):
CLICommands.new(project_type, name, *args) CLICommands.new(project_type, name, *args)
workspace_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, name)) workspace_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, name))
self.assertTrue(os.path.exists(workspace_path)) self.assertTrue(os.path.exists(workspace_path))
if test_venv:
self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv')))
self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin')))
self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin/python')))
self.assertTrue(os.path.islink(os.path.join(workspace_path, 'venv/bin/python')))
project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, name, 'src', String.convert_to_snake_case(name))) project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, name, 'src', String.convert_to_snake_case(name)))
self.assertTrue(os.path.exists(project_path)) self.assertTrue(os.path.exists(project_path))
@ -38,11 +43,16 @@ class NewTestCase(unittest.TestCase):
else: else:
self.assertFalse(os.path.isfile(os.path.join(project_path, f'test_case.py'))) self.assertFalse(os.path.isfile(os.path.join(project_path, f'test_case.py')))
def _test_sub_project(self, project_type: str, name: str, workspace_name: str, *args): def _test_sub_project(self, project_type: str, name: str, workspace_name: str, *args, test_venv=False):
os.chdir(os.path.abspath(os.path.join(os.getcwd(), workspace_name))) os.chdir(os.path.abspath(os.path.join(os.getcwd(), workspace_name)))
CLICommands.new(project_type, name, *args) CLICommands.new(project_type, name, *args)
workspace_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, workspace_name)) workspace_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, workspace_name))
self.assertTrue(os.path.exists(workspace_path)) self.assertTrue(os.path.exists(workspace_path))
if test_venv:
self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv')))
self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin')))
self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin/python')))
self.assertTrue(os.path.islink(os.path.join(workspace_path, 'venv/bin/python')))
project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, workspace_name, 'src', String.convert_to_snake_case(name))) project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, workspace_name, 'src', String.convert_to_snake_case(name)))
self.assertTrue(os.path.exists(project_path)) self.assertTrue(os.path.exists(project_path))
@ -76,7 +86,7 @@ class NewTestCase(unittest.TestCase):
os.chdir(os.path.abspath(os.path.join(os.getcwd(), '../'))) os.chdir(os.path.abspath(os.path.join(os.getcwd(), '../')))
def test_console(self): def test_console(self):
self._test_project('console', 'test-console', '--ab', '--s') self._test_project('console', 'test-console', '--ab', '--s', '--venv', test_venv=True)
def test_console_without_s(self): def test_console_without_s(self):
self._test_project('console', 'test-console-without-s', '--ab') self._test_project('console', 'test-console-without-s', '--ab')
@ -88,7 +98,7 @@ class NewTestCase(unittest.TestCase):
self._test_project('console', 'test-console-without-anything', '--n') self._test_project('console', 'test-console-without-anything', '--n')
def test_sub_console(self): def test_sub_console(self):
self._test_sub_project('console', 'test-sub-console', 'test-console', '--ab', '--s', '--sp') self._test_sub_project('console', 'test-sub-console', 'test-console', '--ab', '--s', '--sp', '--venv', test_venv=True)
def test_library(self): def test_library(self):
self._test_project('library', 'test-library', '--ab', '--s', '--sp') self._test_project('library', 'test-library', '--ab', '--s', '--sp')