# /// script # requires-python = ">=3.13" # dependencies = [ # "argparse", # "pathlib", # ] # /// import argparse import subprocess from pathlib import Path # Constant paths for project. LOCALES_DIR = Path("src/locales") LOCALES_DOMAIN = "messages" LOCALES_POT = LOCALES_DIR / f"{LOCALES_DOMAIN}.pot" LOCALES_WIDTH = 80 def run_commands(cmds: list[list[str]]) -> None: """ Run terminal commands from Python. Used for pybabel commands. Args: cmds (list[list[str]]): list of commands split by space. Example: [["echo", "Hello World"], ["uv", "run", "main.py"]] """ try: # Try to run command and print output. # Print only stderr output (pybabel use stderr). for cmd in cmds: # DEBUG: User input is completely safe, # as it only accepts specific values. result = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, check=True, shell=False, ) print(result.stderr) except Exception as error: print(f"Error: {error}") def main() -> None: """ Main logic of script. Parse args, try to run commands. """ parser = argparse.ArgumentParser( description="Wrapper for pybabel operations." ) parser.add_argument( "operation", choices=["extract", "update", "compile", "init"], help="Type of pybabel operation.", ) parser.add_argument( "language", nargs="?", default="all", choices=["ru", "en", "zh", "es", "ar", "fr", "de", "all"], help="" + "Language code. " + "If omitted, all locales are processed. " + "Only for update & compile operations.", ) args = parser.parse_args() if args.operation == "init" and args.language == "all": print("Error: You need to specify new language.") return cmd = list() cmd.append("pybabel") cmd.append(args.operation) # Extract operation require only extract command. if args.operation == "extract": cmd.append(".") cmd.append("-o") cmd.append(str(LOCALES_POT)) run_commands([cmd]) return # Other operations (init, update, compile) # may require multiple commands. # Set base flags for these operations. cmd.append("-D") cmd.append(LOCALES_DOMAIN) cmd.append("-d") cmd.append(str(LOCALES_DIR)) # Specific flags if args.operation in ("update", "init"): cmd.append("-i") cmd.append(str(LOCALES_POT)) if args.operation == "update": cmd.append("-w") cmd.append(str(LOCALES_WIDTH)) # Add all langs or specific lang. if args.language == "all": langs = [ str(path_name.name) for path_name in LOCALES_DIR.iterdir() if path_name.is_dir() ] else: langs = [args.language] cmds = [cmd + ["-l"] + [lang] for lang in langs] # Run commands run_commands(cmds) if __name__ == "__main__": main()