Loading src/climax/__main__.py +196 −140 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ from .config import ( max_releases, max_release, latest_max_release, CLI_MAIN_HELP, ) locales_dir = Path(__file__).parent / "locales" Loading Loading @@ -97,8 +98,8 @@ def class_path_separator() -> str: @cache def cp_paths() -> str: basex_dir_path = Path(os.getcwd(), ".max", "basex") def cp_paths(working_dir: str = os.getcwd()) -> str: basex_dir_path = Path(working_dir, ".max", "basex") paths = class_path_separator().join( [ str(Path(basex_dir_path, "BaseX.jar")), Loading @@ -116,9 +117,7 @@ def find_jdk(cur_sys: str = None) -> Optional[str]: return JAVA_DISTROS.get(cur_sys, None) def dir_is_max(directory: Path = None) -> bool: if directory is None: directory = os.getcwd() def dir_is_max(directory: Path = os.getcwd()) -> bool: directory = Path(directory) config_file = Path(directory, "config.xml") if config_file.exists(): Loading @@ -132,16 +131,16 @@ def dir_is_max(directory: Path = None) -> bool: return False def check_cwd_is_max(): if not dir_is_max(): def check_dir_is_max(directory): if not dir_is_max(directory): print( "[red]{}[/red]".format(_("Le dossier n'est pas une installation de MaX.")) ) raise typer.Exit(code=1) def max_config() -> MaXProjectConfig: return MaXProjectConfig(Path(os.getcwd(), MAX_CONFIG_FILE)) def max_config(directory: str = os.getcwd()) -> MaXProjectConfig: return MaXProjectConfig(Path(directory, MAX_CONFIG_FILE)) def unzip(source: Union[Path, str], destination: Union[Path, str]) -> bool: Loading Loading @@ -213,9 +212,7 @@ def ensure_java() -> Path: return java_bin def ensure_available_max_directory(directory: Optional[Path]) -> tuple[Path, bool]: if not directory: directory = os.getcwd() def ensure_available_max_directory(directory: str = os.getcwd()) -> tuple[Path, bool]: directory = Path(directory) if not directory.exists(): directory.mkdir(parents=True, exist_ok=False) Loading @@ -234,9 +231,7 @@ def ensure_available_max_directory(directory: Optional[Path]) -> tuple[Path, boo return directory, is_max app = typer.Typer( help=_("Utilitaire en ligne de commande pour la gestion des projets MaX") ) app = typer.Typer(help=_(CLI_MAIN_HELP)) def _sync_bundles(root_directory: Path): Loading Loading @@ -391,43 +386,11 @@ def _sync_max_instance(root_directory: Path, verbose=True): ) @app.command(help=_("Initialisation d'une instance existante de MaX")) def sync( directory: Annotated[ Optional[Path], typer.Argument(help=_("chemin vers un dossier")) ] = os.getcwd(), ): ensure_java() root_directory, is_max = ensure_available_max_directory(directory) if is_max: _sync_max_instance(root_directory) climax_db.save(MaxInstall(None, str(root_directory.resolve()))) climax_db.commit() else: print( _( "Le dossier ne contient pas une instance de MaX. Utiliser la commande new" @app.command( help=_( "Création d'une nouvelle instance de MaX\n\nL'option --interactive propose un menu pour choisir sa configuration." ) ) raise typer.Exit() def _choose_between(values: List[str], label: str = "") -> str: try: from simple_term_menu import TerminalMenu terminal_menu = TerminalMenu(values, title=label) menu_entry_index = terminal_menu.show() return values[menu_entry_index] except NotImplementedError: # mainly windows choice = None while choice not in values: choice = typer.prompt("{} ({})".format(_(label), ", ".join(values))) return choice @app.command(help=_("Création d'une nouvelle instance de MaX")) def new( directory: Annotated[ Optional[Path], typer.Argument(help=_("chemin vers un dossier")) Loading Loading @@ -457,15 +420,17 @@ def new( _install_new_max_instance(root_directory, init_values) @app.command( help=_("Installe une édition de démonstration dans l'instance de MaX en cours") ) def demo(): check_cwd_is_max() @app.command(help=_("Installe une édition de démonstration.")) def demo( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) if typer.confirm( _("Voulez-vous installer une édition de démonstration ?"), default=False ): cur_dir = os.getcwd() cur_dir = directory config = MaXProjectConfig(Path(cur_dir, "config.xml")) with tempfile.TemporaryDirectory() as tmpdirname: zip_destination = Path(tmpdirname, "max.zip") Loading Loading @@ -493,23 +458,11 @@ def demo(): print(_("Vous pouvez démarrer MaX avec la commande [bold]climax start[/bold]")) @app.command(help=_("Arrête l'instance de MaX du dossier en cours")) def stop(http_stop_port: int = STOP_PORT): check_cwd_is_max() java_bin_path = ensure_java() process_args = [ str(java_bin_path), "-cp", cp_paths(), "-Xmx2g", "org.basex.BaseXHTTP", f"-s{http_stop_port}", "stop", ] subprocess.run(process_args) @app.command(help=_("Démarre l'instance de MaX du dossier en cours")) @app.command( help=_( "Démarre l'instance de MaX.\n\nSi les ports choisis ne sont pas disponibles, climax tentera de lancer le serveur sur d'autres ports." ) ) def start( http_host: str = WEB_HOST, http_port: int = WEB_PORT, Loading @@ -523,18 +476,21 @@ def start( ) ), ] = False, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): basex_port = _closer_free_port_to(basex_port) http_port = _closer_free_port_to(http_port) if http_stop_port <= http_port: http_stop_port = http_port + 1 http_stop_port = _closer_free_port_to(http_stop_port) check_cwd_is_max() check_dir_is_max(directory) java_bin_path = ensure_java() process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseXHTTP", f"-p{basex_port}", Loading @@ -552,18 +508,49 @@ def start( subprocess.run(process_args) @app.command(help=_("Efface le cache de climax")) def cache_clear(): for p in CACHE_DIR.iterdir(): if p.is_file(): p.unlink(missing_ok=True) shutil.rmtree(Path(USER_MAX_DIR, "max"), ignore_errors=True) def _choose_between(values: List[str], label: str = "") -> str: try: from simple_term_menu import TerminalMenu terminal_menu = TerminalMenu(values, title=label) menu_entry_index = terminal_menu.show() return values[menu_entry_index] except NotImplementedError: # mainly windows choice = None while choice not in values: choice = typer.prompt("{} ({})".format(_(label), ", ".join(values))) return choice @app.command(help=_("Arrête l'instance de MaX")) def stop( http_stop_port: int = STOP_PORT, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) java_bin_path = ensure_java() process_args = [ str(java_bin_path), "-cp", cp_paths(directory), "-Xmx2g", "org.basex.BaseXHTTP", f"-s{http_stop_port}", "stop", ] subprocess.run(process_args) @app.command(help=_("Affiche la configuration de MaX")) def info(): check_cwd_is_max() config = max_config() def info( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) console = Console() table = Table(_("Nom"), _("Valeur"), show_lines=True) table.add_row(_("Version de MaX"), config.max_version.get("name")) Loading @@ -575,19 +562,25 @@ def info(): console.print(table) @app.command(help=_("Fait une copie HTML statique du projet dans le dossier")) @app.command(help=_("Fait une copie HTML statique")) def freeze( directory: Annotated[ Optional[Path], typer.Argument(help=_("chemin vers un dossier")) ] = Path(os.getcwd(), "output"), debug: bool = False, ): max_config() max_config(directory) # start server on specific port port_number = _free_port() stop_port = port_number + 1 stop_port = _closer_free_port_to(stop_port) start(WEB_HOST, port_number, http_stop_port=stop_port, service=True) start( WEB_HOST, port_number, http_stop_port=stop_port, service=True, directory=directory, ) # copy website try: start_url = f"http://localhost:{port_number}/" Loading @@ -596,31 +589,18 @@ def freeze( stop(stop_port) raise e # stop server stop(stop_port) stop(stop_port, directory) print("[green]" + _("Site copié dans {}").format(str(directory)) + "[/green]") @app.command(help=_("Supprime un bundle pour l'instance de Max en cours")) def bundles_remove(bundle_name: str): check_cwd_is_max() config = max_config() keep_bundles = {} bundle_name = bundle_name.lower().strip() if bundle_name not in config.bundles.keys(): print(_("[red]{} n'est pas un bundle actif[/red]").format(bundle_name)) raise typer.Exit(code=1) for active_bundle_name, active_bundle_url in config.bundles.items(): if active_bundle_name.strip() != bundle_name.strip(): keep_bundles[active_bundle_name] = active_bundle_url config.bundles = keep_bundles config.write() bundles_list() @app.command(help=_("Liste les bundles disponibles")) def bundles_list(): check_cwd_is_max() config = max_config() def bundles_list( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) console = Console() table = Table(_("Nom"), _("Installé"), _("Description"), show_lines=True) bundles_done = {} Loading @@ -646,11 +626,16 @@ def bundles_list(): console.print(table) @app.command(help=_("Ajoute un bundle pour l'instance de Max en cours")) def bundles_add(bundle_name: str): @app.command(help=_("Ajoute un bundle")) def bundles_add( bundle_name: str, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): from_archive = None check_cwd_is_max() config = max_config() check_dir_is_max(directory) config = max_config(directory) current_bundles_config = config.bundles # bundle_name is a local archive if bundle_name.endswith(".zip") and Path(bundle_name).is_file(): Loading @@ -671,7 +656,7 @@ def bundles_add(bundle_name: str): print(_("[red]{} n'est pas un bundle[/red]").format(from_archive)) raise typer.Exit(code=1) local_destination = Path( os.getcwd(), directory, ".max", "resources", "local_bundles", Loading @@ -685,8 +670,8 @@ def bundles_add(bundle_name: str): } config.bundles = current_bundles_config config.write() _sync_max_instance(os.getcwd(), verbose=False) bundles_list() _sync_max_instance(directory, verbose=False) bundles_list(directory) else: if bundle_name not in config.available_bundles.keys(): print(_("[red]{} n'est pas un bundle disponible[/red]").format(bundle_name)) Loading @@ -705,13 +690,40 @@ def bundles_add(bundle_name: str): } config.bundles = current_bundles_config config.write() _sync_max_instance(os.getcwd(), verbose=False) _sync_max_instance(directory, verbose=False) bundles_list() @app.command(help=_("Ajoute un fichier ou un dossier XML à l'instance de Max en cours")) def feed(feed_path: Path): check_cwd_is_max() @app.command(help=_("Supprime un bundle")) def bundles_remove( bundle_name: str, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) keep_bundles = {} bundle_name = bundle_name.lower().strip() if bundle_name not in config.bundles.keys(): print(_("[red]{} n'est pas un bundle actif[/red]").format(bundle_name)) raise typer.Exit(code=1) for active_bundle_name, active_bundle_url in config.bundles.items(): if active_bundle_name.strip() != bundle_name.strip(): keep_bundles[active_bundle_name] = active_bundle_url config.bundles = keep_bundles config.write() bundles_list() @app.command(help=_("Ajoute un fichier ou un dossier XML")) def feed( feed_path: Path, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) java_bin_path = ensure_java() feed_path = Path(feed_path).resolve() if not feed_path.is_file() and not feed_path.is_dir(): Loading @@ -720,7 +732,7 @@ def feed(feed_path: Path): process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseX", "if(not(db:exists('max'))) then db:create('max') else ()", Loading @@ -731,7 +743,7 @@ def feed(feed_path: Path): process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseX", f"db:put('max', '{feed_path}', '{feed_path.name}')", Loading @@ -744,7 +756,7 @@ def feed(feed_path: Path): process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseX", f"db:put('max', '{f}', '{str(f)[offset:]}')", Loading @@ -753,27 +765,61 @@ def feed(feed_path: Path): subprocess.run(process_args) @app.command(help=_("Lance le client de BaseX")) def basex(): check_cwd_is_max() @app.command( help=_( "Initialisation d'une instance existante de MaX.\n\nTélécharge et installe les dépendances nécessaires ainsi que les bundles configurés." ) ) def sync( directory: Annotated[ Optional[Path], typer.Argument(help=_("chemin vers un dossier")) ] = os.getcwd(), ): ensure_java() root_directory, is_max = ensure_available_max_directory(directory) if is_max: _sync_max_instance(root_directory) climax_db.save(MaxInstall(None, str(root_directory.resolve()))) climax_db.commit() else: print( _( "Le dossier ne contient pas une instance de MaX. Utiliser la commande new" ) ) raise typer.Exit() @app.command(help=_("Lance le shell de BaseX")) def basex( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) java_bin_path = ensure_java() process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseX", ] subprocess.run(process_args) @app.command(help=_("Liste les templates du bundle de vocabulaire en cours.")) def templates_list(): check_cwd_is_max() config = max_config() @app.command(help=_("Liste les templates du bundle de vocabulaire")) def templates_list( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) vocab_bundle = config.vocabulary_bundle tpl_dir = Path( os.getcwd(), directory, ".max", "basex", "webapp", Loading @@ -792,16 +838,18 @@ def templates_list(): @app.command( help=_( "Liste les fichiers statiques (js, css, etc) du bundle de vocabulaire en cours." ) help=_("Liste les fichiers statiques (js, css, etc) du bundle de vocabulaire") ) def static_list(): check_cwd_is_max() config = max_config() def static_list( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) vocab_bundle = config.vocabulary_bundle tpl_dir = Path( os.getcwd(), directory, ".max", "basex", "webapp", Loading Loading @@ -833,6 +881,14 @@ def projects(): console.print(table) @app.command(help=_("Efface le cache de climax")) def cache_clear(): for p in CACHE_DIR.iterdir(): if p.is_file(): p.unlink(missing_ok=True) shutil.rmtree(Path(USER_MAX_DIR, "max"), ignore_errors=True) # @app.command(help=_("Application web (test)")) # def ui(max_dir: str = None): # from .gui import app Loading src/climax/config.py +6 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,12 @@ logger = logging.getLogger(__name__) GITLAB_API_READ_TOKEN = "glpat-5BCYCid1WaxxBgax-7VW" CLI_MAIN_HELP = """Utilitaire en ligne de commande pour la gestion des projets MaX. La plupart des commandes sont à lancer dans le dossier du projet MaX, à l'exception des commandes new, projects et cache-clear qui peuvent être lancées aussi en dehors d'un dossier MaX. """ WELCOME_PAGE = """ <h1>Bienvenue dans MaX !</h1> <p> Loading Loading
src/climax/__main__.py +196 −140 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ from .config import ( max_releases, max_release, latest_max_release, CLI_MAIN_HELP, ) locales_dir = Path(__file__).parent / "locales" Loading Loading @@ -97,8 +98,8 @@ def class_path_separator() -> str: @cache def cp_paths() -> str: basex_dir_path = Path(os.getcwd(), ".max", "basex") def cp_paths(working_dir: str = os.getcwd()) -> str: basex_dir_path = Path(working_dir, ".max", "basex") paths = class_path_separator().join( [ str(Path(basex_dir_path, "BaseX.jar")), Loading @@ -116,9 +117,7 @@ def find_jdk(cur_sys: str = None) -> Optional[str]: return JAVA_DISTROS.get(cur_sys, None) def dir_is_max(directory: Path = None) -> bool: if directory is None: directory = os.getcwd() def dir_is_max(directory: Path = os.getcwd()) -> bool: directory = Path(directory) config_file = Path(directory, "config.xml") if config_file.exists(): Loading @@ -132,16 +131,16 @@ def dir_is_max(directory: Path = None) -> bool: return False def check_cwd_is_max(): if not dir_is_max(): def check_dir_is_max(directory): if not dir_is_max(directory): print( "[red]{}[/red]".format(_("Le dossier n'est pas une installation de MaX.")) ) raise typer.Exit(code=1) def max_config() -> MaXProjectConfig: return MaXProjectConfig(Path(os.getcwd(), MAX_CONFIG_FILE)) def max_config(directory: str = os.getcwd()) -> MaXProjectConfig: return MaXProjectConfig(Path(directory, MAX_CONFIG_FILE)) def unzip(source: Union[Path, str], destination: Union[Path, str]) -> bool: Loading Loading @@ -213,9 +212,7 @@ def ensure_java() -> Path: return java_bin def ensure_available_max_directory(directory: Optional[Path]) -> tuple[Path, bool]: if not directory: directory = os.getcwd() def ensure_available_max_directory(directory: str = os.getcwd()) -> tuple[Path, bool]: directory = Path(directory) if not directory.exists(): directory.mkdir(parents=True, exist_ok=False) Loading @@ -234,9 +231,7 @@ def ensure_available_max_directory(directory: Optional[Path]) -> tuple[Path, boo return directory, is_max app = typer.Typer( help=_("Utilitaire en ligne de commande pour la gestion des projets MaX") ) app = typer.Typer(help=_(CLI_MAIN_HELP)) def _sync_bundles(root_directory: Path): Loading Loading @@ -391,43 +386,11 @@ def _sync_max_instance(root_directory: Path, verbose=True): ) @app.command(help=_("Initialisation d'une instance existante de MaX")) def sync( directory: Annotated[ Optional[Path], typer.Argument(help=_("chemin vers un dossier")) ] = os.getcwd(), ): ensure_java() root_directory, is_max = ensure_available_max_directory(directory) if is_max: _sync_max_instance(root_directory) climax_db.save(MaxInstall(None, str(root_directory.resolve()))) climax_db.commit() else: print( _( "Le dossier ne contient pas une instance de MaX. Utiliser la commande new" @app.command( help=_( "Création d'une nouvelle instance de MaX\n\nL'option --interactive propose un menu pour choisir sa configuration." ) ) raise typer.Exit() def _choose_between(values: List[str], label: str = "") -> str: try: from simple_term_menu import TerminalMenu terminal_menu = TerminalMenu(values, title=label) menu_entry_index = terminal_menu.show() return values[menu_entry_index] except NotImplementedError: # mainly windows choice = None while choice not in values: choice = typer.prompt("{} ({})".format(_(label), ", ".join(values))) return choice @app.command(help=_("Création d'une nouvelle instance de MaX")) def new( directory: Annotated[ Optional[Path], typer.Argument(help=_("chemin vers un dossier")) Loading Loading @@ -457,15 +420,17 @@ def new( _install_new_max_instance(root_directory, init_values) @app.command( help=_("Installe une édition de démonstration dans l'instance de MaX en cours") ) def demo(): check_cwd_is_max() @app.command(help=_("Installe une édition de démonstration.")) def demo( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) if typer.confirm( _("Voulez-vous installer une édition de démonstration ?"), default=False ): cur_dir = os.getcwd() cur_dir = directory config = MaXProjectConfig(Path(cur_dir, "config.xml")) with tempfile.TemporaryDirectory() as tmpdirname: zip_destination = Path(tmpdirname, "max.zip") Loading Loading @@ -493,23 +458,11 @@ def demo(): print(_("Vous pouvez démarrer MaX avec la commande [bold]climax start[/bold]")) @app.command(help=_("Arrête l'instance de MaX du dossier en cours")) def stop(http_stop_port: int = STOP_PORT): check_cwd_is_max() java_bin_path = ensure_java() process_args = [ str(java_bin_path), "-cp", cp_paths(), "-Xmx2g", "org.basex.BaseXHTTP", f"-s{http_stop_port}", "stop", ] subprocess.run(process_args) @app.command(help=_("Démarre l'instance de MaX du dossier en cours")) @app.command( help=_( "Démarre l'instance de MaX.\n\nSi les ports choisis ne sont pas disponibles, climax tentera de lancer le serveur sur d'autres ports." ) ) def start( http_host: str = WEB_HOST, http_port: int = WEB_PORT, Loading @@ -523,18 +476,21 @@ def start( ) ), ] = False, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): basex_port = _closer_free_port_to(basex_port) http_port = _closer_free_port_to(http_port) if http_stop_port <= http_port: http_stop_port = http_port + 1 http_stop_port = _closer_free_port_to(http_stop_port) check_cwd_is_max() check_dir_is_max(directory) java_bin_path = ensure_java() process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseXHTTP", f"-p{basex_port}", Loading @@ -552,18 +508,49 @@ def start( subprocess.run(process_args) @app.command(help=_("Efface le cache de climax")) def cache_clear(): for p in CACHE_DIR.iterdir(): if p.is_file(): p.unlink(missing_ok=True) shutil.rmtree(Path(USER_MAX_DIR, "max"), ignore_errors=True) def _choose_between(values: List[str], label: str = "") -> str: try: from simple_term_menu import TerminalMenu terminal_menu = TerminalMenu(values, title=label) menu_entry_index = terminal_menu.show() return values[menu_entry_index] except NotImplementedError: # mainly windows choice = None while choice not in values: choice = typer.prompt("{} ({})".format(_(label), ", ".join(values))) return choice @app.command(help=_("Arrête l'instance de MaX")) def stop( http_stop_port: int = STOP_PORT, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) java_bin_path = ensure_java() process_args = [ str(java_bin_path), "-cp", cp_paths(directory), "-Xmx2g", "org.basex.BaseXHTTP", f"-s{http_stop_port}", "stop", ] subprocess.run(process_args) @app.command(help=_("Affiche la configuration de MaX")) def info(): check_cwd_is_max() config = max_config() def info( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) console = Console() table = Table(_("Nom"), _("Valeur"), show_lines=True) table.add_row(_("Version de MaX"), config.max_version.get("name")) Loading @@ -575,19 +562,25 @@ def info(): console.print(table) @app.command(help=_("Fait une copie HTML statique du projet dans le dossier")) @app.command(help=_("Fait une copie HTML statique")) def freeze( directory: Annotated[ Optional[Path], typer.Argument(help=_("chemin vers un dossier")) ] = Path(os.getcwd(), "output"), debug: bool = False, ): max_config() max_config(directory) # start server on specific port port_number = _free_port() stop_port = port_number + 1 stop_port = _closer_free_port_to(stop_port) start(WEB_HOST, port_number, http_stop_port=stop_port, service=True) start( WEB_HOST, port_number, http_stop_port=stop_port, service=True, directory=directory, ) # copy website try: start_url = f"http://localhost:{port_number}/" Loading @@ -596,31 +589,18 @@ def freeze( stop(stop_port) raise e # stop server stop(stop_port) stop(stop_port, directory) print("[green]" + _("Site copié dans {}").format(str(directory)) + "[/green]") @app.command(help=_("Supprime un bundle pour l'instance de Max en cours")) def bundles_remove(bundle_name: str): check_cwd_is_max() config = max_config() keep_bundles = {} bundle_name = bundle_name.lower().strip() if bundle_name not in config.bundles.keys(): print(_("[red]{} n'est pas un bundle actif[/red]").format(bundle_name)) raise typer.Exit(code=1) for active_bundle_name, active_bundle_url in config.bundles.items(): if active_bundle_name.strip() != bundle_name.strip(): keep_bundles[active_bundle_name] = active_bundle_url config.bundles = keep_bundles config.write() bundles_list() @app.command(help=_("Liste les bundles disponibles")) def bundles_list(): check_cwd_is_max() config = max_config() def bundles_list( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) console = Console() table = Table(_("Nom"), _("Installé"), _("Description"), show_lines=True) bundles_done = {} Loading @@ -646,11 +626,16 @@ def bundles_list(): console.print(table) @app.command(help=_("Ajoute un bundle pour l'instance de Max en cours")) def bundles_add(bundle_name: str): @app.command(help=_("Ajoute un bundle")) def bundles_add( bundle_name: str, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): from_archive = None check_cwd_is_max() config = max_config() check_dir_is_max(directory) config = max_config(directory) current_bundles_config = config.bundles # bundle_name is a local archive if bundle_name.endswith(".zip") and Path(bundle_name).is_file(): Loading @@ -671,7 +656,7 @@ def bundles_add(bundle_name: str): print(_("[red]{} n'est pas un bundle[/red]").format(from_archive)) raise typer.Exit(code=1) local_destination = Path( os.getcwd(), directory, ".max", "resources", "local_bundles", Loading @@ -685,8 +670,8 @@ def bundles_add(bundle_name: str): } config.bundles = current_bundles_config config.write() _sync_max_instance(os.getcwd(), verbose=False) bundles_list() _sync_max_instance(directory, verbose=False) bundles_list(directory) else: if bundle_name not in config.available_bundles.keys(): print(_("[red]{} n'est pas un bundle disponible[/red]").format(bundle_name)) Loading @@ -705,13 +690,40 @@ def bundles_add(bundle_name: str): } config.bundles = current_bundles_config config.write() _sync_max_instance(os.getcwd(), verbose=False) _sync_max_instance(directory, verbose=False) bundles_list() @app.command(help=_("Ajoute un fichier ou un dossier XML à l'instance de Max en cours")) def feed(feed_path: Path): check_cwd_is_max() @app.command(help=_("Supprime un bundle")) def bundles_remove( bundle_name: str, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) keep_bundles = {} bundle_name = bundle_name.lower().strip() if bundle_name not in config.bundles.keys(): print(_("[red]{} n'est pas un bundle actif[/red]").format(bundle_name)) raise typer.Exit(code=1) for active_bundle_name, active_bundle_url in config.bundles.items(): if active_bundle_name.strip() != bundle_name.strip(): keep_bundles[active_bundle_name] = active_bundle_url config.bundles = keep_bundles config.write() bundles_list() @app.command(help=_("Ajoute un fichier ou un dossier XML")) def feed( feed_path: Path, directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) java_bin_path = ensure_java() feed_path = Path(feed_path).resolve() if not feed_path.is_file() and not feed_path.is_dir(): Loading @@ -720,7 +732,7 @@ def feed(feed_path: Path): process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseX", "if(not(db:exists('max'))) then db:create('max') else ()", Loading @@ -731,7 +743,7 @@ def feed(feed_path: Path): process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseX", f"db:put('max', '{feed_path}', '{feed_path.name}')", Loading @@ -744,7 +756,7 @@ def feed(feed_path: Path): process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseX", f"db:put('max', '{f}', '{str(f)[offset:]}')", Loading @@ -753,27 +765,61 @@ def feed(feed_path: Path): subprocess.run(process_args) @app.command(help=_("Lance le client de BaseX")) def basex(): check_cwd_is_max() @app.command( help=_( "Initialisation d'une instance existante de MaX.\n\nTélécharge et installe les dépendances nécessaires ainsi que les bundles configurés." ) ) def sync( directory: Annotated[ Optional[Path], typer.Argument(help=_("chemin vers un dossier")) ] = os.getcwd(), ): ensure_java() root_directory, is_max = ensure_available_max_directory(directory) if is_max: _sync_max_instance(root_directory) climax_db.save(MaxInstall(None, str(root_directory.resolve()))) climax_db.commit() else: print( _( "Le dossier ne contient pas une instance de MaX. Utiliser la commande new" ) ) raise typer.Exit() @app.command(help=_("Lance le shell de BaseX")) def basex( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) java_bin_path = ensure_java() process_args = [ str(java_bin_path), "-cp", cp_paths(), cp_paths(directory), "-Xmx2g", "org.basex.BaseX", ] subprocess.run(process_args) @app.command(help=_("Liste les templates du bundle de vocabulaire en cours.")) def templates_list(): check_cwd_is_max() config = max_config() @app.command(help=_("Liste les templates du bundle de vocabulaire")) def templates_list( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) vocab_bundle = config.vocabulary_bundle tpl_dir = Path( os.getcwd(), directory, ".max", "basex", "webapp", Loading @@ -792,16 +838,18 @@ def templates_list(): @app.command( help=_( "Liste les fichiers statiques (js, css, etc) du bundle de vocabulaire en cours." ) help=_("Liste les fichiers statiques (js, css, etc) du bundle de vocabulaire") ) def static_list(): check_cwd_is_max() config = max_config() def static_list( directory: Annotated[ str, typer.Option(help=_("Dossier du projet MaX")) ] = os.getcwd(), ): check_dir_is_max(directory) config = max_config(directory) vocab_bundle = config.vocabulary_bundle tpl_dir = Path( os.getcwd(), directory, ".max", "basex", "webapp", Loading Loading @@ -833,6 +881,14 @@ def projects(): console.print(table) @app.command(help=_("Efface le cache de climax")) def cache_clear(): for p in CACHE_DIR.iterdir(): if p.is_file(): p.unlink(missing_ok=True) shutil.rmtree(Path(USER_MAX_DIR, "max"), ignore_errors=True) # @app.command(help=_("Application web (test)")) # def ui(max_dir: str = None): # from .gui import app Loading
src/climax/config.py +6 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,12 @@ logger = logging.getLogger(__name__) GITLAB_API_READ_TOKEN = "glpat-5BCYCid1WaxxBgax-7VW" CLI_MAIN_HELP = """Utilitaire en ligne de commande pour la gestion des projets MaX. La plupart des commandes sont à lancer dans le dossier du projet MaX, à l'exception des commandes new, projects et cache-clear qui peuvent être lancées aussi en dehors d'un dossier MaX. """ WELCOME_PAGE = """ <h1>Bienvenue dans MaX !</h1> <p> Loading