Spaces:
Paused
Paused
| # src/rotator_library/utils/headless_detection.py | |
| import os | |
| import sys | |
| import logging | |
| lib_logger = logging.getLogger("rotator_library") | |
| # Import console for user-visible output | |
| try: | |
| from rich.console import Console | |
| console = Console() | |
| except ImportError: | |
| console = None | |
| def is_headless_environment() -> bool: | |
| """ | |
| Detects if the current environment is headless (no GUI available). | |
| Returns: | |
| True if headless environment is detected, False otherwise | |
| Detection logic: | |
| - Linux/Unix: Check DISPLAY environment variable | |
| - SSH detection: Check SSH_CONNECTION or SSH_CLIENT | |
| - CI environments: Check common CI environment variables | |
| - Windows: Check SESSIONNAME for service/headless indicators | |
| """ | |
| headless_indicators = [] | |
| # Check DISPLAY for Linux GUI availability (skip on Windows and macOS) | |
| # NOTE: DISPLAY is an X11 (X Window System) variable used on Linux. | |
| # macOS uses its native Quartz windowing system, NOT X11, so DISPLAY is | |
| # typically unset on macOS even with a full GUI. Only check DISPLAY on Linux. | |
| if os.name != "nt" and sys.platform != "darwin": # Linux only | |
| display = os.getenv("DISPLAY") | |
| if display is None or display.strip() == "": | |
| headless_indicators.append("No DISPLAY variable (Linux headless)") | |
| # Check for SSH connection | |
| if os.getenv("SSH_CONNECTION") or os.getenv("SSH_CLIENT") or os.getenv("SSH_TTY"): | |
| headless_indicators.append("SSH connection detected") | |
| # Check for CI environments | |
| ci_vars = [ | |
| "CI", # Generic CI indicator | |
| "GITHUB_ACTIONS", # GitHub Actions | |
| "GITLAB_CI", # GitLab CI | |
| "JENKINS_URL", # Jenkins | |
| "CIRCLECI", # CircleCI | |
| "TRAVIS", # Travis CI | |
| "BUILDKITE", # Buildkite | |
| "DRONE", # Drone CI | |
| "TEAMCITY_VERSION", # TeamCity | |
| "TF_BUILD", # Azure Pipelines | |
| "CODEBUILD_BUILD_ID", # AWS CodeBuild | |
| ] | |
| for var in ci_vars: | |
| if os.getenv(var): | |
| headless_indicators.append(f"CI environment detected ({var})") | |
| break | |
| # Check Windows session type | |
| if os.name == "nt": # Windows | |
| session_name = os.getenv("SESSIONNAME", "").lower() | |
| if session_name in ["services", "rdp-tcp"]: | |
| headless_indicators.append(f"Windows headless session ({session_name})") | |
| # Detect Docker/container environment | |
| if os.path.exists("/.dockerenv") or os.path.exists("/run/.containerenv"): | |
| headless_indicators.append("Container environment detected") | |
| # Determine if headless | |
| is_headless = len(headless_indicators) > 0 | |
| if is_headless: | |
| # Log to logger | |
| lib_logger.info( | |
| f"Headless environment detected: {'; '.join(headless_indicators)}" | |
| ) | |
| # Print to console for user visibility | |
| if console: | |
| console.print( | |
| f"[yellow]βΉ Headless environment detected:[/yellow] {'; '.join(headless_indicators)}" | |
| ) | |
| console.print( | |
| "[yellow]β Browser will NOT open automatically. Please use the URL below.[/yellow]\n" | |
| ) | |
| else: | |
| # Only log to debug, no console output | |
| lib_logger.debug( | |
| "GUI environment detected, browser auto-open will be attempted" | |
| ) | |
| return is_headless | |