Start: Fix startup with new argparser
Since the full argparser requires pydantic, gate it until all dependencies are installed. Also if the venv is deleted, assume that start_options.json is invalid as well. Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
parent
16abaf0922
commit
3c8384ee71
4 changed files with 79 additions and 22 deletions
|
|
@ -1,10 +1,11 @@
|
||||||
"""Argparser for overriding config values"""
|
"""Argparser for overriding config values"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
from typing import Optional
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from common.config_models import TabbyConfigModel
|
from common.config_models import TabbyConfigModel
|
||||||
from common.utils import is_list_type, unwrap_optional_type
|
from common.utils import is_list_type, unwrap, unwrap_optional_type
|
||||||
|
|
||||||
|
|
||||||
def add_field_to_group(group, field_name, field_type, field) -> None:
|
def add_field_to_group(group, field_name, field_type, field) -> None:
|
||||||
|
|
@ -23,12 +24,18 @@ def add_field_to_group(group, field_name, field_type, field) -> None:
|
||||||
group.add_argument(f"--{field_name}", **kwargs)
|
group.add_argument(f"--{field_name}", **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def init_argparser() -> argparse.ArgumentParser:
|
def init_argparser(
|
||||||
|
existing_parser: Optional[argparse.ArgumentParser] = None,
|
||||||
|
) -> argparse.ArgumentParser:
|
||||||
"""
|
"""
|
||||||
Initializes an argparse parser based on a Pydantic config schema.
|
Initializes an argparse parser based on a Pydantic config schema.
|
||||||
|
|
||||||
|
If an existing provider is given, use that.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="TabbyAPI server")
|
parser = unwrap(
|
||||||
|
existing_parser, argparse.ArgumentParser(description="TabbyAPI server")
|
||||||
|
)
|
||||||
|
|
||||||
# Loop through each top-level field in the config
|
# Loop through each top-level field in the config
|
||||||
for field_name, field_info in TabbyConfigModel.model_fields.items():
|
for field_name, field_info in TabbyConfigModel.model_fields.items():
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ if exist "%CONDA_PREFIX%" (
|
||||||
if not exist "venv\" (
|
if not exist "venv\" (
|
||||||
echo Venv doesn't exist! Creating one for you.
|
echo Venv doesn't exist! Creating one for you.
|
||||||
python -m venv venv
|
python -m venv venv
|
||||||
|
|
||||||
|
if exist "start_options.json" (
|
||||||
|
echo Removing old start_options.json
|
||||||
|
del start_options.json
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
call .\venv\Scripts\activate.bat
|
call .\venv\Scripts\activate.bat
|
||||||
|
|
|
||||||
78
start.py
78
start.py
|
|
@ -10,8 +10,6 @@ import sys
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from common.args import convert_args_to_dict, init_argparser
|
|
||||||
|
|
||||||
|
|
||||||
start_options = {}
|
start_options = {}
|
||||||
|
|
||||||
|
|
@ -93,6 +91,20 @@ def get_install_features(lib_name: str = None):
|
||||||
return install_features
|
return install_features
|
||||||
|
|
||||||
|
|
||||||
|
def create_argparser():
|
||||||
|
try:
|
||||||
|
from common.args import init_argparser
|
||||||
|
|
||||||
|
return init_argparser()
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
print(
|
||||||
|
"Pydantic not found. Showing an abridged help menu.\n"
|
||||||
|
"Run this script once to install dependencies.\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
return argparse.ArgumentParser()
|
||||||
|
|
||||||
|
|
||||||
def add_start_args(parser: argparse.ArgumentParser):
|
def add_start_args(parser: argparse.ArgumentParser):
|
||||||
"""Add start script args to the provided parser"""
|
"""Add start script args to the provided parser"""
|
||||||
start_group = parser.add_argument_group("start")
|
start_group = parser.add_argument_group("start")
|
||||||
|
|
@ -151,9 +163,25 @@ if __name__ == "__main__":
|
||||||
subprocess.run(["pip", "-V"])
|
subprocess.run(["pip", "-V"])
|
||||||
|
|
||||||
# Create an argparser and add extra startup script args
|
# Create an argparser and add extra startup script args
|
||||||
parser = init_argparser()
|
# Try creating a full argparser if pydantic is installed
|
||||||
|
# Otherwise, create an abridged one solely for startup
|
||||||
|
try:
|
||||||
|
from common.args import init_argparser
|
||||||
|
|
||||||
|
parser = init_argparser()
|
||||||
|
has_full_parser = True
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Abridged TabbyAPI start script parser.",
|
||||||
|
epilog=(
|
||||||
|
"Some dependencies were not found to display the full argparser. "
|
||||||
|
"Run the script once to install/update them."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
has_full_parser = False
|
||||||
|
|
||||||
add_start_args(parser)
|
add_start_args(parser)
|
||||||
args = parser.parse_args()
|
args, _ = parser.parse_known_args()
|
||||||
script_ext = "bat" if platform.system() == "Windows" else "sh"
|
script_ext = "bat" if platform.system() == "Windows" else "sh"
|
||||||
|
|
||||||
start_options_path = pathlib.Path("start_options.json")
|
start_options_path = pathlib.Path("start_options.json")
|
||||||
|
|
@ -176,6 +204,7 @@ if __name__ == "__main__":
|
||||||
# Set variables that rely on start options
|
# Set variables that rely on start options
|
||||||
first_run = not start_options.get("first_run_done")
|
first_run = not start_options.get("first_run_done")
|
||||||
|
|
||||||
|
# Set gpu_lib for dependency install
|
||||||
if args.gpu_lib:
|
if args.gpu_lib:
|
||||||
print("Overriding GPU lib name from args.")
|
print("Overriding GPU lib name from args.")
|
||||||
gpu_lib = args.gpu_lib
|
gpu_lib = args.gpu_lib
|
||||||
|
|
@ -184,25 +213,13 @@ if __name__ == "__main__":
|
||||||
else:
|
else:
|
||||||
gpu_lib = None
|
gpu_lib = None
|
||||||
|
|
||||||
# Create a config if it doesn't exist
|
# Pull from GitHub
|
||||||
# This is not necessary to run TabbyAPI, but is new user proof
|
|
||||||
config_path = (
|
|
||||||
pathlib.Path(args.config) if args.config else pathlib.Path("config.yml")
|
|
||||||
)
|
|
||||||
if not config_path.exists():
|
|
||||||
sample_config_path = pathlib.Path("config_sample.yml")
|
|
||||||
copyfile(sample_config_path, config_path)
|
|
||||||
|
|
||||||
print(
|
|
||||||
"A config.yml wasn't found.\n"
|
|
||||||
f"Created one at {str(config_path.resolve())}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if args.update_repository:
|
if args.update_repository:
|
||||||
print("Pulling latest changes from Github.")
|
print("Pulling latest changes from Github.")
|
||||||
pull_command = "git pull"
|
pull_command = "git pull"
|
||||||
subprocess.run(pull_command.split(" "))
|
subprocess.run(pull_command.split(" "))
|
||||||
|
|
||||||
|
# Install/update dependencies
|
||||||
if first_run or args.update_deps:
|
if first_run or args.update_deps:
|
||||||
install_command = ["pip", "install", "-U"]
|
install_command = ["pip", "install", "-U"]
|
||||||
|
|
||||||
|
|
@ -231,6 +248,7 @@ if __name__ == "__main__":
|
||||||
"inside the `update_scripts` folder."
|
"inside the `update_scripts` folder."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# First run options
|
||||||
if first_run:
|
if first_run:
|
||||||
start_options["first_run_done"] = True
|
start_options["first_run_done"] = True
|
||||||
|
|
||||||
|
|
@ -245,12 +263,34 @@ if __name__ == "__main__":
|
||||||
"will reinstall TabbyAPI as a first-time user."
|
"will reinstall TabbyAPI as a first-time user."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Import entrypoint after installing all requirements
|
# Expand the parser if it's not fully created
|
||||||
|
if not has_full_parser:
|
||||||
|
from common.args import init_argparser
|
||||||
|
|
||||||
|
parser = init_argparser(parser)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Assume all dependencies are installed from here
|
||||||
try:
|
try:
|
||||||
|
from common.args import convert_args_to_dict
|
||||||
from main import entrypoint
|
from main import entrypoint
|
||||||
|
|
||||||
converted_args = convert_args_to_dict(args, parser)
|
converted_args = convert_args_to_dict(args, parser)
|
||||||
|
|
||||||
|
# Create a config if it doesn't exist
|
||||||
|
# This is not necessary to run TabbyAPI, but is new user proof
|
||||||
|
config_path = (
|
||||||
|
pathlib.Path(args.config) if args.config else pathlib.Path("config.yml")
|
||||||
|
)
|
||||||
|
if not config_path.exists():
|
||||||
|
sample_config_path = pathlib.Path("config_sample.yml")
|
||||||
|
copyfile(sample_config_path, config_path)
|
||||||
|
|
||||||
|
print(
|
||||||
|
"A config.yml wasn't found.\n"
|
||||||
|
f"Created one at {str(config_path.resolve())}"
|
||||||
|
)
|
||||||
|
|
||||||
print("Starting TabbyAPI...")
|
print("Starting TabbyAPI...")
|
||||||
entrypoint(converted_args)
|
entrypoint(converted_args)
|
||||||
except (ModuleNotFoundError, ImportError):
|
except (ModuleNotFoundError, ImportError):
|
||||||
|
|
|
||||||
5
start.sh
5
start.sh
|
|
@ -8,6 +8,11 @@ else
|
||||||
if [ ! -d "venv" ]; then
|
if [ ! -d "venv" ]; then
|
||||||
echo "Venv doesn't exist! Creating one for you."
|
echo "Venv doesn't exist! Creating one for you."
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
|
|
||||||
|
if [ -f "start_options.json" ]; then
|
||||||
|
echo "Removing old start_options.json"
|
||||||
|
rm -rf start_options.json
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Activating venv"
|
echo "Activating venv"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue