Path: blob/trunk/py/selenium/webdriver/common/selenium_manager.py
4007 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.1617import json18import logging19import os20import platform21import subprocess22import sys23import sysconfig24from pathlib import Path2526from selenium.common import WebDriverException2728logger = logging.getLogger(__name__)293031class SeleniumManager:32"""Wrapper for getting information from the Selenium Manager binaries.3334This implementation is still in beta, and may change.35"""3637def binary_paths(self, args: list) -> dict:38"""Determines the locations of the requested assets.3940Args:41args: the commands to send to the selenium manager binary.4243Returns:44Dictionary of assets and their path.45"""46args = [str(self._get_binary())] + args47if logger.getEffectiveLevel() == logging.DEBUG:48args.append("--debug")49args.append("--language-binding")50args.append("python")51args.append("--output")52args.append("json")5354return self._run(args)5556@staticmethod57def _get_binary() -> Path:58"""Determines the path of the Selenium Manager binary.5960Location of the binary is checked in this order:61621. location set in an environment variable632. location where setuptools-rust places the compiled binary (built from the sdist package)643. location where we ship binaries in the wheel package for the platform this is running on654. give up6667Returns:68The Selenium Manager executable location.6970Raises:71WebDriverException: If the platform is unsupported or Selenium Manager executable can't be found.72"""73compiled_path = Path(__file__).parent.joinpath("selenium-manager")74exe = sysconfig.get_config_var("EXE")75if exe is not None:76compiled_path = compiled_path.with_suffix(exe)7778path: Path | None = None7980if (env_path := os.getenv("SE_MANAGER_PATH")) is not None:81logger.debug(f"Selenium Manager set by env SE_MANAGER_PATH to: {env_path}")82path_candidate = Path(env_path)83if not path_candidate.is_file():84raise WebDriverException(f"SE_MANAGER_PATH does not point to a file: {env_path}")85path = path_candidate86elif compiled_path.is_file():87path = compiled_path88else:89allowed = {90("darwin", "any"): "macos/selenium-manager",91("win32", "any"): "windows/selenium-manager.exe",92("cygwin", "any"): "windows/selenium-manager.exe",93("linux", "x86_64"): "linux/selenium-manager",94("freebsd", "x86_64"): "linux/selenium-manager",95("openbsd", "x86_64"): "linux/selenium-manager",96}9798arch = platform.machine() if sys.platform in ("linux", "freebsd", "openbsd") else "any"99if sys.platform in ["freebsd", "openbsd"]:100logger.warning(f"Selenium Manager binary may not be compatible with {sys.platform}; verify settings")101102location = allowed.get((sys.platform, arch))103if location is None:104raise WebDriverException(f"Unsupported platform/architecture combination: {sys.platform}/{arch}")105106path = Path(__file__).parent.joinpath(location)107108if path is None or not path.is_file():109raise WebDriverException(f"Unable to obtain working Selenium Manager binary; {path}")110111logger.debug(f"Selenium Manager binary found at: {path}")112113return path114115@staticmethod116def _run(args: list[str]) -> dict:117"""Executes the Selenium Manager Binary.118119Args:120args: the components of the command being executed.121122Returns:123The log string containing the driver location.124"""125command = " ".join(args)126logger.debug("Executing process: %s", command)127try:128if sys.platform == "win32":129completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)130else:131completed_proc = subprocess.run(args, capture_output=True)132stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")133stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")134output = json.loads(stdout) if stdout != "" else {"logs": [], "result": {}}135except Exception as err:136raise WebDriverException(f"Unsuccessful command executed: {command}") from err137138SeleniumManager._process_logs(output["logs"])139result = output["result"]140if completed_proc.returncode:141raise WebDriverException(142f"Unsuccessful command executed: {command}; code: {completed_proc.returncode}\n{result}\n{stderr}"143)144return result145146@staticmethod147def _process_logs(log_items: list[dict]):148for item in log_items:149if item["level"] == "WARN":150logger.warning(item["message"])151elif item["level"] in ["DEBUG", "INFO"]:152logger.debug(item["message"])153154155