import sys import sysconfig from os.path import dirname, abspath, join import shutil from typing import List, Optional, Tuple, Union import shlex def is_command_available(command_name): """ Use `shutil.which` to determine whether a command is available. Args: command_name (str): The name of the command to check. Returns: bool: True if the command is available, False otherwise. """ return shutil.which(command_name) is not None def find_parameter(parameters: List[str], param_names: List[str]) -> Optional[str]: """ Find specified parameter by name from the parameters. Return the value of the parameter if found, otherwise return None. """ if parameters is None: return None for i, param in enumerate(parameters): # Strip whitespace from the parameter param_stripped = param.strip() if '=' in param_stripped: key, value = param_stripped.split('=', 1) if key.strip().lstrip('-') in param_names: return value elif ' ' in param_stripped: key, value = param_stripped.split(' ', 1) if key.strip().lstrip('-') in param_names: split_values = shlex.split(value) if len(split_values) == 1: return split_values[0] return value else: if param_stripped.lstrip('-') in param_names: if i + 1 < len(parameters): return parameters[i + 1] return None def find_int_parameter(parameters: List[str], param_names: List[str]) -> Optional[int]: """ Find specified integer parameter by name from the parameters. Return the integer value of the parameter if found, otherwise return None. """ value = find_parameter(parameters, param_names) if value is not None: try: return int(value) except ValueError: return None return None def find_bool_parameter(parameters: List[str], param_names: List[str]) -> bool: """ Find specified boolean parameter by name from the parameters. Return True if the parameter is set, otherwise return False. """ if parameters is None: return False for i, param in enumerate(parameters): param_stripped = param.strip() if param_stripped.lstrip('-') in param_names: return True return False def get_versioned_command(command_name: str, version: str) -> str: """ Get the versioned command name. """ if command_name.endswith(".exe"): return f"{command_name[:-4]}_{version}.exe" return f"{command_name}_{version}" def get_command_path(command_name: str) -> str: """ Return the full path of sepcified command. Supports both frozen and python base environments. """ base_path = ( dirname(sys.executable) if getattr(sys, 'frozen', False) else sysconfig.get_path("scripts") ) return abspath(join(base_path, command_name)) def extend_args_no_exist( arguments: List[str], *args: Union[str, Tuple[str, str]] ) -> None: """ Extend arguments list with key-value pairs only if the key is not already present. This function prevents duplicate parameters when user-defined backend parameters may conflict with system-generated ones. Args: arguments: The list of arguments to extend (modified in place) *args: Variable number of arguments, each can be: - A tuple of (key, value) like ("--host", "127.0.0.1") - A single string key like "--enable-metrics" (flag without value) Examples: extend_args_no_exist(args, ("--host", "127.0.0.1"), ("--port", "8080")) extend_args_no_exist(args, "--enable-metrics") """ for arg in args: if isinstance(arg, tuple): key, value = arg if not any( existing_arg == key or existing_arg.startswith(f"{key}=") for existing_arg in arguments ): arguments.extend([key, value]) else: # Single flag without value if arg not in arguments: arguments.append(arg) def format_backend_parameters(parameters: Optional[List[str]]) -> List[str]: """ Format flattened command-line tokens as backend parameter entries. Examples: ["--max-model-len", "8192", "--enable-prefix-caching"] -> ["--max-model-len=8192", "--enable-prefix-caching"] ["--dtype=float16"] -> ["--dtype=float16"] """ if not parameters: return [] formatted = [] index = 0 while index < len(parameters): parameter = parameters[index] if not parameter.startswith("-") or "=" in parameter: formatted.append(parameter) index += 1 continue if index + 1 < len(parameters) and not _looks_like_parameter( parameters[index + 1] ): formatted.append(f"{parameter}={parameters[index + 1]}") index += 2 continue formatted.append(parameter) index += 1 return formatted def _looks_like_parameter(value: str) -> bool: if not value.startswith("-"): return False # Negative numeric values are parameter values, not flags. try: float(value) return False except ValueError: return True