mirror of
https://github.com/trycua/lume.git
synced 2026-01-11 23:10:10 -06:00
82 lines
3.0 KiB
Python
82 lines
3.0 KiB
Python
import asyncio
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
from typing import overload
|
|
|
|
|
|
def get_current_os() -> str:
|
|
"""Determine the current OS.
|
|
|
|
Returns:
|
|
str: The OS type ('android', 'darwin' for macOS, 'linux' for Linux, or 'windows' for Windows)
|
|
|
|
Raises:
|
|
RuntimeError: If unable to determine the current OS
|
|
"""
|
|
try:
|
|
if os.environ.get("IS_CUA_ANDROID") == "true":
|
|
# Verify emulator is actually running by checking adb devices
|
|
try:
|
|
result = subprocess.run(
|
|
["adb", "devices"], capture_output=True, text=True, timeout=5
|
|
)
|
|
if result.returncode == 0 and "emulator-5554" in result.stdout:
|
|
return "android"
|
|
else:
|
|
raise RuntimeError(
|
|
"IS_CUA_ANDROID is set but no emulator found. "
|
|
"Ensure Android emulator is running and accessible via adb."
|
|
)
|
|
except subprocess.TimeoutExpired:
|
|
raise RuntimeError(
|
|
"IS_CUA_ANDROID is set but adb command timed out. "
|
|
"Emulator may be starting up or unresponsive."
|
|
)
|
|
|
|
system = platform.system().lower()
|
|
if system in ["darwin", "linux", "windows"]:
|
|
return system
|
|
|
|
# Fallback to uname if platform.system() doesn't return expected values (Unix-like systems only)
|
|
result = subprocess.run(["uname", "-s"], capture_output=True, text=True)
|
|
if result.returncode == 0:
|
|
return result.stdout.strip().lower()
|
|
|
|
raise RuntimeError(f"Unsupported OS: {system}")
|
|
except Exception as e:
|
|
raise RuntimeError(f"Failed to determine current OS: {str(e)}")
|
|
|
|
|
|
class CommandExecutor:
|
|
def __init__(self, *base_cmd: str) -> None:
|
|
"""Initialize with a base command.
|
|
|
|
Args:
|
|
base_cmd: The base command and its initial arguments.
|
|
"""
|
|
self.__base_cmd = list(base_cmd)
|
|
|
|
@overload
|
|
async def run(self, *args: str, timeout: int = 10) -> tuple[bool, bytes]: ...
|
|
@overload
|
|
async def run(self, *args: str, decode: bool = True, timeout: int = 10) -> tuple[bool, str]: ...
|
|
|
|
async def run(
|
|
self, *args: str, decode: bool = False, timeout: int = 10
|
|
) -> tuple[bool, bytes | str]:
|
|
cmd = self.__base_cmd + list(args)
|
|
try:
|
|
result = await asyncio.create_subprocess_exec(
|
|
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
|
)
|
|
stdout, stderr = await asyncio.wait_for(result.communicate(), timeout=timeout)
|
|
output = stdout or stderr
|
|
if decode:
|
|
output = output.decode("utf-8")
|
|
return result.returncode == 0, output
|
|
except asyncio.TimeoutError:
|
|
return False, f"Command timed out after {timeout}s".encode("utf-8")
|
|
except Exception as e:
|
|
return False, str(e).encode("utf-8")
|