2022.12 #133
| @@ -8,10 +8,12 @@ from cpl_cli.configuration import WorkspaceSettings | ||||
| from cpl_cli.configuration.build_settings import BuildSettings | ||||
| from cpl_cli.configuration.project_settings import ProjectSettings | ||||
| from cpl_cli.live_server.start_executable import StartExecutable | ||||
| from cpl_cli.publish import PublisherService | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.console.console import Console | ||||
| from cpl_core.dependency_injection import ServiceProviderABC | ||||
| from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC | ||||
| from cpl_core.utils import String | ||||
|  | ||||
|  | ||||
| class RunService(CommandABC): | ||||
| @@ -22,7 +24,8 @@ class RunService(CommandABC): | ||||
|                  services: ServiceProviderABC, | ||||
|                  project_settings: ProjectSettings, | ||||
|                  build_settings: BuildSettings, | ||||
|                  workspace: WorkspaceSettings | ||||
|                  workspace: WorkspaceSettings, | ||||
|                  publisher: PublisherService, | ||||
|                  ): | ||||
|         """ | ||||
|         Service for the CLI command start | ||||
| @@ -41,8 +44,10 @@ class RunService(CommandABC): | ||||
|         self._project_settings = project_settings | ||||
|         self._build_settings = build_settings | ||||
|         self._workspace = workspace | ||||
|         self._publisher = publisher | ||||
|  | ||||
|         self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path) | ||||
|         self._is_dev = False | ||||
|  | ||||
|     @property | ||||
|     def help_message(self) -> str: | ||||
| @@ -80,16 +85,36 @@ class RunService(CommandABC): | ||||
|  | ||||
|         self._src_dir = os.path.dirname(json_file) | ||||
|  | ||||
|     def _build(self): | ||||
|         if self._is_dev: | ||||
|             return | ||||
|  | ||||
|         self._env.set_working_directory(self._src_dir) | ||||
|         self._publisher.build() | ||||
|         self._src_dir = os.path.abspath(os.path.join( | ||||
|             self._src_dir, | ||||
|             self._build_settings.output_path, | ||||
|             self._project_settings.name, | ||||
|             'build', | ||||
|             String.convert_to_snake_case(self._project_settings.name) | ||||
|         )) | ||||
|  | ||||
|     def execute(self, args: list[str]): | ||||
|         """ | ||||
|         Entry point of command | ||||
|         :param args: | ||||
|         :return: | ||||
|         """ | ||||
|         if 'dev' in args: | ||||
|             self._is_dev = True | ||||
|             args.remove('dev') | ||||
|  | ||||
|         if len(args) >= 1: | ||||
|             self._set_project_by_args(args[0]) | ||||
|             args.remove(args[0]) | ||||
|  | ||||
|         self._build() | ||||
|  | ||||
|         start_service = StartExecutable(self._env, self._build_settings) | ||||
|         start_service.run(args, self._project_settings.python_executable, self._src_dir, output=False) | ||||
|         Console.write_line() | ||||
|   | ||||
| @@ -6,17 +6,24 @@ import psutil as psutil | ||||
| from watchdog.events import FileSystemEventHandler | ||||
| from watchdog.observers import Observer | ||||
|  | ||||
| from cpl_cli.publish import PublisherService | ||||
| from cpl_core.console.console import Console | ||||
| from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC | ||||
| from cpl_cli.configuration.build_settings import BuildSettings | ||||
| from cpl_cli.configuration.project_settings import ProjectSettings | ||||
| from cpl_cli.live_server.live_server_thread import LiveServerThread | ||||
| from cpl_core.utils import String | ||||
|  | ||||
|  | ||||
| class LiveServerService(FileSystemEventHandler): | ||||
|  | ||||
|     def __init__(self, env: ApplicationEnvironmentABC, project_settings: ProjectSettings, | ||||
|                  build_settings: BuildSettings): | ||||
|     def __init__( | ||||
|             self, | ||||
|             env: ApplicationEnvironmentABC, | ||||
|             project_settings: ProjectSettings, | ||||
|             build_settings: BuildSettings, | ||||
|             publisher: PublisherService, | ||||
|     ): | ||||
|         """ | ||||
|         Service for the live development server | ||||
|         :param env: | ||||
| @@ -28,12 +35,15 @@ class LiveServerService(FileSystemEventHandler): | ||||
|         self._env = env | ||||
|         self._project_settings = project_settings | ||||
|         self._build_settings = build_settings | ||||
|         self._publisher = publisher | ||||
|  | ||||
|         self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path) | ||||
|         self._wd = self._src_dir | ||||
|         self._ls_thread = None | ||||
|         self._observer = None | ||||
|  | ||||
|         self._args: list[str] = [] | ||||
|         self._is_dev = False | ||||
|  | ||||
|     def _start_observer(self): | ||||
|         """ | ||||
| @@ -75,10 +85,11 @@ class LiveServerService(FileSystemEventHandler): | ||||
|             self._restart() | ||||
|  | ||||
|     def _start(self): | ||||
|         self._build() | ||||
|         self._start_observer() | ||||
|         self._ls_thread = LiveServerThread( | ||||
|             self._project_settings.python_executable, | ||||
|             self._src_dir, | ||||
|             self._wd, | ||||
|             self._args, | ||||
|             self._env, | ||||
|             self._build_settings | ||||
| @@ -87,6 +98,22 @@ class LiveServerService(FileSystemEventHandler): | ||||
|         self._ls_thread.join() | ||||
|         Console.close() | ||||
|  | ||||
|     def _build(self): | ||||
|         if self._is_dev: | ||||
|             return | ||||
|  | ||||
|         self._env.set_working_directory(self._src_dir) | ||||
|         Console.disable() | ||||
|         self._publisher.build() | ||||
|         Console.enable() | ||||
|         self._wd = os.path.abspath(os.path.join( | ||||
|             self._src_dir, | ||||
|             self._build_settings.output_path, | ||||
|             self._project_settings.name, | ||||
|             'build', | ||||
|             String.convert_to_snake_case(self._project_settings.name) | ||||
|         )) | ||||
|  | ||||
|     def start(self, args: list[str]): | ||||
|         """ | ||||
|         Starts the CPL live development server | ||||
| @@ -97,6 +124,10 @@ class LiveServerService(FileSystemEventHandler): | ||||
|             Console.error('Project has no entry point.') | ||||
|             return | ||||
|  | ||||
|         if 'dev' in args: | ||||
|             self._is_dev = True | ||||
|             args.remove('dev') | ||||
|  | ||||
|         self._args = args | ||||
|         Console.write_line('** CPL live development server is running **') | ||||
|         self._start() | ||||
|   | ||||
| @@ -60,8 +60,10 @@ class StartupArgumentExtension(StartupExtensionABC): | ||||
|         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]) \ | ||||
|             .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) | ||||
|         config.create_console_argument(ArgumentTypeEnum.Executable, '', 'run', [], RunService, True, validators=[ProjectValidator]) | ||||
|         config.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['s', 'S'], StartService, True, validators=[ProjectValidator]) | ||||
|         config.create_console_argument(ArgumentTypeEnum.Executable, '', 'run', [], RunService, True, validators=[ProjectValidator]) \ | ||||
|             .add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) | ||||
|         config.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['s', 'S'], StartService, True, validators=[ProjectValidator]) \ | ||||
|             .add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) | ||||
|         config.create_console_argument(ArgumentTypeEnum.Executable, '', 'uninstall', ['ui', 'UI'], UninstallService, True, validators=[ProjectValidator]) \ | ||||
|             .add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) \ | ||||
|             .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ | ||||
|   | ||||
| @@ -0,0 +1,26 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| general sh-edraft Common Python library | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| sh-edraft Common Python library | ||||
|  | ||||
| :copyright: (c) 2020 - 2021 sh-edraft.de | ||||
| :license: MIT, see LICENSE for more details. | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'general.arguments' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' | ||||
| __version__ = '2021.4.1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports: | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='2021', minor='04', micro='01') | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| sh_cpl sh-edraft Common Python library | ||||
| general sh-edraft Common Python library | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| sh-edraft Common Python library | ||||
| @@ -11,7 +11,7 @@ sh-edraft Common Python library | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'tests.db' | ||||
| __title__ = 'general.db' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' | ||||
| @@ -19,7 +19,8 @@ __version__ = '2021.4.1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports: | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major=2021, minor=4, micro=1) | ||||
| version_info = VersionInfo(major='2021', minor='04', micro='01') | ||||
|   | ||||
| @@ -16,12 +16,12 @@ | ||||
|     "LicenseName": "MIT", | ||||
|     "LicenseDescription": "MIT, see LICENSE for more details.", | ||||
|     "Dependencies": [ | ||||
|       "cpl-core==2022.10rc2", | ||||
|       "cpl-translation==2022.10rc2", | ||||
|       "cpl-query==2022.10rc2" | ||||
|       "cpl-core==2022.10.0.post9", | ||||
|       "cpl-translation==2022.10.0.post2", | ||||
|       "cpl-query==2022.10.0.post2" | ||||
|     ], | ||||
|     "DevDependencies": [ | ||||
|       "cpl-cli==2022.10.rc2" | ||||
|       "cpl-cli==2022.10" | ||||
|     ], | ||||
|     "PythonVersion": ">=3.10", | ||||
|     "PythonPath": { | ||||
|   | ||||
| @@ -15,10 +15,10 @@ class RunTestCase(CommandTestCase): | ||||
|         CommandTestCase.__init__(self, method_name) | ||||
|         self._source = 'run-test' | ||||
|         self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' | ||||
|         self._appsettings = f'src/{String.convert_to_snake_case(self._source)}/appsettings.json' | ||||
|         self._application = f'src/{String.convert_to_snake_case(self._source)}/application.py' | ||||
|         self._test_code = f""" | ||||
|         import json | ||||
|         import os | ||||
|         settings = dict() | ||||
|         with open('appsettings.json', 'r', encoding='utf-8') as cfg: | ||||
|             # load json | ||||
| @@ -26,14 +26,19 @@ class RunTestCase(CommandTestCase): | ||||
|             cfg.close() | ||||
|              | ||||
|         settings['RunTest']['WasStarted'] = 'True' | ||||
|         settings['RunTest']['Path'] = os.path.dirname(os.path.realpath(__file__)) | ||||
|          | ||||
|         with open('appsettings.json', 'w', encoding='utf-8') as project_file: | ||||
|             project_file.write(json.dumps(settings, indent=2)) | ||||
|             project_file.close() | ||||
|         """ | ||||
|  | ||||
|     def _get_appsettings(self): | ||||
|         with open(os.path.join(os.getcwd(), self._appsettings), 'r', encoding='utf-8') as cfg: | ||||
|     def _get_appsettings(self, is_dev=False): | ||||
|         appsettings = f'dist/{self._source}/build/{String.convert_to_snake_case(self._source)}/appsettings.json' | ||||
|         if is_dev: | ||||
|             appsettings = f'src/{String.convert_to_snake_case(self._source)}/appsettings.json' | ||||
|  | ||||
|         with open(os.path.join(os.getcwd(), appsettings), 'r', encoding='utf-8') as cfg: | ||||
|             # load json | ||||
|             project_json = json.load(cfg) | ||||
|             cfg.close() | ||||
| @@ -41,14 +46,11 @@ class RunTestCase(CommandTestCase): | ||||
|         return project_json | ||||
|  | ||||
|     def _save_appsettings(self, settings: dict): | ||||
|         with open(os.path.join(os.getcwd(), self._appsettings), 'w', encoding='utf-8') as project_file: | ||||
|         with open(os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}/appsettings.json'), 'w', encoding='utf-8') as project_file: | ||||
|             project_file.write(json.dumps(settings, indent=2)) | ||||
|             project_file.close() | ||||
|  | ||||
|     def setUp(self): | ||||
|         if not os.path.exists(PLAYGROUND_PATH): | ||||
|             os.makedirs(PLAYGROUND_PATH) | ||||
|          | ||||
|         os.chdir(PLAYGROUND_PATH) | ||||
|         # create projects | ||||
|         CLICommands.new('console', self._source, '--ab', '--s') | ||||
| @@ -69,9 +71,16 @@ class RunTestCase(CommandTestCase): | ||||
|             'True', | ||||
|             settings['RunTest']['WasStarted'] | ||||
|         ) | ||||
|         self.assertNotEqual( | ||||
|             os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}'), | ||||
|             settings['RunTest']['Path'] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             os.path.join(os.getcwd(), f'dist/{self._source}/build/{String.convert_to_snake_case(self._source)}'), | ||||
|             settings['RunTest']['Path'] | ||||
|         ) | ||||
|  | ||||
|     def test_run_by_project(self): | ||||
|         os.chdir(os.path.join(os.getcwd())) | ||||
|         CLICommands.run(self._source) | ||||
|         settings = self._get_appsettings() | ||||
|         self.assertNotEqual(settings, {}) | ||||
| @@ -81,3 +90,41 @@ class RunTestCase(CommandTestCase): | ||||
|             'True', | ||||
|             settings['RunTest']['WasStarted'] | ||||
|         ) | ||||
|         self.assertNotEqual( | ||||
|             os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}'), | ||||
|             settings['RunTest']['Path'] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             os.path.join(os.getcwd(), f'dist/{self._source}/build/{String.convert_to_snake_case(self._source)}'), | ||||
|             settings['RunTest']['Path'] | ||||
|         ) | ||||
|  | ||||
|     def test_run_dev(self): | ||||
|         CLICommands.run(is_dev=True) | ||||
|         settings = self._get_appsettings(is_dev=True) | ||||
|         self.assertNotEqual(settings, {}) | ||||
|         self.assertIn('RunTest', settings) | ||||
|         self.assertIn('WasStarted', settings['RunTest']) | ||||
|         self.assertEqual( | ||||
|             'True', | ||||
|             settings['RunTest']['WasStarted'] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}'), | ||||
|             settings['RunTest']['Path'] | ||||
|         ) | ||||
|  | ||||
|     def test_run_dev_by_project(self): | ||||
|         CLICommands.run(self._source, is_dev=True) | ||||
|         settings = self._get_appsettings(is_dev=True) | ||||
|         self.assertNotEqual(settings, {}) | ||||
|         self.assertIn('RunTest', settings) | ||||
|         self.assertIn('WasStarted', settings['RunTest']) | ||||
|         self.assertEqual( | ||||
|             'True', | ||||
|             settings['RunTest']['WasStarted'] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}'), | ||||
|             settings['RunTest']['Path'] | ||||
|         ) | ||||
|   | ||||
| @@ -21,6 +21,7 @@ class StartTestCase(CommandTestCase): | ||||
|         self._application = f'src/{String.convert_to_snake_case(self._source)}/application.py' | ||||
|         self._test_code = f""" | ||||
|         import json | ||||
|         import os | ||||
|         settings = dict() | ||||
|         with open('appsettings.json', 'r', encoding='utf-8') as cfg: | ||||
|             # load json | ||||
| @@ -31,14 +32,19 @@ class StartTestCase(CommandTestCase): | ||||
|             settings['RunTest']['WasRestarted'] = 'True' | ||||
|          | ||||
|         settings['RunTest']['WasStarted'] = 'True' | ||||
|         settings['RunTest']['Path'] = os.path.dirname(os.path.realpath(__file__)) | ||||
|          | ||||
|         with open('appsettings.json', 'w', encoding='utf-8') as project_file: | ||||
|             project_file.write(json.dumps(settings, indent=2)) | ||||
|             project_file.close() | ||||
|         """ | ||||
|  | ||||
|     def _get_appsettings(self): | ||||
|         with open(os.path.join(os.getcwd(), self._appsettings), 'r', encoding='utf-8') as cfg: | ||||
|     def _get_appsettings(self, is_dev=False): | ||||
|         appsettings = f'dist/{self._source}/build/{String.convert_to_snake_case(self._source)}/appsettings.json' | ||||
|         if is_dev: | ||||
|             appsettings = f'src/{String.convert_to_snake_case(self._source)}/appsettings.json' | ||||
|  | ||||
|         with open(os.path.join(os.getcwd(), appsettings), 'r', encoding='utf-8') as cfg: | ||||
|             # load json | ||||
|             project_json = json.load(cfg) | ||||
|             cfg.close() | ||||
| @@ -46,7 +52,7 @@ class StartTestCase(CommandTestCase): | ||||
|         return project_json | ||||
|  | ||||
|     def _save_appsettings(self, settings: dict): | ||||
|         with open(os.path.join(os.getcwd(), self._appsettings), 'w', encoding='utf-8') as project_file: | ||||
|         with open(os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}/appsettings.json'), 'w', encoding='utf-8') as project_file: | ||||
|             project_file.write(json.dumps(settings, indent=2)) | ||||
|             project_file.close() | ||||
|  | ||||
| @@ -67,6 +73,39 @@ class StartTestCase(CommandTestCase): | ||||
|     def test_start(self): | ||||
|         thread = StartTestThread() | ||||
|         thread.start() | ||||
|         time.sleep(5) | ||||
|         settings = self._get_appsettings() | ||||
|         self.assertNotEqual(settings, {}) | ||||
|         self.assertIn('RunTest', settings) | ||||
|         self.assertIn('WasStarted', settings['RunTest']) | ||||
|         self.assertEqual( | ||||
|             'True', | ||||
|             settings['RunTest']['WasStarted'] | ||||
|         ) | ||||
|  | ||||
|         with open(os.path.join(os.getcwd(), self._application), 'a', encoding='utf-8') as file: | ||||
|             file.write(f'# trigger restart (comment generated by unittest)') | ||||
|             file.close() | ||||
|  | ||||
|         time.sleep(5) | ||||
|  | ||||
|         settings = self._get_appsettings() | ||||
|         self.assertNotEqual(settings, {}) | ||||
|         self.assertIn('RunTest', settings) | ||||
|         self.assertIn('WasStarted', settings['RunTest']) | ||||
|         self.assertIn('WasRestarted', settings['RunTest']) | ||||
|         self.assertEqual( | ||||
|             'True', | ||||
|             settings['RunTest']['WasStarted'] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             'True', | ||||
|             settings['RunTest']['WasRestarted'] | ||||
|         ) | ||||
|  | ||||
|     def test_start_dev(self): | ||||
|         thread = StartTestThread(is_dev=True) | ||||
|         thread.start() | ||||
|         time.sleep(1) | ||||
|         settings = self._get_appsettings() | ||||
|         self.assertNotEqual(settings, {}) | ||||
| @@ -83,7 +122,7 @@ class StartTestCase(CommandTestCase): | ||||
|  | ||||
|         time.sleep(1) | ||||
|  | ||||
|         settings = self._get_appsettings() | ||||
|         settings = self._get_appsettings(is_dev=True) | ||||
|         self.assertNotEqual(settings, {}) | ||||
|         self.assertIn('RunTest', settings) | ||||
|         self.assertIn('WasStarted', settings['RunTest']) | ||||
|   | ||||
| @@ -5,8 +5,9 @@ from unittests_shared.cli_commands import CLICommands | ||||
|  | ||||
| class StartTestThread(threading.Thread): | ||||
|  | ||||
|     def __init__(self): | ||||
|     def __init__(self, is_dev=False): | ||||
|         threading.Thread.__init__(self, daemon=True) | ||||
|         self._is_dev = is_dev | ||||
|  | ||||
|     def run(self): | ||||
|         CLICommands.start(True) | ||||
|         CLICommands.start(is_dev=self._is_dev, output=True) | ||||
|   | ||||
| @@ -65,15 +65,23 @@ class CLICommands: | ||||
|         cls._run('remove', project, output=output) | ||||
|  | ||||
|     @classmethod | ||||
|     def run(cls, project: str = None, output=False): | ||||
|     def run(cls, project: str = None, is_dev=False, output=False): | ||||
|         args = [] | ||||
|         if is_dev: | ||||
|             args.append('--dev') | ||||
|  | ||||
|         if project is None: | ||||
|             cls._run('run', output=output) | ||||
|             cls._run('run', *args, output=output) | ||||
|             return | ||||
|         cls._run('run', project, output=output) | ||||
|         cls._run('run', project, *args, output=output) | ||||
|  | ||||
|     @classmethod | ||||
|     def start(cls, output=False): | ||||
|         cls._run('start', output=output) | ||||
|     def start(cls, is_dev=False, output=False): | ||||
|         args = [] | ||||
|         if is_dev: | ||||
|             args.append('--dev') | ||||
|  | ||||
|         cls._run('start', *args, output=output) | ||||
|  | ||||
|     @classmethod | ||||
|     def uninstall(cls, package: str, is_dev=False, output=False): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user