Source code for galaxy.selenium.driver_factory

import logging
import os

try:
    from pyvirtualdisplay import Display
except ImportError:
    Display = None

from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.remote.webdriver import WebDriver

logger = logging.getLogger("selenium.webdriver.remote.remote_connection")
logger.setLevel(logging.WARNING)

DEFAULT_BROWSER = "auto"
DEFAULT_DOWNLOAD_PATH = "/tmp/"
LOGGING_PREFS = {
    "browser": "ALL",
}
DEFAULT_SELENIUM_BROWSER = "auto"
DEFAULT_SELENIUM_REMOTE = False
DEFAULT_SELENIUM_REMOTE_PORT = "4444"
DEFAULT_SELENIUM_REMOTE_HOST = "127.0.0.1"
DEFAULT_WINDOW_WIDTH = 1280
DEFAULT_WINDOW_HEIGHT = 1000
VALID_LOCAL_BROWSERS = ["CHROME", "FIREFOX"]


[docs]class ConfiguredDriver: driver: WebDriver
[docs] def __init__( self, browser=DEFAULT_SELENIUM_BROWSER, remote=DEFAULT_SELENIUM_REMOTE, remote_host=DEFAULT_SELENIUM_REMOTE_HOST, remote_port=DEFAULT_SELENIUM_REMOTE_PORT, headless=False, ): self.config = dict( browser=browser, remote=remote, remote_host=remote_host, remote_port=remote_port, headless=headless, ) if remote: driver = get_remote_driver( host=remote_host, port=remote_port, browser=browser, ) else: driver = get_local_driver( browser=browser, headless=headless, ) # Need larger than default window size for workflow index page, paired list creator. driver.set_window_size(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT) self.driver = driver
[docs] def to_dict(self): return self.config
[docs] @staticmethod def from_dict(as_dict): return ConfiguredDriver(**as_dict)
def get_local_browser(browser): if browser == "auto": if _which("chromedriver"): browser = "CHROME" elif _which("geckodriver"): browser = "FIREFOX" else: raise Exception("Selenium browser is 'auto' but neither geckodriver or chromedriver are found on PATH.") return browser
[docs]def get_local_driver(browser=DEFAULT_BROWSER, headless=False) -> WebDriver: browser = get_local_browser(browser) if browser not in VALID_LOCAL_BROWSERS: raise AssertionError(f"{browser} not in VALID_LOCAL_BROWSERS ({VALID_LOCAL_BROWSERS})") driver_to_class = { "CHROME": webdriver.Chrome, "FIREFOX": webdriver.Firefox, } driver_class = driver_to_class[browser] if browser == "CHROME": options = ChromeOptions() if headless: options.add_argument("--headless") prefs = {"download.default_directory": DEFAULT_DOWNLOAD_PATH} options.add_experimental_option("prefs", prefs) return driver_class(desired_capabilities={"loggingPrefs": LOGGING_PREFS}, chrome_options=options) elif browser == "FIREFOX": fp = webdriver.FirefoxProfile() fp.set_preference("network.proxy.type", 2) fp.set_preference("network.proxy.autoconfig_url", "http://127.0.0.1:9675") fp.set_preference("browser.download.folderList", 2) fp.set_preference("browser.download.dir", DEFAULT_DOWNLOAD_PATH) fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream") return driver_class(firefox_profile=fp) else: return driver_class(desired_capabilities={"loggingPrefs": LOGGING_PREFS})
[docs]def get_remote_driver(host, port, browser=DEFAULT_BROWSER) -> WebDriver: # docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-chrome:3.0.1-aluminum if browser == "auto": browser = "CHROME" assert browser in ["CHROME", "EDGE", "ANDROID", "FIREFOX", "INTERNETEXPLORER", "IPAD", "IPHONE", "SAFARI"] desired_capabilities = getattr(DesiredCapabilities, browser) desired_capabilities["loggingPrefs"] = LOGGING_PREFS executor = f"http://{host}:{port}/wd/hub" driver = webdriver.Remote( command_executor=executor, desired_capabilities=desired_capabilities, ) return driver
[docs]def is_virtual_display_available(): return Display is not None
[docs]def virtual_display_if_enabled(enabled): if enabled: display = Display(visible=0, size=(800, 600)) display.start() return display else: return NoopDisplay()
class NoopDisplay: def stop(self): """No-op stop for consistent use with pyvirtualdisplay Display class.""" # Purposely copied from galaxy.util - just use galaxy.util if we decide # galaxy_selenium should definitely depend on Galaxy/galaxy-lib. def _which(file): # http://stackoverflow.com/questions/5226958/which-equivalent-function-in-python for path in os.environ["PATH"].split(":"): if os.path.exists(f"{path}/{file}"): return f"{path}/{file}" return None __all__ = ( "ConfiguredDriver", "get_local_driver", "get_remote_driver", "is_virtual_display_available", "virtual_display_if_enabled", )