[UPD] TODO: auto installation
- better script message first execution - search pycharm-community - calculate time execution - integrate crash diagnostic at importation - show version installed and show installation option into cli
This commit is contained in:
parent
0ac7728d2f
commit
fc73d0b9bd
2 changed files with 366 additions and 83 deletions
|
|
@ -1,5 +1,23 @@
|
|||
#!/bin/bash
|
||||
DIR_VENV_ERPLIBRE_EXIST=1
|
||||
DIR_VENV_ERPLIBRE=".venv.erplibre"
|
||||
# If not exist, create it and do installation
|
||||
# Can be in conflict with ./script/install_locally.sh
|
||||
|
||||
source .venv/bin/activate
|
||||
if [[ ! -d "$DIR_VENV_ERPLIBRE" ]]; then
|
||||
DIR_VENV_ERPLIBRE_EXIST=0
|
||||
echo "$DIR_VENV_ERPLIBRE does not exist."
|
||||
if [[ ! -d "~/.pyenv/versions/$(< ./conf/python-erplibre-version)/bin/python" ]]; then
|
||||
"~/.pyenv/versions/$(< ./conf/python-erplibre-version)/bin/python" -m venv $DIR_VENV_ERPLIBRE
|
||||
else
|
||||
python -m venv $DIR_VENV_ERPLIBRE
|
||||
fi
|
||||
fi
|
||||
|
||||
# If exist, source it and start installation
|
||||
source ./.venv.erplibre/bin/activate
|
||||
if [[ $DIR_VENV_ERPLIBRE_EXIST -eq 0 ]]; then
|
||||
pip install -r requirement/erplibre_require-ments.txt
|
||||
fi
|
||||
|
||||
./script/todo/todo.py
|
||||
|
|
|
|||
|
|
@ -1,89 +1,46 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import datetime
|
||||
import getpass
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
file_error_path = ".erplibre.error.txt"
|
||||
cst_venv_erplibre = ".venv.erplibre"
|
||||
VERSION_DATA_FILE = os.path.join("conf", "supported_version_erplibre.json")
|
||||
INSTALLED_ODOO_VERSION_FILE = os.path.join(
|
||||
".repo", "installed_odoo_version.txt"
|
||||
)
|
||||
ODOO_VERSION_FILE = os.path.join(".odoo-version")
|
||||
ENABLE_CRASH = False
|
||||
CRASH_E = None
|
||||
|
||||
try:
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
|
||||
import click
|
||||
import humanize
|
||||
import openai
|
||||
from pykeepass import PyKeePass
|
||||
|
||||
# TODO implement urwid to improve text user interface
|
||||
# import urwid
|
||||
# TODO implement rich for beautiful print and table
|
||||
# import rich
|
||||
except ModuleNotFoundError as e:
|
||||
# TODO auto-detect gnome-terminal, or choose another.
|
||||
if os.path.exists(".venv"):
|
||||
print("You forgot to activate source \nsource ./.venv/bin/activate")
|
||||
time.sleep(0.5)
|
||||
subprocess.run(
|
||||
"gnome-terminal -- bash -c './script/todo/source_todo.sh'",
|
||||
shell=True,
|
||||
executable="/bin/bash",
|
||||
)
|
||||
else:
|
||||
first_installation_input = (
|
||||
input(
|
||||
"First installation? This will process system installation"
|
||||
" before (Y/N): "
|
||||
)
|
||||
.strip()
|
||||
.upper()
|
||||
)
|
||||
if first_installation_input == "Y":
|
||||
subprocess.run(
|
||||
"gnome-terminal -- bash -c"
|
||||
" './script/version/update_env_version.py --install;bash'",
|
||||
shell=True,
|
||||
executable="/bin/bash",
|
||||
)
|
||||
print("Wait after OS installation before continue.")
|
||||
humanize = None
|
||||
ENABLE_CRASH = True
|
||||
CRASH_E = e
|
||||
|
||||
# First detect pycharm, need to be open before installation and close to increase speed
|
||||
result = subprocess.run(
|
||||
["which", "pycharm"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
if result.returncode == 0 and not os.path.exists(".idea"):
|
||||
pycharm_configuration_input = (
|
||||
input("Open Pycharm? (Y/N): ").strip().upper()
|
||||
)
|
||||
if pycharm_configuration_input == "Y":
|
||||
subprocess.run(
|
||||
"gnome-terminal -- bash -c 'pycharm .'",
|
||||
shell=True,
|
||||
executable="/bin/bash",
|
||||
)
|
||||
print(
|
||||
"Close Pycharm when processing is done before continue"
|
||||
" this guide."
|
||||
)
|
||||
# Propose Odoo installation
|
||||
# TODO detect last version supported
|
||||
odoo_installation_input = (
|
||||
input("Install Odoo 16? (Y/N): ").strip().upper()
|
||||
)
|
||||
if odoo_installation_input == "Y":
|
||||
subprocess.run(
|
||||
"gnome-terminal -- bash -c 'make install_odoo_16;bash'",
|
||||
shell=True,
|
||||
executable="/bin/bash",
|
||||
)
|
||||
print("Wait after installation and open projects by terminal.")
|
||||
print("make open_terminal")
|
||||
else:
|
||||
print("Nothing to do, you need a fresh installation to continue.")
|
||||
sys.exit(0)
|
||||
sys.exit(1)
|
||||
if not ENABLE_CRASH:
|
||||
print("Importation success!")
|
||||
|
||||
# TODO implement urwid to improve text user interface
|
||||
# import urwid
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_FILE = "./script/todo/todo.json"
|
||||
|
|
@ -94,6 +51,30 @@ LOGO_ASCII_FILE = "./script/todo/logo_ascii.txt"
|
|||
class TODO:
|
||||
def __init__(self):
|
||||
self.kdbx = None
|
||||
self.init()
|
||||
|
||||
def init(self):
|
||||
# Get command
|
||||
self.cmd_source_erplibre = ""
|
||||
exec_path_gnome_terminal = shutil.which("gnome-terminal")
|
||||
if exec_path_gnome_terminal:
|
||||
self.cmd_source_erplibre = (
|
||||
f"gnome-terminal -- bash -c 'source"
|
||||
f" ./{cst_venv_erplibre}/bin/activate;%s'"
|
||||
)
|
||||
else:
|
||||
exec_path_tell = shutil.which("osascript")
|
||||
if exec_path_tell:
|
||||
self.cmd_source_erplibre = (
|
||||
"osascript -e 'tell application \"Terminal\"'"
|
||||
)
|
||||
self.cmd_source_erplibre += " -e 'tell application \"System Events\" to keystroke \"PATH\" using {command down}' -e 'delay 0.1' -e 'do script \""
|
||||
self.cmd_source_erplibre += f"./{cst_venv_erplibre}/bin/activate; %s\" in front window'"
|
||||
self.cmd_source_erplibre += " -e 'end tell'"
|
||||
else:
|
||||
self.cmd_source_erplibre = (
|
||||
f"source ./{cst_venv_erplibre}/bin/activate;%s"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
with open(LOGO_ASCII_FILE) as my_file:
|
||||
|
|
@ -102,26 +83,38 @@ class TODO:
|
|||
print("🤖 => Entre tes directives par son chiffre et fait Entrée!")
|
||||
help_info = """Commande :
|
||||
[1] Execute
|
||||
[2] Question
|
||||
[3] Fork - Ouvre TODO 🤖 dans une nouvelle tabulation
|
||||
[2] Install
|
||||
[3] Question
|
||||
[4] Fork - Ouvre TODO 🤖 dans une nouvelle tabulation
|
||||
[0] Quitter
|
||||
"""
|
||||
# [3] install
|
||||
while True:
|
||||
status = click.prompt(help_info)
|
||||
try:
|
||||
status = click.prompt(help_info)
|
||||
except NameError:
|
||||
print("Do")
|
||||
print("source .venv.erplibre/bin/activate && make")
|
||||
sys.exit(1)
|
||||
except ImportError:
|
||||
print("Do")
|
||||
print("source .venv.erplibre/bin/activate && make")
|
||||
sys.exit(1)
|
||||
print()
|
||||
if status == "0":
|
||||
break
|
||||
elif status == "1":
|
||||
self.prompt_execute()
|
||||
elif status == "2":
|
||||
self.execute_prompt_ia()
|
||||
self.prompt_install()
|
||||
elif status == "3":
|
||||
cmd = (
|
||||
f"gnome-terminal --tab -- bash -c 'source"
|
||||
f" ./.venv/bin/activate;make todo'"
|
||||
)
|
||||
self.executer_commande_live(cmd)
|
||||
self.execute_prompt_ia()
|
||||
elif status == "4":
|
||||
# cmd = (
|
||||
# f"gnome-terminal --tab -- bash -c 'source"
|
||||
# f" ./{cst_venv_erplibre}/bin/activate;make todo'"
|
||||
# )
|
||||
cmd = "make todo"
|
||||
self.executer_commande_live(cmd, source_erplibre=True)
|
||||
# elif status == "3" or status == "install":
|
||||
# print("install")
|
||||
else:
|
||||
|
|
@ -236,6 +229,164 @@ class TODO:
|
|||
else:
|
||||
print("Commande non trouvée 🤖!")
|
||||
|
||||
def prompt_install(self):
|
||||
print("Detect first installation from code source.")
|
||||
|
||||
first_installation_input = (
|
||||
input(
|
||||
"First system installation? This will process system installation"
|
||||
" before (Y/N): "
|
||||
)
|
||||
.strip()
|
||||
.upper()
|
||||
)
|
||||
if first_installation_input == "Y":
|
||||
cmd = "./script/version/update_env_version.py --install"
|
||||
self.executer_commande_live(cmd, source_erplibre=True)
|
||||
print("Wait after OS installation before continue.")
|
||||
|
||||
# First detect pycharm, need to be open before installation and close to increase speed
|
||||
has_pycharm = False
|
||||
has_pycharm_community = False
|
||||
result = subprocess.run(
|
||||
["which", "pycharm"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
has_pycharm = True
|
||||
else:
|
||||
result = subprocess.run(
|
||||
["which", "pycharm-community"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
has_pycharm_community = result.returncode == 0
|
||||
if (has_pycharm or has_pycharm_community) and not os.path.exists(
|
||||
".idea"
|
||||
):
|
||||
pycharm_configuration_input = (
|
||||
input("Open Pycharm? (Y/N): ").strip().upper()
|
||||
)
|
||||
if pycharm_configuration_input == "Y":
|
||||
pycharm_bin = "pycharm" if has_pycharm else "pycharm-community"
|
||||
self.executer_commande_live(pycharm_bin, source_erplibre=True)
|
||||
print(
|
||||
"Close Pycharm when processing is done before continue"
|
||||
" this guide."
|
||||
)
|
||||
# Propose Odoo installation
|
||||
# TODO detect last version supported
|
||||
odoo_installation_input = (
|
||||
input("Install virtual environment? (Y/N): ").strip().upper()
|
||||
)
|
||||
if odoo_installation_input == "Y":
|
||||
# cmd_intern = "./script/install/install_erplibre.sh"
|
||||
# TODO maybe update q to only install erplibre from install_locally
|
||||
# TODO problem installing with q, the script depend on odoo
|
||||
key_i = 0
|
||||
dct_cmd_intern_begin = {
|
||||
"q": (
|
||||
"q",
|
||||
"q: ERPLibre only with system python without Odoo",
|
||||
"./script/install/install_erplibre.sh",
|
||||
),
|
||||
"w": (
|
||||
"w",
|
||||
"w: Install all Odoo version with ERPLibre",
|
||||
"make install_odoo_all_version",
|
||||
),
|
||||
}
|
||||
dct_final_cmd_intern = {}
|
||||
with open(VERSION_DATA_FILE) as txt:
|
||||
data_version = json.load(txt)
|
||||
|
||||
if not data_version:
|
||||
raise Exception(
|
||||
f"Internal error, no Odoo version is supported, please valide file '{VERSION_DATA_FILE}'"
|
||||
)
|
||||
|
||||
lst_version_transform = []
|
||||
for key, value in data_version.items():
|
||||
lst_version_transform.append(value)
|
||||
value["erplibre_version"] = key
|
||||
|
||||
lst_version_installed = []
|
||||
if os.path.exists(INSTALLED_ODOO_VERSION_FILE):
|
||||
with open(INSTALLED_ODOO_VERSION_FILE) as txt:
|
||||
lst_version_installed = sorted(txt.read().splitlines())
|
||||
|
||||
odoo_installed_version = None
|
||||
if os.path.exists(ODOO_VERSION_FILE):
|
||||
with open(ODOO_VERSION_FILE) as txt:
|
||||
odoo_installed_version = f"odoo{txt.read().strip()}"
|
||||
|
||||
# Add odoo version installation on command
|
||||
lst_version = sorted(
|
||||
lst_version_transform, key=lambda k: k.get("erplibre_version")
|
||||
)
|
||||
for dct_version in lst_version[::-1]:
|
||||
key_i += 1
|
||||
key_s = str(key_i)
|
||||
label = f"{key_s}: Odoo {dct_version.get('odoo_version')}"
|
||||
|
||||
odoo_version = f"odoo{dct_version.get('odoo_version')}"
|
||||
if odoo_version in lst_version_installed:
|
||||
label += " - Installed"
|
||||
if odoo_version == odoo_installed_version:
|
||||
label += " - Actual"
|
||||
if dct_version.get("default"):
|
||||
label += " - Default"
|
||||
if dct_version.get("is_deprecated"):
|
||||
label += " - Deprecated"
|
||||
erplibre_version = dct_version.get("erplibre_version")
|
||||
dct_cmd_intern_begin[key_s] = (
|
||||
key_s,
|
||||
label,
|
||||
f"./script/version/update_env_version.py --erplibre_version {erplibre_version} --install_dev",
|
||||
)
|
||||
|
||||
# Add final command
|
||||
dct_cmd_intern = {**dct_cmd_intern_begin, **dct_final_cmd_intern}
|
||||
|
||||
# Show command
|
||||
odoo_version_input = ""
|
||||
while odoo_version_input not in dct_cmd_intern.keys():
|
||||
if odoo_version_input:
|
||||
print(
|
||||
f"Error, cannot understand value '{odoo_version_input}'"
|
||||
)
|
||||
str_input_dyn_odoo_version = (
|
||||
"Choose a version:\n\t"
|
||||
+ "\n\t".join([a[1] for a in dct_cmd_intern.values()])
|
||||
+ "\nSelect : "
|
||||
)
|
||||
odoo_version_input = (
|
||||
input(str_input_dyn_odoo_version).strip().lower()
|
||||
)
|
||||
|
||||
cmd_intern = dct_cmd_intern.get(odoo_version_input)[2]
|
||||
print(f"Will execute :\n{cmd_intern}")
|
||||
|
||||
# TODO use external script to detect terminal to use on system
|
||||
# TODO check script open_terminal_code_generator.sh
|
||||
# cmd_extern = f"gnome-terminal -- bash -c '{cmd_intern};bash'"
|
||||
try:
|
||||
subprocess.run(
|
||||
cmd_intern, shell=True, executable="/bin/bash", check=True
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(
|
||||
f"Le script Bash «{cmd_intern}» a échoué avec le code de retour {e.returncode}."
|
||||
)
|
||||
print("Wait after installation and open projects by terminal.")
|
||||
print("make open_terminal")
|
||||
self.restart_script(str(e))
|
||||
else:
|
||||
print("Nothing to do, you need a fresh installation to continue.")
|
||||
|
||||
def execute_from_configuration(
|
||||
self, dct_instance, exec_run_db=False, ignore_makefile=False
|
||||
):
|
||||
|
|
@ -274,7 +425,6 @@ class TODO:
|
|||
help_info = "Commande :\n"
|
||||
help_end = "[0] Retour\n"
|
||||
for i, dct_instance in enumerate(lst_instance):
|
||||
|
||||
help_info += (
|
||||
f"[{i + 1}] " + dct_instance["prompt_description"] + "\n"
|
||||
)
|
||||
|
|
@ -459,17 +609,28 @@ class TODO:
|
|||
new_cmd += f' "sleep {1 * i};{cmd}"'
|
||||
self.executer_commande_live(new_cmd)
|
||||
|
||||
def executer_commande_live(self, commande):
|
||||
def executer_commande_live(self, commande, source_erplibre=True):
|
||||
"""
|
||||
Exécute une commande et affiche la sortie en direct.
|
||||
|
||||
Args:
|
||||
commande (str): La commande à exécuter (sous forme de chaîne de caractères).
|
||||
"""
|
||||
|
||||
if source_erplibre:
|
||||
# commande = f"source ./{cst_venv_erplibre}/bin/activate && " + commande
|
||||
# cmd = (
|
||||
# f"gnome-terminal --tab -- bash -c 'source"
|
||||
# f" ./{cst_venv_erplibre}/bin/activate;{commande}'"
|
||||
# )
|
||||
commande = self.cmd_source_erplibre % commande
|
||||
print(f"Execute : {commande}")
|
||||
# os.system(f"./script/terminal/open_terminal.sh {commande}")
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
commande,
|
||||
shell=True,
|
||||
executable="/bin/bash",
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True,
|
||||
|
|
@ -504,7 +665,111 @@ class TODO:
|
|||
except Exception as e:
|
||||
print(f"Une erreur s'est produite : {e}")
|
||||
|
||||
def crash_diagnostic(self, e):
|
||||
# TODO show message at start if os.path.exists(file_error_path)
|
||||
if os.path.exists(file_error_path) and not os.path.exists(
|
||||
cst_venv_erplibre
|
||||
):
|
||||
print("Got error : ")
|
||||
print(e)
|
||||
print("Got error at first execution.", file_error_path)
|
||||
try:
|
||||
file = open(file_error_path, "r")
|
||||
content = file.read()
|
||||
# TODO si vide, ajouter notre erreur
|
||||
print(content)
|
||||
except FileNotFoundError:
|
||||
print("Error: File not found.")
|
||||
finally:
|
||||
if "file" in locals() and file:
|
||||
file.close()
|
||||
# Force auto installation
|
||||
print("Auto installation")
|
||||
time.sleep(0.5)
|
||||
cmd = "./script/todo/source_todo.sh"
|
||||
# self.restart_script(e)
|
||||
self.executer_commande_live(cmd, source_erplibre=True)
|
||||
sys.exit(1)
|
||||
if os.path.exists(cst_venv_erplibre):
|
||||
print("Import error : ")
|
||||
print(e)
|
||||
# TODO auto-detect gnome-terminal, or choose another. Is it done already?
|
||||
self.restart_script(e)
|
||||
# self.prompt_install()
|
||||
|
||||
# print(
|
||||
# f"You forgot to activate source \nsource ./{cst_venv_erplibre}/bin/activate"
|
||||
# )
|
||||
# time.sleep(0.5)
|
||||
# cmd = "./script/todo/source_todo.sh"
|
||||
print("Re-execute TODO 🤖 or execute :")
|
||||
print()
|
||||
print(f"source {cst_venv_erplibre}/bin/activate;make")
|
||||
print()
|
||||
cmd = "./script/todo/todo.py"
|
||||
# # self.restart_script(e)
|
||||
try:
|
||||
# TODO duplicate
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
|
||||
import click
|
||||
import humanize
|
||||
import openai
|
||||
from pykeepass import PyKeePass
|
||||
except ImportError:
|
||||
print("Rerun and exit")
|
||||
self.executer_commande_live(cmd, source_erplibre=True)
|
||||
sys.exit(1)
|
||||
print("No error")
|
||||
else:
|
||||
self.prompt_install()
|
||||
|
||||
def restart_script(self, last_error):
|
||||
print("Reboot TODO 🤖...")
|
||||
# os.execv(sys.executable, ['python'] + sys.argv)
|
||||
# TODO mettre check que le répertoire est créé, s'il existe, auto-loop à corriger
|
||||
if os.path.exists(cst_venv_erplibre) and not os.path.exists(
|
||||
file_error_path
|
||||
):
|
||||
# TODO mettre check import suivant ne vont pas planter
|
||||
try:
|
||||
with open(file_error_path, "w") as f_file:
|
||||
f_file.write(str(last_error))
|
||||
pass # The file is created and closed here, no content is written
|
||||
print(
|
||||
f"Try to reopen process with before :\nsource ./{cst_venv_erplibre}/bin/activate && exec python "
|
||||
+ " ".join(sys.argv)
|
||||
)
|
||||
os.execv(
|
||||
"/bin/bash",
|
||||
[
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
f"source ./{cst_venv_erplibre}/bin/activate && exec python "
|
||||
+ " ".join(sys.argv),
|
||||
],
|
||||
)
|
||||
except Exception as e:
|
||||
print("Error detect at first execution.")
|
||||
print(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
todo = TODO()
|
||||
todo.run()
|
||||
start_time = time.time()
|
||||
try:
|
||||
todo = TODO()
|
||||
if ENABLE_CRASH:
|
||||
todo.crash_diagnostic(CRASH_E)
|
||||
todo.run()
|
||||
except KeyboardInterrupt:
|
||||
print("Keyboard interrupt")
|
||||
finally:
|
||||
end_time = time.time()
|
||||
duration_sec = end_time - start_time
|
||||
if humanize:
|
||||
duration_delta = datetime.timedelta(seconds=duration_sec)
|
||||
humain_time = humanize.precisedelta(duration_delta)
|
||||
print(f"\nTODO execution time {humain_time}\n")
|
||||
else:
|
||||
print(f"\nTODO execution time {duration_sec:.2f} sec.\n")
|
||||
|
|
|
|||
Loading…
Reference in a new issue