Fix terrible hierarchy of environment/external variables

DEBUG should be respected now.
This commit is contained in:
McCloudS
2025-05-14 09:57:43 -06:00
committed by GitHub
parent d9febbe991
commit c80b5db14d

View File

@@ -10,12 +10,10 @@ def convert_to_bool(in_bool):
def install_packages_from_requirements(requirements_file): def install_packages_from_requirements(requirements_file):
try: try:
# Try installing with pip3
subprocess.run(['pip3', 'install', '-r', requirements_file, '--upgrade'], check=True) subprocess.run(['pip3', 'install', '-r', requirements_file, '--upgrade'], check=True)
print("Packages installed successfully using pip3.") print("Packages installed successfully using pip3.")
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
try: try:
# If pip3 fails, try installing with pip
subprocess.run(['pip', 'install', '-r', requirements_file, '--upgrade'], check=True) subprocess.run(['pip', 'install', '-r', requirements_file, '--upgrade'], check=True)
print("Packages installed successfully using pip.") print("Packages installed successfully using pip.")
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
@@ -24,7 +22,7 @@ def install_packages_from_requirements(requirements_file):
def download_from_github(url, output_file): def download_from_github(url, output_file):
try: try:
with urllib.request.urlopen(url) as response, open(output_file, 'wb') as out_file: with urllib.request.urlopen(url) as response, open(output_file, 'wb') as out_file:
data = response.read() # a `bytes` object data = response.read()
out_file.write(data) out_file.write(data)
print(f"File downloaded successfully to {output_file}") print(f"File downloaded successfully to {output_file}")
except urllib.error.HTTPError as e: except urllib.error.HTTPError as e:
@@ -35,11 +33,6 @@ def download_from_github(url, output_file):
print(f"An error occurred: {e}") print(f"An error occurred: {e}")
def prompt_and_save_bazarr_env_variables(): def prompt_and_save_bazarr_env_variables():
"""
Prompts the user for Bazarr related environment variables with descriptions and saves them to a file.
If the user does not input anything, default values are used.
"""
# Instructions for the user
instructions = ( instructions = (
"You will be prompted for several configuration values.\n" "You will be prompted for several configuration values.\n"
"If you wish to use the default value for any of them, simply press Enter without typing anything.\n" "If you wish to use the default value for any of them, simply press Enter without typing anything.\n"
@@ -51,39 +44,35 @@ def prompt_and_save_bazarr_env_variables():
'WHISPER_MODEL': ('Whisper Model', 'Enter the Whisper model you want to run: tiny, tiny.en, base, base.en, small, small.en, medium, medium.en, large, distil-large-v2, distil-medium.en, distil-small.en', 'medium'), 'WHISPER_MODEL': ('Whisper Model', 'Enter the Whisper model you want to run: tiny, tiny.en, base, base.en, small, small.en, medium, medium.en, large, distil-large-v2, distil-medium.en, distil-small.en', 'medium'),
'WEBHOOKPORT': ('Webhook Port', 'Default listening port for subgen.py', '9000'), 'WEBHOOKPORT': ('Webhook Port', 'Default listening port for subgen.py', '9000'),
'TRANSCRIBE_DEVICE': ('Transcribe Device', 'Set as cpu or gpu', 'gpu'), 'TRANSCRIBE_DEVICE': ('Transcribe Device', 'Set as cpu or gpu', 'gpu'),
'DEBUG': ('Debug', 'Enable debug logging', 'True'), # Defaulting to False here for the prompt, user can change
'DEBUG': ('Debug', 'Enable debug logging (true/false)', 'False'),
'CLEAR_VRAM_ON_COMPLETE': ('Clear VRAM', 'Attempt to clear VRAM when complete (Windows users may need to set this to False)', 'False'), 'CLEAR_VRAM_ON_COMPLETE': ('Clear VRAM', 'Attempt to clear VRAM when complete (Windows users may need to set this to False)', 'False'),
'APPEND': ('Append', 'Append \'Transcribed by whisper\' to generated subtitle', 'False'), 'APPEND': ('Append', 'Append \'Transcribed by whisper\' to generated subtitle (true/false)', 'False'),
} }
# Dictionary to hold the user's input
user_input = {} user_input = {}
# Prompt the user for each environment variable and write to .env file
with open('subgen.env', 'w') as file: with open('subgen.env', 'w') as file:
for var, (description, prompt, default) in env_vars.items(): for var, (description, prompt, default) in env_vars.items():
value = input(f"{prompt} [{default}]: ") or default value = input(f"{prompt} [{default}]: ") or default
file.write(f"{var}={value}\n") file.write(f"{var}={value}\n")
print("Environment variables have been saved to subgen.env") print("Environment variables have been saved to subgen.env")
def load_env_variables(env_filename='subgen.env'): def load_env_variables(env_filename='subgen.env'):
"""
Loads environment variables from a specified .env file and sets them.
"""
try: try:
with open(env_filename, 'r') as file: with open(env_filename, 'r') as file:
for line in file: for line in file:
var, value = line.strip().split('=', 1) line = line.strip()
os.environ[var] = value if line and not line.startswith('#') and '=' in line:
var, value = line.split('=', 1)
# Only set if not already set by a higher priority mechanism (like external env var)
# For this simple loader, we'll let it overwrite,
# and CLI args will overwrite these later if specified.
os.environ[var] = value
print(f"Environment variables have been loaded from {env_filename}") print(f"Environment variables have been loaded from {env_filename}")
except FileNotFoundError: except FileNotFoundError:
print(f"{env_filename} file not found. Please run prompt_and_save_env_variables() first.") print(f"{env_filename} file not found. Consider running with --setup-bazarr or creating it manually.")
def main(): def main():
# Check if the script is run with 'python' or 'python3'
if 'python3' in sys.executable: if 'python3' in sys.executable:
python_cmd = 'python3' python_cmd = 'python3'
elif 'python' in sys.executable: elif 'python' in sys.executable:
@@ -93,77 +82,99 @@ def main():
sys.exit(1) sys.exit(1)
if sys.version_info[0] < 3: if sys.version_info[0] < 3:
print(f"This script requires Python 3 or higher, you are running {sys.version}") print(f"This script requires Python 3 or higher, you are running {sys.version}")
sys.exit(1) # Terminate the script sys.exit(1)
#Make sure we're saving subgen.py and subgen.env in the right folder
os.chdir(os.path.dirname(os.path.abspath(__file__))) os.chdir(os.path.dirname(os.path.abspath(__file__)))
# Construct the argument parser
parser = argparse.ArgumentParser(prog="python launcher.py", formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser = argparse.ArgumentParser(prog="python launcher.py", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-d', '--debug', default=True, action='store_true', help="Enable console debugging") # Changed: action='store_true' means it's False by default, True if flag is present
parser.add_argument('-i', '--install', default=False, action='store_true', help="Install/update all necessary packages") parser.add_argument('-d', '--debug', action='store_true', help="Enable console debugging (overrides .env and external ENV)")
parser.add_argument('-a', '--append', default=False, action='store_true', help="Append 'Transcribed by whisper' to generated subtitle") parser.add_argument('-i', '--install', action='store_true', help="Install/update all necessary packages")
parser.add_argument('-u', '--update', default=False, action='store_true', help="Update Subgen") # Changed: action='store_true'
parser.add_argument('-x', '--exit-early', default=False, action='store_true', help="Exit without running subgen.py") parser.add_argument('-a', '--append', action='store_true', help="Append 'Transcribed by whisper' (overrides .env and external ENV)")
parser.add_argument('-s', '--setup-bazarr', default=False, action='store_true', help="Prompt for common Bazarr setup parameters and save them for future runs") parser.add_argument('-u', '--update', action='store_true', help="Update Subgen")
parser.add_argument('-b', '--branch', type=str, default='main', help='Specify the branch to download from') parser.add_argument('-x', '--exit-early', action='store_true', help="Exit without running subgen.py")
parser.add_argument('-l', '--launcher-update', default=False, action='store_true', help="Update launcher.py and re-launch") parser.add_argument('-s', '--setup-bazarr', action='store_true', help="Prompt for common Bazarr setup parameters and save them for future runs")
parser.add_argument('-b', '--branch', type=str, default='main', help='Specify the branch to download from')
parser.add_argument('-l', '--launcher-update', action='store_true', help="Update launcher.py and re-launch")
args = parser.parse_args() args = parser.parse_args()
# Get the branch name from the BRANCH environment variable or default to 'main'
branch_name = args.branch if args.branch != 'main' else os.getenv('BRANCH', 'main') branch_name = args.branch if args.branch != 'main' else os.getenv('BRANCH', 'main')
# Determine the script name based on the branch name script_name_suffix = f"-{branch_name}.py" if branch_name != "main" else ".py"
script_name = f"-{branch_name}.py" if branch_name != "main" else ".py" subgen_script_to_run = f"subgen{script_name_suffix}"
# Check we need to update the launcher language_code_script_to_download = f"language_code{script_name_suffix}"
if args.launcher_update or convert_to_bool(os.getenv('LAUNCHER_UPDATE')): if args.launcher_update or convert_to_bool(os.getenv('LAUNCHER_UPDATE')):
print(f"Updating launcher.py from GitHub branch {branch_name}...") print(f"Updating launcher.py from GitHub branch {branch_name}...")
download_from_github(f"https://raw.githubusercontent.com/McCloudS/subgen/{branch_name}/launcher.py", f'launcher{script_name}') download_from_github(f"https://raw.githubusercontent.com/McCloudS/subgen/{branch_name}/launcher.py", f'launcher{script_name_suffix}')
excluded_args = ['--launcher-update', '-l']
new_args = [arg for arg in sys.argv[1:] if arg not in excluded_args]
print(f"Relaunching updated launcher: launcher{script_name_suffix}")
os.execl(sys.executable, sys.executable, f"launcher{script_name_suffix}", *new_args)
# The script will not continue past os.execl
# Prepare the arguments to exclude update triggers # --- Environment Variable Handling ---
excluded_args = ['--launcher-update', '-l'] # 1. Load from .env file first. This sets a baseline.
new_args = [arg for arg in sys.argv[1:] if arg not in excluded_args] # External environment variables (set before launcher.py) will already be in os.environ
if branch_name == 'main' and args.launcher_update: # and won't be overwritten by load_env_variables IF load_env_variables checked for existence.
print("Running launcher.py for the 'main' branch.") # For simplicity, this version of load_env_variables *will* overwrite.
os.execl(sys.executable, sys.executable, "launcher.py", *new_args) # If you need to preserve external env vars over .env, load_env_variables needs adjustment.
elif args.launcher_update: if args.setup_bazarr:
print(f"Running launcher-{branch_name}.py for the '{branch_name}' branch.")
os.execl(sys.executable, sys.executable, f"launcher{script_name}", *new_args)
# Set environment variables based on the parsed arguments
if not convert_to_bool(os.environ.get('DEBUG', '')):
os.environ['DEBUG'] = str(args.debug)
if not convert_to_bool(os.environ.get('APPEND', '')):
os.environ['APPEND'] = str(args.append)
if args.setup_bazarr:
prompt_and_save_bazarr_env_variables() prompt_and_save_bazarr_env_variables()
load_env_variables() # After saving, load them immediately for this run
load_env_variables()
else:
# Load if not setting up, assuming subgen.env might exist
load_env_variables()
# 2. Override with command-line arguments (highest priority for these specific flags)
if args.debug: # If -d or --debug was passed
os.environ['DEBUG'] = 'True'
print("Launcher CLI: DEBUG set to True")
elif 'DEBUG' not in os.environ: # If not set by CLI and not by .env or external
os.environ['DEBUG'] = 'False' # Default to False if nothing else specified it
print("Launcher: DEBUG defaulted to False (no prior setting)")
if args.append: # If -a or --append was passed
os.environ['APPEND'] = 'True'
print("Launcher CLI: APPEND set to True")
elif 'APPEND' not in os.environ: # If not set by CLI and not by .env or external
os.environ['APPEND'] = 'False' # Default to False if nothing else specified it
#print("Launcher: APPEND defaulted to False (no prior setting)")
# --- End Environment Variable Handling ---
# URL to the requirements.txt file on GitHub
requirements_url = "https://raw.githubusercontent.com/McCloudS/subgen/main/requirements.txt" requirements_url = "https://raw.githubusercontent.com/McCloudS/subgen/main/requirements.txt"
requirements_file = "requirements.txt" requirements_file = "requirements.txt"
# Install packages from requirements.txt if the install or packageupdate argument is True
if args.install: if args.install:
download_from_github(requirements_url, requirements_file) download_from_github(requirements_url, requirements_file)
install_packages_from_requirements(requirements_file) install_packages_from_requirements(requirements_file)
# Check if the script exists or if the UPDATE environment variable is set to True if not os.path.exists(subgen_script_to_run) or args.update or convert_to_bool(os.getenv('UPDATE')):
if not os.path.exists(f'subgen{script_name}') or args.update or convert_to_bool(os.getenv('UPDATE')): print(f"Downloading {subgen_script_to_run} from GitHub branch {branch_name}...")
print(f"Downloading subgen.py from GitHub branch {branch_name}...") download_from_github(f"https://raw.githubusercontent.com/McCloudS/subgen/{branch_name}/subgen.py", subgen_script_to_run)
download_from_github(f"https://raw.githubusercontent.com/McCloudS/subgen/{branch_name}/subgen.py", f'subgen{script_name}') print(f"Downloading {language_code_script_to_download} from GitHub branch {branch_name}...")
download_from_github(f"https://raw.githubusercontent.com/McCloudS/subgen/{branch_name}/language_code.py", f'language_code{script_name}') download_from_github(f"https://raw.githubusercontent.com/McCloudS/subgen/{branch_name}/language_code.py", language_code_script_to_download)
else: else:
print("subgen.py exists and UPDATE is set to False, skipping download.") print(f"{subgen_script_to_run} exists and UPDATE is set to False, skipping download.")
if not args.exit_early: if not args.exit_early:
print(f'Launching subgen{script_name}') #print(f"DEBUG environment variable for subgen.py: {os.getenv('DEBUG')}")
if branch_name != 'main': #print(f"APPEND environment variable for subgen.py: {os.getenv('APPEND')}")
subprocess.run([f'{python_cmd}', '-u', f'subgen{script_name}'], check=True) print(f'Launching {subgen_script_to_run}')
else: try:
subprocess.run([f'{python_cmd}', '-u', 'subgen.py'], check=True) subprocess.run([python_cmd, '-u', subgen_script_to_run], check=True)
except FileNotFoundError:
print(f"Error: Could not find {subgen_script_to_run}. Make sure it was downloaded correctly.")
except subprocess.CalledProcessError as e:
print(f"Error running {subgen_script_to_run}: {e}")
else: else:
print("Not running subgen.py: -x or --exit-early set") print("Not running subgen.py: -x or --exit-early set")