Implemented live development server

This commit is contained in:
Sven Heidemann 2021-03-12 22:53:02 +01:00
parent 86089a037c
commit 4af18b6c70
7 changed files with 142 additions and 2 deletions

View File

@ -5,6 +5,7 @@ from cpl_cli.command.build_service import BuildService
from cpl_cli.command.generate_service import GenerateService from cpl_cli.command.generate_service import GenerateService
from cpl_cli.command.new_service import NewService from cpl_cli.command.new_service import NewService
from cpl_cli.command.publish_service import PublishService from cpl_cli.command.publish_service import PublishService
from cpl_cli.command.start_service import StartService
from cpl_cli.command_handler_service import CommandHandler from cpl_cli.command_handler_service import CommandHandler
from cpl_cli.command_model import CommandModel from cpl_cli.command_model import CommandModel
from cpl_cli.error import Error from cpl_cli.error import Error
@ -27,6 +28,7 @@ class CLI(ApplicationABC):
self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False)) self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False))
self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False)) self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False))
self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, True)) self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, True))
self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, True))
self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False)) self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False))
def main(self): def main(self):

View File

@ -0,0 +1,68 @@
import os
import signal
import subprocess
import time
import psutil as psutil
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
from cpl.application import ApplicationRuntimeABC
from cpl.console.console import Console
from cpl_cli.command_abc import CommandABC
from cpl_cli.configuration import BuildSettings
from cpl_cli.live_server.live_server import LiveServerThread
class StartService(CommandABC, FileSystemEventHandler):
def __init__(self, runtime: ApplicationRuntimeABC, build_settings: BuildSettings):
CommandABC.__init__(self)
FileSystemEventHandler.__init__(self)
self._runtime = runtime
self._build_settings = build_settings
self._src_dir = os.path.join(self._runtime.working_directory, self._build_settings.source_path)
self._live_server = LiveServerThread(self._src_dir)
self._observer = None
def _start_observer(self):
self._observer = Observer()
self._observer.schedule(self, path=self._src_dir, recursive=True)
self._observer.start()
def _restart(self):
for proc in psutil.process_iter():
try:
if proc.cmdline() == self._live_server.command:
os.system(f'pkill -f {self._live_server.main}')
except Exception as e:
pass
Console.write_line('Restart\n')
while self._live_server.is_alive():
time.sleep(1)
self._live_server = LiveServerThread(self._src_dir)
self._live_server.start()
self._start_observer()
def on_modified(self, event):
if event.is_directory:
return None
# Event is modified, you can process it now
if str(event.src_path).endswith('.py'):
self._observer.stop()
self._restart()
def run(self, args: list[str]):
Console.write_line('** CPL live development server is running **')
self._start_observer()
self._live_server.start()
Console.close()
Console.write('\n')

View File

View File

@ -0,0 +1,23 @@
from watchdog.events import FileSystemEventHandler
from cpl.console.console import Console
from cpl_cli.live_server.live_server import LiveServerThread
class FileChangeHandler(FileSystemEventHandler):
def __init__(self, live_server: LiveServerThread):
FileSystemEventHandler.__init__(self)
self._live_server = live_server
def on_any_event(self, event):
if event.is_directory:
return None
elif event.event_type == 'modified':
# Event is modified, you can process it now
if str(event.src_path).endswith('.py'):
Console.write_line(f'Detected change in {event.src_path}')
self._live_server.kill_application()
self._live_server.start()

View File

@ -0,0 +1,38 @@
import os
import subprocess
import sys
import threading
from datetime import datetime
from cpl.console import Console
class LiveServerThread(threading.Thread):
def __init__(self, path: str):
threading.Thread.__init__(self)
self._path = path
self._main = ''
self._command = []
@property
def command(self) -> list[str]:
return self._command
@property
def main(self) -> str:
return self._main
def run(self):
self._main = os.path.join(self._path, 'main.py')
if not os.path.isfile(self._main):
Console.error('Entry point main.py does not exist')
return
Console.write_line('Read successfully')
now = datetime.now()
Console.write_line(f'Started at {now.strftime("%Y-%m-%d %H:%M:%S")}\n\n')
self._command = [sys.executable, self._main, ''.join(sys.argv[2:])]
subprocess.run(self._command)

View File

@ -10,6 +10,7 @@ from cpl_cli.command.build_service import BuildService
from cpl_cli.command.generate_service import GenerateService from cpl_cli.command.generate_service import GenerateService
from cpl_cli.command.new_service import NewService from cpl_cli.command.new_service import NewService
from cpl_cli.command.publish_service import PublishService from cpl_cli.command.publish_service import PublishService
from cpl_cli.command.start_service import StartService
from cpl_cli.command_handler_service import CommandHandler from cpl_cli.command_handler_service import CommandHandler
from cpl_cli.command.help_service import HelpService from cpl_cli.command.help_service import HelpService
from cpl_cli.command.version_service import VersionService from cpl_cli.command.version_service import VersionService
@ -56,6 +57,7 @@ class Startup(StartupABC):
ConsoleArgument('', 'console', ['c', 'C'], ' ') ConsoleArgument('', 'console', ['c', 'C'], ' ')
])) ]))
self._configuration.add_console_argument(ConsoleArgument('', 'publish', ['p', 'P'], '')) self._configuration.add_console_argument(ConsoleArgument('', 'publish', ['p', 'P'], ''))
self._configuration.add_console_argument(ConsoleArgument('', 'start', ['s', 'S'], ''))
self._configuration.add_console_argument(ConsoleArgument('', 'version', ['v', 'V'], '')) self._configuration.add_console_argument(ConsoleArgument('', 'version', ['v', 'V'], ''))
self._configuration.add_console_arguments() self._configuration.add_console_arguments()
@ -71,6 +73,7 @@ class Startup(StartupABC):
self._services.add_transient(HelpService) self._services.add_transient(HelpService)
self._services.add_transient(NewService) self._services.add_transient(NewService)
self._services.add_transient(PublishService) self._services.add_transient(PublishService)
self._services.add_transient(StartService)
self._services.add_transient(VersionService) self._services.add_transient(VersionService)
return self._services return self._services

View File

@ -1,3 +1,4 @@
import time
from typing import Optional from typing import Optional
from cpl.application.application_abc import ApplicationABC from cpl.application.application_abc import ApplicationABC
@ -33,6 +34,10 @@ class Application(ApplicationABC):
Console.write_at(5, 5, 'at 5, 5') Console.write_at(5, 5, 'at 5, 5')
Console.write_at(10, 10, 'at 10, 10') Console.write_at(10, 10, 'at 10, 10')
@staticmethod
def _wait(time_ms: int):
time.sleep(time_ms)
def configure(self): def configure(self):
self._logger = self._services.get_service(LoggerABC) self._logger = self._services.get_service(LoggerABC)
self._mailer = self._services.get_service(EMailClientABC) self._mailer = self._services.get_service(EMailClientABC)
@ -42,5 +47,6 @@ class Application(ApplicationABC):
self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}') self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}') self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}') self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
Console.spinner('Test', self._wait, 999999, spinner_foreground_color='red')
# self.test_send_mail() # self.test_send_mail()
# self.test_console() # self.test_console()